You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

773 lines
20 KiB

;======================================================================
; VGA DRIVER FOR RBC PROJECT
;
; WRITTEN BY: WAYNE WARTHEN -- 5/29/2017
;======================================================================
;
; TODO:
;
;======================================================================
; VGA DRIVER - CONSTANTS
;======================================================================
;
VGA_BASE .EQU $E0
;
VGA_KBDDATA .EQU VGA_BASE + $00 ; KBD CTLR DATA PORT
VGA_KBDST .EQU VGA_BASE + $01 ; KBD CTLR STATUS/CMD PORT
VGA_REG .EQU VGA_BASE + $02 ; SELECT CRTC REGISTER
VGA_DATA .EQU VGA_BASE + $03 ; READ/WRITE CRTC DATA
VGA_CFG .EQU VGA_BASE + $04 ; VGA3 BOARD CFG REGISTER
VGA_HI .EQU VGA_BASE + $05 ; BOARD RAM HI ADDRESS
VGA_LO .EQU VGA_BASE + $06 ; BOARD RAM LO ADDRESS
VGA_DAT .EQU VGA_BASE + $07 ; BOARD RAM BYTE R/W
;
VGA_ROWS .EQU 25
VGA_COLS .EQU 80
;
#DEFINE DEFREGS REGS_VGA
;
TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER
;
;======================================================================
; VGA DRIVER - INITIALIZATION
;======================================================================
;
VGA_INIT:
LD IY,VGA_IDAT ; POINTER TO INSTANCE DATA
;
CALL NEWLINE ; FORMATTING
PRTS("VGA: IO=0x$")
LD A,VGA_REG
CALL PRTHEXBYTE
CALL VGA_PROBE ; CHECK FOR HW PRESENCE
JR Z,VGA_INIT1 ; CONTINUE IF HW PRESENT
;
; HARDWARE NOT PRESENT
PRTS(" NOT PRESENT$")
OR $FF ; SIGNAL FAILURE
RET
;
VGA_INIT1:
; DISPLAY CONSOLE DIMENSIONS
LD A,VGA_COLS
CALL PC_SPACE
CALL PRTDECB
LD A,'X'
CALL COUT
LD A,VGA_ROWS
CALL PRTDECB
PRTS(" TEXT$")
; HARDWARE INITIALIZATION
CALL VGA_CRTINIT ; SETUP THE VGA CHIP REGISTERS
CALL VGA_LOADFONT ; LOAD FONT DATA FROM ROM TO VGA STRORAGE
CALL VGA_VDARES
CALL KBD_INIT ; INITIALIZE KEYBOARD DRIVER
; ADD OURSELVES TO VDA DISPATCH TABLE
LD BC,VGA_DISPATCH ; BC := DISPATCH ADDRESS
LD DE,VGA_IDAT ; DE := VGA INSTANCE DATA PTR
CALL VDA_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED
; INITIALIZE EMULATION
LD C,A ; C := ASSIGNED VIDEO DEVICE NUM
LD DE,VGA_DISPATCH ; DE := DISPATCH ADDRESS
LD HL,VGA_IDAT ; HL := VGA INSTANCE DATA PTR
CALL TERM_ATTACH ; DO IT
XOR A ; SIGNAL SUCCESS
RET
;
;======================================================================
; VGA DRIVER - VIDEO DISPLAY ADAPTER (VDA) DISPATCHER AND FUNCTIONS
;======================================================================
;
VGA_DISPATCH:
LD A,B ; GET REQUESTED FUNCTION
AND $0F ; ISOLATE SUB-FUNCTION
JP Z,VGA_VDAINI ; $40
DEC A
JP Z,VGA_VDAQRY ; $41
DEC A
JP Z,VGA_VDARES ; $42
DEC A
JP Z,VGA_VDADEV ; $43
DEC A
JP Z,VGA_VDASCS ; $44
DEC A
JP Z,VGA_VDASCP ; $45
DEC A
JP Z,VGA_VDASAT ; $46
DEC A
JP Z,VGA_VDASCO ; $47
DEC A
JP Z,VGA_VDAWRC ; $48
DEC A
JP Z,VGA_VDAFIL ; $49
DEC A
JP Z,VGA_VDACPY ; $4A
DEC A
JP Z,VGA_VDASCR ; $4B
DEC A
JP Z,KBD_STAT ; $4C
DEC A
JP Z,KBD_FLUSH ; $4D
DEC A
JP Z,KBD_READ ; $4E
CALL PANIC
VGA_VDAINI:
; RESET VDA
; CURRENTLY IGNORES VIDEO MODE AND BITMAP DATA
CALL VGA_VDARES ; RESET VDA
XOR A ; SIGNAL SUCCESS
RET
VGA_VDAQRY:
LD C,$00 ; MODE ZERO IS ALL WE KNOW
LD D,VGA_ROWS ; ROWS
LD E,VGA_COLS ; COLS
LD HL,0 ; EXTRACTION OF CURRENT BITMAP DATA NOT SUPPORTED YET
XOR A ; SIGNAL SUCCESS
RET
VGA_VDARES:
LD A,$07 ; ATTRIBUTE IS STANDARD WHITE ON BLACK
LD (VGA_ATTR),A ; SAVE IT
XOR A ; ZERO (REVEVERSE, UNDERLINE, BLINK)
LD (VGA_RUB),A ; SAVE IT
LD DE,0 ; ROW = 0, COL = 0
CALL VGA_XY ; SEND CURSOR TO TOP LEFT
LD A,' ' ; BLANK THE SCREEN
LD DE,$800 ; FILL ENTIRE BUFFER
CALL VGA_FILL ; DO IT
LD DE,0 ; ROW = 0, COL = 0
CALL VGA_XY ; SEND CURSOR TO TOP LEFT
LD HL,$0404 ; SET VIDEO ENABLE BIT
CALL VGA_SETCFG ; DO IT
XOR A
RET
VGA_VDADEV:
LD D,VDADEV_VGA ; D := DEVICE TYPE
LD E,0 ; E := PHYSICAL UNIT IS ALWAYS ZERO
XOR A ; SIGNAL SUCCESS
RET
VGA_VDASCS:
CALL PANIC ; NOT IMPLEMENTED (YET)
VGA_VDASCP:
CALL VGA_XY ; SET CURSOR POSITION
XOR A ; SIGNAL SUCCESS
RET
VGA_VDASAT:
; INCOMING IS: -----RUB (R=REVERSE, U=UNDERLINE, B=BLINK)
;
; JUST SAVE THE VALUE AND FALL THROUGH. ONLY REVERSE IS
; SUPPORTED WHICH IS IMPLEMENTED BELOW.
LD A,E
LD (VGA_RUB),A ; SAVE IT
JR VGA_VDASCO2 ; IMPLEMENT SETTING
VGA_VDASCO:
; INCOMING IS: IBGRIBGR (I=INTENSITY, B=BLUE, G=GREEN, R=RED)
; TRANSFORM TO: -RGBIRGB (DISCARD INTENSITY BIT IN HIGH NIBBLE)
;
; A := INVERTED E, SO A IS RGBIRGBI (F/B)
LD B,8 ; DO 8 BITS
VGA_VDASCO1:
RRC E ; LOW BIT OF E ROTATED RIGHT INTO CF
RLA ; CF ROTATED LEFT INTO LOW BIT OF A
DJNZ VGA_VDASCO1 ; DO FOR ALL 8 BITS
; LS A X 3 TO SWAP F/B BITS, SO A IS IRGBIRGB (B/F)
RLCA
RLCA
RLCA
; MASK FOR RELEVANT BITS, SO A IS 0R0B0R0B
AND %01010101
; SAVE A IN C AND SET A = E
LD C,A
LD A,E
; MASK FOR RELEVANT BITS, SO A IS 00G0I0G0
AND %00101010
; COMBINE WITH SAVED
OR E
; SAVE NEW ATTR VALUE
LD (VGA_ATTR),A ; AND SAVE THE RESULT
VGA_VDASCO2:
; CHECK FOR REVERSE VIDEO
LD A,(VGA_RUB) ; GET RUB SETTING
BIT 2,A ; REVERSE IS BIT 2
JR Z,VGA_VDASCO3 ; DONE IF REVERSE VID NOT SET
; IMPLEMENT REVERSE VIDEO
LD A,(VGA_ATTR) ; GET ATTRIBUTE
PUSH AF ; SAVE IT
AND %00001000 ; ISOLATE INTENSITY BIT
LD E,A ; SAVE IN E
POP AF ; GOT ATTR BACK
RLCA ; SWAP FG/BG COLORS
RLCA
RLCA
RLCA
AND %01110111 ; REMOVE HIGH BITS
OR E ; COMBINE WITH PREVIOUS INTENSITY BIT
LD (VGA_ATTR),A ; SAVE NEW VALUE
VGA_VDASCO3:
XOR A ; SIGNAL SUCCESS
RET
VGA_VDAWRC:
LD A,E ; CHARACTER TO WRITE GOES IN A
CALL VGA_PUTCHAR ; PUT IT ON THE SCREEN
XOR A ; SIGNAL SUCCESS
RET
VGA_VDAFIL:
LD A,E ; FILL CHARACTER GOES IN A
EX DE,HL ; FILL LENGTH GOES IN DE
CALL VGA_FILL ; DO THE FILL
XOR A ; SIGNAL SUCCESS
RET
VGA_VDACPY:
; LENGTH IN HL, SOURCE ROW/COL IN DE, DEST IS VGA_POS
; BLKCPY USES: HL=SOURCE, DE=DEST, BC=COUNT
PUSH HL ; SAVE LENGTH
CALL VGA_XY2IDX ; ROW/COL IN DE -> SOURCE ADR IN HL
POP BC ; RECOVER LENGTH IN BC
LD DE,(VGA_POS) ; PUT DEST IN DE
JP VGA_BLKCPY ; DO A BLOCK COPY
VGA_VDASCR:
LD A,E ; LOAD E INTO A
OR A ; SET FLAGS
RET Z ; IF ZERO, WE ARE DONE
PUSH DE ; SAVE E
JP M,VGA_VDASCR1 ; E IS NEGATIVE, REVERSE SCROLL
CALL VGA_SCROLL ; SCROLL FORWARD ONE LINE
POP DE ; RECOVER E
DEC E ; DECREMENT IT
JR VGA_VDASCR ; LOOP
VGA_VDASCR1:
CALL VGA_RSCROLL ; SCROLL REVERSE ONE LINE
POP DE ; RECOVER E
INC E ; INCREMENT IT
JR VGA_VDASCR ; LOOP
;
;======================================================================
; VGA DRIVER - PRIVATE DRIVER FUNCTIONS
;======================================================================
;
;----------------------------------------------------------------------
; SET BOARD CONFIGURATON REGISTER
; MASK IN H, VALUE IN L
;----------------------------------------------------------------------
;
VGA_SETCFG:
PUSH AF ; PRESERVE AF
LD A,H ; MASK IN ACCUM
CPL ; INVERT IT
LD H,A ; BACK TO H
LD A,(VGA_CFGV) ; GET CURRENT CONFIG VALUE
AND H ; RESET ALL TARGET BITS
OR L ; SET TARGET BITS
LD (VGA_CFGV),A ; SAVE NEW VALUE
OUT (VGA_CFG),A ; AND WRITE IT TO REGISTER
POP AF ; RESTORE AF
RET
;
;----------------------------------------------------------------------
; UPDATE CRTC REGISTERS
; VGA_REGWR WRITES VALUE IN A TO VDU REGISTER SPECIFIED IN C
;----------------------------------------------------------------------
;
VGA_REGWR:
PUSH AF ; SAVE VALUE TO WRITE
LD A,C ; SET A TO VGA REGISTER TO SELECT
OUT (VGA_REG),A ; WRITE IT TO SELECT THE REGISTER
POP AF ; RESTORE VALUE TO WRITE
OUT (VGA_DATA),A ; WRITE IT
RET
;
VGA_REGWRX:
LD A,H ; SETUP MSB TO WRITE
CALL VGA_REGWR ; DO IT
INC C ; NEXT CVDU REGISTER
LD A,L ; SETUP LSB TO WRITE
JR VGA_REGWR ; DO IT & RETURN
;
;----------------------------------------------------------------------
; READ CRTC REGISTERS
; VGA_REGRD READS VDU REGISTER SPECIFIED IN C AND RETURNS VALUE IN A
;----------------------------------------------------------------------
;
VGA_REGRD:
LD A,C ; SET A TO VGA REGISTER TO SELECT
OUT (VGA_REG),A ; WRITE IT TO SELECT THE REGISTER
IN A,(VGA_DATA) ; READ IT
RET
;
VGA_REGRDX:
CALL VGA_REGRD ; GET VALUE FROM REGISTER IN C
LD H,A ; SAVE IN H
INC C ; BUMP TO NEXT REGISTER OF PAIR
CALL VGA_REGRD ; READ THE VALUE
LD L,A ; SAVE IT IN L
RET
;
;----------------------------------------------------------------------
; WRITE VIDEO RAM
; VGA_MEMWR WRITES VALUE IN A TO ADDRESS IN DE
; VGA_MEMWRX WRITES VALUE IN HL TO ADDRESS IN DE
;----------------------------------------------------------------------
;
VGA_MEMWR:
LD C,VGA_HI
OUT (C),D
INC C
OUT (C),E
INC C
OUT (C),A
RET
;
VGA_MEMWRX:
LD C,VGA_HI
OUT (C),D
INC C
OUT (C),E
INC C
OUT (C),H
INC E
DEC C
OUT (C),E
INC C
OUT (C),L
DEC E
RET
;
;----------------------------------------------------------------------
; READ VIDEO RAM
; VGA_MEMRD READS VALUE IN DE TO A
; VGA_MEMRDX READS VALUE IN DE TO HL
;----------------------------------------------------------------------
;
VGA_MEMRD:
LD C,VGA_HI
OUT (C),D
INC C
OUT (C),E
INC C
IN A,(C)
RET
;
VGA_MEMRDX:
LD C,VGA_HI
OUT (C),D
INC C
OUT (C),E
INC C
IN H,(C)
INC E
DEC C
OUT (C),E
INC C
IN L,(C)
DEC E
RET
;
;----------------------------------------------------------------------
; PROBE FOR VGA HARDWARE
;----------------------------------------------------------------------
;
; ON RETURN, ZF SET INDICATES HARDWARE FOUND
;
VGA_PROBE:
LD DE,0 ; POINT TO FIRST BYTE OF VRAM
LD A,$A5 ; INITIAL TEST VALUE
LD B,A ; SAVE IN B
CALL VGA_MEMWR ; WRITE IT
INC E ; NEXT BYTE OF VRAM
CPL ; INVERT TEST VALUE
CALL VGA_MEMWR ; WRITE IT
DEC E ; BACK TO FIRST BYTE OF VRAM
CALL VGA_MEMRD ; READ IT
CP B ; CHECK FOR TEST VALUE
RET NZ ; RETURN NZ IF FAILURE
INC E ; SECOND VRAM BYTE
CALL VGA_MEMRD ; READ IT
CPL ; INVERT IT
CP B ; CHECK FOR INVERTED TEST VALUE
RET ; RETURN WITH ZF SET BASED ON CP
;
;----------------------------------------------------------------------
; CRTC DISPLAY CONTROLLER CHIP INITIALIZATION
;----------------------------------------------------------------------
;
VGA_CRTINIT:
LD HL,$FF00 ; ZERO ALL CFG BITS
CALL VGA_SETCFG ; DO IT
CALL VGA_RES ; RESET CRTC (ALL REGS TO ZERO)
LD HL,DEFREGS ; HL = POINTER TO TABLE OF REG VALUES
VGA_CRTINIT1:
LD A,(HL) ; FIRST BYTE IS REG ADR
LD C,A ; PUT IN C FOR LATER
INC A ; TEST FOR END MARKER ($FF)
RET Z ; IF EQUAL, DONE
INC HL ; NEXT BYTE
LD A,(HL) ; SECOND BYTE IS REG VAL
INC HL ; HL TO NEXT ENTRY
CALL VGA_REGWR ; WRITE REGISTER VALUE
JR VGA_CRTINIT1 ; LOOP
;
VGA_RES:
LD C,0 ; START WITH REG ZERO
LD B,40 ; CLEAR 40 REGISTERS
VGA_RES1:
XOR A ; VALUE IS ZERO
CALL VGA_REGWR ; SET VALUE
INC C ; NEXT REGISTER
DJNZ VGA_RES1 ; LOOP TILL DONE
RET ; DONE
;
VGA_CRTCDUMP:
LD C,0 ; START WITH REG ZERO
LD B,40 ; CLEAR 40 REGISTERS
VGA_CRTCDUMP1:
CALL VGA_REGRD ; SET VALUE
CALL PRTHEXBYTE
CALL PC_SPACE
INC C ; NEXT REGISTER
DJNZ VGA_CRTCDUMP1 ; LOOP TILL DONE
RET ; DONE
;
;----------------------------------------------------------------------
; LOAD FONT DATA
;----------------------------------------------------------------------
;
VGA_LOADFONT:
LD HL,$7000 ; CLEAR FONT PAGE NUM
CALL VGA_SETCFG
LD DE,$7000 ; PAGE 7 OF VIDEO RAM
LD HL,FONT_HI ; START OF FONT DATA
VGA_LOADFONT1:
LD A,(HL) ; GET NEXT BYTE
CALL VGA_MEMWR ; MEM(DE) := A
INC HL ; NEXT FONT BYTE
INC DE ; NEXT MEM BYTE
LD A,D
CP $80 ; CHECK FOR END
JR NZ,VGA_LOADFONT1 ; LOOP
LD HL,$7070 ; SET FONT PAGE NUM TO 7
CALL VGA_SETCFG
RET ; DONE
;
;----------------------------------------------------------------------
; SET CURSOR POSITION TO ROW IN D AND COLUMN IN E
;----------------------------------------------------------------------
;
VGA_XY:
CALL VGA_XY2IDX ; CONVERT ROW/COL TO BUF IDX
LD (VGA_POS),HL ; SAVE THE RESULT (DISPLAY POSITION)
LD C,14 ; CURSOR POSITION REGISTER PAIR
JP VGA_REGWRX ; DO IT AND RETURN
;
;----------------------------------------------------------------------
; CONVERT XY COORDINATES IN DE INTO LINEAR INDEX IN HL
; D=ROW, E=COL
;----------------------------------------------------------------------
;
VGA_XY2IDX:
LD A,E ; SAVE COLUMN NUMBER IN A
LD H,D ; SET H TO ROW NUMBER
LD E,VGA_COLS ; SET E TO ROW LENGTH
CALL MULT8 ; MULTIPLY TO GET ROW OFFSET
LD E,A ; GET COLUMN BACK
ADD HL,DE ; ADD IT IN
RET ; RETURN
;
;----------------------------------------------------------------------
; WRITE VALUE IN A TO CURRENT VDU BUFFER POSTION, ADVANCE CURSOR
;----------------------------------------------------------------------
;
VGA_PUTCHAR:
; SETUP DE WITH BUFFER ADDRESS
LD DE,(VGA_POS) ; GET CURRENT POSITION
RL E ; MULTIPLY BY 2
RL D ; ... 2 BYTES PER CHAR
; SETUP CHAR/ATTR IN HL
LD H,A ; CHARACTER
LD A,(VGA_ATTR) ; ATTRIBUTE
LD L,A ; ... TO L
; WRITE CHAR & ATTR
CALL VGA_MEMWRX
; UPDATE CURRENT POSITION
LD HL,(VGA_POS) ; GET CURSOR POSITION
INC HL ; INCREMENT
LD (VGA_POS),HL ; SAVE NEW POSITION
LD C,14 ; CURSOR POSITION REGISTER PAIR
JP VGA_REGWRX ; DO IT AND RETURN
;
;----------------------------------------------------------------------
; FILL AREA IN BUFFER WITH SPECIFIED CHARACTER AND CURRENT COLOR/ATTRIBUTE
; STARTING AT THE CURRENT FRAME BUFFER POSITION
; A: FILL CHARACTER
; DE: NUMBER OF CHARACTERS TO FILL
;----------------------------------------------------------------------
;
VGA_FILL:
PUSH DE ; COUNT ON STACK
LD H,A ; H = CHAR
LD A,(VGA_ATTR) ; GET CUR ATTR
LD L,A ; PUT INT L
; SETUP DE WITH INITIAL BUFFER ADDRESS
LD DE,(VGA_POS) ; GET CURRENT POSITION
RL E ; MULTIPLY BY 2
RL D ; ... 2 BYTES PER CHAR
LD C,VGA_HI
VGA_FILL1:
OUT (C),D ; SET HI ADDR
INC C ; POINT TO LO ADDR REG
VGA_FILL2:
EX (SP),HL ; HL = COUNT, SAVE CHAR/ATTR
LD A,H ; CHECK FOR
OR L ; ... ZERO
JR Z,VGA_FILL3 ; ALL DONE
DEC HL ; DEC COUNT
EX (SP),HL ; HL = CHAR/ATTR, COUNT ON STACK
OUT (C),E ; SET LO ADDR
INC C ; POINT TO DATA REG
OUT (C),H ; OUTPUT CHAR
INC E ; INC ADDR
DEC C ; POINT TO LO ADDR REG
OUT (C),E ; UPDATE LO ADDR
INC C ; POINT TO DATA REG
OUT (C),L ; OUTPUT ATTR
DEC C ; POINT TO LO ADDR REG
INC E ; INC ADDR LO
JR NZ,VGA_FILL2 ; IF NO CF, SHORT LOOP
DEC C ; POINT TO HI ADDR REG
INC D ; INC ADDR HI
JR VGA_FILL1 ; FULL LOOP
VGA_FILL3:
POP DE ; CLEAR STACK
RET
;
;----------------------------------------------------------------------
; SCROLL ENTIRE SCREEN FORWARD BY ONE LINE (CURSOR POSITION UNCHANGED)
;----------------------------------------------------------------------
;
VGA_SCROLL:
; CLEAR LINE ABOUT TO BE EXPOSED
LD DE,(VGA_POS)
PUSH DE
LD DE,0 + (VGA_ROWS * VGA_COLS)
LD (VGA_POS),DE
LD DE,VGA_COLS
LD A,' '
CALL VGA_FILL
POP DE
LD (VGA_POS),DE
; USE BLOCK COPY TO SCROLL UP ONE LINE
LD HL,VGA_COLS
LD DE,0
LD BC,0 + ((VGA_ROWS) * VGA_COLS)
CALL VGA_BLKCPY
RET
;
;----------------------------------------------------------------------
; REVERSE SCROLL ENTIRE SCREEN BY ONE LINE (CURSOR POSITION UNCHANGED)
;----------------------------------------------------------------------
;
VGA_RSCROLL:
; USE BLOCK COPY TO SCROLL DOWN ONE LINE
LD HL,0 + ((VGA_ROWS - 1) * VGA_COLS) - 1 ; SRC IS EOS - 1 LINE
LD DE,0 + ((VGA_ROWS) * VGA_COLS) - 1 ; DEST IS EOS
LD BC,0 + ((VGA_ROWS - 1) * VGA_COLS) ; LENGTH IS ROWS - 1
CALL VGA_RBLKCPY
; CLEAR TOP LINE
LD DE,(VGA_POS)
PUSH DE
LD DE,0
LD (VGA_POS),DE
LD DE,VGA_COLS
LD A,' '
CALL VGA_FILL
POP DE
LD (VGA_POS),DE
RET
;
;----------------------------------------------------------------------
; BLOCK COPY BC BYTES FROM HL TO DE
;----------------------------------------------------------------------
;
VGA_BLKCPY:
; ADJUST POINTERS FOR 2 BYTE WIDTH (CHAR & ATTR)
RL E
RL D
RL L
RL H
VGA_BLKCPY1:
PUSH BC ; SAVE COUNT
; BA = (HL), HL INCREMENTED
LD C,VGA_HI ; C := VGA_HI
OUT (C),H ; VGA_HI := SOURCE HI (H)
INC C ; C := VGA_LO
OUT (C),L ; VGA_LO := SOURCE LO (L)
INC C ; C := VGA_DATA
IN B,(C) ; B := EVEN DATA BYTE (CHAR)
INC HL ; INC SOURCE PTR
DEC C ; C := VGA_LO
OUT (C),L ; VGA_LO := SOURCE LO (L), VGA_HI IS UNCHANGED!
INC C ; C := VGA_DATA
IN A,(C) ; A := ODD DATA BYTE (ATTR)
INC HL ; INC SOURCE PTR
; (DE) = BA, DE INCREMENTED
LD C,VGA_HI ; C := VGA_HI
OUT (C),D ; VGA_HI := DEST HI (D)
INC C ; C := VGA_LO
OUT (C),E ; VGA_LO := DEST LO (E)
INC C ; C := VGA_DATA
OUT (C),B ; EVEN DATA BYTE (CHAR) := B
INC DE ; INC DEST PTR
DEC C ; C := VGA_LO
OUT (C),E ; VGA_LO := DEST LO (E), VGA_HI IS UNCHANGED
INC C ; C := VGA_DATA
OUT (C),A ; ODD DATA BYTE (ATTR) := A
INC DE ; INC DEST PTR
; CHECK COUNT AND LOOP TILL DONE
POP BC ; RECOVER COUNT
DEC BC ; DEC COUNT
LD A,B ; CHECK COUNT
OR C ; ... FOR ZERO
JR NZ,VGA_BLKCPY1 ; LOOP TILL DONE
RET ; DONE
;
VGA_RBLKCPY:
; ADJUST POINTERS FOR 2 BYTE WIDTH (CHAR & ATTR)
RL E
RL D
RL L
RL H
; ADJUST TO POINT TO SECOND BYTE OF PAIR (ATTR)
INC E
INC L
VGA_RBLKCPY1:
PUSH BC ; SAVE COUNT
; BA = (HL), HL INCREMENTED
LD C,VGA_HI ; C := VGA_HI
OUT (C),H ; VGA_HI := SOURCE HI (H)
INC C ; C := VGA_LO
OUT (C),L ; VGA_LO := SOURCE LO (L)
INC C ; C := VGA_DATA
IN A,(C) ; A := ODD DATA BYTE (ATTR)
DEC HL ; DEC SOURCE PTR
DEC C ; C := VGA_LO
OUT (C),L ; VGA_LO := SOURCE LO (L), VGA_HI IS UNCHANGED!
INC C ; C := VGA_DATA
IN B,(C) ; B := EVEN DATA BYTE (CHAR)
DEC HL ; DEC SOURCE PTR
; (DE) = BA, DE INCREMENTED
LD C,VGA_HI ; C := VGA_HI
OUT (C),D ; VGA_HI := DEST HI (D)
INC C ; C := VGA_LO
OUT (C),E ; VGA_LO := DEST LO (E)
INC C ; C := VGA_DATA
OUT (C),A ; ODD DATA BYTE (ATTR) := A
DEC DE ; DEC DEST PTR
DEC C ; C := VGA_LO
OUT (C),E ; VGA_LO := DEST LO (E), VGA_HI IS UNCHANGED
INC C ; C := VGA_DATA
OUT (C),B ; EVEN DATA BYTE (CHAR) := B
DEC DE ; DEC DEST PTR
; CHECK COUNT AND LOOP TILL DONE
POP BC ; RECOVER COUNT
DEC BC ; DEC COUNT
LD A,B ; CHECK COUNT
OR C ; ... FOR ZERO
JR NZ,VGA_RBLKCPY1 ; LOOP TILL DONE
RET ; DONE
;
;==================================================================================================
; VGA DRIVER - DATA
;==================================================================================================
;
VGA_ATTR .DB 0 ; CURRENT COLOR
VGA_POS .DW 0 ; CURRENT DISPLAY POSITION
VGA_CFGV .DB 0 ; CURRENT BOARD CONFIG VALUE
VGA_RUB .DB 0 ; REVERSE/UNDERLINE/BLINK (-----RUB)
;
; ATTRIBUTE ENCODING:
; BIT 7: ALT FONT
; BIT 6: BG REG
; BIT 5: BG GREEN
; BIT 4: BG BLUE
; BIT 3: FG INTENSITY
; BIT 2: FG RED
; BIT 1: FG GREEN
; BIT 0: FG BLUE
;
;===============================================================================
; DEFAULT REGISTER VALUES
;===============================================================================
;
REGS_VGA:
.DB 0,100 - 1 ; HORZ TOT - 1
.DB 1,80 ; HORZ DISP
.DB 2,80 + 2 ; HORZ DISP + HORZ FP
.DB 3,(2 << 4) | (12 & $0F) ; VERT SW, HORZ SW
.DB 4,28 - 1 ; VERT TOT - 1
.DB 5,1 ; VERT TOT ADJ
.DB 6,25 ; VERT DISP
.DB 7,25 + 1 ; VERT DISP + VERT FP
.DB 9,16 - 1 ; CHAR HEIGHT - 1
.DB 10,(13 | $60) ; CURSOR START & CURSOR BLINK
.DB 11,14 ; CURSOR END
.DB 12,($0000 >> 8) & $FF ; SCRN 1 START (HI)
.DB 13,($0000 & $FF) ; SCRN 1 START (LO)
.DB 30,0 ; CONTROL 1
.DB 31,0 ; CONTROL 2
.DB 33,0 ; CONTROL 3
.DB $FF ; END MARKER
;
;==================================================================================================
; VGA DRIVER - INSTANCE DATA
;==================================================================================================
;
VGA_IDAT:
.DB VGA_KBDST
.DB VGA_KBDDATA