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.
397 lines
11 KiB
397 lines
11 KiB
;======================================================================
|
|
; VDU DRIVER FOR N8VEM PROJECT
|
|
;
|
|
; ORIGINALLY WRITTEN BY: ANDREW LYNCH
|
|
; REVISED/ENHANCED BY DAN WERNER -- 11/7/2009
|
|
; ROMWBW ADAPTATION BY: WAYNE WARTHEN -- 11/9/2012
|
|
;======================================================================
|
|
;
|
|
; TODO:
|
|
; - ADD REMAINING REGISTERS TO INIT
|
|
; - TRY 25 ROW MODE?
|
|
; - IMPLEMENT CONSTANTS FOR SCREEN DIMENSIONS
|
|
; - IMPLEMENT SET CURSOR STYLE (VDASCS) FUNCTION
|
|
; - IMPLEMENT ALTERNATE DISPLAY MODES?
|
|
;
|
|
;======================================================================
|
|
; CVDU DRIVER - CONSTANTS
|
|
;======================================================================
|
|
;
|
|
VDU_RAMRD .EQU 0F0h ; READ VDU
|
|
VDU_RAMWR .EQU 0F1h ; WRITE VDU
|
|
VDU_STAT .EQU 0F2h ; VDU STATUS/REGISTER
|
|
VDU_REG .EQU 0F2h ; VDU STATUS/REGISTER
|
|
VDU_DATA .EQU 0F3h ; VDU DATA REGISTER
|
|
;
|
|
;======================================================================
|
|
; VDU DRIVER - INITIALIZATION
|
|
;======================================================================
|
|
;
|
|
VDU_INIT:
|
|
PRTS("VDU:$")
|
|
CALL VDU_CRTINIT ; INIT SY6845 VDU CHIP
|
|
|
|
VDU_RESET:
|
|
LD DE,0
|
|
LD (VDU_OFFSET),DE
|
|
CALL VDU_XY
|
|
LD A,' '
|
|
LD DE,1024*16
|
|
CALL VDU_FILL
|
|
XOR A
|
|
RET
|
|
;
|
|
;======================================================================
|
|
; VDU DRIVER - CHARACTER I/O (CIO) DISPATCHER AND FUNCTIONS
|
|
;======================================================================
|
|
;
|
|
VDU_DISPCIO:
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
AND $0F ; ISOLATE SUB-FUNCTION
|
|
JR Z,VDU_CIOIN ; $00
|
|
DEC A
|
|
JR Z,VDU_CIOOUT ; $01
|
|
DEC A
|
|
JR Z,VDU_CIOIST ; $02
|
|
DEC A
|
|
JR Z,VDU_CIOOST ; $03
|
|
CALL PANIC
|
|
;
|
|
VDU_CIOIN:
|
|
JP PPK_READ ; CHAIN TO KEYBOARD DRIVER
|
|
;
|
|
VDU_CIOIST:
|
|
JP PPK_STAT ; CHAIN TO KEYBOARD DRIVER
|
|
;
|
|
VDU_CIOOUT:
|
|
JP VDU_VDAWRC ; WRITE CHARACTER
|
|
;
|
|
VDU_CIOOST:
|
|
XOR A ; A := 0
|
|
INC A ; A := 1, SIGNAL OUTPUT BUFFER READY
|
|
RET
|
|
;
|
|
;======================================================================
|
|
; VDU DRIVER - VIDEO DISPLAY ADAPTER (VDA) DISPATCHER AND FUNCTIONS
|
|
;======================================================================
|
|
;
|
|
VDU_DISPVDA:
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
AND $0F ; ISOLATE SUB-FUNCTION
|
|
|
|
JR Z,VDU_VDAINI ; $40
|
|
DEC A
|
|
JR Z,VDU_VDAQRY ; $41
|
|
DEC A
|
|
JR Z,VDU_VDARES ; $42
|
|
DEC A
|
|
JR Z,VDU_VDASCS ; $43
|
|
DEC A
|
|
JR Z,VDU_VDASCP ; $44
|
|
DEC A
|
|
JR Z,VDU_VDASAT ; $45
|
|
DEC A
|
|
JR Z,VDU_VDASCO ; $46
|
|
DEC A
|
|
JR Z,VDU_VDAWRC ; $47
|
|
DEC A
|
|
JR Z,VDU_VDAFIL ; $48
|
|
DEC A
|
|
JR Z,VDU_VDASCR ; $49
|
|
DEC A
|
|
JP Z,PPK_STAT ; $4A
|
|
DEC A
|
|
JP Z,PPK_FLUSH ; $4B
|
|
DEC A
|
|
JP Z,PPK_READ ; $4C
|
|
CALL PANIC
|
|
|
|
VDU_VDAINI:
|
|
JR VDU_INIT ; INITIALIZE
|
|
|
|
VDU_VDAQRY:
|
|
LD C,$00 ; MODE ZERO IS ALL WE KNOW
|
|
LD DE,$1850 ; 24 ROWS ($18), 80 COLS ($50)
|
|
LD HL,0 ; EXTRACTION OF CURRENT BITMAP DATA NOT SUPPORTED
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
VDU_VDARES:
|
|
JR VDU_RESET ; DO THE RESET
|
|
|
|
VDU_VDASCS:
|
|
CALL PANIC ; NOT IMPLEMENTED (YET)
|
|
|
|
VDU_VDASCP:
|
|
CALL VDU_XY
|
|
XOR A
|
|
RET
|
|
|
|
VDU_VDASAT:
|
|
XOR A
|
|
RET
|
|
|
|
VDU_VDASCO:
|
|
XOR A
|
|
RET
|
|
|
|
VDU_VDAWRC:
|
|
LD A,E
|
|
CALL VDU_PUTCHAR
|
|
XOR A
|
|
RET
|
|
|
|
VDU_VDAFIL:
|
|
LD A,E ; FILL CHARACTER GOES IN A
|
|
EX DE,HL ; FILL LENGTH GOES IN DE
|
|
CALL VDU_FILL ; DO THE FILL
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
VDU_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,VDU_VDASCR1 ; E IS NEGATIVE, REVERSE SCROLL
|
|
CALL VDU_SCROLL ; SCROLL FORWARD ONE LINE
|
|
POP DE ; RECOVER E
|
|
DEC E ; DECREMENT IT
|
|
JR VDU_VDASCR ; LOOP
|
|
VDU_VDASCR1:
|
|
CALL VDU_RSCROLL ; SCROLL REVERSE ONE LINE
|
|
POP DE ; RECOVER E
|
|
INC E ; INCREMENT IT
|
|
JR VDU_VDASCR ; LOOP
|
|
;
|
|
;======================================================================
|
|
; CVDU DRIVER - PRIVATE DRIVER FUNCTIONS
|
|
;======================================================================
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; WAIT FOR VDU TO BE READY FOR A DATA READ/WRITE
|
|
;----------------------------------------------------------------------
|
|
;
|
|
VDU_WAITRDY:
|
|
IN A,(VDU_STAT) ; READ STATUS
|
|
OR A ; SET FLAGS
|
|
RET M ; IF BIT 7 SET, THEN READY!
|
|
JR VDU_WAITRDY ; KEEP CHECKING
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; UPDATE SY6845 REGISTERS
|
|
; VDU_WRREG WRITES VALUE IN A TO VDU REGISTER SPECIFIED IN C
|
|
; VDU_WRREGX WRITES VALUE IN DE TO VDU REGISTER PAIR IN C, C+1
|
|
;----------------------------------------------------------------------
|
|
;
|
|
VDU_WRREG:
|
|
PUSH AF ; SAVE VALUE TO WRITE
|
|
LD A,C ; SET A TO CVDU REGISTER TO SELECT
|
|
OUT (VDU_REG),A ; WRITE IT TO SELECT THE REGISTER
|
|
POP AF ; RECOVER VALUE TO WRITE
|
|
OUT (VDU_DATA),A ; WRITE IT
|
|
RET
|
|
;
|
|
VDU_WRREGX:
|
|
LD A,H ; SETUP MSB TO WRITE
|
|
CALL VDU_WRREG ; DO IT
|
|
INC C ; NEXT CVDU REGISTER
|
|
LD A,L ; SETUP LSB TO WRITE
|
|
JR VDU_WRREG ; DO IT & RETURN
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; READ SY6845 REGISTERS
|
|
; VDU_RDREG READS VDU REGISTER SPECIFIED IN C AND RETURNS VALUE IN A
|
|
; VDU_RDREGX READS VDU REGISTER PAIR SPECIFIED BY C, C+1
|
|
; AND RETURNS VALUE IN HL
|
|
;----------------------------------------------------------------------
|
|
;
|
|
VDU_RDREG:
|
|
LD A,C ; SET A TO CVDU REGISTER TO SELECT
|
|
OUT (VDU_REG),A ; WRITE IT TO SELECT THE REGISTER
|
|
IN A,(VDU_DATA) ; READ IT
|
|
RET
|
|
;
|
|
VDU_RDREGX:
|
|
CALL VDU_RDREG ; GET VALUE FROM REGISTER IN C
|
|
LD H,A ; SAVE IN H
|
|
INC C ; BUMP TO NEXT REGISTER OF PAIR
|
|
CALL VDU_RDREG ; READ THE VALUE
|
|
LD L,A ; SAVE IT IN L
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; SY6845 DISPLAY CONTROLLER CHIP INITIALIZATION
|
|
;----------------------------------------------------------------------
|
|
;
|
|
VDU_CRTINIT:
|
|
LD C,0 ; START WITH REGISTER 0
|
|
LD B,16 ; INIT 16 REGISTERS
|
|
LD HL,VDU_INIT6845 ; HL = POINTER TO THE DEFAULT VALUES
|
|
VDU_CRTINIT1:
|
|
LD A,(HL) ; GET VALUE
|
|
CALL VDU_WRREG ; WRITE IT
|
|
INC HL ; POINT TO NEXT VALUE
|
|
INC C ; POINT TO NEXT REGISTER
|
|
DJNZ VDU_CRTINIT1 ; LOOP
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; SET CURSOR POSITION TO ROW IN D AND COLUMN IN E
|
|
;----------------------------------------------------------------------
|
|
;
|
|
VDU_XY:
|
|
LD A,E ; SAVE COLUMN NUMBER IN A
|
|
LD H,D ; SET H TO ROW NUMBER
|
|
LD E,80 ; SET E TO ROW LENGTH
|
|
CALL MULT8 ; MULTIPLY TO GET ROW OFFSET
|
|
LD E,A ; GET COLUMN BACK
|
|
ADD HL,DE ; ADD IT IN
|
|
LD (VDU_POS),HL ; SAVE THE RESULT (DISPLAY POSITION)
|
|
LD DE,(VDU_OFFSET) ; NOW GET THE BUFFER OFFSET
|
|
ADD HL,DE ; AND ADD THAT IN
|
|
LD C,14 ; CURSOR POSITION REGISTER PAIR
|
|
JP VDU_WRREGX ; DO IT AND RETURN
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; WRITE VALULE IN A TO CURRENT VDU BUFFER POSTION, ADVANCE CURSOR
|
|
;----------------------------------------------------------------------
|
|
;
|
|
VDU_PUTCHAR:
|
|
LD B,A ; SAVE THE CHARACTER
|
|
|
|
; SET BUFFER WRITE POSITION
|
|
LD HL,(VDU_OFFSET)
|
|
LD DE,(VDU_POS)
|
|
ADD HL,DE
|
|
INC DE ; INC
|
|
LD (VDU_POS),DE ; SAVE NEW SCREEN POSITION
|
|
LD C,18 ; UPDATE ADDRESS REGISTER PAIR
|
|
CALL VDU_WRREGX ; DO IT
|
|
INC HL ; NEW CURSOR POSITION
|
|
LD C,14 ; CURSOR POSITION REGISTER PAIR
|
|
CALL VDU_WRREGX ; DO IT
|
|
|
|
LD A,31 ; PREP VDU FOR DATA R/W
|
|
OUT (VDU_REG),A
|
|
CALL VDU_WAITRDY ; WAIT FOR VDU TO BE READY
|
|
LD A,B
|
|
OUT (VDU_RAMWR),A ; OUTPUT CHAR TO VDU
|
|
|
|
RET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; 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
|
|
;----------------------------------------------------------------------
|
|
;
|
|
VDU_FILL:
|
|
LD B,A ; SAVE THE FILL CHARACTER
|
|
|
|
; SET FILL START POSITION
|
|
PUSH DE
|
|
LD HL,(VDU_OFFSET)
|
|
LD DE,(VDU_POS)
|
|
ADD HL,DE
|
|
LD C,18
|
|
CALL VDU_WRREGX
|
|
POP DE
|
|
|
|
; FILL LOOP
|
|
LD A,31 ; PREP VDU FOR DATA R/W
|
|
OUT (VDU_REG),A
|
|
VDU_FILL1:
|
|
LD A,D ; CHECK NUMBER OF FILL CHARS LEFT
|
|
OR E
|
|
RET Z ; ALL DONE, RETURN
|
|
CALL VDU_WAITRDY ; WAIT FOR VDU TO BE READY
|
|
LD A,B
|
|
OUT (VDU_RAMWR),A ; OUTPUT CHAR TO VDU
|
|
DEC DE ; DECREMENT COUNT
|
|
JR VDU_FILL1 ; LOOP
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; SCROLL ENTIRE SCREEN FORWARD BY ONE LINE (CURSOR POSITION UNCHANGED)
|
|
;----------------------------------------------------------------------
|
|
;
|
|
VDU_SCROLL:
|
|
; SCROLL FORWARD BY ADDING ONE ROW TO DISPLAY START ADDRESS
|
|
LD HL,(VDU_OFFSET)
|
|
LD DE,80
|
|
ADD HL,DE
|
|
LD (VDU_OFFSET),HL
|
|
LD C,12
|
|
CALL VDU_WRREGX
|
|
|
|
; FILL EXPOSED LINE
|
|
LD HL,(VDU_POS)
|
|
PUSH HL
|
|
LD HL,23*80
|
|
LD (VDU_POS),HL
|
|
LD DE,80
|
|
LD A,' '
|
|
CALL VDU_FILL
|
|
POP HL
|
|
LD (VDU_POS),HL
|
|
|
|
; ADJUST CURSOR POSITION
|
|
LD HL,(VDU_OFFSET)
|
|
LD DE,(VDU_POS)
|
|
ADD HL,DE
|
|
LD C,14
|
|
JP VDU_WRREGX
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; REVERSE SCROLL ENTIRE SCREEN BY ONE LINE (CURSOR POSITION UNCHANGED)
|
|
;----------------------------------------------------------------------
|
|
;
|
|
VDU_RSCROLL:
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; VDU DRIVER - DATA
|
|
;==================================================================================================
|
|
;
|
|
VDU_POS .DW 0 ; CURRENT DISPLAY POSITION
|
|
VDU_OFFSET .DW 0 ; CURRENT DISPLAY POSITION
|
|
;
|
|
;==================================================================================================
|
|
; VDU DRIVER - SY6845 REGISTER INITIALIZATION
|
|
;==================================================================================================
|
|
;
|
|
VDU_INIT6845:
|
|
; DB 07FH, 50H, 60H, 7CH, 19H, 1FH, 19H, 1AH, 78H, 09H, 60H, 09H, 00H, 00H, 00H, 00H
|
|
;
|
|
; CCIR 625/50 VERSION (USED IN MOST OF THE WORLD)
|
|
; JUMPER K1 2-3, K2 1-2 FOR 2MHz CHAR CLOCK
|
|
.DB 07FH ; R0 TOTAL NUMBER OF HORIZONTAL CHARACTERS (DETERMINES HSYNC)
|
|
.DB 050H ; R1 NUMBER OF HORIZONTAL CHARACTERS DISPLAYED (80 COLUMNS)
|
|
.DB 060H ; R2 HORIZONTAL SYNC POSITION
|
|
.DB 00CH ; R3 SYNC WIDTHS
|
|
.DB 01EH ; R4 VERTICAL TOTAL (TOTAL CHARS IN A FRAME -1)
|
|
.DB 002H ; R5 VERTICAL TOTAL ADJUST (
|
|
.DB 018H ; R6 VERTICAL DISPLAYED (24 ROWS)
|
|
.DB 01AH ; R7 VERTICAL SYNC
|
|
.DB 078H ; R8 MODE B7=0 TRANSPARENT UPDATE DURING BLANKING
|
|
; B6=1 PIN 34 IS UPDATE STROBE
|
|
; B5=1 DELAY CURSOR 1 CHARACTER
|
|
; B4=1 DELAY DISPLAY ENABLE 1 CHARACTER
|
|
; B3=1 TRANSPARENT MEMORY ADDRESSING
|
|
; B2=0 RAM STRAIGHT BINARY ADDRESSING
|
|
; B1,B0=0 NON-INTERLACE
|
|
.DB 009H ; R9 SCAN LINE (LINES PER CHAR AND SPACING -1)
|
|
.DB 060H ; R10 CURSOR START RASTER
|
|
.DB 009H ; R11 CURSOR END RASTER
|
|
.DB 00H ; R12 START ADDRESS HI
|
|
.DB 00H ; R13 START ADDRESS LO
|
|
.DB 00H ; R14 CURSOR ADDRESS HI
|
|
.DB 00H ; R15 CURSOR ADDRESS LO
|
|
;
|
|
; THE CCIR 625/50 TELEVISION STANDARD HAS 625 LINES INTERLACED AT 50 FIELDS PER SECOND. THIS WORKS
|
|
; OUT AS 50 FIELDS OF 312.5 LINES PER SECOND NON-INTERLACED AS USED HERE.
|
|
; HORIZONTAL LINE WIDTH IS 64uS. FOR A 2 MHz CHARACTER CLOCK (R0+1)/2000000 = 64uS
|
|
; NEAREST NUMBER OF LINES IS 312 = (R4+1) * (R9+1) + R5.
|
|
; 15625 / 312 = 50.08 FIELDS PER SECOND (NEAR ENOUGH-DGG)
|
|
;
|
|
|