Resurrecting this thread, to try to make this "easier" to from BASIC/BASLOAD and verify working in R47...
EDIT: it is working now with R47 and the System ROM built in BASLOAD! however, there is a fundamental limit to how many keys at the same time that can be detected. It may be a PS/2 interface limitation, or also just a limitation of your particular keyboard. Generally it is between 3-6 keys, but the combination of keys supported isn't well known or consistent across devices. Anyway, this works, but "YMMV" !
Here is the BASLOAD code that should initialize this new handler, and the handler itself to set the key flags in a region of "golden RAM":
Code: Select all
REM VOIDSTAR - JUNE 2024
REM
REM USING GOLDEN RAM $0400-$07FF AS FOLLOWS:
REM $0400 INTERNAL PROGRAM DATA
REM $0500 NEW KBD HANDLER ROUTINE
REM $0600 KEY SCANCODE COMPARISON TABLE
REM $0700 PROGRAM TO INSTALL THE NEW KBD HANDLER
REM ************************************************
REM SETUP: PREPARE THE KBD HANDLER, ITS INSTALLER, AND INVOKE IT
REM OPTIONAL: TRY TO MAKE THE PROGRAM RE-RUNNABLE BY DETECTING
REM IF THE KBD HANDLER WAS ALREADY INSTALLED ONCE BEFORE...
A=PEEK($0400) : REM IF ALREADY INSTALLED, THIS WILL EQUAL THE ORIGINAL KBD HANDLER ADDR.
B=PEEK($0401)
C=PEEK($032E) : REM IF ALREADY INSTALLEd, THIS WILL EQUAL THE NEW KBD HANDLER ADDR.
D=PEEK($032F)
IF (A=$A6) AND (B=$D1) AND (C=$00) AND (D=$05) GOTO SKIP.INSTALL
REM PREPARE SUPPORTING DATA-STRUCTURE REGION
RESTORE BLOB0400
ADDR.BLOB=$0400
GOSUB LOADBLOB
REM PATCH IN THE ACTUAL KBD HANDLER ROUTINE
RESTORE BLOB0500
ADDR.BLOB=$0500
GOSUB LOADBLOB
REM DEFINE SET OF SCAN CODES THAT WE CARE ABOUT (WILL BE USER DEFINED)
RESTORE BLOB0600
ADDR.BLOB=$0600
GOSUB LOADBLOB
REM PREPARE AN "INSTALLER" OF THE KBD HANDLER ROUTINE
RESTORE BLOB0700
ADDR.BLOB=$0700
GOSUB LOADBLOB
REM INVOKE THE INSTALLER OF THE KBD HANDLER
REM WARNING: THIS HANDLER REMAINS IN EFFECT UNTIL SYSTEM RESTARTED
REM (SINCE WE STORE THE ORIGINAL HANDLER ADDR AT $0400, WE COULD UNINSTALL
REM THE CUSTOMER HANDLER)
SYS $0700
PRINT "KBD HANDLER INSTALLED!"
GOTO START.TEST
SKIP.INSTALL:
PRINT "KBD HANDLER (PROBABLY) ALREAD INSTALLED!"
START.TEST:
REM OPTIONAL TEST PROGRAM. EVEN IF YOU "NEW" OR LOAD A NEW PROGRAM,
REM THE KBD HANDLER REMAINS IN EFFECT (UNTIL UNLOADED OR SYSTEM RESET)
GOTO TEST.KBD
END
REM ************************************************
REM ************************************************
TEST.KBD:
KBD$="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
CLS
TEST.KBD.STARTOVER:
KEYS$=""
LOCATE 1,1
I=$0404
TEST.KBD.CHECKNEXT:
A=PEEK(I)
IF A > 0 THEN KEYS$ = KEYS$+MID$(KBD$,I-$0404+1,1)
I=I+1
REM STOP AT BASE ($0404) + 36 (OR HOWEVER MANY SCANCODES SUPPORTED)
IF I >= $0428 THEN GOTO SHOWKEYS
GOTO TEST.KBD.CHECKNEXT
SHOWKEYS:
X=LEN(KEYS$)
IF X < 39 THEN KEYS$=KEYS$+" ":GOTO SHOWKEYS
PRINT KEYS$;
GOTO TEST.KBD.STARTOVER
END
REM ************************************************
REM RE-USABLE "FUNCTION" TO LOAD DATA VALUES AS MACHINE CODE SEQUENCES
LOADBLOB:
PRINT "LOADING ",HEX$(ADDR.BLOB)," ";
BYTES.READ=0
LOADBLOBNEXT:
READ DV
BYTES.READ=BYTES.READ+1
PRINT HEX$(DV);
IF DV = 999 THEN PRINT" DONE (";BYTES.READ;")":RETURN
POKE ADDR.BLOB,DV
ADDR.BLOB=ADDR.BLOB+1
GOTO LOADBLOBNEXT
REM ************************************************
REM ************************************************
REM PROGRAM DATA STORAGE
REM ----
BLOB0400:REM DATA BUFFER
DATA $00:REM 0400 ORIGINAL KBD ISR ADDR
DATA $00:REM 0401 ORIGINAL KBD ISR ADDR+1
DATA $00:REM 0402 SCAN KEY COPY KEY_SCANCODE
DATA $00:REM 0403 FLAG STATUS (0 OR 1) KEY_CARRY_FS
DATA $00:REM 0404 KEY STATUS TABLE (100 BYTES RESERVED, ONLY 36 USED)
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
DATA 999
REM ************************************************
REM USER KBD HANDLER ROUTINE. THIS IS "INLINE" TO THE ORIGINAL SYSTEM ISR,
REM AND IS CALLED AUTOMATICALLY WITH REG.A SET TO THE KEY. THE HIGH BIT
REM OF THAT KEY TELLS WHETHER THE KEY IS PRESSED DOWN OR UP.
REM ----
BLOB0500:REM EXPECTED TO BE LOADED INTO $0500
DATA $DA :REM $0500 PHX ; PUSH X REGISTER TO STACK
DATA $48 :REM $0501 PHA ; PUSH A REGISTER TO STACK
DATA $30,$08 :REM $0502 BMI $050C ; check Carry Flag Status
REM KEY_FS_CLEAR:
DATA $A9,$01 :REM $0504 LDA #$01
DATA $8D,$03,$04:REM $0506 STA $0403 ; fs = flag status
DATA $4C,$11,$05:REM $0509 JMP $0511
REM KEY_FS_SET
DATA $A9,$00 :REM $050C LDA #$00
DATA $8D,$03,$04:REM $050E STA $0403
REM KEY_LOOP_1
REM (NOTE: WE COULD PLACE THE STA $0403 ONCE...)
DATA $68 :REM $0511 PLA ; PULL A FROM STACK
DATA $48 :REM $0512 PHA ; PUSH A REGISTER TO STACK
DATA $29,$7F :REM $0513 AND #$7F ; clear the 7bit (negative)
DATA $8D,$02,$04:REM $0515 STA $0402 ; store modified copy of A (high bit cleared)
DATA $A2,$00 :REM $0518 LDX #$00 ; start at beginning of table
REM KEY_LOOP_NEX
DATA $AD,$02,$04:REM $051A LDA $0402 ; LDA KEY_SCANCODE
DATA $DD,$00,$06:REM $051D CMP $0600,X ; CMP KBD_SCANCODE,X
DATA $D0,$09 :REM $0520 BNE $052B ; BNE KEY_LOOP_3 (is regA == this scancode?)
DATA $AD,$03,$04:REM $0522 LDA $0403 ; LDA KEY_CARRY_FS
DATA $9D,$04,$04:REM $0525 STA $0404,X ; STA KBD_SSTATUS,X
DATA $4C,$30,$05:REM $0528 JMP $0530 ; JMP key_loop_end
REM KEY_LOOP_INC
DATA $E8 :REM $052B INX ; index to next table entry
DATA $E0,$24 :REM $052C CPX #$24 ; did reach table end? (#$53 WAS ORIG. FOR 83 KEY TABLE)
DATA $D0,$EA :REM $052E BNE $051A ; BNE KEY_LOOP_NEX
REM KEY_LOOP_END
DATA $68 :REM $0530 PLA ; PULL A FROM STACK
DATA $FA :REM $0531 PLX ; PULL X FROM STACK
DATA $60 :REM $0532 RTS
DATA 999 :REM END OF THIS BLOB OF CODE
REM ************************************************
REM ************************************************
REM REFER TO IBM KEYNUMBERS DEFINED HERE:
REM https://github.com/X16Community/x16-rom/blob/master/inc/keycode.inc
REM SEE ALSO:
REM https://www.nirsoft.net/utils/keyboard_state_view.html
REM ----
BLOB0600:REM KEY TABLES
REM NOTE: WE COULD JUST PUT ALL 126 KEYS IN HERE, BUT IT IS BETTER
REM TO JUST PUT ONLY THE KEYS YOU NEED FOR YOUR APPLICATION - BECAUSE
REM YOU WANT THE ISR TO BE BRIEF/SHORT RUNTIME, AND YOUR APPLICATION
REM WILL HAVE TO SCAN THE RESULT TABLE TO ACTAULLY CHECK THE CLEAR/SET FLAG
REM SO YOU DON'T WANT THAT UNNECESSARILY SLOW EITHER.
DATA $1F :REM Key ( A ) ( Array Index 0 )
DATA $32 :REM Key ( B ) ( Array Index 1 )
DATA $30 :REM Key ( C ) ( Array Index 2 )
DATA $21 :REM Key ( D ) ( Array Index 3 )
DATA $13 :REM Key ( E ) ( Array Index 4 )
DATA $22 :REM Key ( F ) ( Array Index 5 )
DATA $23 :REM Key ( G ) ( Array Index 6 )
DATA $24 :REM Key ( H ) ( Array Index 7 )
DATA $18 :REM Key ( I ) ( Array Index 8 )
DATA $25 :REM Key ( J ) ( Array Index 9 )
DATA $26 :REM Key ( K ) ( Array Index 10 )
DATA $27 :REM Key ( L ) ( Array Index 11 )
DATA $34 :REM Key ( M ) ( Array Index 12 )
DATA $33 :REM Key ( N ) ( Array Index 13 )
DATA $19 :REM Key ( O ) ( Array Index 14 )
DATA $1A :REM Key ( P ) ( Array Index 15 )
DATA $11 :REM Key ( Q ) ( Array Index 16 )
DATA $14 :REM Key ( R ) ( Array Index 17 )
DATA $20 :REM Key ( S ) ( Array Index 18 )
DATA $15 :REM Key ( T ) ( Array Index 19 )
DATA $17 :REM Key ( U ) ( Array Index 20 )
DATA $31 :REM Key ( V ) ( Array Index 21 )
DATA $12 :REM Key ( W ) ( Array Index 22 )
DATA $2F :REM Key ( X ) ( Array Index 23 )
DATA $16 :REM Key ( Y ) ( Array Index 24 )
DATA $2E :REM Key ( Z ) ( Array Index 25 )
DATA $0B :REM Key ( 0 ) ( Array Index 26 )
DATA $02 :REM Key ( 1 ) ( Array Index 27 )
DATA $03 :REM Key ( 2 ) ( Array Index 28 )
DATA $04 :REM Key ( 3 ) ( Array Index 29 )
DATA $05 :REM Key ( 4 ) ( Array Index 30 )
DATA $06 :REM Key ( 5 ) ( Array Index 31 )
DATA $07 :REM Key ( 6 ) ( Array Index 32 )
DATA $08 :REM Key ( 7 ) ( Array Index 33 )
DATA $09 :REM Key ( 8 ) ( Array Index 34 )
DATA $0A :REM Key ( 9 ) ( Array Index 35 )
DATA 999
REM ************************************************
REM ----
REM THIS IS A BRIEF SET OF CODE TO INSTALL THE KBD HANDLER. WE HAVE
REM TO WRITE THE NEW KBD HANDLER ADDRESS INTO $032E/$032F. NOTE, WE
REM STORE THE ORIGINAL KBD HANDLER INTO $0400 - THIS ISN'T VITAL, BUT
REM SUPPORTS A KEY TO "UNINSTALL" OUR CUSTOM HANDLER (BY REVERTING $032E/$032F
REM BACK TO THAT STORED VALUE), IF WE WANT TO HAVE A NICE EXIT FROM
REM OUR APPLICATION.
REM ---
BLOB0700:
:REM ; SAVE ADDRESS OF THE CURRENT INTERRUPT HANDLER (WILL THEN BE REFERRED TO AS "THE PRIOR" ISR)
DATA $AD,$2E,$03:REM LDA $032E LDA IRQVECTOR (standard ROM kbd handler)
DATA $8D,$00,$04:REM STA $0400 STA PRIOR_IRQ
DATA $AD,$2F,$03:REM LDA $032F LDA IRQVECTOR+1
DATA $8D,$01,$04:REM STA $0401 STA PRIOR_IRQ+1
:REM ; INSERT "MY_ISR" AS NEW INTERRUPT HANDLER
DATA $78 :REM SEI ; DISABLE INTERRUPTS
DATA $A9,$00 :REM LDA #$00 ; WRITE LO ADDRESS OF CUSTOM INTERRUPT MY_ISR
DATA $8D,$2E,$03:REM STA $032E STA KBDIRQVECTOR
DATA $A9,$05 :REM LDA #$05 ; Write HI ADDRESS OF CUSTOM INTERRUPT MY_ISR
DATA $8D,$2F,$03:REM STA $032F STA KBDIRQVECTOR+1
DATA $58 :REM CLI ; ENABLE INTERRUPTS
:REM ; PROCEED WITH APPLICATION... (ISR IS NOW ACTIVE)
DATA $60 :REM RETURN TO BASIC (FROM SYS CALL)
DATA 999 :REM END OF THIS BLOB OF CODE
Below is what loading and running the BASLOAD portion looks like. You can run it independently from your own BASIC code after the kbd_handler is installed, or this version includes a how-to-use example also, to show how you can package it all as a single BASL file. So if you just RUN, then start pressing multiple keys and it will show which ones are being pressed. Try combinations of letters A-Z and numbers 0-9.
CTRL+C to stop the program, or CTRL+R to just reset if you're in the emulator.