diff --git a/auxmem.chario.s b/auxmem.chario.s index b58790b..c0d6177 100644 --- a/auxmem.chario.s +++ b/auxmem.chario.s @@ -1,5 +1,5 @@ * AUXMEM.CHARIO.S -* (c) Bobbi 2021 GPLv3 +* (c) Bobbi 2021,2022 GPLv3 * * AppleMOS Character I/O @@ -9,7 +9,7 @@ * Character read and write * * 14-Aug-2021 Flashing cursor and INKEY sync'd to frame rate -* with VBLK. Ensured cursor turned on straightaway. +* with VBLK. Ensured cursor turned on straight away. * 15-Aug-2021 Cursor keys move copy cursor, copy reads char. * Copy cursor not visible yet. * 16-Aug-2021 Copy cursor and Edit cursor visible. @@ -27,11 +27,18 @@ * 12-Sep-2021 COPY calls new VDU entry point. * 15-Sep-2021 INKEY(0) tests once and returns immediately. * 30-Nov-2021 With *FX4,<>0 TAB returns $09, allows eg VIEW to work. -* 13-Sep-2022 Fix bug in INKEY with misbalanced stack when Escape pressed -* TO DO: CHKESC should go through translations before testing. +* 15-Oct-2022 Replace calling KBDCHKESC with ESCPOLL, does translations, etc. +* Fixed bug with cursor keys after *FX4,2. OSRDCH enables IRQs. -FLASHER EQU BYTEVARBASE+176 ; VSync counter for flashing cursor +* Hardware locations +KBDDATA EQU $C000 ; Read Keyboard data +KBDACK EQU $C010 ; Acknowledge keyboard data +KBDAPPLFT EQU $C061 ; Left Apple key +KBDAPPRGT EQU $C062 ; Right Apple key +IOVBLNK EQU $C019 ; VBLNK pulse + +FLASHER EQU BYTEVARBASE+176 ; VSync counter for flashing cursor FXEXEC EQU BYTEVARBASE+198 FXSPOOL EQU BYTEVARBASE+199 @@ -56,23 +63,23 @@ WRCHHND PHA PHX PHY PHA - JSR OUTCHAR - * TO DO Check any output redirections * TO DO Check any printer output -* BCC WRCHHND3 -* PLA + JSR OUTCHAR ; Send to VDU driver +* BCC WRCHHND3 ; VDU driver says skip printer +* PLA ; Get character back * PHA -* JSR PRNCHAR +* JSR PRNCHAR ; Send to printer * WRCHHND3 - - LDY FXSPOOL ; See if *SPOOL is in effect - BEQ WRCHHND4 +* Check FX3VAR +* Bxx WRCHHND4 ; Spool disabled + LDY FXSPOOL ; See if *SPOOL is in effect + BEQ WRCHHND4 ; No, skip sending to spool file PLA PHA - JSR OSBPUT ; Write char to spool file -WRCHHND4 PLA - PLY + JSR OSBPUT ; Write character to spool file +WRCHHND4 PLA ; Drop stacked character + PLY ; Restore everything PLX PLA RTS @@ -81,32 +88,32 @@ WRCHHND4 PLA * Character Input ***************** * Default keyboard OSBYTE variables -*DEFBYTELOW EQU 219 ; First default OSBYTE value -*DEFBYTE DB $09,$1B ; Default key codes -* DB $01,$D0,$E0,$F0 ; Default key expansion -* DB $01,$80,$90,$00 ; Default key expansion +*DEFBYTELOW EQU 219 ; First default OSBYTE value +*DEFBYTE DB $09,$1B ; Default key codes +* DB $01,$D0,$E0,$F0 ; Default key expansion +* DB $01,$80,$90,$00 ; Default key expansion *DEFBYTEEND * TEMP as no *KEY * Default keyboard OSBYTE variables -DEFBYTELOW EQU 219 ; First default OSBYTE value -DEFBYTE DB $09,$1B ; Default key codes - DB $C0,$D0,$E0,$F0 ; Default key expansion - DB $80,$90,$A0,$B0 ; Default key expansion +DEFBYTELOW EQU 219 ; First default OSBYTE value +DEFBYTE DB $09,$1B ; Default key codes + DB $C0,$D0,$E0,$F0 ; Default key expansion + DB $80,$90,$A0,$B0 ; Default key expansion DEFBYTEEND KBDINIT LDX #DEFBYTEEND-DEFBYTE-1 -:KBDINITLP LDA DEFBYTE,X ; Initialise KBD OSBYTE variables +:KBDINITLP LDA DEFBYTE,X ; Initialise KBD OSBYTE variables STA BYTEVARBASE+DEFBYTELOW,X DEX BPL :KBDINITLP LDX #$C0 - STX FX254VAR ; b7-b4=default KBD map, b3-b0=default MODE - BIT SETV - JSR KBDTEST - BCS :KBDINITOK ; Return default MODE=0 - STA KBDSTRB ; Ack. keypress - TAX ; Use keypress as default MODE + STX FX254VAR ; b7-b4=default KBD map, b3-b0=default MODE + BIT SETV ; Set V + JSR KBDTEST ; Test if key being pressed + BCS :KBDINITOK ; Return default MODE=0 + STA KBDACK ; Ack. keypress + TAX ; Use keypress as default MODE :KBDINITOK TXA RTS @@ -115,88 +122,89 @@ KBDINIT LDX #DEFBYTEEND-DEFBYTE-1 * Read a character from current input * All registers preserved except A, Carry * Flashes a soft cursor while waiting for input +* *NB* OSRDCH returns with IRQs enabled, INKEY returns with IRQs preserved * -RDCHHND LDA #$80 ; flag=wait forever +RDCHHND LDA #$80 ; flag=wait forever PHY TAY - BRA INKEYGO ; Wait forever for input + BRA INKEYGO ; Wait forever for input * XY<$8000 - wait for a keypress -INKEY PHY ; Dummy PHY to balance RDCH -INKEYGO PHX ; Save registers +INKEY PHY ; Dummy PHY to balance RDCH +INKEYGO CLI ; Enable IRQs + PHX ; Save registers PHY - BIT VDUSTATUS ; Enable editing cursor - BVC INKEYGO2 ; No editing cursor - JSR GETCHRC ; Get character under cursor - STA COPYCHAR ; Save char under edit cursor + BIT VDUSTATUS ; Enable editing cursor + BVC INKEYGO2 ; No editing cursor + JSR GETCHRC ; Get character under cursor + STA COPYCHAR ; Save char under edit cursor LDA CURSORED - JSR PUTCHRC ; Display edit cursor - JSR COPYSWAP1 ; Swap to copy cursor -INKEYGO2 JSR GETCHRC ; Get character under cursor + JSR PUTCHRC ; Display edit cursor + JSR COPYSWAP1 ; Swap to copy cursor +INKEYGO2 JSR GETCHRC ; Get character under cursor STA OLDCHAR - BRA INKEY1 ; Turn cursor on + BRA INKEY1 ; Turn cursor on INKEYLP CLC - LDA #$01 ; Slow flash, every 32 frames + LDA #$01 ; Slow flash, every 32 frames BIT VDUSTATUS BVC INKEY0 - ASL A ; Fast flash, every 16 frames + ASL A ; Fast flash, every 16 frames INKEY0 ADC FLASHER STA FLASHER AND #15 - BNE INKEY3 ; Not time to toggle yet - LDA OLDCHAR ; Prepare to remove cursor + BNE INKEY3 ; Not time to toggle yet + LDA OLDCHAR ; Prepare to remove cursor BIT FLASHER - BMI INKEY2 ; Remove cursor -INKEY1 LDA CURSOR ; Add cursor + BMI INKEY2 ; Remove cursor +INKEY1 LDA CURSOR ; Add cursor BIT VDUSTATUS BVC INKEY2 LDA CURSORCP -INKEY2 JSR PUTCHRC ; Toggle cursor +INKEY2 JSR PUTCHRC ; Toggle cursor INKEY3 LDA ESCFLAG - BMI INKEYOK ; Escape pending, return it -INKEY4 JSR KEYREAD ; Test for input, all can be trashed + BMI INKEYOK ; Escape pending, return it +INKEY4 JSR KEYREAD ; Test for input, all can be trashed PLY - BCC INKEYOK ; Char returned, return it - BMI INKEY6 ; Loop forever, skip countdown + BCC INKEYOK ; Char returned, return it + BMI INKEY6 ; Loop forever, skip countdown PLX BNE INKEY5 TYA - BEQ INKEYOUT ; XY=0, timed out - DEY ; 16-bit decrement + BEQ INKEYOUT ; XY=0, timed out + DEY ; 16-bit decrement INKEY5 DEX PHX INKEY6 PHY * * VBLK pulses at 50Hz/60Hz, toggles at 100Hz/120Hz - LDX RDVBL ; Get initial VBLK state -INKEY8 BIT KEYBOARD - BMI INKEY4 ; Key pressed + LDX IOVBLNK ; Get initial VBLK state +INKEY8 BIT KBDDATA + BMI INKEY4 ; Key pressed TXA - EOR RDVBL - BPL INKEY8 ; Wait for VBLK change - BMI INKEYLP ; Loop back to key test + EOR IOVBLNK + BPL INKEY8 ; Wait for VBLK change + BMI INKEYLP ; Loop back to key test -INKEYOUT PLA ; Drop stacked Y - LDA #$FF ; Prepare to stack $FF -* -INKEYOK PHA ; Save key or timeout - PHP ; Save CC=key, CS=timeout - LDA OLDCHAR ; Prepare for main cursor +INKEYOUT PLA ; Drop stacked Y + LDA #$FF ; Prepare to stack $FF +INKEYOK PHA ; Save key or timeout + PHP ; Save CC=key, CS=timeout + LDA OLDCHAR ; Prepare for main cursor BIT VDUSTATUS - BVC INKEYOFF2 ; No editing cursor - JSR PUTCHRC ; Remove cursor - JSR COPYSWAP1 ; Swap cursor back - LDA COPYCHAR ; Remove main cursor -INKEYOFF2 JSR PUTCHRC ; Remove cursor + BVC INKEYOFF2 ; No editing cursor + JSR PUTCHRC ; Remove cursor + JSR COPYSWAP1 ; Swap cursor back + LDA COPYCHAR ; Remove main cursor +INKEYOFF2 JSR PUTCHRC ; Remove cursor * PLP - BCS INKEYOK3 ; Timeout - LDA ESCFLAG ; Keypress, test for Escape - ASL A ; Cy=Escape flag - PLA ; Get char back - PLX ; Restore X,Y for key pressed -INKEYOK3 PLY ; Or pop TimeOut + BCS INKEYOK3 ; Timeout + LDA ESCFLAG ; Keypress, test for Escape + ASL A ; Cy=Escape flag + PLA ; Get char back + PLX ; Restore X,Y for key pressed +INKEYOK3 PLY ; Or pop TimeOut RTS * RDCH Character read: CC, A=char, X=restored, Y=restored * RDCH Escape: CS, A=char, X=restored, Y=restored @@ -206,17 +214,17 @@ INKEYOK3 PLY ; Or pop TimeOut BYTE81 TYA - BMI NEGINKEY ; XY<0, scan for keypress - JSR INKEY ; XY>=0, wait for keypress + BMI NEGINKEY ; XY<0, scan for keypress + JSR INKEY ; XY>=0, wait for keypress * Character read: CC, A=char, X=???, Y<$80 * Escape: CS, A=char, X=???, Y<$80 * Timeout: CS, A=???, X=???, Y=$FF - TAX ; X=character returned + TAX ; X=character returned TYA - BMI BYTE81DONE ; Y=$FF, timeout + BMI BYTE81DONE ; Y=$FF, timeout LDY #$00 - BCC BYTE81DONE ; CC, not Escape - LDY #$1B ; Y=27 + BCC BYTE81DONE ; CC, not Escape + LDY #$1B ; Y=27 BYTE81DONE RTS * Returns: Y=$FF, X=???, CS - timeout * Y=$1B, X=???, CS - escape @@ -224,25 +232,21 @@ BYTE81DONE RTS NEGINKEY CPX #$01 - LDX #$00 ; Unimplemented + LDX #$00 ; Unimplemented BCS NEGINKEY0 - - JSR NEGCALL ; Read machine ID from aux - TAX ; *TEST* - BIT $E0 ; *TEST* - BVS NEGINKEY1 ; *TEST* + JSR NEGCALL ; Read machine ID from mainmem LDX #$2C TAY - BEQ NEGINKEY0 ; $00 = Apple IIc -> INKEY-256 = $2C + BEQ NEGINKEY0 ; $00 = Apple IIc -> INKEY-256 = $2C LDX #$2E AND #$0F - BEQ NEGINKEY0 ; $x0 = Apple IIe -> INKEY-256 = $2E - LDX #$2A ; else = Apple IIgs -> INKEY-256 = $2A + BEQ NEGINKEY0 ; $x0 = Apple IIe -> INKEY-256 = $2E + LDX #$2A ; else = Apple IIgs -> INKEY-256 = $2A NEGINKEY0 LDY #$00 NEGINKEY1 CLC RTS -NEGCALL >>> XF2MAIN,MACHRD ; Try to read Machine ID +NEGCALL >>> XF2MAIN,MACHRD ; Try to read Machine ID * KERNEL/KEYBOARD.S @@ -256,15 +260,14 @@ NEGCALL >>> XF2MAIN,MACHRD ; Try to read Machine ID * On exit, CS=no keypress * CC=keypress * A =keycode, X,Y=corrupted -KEYREAD LDY FXEXEC ; See if *EXEC file is open - BEQ KEYREAD1 - JSR OSBGET ; Read keypress from file - BCC KEYREADOK - LDA #0 ; EOF, close *EXEC file - STA FXEXEC - JSR OSFIND +KEYREAD LDY FXEXEC ; See if EXEC file is open + BEQ KEYREAD1 ; No, skip past + JSR OSBGET ; Read character from file + BCC KEYREADOK ; Not EOF, return it + LDA #$00 ; EOF, close EXEC file + STA FXEXEC ; Clear EXEC handle + JSR OSFIND ; And close it KEYREAD1 - * * TO DO: expand current soft key * LDA SOFTKEYLEN @@ -277,46 +280,45 @@ KEYREAD1 * RTS * KEYREAD2 * - JSR KBDREAD ; Fetch character from KBD "buffer" - BCS KEYREADOK ; Nothing pending - TAY - BPL KEYREADOK ; Not top-bit key - AND #$CF + JSR KBDREAD ; Fetch character from KBD "buffer" + BCS KEYREADOK ; Nothing pending + TAY ; Y=unmodified character + BPL KEYREADOK ; Not top-bit key + AND #$CF ; Drop Shift/Ctrl bits CMP #$C9 - BCC KEYSOFT ; Not cursor key + BCC KEYSOFTY ; Not cursor key LDX FX4VAR - BEQ KEYCURSOR ; *FX4,0 - editing keys - LDY FXTABCHAR - CMP #$C9 - BEQ KEYREADOKY ; TAB key + BEQ KEYCURSOR ; *FX4,0 - editing keys + CPY #$C9 + CLV + BEQ KEYCOPYTAB ; TAB key DEX - BNE KEYSOFT1 ; Not *FX4,1 - soft key - SBC #$44 ; Return $88-$8B - TAY -KEYREADOKY TYA + BNE KEYSOFTHI ; Not *FX4,1 - soft key + SBC #$44 ; Return $88-$8B KEYREADOK1 CLC KEYREADOK RTS -* + * Process soft key -KEYSOFT1 LDX FX254VAR +KEYSOFTHI LDX FX254VAR CPX #$C0 - BCC KEYSOFT + BCC KEYSOFTY + TYA AND #$BF TAY -KEYSOFT TYA +KEYSOFTY TYA ; Get key including Shift/Ctrl LSR A LSR A LSR A - LSR A ; A=key DIV 16 - EOR #$04 ; Offset into KEYBASE + LSR A ; A=key DIV 16 + EOR #$04 ; Offset into KEYBASE TAX LDA FXKEYBASE-8,X * TO DO: *BEQ KEYNONE ; $00=ignored *DEC A *BEQ expandfunction - CMP #2 ; *TEMP* - BCC KEYNONE ; *TEMP* + CMP #2 ; *TEMP* + BCC KEYNONE ; *TEMP* TYA AND #$0F CLC @@ -329,26 +331,26 @@ KEYCURSOR CMP #$C9 BEQ KEYCOPY PHA LDA OLDCHAR - JSR PUTCHRC ; Remove cursor + JSR PUTCHRC ; Remove cursor PLA - JSR COPYMOVE ; Move copy cursor - JSR GETCHRC ; Save char under cursor + JSR COPYMOVE ; Move copy cursor + JSR GETCHRC ; Save char under cursor STA OLDCHAR KEYNONE SEC RTS -KEYCOPY LDA FXTABCHAR ; Prepare TAB if no copy cursor - BIT VDUSTATUS - BVC KEYREADOK1 ; No copy cursor, return TAB - LDA OLDCHAR ; Get the char under cursor +KEYCOPY BIT VDUSTATUS +KEYCOPYTAB LDA FXTABCHAR ; Prepare TAB if no copy cursor + BVC KEYREADOK1 ; No copy cursor, return TAB + LDA OLDCHAR ; Get the char under cursor PHA - JSR OUTCHARCP ; Output it to restore and move cursor - JSR GETCHRC ; Save char under cursor + JSR OUTCHARCP ; Output it to restore and move cursor + JSR GETCHRC ; Save char under cursor STA OLDCHAR PLA - BNE KEYREADOK1 ; Ok character + BNE KEYREADOK1 ; Ok character SEC - JMP BEEP ; Beep and return CS=No char + JMP BEEP ; Beep and return CS=No char * KBDREAD @@ -363,78 +365,96 @@ KEYCOPY LDA FXTABCHAR ; Prepare TAB if no copy cursor * TAB -> $C9 * Cursors -> $CC-$CF * -KBDREAD CLV ; VC=return keypress -KBDTEST LDA KEYBOARD ; VS here to test for keypress - EOR #$80 ; Toggle bit 7 +KBDREAD CLV ; VC=return keypress +KBDTEST LDA KBDDATA ; VS here to test for keypress + EOR #$80 ; Toggle bit 7 CMP #$80 - BCS KBDDONE ; No key pressed - BVS KBDDONE ; VS=test for keypress - STA KBDSTRB ; Ack. keypress - BIT BUTTON0 - BMI KBDLALT ; Left Apple pressed - BIT BUTTON1 - BMI KBDRALT ; Right Apple pressed + BCS KBDDONE ; No key pressed + BVS KBDDONE ; VS=test for keypress + STA KBDACK ; Ack. keypress +KBDREAD2 BIT KBDAPPLFT + BMI KBDLALT ; Left Apple pressed + BIT KBDAPPRGT + BMI KBDRALT ; Right Apple pressed CMP #$09 - BEQ KBDTAB ; TAB is dual action TAB/COPY + BEQ KBDTAB ; TAB is dual action TAB/COPY CMP #$08 - BCC KBDCHKESC ; <$08 not cursor key + BCC KBDCHKESC ; <$08 not cursor key CMP #$0C - BCC KBDCURSR ; $08-$0B are cursor keys + BCC KBDCURSR ; $08-$0B are cursor keys CMP #$15 - BNE KBDCHKESC ; $15 is cursor key + BNE KBDCHKESC ; $15 is cursor key * -KBDCUR15 LDA #$0D ; Convert RGT to $09 -KBDTAB SBC #$04 ; Convert TAB to &C9 +KBDCUR15 LDA #$0D ; Convert RGT to $09 +KBDTAB SBC #$04 ; Convert TAB to &C9 KBDCURSR CLC - ADC #$C4 ; Cursor keys $C0+x + ADC #$C4 ; Cursor keys $C0+x BRA KBDCHKESC -KBDRALT ; Right Apple key pressed -KBDLALT CMP #$40 ; Left Apple key pressed +KBDRALT ; Right Apple key pressed +KBDLALT CMP #$40 ; Left Apple key pressed BCS KBDCTRL CMP #$30 - BCC KBDCHKESC ; <'0' + BCC KBDCHKESC ; <'0' CMP #$3A - BCS KBDCHKESC ; >'9' -KBDFUNC AND #$0F ; Convert Apple-Num to function key + BCS KBDCHKESC ; >'9' +KBDFUNC AND #$0F ; Convert Apple-Num to function key ORA #$80 - BIT BUTTON1 - BPL KBDCHKESC ; Left+Digit -> $8x - ORA #$90 ; Right+Digit -> $9x - BIT BUTTON0 +KBDFUNC2 BIT KBDAPPRGT + BPL KBDCHKESC ; Left+Digit -> $8x + ORA #$90 ; Right+Digit -> $9x + BIT KBDAPPLFT BPL KBDCHKESC - EOR #$30 ; Left+Right+Digit -> $Ax + EOR #$30 ; Left+Right+Digit -> $Ax BRA KBDCHKESC -KBDCTRL AND #$1F ; Apple-Letter -> Ctrl-Letter +KBDCTRL AND #$1F ; Apple-Letter -> Ctrl-Letter * -* Test for Escape key -KBDCHKESC TAX ; X=keycode - EOR FXESCCHAR ; Current ESCAPE char? - ORA FXESCON ; Is ESCAPE an ASCII char? - BNE KBDNOESC ; Not ESCAPE or ESCAPE=ASCII - LDA FX200VAR ; Is ESCAPE ignored? - LSR A ; Check bit 0 - BCS KBDDONE ; ESCAPE completely ignored +* Test for Escape character +KBDCHKESC TAX ; X=keycode + EOR FXESCCHAR ; Current ESCAPE char? + ORA FXESCON ; Is ESCAPE an ASCII char? + BNE KBDNOESC ; Not ESCAPE or ESCAPE=ASCII + LDA FX200VAR ; Is ESCAPE ignored? + LSR A ; Check bit 0 + BCS KBDDONE ; ESCAPE completely ignored SEC - ROR ESCFLAG ; Set Escape flag -KBDNOESC TXA ; A=keycode - CLC ; CLC=Ok + ROR ESCFLAG ; Set Escape flag +KBDNOESC TXA ; A=keycode + CLC ; CLC=Ok KBDDONE RTS + +* Poll the keyboard to update Escape state +* On exit, MI=Escape state pending +* A,X,Y=preserved +* +ESCPOLL PHA ; KBDTEST corrupts A + BIT SETV ; Set V + JSR KBDTEST ; VS - test keyboard + BCS ESCPOLL9 ; No keypress pending + PHX ; KBDREAD corrupts A,X + JSR KBDREAD2 ; Read key and check for Escape + PLX +ESCPOLL9 PLA + BIT ESCFLAG ; Return with Escape state + RTS + * Process pending Escape state -BYTE7E LDX #$00 ; $7E = ack detection of ESC +BYTE7E LDX #$00 ; $7E = ack detection of ESC BIT ESCFLAG - BPL BYTE7DOK ; No Escape pending - LDA FXESCEFFECT ; Process Escape effects + BPL BYTE7DOK ; No Escape pending + LDA FXESCEFFECT ; Process Escape effects BEQ BYTE7E2 - STX FXLINES ; Clear scroll counter - JSR CMDEXEC0 ; Close any EXEC file -* JSR FLUSHALL ; Flush all buffers -BYTE7E2 LDX #$FF ; X=$FF, Escape was pending -BYTE7C CLC ; &7C = clear escape condition -BYTE7D ROR ESCFLAG ; $7D = set escape condition + CLI ; Allow IRQs while flushing + STX FXLINES ; Clear scroll counter + JSR CMDEXEC0 ; Close any EXEC file +* JSR BUFFLUSHALL ; Flush all buffers +BYTE7E2 LDX #$FF ; X=$FF, Escape was pending +BYTE7C CLC ; &7C = clear escape condition +BYTE7D ROR ESCFLAG ; $7D = set escape condition BYTE7DOK RTS -BYTE76 LDX #$00 ; Update LEDs and return X=SHIFT - RTS ; Not possible with Apple +BYTE76 LDX #$00 ; Update LEDs and return X=SHIFT + RTS ; Not possible with Apple + diff --git a/buffer.s b/buffer.s new file mode 100644 index 0000000..5042c10 --- /dev/null +++ b/buffer.s @@ -0,0 +1,288 @@ +* BUFFER.S +* Buffer handling code + + +* Code to call buffer handlers +* ============================ + +* Flush buffer - to do +* ==================== +BUFFLUSHALL RTS +BUFFLUSH RTS + +* Attempt to insert byte in buffer, waiting until done or aborted +* =============================================================== +* On entry, X=buffer number +* A=byte to insert +* On exit, CC=Successful +* CS=Aborted with Escape +* +BUFINSERT PHP +BUFINSERTLP SEI ; Disable interrupts + JSR JMPINSV ; Attempt to insert byte + BCC BUFINSERTOK ; If successful exit + JSR ESCPOLL ; We have a foreground keyboard + ; so we have to poll the hardware + BMI BUFINSERTBAD ; Escape pending, so abort with CS + CLI ; Allow interrupts for a few cycles + BPL BUFINSERTLP ; And loop around and try again +BUFINSERTOK PLP ; Restore IRQs + CLC ; CC=Ok + RTS +BUFINSERTBAD PLP ; Restore IRQs + SEC ; CS=Aborted + RTS + +* OSBYTE &99 - Put byte in buffer checking for Escape +* =================================================== +* On entry, X =buffer number +* Y =character to be written +* On exit, If not Escape character +* X =preserved +* Y =corrupted +* CS=buffer full, couldn't insert +* CC=buffer wasn't full, insertion successful +* If Escape character +* X =corrupted +* Y =corrupted +* +BYTE99 TYA ; A character to write + EOR FXESCCHAR ; Is it current Escape character + ORA FXESCON ; And is it ASCII or Escape + BNE BYTE8A ; If Escape is ASCII or not Escape, insert it + LDA FX200VAR ; Is Escape ignored? + ROR A ; Move bit 0 into Carry to test it + BCS BYTE99A ; Escape completely ignored, exit + JSR BYTE7D ; Set pending Escape +BYTE99A CLC ; Exit with CLC + RTS + +* OSBYTE &8E - Insert byte in buffer +* ================================== +* On entry, X =buffer number +* Y =byte to be written +* On exit, X =preserved +* A =preserved +* Y =corrupted +* CS=buffer full, couldn't insert +* CC=buffer wasn't full, insertion successful +* +BYTE8A TYA ; A=character to enter +JMPINSV JMP (INSV) ; Pass on to buffer handler + +* OSBYTE &91 - Get byte from Buffer +* ================================= +* On entry, X =buffer number +* On exit, X =preserved +* CS=buffer empty +* Y corrupted +* CC=buffer not empty +* Y=byte from buffer +* +BYTE91 CLV ; Clear V + BVC JMPREMV ; Pass on to buffer handler + +* OSBYTE &9A - Examine Buffer +* =========================== +* On entry, X =buffer number +* On exit, X =preserved +* CS=buffer empty +* Y corrupted +* CC=buffer not empty +* Y=byte at top of buffer +* +BYTE9A BIT SETV ; Set V +JMPREMV JMP (REMV) ; Pass on to buffer handler + + +* Buffer handling code, called by INSV, REMV, CNPV +* ================================================ + +* Location and sizes of buffers +* ----------------------------- +BUF4 EQU $0340 +BUF4SZ EQU 16 +BUF5 EQU $0350 +BUF5SZ EQU 16 +BUF6 EQU $0360 +BUF6SZ EQU 16 +BUF7 EQU $0370 +BUF7SZ EQU 16 +BUF3 EQU $0380 +BUF3SZ EQU 64 +BUFBASE EQU $03C0 ; Base of buffer workspace +BUF0 EQU $03E0 +BUF0SZ EQU 32 +BUF2 EQU $0C00 ; Also transient program area +BUF2SZ EQU 192 +BUF8 EQU $0CC0 ; Also transient program area +BUF8SZ EQU 64 +BUF1 EQU $0D00 ; Also transient program area +BUF1SZ EQU 256 + + +* The buffers are arranged so that an offset of &FF is the last entry, and +* incrementing to &00 passes the end of the buffer. A buffer is empty when +* BUFINP=BUFOUT, and is full when BUFINP+1=BUFOUT. + +* BUFFER ADDRESS LOW BYTE LOOKUP TABLE +* ------------------------------------ +* start+len +BUFLO DB (BUF0 + BUF0SZ - 256) AND 255 ; keyboard + DB (BUF1 + BUF1SZ - 256) AND 255 ; serial input + DB (BUF2 + BUF2SZ - 256) AND 255 ; serial output + DB (BUF3 + BUF3SZ - 256) AND 255 ; printer + DB (BUF4 + BUF4SZ - 256) AND 255 ; sound 0 + DB (BUF5 + BUF5SZ - 256) AND 255 ; sound 1 + DB (BUF6 + BUF6SZ - 256) AND 255 ; sound 2 + DB (BUF7 + BUF7SZ - 256) AND 255 ; sound 3 + DB (BUF8 + BUF8SZ - 256) AND 255 ; speech + +* BUFFER ADDRESS HIGH BYTE LOOKUP TABLE +* ------------------------------------- +* start+len +BUFHI DB (BUF0 + BUF0SZ - 256) DIV 256 ; keyboard + DB (BUF1 + BUF1SZ - 256) DIV 256 ; serial input + DB (BUF2 + BUF2SZ - 256) DIV 256 ; serial output + DB (BUF3 + BUF3SZ - 256) DIV 256 ; printer + DB (BUF4 + BUF4SZ - 256) DIV 256 ; sound 0 + DB (BUF5 + BUF5SZ - 256) DIV 256 ; sound 1 + DB (BUF6 + BUF6SZ - 256) DIV 256 ; sound 2 + DB (BUF7 + BUF7SZ - 256) DIV 256 ; sound 3 + DB (BUF8 + BUF8SZ - 256) DIV 256 ; speech + +* BUFFER START ADDRESS OFFSET +* --------------------------- +* len +BUFOFF DB 256-BUF0SZ + DB 256-BUF1SZ + DB 256-BUF2SZ + DB 256-BUF3SZ + DB 256-BUF4SZ + DB 256-BUF5SZ + DB 256-BUF6SZ + DB 256-BUF7SZ + DB 256-BUF8SZ + +BUFNUM EQU BUFHI-BUFLO ; Number of buffers +BUFFLG EQU BUFBASE+0*BUFNUM ; Buffer flags +BUFINP EQU BUFBASE+1*BUFNUM ; Input pointers +BUFOUT EQU BUFBASE+2*BUFNUM ; Output pointers + + +* Get buffer base address +* ----------------------- +* On entry, X=buffer number (not checked) +* On exit, (OSINTWS)=>buffer base +BUFADDR LDA BUFLO,X + STA OSINTWS+0 ; Get buffer base address low + LDA BUFHI,X + STA OSINTWS+1 ; Get buffer base address high + RTS + + +* REMV buffer remove +* ================== +* On entry, X =buffer number +* VS=examine buffer +* VC=remove from buffer +* On exit, X =preserved +* CS=buffer empty +* A,Y corrupted +* CC=buffer not empty +* A=Y=byte from buffer +* If called to remove from buffer, pointers updated +* +BUFREM PHP ; Save flags + SEI ; Disable IRQs + CPX #BUFNUM ; Valid buffer number? + BCS BUFFAIL ; No, return 'empty' + LDA BUFOUT,X ; Get output pointer for buffer X + CMP BUFINP,X ; Compare it to input pointer + BEQ BUFFAIL ; Equal, so buffer is empty + TAY ; Y=output pointer + JSR BUFADDR ; Get buffer base address + LDA (OSINTWS),Y ; Get byte from buffer + BVS BUFREM2 ; If VS, just examine buffer, return + INY ; Otherwise, update buffer pointer + BNE BUFREM1 ; Not zero, not reached end of buffer + LDY BUFOFF,X ; Get offset to start of buffer +BUFREM1 STY BUFOUT,X ; Update the buffer output pointer +BUFREM2 TAY ; Return A=Y=byte from buffer +BUFREMOK PLP ; Restore IRQs + CLC ; CLC=success + RTS + + +* INSV buffer insert +* ================== +* On entry, X =buffer number +* A =byte to be inserted +* On exit, X =preserved +* A =preserved +* Y =corrupted +* CS=buffer full, couldn't insert +* CC=buffer wasn't full, insertion successful +* +BUFINS PHP ; Save flags + SEI ; Disable IRQs + CPX #BUFNUM ; Valid buffer number? + BCS BUFINS2 ; No, sink it and return 'ok' + PHA ; Save A + LDY BUFINP,X ; Get buffer input pointer + INY ; Otherwise, update buffer pointer + BNE BUFINS1 ; Not zero, not reached end of buffer + LDY BUFOFF,X ; Get offset to start of buffer +BUFINS1 TYA ; A=updated input pointer + CMP BUFOUT,X ; Compare with output pointer + BEQ BUFINS4 ; Same, buffer is full, exit with 'failed' + LDY BUFINP,X ; Get unupdated input pointer back + STA BUFINP,X ; Store updated input pointer + JSR BUFADDR ; Get buffer base address + PLA ; Get the byte back + STA (OSINTWS),Y ; And store it in buffer +BUFINS2 PLP ; Restore IRQs + CLC ; CLC=success + RTS +BUFINS4 PLA ; Restore A +BUFFAIL PLP ; Restore IRQs + SEC ; SEC=failed + RTS + + +* CNPV count/purge buffer +* ======================= +* On entry, X =buffer number +* VC=purge (clear) buffer +* VS=count buffer +* CC=count used space +* CS=count free space +* On exit, XY=size counted +* A =corrupted +* +BUFCNP CPX #BUFNUM ; Valid buffer number? + BCS BUFCNP1 ; No, ignore it + BVC BUFCNT1 ; VS, count buffer + LDA BUFOUT,X ; Set input=output, empty buffer + STA BUFINP,X +BUFCNP1 BVS BUFCNT5 ; Purged, exit + LDX #$00 + BEQ BUFCNT4 ; Count, return zero + +BUFCNT1 PHP ; Save flags + SEI ; Disable IRQs + SEC ; Prepare for SBC + LDA BUFOUT,X ; Get output pointer + SBC BUFINP,X ; Subtract input pointer + BCS BUFCNT2 ; No overflow, use it + SEC ; Prepare for SBC + SBC BUFOFF,X ; Subtract buffer start offset +BUFCNT2 PLP ; Get flags back, also restore IRQs + BCC BUFCNT3 ; CLC, exit with size counted + CLC ; Prepare for ADC + ADC BUFOFF,X ; Add buffer offset to get NEG(bytes free) + EOR #$FF ; Invert it to get free space +BUFCNT3 TAX ; YX=count +BUFCNT4 LDY #$00 ; All our buffers are <256 bytes +BUFCNT5 RTS + diff --git a/tests/ENVIRON#060e00 b/tests/ENVIRON#060e00 new file mode 100644 index 0000000..91d0d19 Binary files /dev/null and b/tests/ENVIRON#060e00 differ diff --git a/tests/KBDTEST#060e00 b/tests/KBDTEST#060e00 new file mode 100644 index 0000000..8799bb9 Binary files /dev/null and b/tests/KBDTEST#060e00 differ diff --git a/tests/SNOWFLAKES#060e00 b/tests/SNOWFLAKES#060e00 new file mode 100644 index 0000000..bf81184 Binary files /dev/null and b/tests/SNOWFLAKES#060e00 differ diff --git a/tests/TINY65#000000 b/tests/TINY65#000000 new file mode 100644 index 0000000..325b143 Binary files /dev/null and b/tests/TINY65#000000 differ