;=====================================================================
;This is a scrolling bumpmap 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 CHAIN demo is virtually the same as this, except that
;everytime a newline is created, random pixels are inserted twice
;rather than just once.
;======================================================================

.MODEL SMALL
.386            ;Use 386 code
.STACK          ;Default stack

.DATA
NOVGA           DB      "You need a VGA card!  Sorry!",0ah,0dh,024h
AUTHOR          DB      "Scrolling Bumpmap Demo",0ah,0ah,0dh,"Made by Dennis Katsonis.",0ah,0dh,24h
ARRAY           DB      329 DUP (0)
BACK_COUNT      DB      0
BACK_COL        DB      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
	MOV     CX,63
SETGREY:                            ;Set 63 shades of gray
	INC     AL
	PUSH    AX
	MOV     AL,0
	OUT     DX,AL
	OUT     DX,AL
	POP     AX
	OUT     DX,AL
	DEC     CX
	TEST    CX,CX
	JNZ     SETGREY
	MOV     SI,0

SETPATTERN:
	CALL    RANDOM
	MOV     BYTE PTR ARRAY[SI],DL
	ADD     SI,2
	CMP     SI,328
	JNE     SETPATTERN

	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
	INC     BACK_COUNT
	CMP     BACK_COUNT,8
	JNE     CONT99
	MOV     BACK_COUNT,0
	INC     BACK_COL
	CMP     BACK_COL,16
	JNE     CONT99
	MOV     BACK_COL,0
CONT99:

	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

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
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,BACK_COL
	MOV     BYTE PTR ARRAY[SI-1],AH
	MOV     BYTE PTR ARRAY[SI+1],AL
CONT:
	TEST    BL,BL
	JNZ     CONT44
	MOV     BL,4

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.
