;=====================================================================
;This is a scrolling chain demo.  I apologize for the poor
;comments and somewhat messy arrangment but if you
;look through it you may figure out how it works.
;The screen scrolling part is very unoptimised becase
;it involves copying from screen to screen, which is slow.
;The BMAP demo is virtually the same as this, except that
;everytime a newline is created, random pixels are not inserted twice.
;======================================================================

.MODEL SMALL
.386            ;Use 386 code
.STACK          ;Default stack

.DATA
NOVGA           DB      "You need a VGA card!  Sorry!",0ah,0dh,024h
AUTHOR          DB      "Scrolling Chain Demo.",0ah,0dh,0ah,"Made by Dennis Katsonis.",0ah,0dh,24h
ARRAY           DB      329 DUP (0)

.CODE

MAIN    PROC    FAR

	MOV     AX,@DATA
	MOV     DS,AX

	MOV     AX,1200h        ;Test for VGA card
	MOV     BL,36h
	INT     10h
				 ;Exit if not detected
	.IF     AL != 12h
		MOV     DX,OFFSET NOVGA ;and tell the user
		MOV     AH,09h
		INT     21h
		MOV     AX,4C01h     ; Send exit code to dos
		INT     21h          ; Send command to DOS
	.ENDIF

	MOV     AX,0013h
	INT     10h                  ;Set 320 x 200 x 256

	MOV     AX,0A000h       ;Mov videomem address to AX
	MOV     ES,AX           ;Then to ES
	MOV     DX,3C8h              ;Output to video card we as setting
	MOV     AL,1                 ;colours from colour 0 up
	OUT     DX,AL
	INC     DX                   ;change dx to point to pallete
	XOR     BX,BX
	XOR     AX,AX
	XOR     CX,CX
SETGREY:                            ;Set 63 shades of gray
	MOV     AL,CL
	OUT     DX,AL
	SHR     AL,1
	OUT     DX,AL
	XOR     AL,AL
	OUT     DX,AL

	INC     CX
	CMP     CX,63
	JNE     SETGREY
	CALL    PATTERN

	MOV     SI,0
	MOV     DI,0
	MOV     CX,198
LOOP3:
	CALL    NEWLINE
	MOV     SI,1
LOOP1:
	MOV     EBX,DWORD PTR ARRAY[SI]
	MOV     ES:[DI],EBX
	ADD     SI,4
	ADD     DI,4
	CMP     SI,321
	JNE     LOOP1
	DEC     CX
	TEST    CX,CX
	JNZ     LOOP3
LOOP4:
	CALL    WAIT_RETRACE
	MOV     CX,15920
	MOV     DI,0
LOOP5:
	MOV     EBX,ES:[DI+320]
	MOV     ES:[DI],EBX
	ADD     DI,4
CONT2:
	DEC     CX
	TEST    CX,CX
	JNZ     LOOP5
	SUB     DI,640
	MOV     SI,0
	CALL    NEWLINE
	MOV     SI,1
LOOP6:
	MOV     EBX,DWORD PTR ARRAY[SI]
	MOV     ES:[DI],EBX
	ADD     SI,4
	ADD     DI,4
	CMP     SI,321
	JNE     LOOP6
	MOV     AH,1
	INT     16h              ;and go again if no key was pressed

	JZ      LOOP4
	
	MOV     AX,0003h          ;Set back to text mode
	INT     10h
	MOV     DX,OFFSET AUTHOR         ;Print my name
	MOV     AH,09h
	INT     21h

	MOV     AX,4C00H         ; Send exit code to dos
	INT     21H             ; Send command to DOS
MAIN    ENDP

WAIT_RETRACE    PROC    NEAR
	MOV     DX,3DAh
L1:
	IN      AL,DX
	AND     AL,8h
	JNZ     L1
	RET
WAIT_RETRACE    ENDP


PATTERN PROC    NEAR
	PUSH    SI
	MOV     SI,0

SETPATTERN:
	CALL    RANDOM
	MOV     BYTE PTR ARRAY[SI],DL
	ADD     SI,2
	CMP     SI,328
	JNE     SETPATTERN
	POP     SI
	RET
PATTERN ENDP

RANDOM  PROC    NEAR
	ADD     EAX,12231047d   ;Created a random number
	SHL     EBX,3           ;This does not use the MUL opcode
	ADD     EBX,EAX         ;but uses left shift's to multiply
	MOV     DL,BL
	SHR     DL,3

	RET
RANDOM  ENDP

NEWLINE PROC    NEAR
	MOV     SI,328
	CALL    PATTERN
LOOP2:

	MOV     AH,BYTE PTR ARRAY[SI-1]
	MOV     AL,BYTE PTR ARRAY[SI+1]
	MOV     BL,BYTE PTR ARRAY[SI]
	SHR     AH,2
	SHR     AL,2

	ADD     BL,AL
	ADD     BL,AH
	CMP     BL,63
	JLE     CONT

	MOV     BL,4
	MOV     BYTE PTR ARRAY[SI-1],AH
	MOV     BYTE PTR ARRAY[SI+1],AL

CONT:
	TEST    BL,BL
	JNZ     CONT44
	MOV     BL,2

CONT44:
	MOV     BYTE PTR ARRAY[SI],BL
	DEC     SI
	TEST    SI,SI
	JNZ     LOOP2
	RET

NEWLINE ENDP




END       MAIN                ; Set starting address!
					; Hard to explain. Read the book.
