;====================================================================== ; 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