mirror of https://github.com/wwarthen/RomWBW.git
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
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
|
|
|