;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;=- MAIN.ASM -- This small cycles through all of the video modes            -=
;=-
;=- See the README.TXT file for the Disclaimer and other info               -=
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
.MODEL  SMALL
.386
JUMPS
LOCALS
.STACK  100h
.DATA

ATTRCON_ADDR      EQU       03C0H
MISC_ADDR         EQU       03C2H
VGAENABLE_ADDR    EQU       03C3H
SEQ_ADDR          EQU       03C4H
GRACON_ADDR       EQU       03CEH
CRTC_ADDR         EQU       03D4H
STATUS_ADDR       EQU       03DAH

; Used for the unchained modes only
MODE_WIDTH DW ?
WIDTH_BYTES DW ?

PALETTE DB   0,  0,  0,  0,  0, 42,  0, 42,  0,  0, 42, 42, 42,  0,  0
 DB 42,  0, 42, 42, 21,  0, 42, 42, 42, 21, 21, 21, 21, 21, 63, 21, 63, 21
 DB 21, 63, 63, 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63

ICON DB  0, 0, 0, 0, 0, 0,15,15,15,15, 0, 0, 0, 0, 0, 0
     DB  0, 0, 0, 0, 0,15,15,15,15,15,15, 0, 0, 0, 0, 0
     DB  0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0
     DB  0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0
     DB  0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0
     DB  0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0
     DB  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
     DB  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
     DB  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
     DB  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
     DB  0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0
     DB  0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0
     DB  0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0
     DB  0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0
     DB  0, 0, 0, 0, 0,15,15,15,15,15,15, 0, 0, 0, 0, 0
     DB  0, 0, 0, 0, 0, 0,15,15,15,15, 0, 0, 0, 0, 0, 0

;These next four lines must be included for the text mode stuff to work.
oldmode db ?
oldmisc db ?
oldmask db ?
oldmem db ?

;This next file must be included for the text mode stuff to work.
include mode03.fon

; Must be included for any videomode to be set.
include modes.inc

MSG1 DB 'Back in Text mode using our Mode 03h function.'
MSG2 DB 13,10,13,10,'Press any key to continue...','$'

MSG3 DB 'MAIN.EXE -- Cycles through all of the videomodes.'
     DB 13,10,'Copyright (c) 1997, 1998 Jeffrey Morgan.  All Rights Reserved.'
     DB 13,10,'View the README for the disclaimer.',13,10
     DB 13,10,'Send me some feedback: kinfira@hotmail.com',13,10
     DB 13,10,'Press any key to go to the next mode.'
     DB 13,10,13,10,'Press any key to continue...','$'

.CODE

IODELAY MACRO
   REPT 8
      JMP $+2
   ENDM
ENDM

Start:
   MOV AX,@DATA
   MOV DS,AX

   ; Print out the message
   MOV DX,OFFSET MSG3
   MOV AH,9
   INT 21H

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Call my set mode 12h function
   PUSH 12H
   CALL SETVIDEOMODE

   PUSH 4
   CALL CLEAR12H

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Call my set mode 10h function
   PUSH 10H
   CALL SETVIDEOMODE

   PUSH 12
   CALL CLEAR10H

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Call my set mode C function
   PUSH 18H
   CALL SETVIDEOMODE

   PUSH 11
   CALL CLEARMODEC

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Call my set mode 13h function
   PUSH 13H
   CALL SETVIDEOMODE

   ; Clear the screen to blue
   MOV AX,0A000H
   MOV ES,AX
   MOV EAX,01010101H
   XOR DI,DI
   MOV CX,16000
   CLD
   REP STOSD

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Call my set chain-4 mode function
   PUSH 14H
   CALL SETVIDEOMODE

   ; Number of words in 1 screen
   MOV MODE_WIDTH,320
   MOV WIDTH_BYTES,16000

   PUSH 2
   CALL CLEAR_SCREEN

   CALL MESSAGE

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Call my set mode X function
   PUSH 15H
   CALL SETVIDEOMODE

   ; Number of words in 1 screen
   MOV MODE_WIDTH,320
   MOV WIDTH_BYTES,19200

   PUSH 5
   CALL CLEAR_SCREEN

   CALL MESSAGE

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Call my set mode A function
   PUSH 16H
   CALL SETVIDEOMODE

   ; Number of words in 1 screen
   MOV MODE_WIDTH,320
   MOV WIDTH_BYTES,32000

   PUSH 7
   CALL CLEAR_SCREEN

   CALL MESSAGE

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Call my set mode B function
   PUSH 17H
   CALL SETVIDEOMODE

   ; Number of words in 1 screen
   MOV MODE_WIDTH,360
   MOV WIDTH_BYTES,43200

   PUSH 6
   CALL CLEAR_SCREEN

   CALL MESSAGE

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Set Mode 03h
   PUSH 03H
   CALL SETVIDEOMODE

   ; Clear the screen
   CALL CLRSCR

   ; Put the cursor at 0,0
   MOV AH,2H
   MOV BX,0
   MOV DX,0
   INT 10H

   ; Print out the message
   MOV DX,OFFSET MSG1
   MOV AH,9
   INT 21H

   ; Wait for a keypress
   MOV AH,0
   INT 16H

; ====================== New Video Mode ====================================

   ; Set the BIOS mode 03h
   MOV AX,0003H
   INT 10H

   ; Exit to DOS
   MOV AX,4C00H
   INT 21H

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

SETVIDEOMODE PROC
   PUSH BP
   MOV BP,SP

   MOV AX,[BP+4]
   CMP AX,03H
   JE SET03H
   CMP AX,10H
   JE SET10H
   CMP AX,12H
   JE SET12H
   CMP AX,13H
   JE SET13H
   CMP AX,14H
   JE SETCHAIN4
   CMP AX,15H
   JE SETMODEX
   CMP AX,16H
   JE SETMODEA
   CMP AX,17H
   JE SETMODEB
   CMP AX,18H
   JE SETMODEC
   JMP SET_OUT

SET03H:
   MOV SI,OFFSET MODE03H
   CALL SETMODE
   ; Must do this to ensure proper text
   CALL SETFONT
   JMP SET_OUT

SET10H:
   MOV SI,OFFSET MODE10H
   CALL SETMODE
   JMP SET_OUT

SET12H:
   MOV SI,OFFSET MODE12H
   CALL SETMODE
   JMP SET_OUT

SET13H:
   MOV SI,OFFSET MODE13H
   CALL SETMODE
   JMP SET_OUT

SETCHAIN4:
   MOV SI,OFFSET CHAIN4
   CALL SETMODE
   JMP SET_OUT

SETMODEX:
   MOV SI,OFFSET CHAIN4
   CALL SETMODE

   MOV DX,03C2H
   MOV AL,0E3H
   OUT DX,AL

   ; turn off write protect
   MOV DX,CRTC_ADDR
   MOV AL,11H
   OUT DX,AL
   INC DX
   MOV AL,2CH
   OUT DX,AL

   ; vertical total
   MOV DX,CRTC_ADDR
   MOV AL,06H
   OUT DX,AL
   INC DX
   MOV AL,0DH
   OUT DX,AL

   ; overflow register
   MOV DX,CRTC_ADDR
   MOV AL,07H
   OUT DX,AL
   INC DX
   MOV AL,3EH
   OUT DX,AL

   ; vertical retrace start
   MOV DX,CRTC_ADDR
   MOV AL,10H
   OUT DX,AL
   INC DX
   MOV AL,0EAH
   OUT DX,AL

   ; vertical retrace end AND wr.prot
   MOV DX,CRTC_ADDR
   MOV AL,11H
   OUT DX,AL
   INC DX
   MOV AL,0ACH
   OUT DX,AL

   ; vertical display enable end
   MOV DX,CRTC_ADDR
   MOV AL,12H
   OUT DX,AL
   INC DX
   MOV AL,0DFH
   OUT DX,AL

   ; start vertical blanking
   MOV DX,CRTC_ADDR
   MOV AL,15H
   OUT DX,AL
   INC DX
   MOV AL,0E7H
   OUT DX,AL

   ; end vertical blanking
   MOV DX,CRTC_ADDR
   MOV AL,16H
   OUT DX,AL
   INC DX
   MOV AL,06H
   OUT DX,AL
   JMP SET_OUT

SETMODEA:
   MOV SI,OFFSET MODE13H
   CALL SETMODE

   ; Turn off Chain4
   MOV DX,SEQ_ADDR
   MOV AL,4
   OUT DX,AL
   INC DX
   IN AL,DX
   AND AL,NOT 08H
   OR AL,04H
   OUT DX,AL

   ; Turn off Odd/Even
   MOV DX,GRACON_ADDR
   MOV AL,5
   OUT DX,AL
   INC DX
   IN AL,DX
   AND AL,NOT 10H
   OUT DX,AL

   ; Turn off Chain
   MOV DX,GRACON_ADDR
   MOV AL,6
   OUT DX,AL
   INC DX
   IN AL,DX
   AND AL,NOT 02H
   OUT DX,AL

   ; Tweak the mode out to 400 scan line by not scanning each line twice
   MOV DX,CRTC_ADDR
   MOV AL,9
   OUT DX,AL
   INC DX
   IN AL,DX
   AND AL,NOT 1FH
   OUT DX,AL

   ; Switch from doubleword mode to byte mode
   MOV DX,CRTC_ADDR
   MOV AL,14h
   OUT DX,AL
   INC DX
   IN AL,DX
   AND AL,NOT 40H
   OUT DX,AL

   MOV DX,CRTC_ADDR
   MOV AL,17h
   OUT DX,AL
   INC DX
   IN AL,DX
   OR AL,40H
   OUT DX,AL
   JMP SET_OUT

SETMODEB:

   MOV SI,OFFSET MODE13H
   CALL SETMODE

   ; Turn off Chain4
   MOV DX,SEQ_ADDR
   MOV AX,0604H
   OUT DX,AX

   MOV AX,0100H
   OUT DX,AX

   MOV DX,MISC_ADDR
   MOV AL,0E7H
   OUT DX,AL

   MOV DX,SEQ_ADDR
   MOV AX,0300H
   OUT DX,AX

   MOV DX,SEQ_ADDR

   MOV AL,11H
   OUT DX,AL
   INC DX
   IN AL,DX
   AND AL,7FH
   OUT DX,AL

   MOV SI,OFFSET MODEB_REGS
   MOV CX,0
MODEB_LOOP:
   MOV DX,CRTC_ADDR
   MOV AL,CL
   OUT DX,AL
   IODELAY

   MOV DX,CRTC_ADDR
   INC DX
   MOV AL,[SI]
   OUT DX,AL
   IODELAY

   INC SI
   INC CX
   CMP CL,18H
   JL MODEB_LOOP
   JMP SET_OUT

SETMODEC:
   MOV SI,OFFSET MODE10H
   CALL SETMODE

   MOV DX,03CCH
   IN AL,DX
   AND AL,03FH
   OR AL,40H

   MOV DX,03C2H
   OUT DX,AL

   MOV DX,CRTC_ADDR
   MOV AX,9C10H
   OUT DX,AX
   IODELAY

   MOV AX,8311H
   OUT DX,AX
   IODELAY

   MOV AX,8F12H
   OUT DX,AX
   IODELAY

   MOV AX,9615H
   OUT DX,AX
   IODELAY

   MOV AX,0B916H
   OUT DX,AX
   IODELAY

SET_OUT:
   CALL SETPALETTE

   POP BP
   RET 2
SETVIDEOMODE ENDP

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

   PUBLIC SETMODE
SETMODE PROC

   ; Send MISC regs
   MOV DX,MISC_ADDR
   MOV AL,[SI]
   OUT DX,AL
   IODELAY
   INC SI

   MOV DX,STATUS_ADDR
   MOV AL,[SI]
   OUT DX,AL
   IODELAY
   INC SI

   ; Send SEQ regs
   MOV CX,0
REG_LOOP:
   MOV DX,SEQ_ADDR
   MOV AL,CL
   OUT DX,AL
   IODELAY

   MOV DX,SEQ_ADDR
   INC DX
   MOV AL,[SI]
   OUT DX,AL
   IODELAY
   INC SI
   INC CX
   CMP CL,5
   JL REG_LOOP

   ; Clear Protection bits
   MOV AH,0EH
   MOV AL,11H
   AND AH,7FH
   MOV DX,CRTC_ADDR
   OUT DX,AX
   IODELAY

   ; Send CRTC regs
   MOV CX,0
REG_LOOP2:
   MOV DX,CRTC_ADDR
   MOV AL,CL
   OUT DX,AL
   IODELAY

   MOV DX,CRTC_ADDR
   INC DX
   MOV AL,[SI]
   OUT DX,AL
   IODELAY

   INC SI
   INC CX
   CMP CL,25
   JL REG_LOOP2

   ; Send GRAPHICS regs
   MOV CX,0
REG_LOOP3:
   MOV DX,GRACON_ADDR
   MOV AL,CL
   OUT DX,AL
   IODELAY

   MOV DX,GRACON_ADDR
   INC DX
   MOV AL,[SI]
   OUT DX,AL
   IODELAY

   INC SI
   INC CX
   CMP CL,9
   JL REG_LOOP3

   MOV DX,STATUS_ADDR
   IN AL,DX
   IODELAY

   ; Send ATTRCON regs
   MOV CX,0
REG_LOOP4:
   MOV DX,ATTRCON_ADDR
   IN AX,DX

   MOV AL,CL
   OUT DX,AL
   IODELAY

   MOV AL,[SI]
   OUT DX,AL
   IODELAY

   INC SI
   INC CX
   CMP CL,21
   JL REG_LOOP4

   MOV AL,20H
   OUT DX,AL
   IODELAY

   RET
SETMODE ENDP

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
   PUBLIC SETFONT
SETFONT PROC                            ;
 mov dx,GRACON_ADDR                     ;get graphics port
 mov al,5                               ;get write mode reg
 out dx,al                              ;select the reg
 IODELAY                                ;delay a bit
 inc dx                                 ;change DX
 in al,dx                               ;get value
 IODELAY                                ;pause
 mov [oldmode],al                       ;store it
 dec dx                                 ;restore DX
 mov al,6                               ;get misc reg
 out dx,al                              ;select the reg
 IODELAY                                ;delay a bit
 inc dx                                 ;change DX
 in al,dx                               ;get value
 IODELAY                                ;pause
 mov [oldmisc],al                       ;store it
 dec dx                                 ;restore DX
 mov dx,SEQ_ADDR                        ;get sequencer port
 mov al,2                               ;get map mask reg
 out dx,al                              ;select the reg
 IODELAY                                ;delay a bit
 inc dx                                 ;change DX
 in al,dx                               ;get value
 IODELAY                                ;pause
 mov [oldmask],al                       ;store it
 dec dx                                 ;restore DX
 mov al,4                               ;get memory selector reg
 out dx,al                              ;select the reg
 IODELAY                                ;delay a bit
 inc dx                                 ;change DX
 in al,dx                               ;get value
 IODELAY                                ;pause
 mov [oldmem],al                        ;store it
 mov dx,GRACON_ADDR                     ;select graphics port
 mov al,5                               ;get write mode reg
 mov ah,[oldmode]                       ;get old value
 and ah,0fch                            ;mask it
 out dx,ax                              ;set new value
 IODELAY                                ;pause
 mov al,6                               ;get misc reg
 mov ah,[oldmisc]                       ;get old value
 and ah,0f1h                            ;mask it
 or ah,4                                ;set a flag
 out dx,ax                              ;set it
 IODELAY                                ;pause
 mov dx,SEQ_ADDR                        ;select sequencer port
 mov al,2                             ;get mask reg
 mov ah,4                               ;get new value
 out dx,ax                              ;set it
 IODELAY                                ;pause
 mov al,4                              ;get memory reg
 mov ah,[oldmem]                        ;get old value
 or ah,4                                ;set flag
 out dx,ax                              ;set value
 IODELAY                                ;pause
 mov ax,0a000h                          ;get seg of font mem
 mov es,ax                              ;in ES
 xor di,di                              ;zero destination
 mov si,offset font                     ;get source
 xor ch,ch                              ;clear entries count
 cld                                    ;set direction flag correctly
@@loop1:                                ;
 push di                                ;save destination
 mov cl,16                              ;bytes per font
@@loop2:                                ;
 movsb                                  ;move a byte
 dec cl                                 ;decrease count
 jnz @@loop2                            ;loop until all done
 pop di                                 ;restore destination
 add di,32                              ;update it
 dec ch                                 ;decrease outer count
 jnz @@loop1                            ;loop until all done
 mov dx,GRACON_ADDR                     ;get graphics port
 mov al,5                               ;get 1st reg
 mov ah,[oldmode]                       ;get old value
 out dx,ax                              ;set it
 IODELAY                                ;pause
 mov al,6                               ;get 2nd reg
 mov ah,[oldmisc]                       ;get old value
 out dx,ax                              ;set it
 IODELAY                                ;pause
 mov dx,SEQ_ADDR                        ;get seq port
 mov al,2                               ;get 3rd reg
 mov ah,[oldmask]                       ;get old value
 out dx,ax                              ;set it
 IODELAY                                ;pause
 mov al,4                               ;get 4th reg
 mov ah,[oldmem]                        ;get old value
 out dx,ax                              ;set it
 IODELAY                                ;pause
 ret                                    ;exit
SETFONT endp

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Text Mode clear screen
CLRSCR PROC
   PUSHA

   MOV AX,0B800H ; Set the Video Memory Address
   MOV ES,AX
   XOR DI,DI

   MOV AH,00000111b ; Attribute
   MOV AL,' '       ; Character
   MOV CX,2000
   CLD
   REP STOSW    ; Move to memory

   ; Restore registers
   POPA
   RET 
CLRSCR ENDP

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Mode 12h clear screen
CLEAR12H PROC
   PUSH BP
   MOV BP,SP

   MOV AX,0A000H
   MOV ES,AX
   XOR DI,DI

   MOV CX,9600
CLEAR_LOOP:
   MOV DX,03CEH
   MOV AX,0FF08H
   OUT DX,AX

   MOV EAX,0
   XCHG DWORD PTR ES:[DI],EAX

   MOV DX,03C4H
   MOV AH,BYTE PTR [BP+4]
   MOV AL,2
   OUT DX,AX

   MOV DWORD PTR ES:[DI],0FFFFFFFFH

   MOV AX,0F02H
   OUT DX,AX

   MOV DX,03CEH
   MOV AX,0FF08h
   OUT DX,AX

   ADD DI,4
   LOOP CLEAR_LOOP

   POP BP
   RET 2
CLEAR12H ENDP

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Mode 10h clear screen
CLEAR10H PROC
   PUSH BP
   MOV BP,SP

   MOV AX,0A000H
   MOV ES,AX
   XOR DI,DI

   MOV CX,7000
CLEAR_LOOP2:
   MOV DX,03CEH
   MOV AX,0FF08H
   OUT DX,AX

   MOV EAX,0
   XCHG DWORD PTR ES:[DI],EAX

   MOV DX,03C4H
   MOV AH,BYTE PTR [BP+4]
   MOV AL,2
   OUT DX,AX

   MOV DWORD PTR ES:[DI],0FFFFFFFFH

   MOV AX,0F02H
   OUT DX,AX

   MOV DX,03CEH
   MOV AX,0FF08h
   OUT DX,AX

   ADD DI,4
   LOOP CLEAR_LOOP2

   POP BP
   RET 2
CLEAR10H ENDP

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Mode C clear screen
CLEARMODEC PROC
   PUSH BP
   MOV BP,SP

   MOV AX,0A000H
   MOV ES,AX
   XOR DI,DI

   MOV CX,8000
CLEAR_LOOP3:
   MOV DX,03CEH
   MOV AX,0FF08H
   OUT DX,AX

   MOV EAX,0
   XCHG DWORD PTR ES:[DI],EAX

   MOV DX,03C4H
   MOV AH,BYTE PTR [BP+4]
   MOV AL,2
   OUT DX,AX

   MOV DWORD PTR ES:[DI],0FFFFFFFFH

   MOV AX,0F02H
   OUT DX,AX

   MOV DX,03CEH
   MOV AX,0FF08h
   OUT DX,AX

   ADD DI,4
   LOOP CLEAR_LOOP3

   POP BP
   RET 2
CLEARMODEC ENDP

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Clears screen on unchained video modes
CLEAR_SCREEN PROC
   PUSH BP
   MOV BP,SP

   mov   dx, 03C4h         ; 03c4h
   mov   al, 2             ; Map Mask Register
   out   dx, al
   inc   dx
   mov   al,00001111B      ; Select all planes to write to
   out   dx, al            ; Doing this to clear all planes at once

   mov   ax,0A000H
   mov   es, ax
   XOR DI,DI               ; set es:di = Screen Mem
   mov ah,[BP+4]           ; move the color into ah
   mov al,ah               ; copy the value to al
   mov   cx,WIDTH_BYTES    ; Number of words
   SHR CL,1
   cld
   rep   stosw             ; clear it

   POP BP
   RET 2
CLEAR_SCREEN ENDP

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
include msg.asm
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

   PUBLIC SETPAL
SETPAL PROC
   PUSH BP
   MOV BP,SP
   PUSHA

   MOV AX,[BP+4]
   ; Send color
   MOV DX,03C8H
   OUT DX,AL

   ; Address of the 3-byte array
   MOV DI,[BP+6]

   ; Write R value
   MOV DX,03C9H
   MOV AL,BYTE PTR [DI]
   OUT DX,AL

   ; Write G value
   MOV DX,03C9H
   MOV AL,BYTE PTR [DI+1]
   OUT DX,AL

   ; Write B value
   MOV DX,03C9H
   MOV AL,BYTE PTR [DI+2]
   OUT DX,AL

   POPA
   POP BP
   RET 4
SETPAL ENDP

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

   PUBLIC SETPALETTE
SETPALETTE PROC

   ; Address of the 6-byte array
   MOV DI,OFFSET PALETTE

   MOV ECX,0
PAL_LOOP:
   MOV AX,CX
   ; Send color
   MOV DX,03C8H
   OUT DX,AL

   ; Write R value
   MOV DX,03C9H
   MOV AL,BYTE PTR [DI]
   OUT DX,AL

   ; Write G value
   MOV DX,03C9H
   MOV AL,BYTE PTR [DI+1]
   OUT DX,AL

   ; Write B value
   MOV DX,03C9H
   MOV AL,BYTE PTR [DI+2]
   OUT DX,AL

   ADD DI,3
   INC CX
   CMP CX,16
   JLE PAL_LOOP

   RET
SETPALETTE ENDP

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

END Start
