From 49cb98d6683155ce176e49965e12cc4d6dcb2e0b Mon Sep 17 00:00:00 2001 From: zohassadar Date: Thu, 26 Sep 2024 20:30:13 +0000 Subject: [PATCH 01/31] More efficient keyboard reading (when more keys are read) --- src/nmi/pollkeyboard.asm | 52 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index 6b2ff80d..f878adae 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -77,22 +77,21 @@ pollKeyboard: @ret: rts ; Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7 -; ] [ RETURN F8 STOP ¥ RSHIFT KANA -; ; : @ F7 ^ - / _ -; K L O F6 0 P , . -; J U I F5 8 9 N M -; H G Y F4 6 7 V B -; D R T F3 4 5 C F -; A S W F2 3 E Z X -; CTR Q ESC F1 2 1 GRPH LSHIFT -; LEFT RIGHT UP CLR HOME INS DEL SPACE DOWN +; ] [ RETURN F8 STOP ¥ RSHIFT KANA +; ; : @ F7 ^ - / _ +; K L O F6 0 P , . +; J U I F5 8 9 N M +; H G Y F4 6 7 V B +; D R T F3 4 5 C F +; A S W F2 3 E Z X +; CTR Q ESC F1 2 1 GRPH LSHIFT +; LEFT RIGHT UP CLR HOME INS DEL SPACE DOWN ; Read keys. up/down/left/right are mapped directly mapKeysToButtons: - ldy #$08 - ldx #$02 + lda #$82 jsr readKey beq @upNotPressed lda newlyPressedKeys @@ -101,8 +100,7 @@ mapKeysToButtons: bne @skipDownRead @upNotPressed: - ldy #$08 - ldx #$07 + lda #$87 jsr readKey beq @downNotPressed lda newlyPressedKeys @@ -111,8 +109,7 @@ mapKeysToButtons: @skipDownRead: @downNotPressed: - ldy #$08 - ldx #$00 + lda #$80 jsr readKey beq @leftNotPressed lda newlyPressedKeys @@ -121,8 +118,7 @@ mapKeysToButtons: bne @skipRightRead @leftNotPressed: - ldy #$08 - ldx #$01 + lda #$81 jsr readKey beq @rightNotPressed lda newlyPressedKeys @@ -131,8 +127,7 @@ mapKeysToButtons: @skipRightRead: @rightNotPressed: - ldy #$07 ; grph -> B - ldx #$06 + lda #$76 ; grph -> B jsr readKey beq @bNotPressed lda newlyPressedKeys @@ -140,8 +135,7 @@ mapKeysToButtons: sta newlyPressedKeys @bNotPressed: - ldy #$08 ; space -> A - ldx #$06 + lda #$86 ; space -> A jsr readKey beq @aNotPressed lda newlyPressedKeys @@ -149,8 +143,7 @@ mapKeysToButtons: sta newlyPressedKeys @aNotPressed: - ldy #$00 ; right shift -> select - ldx #$06 + lda #$06 ; right shift -> select jsr readKey beq @selectNotPressed lda newlyPressedKeys @@ -158,8 +151,7 @@ mapKeysToButtons: sta newlyPressedKeys @selectNotPressed: - ldy #$00 ; return -> start - ldx #$02 + lda #$02 ; return -> start jsr readKey beq @startNotPressed lda newlyPressedKeys @@ -188,7 +180,17 @@ mapKeysToButtons: keyMask: .byte $80,$40,$20,$10,$08,$04,$02,$01 + readKey: + pha + lsr + lsr + lsr + lsr + tay + pla + and #$0F + tax lda keyboardInput,y and keyMask,x rts From 035950bf0ab3c96bb8b65f1e5db5d8764bc9de1b Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 27 Sep 2024 01:06:25 +0000 Subject: [PATCH 02/31] Use family basic keyboard for score name entry --- src/highscores/data.asm | 55 +++++++- src/highscores/entry_screen.asm | 15 ++ src/nmi/pollkeyboard.asm | 233 ++++++++++++++++++++++++++------ src/ram.asm | 11 +- 4 files changed, 262 insertions(+), 52 deletions(-) diff --git a/src/highscores/data.asm b/src/highscores/data.asm index c73575ad..649292cd 100644 --- a/src/highscores/data.asm +++ b/src/highscores/data.asm @@ -1,10 +1,51 @@ highScorePpuAddrTable: - .dbyt $2284,$22C4,$2304 + .dbyt $2284,$22C4,$2304 highScoreCharToTile: - .byte $FF,$0A,$0B,$0C,$0D,$0E,$0F,$10 - .byte $11,$12,$13,$14,$15,$16,$17,$18 - .byte $19,$1A,$1B,$1C,$1D,$1E,$1F,$20 - .byte $21,$22,$23,$00,$01,$02,$03,$04 - .byte $05,$06,$07,$08,$09,$25,$4F,$5E - .byte $5F,$6E,$6F,$52,$55,$24 + .byte $FF ; Space + .byte $0A ; A + .byte $0B ; B + .byte $0C ; C + .byte $0D ; D + .byte $0E ; E + .byte $0F ; F + .byte $10 ; G + .byte $11 ; H + .byte $12 ; I + .byte $13 ; J + .byte $14 ; K + .byte $15 ; L + .byte $16 ; M + .byte $17 ; N + .byte $18 ; O + .byte $19 ; P + .byte $1A ; Q + .byte $1B ; R + .byte $1C ; S + .byte $1D ; T + .byte $1E ; U + .byte $1F ; V + .byte $20 ; W + .byte $21 ; X + .byte $22 ; Y + .byte $23 ; Z + .byte $00 ; 0 + .byte $01 ; 1 + .byte $02 ; 2 + .byte $03 ; 3 + .byte $04 ; 4 + .byte $05 ; 5 + .byte $06 ; 6 + .byte $07 ; 7 + .byte $08 ; 8 + .byte $09 ; 9 + .byte $25 ; , + .byte $4F ; / + .byte $5E ; ( + .byte $5F ; ) + .byte $6E ; <3 + .byte $6F ; . + .byte $52 ; ! + .byte $55 ; ? + .byte $24 ; - + highScoreCharSize := $2E diff --git a/src/highscores/entry_screen.asm b/src/highscores/entry_screen.asm index fad9f22b..9f21deaa 100644 --- a/src/highscores/entry_screen.asm +++ b/src/highscores/entry_screen.asm @@ -176,12 +176,27 @@ highScoreEntryScreen: jmp @ret @checkForAOrRightPressed: + +.if KEYBOARD = 1 + jsr readKbScoreInput + bmi @noKeyboardInput + beq @nextTile + cmp #$7F + beq @prevTile + jmp @waitForVBlank +@noKeyboardInput: + +.endif lda #BUTTON_RIGHT jsr menuThrottle bne @nextTile lda #BUTTON_A jsr menuThrottle beq @checkForBOrLeftPressed +.if KEYBOARD = 1 + lda kbHeldInput ; due to space being mapped to A, skip if space is currently pressed + beq @checkForBOrLeftPressed +.endif @nextTile: lda #$01 sta soundEffectSlot1Init diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index f878adae..fe517e56 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -76,23 +76,10 @@ pollKeyboard: jsr mapKeysToButtons @ret: rts -; Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7 -; ] [ RETURN F8 STOP ¥ RSHIFT KANA -; ; : @ F7 ^ - / _ -; K L O F6 0 P , . -; J U I F5 8 9 N M -; H G Y F4 6 7 V B -; D R T F3 4 5 C F -; A S W F2 3 E Z X -; CTR Q ESC F1 2 1 GRPH LSHIFT -; LEFT RIGHT UP CLR HOME INS DEL SPACE DOWN - -; Read keys. up/down/left/right are mapped directly - mapKeysToButtons: - lda #$82 - jsr readKey + lda keyboardInput+8 + and #$20 beq @upNotPressed lda newlyPressedKeys ora #BUTTON_UP @@ -100,8 +87,8 @@ mapKeysToButtons: bne @skipDownRead @upNotPressed: - lda #$87 - jsr readKey + lda keyboardInput+8 + and #$01 beq @downNotPressed lda newlyPressedKeys ora #BUTTON_DOWN @@ -109,8 +96,8 @@ mapKeysToButtons: @skipDownRead: @downNotPressed: - lda #$80 - jsr readKey + lda keyboardInput+8 + and #$80 beq @leftNotPressed lda newlyPressedKeys ora #BUTTON_LEFT @@ -118,8 +105,8 @@ mapKeysToButtons: bne @skipRightRead @leftNotPressed: - lda #$81 - jsr readKey + lda keyboardInput+8 + and #$40 beq @rightNotPressed lda newlyPressedKeys ora #BUTTON_RIGHT @@ -127,32 +114,32 @@ mapKeysToButtons: @skipRightRead: @rightNotPressed: - lda #$76 ; grph -> B - jsr readKey + lda keyboardInput+7 ; grph -> B + and #$02 beq @bNotPressed lda newlyPressedKeys ora #BUTTON_B sta newlyPressedKeys @bNotPressed: - lda #$86 ; space -> A - jsr readKey + lda keyboardInput+8 ; space -> A + and #$02 beq @aNotPressed lda newlyPressedKeys ora #BUTTON_A sta newlyPressedKeys @aNotPressed: - lda #$06 ; right shift -> select - jsr readKey + lda keyboardInput+0 ; right shift -> select0 + and #$02 beq @selectNotPressed lda newlyPressedKeys ora #BUTTON_SELECT sta newlyPressedKeys @selectNotPressed: - lda #$02 ; return -> start - jsr readKey + lda keyboardInput+0 ; return -> start + and #$20 beq @startNotPressed lda newlyPressedKeys ora #BUTTON_START @@ -178,19 +165,179 @@ mapKeysToButtons: sta heldButtons_player1 rts -keyMask: - .byte $80,$40,$20,$10,$08,$04,$02,$01 +; Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7 +; 0 ] [ RETURN F8 STOP ¥ RSHIFT KANA +; 1 ; : @ F7 ^ - / _ +; 2 K L O F6 0 P , . +; 3 J U I F5 8 9 N M +; 4 H G Y F4 6 7 V B +; 5 D R T F3 4 5 C F +; 6 A S W F2 3 E Z X +; 7 CTR Q ESC F1 2 1 GRPH LSHIFT +; 8 LEFT RIGHT UP CLR HOME INS DEL SPACE DOWN + +shiftFlag := $08 +charToKbMap: + .byte $86 ; Space + .byte $60 ; A + .byte $47 ; B + .byte $56 ; C + .byte $50 ; D + .byte $65 ; E + .byte $57 ; F + .byte $41 ; G + .byte $40 ; H + .byte $32 ; I + .byte $30 ; J + .byte $20 ; K + .byte $21 ; L + .byte $37 ; M + .byte $36 ; N + .byte $22 ; O + .byte $25 ; P + .byte $71 ; Q + .byte $51 ; R + .byte $61 ; S + .byte $52 ; T + .byte $31 ; U + .byte $46 ; V + .byte $62 ; W + .byte $67 ; X + .byte $42 ; Y + .byte $66 ; Z + .byte $24 ; 0 + .byte $75 ; 1 + .byte $74 ; 2 + .byte $64 ; 3 + .byte $54 ; 4 + .byte $55 ; 5 + .byte $44 ; 6 + .byte $45 ; 7 + .byte $34 ; 8 + .byte $35 ; 9 + .byte $26 ; , + .byte $16 ; / + .byte $01 ; ( + .byte $00 ; ) + .byte $07 ; <3 + .byte $27 ; . + .byte $75 | shiftFlag ; ! + .byte $16 | shiftFlag ; ? + .byte $15 ; - + .byte $85 ; del ; treated differently + +charToKbMapEnd: + +kbChars = <(charToKbMapEnd - charToKbMap) - 1 +kbInputThrottle := generalCounter4 + +readKbScoreInput: +; n - no input or throttled +; z - ready to shift +; 7F - backspace +; new char otherwise + +; check if shift flag is set + lda kbShiftFlag ; 1 when ready to shift + beq @noShift + dec kbShiftFlag + beq @noBackspace + dec kbShiftFlag + lda #$7F +@noBackspace: + rts + +@noShift: + ldx #kbChars + +@checkNextChar: + lda charToKbMap,x + jsr readKey + bne @keyPressed + dex + bpl @checkNextChar + stx kbHeldInput + +@noKeyPressed: +; n flag set due to heldInput no keys byte or active throttle + rts + +@keyPressed: + cpx kbHeldInput + bne @newInput + + inc kbInputThrottle + bne @noKeyPressed + + lda #-4 + bne @storeThrottle + +@newInput: + stx kbHeldInput + lda #-16 + +@storeThrottle: + sta kbInputThrottle + +@placeInput: + lda highScoreEntryNameOffsetForLetter + clc + adc highScoreEntryNameOffsetForRow + tay + txa + cmp #kbChars + bne @notBackspace + lda #$00 + inc kbShiftFlag ; +1 to indicate backspace +@notBackspace: + sta highscores,y +.if SAVE_HIGHSCORES + tax + jsr detectSRAM + beq @noSRAM + txa + sta SRAM_highscores,y +@noSRAM: +.endif +; causes next frame to trigger shift ; clears z & n flags + inc kbShiftFlag + rts + +shiftCounter := generalCounter5 readKey: - pha - lsr - lsr - lsr - lsr - tay - pla - and #$0F - tax - lda keyboardInput,y - and keyMask,x - rts +; RRRRSCCC - Row, Shift, Column + pha + lsr + lsr + lsr + lsr + tay + pla + pha + and #$07 + sta shiftCounter + pla + and #$08 + beq @checkInput + +; left shift + lda keyboardInput+7 + and #$01 + bne @checkInput + +; right shift + lda keyboardInput+0 + and #$02 + beq @ret + +@checkInput: + lda keyboardInput,y +@shiftLoop: + asl + dec shiftCounter + bpl @shiftLoop + lda #$00 + rol +@ret: + rts diff --git a/src/ram.asm b/src/ram.asm index f021f206..f817c589 100755 --- a/src/ram.asm +++ b/src/ram.asm @@ -221,14 +221,21 @@ invisibleFlag: .res 1 ; $63B ; 0 for normal mode, non-zero for Invisible playfi currentFloor: .res 1 ; $63C floorModifier is copied here at game init. Set to 0 otherwise and incremented when linecap floor. mapperId: .res 1 ; $63D ; For INES_MAPPER 1000 (autodetect). 0 = CNROM. 1 = MMC1. - .res $37 + .res $35 .if KEYBOARD +; used for high score entry to throttle input and to flag when a letter has been input +kbShiftFlag: .res 1 ; $0673 +kbHeldInput: .res 1 ; $0674 + +; controller equivalent, can possibly be removed newlyPressedKeys: .res 1 ; $0675 heldKeys: .res 1 ; $0676 + +; raw input from keyboard keyboardInput: .res 9 ; $0677 .else - .res $B + .res $D .endif musicStagingSq1Lo: .res 1 ; $0680 From 45909bfdb247b11c3990e8409e87d6b99438175d Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 27 Sep 2024 01:09:10 +0000 Subject: [PATCH 03/31] replace space --- src/highscores/data.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/highscores/data.asm b/src/highscores/data.asm index 649292cd..7a1ceeb6 100644 --- a/src/highscores/data.asm +++ b/src/highscores/data.asm @@ -1,5 +1,5 @@ highScorePpuAddrTable: - .dbyt $2284,$22C4,$2304 + .dbyt $2284,$22C4,$2304 highScoreCharToTile: .byte $FF ; Space .byte $0A ; A From ae72c504fb41c412f87c6fe82889fe2bd974f0c1 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 27 Sep 2024 02:22:20 +0000 Subject: [PATCH 04/31] Delay before first row --- src/nmi/pollkeyboard.asm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index fe517e56..8e33d8fe 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -45,6 +45,7 @@ pollKeyboard: stx newlyPressedKeys lda #KB_INIT sta JOY1 + jsr @ret ; wait 12 cycles before first row @rowLoop: lda #KB_COL_0 sta JOY1 From 95c9e4017cfaef6c9a8bbf2e26b83b9f89cf661a Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 27 Sep 2024 03:14:39 +0000 Subject: [PATCH 05/31] wait before column 1 --- src/nmi/pollkeyboard.asm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index 8e33d8fe..c18fdea9 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -39,6 +39,12 @@ ; Note that Family BASIC never writes to $4016 with bit 2 clear, there is no need to disable the keyboard matrix. +kbReadWait: + ldy #$09 +@avoidParasiticCapacitance: ; wait approx 50 cycles after advancing rows + dey + bne @avoidParasiticCapacitance + rts pollKeyboard: ldx #$00 @@ -49,15 +55,13 @@ pollKeyboard: @rowLoop: lda #KB_COL_0 sta JOY1 - ldy #$0A -@avoidParasiticCapacitance: ; wait approx 50 cycles after advancing rows - dey - bne @avoidParasiticCapacitance + jsr kbReadWait lda JOY2_APUFC and #KB_MASK sta generalCounter lda #KB_COL_1 sta JOY1 + jsr kbReadWait lda JOY2_APUFC and #KB_MASK lsr From f1c76b80c3576636804b312c2ff5bfaef45a4ade Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 27 Sep 2024 03:23:48 +0000 Subject: [PATCH 06/31] save 5 cycles in wait loop and still be >50 --- src/nmi/pollkeyboard.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index c18fdea9..8dc9df6e 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -40,7 +40,7 @@ ; Note that Family BASIC never writes to $4016 with bit 2 clear, there is no need to disable the keyboard matrix. kbReadWait: - ldy #$09 + ldy #$08 @avoidParasiticCapacitance: ; wait approx 50 cycles after advancing rows dey bne @avoidParasiticCapacitance From d940c770309e9a4403bbb48e2661d968ed2e1942 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 25 Aug 2025 02:03:15 +0000 Subject: [PATCH 07/31] better mapping --- src/nmi/pollkeyboard.asm | 65 +++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index 8dc9df6e..1ab471e8 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -82,9 +82,30 @@ pollKeyboard: @ret: rts +; Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7 +; 0 ] [ RETURN F8 STOP ¥ RSHIFT KANA +; 1 ; : @ F7 ^ - / _ +; 2 K L O F6 0 P , . +; 3 J U I F5 8 9 N M +; 4 H G Y F4 6 7 V B +; 5 D R T F3 4 5 C F +; 6 A S W F2 3 E Z X +; 7 CTR Q ESC F1 2 1 GRPH LSHIFT +; 8 LEFT RIGHT UP CLR HOME INS DEL SPACE DOWN + +kbUp = $0820 +kbDown = $0801 +kbLeft = $0880 +kbRight = $0840 +kbB = $0702 ; grph -> B +kbA = $0802 ; space -> A +kbSelect = $0002 ; right shift -> select0 +kbStart = $0020 ; return -> start + + mapKeysToButtons: - lda keyboardInput+8 - and #$20 + lda keyboardInput+>kbUp + and #kbDown + and #kbLeft + and #kbRight + and # B - and #$02 + lda keyboardInput+>kbB + and # A - and #$02 + lda keyboardInput+>kbA + and # select0 - and #$02 + lda keyboardInput+>kbSelect + and # start - and #$20 + lda keyboardInput+>kbStart + and # Date: Mon, 25 Aug 2025 03:23:31 +0000 Subject: [PATCH 08/31] preferred keybindings --- src/nmi/pollkeyboard.asm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index 1ab471e8..9c5f9f57 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -93,14 +93,14 @@ pollKeyboard: ; 7 CTR Q ESC F1 2 1 GRPH LSHIFT ; 8 LEFT RIGHT UP CLR HOME INS DEL SPACE DOWN -kbUp = $0820 -kbDown = $0801 -kbLeft = $0880 -kbRight = $0840 -kbB = $0702 ; grph -> B -kbA = $0802 ; space -> A -kbSelect = $0002 ; right shift -> select0 -kbStart = $0020 ; return -> start +kbUp = $0280 ; k +kbDown = $0380 ; j +kbLeft = $0480 ; h +kbRight = $0240 ; l +kbB = $0580 ; d +kbA = $0501 ; f +kbSelect = $0701 ; lshift +kbStart = $0020 ; return mapKeysToButtons: From 02da1ca71dd08ce9123a5dbb4237e92f8ab4bf75 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 25 Aug 2025 14:14:38 +0000 Subject: [PATCH 09/31] read keyboard after nmi wait --- src/nmi/nmi.asm | 4 ---- src/util/core.asm | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nmi/nmi.asm b/src/nmi/nmi.asm index d0dfca0a..612f61fb 100644 --- a/src/nmi/nmi.asm +++ b/src/nmi/nmi.asm @@ -28,10 +28,6 @@ nmi: pha jsr pollControllerButtons lda #$00 sta lagState ; clear flag after lag frame achieved -.if KEYBOARD -; Read Family BASIC Keyboard - jsr pollKeyboard -.endif lda #$01 sta verticalBlankingInterval pla diff --git a/src/util/core.asm b/src/util/core.asm index 9204e1fd..72282e10 100755 --- a/src/util/core.asm +++ b/src/util/core.asm @@ -65,6 +65,10 @@ updateAudioWaitForNmiAndResetOamStaging: lda verticalBlankingInterval beq @checkForNmi +.if KEYBOARD +; Read Family BASIC Keyboard + jsr pollKeyboard +.endif resetOAMStaging: ; Hide a sprite by moving it down offscreen, by writing any values between #$EF-#$FF here. ; Sprites are never displayed on the first line of the picture, and it is impossible to place From aed681ebc3e042b628c6bf0087cad66d0bc02e63 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 25 Aug 2025 14:16:49 +0000 Subject: [PATCH 10/31] map only start during high score entry --- src/gamemodestate/handlegameover.asm | 2 ++ src/nmi/pollkeyboard.asm | 3 +++ src/ram.asm | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gamemodestate/handlegameover.asm b/src/gamemodestate/handlegameover.asm index ae1288d4..7effd963 100644 --- a/src/gamemodestate/handlegameover.asm +++ b/src/gamemodestate/handlegameover.asm @@ -17,7 +17,9 @@ gameModeState_handleGameOver: @gameOver: lda #$03 sta renderMode + inc entryActive jsr handleHighScoreIfNecessary + dec entryActive lda #$01 sta playState lda #$EF diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index 9c5f9f57..afcc8d97 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -104,6 +104,8 @@ kbStart = $0020 ; return mapKeysToButtons: + lda entryActive + bne @startOnly lda keyboardInput+>kbUp and #kbStart and # Date: Mon, 25 Aug 2025 14:31:24 +0000 Subject: [PATCH 11/31] no longer applicable --- src/highscores/entry_screen.asm | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/highscores/entry_screen.asm b/src/highscores/entry_screen.asm index 9f21deaa..238f00c1 100644 --- a/src/highscores/entry_screen.asm +++ b/src/highscores/entry_screen.asm @@ -193,10 +193,6 @@ highScoreEntryScreen: lda #BUTTON_A jsr menuThrottle beq @checkForBOrLeftPressed -.if KEYBOARD = 1 - lda kbHeldInput ; due to space being mapped to A, skip if space is currently pressed - beq @checkForBOrLeftPressed -.endif @nextTile: lda #$01 sta soundEffectSlot1Init From d312cc2a05e8caf42b2d04057843a2b7c2dd844c Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 25 Aug 2025 14:34:07 +0000 Subject: [PATCH 12/31] add note & build flag for var --- src/gamemodestate/handlegameover.asm | 4 ++++ src/ram.asm | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gamemodestate/handlegameover.asm b/src/gamemodestate/handlegameover.asm index 7effd963..9f725f4d 100644 --- a/src/gamemodestate/handlegameover.asm +++ b/src/gamemodestate/handlegameover.asm @@ -17,9 +17,13 @@ gameModeState_handleGameOver: @gameOver: lda #$03 sta renderMode +.if KEYBOARD = 1 inc entryActive jsr handleHighScoreIfNecessary dec entryActive +.else + jsr handleHighScoreIfNecessary +.endif lda #$01 sta playState lda #$EF diff --git a/src/ram.asm b/src/ram.asm index 83c736b4..ea4d0ae9 100755 --- a/src/ram.asm +++ b/src/ram.asm @@ -221,7 +221,7 @@ invisibleFlag: .res 1 ; $63B ; 0 for normal mode, non-zero for Invisible playfi currentFloor: .res 1 ; $63C floorModifier is copied here at game init. Set to 0 otherwise and incremented when linecap floor. mapperId: .res 1 ; $63D ; For INES_MAPPER 1000 (autodetect). 0 = CNROM. 1 = MMC1. -entryActive: .res 1 +entryActive: .res 1 ; todo: find better way to track high score entry screen .res $34 .if KEYBOARD From c3b4e9c2aa711b7cfc475d6f84474b527181fd65 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 29 Aug 2025 15:51:25 +0000 Subject: [PATCH 13/31] fix b-type crash when using keyboard code --- src/gamemodestate/initstate.asm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gamemodestate/initstate.asm b/src/gamemodestate/initstate.asm index dfd59d17..5bda81a6 100755 --- a/src/gamemodestate/initstate.asm +++ b/src/gamemodestate/initstate.asm @@ -299,7 +299,16 @@ L8824: ldx #rng_seed tay lda #EMPTY_TILE sta playfield,y +.if KEYBOARD = 1 + ; this can probably be the same whether keyboard or not. + ; the keyboard code adds the keyboard reading right before the oam staging reset. + ; the additional keyboard reading cycles causes the b type setup to crash. + ; Using the wait routine that skips the oam staging reset (and keyboard read) for now and + ; keeping separate until b-type board test is developed. + jsr updateAudioAndWaitForNmi +.else jsr updateAudioWaitForNmiAndResetOamStaging +.endif dec generalCounter bne L87E7 L884A: From da59823db71218b87bf1a6ccb94d0648c0587d2a Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 22 Sep 2025 18:31:01 +0000 Subject: [PATCH 14/31] add mapping for every key & macro to use them --- src/nmi/keyboardmap.asm | 109 +++++++++++++++++++++++++++++++++++++++ src/nmi/pollkeyboard.asm | 91 ++++++++++++++++---------------- 2 files changed, 154 insertions(+), 46 deletions(-) create mode 100644 src/nmi/keyboardmap.asm diff --git a/src/nmi/keyboardmap.asm b/src/nmi/keyboardmap.asm new file mode 100644 index 00000000..ac36952a --- /dev/null +++ b/src/nmi/keyboardmap.asm @@ -0,0 +1,109 @@ +; Assisted with the following python: +; kbmap = """ +; CloseBracket OpenBracket RETURN F8 STOP Yen SHIFTRight KANA +; Semicolon Colon atSign F7 Caret Dash Slash Underscore +; K L O F6 0 P Comma Period +; J U I F5 8 9 N M +; H G Y F4 6 7 V B +; D R T F3 4 5 C F +; A S W F2 3 E Z X +; CTR Q ESC F1 2 1 GRPH SHIFTLeft +; Left Right UP CLR_HOME INS DEL Space Down +; """ +; for row, keys in enumerate(kbmap.strip().splitlines()): +; for mask, key in enumerate(keys.split()): +; mask = 0x80 >> mask +; print(f"key{key:<12} = ${row:02x}{mask:02x}") + + +; 2 bytes to represent each key +; hi byte is an index into keyboardInput and represents row +; lo byte is a bitmask to single out key's bit +; result is not zero if key pressed + +.macro readKeyDirect keyMap + lda keyboardInput+>keyMap + and #kbUp - and #kbDown - and #kbLeft - and #kbRight - and #kbB - and #kbA - and #kbSelect - and #kbStart - and # Date: Tue, 23 Sep 2025 16:12:55 +0000 Subject: [PATCH 15/31] untested revamp of everything --- src/nmi/keyboardmap.asm | 168 ++++++++-------- src/nmi/pollkeyboard.asm | 407 +++++++++++++++++++++------------------ src/ram.asm | 2 +- 3 files changed, 312 insertions(+), 265 deletions(-) diff --git a/src/nmi/keyboardmap.asm b/src/nmi/keyboardmap.asm index ac36952a..442e5928 100644 --- a/src/nmi/keyboardmap.asm +++ b/src/nmi/keyboardmap.asm @@ -12,98 +12,104 @@ ; """ ; for row, keys in enumerate(kbmap.strip().splitlines()): ; for mask, key in enumerate(keys.split()): -; mask = 0x80 >> mask -; print(f"key{key:<12} = ${row:02x}{mask:02x}") +; print(f"key{key:<12} = ${((8 - row) << 3) | mask:02X}") +.macro readKeyDirect keyMap + lda keyboardInput + (keyMap >> 3) + and #$80 >> (keyMap & 7) +.endmacro -; 2 bytes to represent each key -; hi byte is an index into keyboardInput and represents row -; lo byte is a bitmask to single out key's bit -; result is not zero if key pressed +.macro expandKeyRow keyMap + .byte keyMap >> 3 +.endmacro -.macro readKeyDirect keyMap - lda keyboardInput+>keyMap - and #> (keyMap & 7) .endmacro -keyF1 = $0710 -keyF2 = $0610 -keyF3 = $0510 -keyF4 = $0410 -keyF5 = $0310 -keyF6 = $0210 -keyF7 = $0110 -keyF8 = $0010 -keyStop = $0008 -keyReturn = $0020 +; each key is represented by a byte 0RRRRCCC +; row is 0-8 and is inverted +; col is byte position from left to right + +keyF1 = $0B +keyF2 = $13 +keyF3 = $1B +keyF4 = $23 +keyF5 = $2B +keyF6 = $33 +keyF7 = $3B +keyF8 = $43 + +keyStop = $44 +keyReturn = $42 -keyShiftRight = $0002 -keyShiftLeft = $0701 +keyShiftRight = $46 +keyShiftLeft = $0F -keyESC = $0720 -keyCTR = $0780 -keyGRPH = $0702 +keyESC = $0A +keyCTR = $08 +keyGRPH = $0E -keyCLR_HOME = $0810 -keyINS = $0808 -keyDEL = $0804 +keyCLR_HOME = $03 +keyINS = $04 +keyDEL = $05 -keyUp = $0820 -keyLeft = $0880 -keyRight = $0840 -keyDown = $0801 +keyUp = $02 +keyLeft = $00 +keyRight = $01 +keyDown = $07 -keyCloseBracket = $0080 ; ] -keyOpenBracket = $0040 ; [ -keyYen = $0004 ; ¥ -keySemicolon = $0180 ; ; -keyColon = $0140 ; : -keyatSign = $0120 ; @ -keyCaret = $0108 ; ^ -keySlash = $0102 ; / -keyUnderscore = $0101 ; _ -keyComma = $0202 ; , -keyPeriod = $0201 ; . -keyDash = $0104 ; - -keyKana = $0001 +keyCloseBracket = $40 ; ] +keyOpenBracket = $41 ; [ +keyYen = $45 ; ¥ +keySemicolon = $38 ; ; +keyColon = $39 ; : +keyatSign = $3A ; @ +keyCaret = $3C ; ^ +keySlash = $3E ; / +keyUnderscore = $3F ; _ +keyComma = $36 ; , +keyPeriod = $37 ; . +keyDash = $3D ; - +keyKana = $47 -keySpace = $0802 +keySpace = $06 -key0 = $0208 -key1 = $0704 -key2 = $0708 -key3 = $0608 -key4 = $0508 -key5 = $0504 -key6 = $0408 -key7 = $0404 -key8 = $0308 -key9 = $0304 +key0 = $34 +key1 = $0D +key2 = $0C +key3 = $14 +key4 = $1C +key5 = $1D +key6 = $24 +key7 = $25 +key8 = $2C +key9 = $2D -keyA = $0680 -keyB = $0401 -keyC = $0502 -keyD = $0580 -keyE = $0604 -keyF = $0501 -keyG = $0440 -keyH = $0480 -keyI = $0320 -keyJ = $0380 -keyK = $0280 -keyL = $0240 -keyM = $0301 -keyN = $0302 -keyO = $0220 -keyP = $0204 -keyQ = $0740 -keyR = $0540 -keyS = $0640 -keyT = $0520 -keyU = $0340 -keyV = $0402 -keyW = $0620 -keyX = $0601 -keyY = $0420 -keyZ = $0602 +keyA = $10 +keyB = $27 +keyC = $1E +keyD = $18 +keyE = $15 +keyF = $1F +keyG = $21 +keyH = $20 +keyI = $2A +keyJ = $28 +keyK = $30 +keyL = $31 +keyM = $2F +keyN = $2E +keyO = $32 +keyP = $35 +keyQ = $09 +keyR = $19 +keyS = $11 +keyT = $1A +keyU = $29 +keyV = $26 +keyW = $12 +keyX = $17 +keyY = $22 +keyZ = $16 diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index d850561f..ffb15b58 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -52,122 +52,103 @@ kbMappedStart = keyReturn ; Note that Family BASIC never writes to $4016 with bit 2 clear, there is no need to disable the keyboard matrix. -kbReadWait: - ldy #$08 -@avoidParasiticCapacitance: ; wait approx 50 cycles after advancing rows - dey - bne @avoidParasiticCapacitance - rts pollKeyboard: - ldx #$00 - stx newlyPressedKeys +@kbTmp1 = generalCounter +@upDown = BUTTON_UP|BUTTON_DOWN +@leftRight = BUTTON_LEFT|BUTTON_RIGHT + + lda #KB_INIT sta JOY1 - jsr @ret ; wait 12 cycles before first row + + ; wait 12 cycles before first row + lda #$00 + sta newlyPressedKeys + ldx #8 + nop + nop + nop @rowLoop: - lda #KB_COL_0 - sta JOY1 - jsr kbReadWait - lda JOY2_APUFC - and #KB_MASK - sta generalCounter - lda #KB_COL_1 - sta JOY1 - jsr kbReadWait + ; start first column read + ldy #KB_COL_0 + sty JOY1 + + ldy #6 + jsr @keyboardReadWait lda JOY2_APUFC + + ; start second column read + ldy #KB_COL_1 + sty JOY1 + + ; make good use of wait time and #KB_MASK - lsr - sta keyboardInput,x - lda generalCounter asl asl asl - ora keyboardInput,x - eor #$FF - cmp #$FF - beq @ret ; Assume 8 simultaneously pressed keys means there's no keyboard to be read - sta keyboardInput,x - inx - cpx #$09 - bne @rowLoop - jsr mapKeysToButtons -@ret: rts + beq @ret ; assume 4 simultaneously pressed keys in one row indicates no keyboard + sta @kbTmp1 + ldy #3 + jsr @keyboardReadWait + lda JOY2_APUFC -mapKeysToButtons: - lda entryActive - ; ignore all keys except for start/return during high score entry - bne @readStart - - readKeyDirect kbMappedUp - beq @upNotPressed - lda newlyPressedKeys - ora #BUTTON_UP - sta newlyPressedKeys - bne @downNotPressed ; skip down read if up is pressed -@upNotPressed: - - readKeyDirect kbMappedDown - beq @downNotPressed - lda newlyPressedKeys - ora #BUTTON_DOWN - sta newlyPressedKeys -@downNotPressed: - - readKeyDirect kbMappedLeft - beq @leftNotPressed - lda newlyPressedKeys - ora #BUTTON_LEFT - sta newlyPressedKeys - bne @rightNotPressed ; skip right read if left is pressed -@leftNotPressed: - - readKeyDirect kbMappedRight - beq @rightNotPressed - lda newlyPressedKeys - ora #BUTTON_RIGHT - sta newlyPressedKeys -@rightNotPressed: + and #KB_MASK + lsr + ora @kbTmp1 + eor #$FF + sta keyboardInput,x + dex + bpl @rowLoop - readKeyDirect kbMappedB - beq @bNotPressed - lda newlyPressedKeys - ora #BUTTON_B +; map keys to buttons + lda #$00 sta newlyPressedKeys -@bNotPressed: + ldx #7 - readKeyDirect kbMappedA - beq @aNotPressed - lda newlyPressedKeys - ora #BUTTON_A - sta newlyPressedKeys -@aNotPressed: +; build a byte that looks like controller input +@readKeyLoop: + clc + ldy @mappedRows,x + and @mappedMasks,x + beq @notPressed + sec +@notPressed: + rol newlyPressedKeys + dex + bpl @readKeyLoop - readKeyDirect kbMappedSelect - beq @readStart +; prevent SOCD (Simultaneous Opposite Cardinal Direction + ldx #$01 +@antiSocd: lda newlyPressedKeys - ora #BUTTON_SELECT + and @antiSocdMatch,x + cmp @antiSocdMatch,x + bne @noMatch + eor #$FF + and newlyPressedKeys sta newlyPressedKeys -@readStart: +@noMatch: + dex + bpl @antiSocd - readKeyDirect kbMappedStart - beq @startNotPressed +; determine which are new lda newlyPressedKeys - ora #BUTTON_START - sta newlyPressedKeys -@startNotPressed: +; ignore everything except start during score entry + ldy entryActive + beq @entryNotActive + and #BUTTON_START +@entryNotActive: -; Separate Newly Pressed from Held - lda newlyPressedKeys tay eor heldKeys and newlyPressedKeys sta newlyPressedKeys sty heldKeys -; Copy to buttons +; Copy to controller buttons lda newlyPressedButtons_player1 ora newlyPressedKeys sta newlyPressedButtons_player1 @@ -175,8 +156,37 @@ mapKeysToButtons: lda heldButtons_player1 ora heldKeys sta heldButtons_player1 +@ret: rts + +@keyboardReadWait: + ; consumes (y * 5) + 16 + dey + bpl @keyboardReadWait rts +@antiSocdMatch: + .byte @upDown,@leftRight + +@mappedRows: + expandKeyRow kbMappedRight + expandKeyRow kbMappedLeft + expandKeyRow kbMappedDown + expandKeyRow kbMappedUp + expandKeyRow kbMappedStart + expandKeyRow kbMappedSelect + expandKeyRow kbMappedB + expandKeyRow kbMappedA +@mappedMasks: + expandKeyMask kbMappedRight + expandKeyMask kbMappedLeft + expandKeyMask kbMappedDown + expandKeyMask kbMappedUp + expandKeyMask kbMappedStart + expandKeyMask kbMappedSelect + expandKeyMask kbMappedB + expandKeyMask kbMappedA + + ; Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7 ; 0 ] [ RETURN F8 STOP ¥ RSHIFT KANA ; 1 ; : @ F7 ^ - / _ @@ -191,79 +201,94 @@ mapKeysToButtons: ; each byte represents row, column and if shift should be read ; only keys supported by the score entry routine are included -shiftFlag = $08 charToKbMap: - .byte $86 ; Space - .byte $60 ; A - .byte $47 ; B - .byte $56 ; C - .byte $50 ; D - .byte $65 ; E - .byte $57 ; F - .byte $41 ; G - .byte $40 ; H - .byte $32 ; I - .byte $30 ; J - .byte $20 ; K - .byte $21 ; L - .byte $37 ; M - .byte $36 ; N - .byte $22 ; O - .byte $25 ; P - .byte $71 ; Q - .byte $51 ; R - .byte $61 ; S - .byte $52 ; T - .byte $31 ; U - .byte $46 ; V - .byte $62 ; W - .byte $67 ; X - .byte $42 ; Y - .byte $66 ; Z - .byte $24 ; 0 - .byte $75 ; 1 - .byte $74 ; 2 - .byte $64 ; 3 - .byte $54 ; 4 - .byte $55 ; 5 - .byte $44 ; 6 - .byte $45 ; 7 - .byte $34 ; 8 - .byte $35 ; 9 - .byte $26 ; , - .byte $16 ; / - .byte $01 ; ( - .byte $00 ; ) - .byte $07 ; <3 - .byte $27 ; . - .byte $75 | shiftFlag ; ! - .byte $16 | shiftFlag ; ? - .byte $15 ; - - .byte $85 ; del ; treated differently - ; future feature: read left and right to shift cursor position - + .byte keySpace + .byte keyA + .byte keyB + .byte keyC + .byte keyD + .byte keyE + .byte keyF + .byte keyG + .byte keyH + .byte keyI + .byte keyJ + .byte keyK + .byte keyL + .byte keyM + .byte keyN + .byte keyO + .byte keyP + .byte keyQ + .byte keyR + .byte keyS + .byte keyT + .byte keyU + .byte keyV + .byte keyW + .byte keyX + .byte keyY + .byte keyZ + .byte key0 + .byte key1 + .byte key2 + .byte key3 + .byte key4 + .byte key5 + .byte key6 + .byte key7 + .byte key8 + .byte key9 + .byte keyComma + .byte keySlash + .byte keyOpenBracket + .byte keyCloseBracket + .byte keyKana ; <3 + .byte keyPeriod + .byte key1 | $80 ; ! + .byte keySlash | $80 ; ? + .byte keyDash + ; treated differently + .byte keyRight + .byte keyLeft + .byte keyDEL charToKbMapEnd: -kbChars = <(charToKbMapEnd - charToKbMap) - 1 +kbChars = <(charToKbMapEnd - charToKbMap) - 1 +kbScoreDelete = kbChars +kbScoreLeft = kbChars - 1 +kbScoreRight = kbChars - 2 + kbInputThrottle := generalCounter4 readKbScoreInput: -; n - no input or throttled -; z - ready to shift -; 7F - backspace -; new char otherwise +; 2 frames to complete action +; first reads key, determines action and stores key (unless key is action only) +; second returns cursor action + +; return values +; >$80 - do nothing (flag) +; $00 - move cursor right (flag) +; $7F - move cursor left +; default action is to set render flags for new letter + +; kbReadState set in frame 1 for action in frame 2 +; 0 - read input +; 1 - signal cursor right +; 2 - signal cursor left ; check if shift flag is set - lda kbShiftFlag ; 1 when ready to shift - beq @noShift - dec kbShiftFlag - beq @noBackspace - dec kbShiftFlag + lda kbReadState + beq @readScoreInput + dec kbReadState + beq @signalRight + dec kbReadState ; reset to 0 + ; signal left lda #$7F -@noBackspace: +@signalRight: rts -@noShift: +@readScoreInput: ldx #kbChars @checkNextChar: @@ -301,59 +326,75 @@ readKbScoreInput: adc highScoreEntryNameOffsetForRow tay txa - cmp #kbChars - bne @notBackspace + + cmp #kbScoreDelete + beq @delete + + cmp #kbScoreLeft + bne @checkRight + + inc kbReadState + bne @signalCursorShift + +@checkRight: + cmp #kbScoreRight + beq @signalCursorShift + +@delete: lda #$00 - inc kbShiftFlag ; +1 to indicate backspace -@notBackspace: + inc kbReadState ; +1 to indicate backspace +@normal: sta highscores,y .if SAVE_HIGHSCORES tax jsr detectSRAM - beq @noSRAM + beq @signalCursorShift txa sta SRAM_highscores,y -@noSRAM: +@signalCursorShift: .endif -; causes next frame to trigger shift ; clears z & n flags - inc kbShiftFlag + inc kbReadState rts -shiftCounter := generalCounter5 readKey: -; RRRRSCCC - Row, Shift, Column - pha - lsr +; clobbers y & generalCounter5 + +@readKeyMask := generalCounter5 +; SRRRRCCC - Shift, Row, Column + php ; store shift (negative) flag + pha ; store byte + +; extract mask + and #07 + tay + lda @readKeyMasks,y + sta @readKeyMask + +; extract row index + pla lsr lsr lsr + and $0F tay - pla - pha - and #$07 - sta shiftCounter - pla - and #$08 - beq @checkInput -; left shift - lda keyboardInput+7 - and #$01 - bne @checkInput +; determine if char is shifted + plp + bpl @readKey -; right shift - lda keyboardInput+0 - and #$02 +; if so, read both shift keys + readKeyDirect keyShiftLeft + bne @readKey + + readKeyDirect keyShiftRight beq @ret -@checkInput: +@readKey: lda keyboardInput,y -@shiftLoop: - asl - dec shiftCounter - bpl @shiftLoop - lda #$00 - rol + and @readKeyMask @ret: rts + +@readKeyMasks: + .byte $80,$40,$20,$10,$08,$04,$02,$01 diff --git a/src/ram.asm b/src/ram.asm index ea4d0ae9..6b444861 100755 --- a/src/ram.asm +++ b/src/ram.asm @@ -226,7 +226,7 @@ entryActive: .res 1 ; todo: find better way to track high score entry screen .if KEYBOARD ; used for high score entry to throttle input and to flag when a letter has been input -kbShiftFlag: .res 1 ; $0673 +kbReadState: .res 1 ; $0673 kbHeldInput: .res 1 ; $0674 ; controller equivalent, can possibly be removed From 55e4e4434ffb99b4dfa364a6ecd5055bb9d5e1f6 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 23 Sep 2025 21:36:29 +0000 Subject: [PATCH 16/31] fix bugs after testing --- src/nmi/pollkeyboard.asm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index ffb15b58..0d0a276a 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -54,7 +54,6 @@ kbMappedStart = keyReturn pollKeyboard: -@kbTmp1 = generalCounter @upDown = BUTTON_UP|BUTTON_DOWN @leftRight = BUTTON_LEFT|BUTTON_RIGHT @@ -88,7 +87,7 @@ pollKeyboard: asl asl beq @ret ; assume 4 simultaneously pressed keys in one row indicates no keyboard - sta @kbTmp1 + sta generalCounter ldy #3 jsr @keyboardReadWait @@ -96,7 +95,7 @@ pollKeyboard: and #KB_MASK lsr - ora @kbTmp1 + ora generalCounter eor #$FF sta keyboardInput,x dex @@ -111,6 +110,7 @@ pollKeyboard: @readKeyLoop: clc ldy @mappedRows,x + lda keyboardInput,y and @mappedMasks,x beq @notPressed sec @@ -339,6 +339,7 @@ readKbScoreInput: @checkRight: cmp #kbScoreRight beq @signalCursorShift + bne @normal @delete: lda #$00 @@ -376,7 +377,7 @@ readKey: lsr lsr lsr - and $0F + and #$0F tay ; determine if char is shifted From 8d0cd566551ae720672904915ed8a4453e2cb171 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 23 Sep 2025 22:59:36 +0000 Subject: [PATCH 17/31] seed input with keyboard --- src/gamemode/gametypemenu/menu.asm | 32 +++++++++++++++++++++++ src/nmi/pollkeyboard.asm | 41 ++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index e385bbb0..0cca326c 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -140,6 +140,7 @@ seedControls: lda #BUTTON_RIGHT jsr menuThrottle beq @skipSeedRight +@moveRight: lda #$01 sta soundEffectSlot1Init inc menuSeedCursorIndex @@ -151,7 +152,38 @@ seedControls: @skipSeedRight: lda menuSeedCursorIndex +.if KEYBOARD <> 1 beq @skipSeedControl +.else + bne @readKeys + jmp @skipSeedControl +@readKeys: + jsr readKbSeedEntry + bmi @noKeysPressed + sta generalCounter + ldy menuSeedCursorIndex + dey + tya + lsr + tay ; save seed offset + bcc @highByte + lda set_seed_input,y + and #$F0 + ora generalCounter + sta set_seed_input,y + jmp @moveRight +@highByte: + lda set_seed_input,y + and #$0F + asl generalCounter + asl generalCounter + asl generalCounter + asl generalCounter + ora generalCounter + sta set_seed_input,y + jmp @moveRight +@noKeysPressed: +.endif lda menuSeedCursorIndex sbc #1 diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index 0d0a276a..488016ea 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -201,6 +201,47 @@ pollKeyboard: ; each byte represents row, column and if shift should be read ; only keys supported by the score entry routine are included +charToSeedMap: + .byte key0 + .byte key1 + .byte key2 + .byte key3 + .byte key4 + .byte key5 + .byte key6 + .byte key7 + .byte key8 + .byte key9 + .byte keyA + .byte keyB + .byte keyC + .byte keyD + .byte keyE + .byte keyF +charToSeedMapEnd: + +seedChars = <(charToSeedMapEnd - charToSeedMap) - 1 + +readKbSeedEntry: + ldx #seedChars +@readLoop: + lda charToSeedMap,x + jsr readKey + bne @seedEntered + dex + bpl @readLoop +@seedEntered: + txa + cmp kbHeldInput + beq @noInput + sta kbHeldInput + lda kbHeldInput + rts +@noInput: + lda #$FF + rts + + charToKbMap: .byte keySpace .byte keyA From 4480354725551d7bc59340b9b9be0f7fd51e931e Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 24 Sep 2025 01:25:03 +0000 Subject: [PATCH 18/31] update kb doc from nesdev site --- src/nmi/pollkeyboard.asm | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/nmi/pollkeyboard.asm b/src/nmi/pollkeyboard.asm index 488016ea..8ec6f844 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/nmi/pollkeyboard.asm @@ -37,21 +37,22 @@ kbMappedStart = keyReturn ; ($4016 reads from the data recorder.) -; Similar to the Family Trainer Mat, there are parasitic capacitances that the program must wait for to get a valid result. Family -; BASIC waits approximately 50 cycles after advancing rows before assuming the output is valid. -; Usage - -; Family BASIC reads the keyboard state with the following procedure: - -; Write $05 to $4016 (reset to row 0, column 0) -; Write $04 to $4016 (select column 0, next row if not just reset) -; Read column 0 data from $4017 -; Write $06 to $4016 (select column 1) -; Read column 1 data from $4017 -; Repeat steps 2-5 eight more times - -; Note that Family BASIC never writes to $4016 with bit 2 clear, there is no need to disable the keyboard matrix. +; Similar to the Family Trainer Mat, there are parasitic capacitances that the program must wait for to get a valid result. Family BASIC and the FDS BIOS wait at least 12 cycles (16 if load instructions are considered) between resetting the keyboard and reselecting column 0, and approximately 50 cycles after selecting each column before assuming the output is valid. +; Usage +; Family BASIC and the FDS BIOS read the keyboard state with the following procedure: + +; Write $05 to $4016 (reset to row 0, column 0), followed by 6 NOPs (12 cycles) +; Write $04 to $4016 (select column 0, next row if not just reset), followed by a delay of ~50 cycles +; Read column 0 data from $4017 +; Write $06 to $4016 (select column 1), followed by a delay of ~50 cycles +; Read column 1 data from $4017 +; Repeat steps 2-5 eight more times +; Differences between Family BASIC and the FDS BIOS: + +; The FDS BIOS terminates the routine early if all keys are pressed on column 0 of any row (it determines that the keyboard is disconnected). Family BASIC always reads all rows/columns. +; The FDS BIOS writes to $4016 with bit 2 clear at the end of the routine (thus disabling the keyboard matrix), but Family BASIC does not. +; There are currently no known commercial FDS games which use the BIOS routine for keyboard reading[footnotes 1]. pollKeyboard: @upDown = BUTTON_UP|BUTTON_DOWN From d999b6ddd36689051c8cd07c37c345fa7e7f76c8 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 24 Sep 2025 01:59:34 +0000 Subject: [PATCH 19/31] move things around --- src/keyboard/buttonmap.asm | 10 ++++++++++ src/{nmi/keyboardmap.asm => keyboard/map.asm} | 0 src/{nmi/pollkeyboard.asm => keyboard/poll.asm} | 13 ------------- src/main.asm | 4 +++- 4 files changed, 13 insertions(+), 14 deletions(-) create mode 100644 src/keyboard/buttonmap.asm rename src/{nmi/keyboardmap.asm => keyboard/map.asm} (100%) rename src/{nmi/pollkeyboard.asm => keyboard/poll.asm} (97%) diff --git a/src/keyboard/buttonmap.asm b/src/keyboard/buttonmap.asm new file mode 100644 index 00000000..eb9f509f --- /dev/null +++ b/src/keyboard/buttonmap.asm @@ -0,0 +1,10 @@ +; see keymap.asm for full list of keys + +kbMappedUp = keyK +kbMappedDown = keyJ +kbMappedLeft = keyH +kbMappedRight = keyL +kbMappedB = keyD +kbMappedA = keyF +kbMappedSelect = keyShiftLeft +kbMappedStart = keyReturn diff --git a/src/nmi/keyboardmap.asm b/src/keyboard/map.asm similarity index 100% rename from src/nmi/keyboardmap.asm rename to src/keyboard/map.asm diff --git a/src/nmi/pollkeyboard.asm b/src/keyboard/poll.asm similarity index 97% rename from src/nmi/pollkeyboard.asm rename to src/keyboard/poll.asm index 8ec6f844..503599e3 100644 --- a/src/nmi/pollkeyboard.asm +++ b/src/keyboard/poll.asm @@ -1,16 +1,3 @@ -.include "keyboardmap.asm" - -; for remapping, see above map file for full list -kbMappedUp = keyK -kbMappedDown = keyJ -kbMappedLeft = keyH -kbMappedRight = keyL -kbMappedB = keyD -kbMappedA = keyF -kbMappedSelect = keyShiftLeft -kbMappedStart = keyReturn - - ; https://www.nesdev.org/wiki/Family_BASIC_Keyboard ; Input ($4016 write) diff --git a/src/main.asm b/src/main.asm index 1bebb3e3..ba905467 100644 --- a/src/main.asm +++ b/src/main.asm @@ -36,7 +36,9 @@ mainLoop: .include "nmi/render.asm" .include "nmi/pollcontroller.asm" .if KEYBOARD -.include "nmi/pollkeyboard.asm" +.include "keyboard/map.asm" +.include "keyboard/buttonmap.asm" +.include "keyboard/poll.asm" .endif .include "gamemode/branch.asm" From 71edb34941b243895a9dffec1882c613eb36b7a8 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 26 Sep 2025 12:21:40 +0000 Subject: [PATCH 20/31] Rename map.asm to constants.asm --- src/keyboard/{map.asm => constants.asm} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/keyboard/{map.asm => constants.asm} (100%) diff --git a/src/keyboard/map.asm b/src/keyboard/constants.asm similarity index 100% rename from src/keyboard/map.asm rename to src/keyboard/constants.asm From 42610a6fd1e18e5512aa30eccf411a2a02f091ab Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 27 Sep 2025 21:46:14 +0000 Subject: [PATCH 21/31] keyboard detection --- README.md | 2 +- build.js | 1 + src/constants.asm | 11 ++ src/gamemode/bootscreen.asm | 4 + src/gamemode/gametypemenu/menu.asm | 40 ++-- src/gamemodestate/handlegameover.asm | 5 +- src/highscores/entry_screen.asm | 2 +- src/io.asm | 7 - src/keyboard/buttonmap.asm | 2 - src/keyboard/constants.asm | 56 +++--- src/keyboard/keymap.py | 15 ++ src/keyboard/poll.asm | 286 ++++++++------------------- src/keyboard/tables.asm | 108 ++++++++++ src/main.asm | 2 - src/nametables/game_type_menu.js | 4 + src/nametables/nametables.js | 7 +- src/ram.asm | 25 ++- src/util/core.asm | 2 +- 18 files changed, 301 insertions(+), 278 deletions(-) create mode 100644 src/keyboard/keymap.py create mode 100644 src/keyboard/tables.asm diff --git a/README.md b/README.md index 6e189300..35c8aab3 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ Blocks are invisible until the end of the game. ![Hard Drop](./assets/screens/harddrop.png) -Press `up` to hard drop and `select` to soft drop. +Press `up` to hard drop and `select` to sonic drop. ## Level Menu diff --git a/build.js b/build.js index aaa24637..bd79b285 100644 --- a/build.js +++ b/build.js @@ -100,6 +100,7 @@ console.log(); // build / compress nametables console.time('nametables'); +process.env['GYM_FLAGS'] = compileFlags.join(' '); require('./src/nametables/build'); console.timeEnd('nametables'); diff --git a/src/constants.asm b/src/constants.asm index 79e759dd..f0560c57 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -101,9 +101,17 @@ MODE_LINECAP MODE_DASONLY MODE_QUAL MODE_PAL +.if KEYBOARD = 1 +MODE_KEYBOARD +.endif .endenum +.if KEYBOARD = 1 +MODE_QUANTITY = MODE_KEYBOARD + 1 +.else MODE_QUANTITY = MODE_PAL + 1 +.endif + MODE_GAME_QUANTITY = MODE_HARDDROP + 1 SCORING_CLASSIC := 0 ; for scoringModifier @@ -169,6 +177,9 @@ MENU_TOP_MARGIN_SCROLL := 7 ; in blocks .byte $1 ; MODE_DASONLY .byte $1 ; MODE_QUAL .byte $1 ; MODE_PAL +.if KEYBOARD = 1 + .byte $1 ; MODE_KEYBOARD +.endif .endmacro .macro MODENAMES diff --git a/src/gamemode/bootscreen.asm b/src/gamemode/bootscreen.asm index 7c7d63af..9d4fcdb3 100644 --- a/src/gamemode/bootscreen.asm +++ b/src/gamemode/bootscreen.asm @@ -15,6 +15,10 @@ gameMode_bootScreen: ; boot jsr updateAudioAndWaitForNmi jsr checkRegion +.if KEYBOARD = 1 + jsr detectKeyboard +.endif + .if !QUAL_BOOT ; check if qualMode is already set lda qualFlag diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index 0cca326c..344734d3 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -152,37 +152,43 @@ seedControls: @skipSeedRight: lda menuSeedCursorIndex -.if KEYBOARD <> 1 - beq @skipSeedControl -.else - bne @readKeys + +.if KEYBOARD = 1 +@kbSeedLow = generalCounter +@kbSeedHigh = generalCounter2 + bne @checkForKbSeedEntry jmp @skipSeedControl -@readKeys: +@checkForKbSeedEntry: jsr readKbSeedEntry bmi @noKeysPressed - sta generalCounter + sta @kbSeedLow + asl + asl + asl + asl + sta @kbSeedHigh ldy menuSeedCursorIndex dey tya lsr - tay ; save seed offset - bcc @highByte + tay + ; y = (index-1) // 2 + ; c = (index-1) % 2 lda set_seed_input,y + bcc @highByte +; low byte: and #$F0 - ora generalCounter - sta set_seed_input,y - jmp @moveRight + ora @kbSeedLow + bcs @storeSeed @highByte: - lda set_seed_input,y and #$0F - asl generalCounter - asl generalCounter - asl generalCounter - asl generalCounter - ora generalCounter + ora @kbSeedHigh +@storeSeed: sta set_seed_input,y jmp @moveRight @noKeysPressed: +.else + beq @skipSeedControl .endif lda menuSeedCursorIndex diff --git a/src/gamemodestate/handlegameover.asm b/src/gamemodestate/handlegameover.asm index 9f725f4d..2a6a4afe 100644 --- a/src/gamemodestate/handlegameover.asm +++ b/src/gamemodestate/handlegameover.asm @@ -18,9 +18,10 @@ gameModeState_handleGameOver: lda #$03 sta renderMode .if KEYBOARD = 1 - inc entryActive + ; flag for keyboard poll to ignore mapped keys except start/return + inc highScoreEntryActive jsr handleHighScoreIfNecessary - dec entryActive + dec highScoreEntryActive .else jsr handleHighScoreIfNecessary .endif diff --git a/src/highscores/entry_screen.asm b/src/highscores/entry_screen.asm index 238f00c1..3a59f34d 100644 --- a/src/highscores/entry_screen.asm +++ b/src/highscores/entry_screen.asm @@ -178,7 +178,7 @@ highScoreEntryScreen: @checkForAOrRightPressed: .if KEYBOARD = 1 - jsr readKbScoreInput + jsr readKbHighScoreEntry bmi @noKeyboardInput beq @nextTile cmp #$7F diff --git a/src/io.asm b/src/io.asm index db42f1cf..1e99e4da 100644 --- a/src/io.asm +++ b/src/io.asm @@ -34,13 +34,6 @@ SND_CHN := $4015 JOY1 := $4016 JOY2_APUFC := $4017 ; read: bits 0-4 joy data lines (bit 0 being normal controller), bits 6-7 are FC inhibit and mode -; Used by Family Basic Keyboard -.if KEYBOARD -KB_INIT := $05 -KB_COL_0 := $04 -KB_COL_1 := $06 -KB_MASK := $1E -.endif MMC1_Control := $8000 MMC1_CHR0 := $BFFF diff --git a/src/keyboard/buttonmap.asm b/src/keyboard/buttonmap.asm index eb9f509f..d6161606 100644 --- a/src/keyboard/buttonmap.asm +++ b/src/keyboard/buttonmap.asm @@ -1,5 +1,3 @@ -; see keymap.asm for full list of keys - kbMappedUp = keyK kbMappedDown = keyJ kbMappedLeft = keyH diff --git a/src/keyboard/constants.asm b/src/keyboard/constants.asm index 442e5928..2ee0a72c 100644 --- a/src/keyboard/constants.asm +++ b/src/keyboard/constants.asm @@ -1,35 +1,5 @@ -; Assisted with the following python: -; kbmap = """ -; CloseBracket OpenBracket RETURN F8 STOP Yen SHIFTRight KANA -; Semicolon Colon atSign F7 Caret Dash Slash Underscore -; K L O F6 0 P Comma Period -; J U I F5 8 9 N M -; H G Y F4 6 7 V B -; D R T F3 4 5 C F -; A S W F2 3 E Z X -; CTR Q ESC F1 2 1 GRPH SHIFTLeft -; Left Right UP CLR_HOME INS DEL Space Down -; """ -; for row, keys in enumerate(kbmap.strip().splitlines()): -; for mask, key in enumerate(keys.split()): -; print(f"key{key:<12} = ${((8 - row) << 3) | mask:02X}") - -.macro readKeyDirect keyMap - lda keyboardInput + (keyMap >> 3) - and #$80 >> (keyMap & 7) -.endmacro - -.macro expandKeyRow keyMap - .byte keyMap >> 3 -.endmacro - -.macro expandKeyMask keyMap - .byte $80 >> (keyMap & 7) -.endmacro - - ; each key is represented by a byte 0RRRRCCC -; row is 0-8 and is inverted +; row is 0-8 ; col is byte position from left to right keyF1 = $0B @@ -113,3 +83,27 @@ keyW = $12 keyX = $17 keyY = $22 keyZ = $16 + + +KB_DISABLE = $00 +KB_INIT = $05 +KB_COL_0 = $04 +KB_COL_1 = $06 +KB_MASK = $1E + +UPDOWN = BUTTON_UP | BUTTON_DOWN +LEFTRIGHT = BUTTON_LEFT | BUTTON_RIGHT + +.macro readKeyDirect keyMap +; not zero - key is pressed + lda kbRawInput + (keyMap >> 3) + and #$80 >> (keyMap & 7) +.endmacro + +.macro expandKeyRow keyMap + .byte keyMap >> 3 +.endmacro + +.macro expandKeyMask keyMap + .byte $80 >> (keyMap & 7) +.endmacro diff --git a/src/keyboard/keymap.py b/src/keyboard/keymap.py new file mode 100644 index 00000000..30917e8a --- /dev/null +++ b/src/keyboard/keymap.py @@ -0,0 +1,15 @@ +keymap = """ +CloseBracket OpenBracket RETURN F8 STOP Yen SHIFTRight KANA +Semicolon Colon atSign F7 Caret Dash Slash Underscore +K L O F6 0 P Comma Period +J U I F5 8 9 N M +H G Y F4 6 7 V B +D R T F3 4 5 C F +A S W F2 3 E Z X +CTR Q ESC F1 2 1 GRPH SHIFTLeft +Left Right UP CLR_HOME INS DEL Space Down +""" + +for row, keys in enumerate(keymap.strip().splitlines()): + for mask, key in enumerate(keys.split()): + print(f"key{key:<12} = ${((8 - row) << 3) | mask:02X}") diff --git a/src/keyboard/poll.asm b/src/keyboard/poll.asm index 503599e3..5f3c44a4 100644 --- a/src/keyboard/poll.asm +++ b/src/keyboard/poll.asm @@ -1,57 +1,19 @@ ; https://www.nesdev.org/wiki/Family_BASIC_Keyboard - -; Input ($4016 write) - -; 7 bit 0 -; ---- ---- -; xxxx xKCR -; ||| -; ||+-- Reset the keyboard to the first row. -; |+--- Select column, row is incremented if this bit goes from high to low. -; +---- Enable keyboard matrix (if 0, all voltages inside the keyboard will be 5V, reading back as logical 0 always) - -; Incrementing the row from the (keyless) 10th row will cause it to wrap back to the first row. - -; Output ($4017 read) - -; 7 bit 0 -; ---- ---- -; xxxK KKKx -; | ||| -; +-+++--- Receive key status of currently selected row/column. - -; Any key that is held down, will read back as 0. - -; ($4016 reads from the data recorder.) - -; Similar to the Family Trainer Mat, there are parasitic capacitances that the program must wait for to get a valid result. Family BASIC and the FDS BIOS wait at least 12 cycles (16 if load instructions are considered) between resetting the keyboard and reselecting column 0, and approximately 50 cycles after selecting each column before assuming the output is valid. - -; Usage -; Family BASIC and the FDS BIOS read the keyboard state with the following procedure: - -; Write $05 to $4016 (reset to row 0, column 0), followed by 6 NOPs (12 cycles) -; Write $04 to $4016 (select column 0, next row if not just reset), followed by a delay of ~50 cycles -; Read column 0 data from $4017 -; Write $06 to $4016 (select column 1), followed by a delay of ~50 cycles -; Read column 1 data from $4017 -; Repeat steps 2-5 eight more times -; Differences between Family BASIC and the FDS BIOS: - -; The FDS BIOS terminates the routine early if all keys are pressed on column 0 of any row (it determines that the keyboard is disconnected). Family BASIC always reads all rows/columns. -; The FDS BIOS writes to $4016 with bit 2 clear at the end of the routine (thus disabling the keyboard matrix), but Family BASIC does not. -; There are currently no known commercial FDS games which use the BIOS routine for keyboard reading[footnotes 1]. +.include "keyboard/constants.asm" +.include "keyboard/buttonmap.asm" +.include "keyboard/tables.asm" pollKeyboard: -@upDown = BUTTON_UP|BUTTON_DOWN -@leftRight = BUTTON_LEFT|BUTTON_RIGHT - - + lda keyboardFlag + bne @init + rts +@init: lda #KB_INIT sta JOY1 ; wait 12 cycles before first row lda #$00 - sta newlyPressedKeys + sta kbNewKeys ldx #8 nop nop @@ -62,7 +24,7 @@ pollKeyboard: sty JOY1 ldy #6 - jsr @keyboardReadWait + jsr keyboardReadWait lda JOY2_APUFC ; start second column read @@ -74,146 +36,127 @@ pollKeyboard: asl asl asl - beq @ret ; assume 4 simultaneously pressed keys in one row indicates no keyboard + beq @disconnected sta generalCounter ldy #3 - jsr @keyboardReadWait + jsr keyboardReadWait lda JOY2_APUFC and #KB_MASK lsr ora generalCounter eor #$FF - sta keyboardInput,x + sta kbRawInput,x dex bpl @rowLoop ; map keys to buttons lda #$00 - sta newlyPressedKeys + sta kbNewKeys ldx #7 ; build a byte that looks like controller input @readKeyLoop: clc - ldy @mappedRows,x - lda keyboardInput,y - and @mappedMasks,x + ldy kbMappedKeyRows,x + lda kbRawInput,y + and kbMappedKeyMasks,x beq @notPressed sec @notPressed: - rol newlyPressedKeys + rol kbNewKeys dex bpl @readKeyLoop ; prevent SOCD (Simultaneous Opposite Cardinal Direction ldx #$01 @antiSocd: - lda newlyPressedKeys - and @antiSocdMatch,x - cmp @antiSocdMatch,x + lda kbNewKeys + and kbAntiSocd,x + cmp kbAntiSocd,x bne @noMatch eor #$FF - and newlyPressedKeys - sta newlyPressedKeys + and kbNewKeys + sta kbNewKeys @noMatch: dex bpl @antiSocd ; determine which are new - lda newlyPressedKeys + lda kbNewKeys ; ignore everything except start during score entry - ldy entryActive + ldy highScoreEntryActive beq @entryNotActive and #BUTTON_START @entryNotActive: tay - eor heldKeys - and newlyPressedKeys - sta newlyPressedKeys - sty heldKeys + eor kbHeldKeys + and kbNewKeys + sta kbNewKeys + sty kbHeldKeys ; Copy to controller buttons lda newlyPressedButtons_player1 - ora newlyPressedKeys + ora kbNewKeys sta newlyPressedButtons_player1 lda heldButtons_player1 - ora heldKeys + ora kbHeldKeys sta heldButtons_player1 @ret: rts -@keyboardReadWait: +@disconnected: + ldy #8 + lda #$00 + sta keyboardFlag +@clearInput: + sta kbRawInput,y + dey + bpl @clearInput + rts + +keyboardReadWait: ; consumes (y * 5) + 16 dey - bpl @keyboardReadWait + bpl keyboardReadWait rts -@antiSocdMatch: - .byte @upDown,@leftRight - -@mappedRows: - expandKeyRow kbMappedRight - expandKeyRow kbMappedLeft - expandKeyRow kbMappedDown - expandKeyRow kbMappedUp - expandKeyRow kbMappedStart - expandKeyRow kbMappedSelect - expandKeyRow kbMappedB - expandKeyRow kbMappedA -@mappedMasks: - expandKeyMask kbMappedRight - expandKeyMask kbMappedLeft - expandKeyMask kbMappedDown - expandKeyMask kbMappedUp - expandKeyMask kbMappedStart - expandKeyMask kbMappedSelect - expandKeyMask kbMappedB - expandKeyMask kbMappedA - - -; Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7 -; 0 ] [ RETURN F8 STOP ¥ RSHIFT KANA -; 1 ; : @ F7 ^ - / _ -; 2 K L O F6 0 P , . -; 3 J U I F5 8 9 N M -; 4 H G Y F4 6 7 V B -; 5 D R T F3 4 5 C F -; 6 A S W F2 3 E Z X -; 7 CTR Q ESC F1 2 1 GRPH LSHIFT -; 8 LEFT RIGHT UP CLR_HOME INS DEL SPACE DOWN - -; each byte represents row, column and if shift should be read -; only keys supported by the score entry routine are included - -charToSeedMap: - .byte key0 - .byte key1 - .byte key2 - .byte key3 - .byte key4 - .byte key5 - .byte key6 - .byte key7 - .byte key8 - .byte key9 - .byte keyA - .byte keyB - .byte keyC - .byte keyD - .byte keyE - .byte keyF -charToSeedMapEnd: - -seedChars = <(charToSeedMapEnd - charToSeedMap) - 1 +detectKeyboard: +; read 10th row, expect 1E +; disable keyboard, expect 00 +; see https://www.nesdev.org/wiki/Family_BASIC_Keyboard#Keyboard_detection_in_other_games + jsr pollKeyboard + ldy #KB_COL_0 + sty JOY1 + ldy #6 + jsr keyboardReadWait + lda JOY2_APUFC + and #KB_MASK + cmp #KB_MASK + bne @noKeyboard + ldy #6 + jsr keyboardReadWait + lda #KB_DISABLE + sta JOY1 + ldy #6 + jsr keyboardReadWait + lda JOY2_APUFC + and #KB_MASK + bne @noKeyboard + inc keyboardFlag +@noKeyboard: + rts + +; Seed Entry + readKbSeedEntry: - ldx #seedChars + ldx #seedEntryCharCount @readLoop: - lda charToSeedMap,x + lda seedEntryTable,x jsr readKey bne @seedEntered dex @@ -230,67 +173,11 @@ readKbSeedEntry: rts -charToKbMap: - .byte keySpace - .byte keyA - .byte keyB - .byte keyC - .byte keyD - .byte keyE - .byte keyF - .byte keyG - .byte keyH - .byte keyI - .byte keyJ - .byte keyK - .byte keyL - .byte keyM - .byte keyN - .byte keyO - .byte keyP - .byte keyQ - .byte keyR - .byte keyS - .byte keyT - .byte keyU - .byte keyV - .byte keyW - .byte keyX - .byte keyY - .byte keyZ - .byte key0 - .byte key1 - .byte key2 - .byte key3 - .byte key4 - .byte key5 - .byte key6 - .byte key7 - .byte key8 - .byte key9 - .byte keyComma - .byte keySlash - .byte keyOpenBracket - .byte keyCloseBracket - .byte keyKana ; <3 - .byte keyPeriod - .byte key1 | $80 ; ! - .byte keySlash | $80 ; ? - .byte keyDash - ; treated differently - .byte keyRight - .byte keyLeft - .byte keyDEL -charToKbMapEnd: - -kbChars = <(charToKbMapEnd - charToKbMap) - 1 -kbScoreDelete = kbChars -kbScoreLeft = kbChars - 1 -kbScoreRight = kbChars - 2 - -kbInputThrottle := generalCounter4 - -readKbScoreInput: +; high score entry + + +readKbHighScoreEntry: +@kbInputThrottle := generalCounter4 ; 2 frames to complete action ; first reads key, determines action and stores key (unless key is action only) ; second returns cursor action @@ -308,7 +195,7 @@ readKbScoreInput: ; check if shift flag is set lda kbReadState - beq @readScoreInput + beq @readChar dec kbReadState beq @signalRight dec kbReadState ; reset to 0 @@ -317,11 +204,11 @@ readKbScoreInput: @signalRight: rts -@readScoreInput: - ldx #kbChars +@readChar: + ldx #scoreEntryCharCount @checkNextChar: - lda charToKbMap,x + lda scoreEntryTable,x jsr readKey bne @keyPressed dex @@ -336,7 +223,7 @@ readKbScoreInput: cpx kbHeldInput bne @newInput - inc kbInputThrottle + inc @kbInputThrottle bne @noKeyPressed lda #-4 @@ -347,7 +234,7 @@ readKbScoreInput: lda #-16 @storeThrottle: - sta kbInputThrottle + sta @kbInputThrottle @placeInput: lda highScoreEntryNameOffsetForLetter @@ -398,7 +285,7 @@ readKey: ; extract mask and #07 tay - lda @readKeyMasks,y + lda kbColumnMaskTable,y sta @readKeyMask ; extract row index @@ -421,10 +308,7 @@ readKey: beq @ret @readKey: - lda keyboardInput,y + lda kbRawInput,y and @readKeyMask @ret: rts - -@readKeyMasks: - .byte $80,$40,$20,$10,$08,$04,$02,$01 diff --git a/src/keyboard/tables.asm b/src/keyboard/tables.asm new file mode 100644 index 00000000..7ff323b9 --- /dev/null +++ b/src/keyboard/tables.asm @@ -0,0 +1,108 @@ +kbAntiSocd: + .byte BUTTON_UP | BUTTON_DOWN + .byte BUTTON_LEFT | BUTTON_RIGHT + +kbMappedKeyRows: + expandKeyRow kbMappedRight + expandKeyRow kbMappedLeft + expandKeyRow kbMappedDown + expandKeyRow kbMappedUp + expandKeyRow kbMappedStart + expandKeyRow kbMappedSelect + expandKeyRow kbMappedB + expandKeyRow kbMappedA + +kbMappedKeyMasks: + expandKeyMask kbMappedRight + expandKeyMask kbMappedLeft + expandKeyMask kbMappedDown + expandKeyMask kbMappedUp + expandKeyMask kbMappedStart + expandKeyMask kbMappedSelect + expandKeyMask kbMappedB + expandKeyMask kbMappedA + + +seedEntryTable: + .byte key0 + .byte key1 + .byte key2 + .byte key3 + .byte key4 + .byte key5 + .byte key6 + .byte key7 + .byte key8 + .byte key9 + .byte keyA + .byte keyB + .byte keyC + .byte keyD + .byte keyE + .byte keyF +seedEntryTableEnd: +seedEntryCharCount = <(seedEntryTableEnd - seedEntryTable) - 1 + +scoreEntryTable: + .byte keySpace + .byte keyA + .byte keyB + .byte keyC + .byte keyD + .byte keyE + .byte keyF + .byte keyG + .byte keyH + .byte keyI + .byte keyJ + .byte keyK + .byte keyL + .byte keyM + .byte keyN + .byte keyO + .byte keyP + .byte keyQ + .byte keyR + .byte keyS + .byte keyT + .byte keyU + .byte keyV + .byte keyW + .byte keyX + .byte keyY + .byte keyZ + .byte key0 + .byte key1 + .byte key2 + .byte key3 + .byte key4 + .byte key5 + .byte key6 + .byte key7 + .byte key8 + .byte key9 + .byte keyComma + .byte keySlash + .byte keyOpenBracket + .byte keyCloseBracket + .byte keyKana ; <3 + .byte keyPeriod + .byte key1 | $80 ; ! + .byte keySlash | $80 ; ? + .byte keyDash + ; treated differently + .byte keyRight + .byte keyLeft + .byte keyDEL +scoreEntryTableEnd: + +scoreEntryCharCount = <(scoreEntryTableEnd - scoreEntryTable) - 1 + +kbScoreDelete = scoreEntryCharCount +kbScoreLeft = scoreEntryCharCount - 1 +kbScoreRight = scoreEntryCharCount - 2 + +kbColumnMaskTable: + .repeat 8,i + .byte $80 >> i + .endrepeat diff --git a/src/main.asm b/src/main.asm index ba905467..5500f79c 100644 --- a/src/main.asm +++ b/src/main.asm @@ -36,8 +36,6 @@ mainLoop: .include "nmi/render.asm" .include "nmi/pollcontroller.asm" .if KEYBOARD -.include "keyboard/map.asm" -.include "keyboard/buttonmap.asm" .include "keyboard/poll.asm" .endif diff --git a/src/nametables/game_type_menu.js b/src/nametables/game_type_menu.js index 45cc8a47..a12cb1a1 100644 --- a/src/nametables/game_type_menu.js +++ b/src/nametables/game_type_menu.js @@ -95,6 +95,10 @@ drawTiles(buffer, lookup, ` #a d# `); +if (process.env['GYM_FLAGS']?.match(/-D KEYBOARD=1/)) { + drawTiles(extra, lookup, "KEYBOARD", 32 * 15 + 6); + } + const background = ` ɢ##############################ɳ ɲ##############################ɢ diff --git a/src/nametables/nametables.js b/src/nametables/nametables.js index 705e81f2..0b0c563e 100644 --- a/src/nametables/nametables.js +++ b/src/nametables/nametables.js @@ -42,14 +42,15 @@ function blankNT() { return Array.from({ length: 1024 }, () => 0xFF); } -function drawTiles(buffer, lookup, tiles) { +function drawTiles(buffer, lookup, tiles, offset) { + const o = offset ? offset : 0; [...tiles.trim().split('\n').join('')].forEach((d, i) => { if (d !== '#') { const charCode = d.charCodeAt(0); if (charCode > STR_OFFSET) { - buffer[i] = charCode - STR_OFFSET; + buffer[o + i] = charCode - STR_OFFSET; } else { - buffer[i] = lookup.indexOf(d); + buffer[o + i] = lookup.indexOf(d); } } }); diff --git a/src/ram.asm b/src/ram.asm index 6b444861..77d8bb3c 100755 --- a/src/ram.asm +++ b/src/ram.asm @@ -221,22 +221,24 @@ invisibleFlag: .res 1 ; $63B ; 0 for normal mode, non-zero for Invisible playfi currentFloor: .res 1 ; $63C floorModifier is copied here at game init. Set to 0 otherwise and incremented when linecap floor. mapperId: .res 1 ; $63D ; For INES_MAPPER 1000 (autodetect). 0 = CNROM. 1 = MMC1. -entryActive: .res 1 ; todo: find better way to track high score entry screen .res $34 .if KEYBOARD -; used for high score entry to throttle input and to flag when a letter has been input -kbReadState: .res 1 ; $0673 -kbHeldInput: .res 1 ; $0674 +kbReadState: .res 1 ; $0673 - used for high score entry +kbHeldInput: .res 1 ; $0674 - high score input throttling -; controller equivalent, can possibly be removed -newlyPressedKeys: .res 1 ; $0675 -heldKeys: .res 1 ; $0676 + ; mapped buttons stored like a controller byte + ; player2 controller can possibly be used instead +kbNewKeys: .res 1 ; $0675 +kbHeldKeys: .res 1 ; $0676 -; raw input from keyboard -keyboardInput: .res 9 ; $0677 +kbRawInput: .res 9 ; $0677 - all 72 keys' input + +; used to track state of high score entry screen. Can possibly use the address of the nmi interrupted +; routine in the stack to track instead +highScoreEntryActive: .res 1 ; $0675 .else - .res $D + .res $B .endif musicStagingSq1Lo: .res 1 ; $0680 @@ -359,5 +361,8 @@ linecapFlag: .res 1 dasOnlyFlag: .res 1 qualFlag: .res 1 palFlag: .res 1 +.if KEYBOARD = 1 +keyboardFlag: .res 1 +.endif ; ... $7FF diff --git a/src/util/core.asm b/src/util/core.asm index 72282e10..112d4293 100755 --- a/src/util/core.asm +++ b/src/util/core.asm @@ -65,7 +65,7 @@ updateAudioWaitForNmiAndResetOamStaging: lda verticalBlankingInterval beq @checkForNmi -.if KEYBOARD +.if KEYBOARD = 1 ; Read Family BASIC Keyboard jsr pollKeyboard .endif From 350e56cbd2057a8488d72079c32a43922979be38 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 27 Sep 2025 21:54:15 +0000 Subject: [PATCH 22/31] read 10th row instead of first This was skipping rows 1-9 because keyboardFlag was 0, but worked anyway as expected. Doing a full read when detecting anyway. --- src/keyboard/poll.asm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/keyboard/poll.asm b/src/keyboard/poll.asm index 5f3c44a4..244d7feb 100644 --- a/src/keyboard/poll.asm +++ b/src/keyboard/poll.asm @@ -5,9 +5,9 @@ pollKeyboard: lda keyboardFlag - bne @init + bne pollKeyboardInit rts -@init: +pollKeyboardInit: lda #KB_INIT sta JOY1 @@ -128,7 +128,7 @@ detectKeyboard: ; read 10th row, expect 1E ; disable keyboard, expect 00 ; see https://www.nesdev.org/wiki/Family_BASIC_Keyboard#Keyboard_detection_in_other_games - jsr pollKeyboard + jsr pollKeyboardInit ldy #KB_COL_0 sty JOY1 ldy #6 From 6a4bc04414007550251a111bd2cfc44129e305ab Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 27 Sep 2025 22:33:59 +0000 Subject: [PATCH 23/31] update addresses in ram comments --- src/ram.asm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ram.asm b/src/ram.asm index 77d8bb3c..7e7e60d3 100755 --- a/src/ram.asm +++ b/src/ram.asm @@ -224,19 +224,19 @@ mapperId: .res 1 ; $63D ; For INES_MAPPER 1000 (autodetect). 0 = CNROM. 1 = MM .res $34 .if KEYBOARD -kbReadState: .res 1 ; $0673 - used for high score entry -kbHeldInput: .res 1 ; $0674 - high score input throttling +kbReadState: .res 1 ; $0672 - used for high score entry +kbHeldInput: .res 1 ; $0673 - high score input throttling ; mapped buttons stored like a controller byte ; player2 controller can possibly be used instead -kbNewKeys: .res 1 ; $0675 -kbHeldKeys: .res 1 ; $0676 +kbNewKeys: .res 1 ; $0674 +kbHeldKeys: .res 1 ; $0675 -kbRawInput: .res 9 ; $0677 - all 72 keys' input +kbRawInput: .res 9 ; $0676 - all 72 keys' input ; used to track state of high score entry screen. Can possibly use the address of the nmi interrupted ; routine in the stack to track instead -highScoreEntryActive: .res 1 ; $0675 +highScoreEntryActive: .res 1 ; $067F .else .res $B .endif From ff3914c66f2587db0de0a5144992e62c7b6fc767 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 29 Sep 2025 00:43:04 +0000 Subject: [PATCH 24/31] proper ram reservation when no-keyboard --- src/ram.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ram.asm b/src/ram.asm index 7e7e60d3..ddab4288 100755 --- a/src/ram.asm +++ b/src/ram.asm @@ -238,7 +238,7 @@ kbRawInput: .res 9 ; $0676 - all 72 keys' input ; routine in the stack to track instead highScoreEntryActive: .res 1 ; $067F .else - .res $B + .res $E .endif musicStagingSq1Lo: .res 1 ; $0680 From 491b5adfeca12e814e6fe23acfdbeb9449a16804 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 29 Sep 2025 00:43:58 +0000 Subject: [PATCH 25/31] specify low byte for negative numbers --- src/keyboard/poll.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/keyboard/poll.asm b/src/keyboard/poll.asm index 244d7feb..4644ffc0 100644 --- a/src/keyboard/poll.asm +++ b/src/keyboard/poll.asm @@ -226,12 +226,12 @@ readKbHighScoreEntry: inc @kbInputThrottle bne @noKeyPressed - lda #-4 + lda #<-4 bne @storeThrottle @newInput: stx kbHeldInput - lda #-16 + lda #<-16 @storeThrottle: sta @kbInputThrottle From 8fe6f18157408f3b7ad741e4b8c55f73ec58f769 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 29 Sep 2025 00:45:09 +0000 Subject: [PATCH 26/31] Update src/nametables/nametables.js Co-authored-by: Kirjava --- src/nametables/nametables.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/nametables/nametables.js b/src/nametables/nametables.js index 0b0c563e..d0b1853b 100644 --- a/src/nametables/nametables.js +++ b/src/nametables/nametables.js @@ -42,8 +42,7 @@ function blankNT() { return Array.from({ length: 1024 }, () => 0xFF); } -function drawTiles(buffer, lookup, tiles, offset) { - const o = offset ? offset : 0; +function drawTiles(buffer, lookup, tiles, offset = 0) { [...tiles.trim().split('\n').join('')].forEach((d, i) => { if (d !== '#') { const charCode = d.charCodeAt(0); From fe9df0a0f840e15e2d9118d131ff32523455ffeb Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 29 Sep 2025 00:57:56 +0000 Subject: [PATCH 27/31] fix offset var --- src/nametables/nametables.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nametables/nametables.js b/src/nametables/nametables.js index d0b1853b..c7471aaf 100644 --- a/src/nametables/nametables.js +++ b/src/nametables/nametables.js @@ -47,9 +47,9 @@ function drawTiles(buffer, lookup, tiles, offset = 0) { if (d !== '#') { const charCode = d.charCodeAt(0); if (charCode > STR_OFFSET) { - buffer[o + i] = charCode - STR_OFFSET; + buffer[offset + i] = charCode - STR_OFFSET; } else { - buffer[o + i] = lookup.indexOf(d); + buffer[offset + i] = lookup.indexOf(d); } } }); From 831a04afb3c2b553045fbd445d7da0224dc81b36 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 30 Sep 2025 20:29:33 +0000 Subject: [PATCH 28/31] save bytes --- src/keyboard/poll.asm | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/keyboard/poll.asm b/src/keyboard/poll.asm index 4644ffc0..5e02faea 100644 --- a/src/keyboard/poll.asm +++ b/src/keyboard/poll.asm @@ -162,11 +162,10 @@ readKbSeedEntry: dex bpl @readLoop @seedEntered: - txa - cmp kbHeldInput + cpx kbHeldInput beq @noInput - sta kbHeldInput - lda kbHeldInput + stx kbHeldInput + txa rts @noInput: lda #$FF From 6f72aa23d511fca063d943fdacc9eed5282632f9 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 30 Sep 2025 20:41:52 +0000 Subject: [PATCH 29/31] disable controller while keyboard is active --- src/nmi/pollcontroller.asm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/nmi/pollcontroller.asm b/src/nmi/pollcontroller.asm index d1fe24eb..1c9c6eb5 100644 --- a/src/nmi/pollcontroller.asm +++ b/src/nmi/pollcontroller.asm @@ -66,6 +66,21 @@ pollController: diffOldAndNewButtons: ldx #$01 +.if KEYBOARD = 1 +; clear controller input when keyboard is active +; disable keyboard when reset sequence is pressed + lda keyboardFlag + beq @diffForPlayer + lda newlyPressedButtons_player1 + and #BUTTON_B|BUTTON_A|BUTTON_SELECT|BUTTON_START + cmp #BUTTON_B|BUTTON_A|BUTTON_SELECT|BUTTON_START + php + lda #$00 + sta newlyPressedButtons_player1 + plp + bne @diffForPlayer + sta keyboardFlag +.endif @diffForPlayer: lda newlyPressedButtons_player1,x tay From 150a639de81780a5800f0cd948a24f70cf076aad Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 15 Oct 2025 04:25:57 +0000 Subject: [PATCH 30/31] prevent yutaps --- src/keyboard/poll.asm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/keyboard/poll.asm b/src/keyboard/poll.asm index 5e02faea..fe02db7f 100644 --- a/src/keyboard/poll.asm +++ b/src/keyboard/poll.asm @@ -72,12 +72,17 @@ pollKeyboardInit: ; prevent SOCD (Simultaneous Opposite Cardinal Direction ldx #$01 @antiSocd: + lda kbHeldKeys + and kbAntiSocd,x + sta generalCounter lda kbNewKeys and kbAntiSocd,x cmp kbAntiSocd,x bne @noMatch eor #$FF and kbNewKeys + ; allow previously held input to continue to be held, prevents yutaps + ora generalCounter sta kbNewKeys @noMatch: dex From c9c13159df97a50098b120d844fae49d57e8c144 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 15 Oct 2025 08:49:25 +0000 Subject: [PATCH 31/31] kb takes over controller bytes when active --- src/keyboard/poll.asm | 37 +++++++++++++------------------------ src/nmi/pollcontroller.asm | 4 ++-- src/ram.asm | 20 +++++++------------- 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/src/keyboard/poll.asm b/src/keyboard/poll.asm index fe02db7f..88bd14cd 100644 --- a/src/keyboard/poll.asm +++ b/src/keyboard/poll.asm @@ -13,11 +13,12 @@ pollKeyboardInit: ; wait 12 cycles before first row lda #$00 - sta kbNewKeys + sta newlyPressedButtons_player1 ldx #8 nop nop nop + nop @rowLoop: ; start first column read ldy #KB_COL_0 @@ -52,8 +53,6 @@ pollKeyboardInit: bpl @rowLoop ; map keys to buttons - lda #$00 - sta kbNewKeys ldx #7 ; build a byte that looks like controller input @@ -65,53 +64,43 @@ pollKeyboardInit: beq @notPressed sec @notPressed: - rol kbNewKeys + rol newlyPressedButtons_player1 dex bpl @readKeyLoop ; prevent SOCD (Simultaneous Opposite Cardinal Direction ldx #$01 @antiSocd: - lda kbHeldKeys + lda heldButtons_player1 and kbAntiSocd,x sta generalCounter - lda kbNewKeys + lda newlyPressedButtons_player1 and kbAntiSocd,x cmp kbAntiSocd,x bne @noMatch eor #$FF - and kbNewKeys - ; allow previously held input to continue to be held, prevents yutaps + and newlyPressedButtons_player1 + ; allow previously held input to continue, prevents yutaps ora generalCounter - sta kbNewKeys + sta newlyPressedButtons_player1 @noMatch: dex bpl @antiSocd ; determine which are new - lda kbNewKeys + lda newlyPressedButtons_player1 ; ignore everything except start during score entry ldy highScoreEntryActive beq @entryNotActive and #BUTTON_START @entryNotActive: - tay - eor kbHeldKeys - and kbNewKeys - sta kbNewKeys - sty kbHeldKeys - -; Copy to controller buttons - lda newlyPressedButtons_player1 - ora kbNewKeys + eor heldButtons_player1 + and newlyPressedButtons_player1 sta newlyPressedButtons_player1 - - lda heldButtons_player1 - ora kbHeldKeys - sta heldButtons_player1 -@ret: rts + sty heldButtons_player1 + rts @disconnected: ldy #8 diff --git a/src/nmi/pollcontroller.asm b/src/nmi/pollcontroller.asm index 1c9c6eb5..4f89b1ec 100644 --- a/src/nmi/pollcontroller.asm +++ b/src/nmi/pollcontroller.asm @@ -78,7 +78,7 @@ diffOldAndNewButtons: lda #$00 sta newlyPressedButtons_player1 plp - bne @diffForPlayer + bne @ret sta keyboardFlag .endif @diffForPlayer: @@ -90,4 +90,4 @@ diffOldAndNewButtons: sty heldButtons_player1,x dex bpl @diffForPlayer - rts +@ret: rts diff --git a/src/ram.asm b/src/ram.asm index ddab4288..aa0e2ee4 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -221,26 +221,20 @@ invisibleFlag: .res 1 ; $63B ; 0 for normal mode, non-zero for Invisible playfi currentFloor: .res 1 ; $63C floorModifier is copied here at game init. Set to 0 otherwise and incremented when linecap floor. mapperId: .res 1 ; $63D ; For INES_MAPPER 1000 (autodetect). 0 = CNROM. 1 = MMC1. - .res $34 - .if KEYBOARD -kbReadState: .res 1 ; $0672 - used for high score entry -kbHeldInput: .res 1 ; $0673 - high score input throttling - - ; mapped buttons stored like a controller byte - ; player2 controller can possibly be used instead -kbNewKeys: .res 1 ; $0674 -kbHeldKeys: .res 1 ; $0675 - -kbRawInput: .res 9 ; $0676 - all 72 keys' input +kbReadState: .res 1 ; $063E - used for high score entry +kbHeldInput: .res 1 ; $063E - high score input throttling +kbRawInput: .res 9 ; $0640 - all 72 keys' input ; used to track state of high score entry screen. Can possibly use the address of the nmi interrupted ; routine in the stack to track instead -highScoreEntryActive: .res 1 ; $067F +highScoreEntryActive: .res 1 ; $0649 .else - .res $E + .res $C .endif + .res $36 + musicStagingSq1Lo: .res 1 ; $0680 musicStagingSq1Hi: .res 1 ; $0681 audioInitialized: .res 1 ; $0682