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.
 
 
 
 
 
 

1085 lines
21 KiB

;======================================================================
; EF9345 DRIVER FOR ROMWBW
;
; PARTS WRITTEN BY: ALAN COX
; REVISED/ENHANCED BY LASZLO SZOLNOKI -- 01/2024
;======================================================================
; TODO:
; - 40X24 IMPLEMENTATION
;======================================================================
; EF9345 DRIVER - CONSTANTS
;======================================================================
;
TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER
;
EF_BASE .EQU $F0
EF_SETREG .EQU EF_BASE + 4
EF_DATAACC .EQU EF_BASE + 5
EF_RESET .EQU EF_BASE + 6
;
EF_SIZE .EQU V80X24
;
EF_R0 .EQU $20
EF_R1 .EQU EF_R0+1
EF_R2 .EQU EF_R0+2
EF_R3 .EQU EF_R0+3
EF_R4 .EQU EF_R0+4
EF_R5 .EQU EF_R0+5
EF_R6 .EQU EF_R0+6
EF_R7 .EQU EF_R0+7
;
EF_XA .EQU EF_R5
EF_YA .EQU EF_R4
EF_XP .EQU EF_R7
EF_YP .EQU EF_R6
;
EF_EXEC .EQU 00001000b
;
EF_TGSREG .EQU 1
EF_MATREG .EQU 2
EF_PATREG .EQU 3
EF_DORREG .EQU 4
EF_RORREG .EQU 7
;EF_WRTINDIR .EQU 10000000b
;
; CMD
;
EF_NOP .EQU $91 ;
EF_IND .EQU $80 ;
EF_CLF .EQU $05 ;
EF_OCT .EQU $30 ;
EF_OCTAUX .EQU $04 ; AUXILIARY POITER
EF_KRF .EQU $00 ; NO AUTOINCREMENT
EF_KRL .EQU $50 ; NO AUTOINCREMENT
EF_INY .EQU $B0 ; INC Y
;
;EF_IND_TGS .EQU $81
;EF_IND_MAT .EQU $82
;EF_IND_PAT .EQU $83
;EF_IND_DOR .EQU $84
;EF_IND_ROR .EQU $87
EF_RREG .EQU 00001000b
;EF_WREG .EQU ~EF_RREG
;
; | 1 | 0 | 0| 0| R/!W | r | r | r | IND command
; 0 0 1 TGS
; 0 1 0 MAT
; 0 1 1 PAT
; 1 0 0 DOR
; 1 0 1
; 1 1 0
; 1 1 1 ROR
; MAT5 MAT4
; fixed complemented 0 0
; flash complemented 1 0
; fixed underlined 0 1
; flash underlined 1 1
;
EF_NOCU .EQU 10111111B ; MAT6 = 0 : NO CURSOR
EF_BLK .EQU 00100000B ; MAT5 = 1 : BLINK CURSOR
EF_NOBL .EQU 11011111B ; MAT5 = 0 : NO BLINK
;
EF_BLOK .EQU 11101111b ; MAT4 = 0 : BLOCK CURSOR
EF_ULIN .EQU 00010000b ; MAT4 = 1 : UNDERLINE CURSOR
;
EF_CURENA .EQU TRUE ; ENABLE CURSOR
;
EF_MARCOL .EQU 00000000B ; MARGIN COLOR BLACK : MAT0 = R, MAT1 = G, MAT2 = B
EF_MARENA .EQU 00001000B ; MARGIN INSERT : MAT3 = 1
;
EF_CUREN .EQU 01000000B ; MAT6 = 1 : CURSOR ENABLED
EF_DISCU .EQU 10111111B ; MAT6 = 0 : NO CURSOR
;
EF_BLINK .EQU 00100000B ; MAT5 = 1 : BLINK CURSOR
EF_NOBLINK .EQU 11011111B ; MAT5 = 0 : NO BLINK
;
EF_COMPL .EQU 11101111b ; MAT4 = 0 : BLOCK CURSOR
;
EF_FLASHCHAR .EQU 00001000B
EF_REVERSCHAR .EQU 10000000B
;
#IF EF_CURENA
EF_CSTY .EQU EF_CUREN | EF_BLINK | EF_ULIN | EF_MARENA | EF_MARCOL
#ELSE
EF_CSTY .EQU EF_MARENA | EF_MARCOL
#ENDIF
;
FIRSTLINE .EQU 8
;
#IF (EF_SIZE=V80X24) ; V80X24
EF_DLINES .EQU 24
EF_DROWS .EQU 80
EF_DSCANL .EQU 10
; ATTRIBUTES
EF_FLASH .EQU 01000100B
EF_NEGATIVE .EQU 10001000B
EF_UNDERLINE .EQU 00100010B
EF_COLORSET .EQU 00010001B
#ENDIF
;
#IF (EF_SIZE=V40X24)
EF_DLINES .EQU 24
EF_DROWS .EQU 40
EF_DSCANL .EQU 10
; ATTRIBUTES
EF_FLASH .EQU 01000100B
EF_NEGATIVE .EQU 10001000B
EF_UNDERLINE .EQU 00100010B
EF_COLORSET .EQU 00010001B
#ENDIF
;
; DISTRICTS
;
EF_DIST0 .EQU 0
EF_DIST1 .EQU $20
EF_DIST2 .EQU $80
EF_DIST3 .EQU $A0
;
EF_BG_BLACK .EQU $0
EF_BG_RED .EQU $10
EF_BG_GREEN .EQU $20
EF_BG_BROWN .EQU $30
EF_BG_BLUE .EQU $40
EF_BG_MAGENTA .EQU $50
EF_BG_CYAN .EQU $60
EF_BG_WHITE .EQU $70
EF_FG_BLACK .EQU 0
EF_FG_RED .EQU 1
EF_FG_GREEN .EQU 2
EF_FG_BROWN .EQU 3
EF_FG_BLUE .EQU 4
EF_FG_MAGENTA .EQU 5
EF_FG_CYAN .EQU 6
EF_FG_WHITE .EQU 7
;
EF_SCREENSIZE .EQU EF_DROWS * EF_DLINES
;
;======================================================================
; VDU DRIVER - INITIALIZATION
;======================================================================
;
EF_INIT:
;
LD IY,EF_IDAT ; POITER TO INSTANCE DATA
;
CALL NEWLINE ; FORMATTING
PRTS("EF : IO=0x$")
LD A,EF_BASE
CALL PRTHEXBYTE
PRTS(" MODE=$") ; OUTPUT DISPLAY FORMAT
LD A,EF_DROWS
CALL PRTDECB
PRTS("X$")
LD A,EF_DLINES
CALL PRTDECB
CALL EF_PROBE ; CHECK FOR HW EXISTENCE
JR Z,EF_INIT1 ; CONTINUE IF HW PRESENT
;
PRTS(" NOT PRESENT$")
XOR A
OR -8 ; HARDWARE NOT PRESENT
RET
;
EF_INIT1:
OUT (EF_RESET),A ; HARDWARE RESET
;
LD A,EF_DIST0
LD (EF_CON_BANKY),A ;
;
CALL EF_CRTINIT ; INIT EF9345 CHIP
;
; ADD OURSELVES TO VDA DISPATCH TABLE
LD BC,EF_FNTBL ; BC := FUNCTION TABLE ADDRESS
LD DE,EF_IDAT ; DE := VDU INSTANCE DATA PTR
CALL VDA_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED
;
#IF TERMENABLE
; INITIALIZE EMULATION
LD C,A ; ASSIGNED VIDEO UNIT IN C
LD DE,EF_FNTBL ; DE := FUNCTION TABLE ADDRESS
LD HL,EF_IDAT ; HL := VDU INSTANCE DATA PTR
CALL TERM_ATTACH ; DO IT
#ENDIF
;
XOR A ; SIGNAL SUCCESS
RET
;
EF_CRTINIT:
LD DE,(EF_R0+EF_EXEC)*256 + EF_NOP ; FORCE NOP
CALL EF_WWRREG
;
LD HL,EF_INIT9345 ; INITIAL SETUP PARAMETERS
CALL EF_LOAD_MODE
;
LD DE,0
LD (EF_VDA_OFFSET),DE
;
#IF (EF_SIZE = V40X24)
XOR A
LD (EF_VDATYPESET),A
#ENDIF
;
; E = CHARACTER ATTRIBUTES : E0 = BLINK, E1 = UNDELINE, E2 = REVERSE, E3 = COLOR SET
; VIDEO SET CHARACTER ATTRIBUTE FOR SCROLL, KRL, ETC.
LD E,00000000B
CALL EF_VDASAT
;
LD E,EF_BG_BLACK + EF_FG_WHITE ; SET CHARACTER COLOR
CALL EF_VDASCO
;
; VIDEO SET CURSOR STYLE
; ENTRY: C = VIDEO UNIT, D = START/END, E = STYLE : E0 = BLINK/FLASH, E1 = UNDELINE, E2 = REVERSE/COMPLEMENT
; MAT5 = 1 : FLASH, MAT4 = 0 : COMPLEMENT
; RETURN A = STATUS
LD E,3 ; UNDERLINED BLINKING
CALL EF_VDASCS
;
CALL EF_CLEARALL
;
LD DE,0 ; SET CURSOR TO 0,0
CALL EF_VDASCP
RET
;
EF_CLEARALL:
LD DE,0 ; SET CURSOR 0,0
CALL EF_VDASCP ; D = ROW, E = COLUMNS
LD HL,EF_DROWS * EF_DLINES
;
LD E,' '
CALL EF_VDAFIL
XOR A
RET
;
; R1 := C BYTE IS THE CHARACTER CODE
; R2 := B BYTE TYPE AND SET, OTHER PARAMETERS
; R3 := A BYTE ATTRIBUTES, NEGATIVE, FG COLOR, FLASH, BG COLOR
;
#IF (EF_SIZE=V80X24)
EF_KRL80:
PUSH DE
LD DE,EF_R0*256 + EF_KRL ; R0 KRL COMMAND
CALL EF_WWRREG
LD D,EF_R3
LD A,(EF_VDAATTR) ; DOUBLE ATTRIBUTES FOR LOWER NIBBLE
LD E,A
CALL EF_WWRREG
POP DE
RET
#ENDIF
;
#IF (EF_SIZE = V40X24)
EF_KRF40:
PUSH DE
LD DE,EF_R0*256 + KRF
CALL EF_WWRREG
LD D,R3
LD A,(EF_VDACOLOR)
LD B,A
LD A,(EF_VDAATTR)
OR B
LD E,A ; COLOR
CALL EF_WRREG
LD D,EF_R2
LD A,(EF_VDATYPESET)
LD E,A
CALL EF_WRREG
POP DE
XOR A
RET
#ENDIF
;
;----------------------------------------------------------------------
; PROBE FOR EF9345 HARDWARE
;----------------------------------------------------------------------
;
; ON RETURN, ZF SET INDICATES HARDWARE FOUND
;
EF_PROBE:
LD DE,EF_R1*256+'a'
LD H,E
CALL EF_WRREG
CALL EF_RDREG
CP H
RET
;
;----------------------------------------------------------------------
; WAIT FOR VDU TO BE READY FOR A DATA READ/WRITE
;----------------------------------------------------------------------
;
EF_WAITRDY:
LD A,EF_R0
OUT (EF_SETREG),A
IN A,(EF_DATAACC)
RLA
JR C,EF_WAITRDY
RET
;
;----------------------------------------------------------------------
; UPDATE EF9345 REGISTERS
; EF_WRREG WRITES VALUE IN E TO EF9345 REGISTER SPECIFIED IN D
; EF_WWRREG AFTER WAITING FOR READY WRITES VALUE IN E TO EF9345 REGISTER SPECIFIED IN D
;------------------------------------------------------------------- --
;
EF_WWRREG:
CALL EF_WAITRDY
EF_WRREG:
LD A,D
OUT (EF_SETREG),A
LD A,E
OUT (EF_DATAACC),A
RET
;
;----------------------------------------------------------------------
; READ EF9345 REGISTERS
; EF_RDREG READS EF9345 REGISTER SPECIFIED IN D AND RETURNS VALUE IN A AND E
;----------------------------------------------------------------------
EF_RDREG:
CALL EF_WAITRDY
LD A,D
OUT (EF_SETREG),A
IN A,(EF_DATAACC)
LD E,A
RET
;
;----------------------------------------------------------------------
; READ INDIRECT EF9345 REGISTERS
; EF_READ_INDIR READS EF9345 REGISTER SPECIFIED IN D AND RETURNS VALUE IN A AND E
;----------------------------------------------------------------------
;
EF_READ_INDIR:
LD A,EF_IND
OR D
OR EF_RREG
LD E,A
LD D,EF_R0 + EF_EXEC
CALL EF_WWRREG
LD D,EF_R1
CALL EF_RDREG
RET
;
;----------------------------------------------------------------------
; WRITES INDIRECT EF9345 REGISTERS
; EF_LOAD_INDIR WRITES VALUE IN E TO INDIRECT EF9345 REGISTER SPECIFIED IN D
;----------------------------------------------------------------------
;
EF_LOAD_INDIR: ; D = TARGET REGISTER, E = VALUE TO WRITE
PUSH DE
LD D,EF_R1
CALL EF_WWRREG
POP DE
PUSH DE
LD A,EF_IND
OR D
LD E,A
LD D,EF_R0 + EF_EXEC
CALL EF_WWRREG
POP DE
RET
;
EF_LOAD_MODE: ; LOAD MODE
LD D,EF_TGSREG ; START INDIRECT REGISTER 1 : TGS
LD B,EF_INIT_CNT ; LOAD 5 INDIRECT REGISTERS
EF_MODEREG:
LD E,(HL)
CALL EF_LOAD_INDIR
INC HL
INC D
LD A,EF_INIT_CNT
CP D
JR NZ,EF_NOSKIP
INC D
INC D
LD E,(HL)
LD A,(EF_CON_BANKY)
ADD A,E
LD E,A
CALL EF_LOAD_INDIR
RET
EF_NOSKIP:
DJNZ EF_MODEREG
RET
;
EF_GETXY: ; D = ROW, E = COLUMNS
CALL EF_GETX
CALL EF_GETY
RET
;
EF_GETX: ; E = COLUMNS
CALL EF_WAITRDY
LD D,EF_XP
CALL EF_RDREG
#IF (EF_SIZE=V80X24)
RLCA ; CORRECTION 80 ROWS MODE
#ENDIF
LD E,A
RET
;
EF_GETY: ; D = ROW
CALL EF_WAITRDY
PUSH DE
LD D,EF_YP
CALL EF_RDREG
AND 00011111B
PUSH HL
LD HL,(EF_VDA_OFFSET)
SUB H
POP HL
SUB FIRSTLINE
POP DE
LD D,A
RET
;
EF_LOADFONTS:
PRTS("Not implemented$")
CALL NEWLINE
SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED (YET)
LD A,-2
OR A
RET
;
EF_NOTIMP:
PRTS("Not implemented$")
CALL NEWLINE
SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED (YET)
XOR A
OR -2 ; FUNCTION NOT IMPLEMENTED
RET
;
EF_CURSORON: ; CURSOR DISPLAY ENABLE
PUSH DE
PUSH AF
LD D,EF_MATREG ; LOAD CURSOR ENABLE
CALL EF_READ_INDIR
OR 01000000B
LD D,EF_MATREG ; SET CURPOS ENABLE
LD E,A
CALL EF_LOAD_INDIR
POP AF
POP DE
RET
;
EF_CURSOROFF:
PUSH DE
PUSH AF
LD D,EF_MATREG ; LOAD CURSOR ENABLE
CALL EF_READ_INDIR
AND 10111111B
LD D,EF_MATREG ; SET CURSOR ENABLE
LD E,A
CALL EF_LOAD_INDIR
POP AF
POP DE
RET
;
EF_INCCURSOR: ; CURSOR POSITION, D = ROW, E = COLUMN
; Y , X WITH MODULO DROWS
PUSH DE
PUSH HL
LD HL,(EF_VDA_OFFSET)
LD DE,(EF_VDA_POS)
ADD HL,DE
INC DE
LD A,EF_DROWS
CP E
JR NZ,EF_CURS0
LD E,0
INC D
LD A,EF_DLINES
CP D
JR NZ,EF_CURS0
; LD D,0
DEC D ; Y REMAINS INSIDE THE BOUNDARY
LD (EF_VDA_POS),DE
CALL EF_VDASCP
POP HL
POP DE
OR -6 ; PARAMETER OUT OF RANGE
RET
EF_CURS0:
LD (EF_VDA_POS),DE
CALL EF_VDASCP
POP HL
POP DE
RET
;
;----------------------------------------------------------------------
; DISPLAY CONTROLLER CHIP INITIALIZATION
;----------------------------------------------------------------------
;
EF_INIT9345:
#IF (EF_SIZE=V80X24) ; E)
EF_TGS: .DB 11000010b ; 80 char/row, long char code (12 bits) : TGS Register interlaced
EF_MAT: .DB EF_CSTY ; 01001000b ; cursor enabled, fixed complent cursor, margin color = black : MAT Register
EF_PAT: .DB 01111110b ; 80 char/row, long code, upper/lower bulk on, conceal on,
; I high during active disp. area, status row disebled : PAT Register
EF_DOR: .DB 10001111b ; DOR(3:0) = 1111 : color c0 = white, DOR(7:4) = 1000 : color c1 = black
EF_ROR: .DB 00001000b ; ROR(7:5) = 000 : displayed page memory starts from block 0
; ROR(4:0) = 01000 : origin row = 8
#ENDIF
;
#IF (EF_SIZE=V40X24)
EF_TGS: .DB 00000000B ; 40 char/row, long char code (24 bits) : TGS Register interlaced
EF_MAT: .DB EF_CSTY ; 01001100B cursor enabled, fixed complent cursor, margin color = black : MAT Register
EF_PAT: .DB 01111110B ; 40 char/row, long code, upper/lower bulk on, conceal on,
; I high during active disp. area, status row disebled : PAT Register
; DOR register initialization
;
; DOR(3:0) = 0011 : alpha UDS slices in block 3
; DOR(6:4) = 001 : semigraphic uds slices in block 2 and 3
; DOR 7 = 0 : Quadrichrome slices from block 0
EF_DOR: .DB 0 ;
EF_ROR: .DB 00001000B ; ROR(7:5) = 000 : displayed page memory starts from block 0
; ROR(4:0) = 01000 : origin row = 8
#ENDIF
EF_INIT_CNT: .EQU $ - EF_INIT9345
;
;======================================================================
; EF9345 DRIVER - VIDEO DISPLAY ADAPTER FUNCTIONS
;======================================================================
;
EF_FNTBL:
.DW EF_VDAINI
.DW EF_VDAQRY
.DW EF_VDARES
.DW EF_VDADEV
.DW EF_VDASCS
.DW EF_VDASCP
.DW EF_VDASAT
.DW EF_VDASCO
.DW EF_VDAWRC
.DW EF_VDAFIL
.DW EF_VDACPY
.DW EF_VDASCR
.DW EF_NOTIMP ; PPK_STAT
.DW EF_NOTIMP ; PPK_FLUSH
.DW EF_NOTIMP ; PPK_READ
.DW EF_VDARDC
#IF (($ - EF_FNTBL) != (VDA_FNCNT * 2))
.ECHO "*** INVALID VDU FUNCTION TABLE ***\n"
#ENDIF
;
EF_VDAINI:
; VIDEO INITIALIZE
; FULL REINITIALIZATION, CLEAR SCREEN, CURRENTLY IGNORES VIDEO MODE AND BITMAP DATA
PUSH HL
CALL EF_INIT1
POP HL
LD A,L
OR H
CALL NZ,EF_LOADFONTS
CALL EF_CLEARALL
CALL EF_LOADCSTYLE
LD DE,0
LD (EF_VDA_OFFSET),DE
CALL EF_VDASCP
XOR A
RET
;
EF_VDAQRY:
; VIDEO QUERY
; ENTRY: C = VIDEO UNIT, HL = FONT BITMAT
; RETURN: C = VIDEO MODE, D = ROWS, E = COLUMNS, HL = FONT BITMAT
LD C,$00 ; MODE ZERO IS ALL WE KNOW
LD D,EF_DLINES
LD E,EF_DROWS
LD HL,0 ; EXTRACTION OF CURRENT BITMAP DATA NOT SUPPORTED
XOR A ; SIGNAL SUCCESS
RET
;
EF_VDARES:
; VIDEO RESET
; SOFT RESET
;
XOR A
RET
;
EF_VDADEV:
; VIDEO DEVICE
; ENTRY: C = VIDEO UNIT
; RETURN: D := DEVICE TYPE, E := DEVICE NUMBER, H := DEVICE UNIT MODE, L := DEVICE I/O BASE ADDRESS
LD DE,(VDADEV_EF * 256) + 0 ; D := DEVICE TYPE
; E := PHYSICAL UNIT IS ALWAYS ZERO
LD HL,EF_BASE ; H INDICATES THE VARIANT OF THE CHIP OR CIRCUIT, H = 0 : NO VARIANTS
; L := BASE I/O ADDRESS
XOR A ; SIGNAL SUCCESS
RET
;
EF_VDASCS:
; VIDEO SET CURSOR STYLE
; ENTRY: C = VIDEO UNIT, D = START/END, E = STYLE : E0 = BLINK/FLASH, E1 = UNDELINE, E2 = REVERSE/COMPLEMENT
; MAT5 = 1 : FLASH, MAT4 = 0 : COMPLEMENT
; RETURN A = STATUS
XOR A
SRA E
JR NC,EF_VDASCS0
OR EF_BLINK ; CURSOR IS BLINKING
EF_VDASCS0:
SRA E
JR NC,EF_VDASCS1
OR EF_ULIN ; UNDERLINED CURSOR
JR EF_VDASCS2
EF_VDASCS1:
SRA E
JR NC,EF_VDASCS2
AND EF_COMPL
EF_VDASCS2:
LD (EF_VDACATTR),A
CALL EF_LOADCSTYLE
XOR A
RET
;
EF_VDASCP:
; SET VIDEO CURSOR POSITION
; ENTRY: C = VIDEO UNIT, D = ROW, E = COLUMN
; RETURN A = STATUS
; CHECKING THE FEASIBILITY OF THE INPUT VALUES
LD A,EF_DLINES-1
CP D
JR C,EF_VDASCP0
LD A,EF_DROWS-1
CP E
JR C,EF_VDASCP0
LD (EF_VDA_POS),DE ; D = ROW, E = COLUMNS
;
PUSH DE
#IF (EF_SIZE=V80X24)
RRC E ; ADJUST TO 80 COLUMN LAYOUT
#ENDIF
LD D,EF_XP ; X POSITION
CALL EF_WWRREG
POP DE
;
PUSH HL
LD HL,(EF_VDA_OFFSET)
LD A,H
POP HL
;
ADD A,FIRSTLINE
ADD A,D
CP FIRSTLINE+EF_DLINES
JR C,EF_SETYP0
SUB EF_DLINES
EF_SETYP0:
LD E,A
LD A,(EF_CON_BANKY) ; STAY IN DISTRICT
OR E
LD E,A
LD D,EF_YP
CALL EF_WWRREG
XOR A
RET
EF_VDASCP0:
XOR A
OR -6 ; PARAMETERS OUT OF RANGE $FF
RET
;
EF_VDASAT:
; VIDEO SET CHARACTER ATTRIBUTE FOR SCROLL, KRL, ETC.
; ENTRY: C = VIDEO UNIT, E = ATTRIBUTE
; 80 CHARACTER/ROW STYLE := E0 = BLINK, E1 = UNDELINE, E2 = REVERSE, E3 = COLOR SELECT
; 40 CHARACTER/ROW STYLE := E0 = BLINK, E1 = UNDELINE, E2 = REVERSE, E3 = COLOR SELECT, E4..E7 = TYPE AND SET
; B(0) := INSERT
; B(1) := DOUBLE HIGHT
; B(2) := concealed character appears as a space on the screen
; B(3) := DOUBLE WIDTH
; B(4..7) := TYPE AND SET
; RETURN A = STATUS
#IF (EF_SIZE=V80X24)
XOR A
SRA E ; IS BLINKING
JR NC,EF_VDASAT0
OR EF_FLASH
EF_VDASAT0:
SRA E
JR NC,EF_VDASAT1
OR EF_UNDERLINE ; UNDERLINED CURSOR
EF_VDASAT1:
SRA E
JR NC,EF_VDASAT
OR EF_NEGATIVE ; NEGATIVE CURSOR
EF_VDASAT2:
SRA E
JR NC,EF_VDASAT3
OR EF_COLORSET
EF_VDASAT3:
#ENDIF
#IF (EF_SIZE=V40X24)
; set VDATYPESET
LD A,E
AND $F0
LD (EF_VDATYPESET),A
XOR A
SRA E ; IS BLINKING
JR NC,EF_VDASAT0
OR EF_FLASHCHAR
EF_VDASAT0:
SRA E
SRA E
JR NC,EF_VDASAT1
OR EF_REVERSCHAR
EF_VDASAT1:
#ENDIF
LD (EF_VDAATTR),A
XOR A
RET
;
EF_LOADCSTYLE:
LD A,(EF_VDACATTR)
LD B,A
LD D,EF_MATREG
CALL EF_READ_INDIR
AND 11001111B
OR B
LD E,A
LD D,EF_MATREG
CALL EF_LOAD_INDIR
RET
;
EF_VDASCO:
; VIDEO SET CHARACTER COLOR
; ENTRY C = VIDEO UNIT, E = COLOR
; RETURN A = STATUS
CALL EF_WAITRDY
#IF (EF_SIZE=V80X24) ; COLOR SETUP USE MARGIN COLOR IN MAT AND
LD A,E
LD B,A ; B = BG
SRL B
SRL B
SRL B
SRL B
AND $F8 ; MASK BG COLOR
LD A,E
AND $07 ; MASK FG COLOR
LD C,A ; C = FG
LD D,EF_DORREG ; LOAD FG COLOR FROM DOR(3..0)
CALL EF_READ_INDIR
AND $F8
OR C ; SET NEW FG COLOR
LD E,A
LD D,EF_DORREG ; LOAD NEW FG COLOR
CALL EF_LOAD_INDIR
;
LD D,EF_MATREG ; LOAD BG COLOR
CALL EF_READ_INDIR
AND $F8 ; MASK BG COLOR
OR B ; SET NEW BG COLOR
LD E,A
LD D,EF_MATREG ; LOAD NEW BG COLOR
CALL EF_LOAD_INDIR
#ENDIF
#IF (EF_SIZE=V40X24)
LD HL,EF_VDACOLOR
LD A,E
AND $7 ; MASK FG COLOR
RLD
LD A,E
SRL A ; BG COLOR TO LOW ORDER FOUR BITS
SRL A
SRL A
SRL A
RLD
#ENDIF
XOR A
RET
;
EF_VDAWRC:
; VIDEO WRITE CHARACTER,
; ENTRY C = VIDEO UNIT, E = CHARACTER
; RETURN A = STATUS
#IF (EF_SIZE=V80X24)
CALL EF_KRL80
LD D,EF_R1+EF_EXEC
CALL EF_WWRREG
#ENDIF
#IF (EF_SIZE=V40X24)
CALL EF_KRF40
LD D,EF_R1+EF_EXEC
CALL EF_WWRREG
#ENDIF
CALL EF_INCCURSOR
XOR A
RET
;
EF_VDAFIL:
; VIDEO FILL
; ENTRY: C = VIDEO UNIT, E = CHARACTER, HL = COUNT OF CHARACTERS
; RETURN A = STATUS
CALL EF_CURSOROFF
EF_VDAFIL0:
CALL EF_VDAWRC
DEC HL
LD A,H
OR L
JR NZ,EF_VDAFIL0
CALL EF_CURSORON
XOR A
RET
;
EF_VDACPY:
; VIDEO COPY
; ENTRY C = VIDEO UNIT, D = SOURCE ROW, E = SOURCE COLUMN, L = COUNT
; RETURN A = STATUS
PUSH DE ; SAVE SOURCE
LD A,L
LD (EF_CPYCNT),A
CALL EF_CURSOROFF
CALL EF_GETXY ; GET AND SAVE CURRENT CURSOR POSITION
LD (EF_CURPOS),DE
; CHECK END OF SCREEN
LD H,D ; D = CURRENT LINE
LD E,EF_DROWS ; CHARACTERS IN ROW
CALL MULT8 ; LINES * DROWS
POP DE
PUSH DE
LD D,0
ADD HL,DE ; ADD CHARACTERS IN CURRENT LINE := USED CHARACTERS
EX DE,HL
LD HL,EF_DLINES*EF_DROWS ; AVAILABLE CHARACTER COUNT
XOR A
SBC HL,DE ; REMAINING CHARACTERS = AVAILABLE - USED
LD C,L ; SAVE REMAINING CHARACTER COUNT
LD A,(EF_CPYCNT)
LD B,A
LD E,A
LD D,0
SBC HL,DE ; COMPARE COPY COUNT WITH AVAILABLE
JR NC,EF_CPY0
LD B,C ; ADJUST COPY COUNT
EF_CPY0:
POP DE
CALL EF_VDASCP ; SET SOURCE AS CURSOR
LD HL,EF_BUF
PUSH BC
EF_CPYRD:
#IF (EF_SIZE=V80X24)
PUSH BC
CALL EF_VDARDC
POP BC
LD (HL),E
INC HL
#ENDIF
#IF (EF_SIZE=V40X24)
PUSH HL
PUSH BC
CALL EF_VDARDC
LD A,L
POP BC
POP HL
LD (HL),E
INC HL
LD (HL),A
INC HL
#ENDIF
CALL EF_INCCURSOR
DJNZ EF_CPYRD
LD DE,(EF_CURPOS) ; RECOVER AND SET CURSOR POSITION
CALL EF_VDASCP
POP BC
LD HL,EF_BUF
EF_CPYWR:
#IF (EF_SIZE=V80X24)
PUSH BC
LD E,(HL)
CALL EF_VDAWRC
INC HL
POP BC
DJNZ EF_CPYWR
#ENDIF
#IF (EF_SIZE=V40X24)
PUSH BC
LD E,(HL)
INC HL
PUSH HL
LD L,(HL)
CALL EF_VDAWRC
POP HL
INC HL
POP BC
DJNZ EF_CPYWR
#ENDIF
; RESTORE CURSOR
LD DE,(EF_CURPOS)
CALL EF_VDASCP
CALL EF_CURSORON
XOR A
RET
;
EF_VDASCR:
; VIDEO SCROLL
; ENTRY: C = VIDEO UNIT, E = LINES
; RETURN A = STATUS
CALL EF_CURSOROFF
EF_VDASCR0:
LD A,E
OR A
JR Z,EF_VDASCR2 ; SCROLL 0, NOTHING TO DO
PUSH DE
RLCA
JR C,EF_VDASCR1
CALL EF_SCRUP
POP DE
DEC E
JR EF_VDASCR0
EF_VDASCR1:
CALL EF_SCRDOWN
POP DE
INC E
JP EF_VDASCR0
EF_VDASCR2:
CALL EF_CURSORON
RET
;
EF_SCRUP:
LD HL,(EF_VDA_OFFSET)
LD DE,$0100 ; inc y
ADD HL,DE
LD A,H
CP EF_DLINES
JR NZ,EF_SCRUP0
LD HL,0
EF_SCRUP0:
LD (EF_VDA_OFFSET),HL
LD A,(EF_CON_BANKY)
ADD A,H
ADD A,FIRSTLINE
LD E,A
LD D,EF_RORREG
CALL EF_LOAD_INDIR
; fill exposed line
LD HL,(EF_VDA_POS)
PUSH HL
LD HL,(EF_DLINES-1)*256
EX DE,HL
EF_SCRCLEAR:
CALL EF_VDASCP
LD E,' '
LD HL,EF_DROWS
CALL EF_VDAFIL
;
POP HL
EX DE,HL
CALL EF_VDASCP
RET
;
EF_SCRDOWN:
XOR A
LD HL,(EF_VDA_OFFSET)
LD DE,$FF00
ADD HL,DE
LD A,$FF
CP H
JR NZ,EF_SCRDOWN0
LD H,EF_DLINES-1
EF_SCRDOWN0:
LD (EF_VDA_OFFSET),HL
LD A,(EF_CON_BANKY)
ADD A,FIRSTLINE
ADD A,H
LD E,A
LD D,EF_RORREG
CALL EF_LOAD_INDIR
; fill exposed line
LD HL,(EF_VDA_POS)
PUSH HL
LD DE,0
; JR EF_SCRCLEAR
CALL EF_VDASCP
LD E,' '
LD HL,EF_DROWS
CALL EF_VDAFIL
;
POP HL
EX DE,HL
CALL EF_VDASCP
RET
;
EF_VDARDC:
; READ CHARACTER AT CURRENT VIDEO POSITION
; ENTRY: C = VIDEO UNIT
; RETURN: A = STATUS, E = CHARACTER, B = CHARACTER COLOR, C = CHARACTER ATTRIBUTES, L = CHARACTER TYPESET, 40X24 ONLY
#IF (EF_SIZE = V80X24)
LD D,EF_R0
LD A,EF_KRL ; R0 KRL COMMAND NO AUTOINC
OR EF_RREG
LD E,A
CALL EF_WWRREG
LD D,EF_R3 + EF_EXEC ; READ ATTRIBUTES
CALL EF_RDREG
LD C,A
CALL EF_WAITRDY
LD D,EF_R1+EF_EXEC
CALL EF_RDREG
PUSH DE
; READ COLOR
LD D,EF_DORREG ; LOAD FG COLOR
CALL EF_READ_INDIR
AND $07
LD B,A
LD D,EF_MATREG ; LOAD BG COLOR
CALL EF_READ_INDIR
RLCA
RLCA
RLCA
RLCA
AND $70
OR B
LD B,A
POP DE
XOR A
; LD L,A
RET
#ENDIF
#IF (EF_SIZE = V40X24)
LD D,R0
LD A,KRF ; R0 KRL COMMAND NO AUTOINC
OR EF_RREG
LD E,A
CALL EF_WWRREG
LD D,EF_R3 + EF_EXEC ; READ CHARACTER ATTRIBUTES
CALL EF_RDREG
AND $77
LD B,A
RLC B
RLC B
RLC B
RLC B
LD A,E
AND $88
LD C,A
LD D,EF_R2 + EF_EXEC ; READ CHARACTER TYPESET
CALL EF_RDREG
LD L,A
LD D,EF_R1+EF_EXEC ; READ CHARACTER
CALL EF_RDREG
XOR A
RET
#ENDIF
;
EF_IDAT:
.DB KBDMODE_NONE ; PS/2 8242 KEYBOARD CONTROLLER
.DB 0
.DB 0
;
EF_VDA_POS .DW 0
EF_CURPOS .DW 0
EF_CPYCNT .DB 0
EF_VDA_OFFSET .DW 0
EF_CON_BANKY .DB 0
EF_VDAATTR .DB 0 ; CHARACTER ATTRIBUTES
EF_VDACATTR .DB 0 ; CURSOR ATTRIBUTES
EF_VDACOLOR .DB 0 ; CHARACTER COLOR
#IF (EF_SIZE = V40X24)
EF_VDATYPESET .DB 0 ; 40 CHAR/ROW PARAMETER
#ENDIF
EF_BUF:
#IF (EF_SIZE = V80X24)
.FILL EF_DLINES*EF_DROWS ;256,0 ; COPY BUFFER
#ENDIF
#IF (EF_SIZE = V40X24)
.FILL 2*EF_DLINES*EF_DROWS ;512,0
#ENDIF