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.
1055 lines
33 KiB
1055 lines
33 KiB
;__CVDUTEST________________________________________________________________________________________
|
|
;
|
|
; CVDUTEST COLOR VDU TEST
|
|
;
|
|
; WRITTEN BY: DAN WERNER -- 11/4/2011
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
|
|
; DATA CONSTANTS
|
|
;__________________________________________________________________________________________________
|
|
;IDE REGISTER IO PORT ; FUNCTION
|
|
M8563Status .EQU $E4
|
|
M8563Register .EQU $E4
|
|
M8563Data .EQU $E5
|
|
|
|
I8242Status .EQU $E3
|
|
I8242Command .EQU $E3
|
|
I8242Data .EQU $E2
|
|
|
|
|
|
.ORG $0100
|
|
;__________________________________________________________________________________________________
|
|
; MAIN PROGRAM BEGINS HERE
|
|
;__________________________________________________________________________________________________
|
|
INITVDU:
|
|
CALL VDU_INIT ; INIT VDU
|
|
; CALL KB_INITIALIZE ; INIT KB
|
|
|
|
CALL DSPMATRIX ; DISPLAY INIT MATRIX SCREEN
|
|
; CALL WAIT_KBHIT ; WAIT FOR A KEYSTROKE
|
|
|
|
LOOP1:
|
|
; CALL GET_KEY
|
|
LD A,27 ; SIMULATE KEYSTROKE TO END PROGRAM
|
|
|
|
LD C,14
|
|
CP 13
|
|
JP Z,LOOP2
|
|
CP 27
|
|
JP Z,LOOP3
|
|
CP '6'
|
|
JP Z,LOOP4
|
|
CALL VDU_PutChar ; DUMP CHAR TO DISPLAY
|
|
JP LOOP1
|
|
LOOP2:
|
|
LD A,0 ; YES, WRAP TO NEXT LINE
|
|
LD (TERM_X),A ; STORE X
|
|
LD A,(TERM_Y) ; A= Y COORD
|
|
INC A ; INC Y COORD
|
|
LD (TERM_Y),A ; STORE Y
|
|
CALL GOTO_XY ; YES, HANDLE SCROLLING
|
|
JP LOOP1
|
|
LOOP3:
|
|
LD C,00H ; CP/M SYSTEM RESET CALL
|
|
CALL 0005H ; RETURN TO PROMPT
|
|
RET
|
|
LOOP4:
|
|
CALL REVERSE_SCROLL
|
|
JP LOOP1
|
|
|
|
|
|
;__DO_SCROLL_______________________________________________________________________________________
|
|
;
|
|
; SCROLL THE SCREEN UP ONE LINE
|
|
;__________________________________________________________________________________________________
|
|
DO_SCROLL:
|
|
PUSH AF ; STORE AF
|
|
DO_SCROLLE1:
|
|
PUSH HL ; STORE HL
|
|
PUSH BC ; STORE BC
|
|
|
|
LD B, 24 ; GET REGISTER 24
|
|
CALL VDU_GREG ;
|
|
OR 80H ; TURN ON COPY BIT
|
|
LD D,A ; PARK IT
|
|
|
|
LD HL, (VDU_DISPLAY_START) ; GET UP START OF DISPLAY
|
|
LD E,23 ;
|
|
DO_SCROLL1:
|
|
LD B, 18 ; SET UPDATE(DEST) POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE(DEST) POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD BC,0050H ;
|
|
ADD HL,BC ;
|
|
LD B, 32 ; SET SOURCE POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 33 ; SET SOURCE POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B, 24 ; SET COPY
|
|
LD A,D ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B, 30 ; SET AMOUNT TO COPY
|
|
LD A,050H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
DEC A
|
|
LD A,E ;
|
|
CP 00H ;
|
|
JP NZ,DO_SCROLL1 ; LOOP TILL DONE
|
|
|
|
LD HL, (VDU_DISPLAY_START) ; GET UP START OF DISPLAY
|
|
LD BC,0820H ;
|
|
ADD HL,BC ;
|
|
LD E,23
|
|
DO_SCROLL2:
|
|
LD B, 18 ; SET UPDATE(DEST) POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE(DEST) POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD BC,0050H ;
|
|
ADD HL,BC ;
|
|
LD B, 32 ; SET SOURCE POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 33 ; SET SOURCE POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B, 24 ; SET COPY
|
|
LD A,D ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B, 30 ; SET AMOUNT TO COPY
|
|
LD A,050H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
DEC E
|
|
LD A,E ;
|
|
CP 00H ;
|
|
JP NZ,DO_SCROLL2 ; LOOP TILL DONE
|
|
|
|
|
|
LD A,23 ; SET CURSOR TO BEGINNING OF LAST LINE
|
|
LD (TERM_Y),A ;
|
|
LD A,(TERM_X) ;
|
|
PUSH AF ; STORE X COORD
|
|
LD A,0 ;
|
|
LD (TERM_X),A ;
|
|
CALL GOTO_XY ; SET CURSOR POSITION TO BEGINNING OF LINE
|
|
POP AF ; RESTORE X COORD
|
|
POP BC ; RESTORE BC
|
|
CALL PERF_ERASE_EOL ; ERASE SCROLLED LINE
|
|
LD (TERM_X),A ;
|
|
CALL GOTO_XY ; SET CURSOR POSITION
|
|
POP HL ; RESTORE HL
|
|
POP AF ; RESTORE AF
|
|
RET ;
|
|
|
|
;__REVERSE_SCROLL__________________________________________________________________________________
|
|
;
|
|
; SCROLL THE SCREEN DOWN ONE LINE
|
|
;__________________________________________________________________________________________________
|
|
REVERSE_SCROLL:
|
|
PUSH AF ; STORE AF
|
|
PUSH HL ; STORE HL
|
|
PUSH BC ; STORE BC
|
|
|
|
LD B, 24 ; GET REGISTER 24
|
|
CALL VDU_GREG ;
|
|
OR 80H ; TURN ON COPY BIT
|
|
LD E,A ; PARK IT
|
|
|
|
LD HL, (VDU_DISPLAY_START) ; GET UP START OF DISPLAY
|
|
LD BC,0730H ;
|
|
ADD HL,BC
|
|
LD D,23 ;
|
|
REVERSE_SCROLL1:
|
|
LD B, 18 ; SET UPDATE(DEST) POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE(DEST) POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD BC,0FFB0H ;
|
|
ADD HL,BC ;
|
|
LD B, 32 ; SET SOURCE POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 33 ; SET SOURCE POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B, 24 ; SET COPY
|
|
LD A,E ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B, 30 ; SET AMOUNT TO COPY
|
|
LD A,050H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
DEC D
|
|
LD A,D ;
|
|
CP 00H ;
|
|
JP NZ,REVERSE_SCROLL1 ; LOOP TILL DONE
|
|
|
|
|
|
LD HL, (VDU_DISPLAY_START) ; GET UP START OF DISPLAY
|
|
LD BC,0F50H ;
|
|
ADD HL,BC
|
|
LD D,23 ;
|
|
REVERSE_SCROLL2:
|
|
LD B, 18 ; SET UPDATE(DEST) POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE(DEST) POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD BC,0FFB0H ;
|
|
ADD HL,BC ;
|
|
LD B, 32 ; SET SOURCE POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 33 ; SET SOURCE POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B, 24 ; SET COPY
|
|
LD A,E ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B, 30 ; SET AMOUNT TO COPY
|
|
LD A,050H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
DEC D
|
|
LD A,D ;
|
|
CP 00H ;
|
|
JP NZ,REVERSE_SCROLL2 ; LOOP TILL DONE
|
|
LD A,0 ; SET CURSOR TO BEGINNING OF FIRST LINE
|
|
LD (TERM_Y),A ;
|
|
LD A,(TERM_X) ;
|
|
PUSH AF ; STORE X COORD
|
|
LD A,0 ;
|
|
LD (TERM_X),A ;
|
|
CALL GOTO_XY ; SET CURSOR POSITION TO BEGINNING OF LINE
|
|
POP AF ; RESTORE AF
|
|
POP BC ; RESTORE BC
|
|
CALL PERF_ERASE_EOL ; ERASE SCROLLED LINE
|
|
LD (TERM_X),A ;
|
|
CALL GOTO_XY ; SET CURSOR POSITION
|
|
POP HL ; RESTORE HL
|
|
POP AF ; RESTORE AF
|
|
RET ;
|
|
|
|
;__VDU_INIT_________________________________________________________________________________________
|
|
;
|
|
; INITIALIZE VDU
|
|
;__________________________________________________________________________________________________
|
|
VDU_INIT:
|
|
PUSH AF ; STORE AF
|
|
PUSH DE ; STORE DE
|
|
PUSH HL ; STORE HL
|
|
PUSH BC ; STORE BC
|
|
|
|
CALL VDU_CRTInit ; INIT 8563 VDU CHIP
|
|
CALL VDU_LOADFONT ;
|
|
CALL PERF_CURSOR_HOME ; CURSOR HOME
|
|
LD C,14 ;
|
|
CALL PERF_ERASE_EOS ; CLEAR SCREEN
|
|
CALL VDU_CursorOn ; TURN ON CURSOR
|
|
|
|
POP BC ;
|
|
POP HL ;
|
|
POP DE ;
|
|
POP AF ;
|
|
|
|
RET
|
|
|
|
;__PERF_CURSOR_HOME________________________________________________________________________________
|
|
;
|
|
; PERFORM CURSOR HOME
|
|
;__________________________________________________________________________________________________
|
|
PERF_CURSOR_HOME:
|
|
LD A,0 ; LOAD 0 INTO A
|
|
LD (TERM_X),A ; SET X COORD
|
|
LD (TERM_Y),A ; SET Y COORD
|
|
JP GOTO_XY ; MOVE CURSOR TO POSITION
|
|
|
|
;__PERF_ERASE_EOS__________________________________________________________________________________
|
|
;
|
|
; PERFORM ERASE FROM CURSOR POS TO END OF SCREEN
|
|
; C= DEFAULT COLOR
|
|
;__________________________________________________________________________________________________
|
|
PERF_ERASE_EOS:
|
|
PUSH HL
|
|
PUSH AF
|
|
PUSH BC
|
|
|
|
LD HL, (VDU_DisplayPos) ; GET CURRENT DISPLAY ADDRESS
|
|
LD B, 18 ; SET UPDATE CSR POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE CSR POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
CALL GOTO_XY ; MOVE CURSOR
|
|
LD DE,0820H ; SET SCREEN SIZE INTO HL
|
|
PERF_ERASE_EOS_LOOP:
|
|
LD A, ' ' ; MOVE SPACE CHARACTER INTO A
|
|
LD B,31 ;
|
|
CALL VDU_WREG ; WRITE IT TO SCREEN, VDU WILL AUTO INC TO NEXT ADDRESS
|
|
DEC DE ; DEC COUNTER
|
|
LD A,D ; IS COUNTER 0 YET?
|
|
OR E ;
|
|
JP NZ,PERF_ERASE_EOS_LOOP ; NO, LOOP
|
|
LD DE,0820H ; SET SCREEN SIZE INTO HL
|
|
PERF_ERASE_EOS_CLOOP:
|
|
LD A, C ; MOVE COLOR INTO A
|
|
LD B,31 ;
|
|
CALL VDU_WREG ; WRITE IT TO SCREEN, VDU WILL AUTO INC TO NEXT ADDRESS
|
|
DEC DE ; DEC COUNTER
|
|
LD A,D ; IS COUNTER 0 YET?
|
|
OR E ;
|
|
JP NZ,PERF_ERASE_EOS_CLOOP ; NO, LOOP
|
|
|
|
CALL GOTO_XY ; YES, MOVE CURSOR BACK TO ORIGINAL POSITION
|
|
POP BC
|
|
POP AF
|
|
POP HL
|
|
RET
|
|
|
|
;__PERF_ERASE_EOL__________________________________________________________________________________
|
|
;
|
|
; PERFORM ERASE FROM CURSOR POS TO END OF LINE
|
|
; C=DEFAULT COLOR
|
|
;__________________________________________________________________________________________________
|
|
PERF_ERASE_EOL:
|
|
PUSH HL
|
|
PUSH AF
|
|
PUSH BC
|
|
|
|
LD A,(TERM_X) ; GET CURRENT CURSOR X COORD
|
|
LD D,A ; STORE IT IN C
|
|
LD A,80 ; MOVE CURRENT LINE WIDTH INTO A
|
|
SUB D ; GET REMAINING POSITIONS ON CURRENT LINE
|
|
LD B,A ; MOVE IT INTO B
|
|
PERF_ERASE_EOL_LOOP:
|
|
LD A, ' ' ; MOVE SPACE CHARACTER INTO A
|
|
CALL VDU_PutCharRAW ;
|
|
DJNZ PERF_ERASE_EOL_LOOP ; LOOP UNTIL DONE
|
|
CALL GOTO_XY ; MOVE CURSOR BACK TO ORIGINAL POSITION
|
|
POP BC
|
|
POP AF
|
|
POP HL
|
|
RET
|
|
|
|
;__DSPMATRIX_______________________________________________________________________________________
|
|
;
|
|
; DISPLAY INTRO SCREEN
|
|
;__________________________________________________________________________________________________
|
|
DSPMATRIX:
|
|
CALL PERF_CURSOR_HOME ; RESET CURSOR TO HOME POSITION
|
|
LD HL,TESTMATRIX ; SET HL TO SCREEN IMAGE
|
|
LD DE, 1919 ; SET IMAGE SIZE
|
|
; LD C,00000011B ; SET COLOR
|
|
LD C,00001111B ; SET COLOR
|
|
DSPMATRIX_LOOP:
|
|
LD A,(HL) ; GET NEXT CHAR FROM IMAGE
|
|
call VDU_PutChar ; DUMP CHAR TO DISPLAY
|
|
INC HL ; INC POINTER
|
|
DEC DE ; DEC COUNTER
|
|
LD A,D ; IS COUNTER ZERO?
|
|
OR E ;
|
|
JP NZ,DSPMATRIX_LOOP ; NO, LOOP
|
|
CALL PERF_CURSOR_HOME ; YES, RESET CURSOR TO HOME POSITION
|
|
RET
|
|
|
|
TESTMATRIX:
|
|
.TEXT "0 1 2 3 4 5 6 7 "
|
|
.TEXT "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
|
|
.TEXT "2 "
|
|
.TEXT "3 "
|
|
.TEXT "4 ===================================================== "
|
|
.TEXT "5 "
|
|
.TEXT "6 **** * * **** * * **** * * "
|
|
.TEXT "7 * * * * * * * * * * * * "
|
|
.TEXT "8 * * * * * * * * * ** "
|
|
.TEXT "9 * * * * * * * * * ** "
|
|
.TEXT "10 * * * * * * * * * * * * "
|
|
.TEXT "11 **** * **** **** **** * * "
|
|
.TEXT "12 "
|
|
.TEXT "13 ===================================================== "
|
|
.TEXT "14 "
|
|
.TEXT "15 VDU TEST V0.1 VT-52 EMULATION "
|
|
.TEXT "16 "
|
|
.TEXT "17 ** PRESS ANY KEY TO ENTER TERMINAL MODE ** "
|
|
.TEXT "18 "
|
|
.TEXT "19 "
|
|
.TEXT "21 "
|
|
.TEXT "22 "
|
|
.TEXT "23 "
|
|
.TEXT "24 "
|
|
|
|
|
|
;__VDU_WREG________________________________________________________________________________________
|
|
;
|
|
; WRITE VALUE IN A TO REGISTER IN B
|
|
; B: REGISTER TO UPDATE
|
|
; A: VALUE TO WRITE
|
|
;__________________________________________________________________________________________________
|
|
VDU_WREG:
|
|
PUSH AF ; STORE AF
|
|
VDU_WREG_1:
|
|
IN A,(M8563Status) ; read address/status register
|
|
BIT 7,A ; if bit 7 = 1 than an update strobe has been occured
|
|
JR Z,VDU_WREG_1 ; wait for ready
|
|
LD A,B ;
|
|
OUT (M8563Register),A ; select register
|
|
VDU_WREG_2:
|
|
IN A,(M8563Status) ; read address/status register
|
|
BIT 7,A ; if bit 7 = 1 than an update strobe has been occured
|
|
JR Z,VDU_WREG_2 ; wait for ready
|
|
POP AF ;
|
|
OUT (M8563Data),A ; PUT DATA
|
|
RET
|
|
|
|
|
|
;__VDU_GREG________________________________________________________________________________________
|
|
;
|
|
; GET VALUE FROM REGISTER IN B PLACE IN A
|
|
; B: REGISTER TO GET
|
|
; A: VALUE
|
|
;__________________________________________________________________________________________________
|
|
VDU_GREG:
|
|
IN A,(M8563Status) ; read address/status register
|
|
BIT 7,A ; if bit 7 = 1 than an update strobe has been occured
|
|
JR Z,VDU_GREG ; wait for ready
|
|
LD A,B ;
|
|
OUT (M8563Register) , A ; select register
|
|
VDU_GREG_1:
|
|
IN A,(M8563Status) ; read address/status register
|
|
BIT 7,A ; if bit 7 = 1 than an update strobe has been occured
|
|
JR Z,VDU_GREG_1 ; wait for ready
|
|
IN A,(M8563Data) ; GET DATA
|
|
RET
|
|
|
|
|
|
|
|
VDU_Init8563:
|
|
.DB 126,80,102,73,32,224,25,29,252,231,160,231,0,0,7,128
|
|
.DB 18,23,15,208,8,32,120,232,32,71,240,0,47,231,79,7,15,208,125,100,245
|
|
|
|
;__VDU_CRTInit_____________________________________________________________________________________
|
|
;
|
|
; INIT VDU CHIP
|
|
;__________________________________________________________________________________________________
|
|
VDU_CRTInit:
|
|
PUSH AF ; STORE AF
|
|
PUSH BC ; STORE BC
|
|
PUSH HL ; STORE HL
|
|
|
|
LD B,$00 ; B = 0
|
|
LD HL,VDU_Init8563 ; HL = pointer to the default values
|
|
XOR A ; A = 0
|
|
VDU_CRTInitLoop:
|
|
LD A,(HL) ; GET VALUE
|
|
CALL VDU_WREG ; WRITE IT
|
|
INC HL
|
|
INC B ;
|
|
LD A,B ;
|
|
CP 37 ;
|
|
JR NZ,VDU_CRTInitLoop ; LOOP UNTIL DONE
|
|
POP HL ; RESTORE HL
|
|
POP BC ; RESTORE BC
|
|
POP AF ; RESTORE AF
|
|
RET
|
|
|
|
|
|
;__VDU_CursorOn____________________________________________________________________________________
|
|
;
|
|
; TURN ON CURSOR
|
|
;__________________________________________________________________________________________________
|
|
VDU_CursorOn:
|
|
PUSH AF ; STORE AF
|
|
LD A, $60 ; SET CURSOR VALUE
|
|
JP VDU_CursorSet ;
|
|
|
|
;__VDU_CursorOff___________________________________________________________________________________
|
|
;
|
|
; TURN OFF CURSOR
|
|
;__________________________________________________________________________________________________
|
|
VDU_CursorOff:
|
|
PUSH AF ; STORE AF
|
|
LD A, $20 ; SET CURSOR VALUE
|
|
VDU_CursorSet:
|
|
PUSH BC ; STORE BC
|
|
LD B,10
|
|
CALL VDU_WREG ; WRITE IT
|
|
POP BC ; RESTORE BC
|
|
POP AF ; RESTORE AF
|
|
RET
|
|
|
|
;__GOTO_XY_________________________________________________________________________________________
|
|
;
|
|
; MOVE CURSOR TO POSITON IN TERM_X AND TERM_Y
|
|
;__________________________________________________________________________________________________
|
|
GOTO_XY:
|
|
PUSH AF ; STORE AF
|
|
|
|
LD A,(TERM_Y) ; PLACE Y COORD IN A
|
|
CP 24 ; IS 24?
|
|
JP Z,DO_SCROLLE1 ; YES, MUST SCROLL
|
|
|
|
PUSH BC ; STORE BC
|
|
PUSH DE ; STORE DE
|
|
LD A,(TERM_X) ;
|
|
LD H,A ;
|
|
LD A,(TERM_Y) ;
|
|
LD L,A ;
|
|
PUSH HL ; STORE HL
|
|
LD B, A ; B = Y COORD
|
|
LD DE, 80 ; MOVE LINE LENGTH INTO DE
|
|
LD HL, 0 ; MOVE 0 INTO HL
|
|
LD A, B ; A=B
|
|
CP 0 ; Y=0?
|
|
JP Z, VDU_YLoopEnd ; THEN DO NOT MULTIPLY BY 80
|
|
VDU_YLoop: ; HL = 80 * Y
|
|
ADD HL, DE ; HL=HL+DE
|
|
DJNZ VDU_YLoop ; LOOP
|
|
VDU_YLoopEnd: ;
|
|
POP DE ; DE = org HL
|
|
LD E, D ; E = X
|
|
LD D, 0 ; D = 0
|
|
ADD HL, DE ; HL = HL + X
|
|
LD (VDU_DisplayPos), HL ;
|
|
PUSH HL ;
|
|
POP DE ;
|
|
LD HL,(VDU_DISPLAY_START) ;
|
|
ADD HL,DE ;
|
|
LD B, 18 ; SET UPDATE ADDRESS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE ADDRESS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B, 14 ; SET UPDATE CSR POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 15 ; SET UPDATE CSR POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
POP DE ; RESTORE DE
|
|
POP BC ; RESTORE BC
|
|
POP AF ; RESTORE AF
|
|
RET
|
|
|
|
;__VDU_PutChar______________________________________________________________________________________
|
|
;
|
|
; PLACE CHARACTER ON SCREEN
|
|
; A: CHARACTER TO OUTPUT
|
|
; C: COLOR
|
|
;__________________________________________________________________________________________________
|
|
VDU_PutChar:
|
|
PUSH DE ; STORE DE
|
|
PUSH AF ; STORE AF
|
|
PUSH HL ; STORE HL
|
|
LD D,A ; STORE CHAR IN D
|
|
LD A,(TERM_X) ; PLACE X COORD IN A
|
|
INC A ; INC X COORD
|
|
LD (TERM_X),A ; STORE IN A
|
|
CP 80 ; IS 80?
|
|
JP NZ,VDU_PutChar1 ; NO, PLACE CHAR ON DISPLAY
|
|
LD A,0 ; YES, WRAP TO NEXT LINE
|
|
LD (TERM_X),A ; STORE X
|
|
LD A,(TERM_Y) ; A= Y COORD
|
|
INC A ; INC Y COORD
|
|
LD (TERM_Y),A ; STORE Y
|
|
CP 24 ; IS PAST END OF SCREEN?
|
|
CALL Z,GOTO_XY ; YES, HANDLE SCROLLING
|
|
VDU_PutChar1: ;
|
|
;
|
|
LD HL, (VDU_DisplayPos) ; GET CURRENT DISPLAY ADDRESS
|
|
LD B, 18 ; SET UPDATE CSR POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE CSR POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD A,D ; RESTORE CHAR
|
|
LD B,31 ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
PUSH HL ;
|
|
LD DE,$0820 ;
|
|
ADD HL,DE ;
|
|
LD B, 18 ; SET UPDATE CSR POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE CSR POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD A,C ; GET COLOR
|
|
LD B,31 ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
POP HL ; RESTORE ADDRESS
|
|
INC HL ; INCREMENT IT
|
|
LD (VDU_DisplayPos), HL ; STORE CURRENT DISPLAY ADDRESS
|
|
PUSH HL ; MOVE HL TO DE
|
|
POP DE ;
|
|
LD HL,(VDU_DISPLAY_START) ;
|
|
ADD HL,DE ;
|
|
LD B, 14 ; SET UPDATE CSR POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 15 ; SET UPDATE CSR POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
POP HL ; RESTORE HL
|
|
POP AF ; RESTORE AF
|
|
POP DE ; RESTORE DE
|
|
RET
|
|
|
|
VDU_PutCharRAW:
|
|
PUSH BC ;
|
|
LD D,A ;
|
|
LD HL, (VDU_DisplayPos) ; GET CURRENT DISPLAY ADDRESS
|
|
LD B, 18 ; SET UPDATE CSR POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE CSR POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD A,D ; RESTORE CHAR
|
|
LD B,31 ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
PUSH HL ;
|
|
LD DE,$0820 ;
|
|
ADD HL,DE ;
|
|
LD B, 18 ; SET UPDATE CSR POS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE CSR POS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD A,C ; GET COLOR
|
|
LD B,31 ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
POP HL ; RESTORE ADDRESS
|
|
INC HL ; INCREMENT IT
|
|
LD (VDU_DisplayPos), HL ; STORE CURRENT DISPLAY ADDRESS
|
|
POP BC
|
|
RET
|
|
|
|
;__VDU_LOADFONT____________________________________________________________________________________
|
|
;
|
|
; LOAD SCREEN FONT
|
|
;__________________________________________________________________________________________________
|
|
VDU_LOADFONT:
|
|
PUSH AF
|
|
PUSH BC
|
|
|
|
LD HL,$2000 ; SET FONT LOCATION
|
|
;
|
|
LD B, 18 ; SET UPDATE ADDRESS IN VDU
|
|
LD A,H ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
LD B, 19 ; SET UPDATE ADDRESS IN VDU
|
|
LD A,L ;
|
|
CALL VDU_WREG ; WRITE IT
|
|
|
|
LD B,$00 ; FONT SIZE
|
|
LD C,$20 ; FONT SIZE
|
|
LD HL,FONT ; FONT DATA
|
|
VDU_LOADFONT_LOOP:
|
|
IN A,(M8563Status) ; read address/status register
|
|
BIT 7,A ; if bit 7 = 1 than an update strobe has been occured
|
|
JR Z,VDU_LOADFONT_LOOP ; wait for ready
|
|
LD A,31 ;
|
|
OUT (M8563Register) , A ; select register
|
|
VDU_LOADFONT_LOOP_1:
|
|
IN A,(M8563Status) ; read address/status register
|
|
BIT 7,A ; if bit 7 = 1 than an update strobe has been occured
|
|
JR Z,VDU_LOADFONT_LOOP_1 ; wait for ready
|
|
LD A,(HL) ;
|
|
OUT (M8563Data) , A ; PUT DATA
|
|
INC HL
|
|
DJNZ VDU_LOADFONT_LOOP ;
|
|
DEC C ;
|
|
JP NZ,VDU_LOADFONT_LOOP ;
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
|
|
;__KB_INITIALIZE___________________________________________________________________________________
|
|
;
|
|
; INIT KEYBOARD CONTROLLER
|
|
;__________________________________________________________________________________________________
|
|
KB_INITIALIZE:
|
|
LD C,0a7H ;
|
|
CALL I8242CommandPut ;
|
|
LD C,0aeH ;
|
|
CALL I8242CommandPut ;
|
|
LD C,0aaH ;
|
|
CALL I8242CommandPut ;
|
|
LD A,0 ; EMPTY KB QUEUE
|
|
LD (KB_QUEUE_PTR),A ;
|
|
RET
|
|
|
|
;__I8242CommandPut_________________________________________________________________________________
|
|
;
|
|
; WRITE VALUE IN A TO 8242
|
|
; C: VALUE TO WRITE
|
|
;__________________________________________________________________________________________________
|
|
I8242CommandPut:
|
|
IN A,(I8242Status) ; read status register
|
|
BIT 1,A ; if bit 1 = 1
|
|
JR NZ,I8242CommandPut ; wait for ready
|
|
LD A,C ;
|
|
OUT (I8242Command),A ; select register
|
|
RET
|
|
|
|
;__WAIT_KBHIT______________________________________________________________________________________
|
|
;
|
|
; WAIT FOR A KEY PRESS
|
|
;__________________________________________________________________________________________________
|
|
WAIT_KBHIT:
|
|
CALL KB_PROCESS ; call keyboard routine
|
|
LD A,(KB_QUEUE_PTR) ; IS QUEUE EMPTY?
|
|
OR A ; set flags
|
|
JP Z,WAIT_KBHIT ; if no keys waiting, try again
|
|
RET
|
|
|
|
;__IS_KBHIT________________________________________________________________________________________
|
|
;
|
|
; WAS A KEY PRESSED?
|
|
;__________________________________________________________________________________________________
|
|
IS_KBHIT:
|
|
CALL KB_PROCESS ; call keyboard routine
|
|
LD A,(KB_QUEUE_PTR) ; ask if keyboard has key waiting
|
|
RET
|
|
|
|
;__GET_KEY_________________________________________________________________________________________
|
|
;
|
|
; GET KEY PRESS VALUE
|
|
;__________________________________________________________________________________________________
|
|
GET_KEY:
|
|
CALL WAIT_KBHIT ; WAIT FOR A KEY
|
|
LD A,(KB_QUEUE_PTR) ; GET QUEUE POINTER
|
|
OR A ;
|
|
RET Z ; ABORT IF QUEUE EMPTY
|
|
PUSH BC ; STORE BC
|
|
LD B,A ; STORE QUEUE COUNT FOR LATER
|
|
PUSH HL ; STORE HL
|
|
LD A,(KB_QUEUE) ; GET TOP BYTE FROM QUEUE
|
|
PUSH AF ; STORE IT
|
|
LD HL,KB_QUEUE ; GET POINTER TO QUEUE
|
|
GET_KEY_LOOP: ;
|
|
INC HL ; POINT TO NEXT VALUE IN QUEUE
|
|
LD A,(HL) ; GET VALUE
|
|
DEC HL ;
|
|
LD (HL),A ; MOVE IT UP ONE
|
|
INC HL ;
|
|
DJNZ GET_KEY_LOOP ; LOOP UNTIL DONE
|
|
LD A,(KB_QUEUE_PTR) ; DECREASE QUEUE POINTER BY ONE
|
|
DEC A ;
|
|
LD (KB_QUEUE_PTR),A ;
|
|
POP AF ; RESTORE VALUE
|
|
POP HL ; RESTORE HL
|
|
POP BC ; RESTORE BC
|
|
RET
|
|
|
|
|
|
;__KB_PROCESS______________________________________________________________________________________
|
|
;
|
|
; a=0 if want to know if a byte is available, and a=1 to ask for the byte
|
|
;__________________________________________________________________________________________________
|
|
KB_PROCESS:
|
|
IN A,(I8242Status) ; read status register
|
|
BIT 0,A ; if bit 0 = 0
|
|
RET Z ; EXIT
|
|
IN A,(I8242Data) ; GET BYTE
|
|
call KB_decodechar ; returns char or 0 for things like keyup, some return directly to cp/m
|
|
ret ; return to cp/m
|
|
|
|
;__KB_waitbyte______________________________________________________________________________________
|
|
;
|
|
; WAIT FOR byte TO BE available
|
|
;__________________________________________________________________________________________________
|
|
KB_waitbyte:
|
|
IN A,(I8242Status) ; read status register
|
|
BIT 0,A ; if bit 0 = 0
|
|
jp Z,KB_waitbyte ; LOOP
|
|
IN A,(I8242Data) ; GET BYTE
|
|
RET
|
|
|
|
;__KB_decodechar____________________________________________________________________________________
|
|
;
|
|
; decode character pass a and prints out the char
|
|
; on the LCD screen
|
|
;__________________________________________________________________________________________________
|
|
KB_decodechar:
|
|
cp 0 ; is it zero
|
|
ret z ; return if a zero - no need to do anything
|
|
|
|
ld c,a ;
|
|
cp 0AAh ; shift (down, because up would be trapped by 0F above)
|
|
jp z,shiftup ;
|
|
cp 0B6h ; other shift key
|
|
jp z,shiftup ;
|
|
cp 9Dh ; control key
|
|
jp z,controlup ;
|
|
AND 80H ; if bit 7 = 1
|
|
RET nz ; ignore char up
|
|
ld a,C ;
|
|
cp 0E0h ; TWO BYTE
|
|
JP Z,twobyte ;
|
|
cp 03Ah ; caps lock so toggle
|
|
jp z,capstog ;
|
|
cp 2Ah ; shift (down, because up would be trapped by 0F above)
|
|
jp z,shiftdown ;
|
|
cp 36h ; other shift key
|
|
jp z,shiftdown ;
|
|
cp 01Dh ; control key
|
|
jp z,controldown ;
|
|
ld c,a ;
|
|
ld b,0 ; add bc to hl
|
|
ld hl,normalkeys ; offset to add
|
|
add hl,bc ;
|
|
ld a,(ctrl) ;
|
|
cp 0 ; is control being held down?
|
|
jR z,dc1 ; no so go back to test caps lock on
|
|
ld a,(hl) ; get the letter, should be smalls
|
|
sub 96 ; a=97 so subtract 96 a=1=^A
|
|
JP KB_ENQUEUE ; STORE ON KB QUEUE
|
|
dc1: ld a,(capslock) ;
|
|
cp 0 ; is it 0, if so then don't add the caps offset
|
|
jr z,dc2 ;
|
|
ld c,080h ; add another 50h to smalls to get caps
|
|
add hl,bc ;
|
|
dc2: ld a,(hl) ;
|
|
JP KB_ENQUEUE ; STORE ON KB QUEUE
|
|
twobyte:; already got EO so get the next character
|
|
call KB_waitbyte
|
|
cp 053h ; delete
|
|
jp z,deletekey ;
|
|
cp 01Ch ; return on number pad
|
|
jp z,returnkey ;
|
|
cp 050h ;
|
|
jp z,downarrow ;
|
|
cp 04Dh ;
|
|
jp z,rightarrow ;
|
|
cp 04Bh ;
|
|
jp z,leftarrow ;
|
|
cp 048h ;
|
|
jp z,uparrow ;
|
|
cp 052h ;
|
|
jp z,insert ;
|
|
cp 049h ;
|
|
jp z,pageup ;
|
|
cp 051h ;
|
|
jp z,pagedown ;
|
|
cp 047h ;
|
|
jp z,home ;
|
|
cp 04Fh ;
|
|
jp z,end ;
|
|
ld a,0 ; returns nothing
|
|
ret
|
|
home: ;
|
|
ld a,1BH ; ESC
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'?' ; ?
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'w' ; w
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
end: ;
|
|
ld a,1BH ; ESC
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'?' ; ?
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'q' ; q
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
downarrow: ;
|
|
ld a,1BH ; ESC
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'B' ; B
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
rightarrow: ;
|
|
ld a,1BH ; ESC
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'C' ; C
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
leftarrow: ;
|
|
ld a,1BH ; ESC
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'D' ; D
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
uparrow: ;
|
|
ld a,1BH ; ESC
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'A' ; A
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
insert: ;
|
|
ld a,1BH ; ESC
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'?' ; ?
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'p' ; p
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
pageup: ;
|
|
ld a,1BH ; ESC
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'?' ; ?
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'y' ; y
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
pagedown: ;
|
|
ld a,1BH ; ESC
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'?' ; ?
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ld a,'s' ; s
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
controldown: ; same code as shiftdown but diff location
|
|
ld a,0ffh ;
|
|
ld (ctrl),a ; control down
|
|
ld a,0 ;
|
|
ret ;
|
|
controlup: ; control key up see shift for explanation
|
|
ld a,0 ;
|
|
ld (ctrl),a ;
|
|
ld a,0 ;
|
|
ret ;
|
|
returnkey: ;
|
|
ld a,13 ;
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
deletekey: ;
|
|
ld a,07fh ; delete key value that cp/m uses
|
|
CALL KB_ENQUEUE ; STORE ON KB QUEUE
|
|
ret ;
|
|
capstog: ;
|
|
ld a,(capslock) ;
|
|
xor 11111111B ; swap all the bits
|
|
ld (capslock),a ;
|
|
ld a,0 ; returns nothing
|
|
ret ;
|
|
shiftdown: ; shift is special - hold it down and it autorepeats
|
|
; so once it is down, turn caps on and ignore all further shifts
|
|
; only an F0+shift turns caps lock off again
|
|
ld a,0ffh ;
|
|
ld (capslock),a ;
|
|
ld a,0 ; returns nothing
|
|
ret ;
|
|
shiftup: ; shiftup turns off caps lock definitely
|
|
ld a,0 ;
|
|
ld (capslock),a ;
|
|
ld a,0 ; returns nothing
|
|
ret ;
|
|
|
|
;__KB_ENQUEUE______________________________________________________________________________________
|
|
;
|
|
; STORE A BYTE IN THE KEYBOARD QUEUE
|
|
; A: BYTE TO ENQUEUE
|
|
;__________________________________________________________________________________________________
|
|
KB_ENQUEUE:
|
|
PUSH DE ; STORE DE
|
|
PUSH HL ; STORE HL
|
|
PUSH AF ; STORE VALUE
|
|
LD A,(KB_QUEUE_PTR); PUT QUEUE POINTER IN A
|
|
CP 15 ; IS QUEUE FULL
|
|
JP P,KB_ENQUEUE_AB ; YES, ABORT
|
|
LD HL,KB_QUEUE ; GET QUEUE POINTER
|
|
PUSH HL ; MOVE HL TO BC
|
|
POP BC ;
|
|
LD H,0 ; ZERO OUT H
|
|
LD L,A ; PLACE QUEUE POINTER IN L
|
|
ADD HL,BC ; POINT HL AT THE NEXT LOACTION TO ADD VALUE
|
|
POP AF ; RESTORE VALUE
|
|
LD (HL),A ; ENQUEUE VALUE
|
|
LD A,(KB_QUEUE_PTR); GET QUEUE POINTER
|
|
INC A ; INC IT
|
|
LD (KB_QUEUE_PTR),A; STORE QUEUE POINTER
|
|
KB_ENQUEUE_AB:
|
|
POP HL ; RESTORE HL
|
|
POP DE ; RESTORE DE
|
|
RET
|
|
|
|
normalkeys: ; The TI character codes, offset from label by keyboard scan code
|
|
.db 000,027,"1","2","3","4","5","6","7","8","9","0","-","=",008,009 ;00-0F
|
|
.DB "q","w","e","r","t","y","u","i","o","p","[","]",013,000,"a","s" ;10-1F
|
|
.DB "d","f","g","h","j","k","l",";",27H,60H,000,092,"z","x","c","v" ;20-2F
|
|
.DB "b","n","m",",",".","/",000,000,000," ",000,000,000,000,000,000 ;30-3F
|
|
.DB 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 ;40-4F
|
|
.db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 ;50-5F
|
|
.db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 ;60-6F
|
|
.db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 ;70-7F
|
|
.db 000,027,"!","@","#","$","%","^","&","*","(",")","_","+",008,009
|
|
.DB "Q","W","E","R","T","Y","U","I","O","P","{","}",013,000,"A","S"
|
|
.DB "D","F","G","H","J","K","L",":",034,"~",000,"|","Z","X","C","V"
|
|
.DB "B","N","M","<",">","?",000,000,000," ",000,000,000,000,000,000
|
|
.db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
|
|
.DB 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
|
|
.db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
|
|
.db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
|
|
|
|
.include "font.asm"
|
|
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; RAM STORAGE AREAS
|
|
;__________________________________________________________________________________________________
|
|
|
|
ALT_KEYPAD .DB 0 ; ALT KEYPAD ENABLED?
|
|
GR_MODE .DB 0 ; GRAPHICS MODE ENABLED?
|
|
TERM_X: .DB 0 ; CURSOR X
|
|
TERM_Y: .DB 0 ; CURSOR Y
|
|
TERMSTATE: .DB 0 ; TERMINAL STATE
|
|
; 0 = NORMAL
|
|
; 1 = ESC RCVD
|
|
VDU_DisplayPos: .DW 0 ; CURRENT DISPLAY POSITION
|
|
VDU_DISPLAY_START:
|
|
.DW 0 ; CURRENT DISPLAY POSITION
|
|
capslock .DB 0 ; location for caps lock, either 00000000 or 11111111
|
|
ctrl .DB 0 ; location for ctrl on or off 00000000 or 11111111
|
|
numlock .DB 0 ; location for num lock
|
|
skipcount .DB 0 ; only check some calls, speeds up a lot of cp/m
|
|
|
|
KB_QUEUE .DB 0,0,0,0,0,0,0,0 ; 16 BYTE KB QUEUE
|
|
.DB 0,0,0,0,0,0,0,0
|
|
KB_QUEUE_PTR .DB 0 ; POINTER TO QUEUE
|
|
PARKSTACK .DW 0000 ; SAVE STACK POINTER
|
|
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
.DB 0,0,0,0,0,0,0,0 ;
|
|
TERMSTACK: .DB 0 ;
|
|
|
|
|
|
.end
|
|
|