* AUXMEM.CHARIO.S * (c) Bobbi 2021,2022 GPLv3 * * AppleMOS Character I/O * KERNEL/CHARIO.S ***************** * Character read and write * * 14-Aug-2021 Flashing cursor and INKEY sync'd to frame rate * 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. * 17-Aug-2021 OSBYTE 4 for cursors, OSBYTE 221-228 for topbit * keys. * 21-Aug-2021 FIXED: If screen scrolls, copy cursor ends on * wrong line. * FIXED: KBDREAD has several paths that don't * test ESCHAR. * FIXED: INKEY doesn't restore cursor on timeout. * The three separate cursors can be set seperately. * 02-Sep-2021 INKEY-256 tests Apple IIe vs IIc. * 05-Sep-2021 KBDINIT returns startup value to pass to VDUINT. * 09-Sep-2021 Moved keyboard OSBYTEs to here. * 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. * 15-Oct-2022 Replace calling KBDCHKESC with ESCPOLL, does translations, etc. * Fixed bug with cursor keys after *FX4,2. OSRDCH enables IRQs. * 23-Oct-2022 Escape: BYTE7E needed to ESCPOLL, INKEYESC unbalanced stack. * 03-Nov-2022 Escape: Fixed INKEY loop failing if entering with previous Escape, * combined with EscAck clearing keyboard. * 06-Dec-2022 Moved *KEY into here. * 12-Dec-2022 Test code to write *KEY data to mainmem. * 24-Dec-2022 Minor bit of tidying. * 26-Dec-2022 Integrated ADB extended keyboard keys. * 27-Dec-2022 Bobbi's keyboard uses $60+n extended keys. * 30-Dec-2022 Optimised *KEY, US KBD Alt-Ctrl-2, Alt-Ctrl-6 -> f2/f6. * 03-Jan-2023 Wrote BYTE76 to return CTRL/SHIFT state for text pausing. * 07-Jan-2023 Updated KBDREAD to use BYTE76. * 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 KBDMOD EQU $C025 ; AppleIIgs modifier keys IOVBLNK EQU $C019 ; VBLNK pulse FLASHER EQU BYTEVARBASE+176 ; VSync counter for flashing cursor FXEXEC EQU BYTEVARBASE+198 ; *EXEC handle FXSPOOL EQU BYTEVARBASE+199 ; *SPOOL handle FXKBDSTATE EQU BYTEVARBASE+202 ; Keyboard modifier state FXTABCHAR EQU BYTEVARBASE+219 ; Char for TAB key to return FXESCCHAR EQU BYTEVARBASE+220 ; Char to match as Escape key FXKEYBASE EQU BYTEVARBASE+221 ; Base of char &80+ translations FXKEYPADBASE EQU BYTEVARBASE+238 ; Base of keypad keys FXESCON EQU BYTEVARBASE+229 ; Escape key is ASC or ESC FXESCEFFECT EQU BYTEVARBASE+230 ; Actions when Escape acknowledged FX200VAR EQU BYTEVARBASE+200 ; Completely ignore CHR$(escape) FX254VAR EQU BYTEVARBASE+254 ; Keyboard map FXSOFTLEN EQU BYTEVARBASE+216 ; Length of current soft key FXSOFTOFF EQU BYTEVARBASE+233 ; Offset to current soft key FXSOFTOK EQU BYTEVARBASE+244 ; Soft keys not unstable FX2VAR EQU BYTEVARBASE+$B1 ; Input stream FX3VAR EQU BYTEVARBASE+$EC ; Output streams FX4VAR EQU BYTEVARBASE+$ED ; Cursor key state * FKEYLENS defined in mainmem.misc.s ; Length of soft key definitions * FKEYBUF defined in mainmem.misc.s ; Base of soft key definitions * OSWRCH handler **************** * Send a character to current output * All registers preserved * WRCHHND PHA PHX PHY PHA * TO DO Check any output redirections * TO DO Check any printer output JSR OUTCHAR ; Send to VDU driver * BCC WRCHHND3 ; VDU driver says skip printer * PLA ; Get character back * PHA * JSR PRNCHAR ; Send to printer * WRCHHND3 * 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 character to spool file WRCHHND4 PLA ; Drop stacked character PLY ; Restore everything PLX PLA RTS * 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 DEFBYTEEND KBDINIT LDX #DEFBYTEEND-DEFBYTE-1 :KBDINITLP LDA DEFBYTE,X ; Initialise KBD OSBYTE variables STA BYTEVARBASE+DEFBYTELOW,X DEX BPL :KBDINITLP LDA #$80 ; Keypad keys are function keys STA FXKEYPADBASE JSR SOFTKEYCHK ; Clear soft keys LDX #$C3 ; Default KBD=RISC OS, MODE=3 STX FX254VAR ; b7-b4=default KBD map, b3-b0=default MODE * LDX #$03 ; Default MODE=3 (map already <$C0 by startup) BIT SETV ; Set V JSR KBDTEST ; Test if key being pressed BCS :KBDINITOK ; Return default MODE STA KBDACK ; Ack. keypress TAX ; Use keypress as default MODE :KBDINITOK TXA RTS * OSRDCH/INKEY handler ********************** * 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 PHY TAY BRA INKEYGO ; Wait forever for input * XY<$8000 - wait for a keypress 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 LDA CURSORED JSR SHOWWTCURSOR ; Show write cursor JSR COPYSWAP1 ; Swap to copy cursor INKEYGO2 JSR GETCHRC ; Get character under cursor STA OLDCHAR BRA INKEY1 ; Turn cursor on INKEYLP CLC LDA #$01 ; Slow flash, every 32 frames BIT VDUSTATUS BVC INKEY0 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 BIT FLASHER BPL INKEY1 ; Do not remove cursor JSR REMRDCURSOR ; Remove read cursor BRA INKEY3 INKEY1 LDA CURSOR ; Add cursor BIT VDUSTATUS BVC INKEY2 LDA CURSORCP INKEY2 JSR SHOWRDCURSOR ; Show read cursor INKEY3 LDA #$27 ; Prepare to return CHR$27 if Escape state CLC BIT ESCFLAG ; Check Escape state BMI INKEYESC ; Escape pending, return it with A=27 INKEY4 JSR KEYREAD ; Test for input, all can be trashed PLY 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 INKEY5 DEX PHX INKEY6 PHY * * VBLK pulses at 50Hz/60Hz, toggles at 100Hz/120Hz LDX IOVBLNK ; Get initial VBLK state INKEY8 BIT KBDDATA BMI INKEY4 ; Key pressed TXA EOR IOVBLNK BPL INKEY8 ; Wait for VBLK change BMI INKEYLP ; Loop back to key test INKEYOUT LDA #$FF ; Prepare to stack $FF INKEYESC PLY ; Drop stacked Y 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 REMRDCURSOR ; Remove read cursor JSR COPYSWAP1 ; Swap cursor back LDA COPYCHAR ; Remove main cursor INKEYOFF2 JSR REMWTCURSOR ; Remove write 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 RTS * RDCH Character read: CC, A=char, X=restored, Y=restored * RDCH Escape: CS, A=char, X=restored, Y=restored * INKEY Character read: CC, A=char, X=???, Y<$80 * INKEY Escape: CS, A=char, X=???, Y<$80 * INKEY Timeout: CS, A=???, X=???, Y=$FF BYTE81 TYA 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 TYA BMI BYTE81DONE ; Y=$FF, timeout LDY #$00 BCC BYTE81DONE ; CC, not Escape LDY #$1B ; Y=27 BYTE81DONE RTS * Returns: Y=$FF, X=???, CS - timeout * Y=$1B, X=???, CS - escape * Y=$00, X=char, CC - keypress NEGINKEY CPX #$01 LDX #$00 ; Unimplemented BCS NEGINKEY0 JSR NEGCALL ; Read machine ID from mainmem LDX #$2C TAY 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 NEGINKEY0 LDY #$00 NEGINKEY1 CLC RTS NEGCALL >>> XF2MAIN,MACHRD ; Try to read Machine ID * KERNEL/KEYBOARD.S ******************* * SOFT KEY PROCESSING * =================== OSDECNUM EQU OSTEMP * *SHOW () * ------------- STARSHOW RTS * *KEY * --------------------------- STARKEY LDA FXSOFTLEN BNE ERRKEYUSED ; Key being expanded JSR SCANDEC CMP #$10 BCC STARKEY1 ERRBADKEY BRK DB $FB ASC 'Bad key' ERRKEYUSED BRK DB $FA ASC 'Key in use' BRK * * A slightly fiddly procedure, as we need to check the new * definition is valid before we insert it, we can't bomb * out halfway through inserting a string, and we mustn't * have mainmem paged in while parsing the string as the * string might be "underneath" the memory we've paged in, * we don't know how long the new definition is and if it * will fit into memory until after we've parsed it, so we * either have to store it to a temp area or parse it twice. * * All this, and we need a structure that is reasonably coded, * but with the priority to be easy for KEYREAD to extract * from (as called more often), even if at expense of storing * being more complex. * * Soft key definition layout: * FKEYLENS+n - length of key n * FKEYBUF+n - start of key n where x=SUM(len(0)...len(n-1)) * * SCANDEC stores number in OSDECNUM, so we can keep it there * We also have OSKBDx variables available for shuffling code * NB: OSKBD1, OSKBD2 also hold copy cursor state * STARKEY1 INC FXSOFTOK ; Soft keys unstable PHY ; Y=>command line * PHP ; Read/write main memory SEI ; MACRO-ise this STA WRMAINRAM STA RDMAINRAM * JSR KEYOFFLEN ; X=offset, A=length, CLC STX OSKBD1 ; OSKBD1=offset to old definition STA OSKBD2 ; OSKBD2=old length ADC OSKBD1 ; A=offset to next definition TAY * Remove old definition :LOOP LDA FKEYBUF,Y ; Get byte from next string STA FKEYBUF,X ; Move it down over this string INX INY BNE :LOOP LDX OSDECNUM STZ FKEYLENS,X ; Length=0 LDA #17 JSR KEYOFFLEN ; X=offset to free space * STA RDCARDRAM ; Read/write aux memory STA WRCARDRAM ; MACRO-ise this PLP * STX OSKBD2 PLY JSR SKIPCOMMA SEC JSR GSINIT ; Initialise '*KEY-type string' STARKEYLP1 JSR GSREAD BCS STARKEYEND >>> WRTMAIN ; Write main memory STA FKEYBUF,X ; Store char of definition >>> WRTAUX ; Back to writing aux again INX BNE STARKEYLP1 STARKEYERR JMP ERRBADSTR ; String too long * Should this be ERRBADKEY? STARKEYEND BNE STARKEYERR ; Badly terminated * X=offset to end of new definition * OSDECNUM=key number * OSKBD1=offset to insertion point * OSKBD2=start of new string, holding position * TXA ; SEC from above SBC OSKBD2 ; A=length of new definition BEQ STARKEYDONE ; Zero length, all done LDX OSDECNUM * PHP ; Read/write main memory SEI ; MACRO-ise this STA WRMAINRAM STA RDMAINRAM * STA FKEYLENS,X ; Set new length * * A=length of new string * X=key number * OSKBD1=offset to insertion point * OSKBD2=offset to free space, holding new string * TAX LDA OSKBD2 SEC SBC OSKBD1 TAY ; Y=length between insertion point and free space BEQ STARKEYNONE ; Nothing to move, all done STX OSKBD1 ; OSKBD1=length of new string LDX OSKBD2 ; X=offset to free space, holding new string * * Insert new string STARKEYLP2 PHY PHX LDA FKEYBUF,X ; Shuffle strings up PHA STARKEYLP4 DEX LDA FKEYBUF,X STA FKEYBUF+1,X DEY BNE STARKEYLP4 PLA STA FKEYBUF,X ; Insert new string PLX INX PLY DEC OSKBD1 ; Loop for length of new string BNE STARKEYLP2 STARKEYNONE * STA RDCARDRAM ; Read/write aux memory STA WRCARDRAM ; MACRO-ise this PLP * STARKEYDONE STZ FXSOFTOK ; Soft keys are stable RTS * Get offset and length of key in X * Add lengths of previous definitions together * Assumes mainmen is paged in by caller * On entry: A=key number * On exit X=offset to definition start * A=length of definition * CC always KEYOFFLEN TAX LDA FKEYLENS,X ; Get length of this key PHA LDA #0 CLC ; CLC for addition BCC :ADDUP :KEYLOOP ADC FKEYLENS,X ; Add length of previous key :ADDUP DEX ; Step to previous key BPL :KEYLOOP ; Do until key 0 added TAX ; Return X=offset PLA ; Return A=length RTS * OSBYTE &12 - Clear soft keys * ---------------------------- SOFTKEYCHK LDA FXSOFTOK BEQ BYTE12OK ; Soft keys ok, exit BYTE12 LDX #15 STX FXSOFTOK ; Soft keys being updated >>> WRTMAIN ; Short enough to page for whole loop :L2 STZ FKEYLENS,X ; Zero the lengths DEX BNE :L2 >>> WRTAUX STZ FXSOFTOK ; Soft keys stable BYTE12OK RTS * KEYREAD ************************ * Test for and read from input, * expanding keyboard special keys * * On exit, CS=no keypress * CC=keypress * A =keycode, X,Y=corrupted 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 LDA FXSOFTLEN ; Soft key active? BEQ KEYREAD2 ; No, skip past LDX FXSOFTOFF ; Get offset to current character >>> RDMAIN LDA FKEYBUF,X ; Get it from mainmem >>> RDAUX INC FXSOFTOFF ; Inc. offset DEC FXSOFTLEN ; Dec. counter CLC RTS KEYREAD2 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 KEYSOFTHI ; Not cursor key BCC KEYSOFTY ; Not cursor key LDX FX4VAR BEQ KEYCURSOR ; *FX4,0 - editing keys CPY #$C9 CLV BEQ KEYCOPYTAB ; TAB key DEX BNE KEYSOFTHI ; Not *FX4,1 - soft key SBC #$44 ; Return $88-$8B KEYREADOK1 CLC KEYREADOK RTS * Process soft key KEYSOFTHI LDX FX254VAR CPX #$C0 BCC KEYSOFTY TYA EOR #$40 ; Toggle keyboard map * AND #$BF TAY KEYSOFTY TYA ; Get key including Shift/Ctrl LSR A LSR A LSR A LSR A ; A=key DIV 16 EOR #$04 ; Offset into KEYBASE TAX LDA FXKEYBASE-8,X BEQ KEYNONE ; Value 0 means 'ignore key' DEC A BEQ KEYEXPAND ; Value 1 means 'expand key' TYA AND #$0F CLC ADC FXKEYBASE-8,X CLC RTS * Expand soft key * On entry: Y=key code ($Xn where n is soft key number) KEYEXPAND TYA AND #$0F ; Obtain soft key number >>> RDMAIN JSR KEYOFFLEN ; Get offset and length of key >>> RDAUX STX FXSOFTOFF STA FXSOFTLEN BRA KEYREAD1 ; Go back and start fetching * Process cursor keys KEYCURSOR CMP #$C9 BEQ KEYCOPY PHA LDA OLDCHAR JSR REMRDCURSOR ; Remove read cursor PLA JSR COPYMOVE ; Move copy cursor JSR GETCHRC ; Save char under cursor STA OLDCHAR KEYNONE SEC KBDDONE2 RTS 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 PUTCOPYCURS ; Restore and move read cursor [OFF] JSR GETCHRC ; Save char under cursor STA OLDCHAR PLA BNE KEYREADOK1 ; Ok character SEC JMP BEEP ; Beep and return CS=No char * KBDREAD ************************ * Test for and fetch key from keyboard * Updated for ADB keyboards * * On exit, CS=no keypress * CC=keypress * A =keycode, X=corrupted * Apple+Letter -> Ctrl+Letter * AppleL+digit -> 80+x fkey -> 80+x * AppleR+digit -> 90+x Shift+fkey -> 90+x * AppleLR+digit -> A0+x Ctrl+fkey -> A0+x * TAB -> $C9 Shift+Ctrl+fkey -> B0+x * Cursors -> $CC-$CF * Keypad -> PADBASE+key * KBDREAD CLV ; VC=return keypress KBDTEST LDA KBDDATA ; VS here to test for keypress EOR #$80 ; Toggle bit 7 CMP #$80 BCS KBDDONE2 ; No key pressed BVS KBDDONE2 ; VS=test for keypress STA KBDACK ; Ack. keypress KBDREAD2 PHA JSR BYTE76A ; Check keyboard modifiers BVC KBDREAD5 ; Not keypad PLA ; Get raw keycode back * TAX ; X=raw keypress ** NB: BYTE76A corrupts X ** Set FXKBDSTATE to %x0CS0000 from Alt or Shift keys * LDA KBDAPPRGT ; Right Apple/Alt pressed * ASL A * LDA KBDAPPLFT ; Left Apple/Alt pressed * ROR A ; b7=Right, b6=Left * AND #$C0 * LSR A * LSR A * PHP ; Save EQ=no ALTs pressed * BEQ KBDREAD2A * ADC #$F0 ; Convert into fkey modifer *KBDREAD2A STA FXKBDSTATE * BIT VDUBANK * BPL KBDREAD5 ; Not IIgs * LDA KBDMOD ; Get extended KBD state * PLP * PHP * BNE KBDREAD2B ; ALTs pressed, skip * PHA ; Save b4=Keypad * ASL A * ASL A * ASL A * ASL A ; b5=Ctrl, b4=Shift * AND #$30 * STA FXKBDSTATE * PLA ** *KBDREAD2B AND #$10 * BEQ KBDREAD5 ; Not keypad * PLP ; Drop NoALT * TXA ; A=raw keypress BMI KBDREADPAD ; Translate keypad CMP #$60 BCC KBDREADPAD TAX LDA KBDADBKEYS-$60,X ; Translate $60-$7E keys BRA KBDREAD6 KBDREADPAD LDX FXKEYPADBASE BEQ KBDCHKESC ; $00=use unchanged BPL KBDREAD4 ; Keypad not function keys CMP #$20 BCC KBDCHKESC ; Don't translate control chars CMP #$3D BNE KBDREAD3 ; Special case for KP'=' DEC A KBDREAD3 ORA #$30 ; Ensure $30-$3F KBDREAD4 SEC SBC #$30 ; Convert to offset from $30 CLC ADC FXKEYPADBASE ; Add to keypad base BRA KBDREAD6 * Special-case checks KBDREADX2 LDA #$1A ; Alt-Ctrl-2 -> f2 KBDREADX6 EOR #$98 ; Alt-Ctrl-6 -> f6 BNE KBDFUNC KBDREAD5 LSR A LSR A ; Cy=ALTs pressed PLA ; A=raw keypress BCC KBDNOALT ; No ALTs pressed * TXA ; A=raw keypress * PLP * BEQ KBDNOALT ; No ALTs pressed * KBDALT * TXA BEQ KBDREADX2 ; RAlt-2 CMP #$1E BEQ KBDREADX6 ; RAlt-6 CMP #$40 BCS KBDCTRL ; 'A'+ Alt+letter ->Control code CMP #$30 BCC KBDCHKESC ; <'0' Alt+nondigit -> keep CMP #$3A BCS KBDCHKESC ; >'9' Alt+nondigit -> keep ORA #$80 ; Alt+digit -> function key * KBDREAD6 BPL KBDCHKESC ; Not a top-bit key KBDFUNC AND #$CF ; Clear Ctrl+Shift bits * ORA FXKBDSTATE ; Add in Ctrl+Shift ORA OSKBD3 ; Add in Ctrl+Shift * * Test for Escape character KBDCHKESC TAX ; X=processed 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 KBDDONE RTS * Moved here to reduce BRx ranges KBDCTRL AND #$1F ; Apple-Letter -> Ctrl-Letter BRA KBDCHKESC KBDNOALT CMP #$09 BEQ KBDTAB ; TAB is dual action TAB/COPY CMP #$08 BCC KBDCHKESC ; <$08 not cursor key CMP #$0C BCC KBDCURSR ; $08-$0B are cursor keys CMP #$15 BNE KBDCHKESC ; $15 is cursor key KBDCUR15 LDA #$0D ; Convert RGT to $09 KBDTAB SBC #$04 ; Convert TAB to &C9 KBDCURSR CLC ADC #$C4 ; Cursor keys $C0+x BRA KBDFUNC KBDADBKEYS DB $85,$86,$87,$83,$88,$89,$80,$8B DB $80,$8D,$80,$8E,$80,$8A,$80,$8C DB $80,$8F,$C6,$C8,$CB,$C7,$84,$87 DB $82,$CA,$81,$CC,$CD,$CE,$C4,$7F * Poll the keyboard to update Escape state * On exit, MI=Escape state pending * CC=key pressed, CS=no key pressed * A=character * X,Y=preserved * ESCPOLL 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, returns CC PLX ESCPOLL9 BIT ESCFLAG ; Return with Escape state RTS * Process pending Escape state BYTE7E STA KBDACK ; Flush keyboard LDX #$00 ; $7E = ack detection of ESC BIT ESCFLAG BPL BYTE7DOK ; No Escape pending LDA FXESCEFFECT ; Process Escape effects BEQ BYTE7E2 CLI ; Allow IRQs while flushing STX FXLINES ; Clear scroll counter STX FXSOFTLEN ; Cancel soft key expansion JSR CMDEXEC0 ; Close any EXEC file * JSR BUFFLUSHALL ; Flush all buffers (this should do FXSOFTLEN) BYTE7E2 LDX #$FF ; X=$FF, Escape was pending BYTE7C CLC ; &7C = clear escape condition BYTE7D ROR ESCFLAG ; $7D = set escape condition BYTE7DOK RTS * Update KBDSTATE and return state of SHIFT and CTRL keys * Returns A=X= =%SxxxxEAx * Flags =C=Ctrl, M=Shift, V=Extended key * OSKBD3 =%00CS0000 * FXKBDSTATE=%CSxxxxEA C=Ctrl, S=Shift, E=Extended, A=Apple BYTE76 JSR ESCPOLL CLC BMI BYTE76X ; Escape pending, return M=Shift, C=None BYTE76A LDA KBDAPPRGT ; Right Apple/Alt pressed ASL A LDA KBDAPPLFT ; Left Apple/Alt pressed ROR A ; b7=Right, b6=Left AND #$C0 PHP ; Save EQ=no ALTs pressed BEQ BYTE76C ADC #$C1 ; Convert into fkey modifer, b0=1 BYTE76C STA OSKBD3 BIT VDUBANK BPL BYTE76E ; Not IIgs LDA KBDMOD ; Get extended KBD state ROR A ROR A ROR A ; b7=Ctrl, b6=Shift, b1=Extended AND #$C2 PLP BEQ BYTE76D AND #$02 ; ALTs pressed, just keep Extend BYTE76D ORA OSKBD3 STA OSKBD3 ; Update with Ctrl/Shift/Extend PHP ; Balance stack BYTE76E PLP ; Drop flags, NE=either ALT pressed LSR OSKBD3 ; Adjust for soft key modifier LSR OSKBD3 ; b5=Ctrl, b4=Shift, Cy=Extend CLV ; CLV=Not Extend BCC BYTE76F BIT SETV ; SEV=Extend BYTE76F LSR A ; Test ALT bit in bit 0 BCC BYTE76G ORA #$20 BYTE76G ROL A ; Put bit 0 back STA FXKBDSTATE ASL A ; C=Ctrl, M=Shift TAX ; X.b7=Shift BYTE76X RTS * Call BYTE76 to get state of SHIFT/CTRL to pause/restore scrolling * Left and Right Apple keys simulate SHIFT/CTRL when no KBDMOD register * Returns: M =SHIFT or one APPLE key pressed * C =CTRL pressed * M+C =SHIFT+CTRL pressed or both APPLE keys pressed * Escape will abort and return MI+CC to simulate SHIFT to continue * * Scrolling can pause with: * LOOP: * JSR BYTE76 * BPL EXIT ; SHIFT not pressed * BCS LOOP ; SHIFT+CTRL pressed * EXIT: * * Paged mode can be released with: * LOOP: * JSR BYTE76 * BPL LOOP ; SHIFT not pressed *