Applecorn/auxmem.vdu.s
2021-09-06 22:28:07 -04:00

504 lines
14 KiB
ArmAsm

* AUXMEM.VDU.S
* (c) Bobbi 2021 GPLv3
*
* Apple //e VDU Driver for 40/80 column mode (PAGE2)
*
* 15-Aug-2021 Optimised address calculations and PRCHRC.
* Entry point to move copy cursor.
* Start to consolidate VDU workspace.
* 16-Aug-2021 Added COPY cursor handling.
* 21-Aug-2021 CHR$(&80+n) is inverse of CHR$(&00+n)
* 21-Aug-2021 If screen scrolls, copy cursor adjusted.
* 05-Sep-2021 Starting to prepare VDU workspace.
**********************************
* VDU DRIVER WORKSPACE LOCATIONS *
**********************************
* $00D0-$00DF VDU driver zero page workspace
* $03ED-$03EE XFER transfer address
VDUSTATUS EQU $D0 ; $D0 VDU status
VDUZP1 EQU VDUSTATUS+1 ; $D1
* VDUTEXTX EQU VDUSTATUS+2 ; $D2 text column
* VDUTEXTY EQU VDUSTATUS+3 ; $D3 text row
VDUADDR EQU VDUSTATUS+4 ; $D4 address of current char cell
FXVDUQLEN EQU $D1 ; TEMP HACK
VDUCHAR EQU $D6 ; TEMP HACK
VDUQ EQU $D7 ; TEMP HACK
* VDUVARS
* VDUTEXTX EQU $2A0+0 ; text X coord
* VDUTEXTY EQU $2A0+1 ; text Y coord
VDUTEXTX EQU $96 ;COL TEMP
VDUTEXTY EQU $97 ;ROW TEMP
VDUCOPYX EQU $2A0+2 ; copy cursor X coord
VDUCOPYY EQU $2A0+3 ; copy cursor Y coord
* VDUCOPYCHR EQU $2A0+0 ; char underneath cursor when copying
* VDUCURSOR EQU $2A0+4 ; cursor character
VDUMODE EQU $2A0+5 ; current MODE
* VDUCHAR EQU $2A0+6 ; VDU command, 1 byte
* VDUQ EQU $2A0+7 ; VDU sequence, 9 bytes
* TEMP, move to VDU.S
* FLASHER EQU $290 ; flash counter for cursor
* CURSOR EQU $291 ; character under cursor
* CURSORED EQU $292 ; character used for cursor
* CURSORCP EQU $293 ; character used for edit cursor
* OLDCHAR EQU $294 ; character used for copy cursor
* COPYCHAR EQU $295 ;
* Start restructuring VDU variables
***********************************
VDUVARS EQU $290
* VDUTWINL VDUVARS+$08 ; text window left
* VDUTWINB VDUVARS+$09 ; text window bottom \ window
* VDUTWINR VDUVARS+$0A ; text window right / size
* VDUTWINT VDUVARS+$0B ; text window top
*
* VDUTEXTX EQU VDUVARS+$18 ; absolute POS
* VDUTEXTY EQU VDUVARS+$19 ; absolute VPOS
* VDUCOPYX EQU VDUVARS+$1A ;
* VDUCOPYY EQU VDUVARS+$1B ;
* VDUMODE
* CURSOR
* CURSORED
* CURSORCP
* Move editing cursor
* A=cursor key, CS from caller
COPYMOVE PHA
BIT VDUSTATUS
BVS COPYMOVE2 ; Edit cursor already on
JSR GETCHRC
STA COPYCHAR
LDA CURSORED
JSR PUTCHRC ; Edit cursor
SEC
JSR COPYSWAP2 ; Initialise copy cursor
ROR FLASHER
ASL FLASHER ; Ensure b0=0
LDA #$42
ORA VDUSTATUS
STA VDUSTATUS ; Turn cursor editing on
COPYMOVE2 PLA
AND #3 ; Convert to 8/9/10/11
ORA #8
COPYMOVE3 JMP OUTCHARGO ; Move edit cursor
** Turn editing cursor on/off
*COPYCURSOR BIT VDUSTATUS
* BVC COPYSWAP4 ; Copy cursor not active
* PHP ; Save CS=Turn On, CC=Turn Off
* JSR COPYSWAP1 ; Swap to edit cursor
* LDA COPYCHAR ; Prepare to turn edit cursor off
* PLP
* BCC COPYCURS2 ; Restore character
*COPYCURS1 JSR GETCHRC ; Get character under edit cursor
* STA COPYCHAR
* LDA #$A0 ; Output edit cursor
*COPYCURS2 JSR PUTCHRC
** ; Drop through to swap back
* Swap between edit and copy cursors
*COPYSWAP BIT VDUSTATUS
* BVC COPYSWAP4 ; Edit cursor off
COPYSWAP1 CLC ; CC=Swap TEXT and COPY
COPYSWAP2 LDX #1
COPYSWAPLP LDY VDUCOPYX,X
LDA VDUTEXTX,X
STA VDUCOPYX,X
BCS COPYSWAP3 ; CS=Copy TEXT to COPY
TYA
STA VDUTEXTX,X
COPYSWAP3 DEX
BPL COPYSWAPLP
COPYSWAP4 RTS
* Clear to EOL
CLREOL LDA VDUTEXTY ; ROW
ASL
TAX
LDA SCNTAB,X ; LSB of row
STA ZP1
LDA SCNTAB+1,X ; MSB of row
STA ZP1+1
LDA VDUTEXTX ; COL
PHA
STZ VDUTEXTX ; COL
:L1
LDA VDUTEXTX ; COL
LSR
TAY
BCC :S1
>>> WRTMAIN
:S1 LDA #" "
STA (ZP1),Y
>>> WRTAUX
LDA VDUTEXTX ; COL
CMP #79
BEQ :S2
INC VDUTEXTX ; COL
BRA :L1
:S2 PLA
STA VDUTEXTX ; COL
RTS
* Clear the screen
VDUINIT STA $C00F
LDA #'_'
STA CURSOR ; Normal cursor
STA CURSORCP ; Copy cursor when editing
LDA #$A0
STA CURSORED ; Edit cursor when editing
CLEAR STZ VDUTEXTY ; ROW
STZ VDUTEXTX ; COL
:L1 JSR CLREOL
:S2 LDA VDUTEXTY ; ROW
CMP #23
BEQ :S3
INC VDUTEXTY ; ROW
BRA :L1
:S3 STZ VDUTEXTY ; ROW
STZ VDUTEXTX ; COL
RTS
* Calculate character address
CHARADDR LDA VDUTEXTY
ASL
TAX
LDA SCNTAB+0,X ; LSB of row address
STA VDUADDR+0
LDA SCNTAB+1,X ; MSB of row address
STA VDUADDR+1
LDA VDUTEXTX
BIT $C01F
SEC
BPL CHARADDR40 ; 40-col
LSR A
CHARADDR40 TAY ; Y=offset into this row
RTS
* (VDUADDR),Y=>character address
* CC=auxmem
* CS=mainmem
* Print char in A at ROW,COL
PRCHRC PHA ; Save character
LDA $C000
BPL :RESUME ; No key pressed
EOR #$80
:PAUSE1 JSR KBDCHKESC ; Ask KBD to test if Escape
BIT ESCFLAG
BMI :RESUMEACK ; Escape, skip pausing
CMP #$13
BNE :RESUME ; Not Ctrl-S
STA $C010 ; Ack. keypress
:PAUSE2 LDA $C000
BPL :PAUSE2 ; Loop until keypress
EOR #$80
CMP #$11 ; Ctrl-Q
BEQ :RESUMEACK ; Stop pausing
JSR KBDCHKESC ; Ask KBD to test if Escape
BIT ESCFLAG
BPL :PAUSE2 ; No Escape, keep pausing
:RESUMEACK STA $C010 ; Ack. keypress
:RESUME PLA
* Put character to screen
PUTCHRC EOR #$80 ; Convert character
TAY
AND #$A0
BNE PRCHR4
TYA
EOR #$40
TAY
PRCHR4 PHY
JSR CHARADDR ; Find character address
PLA ; Get character back
PHP ; Disable IRQs while
SEI ; toggling memory
BCC PRCHR6 ; Aux memory
STA $C004 ; Switch to main memory
PRCHR6 STA (VDUADDR),Y ; Store it
STA $C005 ; Back to aux memory
PLP ; Restore IRQs
RTS
* Return char at ROW,COL in A and X, MODE in Y
BYTE87
GETCHRC JSR CHARADDR ; Find character address
PHP ; Disable IRQs while
SEI ; toggling memory
BCC GETCHR6 ; Aux memory
STA $C002 ; Switch to main memory
GETCHR6 LDA (VDUADDR),Y ; Get character
STA $C003 ; Back to aux memory
PLP ; Restore IRQs
TAY ; Convert character
AND #$A0
BNE GETCHR7
TYA
EOR #$40
TAY
GETCHR7 TYA
EOR #$80
TAX ; X=char for OSBYTE
LDY #$00
BIT $C01F
BMI GETCHROK
INY ; Y=MODE
GETCHROK RTS
BYTE86 LDY VDUTEXTY ; ROW ; $86 = read cursor pos
LDX VDUTEXTX ; COL
RTS
* Perform backspace & delete operation
DELETE JSR BACKSPC
:S2 LDA #' '
JMP PUTCHRC
*:S3 RTS
* Perform backspace/cursor left operation
BACKSPC
LDA VDUTEXTX ; COL
BEQ :S1
DEC VDUTEXTX ; COL
BRA :S3
:S1 LDA VDUTEXTY ; ROW
BEQ :S3
DEC VDUTEXTY ; ROW
LDA #39
BIT $C01F
BPL :S2
LDA #79
:S2
STA VDUTEXTX ; COL
:S3 RTS
* Output character to VDU driver
* All registers trashable
OUTCHAR
*
* Quick'n'nasty VDU queue
LDX FXVDUQLEN
BNE ADDTOQ
CMP #$01
BEQ ADDQ ; One param
CMP #$11
BCC OUTCHARGO ; Zero param
CMP #$20
BCS OUTCHARGO ; Print chars
ADDQ STA VDUCHAR ; Save initial character
AND #$0F
TAX
LDA QLEN,X
STA FXVDUQLEN
BEQ OUTCHARGO1
QDONE RTS
QLEN DB -0,-1,-2,-5,-0,-0,-1,-9
DB -8,-5,-0,-0,-4,-4,-0,-2
ADDTOQ STA VDUQ-256+9,X
INC FXVDUQLEN
BNE QDONE
OUTCHARGO1 LDA VDUCHAR
* end nasty hack
*
OUTCHARGO CMP #$00 ; NULL
BNE :T1
BRA :IDONE
:T1 CMP #$07 ; BELL
BNE :T2
JSR BEEP
BRA :IDONE
:T2 CMP #$08 ; Backspace
BNE :T3
JSR BACKSPC
BRA :IDONE
:T3 CMP #$09 ; Cursor right
BNE :T4
* JSR CURSRT
JSR VDU09
BRA :IDONE
:T4 CMP #$0A ; Linefeed
BNE :T5
LDA VDUTEXTY ; ROW
CMP #23
BEQ :TOSCROLL ; JGH
INC VDUTEXTY ; ROW
:IDONE RTS
* BRA :DONE
:TOSCROLL JMP SCROLL ; JGH
:T5 CMP #$0B ; Cursor up
BNE :T6
LDA VDUTEXTY ; ROW
BEQ :IDONE
DEC VDUTEXTY ; ROW
* BRA :IDONE
RTS
:T6 CMP #$0D ; Carriage return
BNE :T7
LDA #$BF
AND VDUSTATUS
STA VDUSTATUS ; Turn copy cursor off
STZ VDUTEXTX ; COL
* BRA :IDONE
RTS
:T7 CMP #$0C ; Ctrl-L
BEQ :T7A
CMP #$16 ; MODE
BNE :T8
LDA VDUQ+8
STA VDUMODE
EOR #$07
AND #$01
TAX
STA $C00C,X
:T7A JSR CLEAR
* BRA :IDONE
RTS
:T8 CMP #$1E ; Home
BNE :T9
STZ VDUTEXTY ; ROW
STZ VDUTEXTX ; COL
* BRA :IDONE
RTS
:T9
CMP #$1F ; TAB
BNE :T9B
LDY VDUQ+8
CPY #24
BCS :IDONE
LDX VDUQ+7
CPX #80
BCS :IDONE
BIT $C01F
BMI :T9A
CPX #80
BCS :IDONE
:T9A
STX VDUTEXTX ; COL
STY VDUTEXTY ; ROW
RTS
:T9B CMP #$7F ; Delete
BNE :T10
JSR DELETE
* BRA :IDONE
RTS
:T10 CMP #$20
BCC :IDONE
CMP #$80
BCC :T10A
CMP #$A0
BCS :T10A
LDX VDUMODE
CPX #$07
BNE :T10A
LDA #$20
:T10A JSR PRCHRC ; Store char, checking keypress
* Perform cursor right operation
VDU09
LDA VDUTEXTX ; COL
CMP #39
BCC :S2
BIT $C01F
BPL :T11
CMP #79
BCC :S2
:T11
STZ VDUTEXTX ; COL
LDA VDUTEXTY ; ROW
CMP #23
BEQ SCROLL
INC VDUTEXTY ; ROW
:DONE RTS
* BRA :DONE
:S2
INC VDUTEXTX ; COL
BRA :DONE
SCROLL JSR SCROLLER
* STZ VDUTEXTX ; COL
JSR CLREOL
*:DONE
RTS
* Scroll whole screen one line
SCROLLER LDA #$00
:L1 PHA
JSR SCR1LINE
PLA
INC
CMP #23
BNE :L1
BIT VDUSTATUS
BVC :L2 ; Copy cursor not active
JSR COPYSWAP1
LDA #11
JSR OUTCHARGO
JSR COPYSWAP1
:L2 RTS
* Copy line A+1 to line A
SCR1LINE ASL ; Dest addr->ZP1
TAX
LDA SCNTAB,X
STA ZP1
LDA SCNTAB+1,X
STA ZP1+1
INX ; Source addr->ZP2
INX
LDA SCNTAB,X
STA ZP2
LDA SCNTAB+1,X
STA ZP2+1
LDY #$00
:L1 LDA (ZP2),Y
STA (ZP1),Y
STA $C002 ; Read main mem
>>> WRTMAIN
LDA (ZP2),Y
STA (ZP1),Y
STA $C003 ; Read aux mem
>>> WRTAUX
INY
CPY #40
BNE :L1
RTS
* Addresses of screen rows in PAGE2
SCNTAB DW $800,$880,$900,$980,$A00,$A80,$B00,$B80
DW $828,$8A8,$928,$9A8,$A28,$AA8,$B28,$BA8
DW $850,$8D0,$950,$9D0,$A50,$AD0,$B50,$BD0
* TEST code for VIEW
BYTE75 LDX VDUSTATUS
RTS
BYTE76 LDX #$00
RTS
BYTEA0 LDY #79 ; Read VDU variable $09,$0A
LDX #23
RTS
* TEST