From 3268ea358df8773ded3d6fc3b3a66052b75eb12f Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 29 Aug 2025 18:05:14 +0000 Subject: [PATCH 01/37] thanks hydrantdude todo: figure out how this works --- src/gamemodestate/initstate.asm | 3 + src/nametables/game.js | 6 +- src/nmi/render_mode_play_and_demo.asm | 12 ++ src/playstate/branch.asm | 1 + src/playstate/trt.asm | 158 ++++++++++++++++++++++++++ src/playstate/updatestats.asm | 2 +- src/ram.asm | 5 +- 7 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 src/playstate/trt.asm diff --git a/src/gamemodestate/initstate.asm b/src/gamemodestate/initstate.asm index dfd59d17..925338e6 100755 --- a/src/gamemodestate/initstate.asm +++ b/src/gamemodestate/initstate.asm @@ -47,6 +47,9 @@ gameModeState_initGameState: sta invisibleFlag sta currentFloor sta crashState + sta trtLineCounter + sta trtLineCounter+1 + sta trtScratch+5 ; initialize currentFloor if necessary lda practiseType diff --git a/src/nametables/game.js b/src/nametables/game.js index b9c0c77a..0b80a1cd 100644 --- a/src/nametables/game.js +++ b/src/nametables/game.js @@ -86,9 +86,9 @@ drawTiles(buffer, lookup, ` ʞ##ɌɍɎ#####ȱ##########Ȳ#######ʡʟ ʟ##ɜɝɞ#####ȱ##########Ȳ#######ʜʛ ʙ##########ȱ##########Ȳʟʜʕʞʟʒʝʞʡ -ʓ##ɤɥɦ#####ȱ##########Ȳʔʞʡʜʛʡʟʜʝ -ʠ##########ȱ##########Ȳʡʜʝʓʡʒʙʒʞ -ʡ##########ɲȳȳȳȳȳȳȳȳȳȳɳʟʐʑʡʟʡʜʙʟ +ʓ##ɤɥɦ#####ȱ##########Ȳɴȴȴɵʛʡʟʜʝ +ʠ##########ȱ##########Ȳȵ00ȶʡʒʙʒʞ +ʡ##########ɲȳȳȳȳȳȳȳȳȳȳɳɶȷȷɷʟʡʜʙʟ ʟʟʜʕʞʒʝʞʟʜʓʜʓʟʒʞʒʝʞʜʝʝʞʠʖʗʜʛʟʜʝʙ ʠʘʓʡʟʡʟʒʙʟʘʞʠʠʠʟʡʟʐʑʒʞʟʖʞʜʓʡʠʜʝʝ ʖʞʡʜʚʞʠʡʜʚʞʟʡʠʡʠʒʙʖʗʠʟʘʝʞʟʠʜʙʒʞʟ diff --git a/src/nmi/render_mode_play_and_demo.asm b/src/nmi/render_mode_play_and_demo.asm index 3bc2f9cb..08a31b98 100644 --- a/src/nmi/render_mode_play_and_demo.asm +++ b/src/nmi/render_mode_play_and_demo.asm @@ -13,6 +13,18 @@ render_mode_play_and_demo: jsr render_playfield @renderLines: + lda trtScratch+5 + beq LFC0C + ; lda gameMode + ; bne LFC0C + lda #$23 + sta PPUADDR + lda #$38 + sta PPUADDR + lda trtScratch+5 + jsr twoDigsToPPU +LFC0C: + lda scoringModifier bne @modernLines diff --git a/src/playstate/branch.asm b/src/playstate/branch.asm index d5e4b45c..c91eaf55 100644 --- a/src/playstate/branch.asm +++ b/src/playstate/branch.asm @@ -32,5 +32,6 @@ playState_noop: .include "garbage.asm" .include "spawnnext.asm" .include "gameover_rocket.asm" +.include "trt.asm" .include "util.asm" diff --git a/src/playstate/trt.asm b/src/playstate/trt.asm new file mode 100644 index 00000000..3c3e5514 --- /dev/null +++ b/src/playstate/trt.asm @@ -0,0 +1,158 @@ +trtCalculate: + ldx completedLines + cpx #$04 + bne @notTetris +@addToLineCounter: + inc trtLineCounter + lda trtLineCounter + and #$0F + cmp #$0A + bmi @noCarry + lda trtLineCounter + clc + adc #$06 + sta trtLineCounter + and #$F0 + cmp #$A0 + bcc @noCarry + lda trtLineCounter + and #$0F + sta trtLineCounter + inc trtLineCounter+1 +@noCarry: + dex + bne @addToLineCounter +@notTetris: + lda #$00 + ldx #$06 +@zeroScratch: + sta trtLineCounter+1,x + dex + bne @zeroScratch + ldy #$04 + lda trtLineCounter + sta trtRam+2 + lda trtLineCounter+1 + sta trtRam+1 +LFA41: clc + ldx #$03 +LFA44: rol trtRam,x + dex + bne LFA44 + dey + bne LFA41 +LFA4D: jsr LFADF + lda trtScratch+4 + cmp trtRam + bcc LFA6C + bne LFA85 + lda trtScratch+3 + cmp trtRam+1 + bcc LFA6C + bne LFA85 + lda trtScratch+2 + cmp trtRam+2 + bcs LFA85 +LFA6C: ldx #$03 +LFA6E: lda trtScratch+1,x + sta trtRam+3,x + dex + bne LFA6E + lda trtScratch+5 + adc #$10 + sta trtScratch+5 + cmp #$A0 + bne LFA4D + beq LFABD +LFA85: ldx #$03 +LFA87: lda trtRam+3,x + sta trtScratch+1,x + dex + bne LFA87 + ldy #$04 +LFA92: asl trtScratch+2 + rol trtScratch+3 + rol trtScratch+4 + dey + bne LFA92 +LFA9E: jsr LFADF + inc trtScratch+5 + lda trtScratch+4 + cmp trtLineCounter+1 + bcc LFAB6 + bne LFABD + lda trtScratch+3 + cmp trtLineCounter + bcs LFABD +LFAB6: lda trtScratch+5 + cmp #$A0 + bne LFA9E +LFABD: lda trtScratch+5 + and #$0F + cmp #$0A + bne LFACE + lda trtScratch+5 + adc #$05 + sta trtScratch+5 +LFACE: lda trtScratch+5 + cmp #$01 + bne LFADA + lda #$00 + sta trtScratch+5 +LFADA: + ; lda holdDownPoints + ; cmp #$02 + rts + +LFADF: lda lines + and #$0F + sta trtScratch+1 + lda trtScratch+2 + and #$0F + clc + adc trtScratch+1 + tax + lda trtScratch+2 + and #$F0 + adc trtBCDTable,x + cmp #$A0 + bcc LFB01 + adc #$5F + inc trtScratch+3 +LFB01: sta trtScratch+2 + lda lines + and #$F0 + sta trtScratch+1 + lda trtScratch+2 + clc + adc trtScratch+1 + bcc LFB19 + inc trtScratch+3 + adc #$5F +LFB19: cmp #$A0 + bcc LFB22 + adc #$5F + inc trtScratch+3 +LFB22: sta trtScratch+2 + lda trtScratch+3 + clc + adc lines+1 + sta trtScratch+3 + and #$0F + cmp #$0A + bcc LFB3C + lda trtScratch+3 + adc #$05 + sta trtScratch+3 +LFB3C: lda trtScratch+3 + cmp #$A0 + bcc LFB48 + adc #$5F + inc trtScratch+4 +LFB48: sta trtScratch+3 + rts + +trtBCDTable: + .byte $00,$01,$02,$03,$04,$05,$06,$07 + .byte $08,$09,$10,$11,$12,$13,$14,$15 + .byte $16,$17,$18 diff --git a/src/playstate/updatestats.asm b/src/playstate/updatestats.asm index 83b07592..e9a12689 100644 --- a/src/playstate/updatestats.asm +++ b/src/playstate/updatestats.asm @@ -182,6 +182,7 @@ checkLinecap: ; set linecapState @floorLinecapEnd: addPoints: + jsr trtCalculate inc playState lda practiseType cmp #MODE_CHECKERBOARD @@ -211,7 +212,6 @@ addPointsRaw: .if NO_SCORING rts .endif - lda holdDownPoints cmp #$02 bmi @noPushDown diff --git a/src/ram.asm b/src/ram.asm index f021f206..ebee7c65 100755 --- a/src/ram.asm +++ b/src/ram.asm @@ -164,7 +164,10 @@ currentPpuCtrl: .res 1 ; $00FF stack: .res $FF ; $0100 .res 1 oamStaging: .res $100 ; $0200 ; format: https://wiki.nesdev.com/w/index.php/PPU_programmer_reference#OAM - .res $F0 +trtLineCounter: .res $2 +trtScratch: .res $6 +trtRam: .res $8 + .res $E0 statsByType: .res $E ; $03F0 .res 2 playfield: .res $c8 ; $0400 From 07b12755c65be25ae7913e3520d782e03ee2f5ef Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 5 Jan 2026 11:09:20 +0000 Subject: [PATCH 02/37] menu --- .gitignore | 1 + build.js | 9 + src/gamemode/gametypemenu/linecap.asm | 236 ---- src/gamemode/gametypemenu/menu.asm | 1515 ++++++++++++++---------- src/gamemode/gametypemenu/menu.js | 386 ++++++ src/gamemode/gametypemenu/menudata.asm | 843 +++++++++++++ src/gamemode/gametypemenu/menudata.js | 551 +++++++++ src/gamemode/gametypemenu/menuram.asm | 8 + src/gamemode/levelmenu.asm | 24 +- src/gamemodestate/pause.asm | 7 +- src/modes/crash.asm | 4 +- src/nametables.asm | 2 - src/nametables/game_type_menu.js | 76 +- src/nmi/nmi.asm | 32 +- src/nmi/render.asm | 53 +- src/ram.asm | 71 +- src/sprites/bytesprite.asm | 43 +- src/sprites/loadsprite.asm | 10 + src/util/core.asm | 9 - src/util/strings.asm | 128 +- tools/disasm.js | 69 ++ 21 files changed, 2968 insertions(+), 1109 deletions(-) delete mode 100644 src/gamemode/gametypemenu/linecap.asm create mode 100644 src/gamemode/gametypemenu/menu.js create mode 100644 src/gamemode/gametypemenu/menudata.asm create mode 100644 src/gamemode/gametypemenu/menudata.js create mode 100644 src/gamemode/gametypemenu/menuram.asm create mode 100644 tools/disasm.js diff --git a/.gitignore b/.gitignore index bd214c44..07ad212d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.chr *.pyc *.bin +*.txt tetris.lst tetris.lbl tetris.map diff --git a/build.js b/build.js index aaa24637..f20953a3 100644 --- a/build.js +++ b/build.js @@ -97,6 +97,13 @@ if (args.includes('--')) { console.log(); +// build menu +if (!args.includes('-M')) { + console.time('menu'); + require('./src/gamemode/gametypemenu/menu'); + console.timeEnd('menu'); +} + // build / compress nametables console.time('nametables'); @@ -226,3 +233,5 @@ if (args.includes('-T')) { console.log(`\nrunning single test: ${singleTest}`); execArgs('cargo', [...'run --release --manifest-path tests/Cargo.toml -- -T'.split(' '), singleTest]); } + +require('./tools/disasm'); diff --git a/src/gamemode/gametypemenu/linecap.asm b/src/gamemode/gametypemenu/linecap.asm deleted file mode 100644 index 11982391..00000000 --- a/src/gamemode/gametypemenu/linecap.asm +++ /dev/null @@ -1,236 +0,0 @@ -linecapMenu: - -linecapMenuCursorIndices := 3 - lda #$8 - sta renderMode - jsr updateAudioWaitForNmiAndDisablePpuRendering - jsr disableNmi - - jsr clearNametable - - jsr bulkCopyToPpu - .addr linecapMenuNametable - - lda #RENDER_LINES - sta renderFlags - - lda #$02 - sta soundEffectSlot1Init - - jsr waitForVBlankAndEnableNmi - jsr updateAudioWaitForNmiAndResetOamStaging - jsr updateAudioWaitForNmiAndEnablePpuRendering - jsr updateAudioWaitForNmiAndResetOamStaging - lda #$10 - sta sleepCounter -@menuLoop: - jsr updateAudioWaitForNmiAndResetOamStaging - - jsr linecapMenuRenderSprites - jsr linecapMenuControls - - lda newlyPressedButtons_player1 - and #BUTTON_B - bne @back - beq @menuLoop -@back: - - lda #$02 - sta soundEffectSlot1Init - jmp gameMode_gameTypeMenu - -linecapMenuRenderSprites: - ; when - clc - lda #LINECAP_WHEN_STRING_OFFSET - adc linecapWhen - sta spriteIndexInOamContentLookup - lda #$6F - sta spriteYOffset - lda #$B0 - sta spriteXOffset - jsr stringSpriteAlignRight - - ; how - clc - lda #LINECAP_HOW_STRING_OFFSET - adc linecapHow - sta spriteIndexInOamContentLookup - lda #$8F - sta spriteYOffset - lda #$B0 - sta spriteXOffset - jsr stringSpriteAlignRight - - ldx linecapCursorIndex - lda linecapCursorYOffset, x - sta spriteYOffset - lda #$40 - sta spriteXOffset - lda #$1D - sta spriteIndexInOamContentLookup - jsr loadSpriteIntoOamStaging - rts - -linecapMenuControls: - lda #BUTTON_DOWN - jsr menuThrottle - beq @downEnd - lda #$01 - sta soundEffectSlot1Init - - inc linecapCursorIndex - lda linecapCursorIndex - cmp #linecapMenuCursorIndices - bne @downEnd - lda #0 - sta linecapCursorIndex -@downEnd: - - lda #BUTTON_UP - jsr menuThrottle - beq @upEnd - lda #$01 - sta soundEffectSlot1Init - dec linecapCursorIndex - lda linecapCursorIndex - cmp #$FF - bne @upEnd - lda #linecapMenuCursorIndices-1 - sta linecapCursorIndex -@upEnd: - - jsr linecapMenuControlsLR - rts - -linecapMenuControlsLR: - lda linecapCursorIndex - jsr switch_s_plus_2a - .addr linecapMenuControlsWhen - .addr linecapMenuControlsLinesLevel - .addr linecapMenuControlsHow -linecapMenuControlsWhen: - lda newlyPressedButtons_player1 - and #BUTTON_LEFT|BUTTON_RIGHT - beq @ret - lda #$01 - sta soundEffectSlot1Init - lda #RENDER_LINES - sta renderFlags - lda linecapWhen - eor #1 - sta linecapWhen -@ret: - rts - -linecapMenuControlsLinesLevel: - lda #BUTTON_RIGHT - jsr menuThrottle - beq @notRight - lda linecapWhen - bne linecapMenuControlsAdjLinesUp - lda #1 - jsr linecapMenuControlsAdjLevel -@notRight: - - lda #BUTTON_LEFT - jsr menuThrottle - beq @notLeft - lda linecapWhen - bne linecapMenuControlsAdjLinesDown - lda #$FF - jsr linecapMenuControlsAdjLevel -@notLeft: - rts - -linecapMenuControlsAdjLevel: - sta tmpZ - clc - lda linecapLevel - adc tmpZ - sta linecapLevel - -linecapMenuControlsBoopAndRender: - lda #$01 - sta soundEffectSlot1Init - lda #RENDER_LINES - sta renderFlags - rts - -linecapMenuControlsAdjLinesUp: - clc - lda linecapLines - adc #$10 - cmp #$A0 - beq @overflowLines - sta linecapLines - bne @noverflow -@overflowLines: - lda #0 - sta linecapLines - clc - lda linecapLines+1 - adc #1 - and #$1F - sta linecapLines+1 -@noverflow: - jmp linecapMenuControlsBoopAndRender - -linecapMenuControlsAdjLinesDown: - sec - lda linecapLines - beq @overflowLines - sbc #$10 - sta linecapLines - jmp @noverflow -@overflowLines: - lda #$90 - sta linecapLines - sec - lda linecapLines+1 - sbc #1 - and #$1F - sta linecapLines+1 -@noverflow: - jmp linecapMenuControlsBoopAndRender - - -linecapMenuControlsHow: - lda #BUTTON_RIGHT - jsr menuThrottle - beq @notRight - lda #$01 - sta soundEffectSlot1Init - inc linecapHow - lda linecapHow - cmp #4 - bne @notRight - lda #0 - sta linecapHow -@notRight: - - lda #BUTTON_LEFT - jsr menuThrottle - beq @notLeft - lda #$01 - sta soundEffectSlot1Init - dec linecapHow - lda linecapHow - cmp #$FF - bne @notLeft - lda #3 - sta linecapHow -@notLeft: - rts - -linecapMenuNametable: ; stripe - .byte $21, $0A, 12, 'L','I','N','E','C','A','P',' ','M','E','N','U' - .byte $21, $CA, 4, 'W','H','E','N' - .byte $22, $4A, 3, 'H','O','W' - .byte $21, $2A, $4C, $39 - .byte $FF - -linecapCursorYOffsetOffset := $6F - -linecapCursorYOffset: - .byte 0+linecapCursorYOffsetOffset, 8+linecapCursorYOffsetOffset, 32+linecapCursorYOffsetOffset diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index 9ce4695d..6e299f0a 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -1,613 +1,920 @@ -.include "linecap.asm" +; to do +; get into game +; do arbitrary action +; get back into menu from game or level menu +; get back into menu from game w/block tool on +; each title associated with action +; more sanity checks +; set defaults +; save/restore to/from sram + + +AUTO_MENU_VARS_HI = >autoMenuVars + +; valid background chars are 0-253 +EOL = $FE +EOF = $FF +NORAM = $00 + +MENU_TITLE_PPU = $2106 +MENU_STRIPE_WIDTH = 20 +MENU_ROWS = 9 +MENU_STACK = $DF ; $01C8 - $01DF intended range + +MODE_DEFAULT = 0 ; needs to be auto generated + +menuDataStart: +.include "menudata.asm" +.out .sprintf("Menu data: %d", *-menuDataStart) + +; tttnnnnnn n = mode +PAGE_DEFAULT = %00000000 + +; table of first items instead +; + table of item counts + +VALUE_MASK = %00011111 +TYPE_MASK = %11100000 + +; tttnnnnn +TYPE_UNUSED = %00000000 +TYPE_NUMBER = %00100000 ; n = limit +TYPE_CHOICES = %01000000 ; n = wordlist index +TYPE_FF_OFF = %01100000 ; n = limit + +TYPE_HEX = %10000000 ; n = digits +TYPE_MODE_ONLY = %10100000 ; n = mode +TYPE_BCD = %11000000 ; n = digits, v bit to differentiate from hex +TYPE_SUBMENU = %11100000 ; n = menu index + +DIGIT_MASK = %10100000 +DIGIT_COMPARE = %10000000 + + gameMode_gameTypeMenu: .if NO_MENU - inc gameMode - rts + inc gameMode + rts .endif - jsr makeNotReady - jsr calc_menuScrollY - sta menuScrollY - lda #0 - sta hideNextPiece - lda #$1 - sta renderMode - jsr updateAudioWaitForNmiAndDisablePpuRendering - jsr disableNmi - jsr bulkCopyToPpu - .addr title_palette - jsr copyRleNametableToPpu - .addr game_type_menu_nametable - lda #$28 - sta tmp3 - jsr copyRleNametableToPpuOffset - .addr game_type_menu_nametable_extra + jsr updateAudioWaitForNmiAndDisablePpuRendering + jsr disableNmi + jsr bulkCopyToPpu + .addr title_palette + jsr copyRleNametableToPpu + .addr game_type_menu_nametable .if INES_MAPPER <> 0 - lda #CHRBankSet0 - jsr changeCHRBanks + lda #CHRBankSet0 + jsr changeCHRBanks .endif - lda #NMIEnable - sta currentPpuCtrl - jsr waitForVBlankAndEnableNmi - jsr updateAudioWaitForNmiAndResetOamStaging - jsr updateAudioWaitForNmiAndEnablePpuRendering - jsr updateAudioWaitForNmiAndResetOamStaging + lda #NMIEnable + sta currentPpuCtrl + jsr waitForVBlankAndEnableNmi + jsr updateAudioWaitForNmiAndResetOamStaging + jsr updateAudioWaitForNmiAndEnablePpuRendering + jsr updateAudioWaitForNmiAndResetOamStaging + + lda #AUTO_MENU_VARS_HI + sta byteSpriteAddr+1 + lda #$1 + sta renderMode + lda #0 + sta hideNextPiece + sta byteSpriteTile + sta gameStarted + jsr makeNotReady + +; check to see if returning from level menu or game + ldy activeMenu + iny + bne @initMenu + jsr exitSubmenuNoSfx + jmp gameTypeLoop +@initMenu: + lda #MENU_STACK + sta menuStackPtr + lda #0 + jsr enterMenu gameTypeLoop: - ; memset FF-02 used to happen every loop - ; but it's done in ResetOamStaging anyway? - jmp seedControls - -gameTypeLoopContinue: - jsr menuConfigControls - jsr practiseTypeMenuControls - -gameTypeLoopCheckStart: - lda newlyPressedButtons_player1 - cmp #BUTTON_START - bne gameTypeLoopNext - - ; check double killscreen - lda practiseType - cmp #MODE_KILLX2 - bne @checkSpeedTest - lda #29 - sta startLevel - sta levelNumber - lda #$00 - sta gameModeState - lda #$02 - sta soundEffectSlot1Init - - jsr bufferScreen ; hides glitchy scroll - - inc gameMode - inc gameMode - rts - -@checkSpeedTest: - ; check if speed test mode - cmp #MODE_SPEED_TEST - beq changeGameTypeToSpeedTest - cmp #MODE_LINECAP - beq gotoLinecapMenu - - ; check for seed of 0000XX - cmp #MODE_SEED - bne @checkSelectable - lda set_seed_input - bne @checkSelectable - lda set_seed_input+1 - and #$FE ; treat 0001 like 0000 - beq gameTypeLoopNext - -@checkSelectable: - lda practiseType - cmp #MODE_GAME_QUANTITY - bpl gameTypeLoopNext - - lda #$02 - sta soundEffectSlot1Init - inc gameMode - rts - -changeGameTypeToSpeedTest: - lda #$02 - sta soundEffectSlot1Init - lda #7 - sta gameMode - rts - -gotoLinecapMenu: - jmp linecapMenu - -gameTypeLoopNext: - jsr renderMenuVars - jsr updateAudioWaitForNmiAndResetOamStaging - jmp gameTypeLoop - -seedControls: - lda practiseType - cmp #MODE_SEED - bne gameTypeLoopContinue - - lda newlyPressedButtons_player1 - cmp #BUTTON_SELECT - bne @skipSeedSelect - lda rng_seed - sta set_seed_input - lda rng_seed+1 - sta set_seed_input+1 - lda rng_seed+1 - eor #$77 - ror - sta set_seed_input+2 -@skipSeedSelect: - - lda #BUTTON_LEFT - jsr menuThrottle - beq @skipSeedLeft - lda #$01 - sta soundEffectSlot1Init - lda menuSeedCursorIndex - bne @noSeedLeftWrap - lda #7 - sta menuSeedCursorIndex -@noSeedLeftWrap: - dec menuSeedCursorIndex -@skipSeedLeft: - - lda #BUTTON_RIGHT - jsr menuThrottle - beq @skipSeedRight - lda #$01 - sta soundEffectSlot1Init - inc menuSeedCursorIndex - lda menuSeedCursorIndex - cmp #7 - bne @skipSeedRight - lda #0 - sta menuSeedCursorIndex -@skipSeedRight: - - lda menuSeedCursorIndex - beq @skipSeedControl - - lda menuSeedCursorIndex - sbc #1 - lsr - tax ; save seed offset - - ; handle changing seed vals - - lda #BUTTON_UP - jsr menuThrottle - beq @skipSeedUp - lda #$01 - sta soundEffectSlot1Init - lda menuSeedCursorIndex - and #1 - beq @lowNybbleUp - - lda set_seed_input, x - clc - adc #$10 - sta set_seed_input, x - - jmp @skipSeedUp -@lowNybbleUp: - lda set_seed_input, x - clc - tay - and #$F - cmp #$F - bne @noWrapUp - tya - and #$F0 - sta set_seed_input, x - jmp @skipSeedUp -@noWrapUp: - tya - adc #1 - sta set_seed_input, x -@skipSeedUp: - - lda #BUTTON_DOWN - jsr menuThrottle - beq @skipSeedDown - lda #$01 - sta soundEffectSlot1Init - lda menuSeedCursorIndex - and #1 - beq @lowNybbleDown - - lda set_seed_input, x - sbc #$10 - clc - sta set_seed_input, x - - jmp @skipSeedDown -@lowNybbleDown: - lda set_seed_input, x - tay - and #$F - ; cmp #$0 ; and sets z flag - bne @noWrapDown - tya - and #$F0 - clc - adc #$F - sta set_seed_input, x - jmp @skipSeedDown -@noWrapDown: - tya - sec - sbc #1 - sta set_seed_input, x -@skipSeedDown: - - jmp gameTypeLoopCheckStart -@skipSeedControl: - jmp gameTypeLoopContinue - -menuConfigControls: - ; account for 'gaps' in config items of size zero - ; previously the offset was just set on X directly - - ldx #0 ; memory offset we want - ldy #0 ; cursor -@searchByte: - cpy practiseType - bne @notYet - lda menuConfigSizeLookup, y - beq @configEnd - ; if zero, caller will beq to skip the config - jmp @searchEnd -@notYet: - lda menuConfigSizeLookup, y - beq @noMem - inx -@noMem: - iny - jmp @searchByte -@searchEnd: - - ; actual offset now in Y - ; RAM offset now in X - - ; check if pressing left - lda #BUTTON_LEFT - jsr menuThrottle - beq @skipLeftConfig - ; check if zero - lda menuVars, x - ; cmp #0 ; lda sets z flag - beq @skipLeftConfig - ; dec value - dec menuVars, x - lda #$01 - sta soundEffectSlot1Init - jsr assertValues -@skipLeftConfig: - - ; check if pressing right - lda #BUTTON_RIGHT - jsr menuThrottle - beq @skipRightConfig - ; check if within the offset - lda menuVars, x - cmp menuConfigSizeLookup, y - bpl @skipRightConfig - inc menuVars, x - lda #$01 - sta soundEffectSlot1Init - jsr assertValues -@skipRightConfig: -@configEnd: - rts - -menuConfigSizeLookup: - MENUSIZES - -assertValues: - ; make sure you can only have block or qual - lda practiseType - cmp #MODE_QUAL - bne @noQual - lda menuVars, x - beq @noQual - lda #0 - sta debugFlag -@noQual: - lda practiseType - cmp #MODE_DEBUG - bne @noDebug - lda menuVars, x - beq @noDebug - lda #0 - sta qualFlag -@noDebug: - ; goofy - lda practiseType - cmp #MODE_GOOFY - bne @noFlip - lda heldButtons_player1 - asl - and #$AA - sta tmp3 - lda heldButtons_player1 - and #$AA - lsr - ora tmp3 - sta heldButtons_player1 -@noFlip: - rts - -practiseTypeMenuControls: - ; down - lda #BUTTON_DOWN - jsr menuThrottle - beq @downEnd - lda #$01 - sta soundEffectSlot1Init - - inc practiseType - lda practiseType - cmp #MODE_QUANTITY - bne @downEnd - lda #0 - sta practiseType -@downEnd: - - ; up - lda #BUTTON_UP - jsr menuThrottle - beq @upEnd - lda #$01 - sta soundEffectSlot1Init - lda practiseType - bne @noWrap - lda #MODE_QUANTITY - sta practiseType -@noWrap: - dec practiseType -@upEnd: - rts - -renderMenuVars: - - ; playType / seed cursors - - lda menuSeedCursorIndex - bne @seedCursor - - lda practiseType - jsr menuItemY16Offset - bne @cursorFinished - stx spriteYOffset - lda #$17 - sta spriteXOffset - lda #$1D - sta spriteIndexInOamContentLookup - jsr loadSpriteIntoOamStaging - jmp @cursorFinished - -@seedCursor: - clc - lda #MENU_SPRITE_Y_BASE + 7 - sbc menuScrollY - sta spriteYOffset - lda menuSeedCursorIndex - asl a - asl a - asl a - adc #$B1 - sta spriteXOffset - lda #$1B - sta spriteIndexInOamContentLookup - jsr loadSpriteIntoOamStaging - - ; indicator - - lda set_seed_input - bne @renderIndicator - lda set_seed_input+1 - and #$FE ; treat 0001 like 0000 - beq @cursorFinished -@renderIndicator: - ldx #$E - lda set_seed_input+2 - and #$F0 - beq @v5 - lda set_seed_input - bne @v4 - lda set_seed_input+1 - beq @v5 - jmp @v4 -@v5: - ldx #$F -@v4: - stx spriteIndexInOamContentLookup - sec - lda #(MODE_SEED*8) + MENU_SPRITE_Y_BASE + 1 - sbc menuScrollY - sta spriteYOffset - lda #$A0 - sta spriteXOffset - jsr stringSprite - -@cursorFinished: - -menuCounter := tmp1 -menuRAMCounter := tmp3 -menuYTmp := tmp2 - - ; render seed - - lda #$b8 - sta spriteXOffset - lda #MODE_SEED - jsr menuItemY16Offset - bne @notSeed - stx spriteYOffset - lda #set_seed_input - sta byteSpriteAddr - lda #0 - sta byteSpriteAddr+1 - lda #0 - sta byteSpriteTile - lda #3 - sta byteSpriteLen - jsr byteSprite -@notSeed: - - ; render config vars - - ; YTAX - lda #0 - sta menuCounter - sta menuRAMCounter + lda gameStarted + beq @noGame + inc gameMode + lda #$2 + sta soundEffectSlot1Init + rts +@noGame: + ; todo: write down which vars are used by which func + jsr collectControllerInput + jsr setScratch + jsr addInputs + jsr respondToInput + jsr stageCursor + + ; scratch is not important anymore + jsr stageBackgroundTiles + jsr stageCurrentValues +gameTypeLoopWait: + jsr updateAudioWaitForNmiAndResetOamStaging + jmp gameTypeLoop + + +.out .sprintf("bg setup & loop: %d", *-gameMode_gameTypeMenu) + +.macro switchToMenuStack + tsx + stx stackPtr + ldx menuStackPtr + txs +.endmacro + +.macro switchToNormalStack + tsx + stx menuStackPtr + ldx stackPtr + txs +.endmacro + +enterSubMenu: + ldy #$02 + sty soundEffectSlot1Init + pha + switchToMenuStack + lda activeRow + pha + lda activePage + pha + lda activeMenu + pha + switchToNormalStack + pla +enterMenu: + sta activeMenu + tay + iny + bne @normalMenu + rts +@normalMenu: + lda #0 +enterPage: + sta activePage + sta originalPage + ldy activeMenu + clc + adc startPageByMenu,y + sta actualPage + tax + + lda pageTypes,x + and #VALUE_MASK + sta unpackedPageValue ; always 0 for now + + lda pageTypes,x + and #TYPE_MASK + sta unpackedPageType + + lda pageCountByMenu,y + ldy #$00 + sty activeColumn + cmp #$1 + beq @storeRow + dey ; start at page select row for multipage + dec unpackedPageType ; hack for now +@storeRow: + sty activeRow + +setScratch: + ldx actualPage + lda activeRow + clc + adc startItemByPage,x + sta activeItem + tax + lda itemTypes,x + tay + and #VALUE_MASK + sta unpackedItemValue + + tya + and #TYPE_MASK + sta unpackedItemType + + jsr setupLR + jmp setupUD + +exitSubmenu: + ldy #$02 + sty soundEffectSlot1Init + +exitSubmenuNoSfx: + switchToMenuStack + pla + switchToNormalStack + + jsr enterMenu + + switchToMenuStack + pla + switchToNormalStack + + jsr enterPage + + switchToMenuStack + pla + switchToNormalStack + + sta activeRow + jmp setScratch + + +setupUD: + ldy activeColumn + bne setupUDDigitChange + +setupUDRowChange: +; ud change row 1/2 - activeColumn == 0 + ldy #$00 + lda unpackedPageType + bpl @storeMin ; no page select row for single page + dey +@storeMin: + sty udMin + ldx actualPage + lda itemCountByPage,x + sta udMax + + lda #>activeRow + sta udPointer+1 + lda # 0 + dey + tya + lsr + tay ; y points to digit + php ; save for later, carry clear if hi byte + lda #$0 + sta udMin + sta udPointer+1 ; won't work if nybbleTemp is not zeropage + lda #activePage + sta lrPointer+1 + lda #= 0 && itemType < 128 + lda #AUTO_MENU_VARS_HI + sta lrPointer+1 + ldx activeItem + lda memoryOffsets,x + sta lrPointer + ldy #$0 + lda unpackedItemType + and #TYPE_MASK + cmp #TYPE_FF_OFF + bne @storeMin + dey +@storeMin: + sty lrMin + ldx unpackedItemValue + cmp #TYPE_CHOICES + bne @storeMax + lda choiceSetCounts,x + tax +@storeMax: + stx lrMax + rts + +setupLRColumnChange: +; setupLRColumnChange itemType & %10100000 == %10000000 + lda #0 + sta lrMin + lda #>activeColumn + sta lrPointer+1 + lda #MENU_TITLE_PPU + sta stack + lda # high byte of offset in A -; -> low byte in X -menuItemY16Offset: - sta tmpY - lda #8 - sta tmpX - ; get 16bit menuitem * 8 in tmpX/tmpY - lda #$0 - ldx #$8 - clc -@mulLoop: - bcc @mulLoop1 - clc - adc tmpY -@mulLoop1: - ror - ror tmpX - dex - bpl @mulLoop - sta tmpY - ; add offset - clc - lda tmpX - adc #MENU_SPRITE_Y_BASE + 1 - sta tmpX - lda tmpY - adc #0 - sta tmpY - ; remove menuscroll - sec - lda tmpX - sbc menuScrollY - sta tmpX - tax - lda tmpY - sbc #0 - rts - -bufferScreen: - lda #$0 - sta renderMode - jsr updateAudioWaitForNmiAndDisablePpuRendering - jsr disableNmi - jsr drawBlackBGPalette - jsr resetScroll - jsr waitForVBlankAndEnableNmi - jsr updateAudioWaitForNmiAndResetOamStaging - jsr updateAudioWaitForNmiAndEnablePpuRendering - jsr updateAudioWaitForNmiAndResetOamStaging - lda #$3 - sta sleepCounter -@endLoop: - jsr updateAudioWaitForNmiAndResetOamStaging - lda sleepCounter - bne @endLoop - rts + ldy #0 + lda (@stringPtr),y + tay + iny + beq @fillBlank ; stop advancing pointer when $FF is reached + inc @stringPtr + bne @noCarry + inc @stringPtr+1 +@noCarry: + iny + beq @fillBlank ; $FE also blanks line but after advancing pointer + sta stack,x + dec @blankCounter + inx + bne @loop ; always taken +@fillBlank: ; should only be entered directly when end of string reached + dec @blankCounter + bmi @finishRow + lda #$FF + sta stack,x + inx + bne @fillBlank ; always taken + +@finishRow: +; check if all rows drawn + dec @rowCounter + beq @shiftTitleRow + +; set next row based on last row + lda stack-((MENU_STRIPE_WIDTH+2)-1),x + clc + adc #$40 + sta stack+1,x + lda stack-(MENU_STRIPE_WIDTH+2),x + adc #$00 + sta stack,x + inx + inx + bne @nextRow ; always taken +@shiftTitleRow: +; bump title row 4 tiles to the right + lda stack+1 + eor #%1111 + sta stack+1 + rts + + +.out .sprintf("background staging: %d", *-stageBackgroundTiles) + + +stageCurrentValues: + @counter = blankCounter + @itemCount = rowCounter + + lda #$00 + sta @counter + lda #AUTO_MENU_VARS_HI + + ldx actualPage + lda startItemByPage,x + + sta activeItem + lda itemCountByPage,x + + sta @itemCount + + lda#(MENU_STRIPE_WIDTH+2) - 8 + sta stackPtr + +@memoryStageLoop: + lda stackPtr + clc + adc #MENU_STRIPE_WIDTH+2 + sta stackPtr + tax + + ldy activeItem + lda memoryOffsets,y + sta byteSpriteAddr + lda #AUTO_MENU_VARS_HI + sta byteSpriteAddr+1 + lda itemTypes,y + tax + ldy #0 + and #TYPE_MASK + bmi @digitInputOrEdge + + cmp #TYPE_CHOICES + beq @drawString + + cmp #TYPE_NUMBER + bne @drawFFOff +@setupOneByte: + lda #$02 + bne @drawOneByte + +@drawFFOff: + lda (byteSpriteAddr),y + bpl @setupOneByte + ldx #CHOICESET_OFFON + jsr @setStringList + jmp @startCopy + +@drawString: + txa + and #%11111 + tax + jsr @setStringList + lda (byteSpriteAddr),y + tay +@startCopy: + lda (stringSetPtr),y + tay + lda choiceSetTable,y + beq @endCopy + sta generalCounter + jsr setStackOffset + iny +@nextChar: + lda choiceSetTable,y + sta stack,x + inx + iny + dec generalCounter + bne @nextChar + +@endCopy: + jmp @nextByte + +@setStringList: + lda choiceSetIndexes,x + clc + adc #choiceSets + sta stringSetPtr+1 + rts + +@digitInputOrEdge: + and #TYPE_MASK + cmp #TYPE_MODE_ONLY + beq @nextByte + cmp #TYPE_SUBMENU + beq @nextByte + txa + and #%11111 +@drawOneByte: + pha + sec + sbc #1 + lsr + clc + adc #$1 + sta generalCounter + pla + + jsr setStackOffset + ldy #$00 +@digitLoop: + lda (byteSpriteAddr),y + pha + lsr + lsr + lsr + lsr + sta stack,x + inx + pla + and #$0F + sta stack,x + inx + iny + dec generalCounter + bne @digitLoop + jmp @nextByte + +@nextByte: + inc activeItem + inc @counter + lda @counter + cmp @itemCount + beq @ret + jmp @memoryStageLoop +@ret: + rts + +setStackOffset: + eor #$FF + clc + adc #$09 + clc + adc stackPtr + tax + rts + + +.out .sprintf("value staging: %d", *-stageCurrentValues) + + +stageCursor: + ldx activeMenu + lda pageCountByMenu,x + cmp #$1 + beq @singlePage + ldx oamStagingLength + sta oamStaging+9,x + lda #$4F + sta oamStaging+5,x + + lda #$CB + sta oamStaging+0,x + sta oamStaging+4,x + sta oamStaging+8,x + + lda #$C8 + sta oamStaging+3,x + clc + adc #$08 + sta oamStaging+7,x + adc #$08 + sta oamStaging+11,x + + lda #$00 + sta oamStaging+2,x + sta oamStaging+6,x + sta oamStaging+10,x + + ldy activePage + iny + tya + sta oamStaging+1,x + txa + clc + adc #$C + sta oamStagingLength + +@singlePage: + + lda activeRow + bpl @notTitle + + lda #$3F + sta spriteYOffset + lda #$10 + sta spriteXOffset + lda #$23 ; page select + sta spriteIndexInOamContentLookup + jmp loadSpriteIntoOamStaging + +@notTitle: + asl + asl + asl + asl + clc + adc #$4F + sta spriteYOffset +; digit input + ldx activeColumn + beq @notColumn + sec + sbc #$09 + sta spriteYOffset + txa + asl + asl + asl + clc + adc #$B9 + sta spriteXOffset + ldx activeItem + lda itemTypes,x + and #VALUE_MASK + sec + sbc #1 + lsr + asl + asl + asl + asl + eor #$FF + clc + adc #$01 + clc + adc spriteXOffset + sta spriteXOffset + lda #$1B ; digit select + bne @store +@notColumn: + lda #$14 + sta spriteXOffset + lda #$1D ; option select +@store: + sta spriteIndexInOamContentLookup +@stage: + jmp loadSpriteIntoOamStaging +gotoEdgeCase: + rts + + +.out .sprintf("cursor staging: %d", *-stageCursor) + + +render_mode_menu: + tsx + txa + ldx #$ff + txs + tax + ldy #MENU_ROWS +@nextRow: + pla + sta PPUADDR + pla + sta PPUADDR + .repeat MENU_STRIPE_WIDTH + pla + sta PPUDATA + .endrepeat + dey + bne @nextRow + txs + rts + + +.out .sprintf("render dump: %d", *-render_mode_menu) + + +.out .sprintf("total: %d", *-gameMode_gameTypeMenu) diff --git a/src/gamemode/gametypemenu/menu.js b/src/gamemode/gametypemenu/menu.js new file mode 100644 index 00000000..622ce576 --- /dev/null +++ b/src/gamemode/gametypemenu/menu.js @@ -0,0 +1,386 @@ +const { mainMenu, extraSpriteStrings } = require("./menudata"); +const { writeFileSync } = require("fs"); + +MAX_LENGTH_NAME = 14; +MAX_LENGTH_VALUE = 8; +DEBUG = false; + +labelMap = { + TYPE_BCD: typeDigit, + TYPE_HEX: typeDigit, + TYPE_NUMBER: typeNumber, + TYPE_FF_OFF: typeNumber, + TYPE_CHOICES: typeChoices, + TYPE_MODE_ONLY: getOutputLines, + TYPE_SUBMENU: typeSubMenu, + TYPE_BOOL: typeBool, +}; + +addedStrings = []; +buffer = []; +choiceSetCounts = []; +choiceSetEnums = []; +choiceSetIndexes = []; +choiceSets = []; +index = 0; +items = []; +lookupConstants = []; +memoryBuffer = []; +memoryMap = []; +memoryReservations = {}; +menuCount = 0; +menuEnums = []; +newStringLines = []; +pageCountByMenu = []; +pageIndex = 0; +pageLabelText = {}; +pagesOutput = []; +startItemByPage = []; +startPageByMenu = []; +unlabeledStringSets = {}; + +function checkStringSanity(string) { + if (string.length > MAX_LENGTH_VALUE) { + throw new Error(`${string} is more than MAX_LENGTH_VALUE chars`); + } + if ((match = string.match(/[^- a-z0-9_?!*]/i))) { + throw new Error(`${string} has invalid char '${match[0]}'`); + } +} + +function cleanWord(word) { + word = word.toLowerCase().replace(/\b\w/g, (c) => c.toUpperCase()); + return word.replace(/[- *?!(),\/]/g, ""); +} + +function getStringName(word) { + return `string${cleanWord(word)}`; +} + +function getChoiceSetName(word) { + return `choiceSet${cleanWord(word)}`; +} + +function getStringConstant(name) { + return `STRING_${cleanWord(name).toUpperCase()}`; +} + +function getChoiceSetConstant(name) { + return `CHOICESET_${cleanWord(name).toUpperCase()}`; +} + +function getByteLine(byte) { + return ` .byte ${byte}`; +} + +function getHexByte(number) { + if (isNaN(number)) return number; + return `$${number.toString(16).padStart(2, "0").toUpperCase()}`; +} + +function getOutputLines(itemType, string, memory) { + return { + string: string, + label: getByteLine(`${itemType} ; ${string}`), + memory: memory, // has to be processed separately to get output line + }; +} + +function getStringByte(c) { + replaceMap = { + ",": "$25", + "/": "$4F", + "(": "$5E", + ")": "$5F", + "*": "$69", // KSx2 x + " ": "$EF", + }; + return replaceMap[c] ? replaceMap[c] : `"${c.toUpperCase()}"`; +} + +function getStringBytes(string) { + return [...string.split("").map((c) => getStringByte(c))].join(","); +} + +function getLineString(string, multiline = false) { + if (string.length > MAX_LENGTH_NAME) { + throw new Error(`${string} is more than MAX_LENGTH_NAME chars`); + } + + return multiline + ? string + .split("") + .map((c) => getByteLine(getStringByte(c))) + .join("\n") + : getByteLine(getStringBytes(string)); +} + +function getPageLines(title, page, pages) { + DEBUG && console.log(`getPageLines`, title, page, pages); + pageType = "PAGE_DEFAULT"; + [_, label, mode] = title.match(/([^[]*)(?:\s*\[mode=(\w+)\])?/i); + const modifier = mode ? `MODE_${mode.toUpperCase()}` : "MODE_DEFAULT"; + const pagelabelsName = `pageLabels${cleanWord(label)}`; + + const endLabel = getByteLine("EOL"); + const endLabelSet = getByteLine("EOF"); + + pageLabelTextLines = []; + pageLabelTextLines.push(`${pagelabelsName}:`); + padding = [...Array(Math.round((MAX_LENGTH_NAME - label.length) / 2))] + .map(() => " ") + .join(""); + pageLabelTextLines.push(getLineString(`${padding}${label}`)); + pageLabelTextLines.push(endLabel); + page.forEach((p, i) => { + pageLabelTextLines.push(getLineString(p[1])); + if (i + 1 != page.length) pageLabelTextLines.push(endLabel); + }); + pageLabelTextLines.push(endLabelSet); + joined = pageLabelTextLines.join("\n"); + existing = pageLabelText[joined]; + if (!existing) pageLabelText[joined] = pagelabelsName; + + return { + label: getByteLine(`${pageType} | ${modifier} ; ${label}`), + count: getByteLine(`${getHexByte(page.length)} ; ${label}`), + hibytes: getByteLine( + `>${existing ? existing : pagelabelsName} ; ${label}`, + ), + lobytes: getByteLine( + `<${existing ? existing : pagelabelsName} ; ${label}`, + ), + choicesets: existing ? "" : joined, + }; +} + +function typeDigit(label, string, digits, memoryLabel) { + if (digits < 2 || digits > 8 || digits & 1) { + throw new Error(`${string}: digits can only be 2, 4, 6 or 8`); + } + memory = memoryLabel ? memoryLabel : (digits + 1) >> 1; + return getOutputLines(`${label} | ${getHexByte(digits)}`, string, memory); +} + +function typeChoices(label, string, choiceSet, memoryLabel) { + DEBUG && console.log(`Choice set ${string} with options ${choiceSet}`); + stringSet = [...choiceSet].map((c) => cleanWord(c.slice(0, 6))).join(""); + unlabeledStringSets[stringSet] = choiceSet; + return getOutputLines( + `${label} | ${getChoiceSetConstant(stringSet)}`, + string, + memoryLabel ? memoryLabel : 1, + ); +} + +function typeNumber(label, string, limit, memoryLabel) { + return getOutputLines( + `${label} | ${getHexByte(limit)}`, + string, + memoryLabel ? memoryLabel : 1, + ); +} + +function typeBool(label, string, memoryLabel) { + return typeChoices( + "TYPE_CHOICES", + string, + ["off", "on"], + memoryLabel ? memoryLabel : 1, + ); +} +function typeSubMenu(label, string) { + return getOutputLines( + `${label} | SUBMENU_${cleanWord(string).toUpperCase()}`, + `${string}`, + ); +} + +function getMemoryLabel(string, bytes) { + if (isNaN(bytes)) return bytes; // if label is specified use that instead + label = `menuVar${cleanWord(string)}`; + memoryReservations[label] = bytes; + return label; +} + +processPageSet = (pages, name) => { + DEBUG && name && console.log(`submenu ${name}`); + DEBUG && !name && console.log(`main menu`); + if (name) menuEnums.push(`SUBMENU_${cleanWord(name).toUpperCase()}`); + startPageByMenu.push( + `${getByteLine(getHexByte(pageIndex))} ; ${name ? name : "main menu"}`, + ); + // collect submenus to process after all pages + let subPageSets = {}; + Object.entries(pages).forEach(([title, page]) => { + DEBUG && console.log(`${title} with ${page.length} entries`); + pageIndex++; + startItemByPage.push( + getByteLine(`${getHexByte(index)} ; ${cleanWord(title)}`), + ); + pagesOutput.push(getPageLines(title, page, pages, index)); + page.forEach((item) => { + items.push(labelMap[item[0]](...item)); + index++; + if (item[0] === "TYPE_SUBMENU") subPageSets[item[1]] = item[2]; + }); + }); + pageCountByMenu.push( + getByteLine( + `${getHexByte(Object.values(pages).length)} ; ${name ? name : "main menu"}`, + ), + ); + + // process any submenus the same was as the main menu + Object.entries(subPageSets).forEach(([name, pages]) => { + processPageSet(pages, name); + }); +}; +processPageSet(mainMenu); + +items.forEach((i) => { + line = getByteLine( + `${i.memory ? "<" + getMemoryLabel(i.string, i.memory) : "NORAM"} ; ${i.string}`, + ); + memoryMap.push(line); +}); + +memoryBuffer.push("; generated by menu.js"); +memoryBuffer.push("autoMenuVars:"); +Object.entries(memoryReservations).forEach(([label, bytes]) => + memoryBuffer.push(`${label}: .res ${getHexByte(bytes)}`), +); +memoryBuffer.push(""); +// memory into separate file +writeFileSync(__dirname + "/menuram.asm", [...memoryBuffer, ""].join("\n")); + +[ + ["extraSpriteStrings", extraSpriteStrings], + ...Object.entries(unlabeledStringSets), +].forEach(([name, choiceSet], i) => { + if (!i) newStringLines.push("stringTable:"); + if (i == 1) { + newStringLines.push( + '\n.out .sprintf("%d/256 sprite string bytes", * - stringTable)\n', + ); + newStringLines.push("choiceSetTable:"); + } + + DEBUG && console.log(`stringlist`, name, choiceSet); + if (name != "extraSpriteStrings") { + choiceSetEnums.push(getChoiceSetConstant(name)); + choiceSetCounts.push(getByteLine(getHexByte(choiceSet.length))); + choiceSetIndexes.push( + getByteLine(`${getChoiceSetName(name)}-choiceSets`), + ); + choiceSets.push(`${getChoiceSetName(name)}:`); + } + DEBUG && console.log(`choiceSet: `, choiceSet); + choiceSet.forEach((choice) => { + choice = choice.toLowerCase(); + checkStringSanity(choice); + if (!addedStrings.includes(choice)) { + addedStrings.push(choice); + newStringLines.push(`${getStringName(choice)}:`); + newStringLines.push( + getByteLine( + `${getHexByte(choice.length)},${getStringBytes(choice)}`, + ), + ); + } + if (name == "extraSpriteStrings") { + lookupConstants.push( + `${getStringConstant(choice)} = ${getStringName(choice)}-stringTable`, + ); + } else { + choiceSets.push( + // getByteLine(`${getStringName(choice)}-${getChoiceSetName(name)}`), + getByteLine(`${getStringName(choice)}-choiceSetTable`), + ); + } + }); +}); +newStringLines.push( + '\n.out .sprintf("%d/256 choice set bytes", * - choiceSetTable)\n', +); + +buffer.push("; generated by menu.js"); +buffer.push("; will be overwritten unless built with -M"); +buffer.push(""); + +buffer.push(...lookupConstants); +buffer.push(""); + +buffer.push(".enum"); +buffer.push("MAIN_MENU"); +buffer.push(...menuEnums); +buffer.push("MENU_COUNT"); +buffer.push(".endenum"); +buffer.push('\n.out .sprintf("%d/32 menus", MENU_COUNT)\n'); +buffer.push(""); + +buffer.push(".enum"); +buffer.push(...choiceSetEnums); +buffer.push("CHOICESET_COUNT"); +buffer.push(".endenum"); +buffer.push('\n.out .sprintf("%d/32 choicesets", CHOICESET_COUNT)\n'); +buffer.push(""); + +buffer.push("; index activeMenu"); +buffer.push("startPageByMenu:"); +buffer.push(...startPageByMenu); +buffer.push(""); + +buffer.push("pageCountByMenu:"); +buffer.push(...pageCountByMenu); +buffer.push(""); + +buffer.push("; index activePage"); +buffer.push("pageTypes:"); +buffer.push(...pagesOutput.map((p) => p.label)); +buffer.push(""); + +buffer.push("itemCountByPage:"); +buffer.push(...pagesOutput.map((p) => p.count)); +buffer.push(""); + +buffer.push("pageLabelsHi:"); +buffer.push(...pagesOutput.map((p) => p.hibytes)); +buffer.push(""); + +buffer.push("pageLabelsLo:"); +buffer.push(...pagesOutput.map((p) => p.lobytes)); +buffer.push(""); + +buffer.push("startItemByPage:"); +buffer.push(...startItemByPage); +buffer.push(""); + +buffer.push("; index activeItem"); +buffer.push("memoryOffsets:"); +buffer.push(...memoryMap); +buffer.push(""); + +buffer.push("itemTypes:"); +buffer.push(...items.map((i) => i.label)); +buffer.push(""); + +buffer.push("choiceSetIndexes:"); +buffer.push(...choiceSetIndexes); +buffer.push(""); + +buffer.push("choiceSetCounts:"); +buffer.push(...choiceSetCounts); +buffer.push(""); + +buffer.push("choiceSets:"); +buffer.push(...choiceSets); +buffer.push(""); + +buffer.push(...newStringLines); +buffer.push(""); + +buffer.push(...pagesOutput.map((p) => p.choicesets)); +buffer.push(""); + +writeFileSync(__dirname + "/menudata.asm", [...buffer, ""].join("\n")); diff --git a/src/gamemode/gametypemenu/menudata.asm b/src/gamemode/gametypemenu/menudata.asm new file mode 100644 index 00000000..d319a4e5 --- /dev/null +++ b/src/gamemode/gametypemenu/menudata.asm @@ -0,0 +1,843 @@ +; generated by menu.js +; will be overwritten unless built with -M + +STRING_PAUSE = stringPause-stringTable +STRING_BLOCK = stringBlock-stringTable +STRING_CLEAR = stringClear-stringTable +STRING_SURE = stringSure-stringTable +STRING_CONFETTI = stringConfetti-stringTable + +.enum +MAIN_MENU +SUBMENU_BOOLEANS +SUBMENU_NUMBERS +SUBMENU_DIGITS +SUBMENU_32BYTES +SUBMENU_DEBUG +SUBMENU_A +SUBMENU_TOURNAMENT +SUBMENU_DISPLAY +SUBMENU_SETTINGS +MENU_COUNT +.endenum + +.out .sprintf("%d/32 menus", MENU_COUNT) + + +.enum +CHOICESET_TETTSPSEESTAPACSETBTFLOCRUQCKTRNMARTAPCKRGARLOBDASLOWKILINVHRD +CHOICESET_OFFON +CHOICESET_ONOFF +CHOICESET_AB +CHOICESET_OFFONABSHOWTOPCRASHNEONLITETEALOGCLASSILETTER7DIGITMCAPPEDHIDDENLINESLEVELKS2FLOORINVIZHALTTETTSPSEESTAPACSETBTFLOCRUQCKTRNMARTAPCKRGARLOBDASLOWKILINVHRDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +CHOICESET_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +CHOICESET_LINESLEVEL +CHOICESET_KS2FLOORINVIZHALT +CHOICESET_CLASSILETTER7DIGITMCAPPEDHIDDEN +CHOICESET_OFFONNEONLITETEALOG +CHOICESET_OFFSHOWTOPCRASH +CHOICESET_COUNT +.endenum + +.out .sprintf("%d/32 choicesets", CHOICESET_COUNT) + + +; index activeMenu +startPageByMenu: + .byte $00 ; main menu + .byte $03 ; booleans + .byte $05 ; numbers + .byte $07 ; Digits + .byte $0A ; 32 bytes + .byte $0B ; debug + .byte $0C ; a + .byte $0D ; Tournament + .byte $0F ; Display + .byte $11 ; Settings + +pageCountByMenu: + .byte $03 ; main menu + .byte $02 ; booleans + .byte $02 ; numbers + .byte $03 ; Digits + .byte $01 ; 32 bytes + .byte $01 ; debug + .byte $01 ; a + .byte $02 ; Tournament + .byte $02 ; Display + .byte $02 ; Settings + +; index activePage +pageTypes: + .byte PAGE_DEFAULT | MODE_DEFAULT ; (new menu,*)?! + .byte PAGE_DEFAULT | MODE_DEFAULT ; kinda working + .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg + .byte PAGE_DEFAULT | MODE_DEFAULT ; boolean + .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg + .byte PAGE_DEFAULT | MODE_DEFAULT ; Numbers + .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg + .byte PAGE_DEFAULT | MODE_DEFAULT ; BCD + .byte PAGE_DEFAULT | MODE_DEFAULT ; Hex + .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg + .byte PAGE_DEFAULT | MODE_DEFAULT ; 07** + .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg + .byte PAGE_DEFAULT | MODE_DEFAULT ; aaaaaaaaaaaaaa + .byte PAGE_DEFAULT | MODE_DEFAULT ; Tournament + .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg + .byte PAGE_DEFAULT | MODE_DEFAULT ; Display + .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg + .byte PAGE_DEFAULT | MODE_DEFAULT ; Settings + .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg + +itemCountByPage: + .byte $06 ; (new menu,*)?! + .byte $04 ; kinda working + .byte $05 ; dbg + .byte $04 ; boolean + .byte $05 ; dbg + .byte $07 ; Numbers + .byte $05 ; dbg + .byte $04 ; BCD + .byte $04 ; Hex + .byte $05 ; dbg + .byte $08 ; 07** + .byte $05 ; dbg + .byte $08 ; aaaaaaaaaaaaaa + .byte $08 ; Tournament + .byte $05 ; dbg + .byte $06 ; Display + .byte $05 ; dbg + .byte $06 ; Settings + .byte $05 ; dbg + +pageLabelsHi: + .byte >pageLabelsNewMenu ; (new menu,*)?! + .byte >pageLabelsKindaWorking ; kinda working + .byte >pageLabelsDbg ; dbg + .byte >pageLabelsBoolean ; boolean + .byte >pageLabelsDbg ; dbg + .byte >pageLabelsNumbers ; Numbers + .byte >pageLabelsDbg ; dbg + .byte >pageLabelsBcd ; BCD + .byte >pageLabelsHex ; Hex + .byte >pageLabelsDbg ; dbg + .byte >pageLabels07 ; 07** + .byte >pageLabelsDbg ; dbg + .byte >pageLabelsAaaaaaaaaaaaaa ; aaaaaaaaaaaaaa + .byte >pageLabelsTournament ; Tournament + .byte >pageLabelsDbg ; dbg + .byte >pageLabelsDisplay ; Display + .byte >pageLabelsDbg ; dbg + .byte >pageLabelsSettings ; Settings + .byte >pageLabelsDbg ; dbg + +pageLabelsLo: + .byte (render_mode_static-1) + .byte >(render_mode_menu-1) + .byte >(render_mode_congratulations_screen-1) + .byte >(render_mode_play_and_demo-1) + .byte >(render_mode_pause-1) + .byte >(render_mode_rocket-1) + .byte >(render_mode_speed_test-1) + .byte >(render_mode_level_menu-1) + .byte >(render_mode_linecap_menu-1) + +renderRTSJumpLo: + .byte <(render_mode_static-1) + .byte <(render_mode_menu-1) + .byte <(render_mode_congratulations_screen-1) + .byte <(render_mode_play_and_demo-1) + .byte <(render_mode_pause-1) + .byte <(render_mode_rocket-1) + .byte <(render_mode_speed_test-1) + .byte <(render_mode_level_menu-1) + .byte <(render_mode_linecap_menu-1) + +render: + ldx renderMode + lda renderRTSJumpHi,x + pha + lda renderRTSJumpLo,x + pha + rts + +; render: lda renderMode +; jsr switch_s_plus_2a +; .addr render_mode_static +; .addr render_mode_menu +; .addr render_mode_congratulations_screen +; .addr render_mode_play_and_demo +; .addr render_mode_pause +; .addr render_mode_rocket +; .addr render_mode_speed_test +; .addr render_mode_level_menu +; .addr render_mode_linecap_menu .include "render_mode_level_menu.asm" ; no rts / jmp @@ -23,7 +53,6 @@ render_mode_static: .include "render_mode_pause.asm" .include "render_mode_congratulations_screen.asm" .include "render_mode_rocket.asm" -.include "render_mode_scroll.asm" .include "render_mode_speed_test.asm" .include "render_mode_play_and_demo.asm" diff --git a/src/ram.asm b/src/ram.asm index f021f206..1f960636 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -30,8 +30,8 @@ lagState: .res 1 ; $0022 for lagged lines & score verticalBlankingInterval: .res 1 ; $0033 set_seed: .res 3 ; $0034 ; rng_seed, rng_seed+1, spawnCount -set_seed_input: .res 3 ; $0037 ; copied to set_seed during gameModeState_initGameState - .res 6 +.res 3 +.res 6 tetriminoX: .res 1 ; $0040 tetriminoY: .res 1 ; $0041 @@ -78,7 +78,56 @@ pztemp := mathRAM+$D byteSpriteAddr: .res 2 byteSpriteTile: .res 1 byteSpriteLen: .res 1 - .res $2A + +; (up to) 32 bytes menu scratch ram. can be reused in any other mode +; can also overlap with mathram +; this is to spread out for easier thinking + +; needs to be the same shape as lr* below +udPointer: .res $2 +udAdjust: .res $1 +udMin: .res $1 +udMax: .res $1 +; needs to be the same shape ud* above +lrPointer: .res $2 +lrAdjust: .res $1 +lrMin: .res $1 +lrMax: .res $1 + +activeItem: .res $1 +MENU_PTR_DISTANCE = lrPointer-udPointer +stringSetPtr: .res $2 +stackPtr: .res $1 + +unpackedPageType: .res $1 +unpackedPageValue: .res $1 +unpackedItemType: .res $1 +unpackedItemValue: .res $1 +digitPtr: .res $2 +originalPage: .res $1 +nybbleTemp: .res $1 +blankCounter: .res $1 +rowCounter: .res $1 + +; probably no value here +APressed: .res $1 +startPressed: .res $1 +startOrAPressed: .res $1 +BPressed: .res $1 +selectPressed: .res $1 + +actualPage: .res $1 +gameStarted: .res $1 +.res $1 + +; lr page ; mem address never changes (activePage) +; lr column ; mem address never changes (activeColumn) +; lr value ; current item is set every time anyway +; ud item ; mem address never changes (activeItem) +; ud value ; mem address never changes (expandedDigit) + + + .res $A spriteXOffset: .res 1 ; $00A0 spriteYOffset: .res 1 ; $00A1 @@ -171,8 +220,7 @@ playfield: .res $c8 ; $0400 .res $38 ; still technically part of playfield .res $100 ; $500 ; 2 player playfield - -practiseType: .res 1 ; $600 +.res 1 spawnDelay: .res 1 ; $601 dasValueDelay: .res 1 ; $602 dasValuePeriod: .res 1 ; $603 @@ -352,4 +400,17 @@ dasOnlyFlag: .res 1 qualFlag: .res 1 palFlag: .res 1 + +set_seed_input: .res 3 ; $0037 ; copied to set_seed during gameModeState_initGameState +practiseType: .res 1 ; $600 +; menu +activeMenu: .res 1 +activePage: .res 1 +activeRow: .res 1 +activeColumn: .res 1 +menuStackPtr: .res 1 +; cursorToggle: .res 1 + +.include "gamemode/gametypemenu/menuram.asm" + ; ... $7FF diff --git a/src/sprites/bytesprite.asm b/src/sprites/bytesprite.asm index c822b809..a951c276 100644 --- a/src/sprites/bytesprite.asm +++ b/src/sprites/bytesprite.asm @@ -1,19 +1,19 @@ byteSprite: -menuXTmp := tmp2 ldy #0 @loop: + ldx oamStagingLength tya asl asl asl asl adc spriteXOffset - sta menuXTmp - - ldx oamStagingLength + sta oamStaging+3,x + adc #$8 + sta oamStaging+7,x lda spriteYOffset - sta oamStaging, x - inx + sta oamStaging+0,x + sta oamStaging+4,x lda (byteSpriteAddr), y and #$F0 lsr a @@ -21,37 +21,18 @@ menuXTmp := tmp2 lsr a lsr a adc byteSpriteTile - sta oamStaging, x - inx + sta oamStaging+1,x lda #$00 - sta oamStaging, x - inx - lda menuXTmp - sta oamStaging, x - inx - - lda spriteYOffset - sta oamStaging, x - inx + sta oamStaging+2,x + sta oamStaging+6,x lda (byteSpriteAddr), y and #$F adc byteSpriteTile - sta oamStaging, x - inx - lda #$00 - sta oamStaging, x - inx - lda menuXTmp - adc #$8 - sta oamStaging, x - inx - - ; increase OAM index - lda #$08 + sta oamStaging+5, x + txa clc - adc oamStagingLength + adc #$08 sta oamStagingLength - iny cpy byteSpriteLen bne @loop diff --git a/src/sprites/loadsprite.asm b/src/sprites/loadsprite.asm index 23e0e427..978dca6e 100644 --- a/src/sprites/loadsprite.asm +++ b/src/sprites/loadsprite.asm @@ -79,6 +79,8 @@ oamContentLookup: .addr spriteReady ; $20 .addr spriteCustomLevelCursor ; $21 .addr spriteIngameHeart ; $22 + .addr spriteMenuPageSelect ; $23 +; .addr spriteMenuPageSelect2 ; $24 ; Sprites are sets of 4 bytes in the OAM format, terminated by FF. byte0=y, byte1=tile, byte2=attrs, byte3=x ; YY AA II XX sprite00LevelSelectCursor: @@ -88,6 +90,14 @@ sprite00LevelSelectCursor: sprite01GameTypeCursor: .byte $00,$27,$00,$00,$00,$27,$40,$3A .byte $FF +spriteMenuPageSelect: + .byte $00,$27,$40,$00 + .byte $00,$27,$00,$D9 + .byte $FF +; spriteMenuPageSelect2: +; .byte $00,$27,$40,$08 +; .byte $00,$27,$40,$D1 +; .byte $FF ; Used as a sort of NOOP for cursors sprite02Blank: .byte $00,$FF,$00,$00,$FF diff --git a/src/util/core.asm b/src/util/core.asm index 9204e1fd..406091a0 100644 --- a/src/util/core.asm +++ b/src/util/core.asm @@ -257,15 +257,6 @@ generateNextPseudorandomNumber: sta oneThirdPRNG rts -; canon is initializeOAM -copyOamStagingToOam: - lda #$00 - sta OAMADDR - lda #$02 - sta OAMDMA - rts - - ; reg a: value; reg x: start page; reg y: end page (inclusive) memset_page: pha diff --git a/src/util/strings.asm b/src/util/strings.asm index f5ab17ee..5148cc79 100644 --- a/src/util/strings.asm +++ b/src/util/strings.asm @@ -1,25 +1,28 @@ +stringLineCapWhen: + ldx linecapWhen + lda choiceSetLineslevel, x + jmp stringBackground +stringLineCapHow: + ldx linecapHow + lda choiceSetKs2floorinvizhalt, x stringBackground: - ldx stringIndexLookup - lda stringLookup, x tax - lda stringLookup, x - sta tmpZ + lda choiceSetTable,x + beq @ret + tay inx - ldy #0 @loop: - lda stringLookup, x + lda choiceSetTable, x sta PPUDATA inx - iny - cpy tmpZ + dey bne @loop +@ret: rts stringSprite: ldx spriteIndexInOamContentLookup - lda stringLookup, x - tax - lda stringLookup, x + lda stringTable, x sta tmpZ inx lda spriteXOffset @@ -28,9 +31,9 @@ stringSprite: stringSpriteAlignRight: ldx spriteIndexInOamContentLookup - lda stringLookup, x +stringSpriteAlignRightA: tax - lda stringLookup, x + lda stringTable, x inx sta tmpZ lda tmpZ @@ -48,7 +51,7 @@ stringSpriteLoop: sec lda spriteYOffset sta oamStaging, y - lda stringLookup, x + lda stringTable, x inx sta oamStaging+1, y lda #$00 @@ -68,100 +71,3 @@ stringSpriteLoop: lda tmpZ bne stringSpriteLoop rts - -stringLookup: - .byte stringClassic-stringLookup - .byte stringLetters-stringLookup - .byte stringSevenDigit-stringLookup - .byte stringFloat-stringLookup - .byte stringScorecap-stringLookup - .byte stringHidden-stringLookup - .byte stringNull-stringLookup ; reserved for future use - .byte stringNull-stringLookup - .byte stringOff-stringLookup ; 8 - .byte stringOn-stringLookup - .byte stringPause-stringLookup - .byte stringDebug-stringLookup - .byte stringClear-stringLookup - .byte stringConfirm-stringLookup - .byte stringV4-stringLookup - .byte stringV5-stringLookup ; F - .byte stringLevel-stringLookup - .byte stringLines-stringLookup - .byte stringKSX2-stringLookup - .byte stringFromBelow-stringLookup - .byte stringInviz-stringLookup - .byte stringHalt-stringLookup - .byte stringShown-stringLookup ;16 - .byte stringTopout-stringLookup - .byte stringCrash-stringLookup - .byte stringConfetti-stringLookup ;19 - .byte stringStrict-stringLookup - .byte stringNeon-stringLookup - .byte stringLite-stringLookup - .byte stringTeal-stringLookup - .byte stringOG-stringLookup -stringClassic: - .byte $7,'C','L','A','S','S','I','C' -stringLetters: - .byte $7,'L','E','T','T','E','R','S' -stringSevenDigit: - .byte $6,'7','D','I','G','I','T' -stringFloat: - .byte $1,'M' -stringScorecap: - .byte $6,'C','A','P','P','E','D' -stringHidden: - .byte $6,'H','I','D','D','E','N' -stringOff: - .byte $3,'O','F','F' -stringOn: - .byte $2,'O','N' -stringPause: - .byte $5,'P','A','U','S','E' -stringDebug: - .byte $5,'B','L','O','C','K' -stringClear: -.if SAVE_HIGHSCORES - .byte $6,'C','L','E','A','R','?' -.endif -stringConfirm: -.if SAVE_HIGHSCORES - .byte $6,'S','U','R','E','?','!' -.endif -stringV4: - .byte $2,'V','4' -stringV5: - .byte $2,'V','5' -stringLines: - .byte $5,'L','I','N','E','S' -stringLevel: - .byte $5,'L','E','V','E','L' -stringKSX2: - .byte $4,'K','S',$69,'2' -stringFromBelow: - .byte $5,'F','L','O','O','R' -stringInviz: - .byte $5,'I','N','V','I','Z' -stringHalt: - .byte $4,'H','A','L','T' -stringNull: - .byte $0 -stringShown: - .byte $4,'S','H','O','W' -stringTopout: - .byte $6,'T','O','P','O','U','T' -stringCrash: - .byte $5,'C','R','A','S','H' -stringConfetti: - .byte $8,'C','O','N','F','E','T','T','I' -stringStrict: - .byte $6,'S','T','R','I','C','T' -stringNeon: - .byte $4,'N','E','O','N' -stringTeal: - .byte $4,'T','E','A','L' -stringLite: - .byte $4,'L','I','T','E' -stringOG: - .byte $2,'O','G' diff --git a/tools/disasm.js b/tools/disasm.js new file mode 100644 index 00000000..de394673 --- /dev/null +++ b/tools/disasm.js @@ -0,0 +1,69 @@ +const { writeFileSync, readFileSync } = require("fs"); + +buffer = []; +segments = {}; + +const dbgfile = readFileSync("tetris.dbg").toString().split(/\n/); + +kvsplit = (line) => { + [_, section, line] = line.match(/(\S+)\s+(\S+)/); + line = line.trim().split(/,/); + result = {}; + line.forEach((kv) => (([k, v] = kv.split(/=/)), (result[k] = v))); + return result; +}; + +dbgfile + .filter((l) => l.match(/^seg.*/)) + .forEach((l) => { + kvs = kvsplit(l); + segments[eval(kvs.name)] = { + id: +kvs.id, + name: eval(kvs.name), + start: eval(kvs.start), + size: eval(kvs.size), + romOffset: eval(kvs.ooffs || "0"), + }; + }); + +const listfile = readFileSync("tetris.lst").toString().split(/\n/); +const rom = readFileSync("tetris.nes"); + +segment = segments["ZEROPAGE"]; +listfile.forEach((l, lineNo) => { + if (l.match(/.*\.bss/)) segment = segments.BSS; + if ((m = l.match(/\.segment\s+"(\w+)"/))) segment = segments[m[1]]; + + offset = parseInt(l.slice(0, 6), 16); + if (!isNaN(offset) && lineNo > 3) { + bytecode = l.slice(11, 23); + bytecode = bytecode.replace(/xx/g, " "); + slices = [ + bytecode.slice(0, 2), + bytecode.slice(3, 5), + bytecode.slice(6, 8), + ]; + for (i = 0; i < slices.length; i++) { + if (slices[i] === "rr") { + slices[i] = rom[offset + segment.romOffset + i] + .toString(16) + .padStart(2, "0") + .toUpperCase(); + } + } + address = + bytecode.trim() || l.match(/\.res/) + ? (offset + segment.start) + .toString(16) + .padStart(4, "0") + .toUpperCase() + : " "; + buffer.push( + `${address} ${slices.join(" ").padEnd(2)} ${bytecode.slice(9)} ${l.slice(23)}`.trimEnd(), + ); + } else { + buffer.push(l); + } +}); + +writeFileSync("tetris.txt", [...buffer].join("\n").trimEnd() + "\n"); From d20ff7cb3860447fef2fc2d0d2d8517c38215d20 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 24 Jan 2026 21:41:02 +0000 Subject: [PATCH 03/37] update menu --- src/gamemode/gametypemenu/.gitignore | 2 + src/gamemode/gametypemenu/menu.js | 2 +- src/gamemode/gametypemenu/menudata.asm | 843 ------------------------- src/gamemode/gametypemenu/menudata.js | 681 +++++--------------- src/gamemode/gametypemenu/menuram.asm | 8 - src/util/strings.asm | 2 +- 6 files changed, 155 insertions(+), 1383 deletions(-) create mode 100644 src/gamemode/gametypemenu/.gitignore delete mode 100644 src/gamemode/gametypemenu/menudata.asm delete mode 100644 src/gamemode/gametypemenu/menuram.asm diff --git a/src/gamemode/gametypemenu/.gitignore b/src/gamemode/gametypemenu/.gitignore new file mode 100644 index 00000000..154cd49e --- /dev/null +++ b/src/gamemode/gametypemenu/.gitignore @@ -0,0 +1,2 @@ +menudata.asm +menuram.asm diff --git a/src/gamemode/gametypemenu/menu.js b/src/gamemode/gametypemenu/menu.js index 622ce576..df352a1c 100644 --- a/src/gamemode/gametypemenu/menu.js +++ b/src/gamemode/gametypemenu/menu.js @@ -43,7 +43,7 @@ function checkStringSanity(string) { if (string.length > MAX_LENGTH_VALUE) { throw new Error(`${string} is more than MAX_LENGTH_VALUE chars`); } - if ((match = string.match(/[^- a-z0-9_?!*]/i))) { + if ((match = string.match(/[^-\/ a-z0-9_?!*]/i))) { throw new Error(`${string} has invalid char '${match[0]}'`); } } diff --git a/src/gamemode/gametypemenu/menudata.asm b/src/gamemode/gametypemenu/menudata.asm deleted file mode 100644 index d319a4e5..00000000 --- a/src/gamemode/gametypemenu/menudata.asm +++ /dev/null @@ -1,843 +0,0 @@ -; generated by menu.js -; will be overwritten unless built with -M - -STRING_PAUSE = stringPause-stringTable -STRING_BLOCK = stringBlock-stringTable -STRING_CLEAR = stringClear-stringTable -STRING_SURE = stringSure-stringTable -STRING_CONFETTI = stringConfetti-stringTable - -.enum -MAIN_MENU -SUBMENU_BOOLEANS -SUBMENU_NUMBERS -SUBMENU_DIGITS -SUBMENU_32BYTES -SUBMENU_DEBUG -SUBMENU_A -SUBMENU_TOURNAMENT -SUBMENU_DISPLAY -SUBMENU_SETTINGS -MENU_COUNT -.endenum - -.out .sprintf("%d/32 menus", MENU_COUNT) - - -.enum -CHOICESET_TETTSPSEESTAPACSETBTFLOCRUQCKTRNMARTAPCKRGARLOBDASLOWKILINVHRD -CHOICESET_OFFON -CHOICESET_ONOFF -CHOICESET_AB -CHOICESET_OFFONABSHOWTOPCRASHNEONLITETEALOGCLASSILETTER7DIGITMCAPPEDHIDDENLINESLEVELKS2FLOORINVIZHALTTETTSPSEESTAPACSETBTFLOCRUQCKTRNMARTAPCKRGARLOBDASLOWKILINVHRDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -CHOICESET_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -CHOICESET_LINESLEVEL -CHOICESET_KS2FLOORINVIZHALT -CHOICESET_CLASSILETTER7DIGITMCAPPEDHIDDEN -CHOICESET_OFFONNEONLITETEALOG -CHOICESET_OFFSHOWTOPCRASH -CHOICESET_COUNT -.endenum - -.out .sprintf("%d/32 choicesets", CHOICESET_COUNT) - - -; index activeMenu -startPageByMenu: - .byte $00 ; main menu - .byte $03 ; booleans - .byte $05 ; numbers - .byte $07 ; Digits - .byte $0A ; 32 bytes - .byte $0B ; debug - .byte $0C ; a - .byte $0D ; Tournament - .byte $0F ; Display - .byte $11 ; Settings - -pageCountByMenu: - .byte $03 ; main menu - .byte $02 ; booleans - .byte $02 ; numbers - .byte $03 ; Digits - .byte $01 ; 32 bytes - .byte $01 ; debug - .byte $01 ; a - .byte $02 ; Tournament - .byte $02 ; Display - .byte $02 ; Settings - -; index activePage -pageTypes: - .byte PAGE_DEFAULT | MODE_DEFAULT ; (new menu,*)?! - .byte PAGE_DEFAULT | MODE_DEFAULT ; kinda working - .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg - .byte PAGE_DEFAULT | MODE_DEFAULT ; boolean - .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg - .byte PAGE_DEFAULT | MODE_DEFAULT ; Numbers - .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg - .byte PAGE_DEFAULT | MODE_DEFAULT ; BCD - .byte PAGE_DEFAULT | MODE_DEFAULT ; Hex - .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg - .byte PAGE_DEFAULT | MODE_DEFAULT ; 07** - .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg - .byte PAGE_DEFAULT | MODE_DEFAULT ; aaaaaaaaaaaaaa - .byte PAGE_DEFAULT | MODE_DEFAULT ; Tournament - .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg - .byte PAGE_DEFAULT | MODE_DEFAULT ; Display - .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg - .byte PAGE_DEFAULT | MODE_DEFAULT ; Settings - .byte PAGE_DEFAULT | MODE_DEFAULT ; dbg - -itemCountByPage: - .byte $06 ; (new menu,*)?! - .byte $04 ; kinda working - .byte $05 ; dbg - .byte $04 ; boolean - .byte $05 ; dbg - .byte $07 ; Numbers - .byte $05 ; dbg - .byte $04 ; BCD - .byte $04 ; Hex - .byte $05 ; dbg - .byte $08 ; 07** - .byte $05 ; dbg - .byte $08 ; aaaaaaaaaaaaaa - .byte $08 ; Tournament - .byte $05 ; dbg - .byte $06 ; Display - .byte $05 ; dbg - .byte $06 ; Settings - .byte $05 ; dbg - -pageLabelsHi: - .byte >pageLabelsNewMenu ; (new menu,*)?! - .byte >pageLabelsKindaWorking ; kinda working - .byte >pageLabelsDbg ; dbg - .byte >pageLabelsBoolean ; boolean - .byte >pageLabelsDbg ; dbg - .byte >pageLabelsNumbers ; Numbers - .byte >pageLabelsDbg ; dbg - .byte >pageLabelsBcd ; BCD - .byte >pageLabelsHex ; Hex - .byte >pageLabelsDbg ; dbg - .byte >pageLabels07 ; 07** - .byte >pageLabelsDbg ; dbg - .byte >pageLabelsAaaaaaaaaaaaaa ; aaaaaaaaaaaaaa - .byte >pageLabelsTournament ; Tournament - .byte >pageLabelsDbg ; dbg - .byte >pageLabelsDisplay ; Display - .byte >pageLabelsDbg ; dbg - .byte >pageLabelsSettings ; Settings - .byte >pageLabelsDbg ; dbg - -pageLabelsLo: - .byte Date: Wed, 22 Apr 2026 13:38:10 -0700 Subject: [PATCH 04/37] das meter --- src/chr/game_tileset.png | Bin 5637 -> 16701 bytes src/gamemodestate/branch.asm | 1 + src/main.asm | 1 + src/modes/dasmeter.asm | 82 +++++++++++++++++++++++++++++++++++ src/palettes.asm | 2 +- src/sprites/piece.asm | 2 +- 6 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 src/modes/dasmeter.asm diff --git a/src/chr/game_tileset.png b/src/chr/game_tileset.png index fee1c5ac9e222a4fd1de20b6d296e2bc18fc4feb..83759c6b883c112f130d6187e9fff07afed44995 100644 GIT binary patch literal 16701 zcmeHPJ;-EP5qWm$qZs5f?~FTvET&4 z1`A>$hH9jlnW1QE;v$T7&Z%>6-S_&v?*6{%X_fB{eebQRQ>V_Ycl-BS_D2ujdGpm* zKJ&^nO|L$9>;9vdpW^X}>lpv}*Ps0>rrmcQz4`j?FTa27Nf;md=DoM?P16TI{p7#D z_VKVk_l>t6y**9e|9m9ar9^Ak8?)P@Pr(b^Z+X!D@qc|5D<%m%W0R}S?WP8Ev z3eUI+6K_~lZ21#85=ejtB&EM$W-$`UM=XZ)RlEA=?=)FNUdNzLm2-qC#TJEt)`Z5e zIVaXaoQt_7dZ|*1sBkIDLXd*EQe%|OxeAd#v8_(Rlm;FGg!1Sd29=#hGX<+Sr$SHOG-K{TyziMbPIsgj8?zB z5u&>hcRKmAld0g+leWP9V3~69e_&BTGpG5$C`Cj>&~zP=o=nP_ z(^fkVz+qrby1@GCYTE5~e8h5jAujK3+6!2w9Ob#n3#3&*ta%Ob|4RX_O)DK3;-v%b zP>bJm(THXO%s0e~0LO1V4+Y90Z1>(3Ag~Bn#Em<3zPNxUc;yxhaTzc6Y1j(9CNa98&;q0fvylv1UQb zb_WXWlCV+%cryVji6XDG+XAYXi?8cp*7-jusip`l&(fb!-pw^~9bF-H{tpV!NvN>p z`LEIW)2haBu5cc7>HLrJJ=Q(}JXD3Mrp=#LHI`4ZbnQL)BOKNq0p)Nm@uFQL*U?qh z8fL~>QxuYC>94d$lFw=#Hq{P}^(fYLB?*z)b-uD{fbw`jVxUENFmeEF?b5b67A?a| zR!LPMp;f9D9HOWVAe3Q!#C4ni5|I%@Thuysaz0d@y9p4k#S67ORXbo|x1lZQnnfjm z6kvJOFdf~2 zEe|k&o9EhLNB!W(gJtM$^YE zQ%{g4pu_=~30N&am8fQc>VO)AmiYod*G&Kq2VhMzRydY+^KniFAS8fp-AV#zz zDpf(=aVf|aR6%?;A&>v!xtJ|Jp#$C#Hk1mWA}*P+30`?96w-)#D=j{u12X~a0r^=r zWQ+pTBmfxqju#z>thkT9=L+MNIYGN(M{(luNJ>XE?-4KpZfWK1_2h1JTfMf8pI++a z_kR0(`-GbFnaBRo%RdJNVET4tNy?h>*X&VBgs*g-XQ%p>Gw;|rpPzcxT)#U3YI;Fo;LHDsW)ow zISZ$|1@uIYVz^LL^9$$zE9H>oq8SUvARx-7fYUa+7tK=qVahlMWygqxJJ3L>g?3_cC)OYV{59P#at@W*1j)xqMNm>Z zl`VvYG&~)d7C^=O%pcR^0368%X;Nr7+y?$jumjTR<>q?hQ*pprW!Cpl{0%dUMPiC=bCGbI026d- z?hZWG#RVHsg(SfFo{^Z>O$C(BXF(|m+E`eKERNyw?0BCK-h!fBbzDCuZS2#~=fNI($;K@gNW zPf)R?PphJUJ_l4l1ZNSb6H={HMXgeBpeiWu+<=Jhb*;Bt@A=PUot)|0-`VFo`|RW< zE70GYVl~VPf*^|6$1@1jDMT?b1)t@CSs|dR!$ZV!v3LU14|D*MWCoE43@D^NZ4;6y zL|A2jG6=K@3{i%W$i_Mcw1@Y!*Mau99t>f_BAGxGQ0IZd25mb~?*c`!ynC&3&?a8} zjBj@n$cT7fdy6H3R5pVJGhE$(JYi;wOkR4Ly#daX|>Sj~fH+X_AGM=iNu_T<^{<~1jmd_UB!baTR8xFqng>_~QK zV_?>ftRGkGnpr-jxwI-Fdw*Eb{&wMOYY|zAZ~lXG`nxLH2I{nw9KnR0Rnu~2ue7rr zdLtn5mA6xc4`XxqU|2h`zZ!C{69JIZ1ArGU8KKkDbRJ!alpQV`$Q>5f0^K z^Q*t!y3xT)f=Vw3zcJ_W%*ObxJKoaPQr>dwo$!~IKP~n`+VTM}Ns$oLf389rq7RYy z2~f3?fnaJG&M+u7#DPJRrWiB`8iVVpGCWeD64L%WT0x^KFd=OYR{~2kB0Ngrlc>dK zCHhOz#2A#1(WXqcnq&|F0wu0Ts0L-MN+&P~X+~ZFXcNOs8r2BV#|UX5AdW<8El%Yy zI1HHXWl$_+(spGUL?zIqC>A&tvfuX(jnmBE&aXT2w z#A9(Kfa<`itdEu?Zd|VgAwi@aedHT4W86+(M}T=R??>qOdpCjs zN+J<>s?j*YJ+Y^dMyxNu)Tjaz7@H^}$8cAc8{HjaVRVig&Z8r49F&gnIT*~t*f<;I z_MsB1bb3UE;sg~SXD9#<%5le042S8c3}?|fIF8T}7F$l2V;GMw$50-d>)MARK&t>z ziNyBxilD*(m8&b8+FgoJO=i+RRjLU+%y}?kybhTEAfa6ps zkw~1WQAHZpAOsh91d4?;HUs`J5*Ul<<-kBl^HZqe3?C+>3MD>Ej}U6I+*w>Up9c!e zcjvM=A3(Eltqw#Y!D-B$#u?&R1Yk2jScHgEKwumPdl87VIHFf;rD}Dokk*@Zd#5Gf zI$?+&@kI1EAnnb=()W4T1!f80Zubc~i5gSL6aE{TxIENJ01uAbN1+4jCm4siZ`3S& zL3gja8>=v0B`Vc;DFg`Gy#*bz5XX#u0iHmVO*H*%0*lemb*LR?v8%Uu2akP@rV}phy*$Utw4AhzoDq(j0ZLTV|08J zPMiV|j1F_@Fi*;63s^h>%<2)0`T4iV=JVxld=5^>WilC^gYso`9uIM&qjEU{0>_n) zagdLl{$IApg8w}xdbT);Nux*2Uq`)VEzeLv;xjspOPXd35uK$}{Rv(@iaTWNX7Z08XJ)SHb z37#cw0{x_3pbicW-nDC2S6A1GWLZ7vlVmfzJ)umplMm=vYJ5U<5M*sj6cV&0&jAct z=*1E*i-%-OdzfW+Lz4wTW_!e*9@3DLPd5rXzzoJ#hIkx4SN>gdtc0P2x*}By}OiCc%}UQ zRsW5euctqM*7+b|s5p1j3TeTZM45>)uCT~szW2G8>$z9!97ImGV>sKhUT1PA_;2AL z69O@l!6MTE!ql|zms6|%*j^c}_CIa&yfNCs&u&>pF{5fz2Zhqc3(VM&|7>T=mC2sb zvg`2;waHbXC0b{4%JI>u!Y3xRlh0T>>Vix5KUqCsooFoT7rs0z)3IPi#Lu#-+9L3$ z%;7UBqb)WC*&G@QpKAPlZ+ZrPOuzL2XUGi0koua@#g}Wv6<&!yzl|+CH*U-@-<7%3 ze!=cY3MM1Yod@swUbdYJrJf!ly;op%*DAa!+R-A>c4u6eZQI+FFq3F&&AXrj$fBT? zC0!YRX6~xK;w7!0uwrV_4?9y*Xo=B7{dc6tti7sP9^z|WYV)+h>{!;s=VK1v92fc^ zY3k9rX%>Yqh8<2~6uV!zv@w6!Hu95x9hQ~Wy0#tL_f>bgpGa{Yw0 zAG|&4j?tZJN3_VHb7J!g_wu)IynFJSdb4w9^K4U(yI=n5nQw88)wr>TNK;}>0>(41 z-$~SO507d|xLtRh@lCktfOF{&p#CdK3k^f9>|xmL9myIE0=M4jQzqZBX5_B|jCKx0+8g&;CyK%faDb}yRMn!9@|55Ru4$ZA*^#y}4!rW2syN%IEtO4|cE^Xc<9Ov_$FW*(ARzKfLByndRbvxg#Fl&+oi)`(^#$ zdTxV=;)4h)r)7kksT)%HIDhEQNY^IFQNPM0!h3h;`4qe1jY~y0w~o&}y>Hd3)1EuB zotXjln_@+mVAB+7W#!XH`!*iRUQ%)G?SqF+tmWhJS}3e}xxIdXDuBtf--9e0=$&?r ze9VO>Wj-A7qU@Gk$-wVy+4sp5%1>|duI%4Tr`Q~rVbM6#*{h-=L^`Y;KRfaKKf;@x z_s24R+LWAUo#l2u5A#(u%n5yo^G}6#E{EdJOpo4_U53|3I&bN+o;v^B#%DQe4rro} zFxa)%@%8^)lVLXoNnIA=*IGYmg!;_MM^uXK$^D>ZX zt?sYzdl5#7SoeJRmg0kHEIuVI?Q#0T%eCZyZ+`Eu@oz6HswNpmTDIp~wO5FE&9{~h zx<0q6Fg=F9>0rY|%7VtafYf diff --git a/src/gamemodestate/branch.asm b/src/gamemodestate/branch.asm index 8ae60ecd..010add6b 100644 --- a/src/gamemodestate/branch.asm +++ b/src/gamemodestate/branch.asm @@ -27,6 +27,7 @@ gameModeState_next: ; used to be updatePlayer2 rts gameModeState_vblankThenRunState2: + jsr stageDasMeterSprites lda #$02 sta gameModeState rts diff --git a/src/main.asm b/src/main.asm index 1fb4c13d..e708fc8f 100644 --- a/src/main.asm +++ b/src/main.asm @@ -91,6 +91,7 @@ mainLoop: .include "modes/crunch.asm" .include "modes/qtap.asm" .include "modes/garbage.asm" +.include "modes/dasmeter.asm" .align $100 ; these tables benefit from page alignment diff --git a/src/modes/dasmeter.asm b/src/modes/dasmeter.asm new file mode 100644 index 00000000..8c3e57ad --- /dev/null +++ b/src/modes/dasmeter.asm @@ -0,0 +1,82 @@ +stageDasMeterSprites: +@dasValue = generalCounter +@tile = generalCounter2 + lda #$CE + sta @tile + lda autorepeatX + lsr + php + sta @dasValue + cmp #5 + bcs @stageSprites + dec @tile + cmp #3 + bcs @stageSprites + dec @tile +@stageSprites: + ldx oamStagingLength + lda #0 + ldy #103 + +@loop: + lda @tile + sta oamStaging+1,x + tya + sta oamStaging+3,x + lda #35 + sta oamStaging+0,x + lda #3 + sta oamStaging+2,x + inx + inx + inx + inx + tya + clc + adc #8 + tay + dec @dasValue + stx oamStagingLength + bpl @loop + plp + bcc @ret + lda @tile + sec + sbc #16 + sta oamStaging+1,x + tya + sta oamStaging+3,x + lda #3 + sta oamStaging+2,x + lda #35 + sta oamStaging+0,x + inx + inx + inx + inx + stx oamStagingLength +@ret: + rts + +; render_mode_play_and_demo_then_dasmeter: +; lda #$23 +; sta PPUADDR +; lda #$89 +; sta PPUADDR +; ldx autorepeatX +; beq @ret +; lda dasMeterTile +; @drawDas: +; sta PPUDATA +; dex +; bne @drawDas +; ldx dasValue +; beq @ret +; lda #$FF +; @drawNonDas: +; sta PPUDATA +; dex +; bne @drawNonDas +; @ret: +; jsr render_mode_play_and_demo +; rts diff --git a/src/palettes.asm b/src/palettes.asm index 3fbb3e0f..d035811f 100644 --- a/src/palettes.asm +++ b/src/palettes.asm @@ -13,7 +13,7 @@ game_palette: .byte $0F,$16,$2A,$22 ; sprite .byte $0F,$10,$16,$2D .byte $0F,$2C,$16,$29 - .byte $0F,$3C,$00,$30 + .byte $0F,$2A,$27,$16 .byte $FF title_palette: .byte $3F,$00 diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 05e84a90..f885c64a 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -107,7 +107,7 @@ stageSpriteForCurrentPiece_actual: inc oamStagingLength dey lda #$FF - sta oamStaging,y + sta oamStaging-1,y iny iny lda #$00 From 33bbee0f8d96518fce011efa94b228a6694c4c44 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Thu, 23 Apr 2026 17:56:31 -0700 Subject: [PATCH 05/37] todo: remove meter after topout --- src/chr/game_tileset.png | Bin 16701 -> 16701 bytes src/gamemodestate/branch.asm | 1 - src/modes/dasmeter.asm | 12 +++++++----- src/util/core.asm | 8 ++++++++ 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/chr/game_tileset.png b/src/chr/game_tileset.png index 83759c6b883c112f130d6187e9fff07afed44995..3ce4b37c7c87b9837ac0b84dc9e60a88b807d0c8 100644 GIT binary patch delta 215 zcmdnn#JIPKal>`p$q7a*lke--5<_pkuV2r&8K{8?NH8%@HegYm%w-w_)v7qT8_t%W zyn&x}GQU|QR1U=Fm^|4m42jP=S`p$qfRHlM{?sCMOuwVxu=F7}PUvo}k0TxEZL538;M8WG>T~$p$Q{ zle@vR^5hNttdsf8B7tHcHpk@2W?@h^>tsQ5h?H;u@O1TaS?83{1OTb@J465g diff --git a/src/gamemodestate/branch.asm b/src/gamemodestate/branch.asm index 010add6b..8ae60ecd 100644 --- a/src/gamemodestate/branch.asm +++ b/src/gamemodestate/branch.asm @@ -27,7 +27,6 @@ gameModeState_next: ; used to be updatePlayer2 rts gameModeState_vblankThenRunState2: - jsr stageDasMeterSprites lda #$02 sta gameModeState rts diff --git a/src/modes/dasmeter.asm b/src/modes/dasmeter.asm index 8c3e57ad..b8a397be 100644 --- a/src/modes/dasmeter.asm +++ b/src/modes/dasmeter.asm @@ -1,7 +1,9 @@ stageDasMeterSprites: @dasValue = generalCounter @tile = generalCounter2 - lda #$CE +@yCoordinate = 211 +@xStart = 103 + lda #$FE sta @tile lda autorepeatX lsr @@ -16,14 +18,14 @@ stageDasMeterSprites: @stageSprites: ldx oamStagingLength lda #0 - ldy #103 + ldy #@xStart @loop: lda @tile sta oamStaging+1,x tya sta oamStaging+3,x - lda #35 + lda #@yCoordinate sta oamStaging+0,x lda #3 sta oamStaging+2,x @@ -42,13 +44,13 @@ stageDasMeterSprites: bcc @ret lda @tile sec - sbc #16 + sbc #32 sta oamStaging+1,x tya sta oamStaging+3,x lda #3 sta oamStaging+2,x - lda #35 + lda #@yCoordinate sta oamStaging+0,x inx inx diff --git a/src/util/core.asm b/src/util/core.asm index cbde7d97..ea31b9c6 100644 --- a/src/util/core.asm +++ b/src/util/core.asm @@ -57,6 +57,14 @@ random10: ; canon is waitForVerticalBlankingInterval updateAudioWaitForNmiAndResetOamStaging: + lda gameMode + cmp #4 + bne @noDasMeter + lda gameModeState + cmp #2 + bcc @noDasMeter + jsr stageDasMeterSprites +@noDasMeter: jsr updateAudio_jmp lda #$00 sta verticalBlankingInterval From 6217df11197f55c6cc1d4f9e816404e2b814639d Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 31 May 2026 16:22:58 +0000 Subject: [PATCH 06/37] formatting --- src/boot.asm | 5 ++++- src/gamemode/gametypemenu/menu.js | 1 + src/gamemode/waitscreen.asm | 2 +- src/modes/crash.asm | 4 ++-- src/util/autodetect.asm | 6 +++--- src/util/mapper.asm | 6 +++--- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/boot.asm b/src/boot.asm index 707d2ac2..935a32e6 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -31,7 +31,10 @@ sta paceModifier lda #$10 - sta dasModifier + + sta menuVarDas + lda #$06 + sta menuVarArr lda #INITIAL_LINECAP_LEVEL sta linecapLevel diff --git a/src/gamemode/gametypemenu/menu.js b/src/gamemode/gametypemenu/menu.js index df352a1c..943c2ecd 100644 --- a/src/gamemode/gametypemenu/menu.js +++ b/src/gamemode/gametypemenu/menu.js @@ -1,6 +1,7 @@ const { mainMenu, extraSpriteStrings } = require("./menudata"); const { writeFileSync } = require("fs"); + MAX_LENGTH_NAME = 14; MAX_LENGTH_VALUE = 8; DEBUG = false; diff --git a/src/gamemode/waitscreen.asm b/src/gamemode/waitscreen.asm index 5b956d64..ae95b51d 100644 --- a/src/gamemode/waitscreen.asm +++ b/src/gamemode/waitscreen.asm @@ -11,7 +11,7 @@ waitScreenLoad: .if INES_MAPPER <> 0 ; NROM (and possibly FDS in the future) won't load the 2nd bankset ; and will instead use the title/menu chrset letters. This won't be noticeable -; unless a graphic is added +; unless a graphic is added lda #CHRBankSet1 jsr changeCHRBanks .endif diff --git a/src/modes/crash.asm b/src/modes/crash.asm index 728de778..d2934400 100644 --- a/src/modes/crash.asm +++ b/src/modes/crash.asm @@ -1,8 +1,8 @@ ; Hydrant's crash theory sheet https://docs.google.com/spreadsheets/d/1zAQIo_mnkk0c9e4-hpeDvVxrl9r_HvLSx8V4h4ttmrs/edit#gid=1013692687 testCrash: - lda #$00 - sta lagState ;clearing lag state between calculations + lda #$00 + sta lagState ;clearing lag state between calculations lda #$1C ; setting all cycles which always happen. for optimizing, this can be removed if all compared numbers are reduced by $6F1C. sta cycleCount lda #$6F diff --git a/src/util/autodetect.asm b/src/util/autodetect.asm index 424c4728..e68d7fc6 100644 --- a/src/util/autodetect.asm +++ b/src/util/autodetect.asm @@ -6,15 +6,15 @@ ; Mapper detection for Holy Mapperel ; ; Copyright 2013-2017 Damian Yerrick -; +; ; This software is provided 'as-is', without any express or implied ; warranty. In no event will the authors be held liable for any damages ; arising from the use of this software. -; +; ; Permission is granted to anyone to use this software for any purpose, ; including commercial applications, and to alter it and redistribute it ; freely, subject to the following restrictions: -; +; ; 1. The origin of this software must not be misrepresented; you must not ; claim that you wrote the original software. If you use this software ; in a product, an acknowledgment in the product documentation would be diff --git a/src/util/mapper.asm b/src/util/mapper.asm index 7abd1949..db3bb141 100644 --- a/src/util/mapper.asm +++ b/src/util/mapper.asm @@ -44,12 +44,12 @@ _setMMC1Control: changeCHRBanks: ; accum should be 0 or 2 (CHRBankset0 or CHRBankset1) - sta generalCounter + sta generalCounter ; autodetect .if INES_MAPPER = 1000 - ldx mapperId - beq @cnrom + ldx mapperId + beq @cnrom changeCHRBanksMMC1 rts @cnrom: From 9cb061e7e9d9b52db1e0861b5b7ba9137157fd2a Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 31 May 2026 16:28:25 +0000 Subject: [PATCH 07/37] pace & hz --- src/gamemode/gametypemenu/menudata.js | 4 ++-- src/gamemodestate/initbackground.asm | 5 ++--- src/modes/events.asm | 6 ++---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 61f009f4..7d37db40 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -15,8 +15,8 @@ const scoringModifier = [ "scoring", ["classic", "letters", "7digit", "m", "capped", "hidden"], ]; -const paceModifier = ["TYPE_FF_OFF", "Pace", 16]; -const hzFlag = ["TYPE_BOOL", "HZ DISPLAY"]; +const paceModifier = ["TYPE_FF_OFF", "Pace", 16, "paceModifier"]; +const hzFlag = ["TYPE_BOOL", "HZ DISPLAY", "hzFlag",]; const inputDisplayFlag = ["TYPE_BOOL", "Input Display"]; const disableFlash = ["TYPE_BOOL", "Disable Flash"]; const darkMode = [ diff --git a/src/gamemodestate/initbackground.asm b/src/gamemodestate/initbackground.asm index cc9658ac..dde5ab79 100644 --- a/src/gamemodestate/initbackground.asm +++ b/src/gamemodestate/initbackground.asm @@ -179,9 +179,8 @@ statisticsNametablePatch: rts showPaceDiffText: - lda practiseType - cmp #MODE_PACE - bne @done + lda paceModifier + bmi @done jsr bulkCopyToPpu .addr paceDiffText lda #0 diff --git a/src/modes/events.asm b/src/modes/events.asm index 477578e6..c5e1f91e 100644 --- a/src/modes/events.asm +++ b/src/modes/events.asm @@ -18,8 +18,7 @@ practiseInitGameState: practisePrepareNext: lda practiseType - cmp #MODE_PACE - bne @skipPace + bmi @skipPace jmp prepareNextPace @skipPace: cmp #MODE_GARBAGE @@ -63,8 +62,7 @@ practiseGameHUD: @noInput: lda practiseType - cmp #MODE_PACE - bne @skipPace + bmi @skipPace jsr gameHUDPace @skipPace: From e50966b2a904d5eea264de1112b72e3f39474d73 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 31 May 2026 16:32:56 +0000 Subject: [PATCH 08/37] input display & dark mode & flash --- src/gamemode/gametypemenu/menudata.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 7d37db40..7ac9c330 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -17,12 +17,13 @@ const scoringModifier = [ ]; const paceModifier = ["TYPE_FF_OFF", "Pace", 16, "paceModifier"]; const hzFlag = ["TYPE_BOOL", "HZ DISPLAY", "hzFlag",]; -const inputDisplayFlag = ["TYPE_BOOL", "Input Display"]; -const disableFlash = ["TYPE_BOOL", "Disable Flash"]; +const inputDisplayFlag = ["TYPE_BOOL", "Input Display", "inputDisplayFlag",]; +const disableFlash = ["TYPE_BOOL", "Disable Flash", "disableFlashFlag"]; const darkMode = [ "TYPE_CHOICES", "dark mode", ["off", "on", "neon", "lite", "teal", "og"], + "darkModifier", ]; const paletteSelection = ["TYPE_CHOICES", "palette", ["vanilla", "pride"]]; From d86bbeae73db3fb65558b26064706628e5b4ef76 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 31 May 2026 16:57:35 +0000 Subject: [PATCH 09/37] add pride & white palettes --- src/gamemode/gametypemenu/menudata.js | 2 +- src/nmi/render_mode_play_and_demo.asm | 42 +++++++++++++++++++++++++++ src/ram.asm | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 7ac9c330..2e01e718 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -25,7 +25,7 @@ const darkMode = [ ["off", "on", "neon", "lite", "teal", "og"], "darkModifier", ]; -const paletteSelection = ["TYPE_CHOICES", "palette", ["vanilla", "pride"]]; +const paletteSelection = ["TYPE_CHOICES", "palette", ["vanilla", "pride", "white",], "paletteFlag"]; const crashModifier = [ "TYPE_CHOICES", diff --git a/src/nmi/render_mode_play_and_demo.asm b/src/nmi/render_mode_play_and_demo.asm index e2bb7670..eab6f8e5 100644 --- a/src/nmi/render_mode_play_and_demo.asm +++ b/src/nmi/render_mode_play_and_demo.asm @@ -312,6 +312,7 @@ updatePaletteForLevel: ldx #$00 @loadLevelNumber: lda levelNumber,x + php ; keep track of glitched color range @mod10: cmp #$0A bmi @copyPalettes ; bcc fixes the colour bug sec @@ -321,6 +322,23 @@ updatePaletteForLevel: @copyPalettes: and #$3F tax + plp + bmi @checkPal ; skip custom palette when in glitched colors + ldy paletteFlag + beq @checkPal + dey + beq @pride + cpx #$0A + bcs @checkPal + adc #$4B ; clc unnecessary, carry already clear + tax + jmp @renderPalettes +@pride: + cpx #$0A ; only modify 0-9 + bcs @checkPal + adc #$41 ; clc unnecessary, carry already clear + tax +@checkPal: lda palFlag beq @renderPalettes cpx #$35 ; Level 181 & 245 and'd with $3F (level 53 & 117 are properly mod10'd) @@ -375,6 +393,14 @@ colorTable0: .byte $06,$4C,$BD,$19 .byte $00,$01,$03,$05 .byte $21 ; level 181/245 pal (different from NTSC) +; pride colors + .byte $30,$30,$25,$30 + .byte $30,$30,$30,$30 + .byte $30,$30 +; all white + .byte $30,$30,$30,$30 + .byte $30,$30,$30,$30 + .byte $30,$30 colorTable1: .byte $21,$29,$24,$2A @@ -394,6 +420,14 @@ colorTable1: .byte $38,$2A,$4E,$60 .byte $00,$01,$04,$05 .byte $2b ; level 181/245 pal (same as NTSC) +; pride colors + .byte $00,$00,$11,$00 + .byte $28,$21,$27,$00 + .byte $25,$27 +; all white + .byte $30,$30,$30,$30 + .byte $30,$30,$30,$30 + .byte $30,$30 colorTable2: .byte $12,$1A,$14,$12 @@ -413,6 +447,14 @@ colorTable2: .byte $E9,$99,$99,$00 .byte $01,$02,$04,$05 .byte $25 ; level 181/245 pal (same as NTSC) +; pride colors + .byte $21,$1a,$14,$25 + .byte $14,$2b,$11,$14 + .byte $21,$15 +; all white + .byte $30,$30,$30,$30 + .byte $30,$30,$30,$30 + .byte $30,$30 incrementPieceStat: tax diff --git a/src/ram.asm b/src/ram.asm index 41597aec..3010cebf 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -402,6 +402,7 @@ linecapFlag: .res 1 dasOnlyFlag: .res 1 qualFlag: .res 1 palFlag: .res 1 +paletteFlag: .res 1 .if KEYBOARD = 1 keyboardFlag: .res 1 .endif From 5999e68ee2684bfcd96f919f4e728d4cae8f37d6 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 31 May 2026 18:34:12 +0000 Subject: [PATCH 10/37] seed works mostly --- src/gamemode/gametypemenu/menudata.js | 8 ++- src/gamemode/levelmenu.asm | 6 ++ src/gamemodestate/initbackground.asm | 4 ++ src/main.asm | 1 + src/modes/events.asm | 4 +- src/playstate/spawnnext.asm | 13 +++-- src/ram.asm | 4 ++ src/seeds.asm | 17 ++++++ src/util/modetext.asm | 82 ++++++++++++++++++++++----- 9 files changed, 114 insertions(+), 25 deletions(-) create mode 100644 src/seeds.asm diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 2e01e718..ff585f02 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -1,5 +1,5 @@ -const seedToggle = ["TYPE_BOOL", "Seed Enabled"]; -const seedInput = ["TYPE_HEX", "seed", 6]; +const seedToggle = ["TYPE_BOOL", "Seed Enabled", "seedEnabled"]; +const seedInput = ["TYPE_HEX", "seed", 6, "set_seed_input"]; const linecapWhen = ["TYPE_CHOICES", "linecap when", ["off", "lines", "level"]]; const linecapHow = [ "TYPE_CHOICES", @@ -14,6 +14,7 @@ const scoringModifier = [ "TYPE_CHOICES", "scoring", ["classic", "letters", "7digit", "m", "capped", "hidden"], + "scoringModifier", ]; const paceModifier = ["TYPE_FF_OFF", "Pace", 16, "paceModifier"]; const hzFlag = ["TYPE_BOOL", "HZ DISPLAY", "hzFlag",]; @@ -31,8 +32,9 @@ const crashModifier = [ "TYPE_CHOICES", "crash", ["off", "show", "top", "crash"], + "crashModifier", ]; -const strictCrashFlag = ["TYPE_BOOL", "strict crash"]; +const strictCrashFlag = ["TYPE_BOOL", "strict crash", "strictFlag"]; const disablePause = ["TYPE_BOOL", "disable pause"]; const goofyFlag = ["TYPE_BOOL", "goofy foot"]; const debugFlag = ["TYPE_BOOL", "block tool"]; diff --git a/src/gamemode/levelmenu.asm b/src/gamemode/levelmenu.asm index 7db0af0f..04704f77 100644 --- a/src/gamemode/levelmenu.asm +++ b/src/gamemode/levelmenu.asm @@ -24,6 +24,12 @@ gameMode_levelMenu: beq @noLinecapInfo jsr levelMenuLinecapInfo @noLinecapInfo: + jsr checkIfSeeded + ; patch if seeded + ldy #$20 + ldx #$B5 + jsr patchSeed + ; render lines when loading screen lda #RENDER_LINES sta renderFlags diff --git a/src/gamemodestate/initbackground.asm b/src/gamemodestate/initbackground.asm index dde5ab79..dd55f5ec 100644 --- a/src/gamemodestate/initbackground.asm +++ b/src/gamemodestate/initbackground.asm @@ -12,6 +12,10 @@ gameModeState_initGameBackground: jsr scoringBackground jsr debugNametableUI + ldy #$20 + ldx #$A2 + jsr patchSeed + ldy darkModifier beq @notDarkMode jsr drawDarkMode diff --git a/src/main.asm b/src/main.asm index 1fb4c13d..5cc0797d 100644 --- a/src/main.asm +++ b/src/main.asm @@ -91,6 +91,7 @@ mainLoop: .include "modes/crunch.asm" .include "modes/qtap.asm" .include "modes/garbage.asm" +.include "seeds.asm" .align $100 ; these tables benefit from page alignment diff --git a/src/modes/events.asm b/src/modes/events.asm index c5e1f91e..5aa2afad 100644 --- a/src/modes/events.asm +++ b/src/modes/events.asm @@ -17,7 +17,7 @@ practiseInitGameState: rts practisePrepareNext: - lda practiseType + lda paceModifier bmi @skipPace jmp prepareNextPace @skipPace: @@ -61,7 +61,7 @@ practiseGameHUD: jsr controllerInputDisplay @noInput: - lda practiseType + lda paceModifier bmi @skipPace jsr gameHUDPace @skipPace: diff --git a/src/playstate/spawnnext.asm b/src/playstate/spawnnext.asm index 3cd6fcc2..b706f84a 100644 --- a/src/playstate/spawnnext.asm +++ b/src/playstate/spawnnext.asm @@ -96,18 +96,19 @@ pickTetriminoPre: lda practiseType cmp #MODE_TSPINS beq pickTetriminoT - ; lda practiseType ; accumulator is still practiseType - cmp #MODE_SEED - beq pickTetriminoSeed - ; lda practiseType cmp #MODE_TAPQTY beq pickTetriminoLongbar - ; lda practiseType cmp #MODE_TAP beq pickTetriminoLongbar - ; lda practiseType cmp #MODE_PRESETS beq pickTetriminoPreset + lda seedEnabled + beq pickRandomTetrimino + lda seedEnabled + beq @pickRandomTetrimino + lda seededPieces + bne pickTetriminoSeed +@pickRandomTetrimino: jmp pickRandomTetrimino pickTetriminoT: diff --git a/src/ram.asm b/src/ram.asm index 3010cebf..9eedb816 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -403,6 +403,10 @@ dasOnlyFlag: .res 1 qualFlag: .res 1 palFlag: .res 1 paletteFlag: .res 1 +seedEnabled: .res 1 +seededPieces: .res 1 + + .if KEYBOARD = 1 keyboardFlag: .res 1 .endif diff --git a/src/seeds.asm b/src/seeds.asm new file mode 100644 index 00000000..2309be98 --- /dev/null +++ b/src/seeds.asm @@ -0,0 +1,17 @@ +checkIfSeeded: + lda #$00 + sta seededPieces + lda practiseType + cmp #MODE_TSPINS + beq @noSeed + cmp #MODE_TAPQTY + beq @noSeed + cmp #MODE_TAP + beq @noSeed + cmp #MODE_PRESETS + beq @noSeed + cmp #MODE_DROUGHT + beq @noSeed + inc seededPieces +@noSeed: + rts diff --git a/src/util/modetext.asm b/src/util/modetext.asm index bad788b6..7f03889c 100644 --- a/src/util/modetext.asm +++ b/src/util/modetext.asm @@ -1,19 +1,5 @@ displayModeText: ldx practiseType - cpx #MODE_SEED - bne @drawModeName - ; draw seed instead - lda tmp1 - sta PPUADDR - lda tmp2 - sta PPUADDR - lda set_seed_input - jsr twoDigsToPPU - lda set_seed_input+1 - jsr twoDigsToPPU - lda set_seed_input+2 - jsr twoDigsToPPU - rts @drawModeName: ; ldx practiseType @@ -42,3 +28,71 @@ displayModeText: dey bne @writeChar rts + +patchSeed: + ; skip if not seeded + lda seedEnabled + beq @ret + lda seededPieces + beq @ret + sty PPUADDR + stx PPUADDR + lda gameMode + cmp #3 + beq @setupGameTiles + +; hack + lda #$35 + sta PPUDATA + lda set_seed_input + jsr twoDigsToPPU + lda set_seed_input+1 + jsr twoDigsToPPU + lda set_seed_input+2 + jsr twoDigsToPPU + lda #$36 + jmp @nextRow + +@setupGameTiles: + lda #$3B + sta PPUDATA + lda set_seed_input + jsr twoDigsToPPU + lda set_seed_input+1 + jsr twoDigsToPPU + lda set_seed_input+2 + jsr twoDigsToPPU + lda #$3C + +@nextRow: + sta PPUDATA + sty PPUADDR + txa + clc + adc #$20 + sta PPUADDR + + ldx #$07 + lda gameMode + cmp #3 + beq @menuBoxLoop +@gameBoxLoop: + lda bottomOfBoxGame,x + sta PPUDATA + dex + bpl @gameBoxLoop + rts + + +@menuBoxLoop: + lda bottomOfBoxMenu,x + sta PPUDATA + dex + bpl @menuBoxLoop +@ret: rts + + +bottomOfBoxMenu: + .byte $3F,$3E,$3E,$3E,$3E,$3E,$3E,$3D +bottomOfBoxGame: + .byte $77,$37,$37,$37,$37,$37,$37,$76 From dbeac60db1a4b2bcee4232a8d0a5ff7b3d138971 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 31 May 2026 22:46:29 +0000 Subject: [PATCH 11/37] broken hard drop features --- src/gamemode/gametypemenu/menudata.js | 19 +++++++++---------- src/playstate/active.asm | 17 +++++++++++++---- src/ram.asm | 5 ++++- src/sprites/piece.asm | 11 +++++++---- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index ff585f02..d068bda2 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -1,4 +1,4 @@ -const seedToggle = ["TYPE_BOOL", "Seed Enabled", "seedEnabled"]; +const seedFlag = ["TYPE_BOOL", "Seed Enabled", "seedEnabled"]; const seedInput = ["TYPE_HEX", "seed", 6, "set_seed_input"]; const linecapWhen = ["TYPE_CHOICES", "linecap when", ["off", "lines", "level"]]; const linecapHow = [ @@ -45,9 +45,9 @@ const qualFlag = ["TYPE_BOOL", "qual"]; const floorModifier = ["TYPE_NUMBER", "floor", 16]; const crunchModifier = ["TYPE_NUMBER", "crunch", 16]; const invisibleFlag = ["TYPE_BOOL", "invisible"]; -const ghostPiece = ["TYPE_BOOL", "ghost"]; -const hardDrop = ["TYPE_BOOL", "hardDrop"]; -const instantClear = ["TYPE_BOOL", "no line clear"]; +const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; +const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; +const instantClear = ["TYPE_BOOL", "no entry delay", "noEntryDelayFlag"]; const scrolltris = ["TYPE_BOOL", "scrolltris"]; const horizMirror = ["TYPE_BOOL", "mirror horiz"]; @@ -105,7 +105,7 @@ const displaySubMenu = { ], }; -const settingsSubMenu = { +const moreSubMenu = { "settings[mode=default]": [ crashModifier, strictCrashFlag, @@ -120,7 +120,7 @@ const settingsSubMenu = { const tournamentSubMenu = { "tournament[mode=default]": [ - seedToggle, + seedFlag, seedInput, linecapHow, linecapWhen, @@ -133,25 +133,24 @@ const tournamentSubMenu = { const goToTournament = ["TYPE_SUBMENU", "tournament", tournamentSubMenu]; const goToMods = ["TYPE_SUBMENU", "board", modsSubMenu]; const goToCursed = ["TYPE_SUBMENU", "cursed", cursedSubmenu]; -const goToSettings = ["TYPE_SUBMENU", "settings", settingsSubMenu]; +const goToMore = ["TYPE_SUBMENU", "more", moreSubMenu]; const goToDisplay = ["TYPE_SUBMENU", "display", displaySubMenu]; const goToAnydas = ["TYPE_SUBMENU", "anydas", anydasSubMenu]; const optionsSubmenu = { "options[mode=tetris]": [ - goToTournament, goToMods, goToCursed, - goToSettings, goToDisplay, goToAnydas, + goToMore, ], }; const goToOptions = ["TYPE_SUBMENU", "options", optionsSubmenu]; const mainMenu = { - "play tetris[mode=tetris]": [goToOptions], + "play tetris[mode=tetris]": [goToOptions, goToTournament], "t-spins[mode=tspins]": [goToOptions], "setups[mode=presets]": [presetModifier, goToOptions], "b-type[mode=typeb]": [typeBModifier, goToOptions], diff --git a/src/playstate/active.asm b/src/playstate/active.asm index 2299ded3..af54269a 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -1,7 +1,6 @@ playState_playerControlsActiveTetrimino: - lda practiseType - cmp #MODE_HARDDROP - bne @notHard + lda hardDropFlag + beq @notHard jsr harddrop_tetrimino lda playState cmp #8 @@ -13,6 +12,12 @@ playState_playerControlsActiveTetrimino: jsr rotate_tetrimino jsr drop_tetrimino + lda playState + cmp #1 + beq playState_playerControlsActiveTetrimino_return + lda noEntryDelayFlag + beq playState_playerControlsActiveTetrimino_return + jmp noEntryDelay playState_playerControlsActiveTetrimino_return: rts @@ -37,10 +42,14 @@ harddrop_tetrimino: @sonic: lda #$D0 sta autorepeatY +@ret: rts @noSonic: + lda noEntryDelayFlag + beq @ret - ; hard drop +noEntryDelay: + sta vramRow lda #1 sta playState lda #0 diff --git a/src/ram.asm b/src/ram.asm index 9eedb816..0ee61be4 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -405,6 +405,9 @@ palFlag: .res 1 paletteFlag: .res 1 seedEnabled: .res 1 seededPieces: .res 1 +ghostPieceFlag: .res 1 +hardDropFlag: .res 1 +noEntryDelayFlag: .res 1 .if KEYBOARD = 1 @@ -420,7 +423,7 @@ activePage: .res 1 activeRow: .res 1 activeColumn: .res 1 menuStackPtr: .res 1 -; cursorToggle: .res 1 +; cursorToggle: .res 1 ; change this to flag if you need it later .include "gamemode/gametypemenu/menuram.asm" diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 05e84a90..1109aabb 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -2,10 +2,10 @@ stageSpriteForCurrentPiece: lda #$0 sta pieceTileModifier jsr stageSpriteForCurrentPiece_actual - - lda practiseType - cmp #MODE_HARDDROP - beq ghostPiece + lda hardDropFlag + bne ghostPiece + lda ghostPieceFlag + bne ghostPiece rts ghostPiece: @@ -26,6 +26,9 @@ ghostPiece: cmp tmp3 beq @noGhost + lda ghostPieceFlag + beq @noGhost + lda frameCounter and #1 asl From c6f182edd346af1da275d30079ee253215f91590 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 1 Jun 2026 17:08:22 +0000 Subject: [PATCH 12/37] Revert "broken hard drop features" This reverts commit dbeac60db1a4b2bcee4232a8d0a5ff7b3d138971. --- src/gamemode/gametypemenu/menudata.js | 19 ++++++++++--------- src/playstate/active.asm | 17 ++++------------- src/ram.asm | 5 +---- src/sprites/piece.asm | 11 ++++------- 4 files changed, 19 insertions(+), 33 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index d068bda2..ff585f02 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -1,4 +1,4 @@ -const seedFlag = ["TYPE_BOOL", "Seed Enabled", "seedEnabled"]; +const seedToggle = ["TYPE_BOOL", "Seed Enabled", "seedEnabled"]; const seedInput = ["TYPE_HEX", "seed", 6, "set_seed_input"]; const linecapWhen = ["TYPE_CHOICES", "linecap when", ["off", "lines", "level"]]; const linecapHow = [ @@ -45,9 +45,9 @@ const qualFlag = ["TYPE_BOOL", "qual"]; const floorModifier = ["TYPE_NUMBER", "floor", 16]; const crunchModifier = ["TYPE_NUMBER", "crunch", 16]; const invisibleFlag = ["TYPE_BOOL", "invisible"]; -const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; -const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; -const instantClear = ["TYPE_BOOL", "no entry delay", "noEntryDelayFlag"]; +const ghostPiece = ["TYPE_BOOL", "ghost"]; +const hardDrop = ["TYPE_BOOL", "hardDrop"]; +const instantClear = ["TYPE_BOOL", "no line clear"]; const scrolltris = ["TYPE_BOOL", "scrolltris"]; const horizMirror = ["TYPE_BOOL", "mirror horiz"]; @@ -105,7 +105,7 @@ const displaySubMenu = { ], }; -const moreSubMenu = { +const settingsSubMenu = { "settings[mode=default]": [ crashModifier, strictCrashFlag, @@ -120,7 +120,7 @@ const moreSubMenu = { const tournamentSubMenu = { "tournament[mode=default]": [ - seedFlag, + seedToggle, seedInput, linecapHow, linecapWhen, @@ -133,24 +133,25 @@ const tournamentSubMenu = { const goToTournament = ["TYPE_SUBMENU", "tournament", tournamentSubMenu]; const goToMods = ["TYPE_SUBMENU", "board", modsSubMenu]; const goToCursed = ["TYPE_SUBMENU", "cursed", cursedSubmenu]; -const goToMore = ["TYPE_SUBMENU", "more", moreSubMenu]; +const goToSettings = ["TYPE_SUBMENU", "settings", settingsSubMenu]; const goToDisplay = ["TYPE_SUBMENU", "display", displaySubMenu]; const goToAnydas = ["TYPE_SUBMENU", "anydas", anydasSubMenu]; const optionsSubmenu = { "options[mode=tetris]": [ + goToTournament, goToMods, goToCursed, + goToSettings, goToDisplay, goToAnydas, - goToMore, ], }; const goToOptions = ["TYPE_SUBMENU", "options", optionsSubmenu]; const mainMenu = { - "play tetris[mode=tetris]": [goToOptions, goToTournament], + "play tetris[mode=tetris]": [goToOptions], "t-spins[mode=tspins]": [goToOptions], "setups[mode=presets]": [presetModifier, goToOptions], "b-type[mode=typeb]": [typeBModifier, goToOptions], diff --git a/src/playstate/active.asm b/src/playstate/active.asm index af54269a..2299ded3 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -1,6 +1,7 @@ playState_playerControlsActiveTetrimino: - lda hardDropFlag - beq @notHard + lda practiseType + cmp #MODE_HARDDROP + bne @notHard jsr harddrop_tetrimino lda playState cmp #8 @@ -12,12 +13,6 @@ playState_playerControlsActiveTetrimino: jsr rotate_tetrimino jsr drop_tetrimino - lda playState - cmp #1 - beq playState_playerControlsActiveTetrimino_return - lda noEntryDelayFlag - beq playState_playerControlsActiveTetrimino_return - jmp noEntryDelay playState_playerControlsActiveTetrimino_return: rts @@ -42,14 +37,10 @@ harddrop_tetrimino: @sonic: lda #$D0 sta autorepeatY -@ret: rts @noSonic: - lda noEntryDelayFlag - beq @ret -noEntryDelay: - sta vramRow + ; hard drop lda #1 sta playState lda #0 diff --git a/src/ram.asm b/src/ram.asm index 0ee61be4..9eedb816 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -405,9 +405,6 @@ palFlag: .res 1 paletteFlag: .res 1 seedEnabled: .res 1 seededPieces: .res 1 -ghostPieceFlag: .res 1 -hardDropFlag: .res 1 -noEntryDelayFlag: .res 1 .if KEYBOARD = 1 @@ -423,7 +420,7 @@ activePage: .res 1 activeRow: .res 1 activeColumn: .res 1 menuStackPtr: .res 1 -; cursorToggle: .res 1 ; change this to flag if you need it later +; cursorToggle: .res 1 .include "gamemode/gametypemenu/menuram.asm" diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 1109aabb..05e84a90 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -2,10 +2,10 @@ stageSpriteForCurrentPiece: lda #$0 sta pieceTileModifier jsr stageSpriteForCurrentPiece_actual - lda hardDropFlag - bne ghostPiece - lda ghostPieceFlag - bne ghostPiece + + lda practiseType + cmp #MODE_HARDDROP + beq ghostPiece rts ghostPiece: @@ -26,9 +26,6 @@ ghostPiece: cmp tmp3 beq @noGhost - lda ghostPieceFlag - beq @noGhost - lda frameCounter and #1 asl From 236baaef9add3363424a9413ed758b28f69399f9 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 1 Jun 2026 17:12:59 +0000 Subject: [PATCH 13/37] ghost piece toggle --- src/gamemode/gametypemenu/menudata.js | 19 +++++++++---------- src/playstate/active.asm | 3 ++- src/ram.asm | 5 ++++- src/sprites/piece.asm | 11 +++++++---- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index ff585f02..d068bda2 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -1,4 +1,4 @@ -const seedToggle = ["TYPE_BOOL", "Seed Enabled", "seedEnabled"]; +const seedFlag = ["TYPE_BOOL", "Seed Enabled", "seedEnabled"]; const seedInput = ["TYPE_HEX", "seed", 6, "set_seed_input"]; const linecapWhen = ["TYPE_CHOICES", "linecap when", ["off", "lines", "level"]]; const linecapHow = [ @@ -45,9 +45,9 @@ const qualFlag = ["TYPE_BOOL", "qual"]; const floorModifier = ["TYPE_NUMBER", "floor", 16]; const crunchModifier = ["TYPE_NUMBER", "crunch", 16]; const invisibleFlag = ["TYPE_BOOL", "invisible"]; -const ghostPiece = ["TYPE_BOOL", "ghost"]; -const hardDrop = ["TYPE_BOOL", "hardDrop"]; -const instantClear = ["TYPE_BOOL", "no line clear"]; +const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; +const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; +const instantClear = ["TYPE_BOOL", "no entry delay", "noEntryDelayFlag"]; const scrolltris = ["TYPE_BOOL", "scrolltris"]; const horizMirror = ["TYPE_BOOL", "mirror horiz"]; @@ -105,7 +105,7 @@ const displaySubMenu = { ], }; -const settingsSubMenu = { +const moreSubMenu = { "settings[mode=default]": [ crashModifier, strictCrashFlag, @@ -120,7 +120,7 @@ const settingsSubMenu = { const tournamentSubMenu = { "tournament[mode=default]": [ - seedToggle, + seedFlag, seedInput, linecapHow, linecapWhen, @@ -133,25 +133,24 @@ const tournamentSubMenu = { const goToTournament = ["TYPE_SUBMENU", "tournament", tournamentSubMenu]; const goToMods = ["TYPE_SUBMENU", "board", modsSubMenu]; const goToCursed = ["TYPE_SUBMENU", "cursed", cursedSubmenu]; -const goToSettings = ["TYPE_SUBMENU", "settings", settingsSubMenu]; +const goToMore = ["TYPE_SUBMENU", "more", moreSubMenu]; const goToDisplay = ["TYPE_SUBMENU", "display", displaySubMenu]; const goToAnydas = ["TYPE_SUBMENU", "anydas", anydasSubMenu]; const optionsSubmenu = { "options[mode=tetris]": [ - goToTournament, goToMods, goToCursed, - goToSettings, goToDisplay, goToAnydas, + goToMore, ], }; const goToOptions = ["TYPE_SUBMENU", "options", optionsSubmenu]; const mainMenu = { - "play tetris[mode=tetris]": [goToOptions], + "play tetris[mode=tetris]": [goToOptions, goToTournament], "t-spins[mode=tspins]": [goToOptions], "setups[mode=presets]": [presetModifier, goToOptions], "b-type[mode=typeb]": [typeBModifier, goToOptions], diff --git a/src/playstate/active.asm b/src/playstate/active.asm index 2299ded3..db77d55d 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -40,7 +40,8 @@ harddrop_tetrimino: rts @noSonic: - ; hard drop + ; lda #$20 + sta vramRow lda #1 sta playState lda #0 diff --git a/src/ram.asm b/src/ram.asm index 9eedb816..0ee61be4 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -405,6 +405,9 @@ palFlag: .res 1 paletteFlag: .res 1 seedEnabled: .res 1 seededPieces: .res 1 +ghostPieceFlag: .res 1 +hardDropFlag: .res 1 +noEntryDelayFlag: .res 1 .if KEYBOARD = 1 @@ -420,7 +423,7 @@ activePage: .res 1 activeRow: .res 1 activeColumn: .res 1 menuStackPtr: .res 1 -; cursorToggle: .res 1 +; cursorToggle: .res 1 ; change this to flag if you need it later .include "gamemode/gametypemenu/menuram.asm" diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 05e84a90..1109aabb 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -2,10 +2,10 @@ stageSpriteForCurrentPiece: lda #$0 sta pieceTileModifier jsr stageSpriteForCurrentPiece_actual - - lda practiseType - cmp #MODE_HARDDROP - beq ghostPiece + lda hardDropFlag + bne ghostPiece + lda ghostPieceFlag + bne ghostPiece rts ghostPiece: @@ -26,6 +26,9 @@ ghostPiece: cmp tmp3 beq @noGhost + lda ghostPieceFlag + beq @noGhost + lda frameCounter and #1 asl From 7e0932446c0a6bd78312b199ed32b2b57cbb301b Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 1 Jun 2026 18:08:15 +0000 Subject: [PATCH 14/37] really broken hard drop & ghost --- src/gamemode/gametypemenu/menudata.js | 2 -- src/playstate/active.asm | 5 ++--- src/playstate/branch.asm | 8 +++++++- src/ram.asm | 1 - src/sprites/piece.asm | 14 +++++++------- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index d068bda2..ec22cb8c 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -47,7 +47,6 @@ const crunchModifier = ["TYPE_NUMBER", "crunch", 16]; const invisibleFlag = ["TYPE_BOOL", "invisible"]; const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; -const instantClear = ["TYPE_BOOL", "no entry delay", "noEntryDelayFlag"]; const scrolltris = ["TYPE_BOOL", "scrolltris"]; const horizMirror = ["TYPE_BOOL", "mirror horiz"]; @@ -81,7 +80,6 @@ const modsSubMenu = { invisibleFlag, ghostPiece, hardDrop, - instantClear, ], }; diff --git a/src/playstate/active.asm b/src/playstate/active.asm index db77d55d..0faf3189 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -1,7 +1,6 @@ playState_playerControlsActiveTetrimino: - lda practiseType - cmp #MODE_HARDDROP - bne @notHard + lda hardDropFlag + beq @notHard jsr harddrop_tetrimino lda playState cmp #8 diff --git a/src/playstate/branch.asm b/src/playstate/branch.asm index aa5b982d..2b347a02 100644 --- a/src/playstate/branch.asm +++ b/src/playstate/branch.asm @@ -12,7 +12,13 @@ branchOnPlayStatePlayer1: playState_spawnNextTetrimino, \ playState_noop, \ playState_checkStartGameOver, \ - playState_incrementPlayState + playState_incrementPlayState, \ + playState_oneFrameDelay + + +playState_oneFrameDelay: + ; do harddrop lineclear here + rts playState_unassignOrientationId: lda #$13 diff --git a/src/ram.asm b/src/ram.asm index 0ee61be4..8b0e3a3a 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -407,7 +407,6 @@ seedEnabled: .res 1 seededPieces: .res 1 ghostPieceFlag: .res 1 hardDropFlag: .res 1 -noEntryDelayFlag: .res 1 .if KEYBOARD = 1 diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 1109aabb..153daafc 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -1,14 +1,14 @@ stageSpriteForCurrentPiece: lda #$0 sta pieceTileModifier - jsr stageSpriteForCurrentPiece_actual lda hardDropFlag - bne ghostPiece - lda ghostPieceFlag - bne ghostPiece - rts + ora ghostPieceFlag + beq @actual + jsr @ghostPiece +@actual: + jmp stageSpriteForCurrentPiece_actual -ghostPiece: +@ghostPiece: lda playState cmp #3 bpl @noGhost @@ -35,7 +35,7 @@ ghostPiece: asl adc #$0D sta pieceTileModifier - jsr stageSpriteForCurrentPiece_actual + ; jsr stageSpriteForCurrentPiece_actual lda tmp3 sta tetriminoY @noGhost: From 64a7b97e6f4af8485e1d0cf54b3d7ac19c3663d4 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 1 Jun 2026 18:08:35 +0000 Subject: [PATCH 15/37] Revert "really broken hard drop & ghost" This reverts commit 7e0932446c0a6bd78312b199ed32b2b57cbb301b. --- src/gamemode/gametypemenu/menudata.js | 2 ++ src/playstate/active.asm | 5 +++-- src/playstate/branch.asm | 8 +------- src/ram.asm | 1 + src/sprites/piece.asm | 14 +++++++------- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index ec22cb8c..d068bda2 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -47,6 +47,7 @@ const crunchModifier = ["TYPE_NUMBER", "crunch", 16]; const invisibleFlag = ["TYPE_BOOL", "invisible"]; const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; +const instantClear = ["TYPE_BOOL", "no entry delay", "noEntryDelayFlag"]; const scrolltris = ["TYPE_BOOL", "scrolltris"]; const horizMirror = ["TYPE_BOOL", "mirror horiz"]; @@ -80,6 +81,7 @@ const modsSubMenu = { invisibleFlag, ghostPiece, hardDrop, + instantClear, ], }; diff --git a/src/playstate/active.asm b/src/playstate/active.asm index 0faf3189..db77d55d 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -1,6 +1,7 @@ playState_playerControlsActiveTetrimino: - lda hardDropFlag - beq @notHard + lda practiseType + cmp #MODE_HARDDROP + bne @notHard jsr harddrop_tetrimino lda playState cmp #8 diff --git a/src/playstate/branch.asm b/src/playstate/branch.asm index 2b347a02..aa5b982d 100644 --- a/src/playstate/branch.asm +++ b/src/playstate/branch.asm @@ -12,13 +12,7 @@ branchOnPlayStatePlayer1: playState_spawnNextTetrimino, \ playState_noop, \ playState_checkStartGameOver, \ - playState_incrementPlayState, \ - playState_oneFrameDelay - - -playState_oneFrameDelay: - ; do harddrop lineclear here - rts + playState_incrementPlayState playState_unassignOrientationId: lda #$13 diff --git a/src/ram.asm b/src/ram.asm index 8b0e3a3a..0ee61be4 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -407,6 +407,7 @@ seedEnabled: .res 1 seededPieces: .res 1 ghostPieceFlag: .res 1 hardDropFlag: .res 1 +noEntryDelayFlag: .res 1 .if KEYBOARD = 1 diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 153daafc..1109aabb 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -1,14 +1,14 @@ stageSpriteForCurrentPiece: lda #$0 sta pieceTileModifier + jsr stageSpriteForCurrentPiece_actual lda hardDropFlag - ora ghostPieceFlag - beq @actual - jsr @ghostPiece -@actual: - jmp stageSpriteForCurrentPiece_actual + bne ghostPiece + lda ghostPieceFlag + bne ghostPiece + rts -@ghostPiece: +ghostPiece: lda playState cmp #3 bpl @noGhost @@ -35,7 +35,7 @@ stageSpriteForCurrentPiece: asl adc #$0D sta pieceTileModifier - ; jsr stageSpriteForCurrentPiece_actual + jsr stageSpriteForCurrentPiece_actual lda tmp3 sta tetriminoY @noGhost: From 15f66d29d380ef7dab163d8ddd6b65ebbe250f64 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 1 Jun 2026 18:13:56 +0000 Subject: [PATCH 16/37] invisible --- src/gamemode/gametypemenu/menudata.js | 2 +- src/gamemodestate/initstate.asm | 5 ++--- src/ram.asm | 1 + 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index d068bda2..7e705e95 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -44,7 +44,7 @@ const qualFlag = ["TYPE_BOOL", "qual"]; const floorModifier = ["TYPE_NUMBER", "floor", 16]; const crunchModifier = ["TYPE_NUMBER", "crunch", 16]; -const invisibleFlag = ["TYPE_BOOL", "invisible"]; +const invisibleFlag = ["TYPE_BOOL", "invisible", "invisibleOptionFlag"]; const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; const instantClear = ["TYPE_BOOL", "no entry delay", "noEntryDelayFlag"]; diff --git a/src/gamemodestate/initstate.asm b/src/gamemodestate/initstate.asm index 5bda81a6..ab06dda7 100644 --- a/src/gamemodestate/initstate.asm +++ b/src/gamemodestate/initstate.asm @@ -56,9 +56,8 @@ gameModeState_initGameState: sta currentFloor @notFloor: - lda practiseType - cmp #MODE_INVISIBLE - bne @notInvisible + lda invisibleOptionFlag + beq @notInvisible sta invisibleFlag @notInvisible: diff --git a/src/ram.asm b/src/ram.asm index 0ee61be4..4ee912bf 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -408,6 +408,7 @@ seededPieces: .res 1 ghostPieceFlag: .res 1 hardDropFlag: .res 1 noEntryDelayFlag: .res 1 +invisibleOptionFlag: .res 1 .if KEYBOARD = 1 From 1da7db3d0b0f4223bbf5435d96b3f46b8bd40aee Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 1 Jun 2026 21:34:19 +0000 Subject: [PATCH 17/37] linecap mostly --- src/boot.asm | 6 +- src/constants.asm | 29 ++++-- src/gamemode/gametypemenu/menudata.js | 13 +-- src/gamemode/levelmenu.asm | 22 ++--- src/nmi/render_mode_linecap.asm | 6 +- src/playstate/updatestats.asm | 11 ++- src/util/strings.asm | 125 ++++++++++++++++++++++---- 7 files changed, 160 insertions(+), 52 deletions(-) diff --git a/src/boot.asm b/src/boot.asm index 935a32e6..66bac555 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -38,10 +38,10 @@ lda #INITIAL_LINECAP_LEVEL sta linecapLevel - lda #INITIAL_LINECAP_LINES - sta linecapLines - lda #INITIAL_LINECAP_LINES_1 + lda #INITIAL_LINECAP_LINES_LO sta linecapLines+1 + lda #INITIAL_LINECAP_LINES_HI + sta linecapLines jsr resetScores diff --git a/src/constants.asm b/src/constants.asm index f0560c57..fb9d3613 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -31,8 +31,12 @@ SWAP_DUTY_CYCLES := 0 ; counters the duty cycle swap present in some clone conso INITIAL_CUSTOM_LEVEL := 29 INITIAL_LINECAP_LEVEL := 39 -INITIAL_LINECAP_LINES := $30 ; bcd -INITIAL_LINECAP_LINES_1 := 3 ; hex (lol) + +; these bytes are currently 2 byte bcd in the menu +; they are swapped and will not work +INITIAL_LINECAP_LINES_LO := $30 ; bcd +INITIAL_LINECAP_LINES_HI := $03 ; bcd (tbd) + BTYPE_START_LINES := $25 ; bcd MENU_HIGHLIGHT_COLOR := $12 ; $12 in gym, $16 in original BLOCK_TILES := $7B @@ -121,18 +125,27 @@ SCORING_FLOAT := 3 SCORING_SCORECAP := 4 SCORING_HIDDEN := 5 -LINECAP_KILLX2 := 1 -LINECAP_FLOOR := 2 -LINECAP_INVISIBLE := 3 -LINECAP_HALT := 4 +.enum +LINECAP_INACTIVE +LINECAP_KILLX2 +LINECAP_FLOOR +LINECAP_INVISIBLE +LINECAP_HALT +.endenum + +.enum +LINECAP_OFF +LINECAP_LEVEL +LINECAP_LINES +.endenum CRASH_OFF := 0 CRASH_SHOW := 1 CRASH_TOPOUT := 2 CRASH_CRASH := 3 -LINECAP_WHEN_STRING_OFFSET := $10 -LINECAP_HOW_STRING_OFFSET := $12 +LINECAP_WHEN_STRING_OFFSET := $FF +LINECAP_HOW_STRING_OFFSET := $2 MENU_SPRITE_Y_BASE := $46 MENU_MAX_Y_SCROLL := $A0 diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 7e705e95..c2292be3 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -1,13 +1,14 @@ const seedFlag = ["TYPE_BOOL", "Seed Enabled", "seedEnabled"]; const seedInput = ["TYPE_HEX", "seed", 6, "set_seed_input"]; -const linecapWhen = ["TYPE_CHOICES", "linecap when", ["off", "lines", "level"]]; +const linecapWhen = ["TYPE_CHOICES", "linecap", ["off", "level", "lines"], "linecapWhen"]; const linecapHow = [ "TYPE_CHOICES", "linecap how", ["ks*2", "floor", "inviz", "halt"], + "linecapHow", ]; -const linecapLevel = ["TYPE_NUMBER", "linecap level", 0]; -const linecapLines = ["TYPE_HEX", "linecap lines", 4]; +const linecapLevel = ["TYPE_NUMBER", "linecap level", 0, "linecapLevel"]; +const linecapLines = ["TYPE_BCD", "linecap lines", 4, "linecapLines"]; const dasOnly = ["TYPE_BOOL", "das only"]; const scoringModifier = [ @@ -106,7 +107,7 @@ const displaySubMenu = { }; const moreSubMenu = { - "settings[mode=default]": [ + "more options[mode=default]": [ crashModifier, strictCrashFlag, disablePause, @@ -120,10 +121,10 @@ const moreSubMenu = { const tournamentSubMenu = { "tournament[mode=default]": [ - seedFlag, seedInput, - linecapHow, + seedFlag, linecapWhen, + linecapHow, linecapLevel, linecapLines, dasOnly, diff --git a/src/gamemode/levelmenu.asm b/src/gamemode/levelmenu.asm index 04704f77..a0d0c892 100644 --- a/src/gamemode/levelmenu.asm +++ b/src/gamemode/levelmenu.asm @@ -20,7 +20,7 @@ gameMode_levelMenu: sta tmp2 jsr displayModeText jsr showHighScores - lda linecapFlag + lda linecapWhen beq @noLinecapInfo jsr levelMenuLinecapInfo @noLinecapInfo: @@ -55,21 +55,21 @@ levelMenuLinecapInfo: sta PPUADDR lda #$F5 sta PPUADDR - ; clc - ; lda #LINECAP_WHEN_STRING_OFFSET - ; adc linecapWhen - jsr stringLineCapWhen + clc + lda #LINECAP_WHEN_STRING_OFFSET + adc linecapWhen + sta stringIndexLookup + jsr stringBackground lda #$21 sta PPUADDR lda #$15 sta PPUADDR - ; clc - ; lda #LINECAP_HOW_STRING_OFFSET - ; adc linecapHow - ; sta stringIndexLookup - ; jsr stringBackground - jsr stringLineCapHow + clc + lda #LINECAP_HOW_STRING_OFFSET + adc linecapHow + sta stringIndexLookup + jsr stringBackground lda #$20 sta PPUADDR diff --git a/src/nmi/render_mode_linecap.asm b/src/nmi/render_mode_linecap.asm index 8fe02656..f51c8cad 100644 --- a/src/nmi/render_mode_linecap.asm +++ b/src/nmi/render_mode_linecap.asm @@ -16,7 +16,10 @@ render_mode_linecap_menu: render_linecap_level_lines: lda linecapWhen - bne @linecapLines + cmp #LINECAP_LINES + beq @linecapLines + cmp #LINECAP_LEVEL + bne @ret lda linecapLevel jsr renderByteBCD jmp render_mode_static @@ -26,4 +29,5 @@ render_linecap_level_lines: sta PPUDATA lda linecapLines jsr twoDigsToPPU +@ret: rts diff --git a/src/playstate/updatestats.asm b/src/playstate/updatestats.asm index 83b07592..a08178f4 100644 --- a/src/playstate/updatestats.asm +++ b/src/playstate/updatestats.asm @@ -131,22 +131,21 @@ checkLevelUp: checkLinecap: ; set linecapState ; check if enabled - lda linecapFlag + ldx linecapWhen beq @linecapEnd - ; skip check if already set lda linecapState bne @linecapEnd - - lda linecapWhen + dex beq @linecapLevelCheck ;linecapLinesCheck +@linecapLines: lda lines+1 - cmp linecapLines+1 + cmp linecapLines bcc @linecapEnd lda lines - cmp linecapLines + cmp linecapLines+1 bcc @linecapEnd bcs @linecapApply diff --git a/src/util/strings.asm b/src/util/strings.asm index b538378d..6ece8b4c 100644 --- a/src/util/strings.asm +++ b/src/util/strings.asm @@ -1,28 +1,33 @@ -stringLineCapWhen: - ldx linecapWhen - lda choiceSetOfflineslevel, x - jmp stringBackground -stringLineCapHow: - ldx linecapHow - lda choiceSetKs2floorinvizhalt, x +; stringLineCapWhen: +; ldx linecapWhen +; lda choiceSetOfflineslevel, x +; jmp stringBackground +; stringLineCapHow: +; ldx linecapHow +; lda choiceSetKs2floorinvizhalt, x + stringBackground: + ldx stringIndexLookup + lda stringLookup, x tax - lda choiceSetTable,x - beq @ret - tay + lda stringLookup, x + sta tmpZ inx + ldy #0 @loop: - lda choiceSetTable, x + lda stringLookup, x sta PPUDATA inx - dey + iny + cpy tmpZ bne @loop -@ret: rts stringSprite: ldx spriteIndexInOamContentLookup - lda stringTable, x + lda stringLookup, x + tax + lda stringLookup, x sta tmpZ inx lda spriteXOffset @@ -31,9 +36,9 @@ stringSprite: stringSpriteAlignRight: ldx spriteIndexInOamContentLookup -stringSpriteAlignRightA: + lda stringLookup, x tax - lda stringTable, x + lda stringLookup, x inx sta tmpZ lda tmpZ @@ -51,7 +56,7 @@ stringSpriteLoop: sec lda spriteYOffset sta oamStaging, y - lda stringTable, x + lda stringLookup, x inx sta oamStaging+1, y lda #$00 @@ -71,3 +76,89 @@ stringSpriteLoop: lda tmpZ bne stringSpriteLoop rts + +stringLookup: + .byte stringLinesO-stringLookup + .byte stringLevelO-stringLookup + .byte stringKSX2O-stringLookup + .byte stringFromBelowO-stringLookup + .byte stringInvizO-stringLookup + .byte stringHaltO-stringLookup +stringLevelO: + .byte $5,'L','E','V','E','L' +stringLinesO: + .byte $5,'L','I','N','E','S' +stringKSX2O: + .byte $4,'K','S',$69,'2' +stringFromBelowO: + .byte $5,'F','L','O','O','R' +stringInvizO: + .byte $5,'I','N','V','I','Z' +stringHaltO: + .byte $4,'H','A','L','T' +; stringBackgroundNotGood: +; tax +; lda choiceSetTable,x +; beq @ret +; tay +; inx +; @loop: +; lda choiceSetTable, x +; sta PPUDATA +; inx +; dey +; bne @loop +; @ret: +; rts +; +; stringSpriteNotGood: +; ldx spriteIndexInOamContentLookup +; lda stringTable, x +; sta tmpZ +; inx +; lda spriteXOffset +; sta tmpX +; jmp stringSpriteLoop +; +; stringSpriteAlignRightNotGood: +; ldx spriteIndexInOamContentLookup +; stringSpriteAlignRightANotGood: +; tax +; lda stringTable, x +; inx +; sta tmpZ +; lda tmpZ +; asl +; asl +; asl +; sta tmpX +; clc +; lda spriteXOffset +; sbc tmpX +; sta tmpX +; +; stringSpriteLoopNotGood: +; ldy oamStagingLength +; sec +; lda spriteYOffset +; sta oamStaging, y +; lda stringTable, x +; inx +; sta oamStaging+1, y +; lda #$00 +; sta oamStaging+2, y +; lda tmpX +; sta oamStaging+3, y +; clc +; adc #$8 +; sta tmpX +; ; increase OAM index +; lda #$04 +; clc +; adc oamStagingLength +; sta oamStagingLength +; +; dec tmpZ +; lda tmpZ +; bne stringSpriteLoop +; rts From f4999d543db427906a11a28f21da602235e6807d Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 2 Jun 2026 17:20:16 +0000 Subject: [PATCH 18/37] practiseType populated --- src/boot.asm | 6 +- src/constants.asm | 160 +++++++++----------------- src/gamemode/gametypemenu/menu.asm | 8 +- src/gamemode/gametypemenu/menudata.js | 21 ++-- src/gamemodestate/handlegameover.asm | 5 - src/gamemodestate/initstate.asm | 5 +- src/modes/events.asm | 11 +- src/playstate/active.asm | 23 +--- src/playstate/completedrows.asm | 9 +- src/playstate/util.asm | 5 +- src/ram.asm | 1 + src/sprites/piece.asm | 6 +- src/util/modetext.asm | 2 +- 13 files changed, 97 insertions(+), 165 deletions(-) diff --git a/src/boot.asm b/src/boot.asm index 66bac555..94214e17 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -27,8 +27,9 @@ bne @loop ; default pace to A - lda #$A + lda #$FF sta paceModifier + sta floorModifier lda #$10 @@ -36,6 +37,9 @@ lda #$06 sta menuVarArr + lda #MODE_TETRIS + sta practiseType + lda #INITIAL_LINECAP_LEVEL sta linecapLevel lda #INITIAL_LINECAP_LINES_LO diff --git a/src/constants.asm b/src/constants.asm index fb9d3613..a462cac2 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -60,70 +60,67 @@ BUTTON_SELECT := $20 BUTTON_START := $10 BUTTON_DPAD := BUTTON_UP | BUTTON_DOWN | BUTTON_LEFT | BUTTON_RIGHT -RENDER_LINES = $01 -RENDER_LEVEL = $02 -RENDER_SCORE = $04 -RENDER_DEBUG = $08 -RENDER_HZ = $10 -RENDER_STATS = $40 -RENDER_HIGH_SCORE_LETTER = $80 +RENDER_LINES := $01 +RENDER_LEVEL := $02 +RENDER_SCORE := $04 +RENDER_DEBUG := $08 +RENDER_HZ := $10 +RENDER_STATS := $40 +RENDER_HIGH_SCORE_LETTER := $80 .enum +MODE_DEFAULT MODE_TETRIS MODE_TSPINS -MODE_SEED -MODE_PARITY -MODE_PACE MODE_PRESETS +MODE_STACKING MODE_TYPEB -MODE_FLOOR -MODE_CRUNCH MODE_TAP +MODE_TAPQTY MODE_TRANSITION MODE_MARATHON -MODE_TAPQTY +MODE_DROUGHT MODE_CHECKERBOARD MODE_GARBAGE -MODE_DROUGHT -MODE_DAS MODE_LOWSTACK -MODE_KILLX2 -MODE_INVISIBLE -MODE_HARDDROP MODE_SPEED_TEST -MODE_SCORE_DISPLAY -MODE_CRASH -MODE_STRICT -MODE_HZ_DISPLAY -MODE_INPUT_DISPLAY -MODE_DISABLE_FLASH -MODE_DISABLE_PAUSE -MODE_DARK -MODE_GOOFY -MODE_DEBUG -MODE_LINECAP -MODE_DASONLY -MODE_QUAL -MODE_PAL -.if KEYBOARD = 1 -MODE_KEYBOARD -.endif +MODE_GAME_QUANTITY .endenum -.if KEYBOARD = 1 -MODE_QUANTITY = MODE_KEYBOARD + 1 -.else -MODE_QUANTITY = MODE_PAL + 1 -.endif - -MODE_GAME_QUANTITY = MODE_HARDDROP + 1 +; .endum +; MODE_FLOOR +; MODE_CRUNCH +; MODE_DAS +; MODE_KILLX2 +; MODE_INVISIBLE +; MODE_HARDDROP +; MODE_SCORE_DISPLAY +; MODE_CRASH +; MODE_STRICT +; MODE_HZ_DISPLAY +; MODE_INPUT_DISPLAY +; MODE_DISABLE_FLASH +; MODE_DISABLE_PAUSE +; MODE_DARK +; MODE_GOOFY +; MODE_DEBUG +; MODE_LINECAP +; MODE_DASONLY +; MODE_QUAL +; MODE_PAL +; .if KEYBOARD = 1 +; MODE_KEYBOARD +; .endif +; .endenum -SCORING_CLASSIC := 0 ; for scoringModifier -SCORING_LETTERS := 1 -SCORING_SEVENDIGIT := 2 -SCORING_FLOAT := 3 -SCORING_SCORECAP := 4 -SCORING_HIDDEN := 5 +.enum +SCORING_CLASSIC +SCORING_LETTERS +SCORING_SEVENDIGIT +SCORING_FLOAT +SCORING_SCORECAP +SCORING_HIDDEN +.endenum .enum LINECAP_INACTIVE @@ -139,10 +136,12 @@ LINECAP_LEVEL LINECAP_LINES .endenum -CRASH_OFF := 0 -CRASH_SHOW := 1 -CRASH_TOPOUT := 2 -CRASH_CRASH := 3 +.enum +CRASH_OFF +CRASH_SHOW +CRASH_TOPOUT +CRASH_CRASH +.endenum LINECAP_WHEN_STRING_OFFSET := $FF LINECAP_HOW_STRING_OFFSET := $2 @@ -151,70 +150,19 @@ MENU_SPRITE_Y_BASE := $46 MENU_MAX_Y_SCROLL := $A0 MENU_TOP_MARGIN_SCROLL := 7 ; in blocks -; menuConfigSizeLookup -; menu ram is defined at menuRAM in ./ram.asm -.macro MENUSIZES - .byte $0 ; MODE_TETRIS - .byte $0 ; MODE_TSPINS - .byte $0 ; MODE_SEED - .byte $0 ; MODE_PARITY - .byte $F ; MODE_PACE - .byte $7 ; MODE_PRESETS - .byte $8 ; MODE_TYPEB - .byte $C ; MODE_FLOOR - .byte $F ; MODE_CRUNCH - .byte $20 ; MODE_TAP - .byte $10 ; MODE_TRANSITION - .byte $4 ; MODE_MARATHON - .byte $1F ; MODE_TAPQTY - .byte $8 ; MODE_CHECKERBOARD - .byte $4 ; MODE_GARBAGE - .byte $12 ; MODE_DROUGHT - .byte $10 ; MODE_DAS - .byte $12 ; MODE_LOWSTACK - .byte $0 ; MODE_KILLX2 - .byte $0 ; MODE_INVISIBLE - .byte $0 ; MODE_HARDDROP - .byte $0 ; MODE_SPEED_TEST - .byte $5 ; MODE_SCORE_DISPLAY - .byte $3 ; MODE_CRASH - .byte $1 ; MODE_STRICT - .byte $1 ; MODE_HZ_DISPLAY - .byte $1 ; MODE_INPUT_DISPLAY - .byte $1 ; MODE_DISABLE_FLASH - .byte $1 ; MODE_DISABLE_PAUSE - .byte $5 ; MODE_DARK - .byte $1 ; MODE_GOOFY - .byte $1 ; MODE_DEBUG - .byte $1 ; MODE_LINECAP - .byte $1 ; MODE_DASONLY - .byte $1 ; MODE_QUAL - .byte $1 ; MODE_PAL -.if KEYBOARD = 1 - .byte $1 ; MODE_KEYBOARD -.endif -.endmacro .macro MODENAMES .byte "TETRIS" .byte "TSPINS" - .byte " SEED " - .byte "STACKN" - .byte " PACE " .byte "SETUPS" + .byte "STACKN" .byte "B-TYPE" - .byte "FLOOR " - .byte "CRUNCH" .byte "QCKTAP" + .byte "TAPQTY" .byte "TRNSTN" .byte "MARTHN" - .byte "TAPQTY" + .byte "LOBARS" .byte "CKRBRD" .byte "GARBGE" - .byte "LOBARS" - .byte "DASDLY" .byte "LOWSTK" - .byte "KILLX2" - .byte "INVZBL" - .byte "HRDDRP" .endmacro diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index df781832..9a61a642 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -21,8 +21,6 @@ MENU_STRIPE_WIDTH = 20 MENU_ROWS = 9 MENU_STACK = $DF ; $01C8 - $01DF intended range -MODE_DEFAULT = 0 ; needs to be auto generated - menuDataStart: .include "menudata.asm" .out .sprintf("Menu data: %d", *-menuDataStart) @@ -115,6 +113,12 @@ gameTypeLoop: jsr stageBackgroundTiles jsr stageCurrentValues gameTypeLoopWait: + ldx activePage + lda pageTypes,x + and #$1F + beq @wait + sta practiseType +@wait: jsr updateAudioWaitForNmiAndResetOamStaging jmp gameTypeLoop diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index c2292be3..7b20c489 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -9,7 +9,7 @@ const linecapHow = [ ]; const linecapLevel = ["TYPE_NUMBER", "linecap level", 0, "linecapLevel"]; const linecapLines = ["TYPE_BCD", "linecap lines", 4, "linecapLines"]; -const dasOnly = ["TYPE_BOOL", "das only"]; +const dasOnly = ["TYPE_BOOL", "das only", "dasOnlyFlag"]; const scoringModifier = [ "TYPE_CHOICES", @@ -43,12 +43,12 @@ const palFlag = ["TYPE_BOOL", "pal mode"]; const keyboardFlag = ["TYPE_BOOL", "keyboard"]; const qualFlag = ["TYPE_BOOL", "qual"]; -const floorModifier = ["TYPE_NUMBER", "floor", 16]; -const crunchModifier = ["TYPE_NUMBER", "crunch", 16]; +const floorModifier = ["TYPE_FF_OFF", "floor", 16, "floorModifier"]; +const crunchModifier = ["TYPE_NUMBER", "crunch", 16, "crunchModifier"]; const invisibleFlag = ["TYPE_BOOL", "invisible", "invisibleOptionFlag"]; const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; -const instantClear = ["TYPE_BOOL", "no entry delay", "noEntryDelayFlag"]; +const killX2 = ["TYPE_BOOL", "killX2", "killX2Flag"]; const scrolltris = ["TYPE_BOOL", "scrolltris"]; const horizMirror = ["TYPE_BOOL", "mirror horiz"]; @@ -63,9 +63,9 @@ const transitionModifier = ["TYPE_NUMBER", "transition", 16]; const marathonModifier = ["TYPE_NUMBER", "marathon", 5]; const tapqtyModifier = ["TYPE_NUMBER", "qty height", 16]; const tapqtyLineClear = ["TYPE_BOOL", "lineclear", 16]; -const garbageModifier = ["TYPE_NUMBER", "garbage", 5]; +const garbageModifier = ["TYPE_NUMBER", "garbage", 5, "garbageModifier"]; const droughtModifier = ["TYPE_NUMBER", "drought", 20]; -const lowStackRowModifier = ["TYPE_NUMBER", "lowstack", 20]; +const lowStackRowModifier = ["TYPE_NUMBER", "lowstack", 20, "lowStackRowModifier"]; const anydasDas = ["TYPE_NUMBER", "das", 32]; const anydasArr = ["TYPE_NUMBER", "arr", 32]; @@ -82,7 +82,7 @@ const modsSubMenu = { invisibleFlag, ghostPiece, hardDrop, - instantClear, + killX2, ], }; @@ -139,7 +139,7 @@ const goToDisplay = ["TYPE_SUBMENU", "display", displaySubMenu]; const goToAnydas = ["TYPE_SUBMENU", "anydas", anydasSubMenu]; const optionsSubmenu = { - "options[mode=tetris]": [ + "options[mode=default]": [ goToMods, goToCursed, goToDisplay, @@ -154,6 +154,7 @@ const mainMenu = { "play tetris[mode=tetris]": [goToOptions, goToTournament], "t-spins[mode=tspins]": [goToOptions], "setups[mode=presets]": [presetModifier, goToOptions], + "stacking[mode=stacking]": [goToOptions], "b-type[mode=typeb]": [typeBModifier, goToOptions], "(quick)tap[mode=tap]": [ quickTapLeftModifier, @@ -166,8 +167,8 @@ const mainMenu = { "drought[mode=drought]": [droughtModifier, goToOptions], "checkerboard[mode=checkerboard]": [checkerModifier, goToOptions], "garbage[mode=garbage]": [garbageModifier, goToOptions], - "lowstack[mode=garbage]": [lowStackRowModifier, goToOptions], - "tap/roll speed[mode=speed_test]": [lowStackRowModifier, goToOptions], + "lowstack[mode=lowstack]": [lowStackRowModifier, goToOptions], + "tap/roll speed[mode=speed_test]": [goToOptions], }; const extraSpriteStrings = ["pause", "block", "clear?", "sure?!", "confetti"]; diff --git a/src/gamemodestate/handlegameover.asm b/src/gamemodestate/handlegameover.asm index 2a6a4afe..61e0df74 100644 --- a/src/gamemodestate/handlegameover.asm +++ b/src/gamemodestate/handlegameover.asm @@ -37,11 +37,6 @@ gameModeState_handleGameOver: sta playState jsr updateAudioWaitForNmiAndResetOamStaging ldx #3 ; levelMenu - lda practiseType - cmp #MODE_KILLX2 - bne @notGameTypeMenu - dex -@notGameTypeMenu: stx gameMode rts diff --git a/src/gamemodestate/initstate.asm b/src/gamemodestate/initstate.asm index ab06dda7..fd493625 100644 --- a/src/gamemodestate/initstate.asm +++ b/src/gamemodestate/initstate.asm @@ -49,9 +49,8 @@ gameModeState_initGameState: sta crashState ; initialize currentFloor if necessary - lda practiseType - cmp #MODE_FLOOR - bne @notFloor + lda floorModifier + bmi @notFloor lda floorModifier sta currentFloor @notFloor: diff --git a/src/modes/events.asm b/src/modes/events.asm index 5aa2afad..b71f4264 100644 --- a/src/modes/events.asm +++ b/src/modes/events.asm @@ -5,13 +5,12 @@ practiseInitGameState: jsr initChecker @skipChecker: jsr practiseEachPiece - cmp #MODE_FLOOR - bne @skipFloor + lda floorModifier + bmi @skipFloor jmp advanceGameFloor @skipFloor: - lda practiseType - cmp #MODE_CRUNCH - bne @skipCrunch + lda crunchModifier + beq @skipCrunch jsr advanceGameCrunch @skipCrunch: rts @@ -25,7 +24,7 @@ practisePrepareNext: bne @skipGarbo jmp prepareNextGarbage @skipGarbo: - cmp #MODE_PARITY + cmp #MODE_STACKING bne @skipParity jmp prepareNextParity @skipParity: diff --git a/src/playstate/active.asm b/src/playstate/active.asm index db77d55d..ea51485e 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -1,7 +1,6 @@ playState_playerControlsActiveTetrimino: - lda practiseType - cmp #MODE_HARDDROP - bne @notHard + lda hardDropFlag + beq @notHard jsr harddrop_tetrimino lda playState cmp #8 @@ -283,9 +282,8 @@ drop_tetrimino: lda linecapState cmp #LINECAP_KILLX2 beq @killX2 - lda practiseType - cmp #MODE_KILLX2 - bne @normal + lda killX2Flag + beq @normal @killX2: jsr lookupDropSpeed sta tmpY @@ -412,19 +410,6 @@ shift_tetrimino: rts @dasOnlyEnd: - lda practiseType - cmp #MODE_DAS - bne @normalDAS - lda dasModifier - sta dasValueDelay - lda palFlag - eor #1 - asl - adc #$8 - sta dasValuePeriod - jmp @shiftTetrimino -@normalDAS: - ; region stuff lda #$10 sta dasValueDelay diff --git a/src/playstate/completedrows.asm b/src/playstate/completedrows.asm index 53d57272..191e0d13 100644 --- a/src/playstate/completedrows.asm +++ b/src/playstate/completedrows.asm @@ -37,8 +37,8 @@ playState_checkForCompletedRows: beq @rowNotComplete ; lda practiseType ; accumulator is still practiseType - cmp #MODE_FLOOR - beq @floorCheck + lda floorModifier + bpl @floorCheck lda linecapState cmp #LINECAP_FLOOR beq @fullRowBurningCheck @@ -141,9 +141,8 @@ playState_checkForCompletedRows: @tapQtyEnd: ; update top row for crunch - lda practiseType - cmp #MODE_CRUNCH - bne @crunchEnd + lda crunchModifier + beq @crunchEnd jsr advanceSides ; clobbers generalCounter3 and generalCounter4 @crunchEnd: diff --git a/src/playstate/util.asm b/src/playstate/util.asm index 7f7a8311..35144f39 100644 --- a/src/playstate/util.asm +++ b/src/playstate/util.asm @@ -74,9 +74,8 @@ updateMusicSpeed: ldy #50 ; replaces above ; check if crunch mode - ldx practiseType - cpx #MODE_CRUNCH - bne @notCrunch + ldx crunchModifier + beq @notCrunch ; add crunch left columns to y jsr unpackCrunchModifier diff --git a/src/ram.asm b/src/ram.asm index 4ee912bf..ce90b864 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -409,6 +409,7 @@ ghostPieceFlag: .res 1 hardDropFlag: .res 1 noEntryDelayFlag: .res 1 invisibleOptionFlag: .res 1 +killX2Flag: .res 1 .if KEYBOARD = 1 diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 1109aabb..6953e3a5 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -153,9 +153,7 @@ stageSpriteForNextPiece: jmp loadSpriteIntoOamStaging @maybeDisplayNextPiece: - lda practiseType - cmp #MODE_HARDDROP - beq @displayNextPiece - lda debugFlag + lda hardDropFlag + ora debugFlag bne @displayNextPiece rts diff --git a/src/util/modetext.asm b/src/util/modetext.asm index 7f03889c..faa473e4 100644 --- a/src/util/modetext.asm +++ b/src/util/modetext.asm @@ -22,7 +22,7 @@ displayModeText: ldy #6 @writeChar: - lda modeText, x + lda modeText-6, x sta PPUDATA inx dey From a070518bdd9058d7909132aa864d05aa32fc3562 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 2 Jun 2026 17:57:18 +0000 Subject: [PATCH 19/37] setups --- src/gamemode/gametypemenu/menudata.js | 2 +- src/modes/events.asm | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 7b20c489..f99600a5 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -54,7 +54,7 @@ const scrolltris = ["TYPE_BOOL", "scrolltris"]; const horizMirror = ["TYPE_BOOL", "mirror horiz"]; const vertMirror = ["TYPE_BOOL", "mirror vert"]; -const presetModifier = ["TYPE_NUMBER", "setups", 8]; +const presetModifier = ["TYPE_NUMBER", "setups", 8, "presetModifier"]; const typeBModifier = ["TYPE_NUMBER", "type-b height", 9]; const checkerModifier = ["TYPE_NUMBER", "checker height", 9]; const quickTapLeftModifier = ["TYPE_NUMBER", "left cols", 20]; diff --git a/src/modes/events.asm b/src/modes/events.asm index b71f4264..7d5ef083 100644 --- a/src/modes/events.asm +++ b/src/modes/events.asm @@ -20,6 +20,7 @@ practisePrepareNext: bmi @skipPace jmp prepareNextPace @skipPace: + lda practiseType cmp #MODE_GARBAGE bne @skipGarbo jmp prepareNextGarbage @@ -40,6 +41,7 @@ practiseAdvanceGame: rts practiseEachPiece: ; only used in this file + lda practiseType ; not necessary, but explicit cmp #MODE_TAPQTY bne @skipTapQuantity jsr prepareNextTapQuantity From c66f9aaaed2f7240de50dfefbab9285eab72dafe Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 2 Jun 2026 22:26:45 +0000 Subject: [PATCH 20/37] most things work --- src/boot.asm | 1 - src/gamemode/gametypemenu/menu.asm | 11 +++----- src/gamemode/gametypemenu/menudata.js | 39 +++++++++++++-------------- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/boot.asm b/src/boot.asm index 94214e17..21c4a904 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -26,7 +26,6 @@ ; cpx #0 ; dex sets z flag bne @loop - ; default pace to A lda #$FF sta paceModifier sta floorModifier diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index 9a61a642..32916045 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -113,12 +113,6 @@ gameTypeLoop: jsr stageBackgroundTiles jsr stageCurrentValues gameTypeLoopWait: - ldx activePage - lda pageTypes,x - and #$1F - beq @wait - sta practiseType -@wait: jsr updateAudioWaitForNmiAndResetOamStaging jmp gameTypeLoop @@ -171,8 +165,11 @@ enterPage: lda pageTypes,x and #VALUE_MASK - sta unpackedPageValue ; always 0 for now + sta unpackedPageValue + beq @noStorePractiseType + sta practiseType +@noStorePractiseType: lda pageTypes,x and #TYPE_MASK sta unpackedPageType diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index f99600a5..94f5fd40 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -36,12 +36,12 @@ const crashModifier = [ "crashModifier", ]; const strictCrashFlag = ["TYPE_BOOL", "strict crash", "strictFlag"]; -const disablePause = ["TYPE_BOOL", "disable pause"]; -const goofyFlag = ["TYPE_BOOL", "goofy foot"]; -const debugFlag = ["TYPE_BOOL", "block tool"]; -const palFlag = ["TYPE_BOOL", "pal mode"]; +const disablePause = ["TYPE_BOOL", "disable pause", "disablePauseFlag"]; +const goofyFlag = ["TYPE_BOOL", "goofy foot", "goofyFlag"]; +const debugFlag = ["TYPE_BOOL", "block tool", "debugFlag"]; +const palFlag = ["TYPE_BOOL", "pal mode", "palFlag"]; const keyboardFlag = ["TYPE_BOOL", "keyboard"]; -const qualFlag = ["TYPE_BOOL", "qual"]; +const qualFlag = ["TYPE_BOOL", "qual", "qualFlag"]; const floorModifier = ["TYPE_FF_OFF", "floor", 16, "floorModifier"]; const crunchModifier = ["TYPE_NUMBER", "crunch", 16, "crunchModifier"]; @@ -55,16 +55,15 @@ const horizMirror = ["TYPE_BOOL", "mirror horiz"]; const vertMirror = ["TYPE_BOOL", "mirror vert"]; const presetModifier = ["TYPE_NUMBER", "setups", 8, "presetModifier"]; -const typeBModifier = ["TYPE_NUMBER", "type-b height", 9]; -const checkerModifier = ["TYPE_NUMBER", "checker height", 9]; +const typeBModifier = ["TYPE_NUMBER", "type-b height", 9, "typeBModifier"]; +const checkerModifier = ["TYPE_NUMBER", "checker height", 9, "checkerModifier"]; const quickTapLeftModifier = ["TYPE_NUMBER", "left cols", 20]; const quickTapRightModifier = ["TYPE_NUMBER", "right cols", 20]; -const transitionModifier = ["TYPE_NUMBER", "transition", 16]; -const marathonModifier = ["TYPE_NUMBER", "marathon", 5]; -const tapqtyModifier = ["TYPE_NUMBER", "qty height", 16]; -const tapqtyLineClear = ["TYPE_BOOL", "lineclear", 16]; +const transitionModifier = ["TYPE_NUMBER", "transition", 16, "transitionModifier"]; +const marathonModifier = ["TYPE_NUMBER", "marathon", 5, "marathonModifier"]; +const tapqtyModifier = ["TYPE_NUMBER", "qty height", 16, "tapqtyModifier"]; const garbageModifier = ["TYPE_NUMBER", "garbage", 5, "garbageModifier"]; -const droughtModifier = ["TYPE_NUMBER", "drought", 20]; +const droughtModifier = ["TYPE_NUMBER", "drought", 20, "droughtModifier"]; const lowStackRowModifier = ["TYPE_NUMBER", "lowstack", 20, "lowStackRowModifier"]; const anydasDas = ["TYPE_NUMBER", "das", 32]; @@ -154,20 +153,20 @@ const mainMenu = { "play tetris[mode=tetris]": [goToOptions, goToTournament], "t-spins[mode=tspins]": [goToOptions], "setups[mode=presets]": [presetModifier, goToOptions], - "stacking[mode=stacking]": [goToOptions], + "stacking[mode=stacking]": [goToOptions, goToTournament], "b-type[mode=typeb]": [typeBModifier, goToOptions], "(quick)tap[mode=tap]": [ quickTapLeftModifier, quickTapRightModifier, goToOptions, ], - "tap quantity[mode=tapqty]": [tapqtyModifier, tapqtyLineClear, goToOptions], - "transition[mode=transition]": [transitionModifier, goToOptions], - "marathon[mode=marathon]": [marathonModifier, goToOptions], - "drought[mode=drought]": [droughtModifier, goToOptions], - "checkerboard[mode=checkerboard]": [checkerModifier, goToOptions], - "garbage[mode=garbage]": [garbageModifier, goToOptions], - "lowstack[mode=lowstack]": [lowStackRowModifier, goToOptions], + "tap quantity[mode=tapqty]": [tapqtyModifier, goToOptions], + "transition[mode=transition]": [transitionModifier, goToOptions, goToTournament], + "marathon[mode=marathon]": [marathonModifier, goToOptions, goToTournament], + "drought[mode=drought]": [droughtModifier, goToOptions, goToTournament], + "checkerboard[mode=checkerboard]": [checkerModifier, goToOptions, goToTournament], + "garbage[mode=garbage]": [garbageModifier, goToOptions, goToTournament], + "lowstack[mode=lowstack]": [lowStackRowModifier, goToOptions, goToTournament], "tap/roll speed[mode=speed_test]": [goToOptions], }; From e8ed04c2c41f8fa39b3c50a2932c7042e7be04ad Mon Sep 17 00:00:00 2001 From: kirjavascript Date: Wed, 3 Jun 2026 01:39:28 +0100 Subject: [PATCH 21/37] gamemodestatefix --- src/gamemodestate/branch.asm | 5 ++++- src/gamemodestate/checkforabss.asm | 6 +++++- src/gamemodestate/handlegameover.asm | 1 - src/gamemodestate/initbackground.asm | 1 - src/gamemodestate/initstate.asm | 1 - src/gamemodestate/pause.asm | 1 - src/gamemodestate/updatecounters.asm | 2 -- src/gamemodestate/updateplayer1.asm | 1 - src/main.asm | 4 ++-- src/ram.asm | 3 ++- 10 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/gamemodestate/branch.asm b/src/gamemodestate/branch.asm index 8ae60ecd..1705ced4 100644 --- a/src/gamemodestate/branch.asm +++ b/src/gamemodestate/branch.asm @@ -10,6 +10,8 @@ ; vblankThenRunState2 gms: 2 acc eq (set to $2) branchOnGameModeState: + lda #0 + sta mainLoopWait branchTo gameModeState, \ gameModeState_initGameBackground, \ gameModeState_initGameState, \ @@ -23,12 +25,13 @@ branchOnGameModeState: gameModeState_next: ; used to be updatePlayer2 inc gameModeState - lda #$1 ; acc should not be equal rts gameModeState_vblankThenRunState2: lda #$02 sta gameModeState + lda #$1 + sta mainLoopWait rts .include "initbackground.asm" diff --git a/src/gamemodestate/checkforabss.asm b/src/gamemodestate/checkforabss.asm index 432a4679..b7129d99 100644 --- a/src/gamemodestate/checkforabss.asm +++ b/src/gamemodestate/checkforabss.asm @@ -4,7 +4,11 @@ gameModeState_checkForResetKeyCombo: cmp #BUTTON_A+BUTTON_B+BUTTON_START+BUTTON_SELECT beq @reset inc gameModeState - ; acc has to be heldButtons_player1 here + cmp #BUTTON_LEFT+BUTTON_DOWN+BUTTON_RIGHT + bne @continue + lda #1 + sta mainLoopWait +@continue: rts @reset: jsr updateAudio2 diff --git a/src/gamemodestate/handlegameover.asm b/src/gamemodestate/handlegameover.asm index 2a6a4afe..cfec037c 100644 --- a/src/gamemodestate/handlegameover.asm +++ b/src/gamemodestate/handlegameover.asm @@ -46,5 +46,4 @@ gameModeState_handleGameOver: rts @ret: inc gameModeState ; 4 - lda #$1 ; acc should not be equal (always $1 in original game) rts diff --git a/src/gamemodestate/initbackground.asm b/src/gamemodestate/initbackground.asm index cc9658ac..99c9a839 100644 --- a/src/gamemodestate/initbackground.asm +++ b/src/gamemodestate/initbackground.asm @@ -56,7 +56,6 @@ gameModeState_initGameBackground: lda #$01 sta playState inc gameModeState ; 1 - lda #0 ; acc should not be equal rts scoringBackground: diff --git a/src/gamemodestate/initstate.asm b/src/gamemodestate/initstate.asm index 5bda81a6..23ca3bfd 100644 --- a/src/gamemodestate/initstate.asm +++ b/src/gamemodestate/initstate.asm @@ -153,7 +153,6 @@ gameModeState_initGameState: lda musicSelectionTable,x jsr setMusicTrack inc gameModeState ; 2 - lda #4 ; acc should not be equal initGameState_return: rts diff --git a/src/gamemodestate/pause.asm b/src/gamemodestate/pause.asm index a3b5c70f..34fcb550 100644 --- a/src/gamemodestate/pause.asm +++ b/src/gamemodestate/pause.asm @@ -17,7 +17,6 @@ gameModeState_handlePause: jsr pause @ret: inc gameModeState ; 8 - lda #$0 ; acc must not be equal rts pause: diff --git a/src/gamemodestate/updatecounters.asm b/src/gamemodestate/updatecounters.asm index b35e93c5..d3b8f65f 100644 --- a/src/gamemodestate/updatecounters.asm +++ b/src/gamemodestate/updatecounters.asm @@ -3,8 +3,6 @@ gameModeState_updateCountersAndNonPlayerState: lda #$00 sta oamStagingLength inc fallTimer - ; next code makes acc behave as normal - ; (dont edit unless you know what you're doing) lda newlyPressedButtons_player1 and #BUTTON_SELECT beq @ret diff --git a/src/gamemodestate/updateplayer1.asm b/src/gamemodestate/updateplayer1.asm index edf9da24..a00be232 100644 --- a/src/gamemodestate/updateplayer1.asm +++ b/src/gamemodestate/updateplayer1.asm @@ -15,5 +15,4 @@ gameModeState_updatePlayer1: jsr stageSpriteForNextPiece inc gameModeState ; 5 - lda #$FF ; acc from stateSpriteForNextPiece rts diff --git a/src/main.asm b/src/main.asm index 1fb4c13d..6445d86f 100644 --- a/src/main.asm +++ b/src/main.asm @@ -27,8 +27,8 @@ initRam: mainLoop: jsr branchOnGameMode - cmp gameModeState - bne @continue + lda mainLoopWait + beq @continue jsr updateAudioWaitForNmiAndResetOamStaging @continue: jmp mainLoop diff --git a/src/ram.asm b/src/ram.asm index 4015c984..a7e36c09 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -24,8 +24,9 @@ allegroIndex: .res 1 ; $001F for crash wasAllegro: .res 1 ; $0020 for crash startParity: .res 1 ; $0021 for crash lagState: .res 1 ; $0022 for lagged lines & score - .res $10 + .res $F +mainLoopWait: .res 1 ; $0032 verticalBlankingInterval: .res 1 ; $0033 set_seed: .res 3 ; $0034 ; rng_seed, rng_seed+1, spawnCount set_seed_input: .res 3 ; $0037 ; copied to set_seed during gameModeState_initGameState From 7c6f5bf95a1e818714f1149837f3e4d0ef38ef04 Mon Sep 17 00:00:00 2001 From: kirjavascript Date: Wed, 3 Jun 2026 01:47:30 +0100 Subject: [PATCH 22/37] gamemodestatefix --- src/gamemodestate/branch.asm | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/gamemodestate/branch.asm b/src/gamemodestate/branch.asm index 1705ced4..7af38053 100644 --- a/src/gamemodestate/branch.asm +++ b/src/gamemodestate/branch.asm @@ -1,14 +1,3 @@ -; the return value of this routine dictates if we should wait for nmi or not right after -; initGameBackground gms: 1 acc: 0 - ne -; initGameState gms: 2 acc: 4/0 - ne -; updateCountersAndNonPlayerState gms: 3 acc: 0/1 - ne -; handleGameOver gms: 4 acc: eq (set to $9) if gameOver, $1 otherwise (ne) -; updatePlayer1 gms: 5 acc: $FF - ne -; next gms: 6 acc: $1 ne -; checkForResetKeyCombo gms: 7 acc: 0 or heldButtons - eq if holding down, left and right -; handlePause gms: 8 acc: 0/3 - ne -; vblankThenRunState2 gms: 2 acc eq (set to $2) - branchOnGameModeState: lda #0 sta mainLoopWait From af89a93803a036dae3312be989203254fdc5d0bd Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 3 Jun 2026 00:57:02 +0000 Subject: [PATCH 23/37] another mode --- src/gamemode/gametypemenu/menudata.js | 4 ++-- src/modes/events.asm | 8 ++++---- src/modes/qtap.asm | 29 ++++++++++++++++----------- src/ram.asm | 2 ++ 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 94f5fd40..e0251d96 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -57,8 +57,8 @@ const vertMirror = ["TYPE_BOOL", "mirror vert"]; const presetModifier = ["TYPE_NUMBER", "setups", 8, "presetModifier"]; const typeBModifier = ["TYPE_NUMBER", "type-b height", 9, "typeBModifier"]; const checkerModifier = ["TYPE_NUMBER", "checker height", 9, "checkerModifier"]; -const quickTapLeftModifier = ["TYPE_NUMBER", "left cols", 20]; -const quickTapRightModifier = ["TYPE_NUMBER", "right cols", 20]; +const quickTapLeftModifier = ["TYPE_NUMBER", "left cols", 20, "tapLeftModifier"]; +const quickTapRightModifier = ["TYPE_NUMBER", "right cols", 20, "tapRightModifier"]; const transitionModifier = ["TYPE_NUMBER", "transition", 16, "transitionModifier"]; const marathonModifier = ["TYPE_NUMBER", "marathon", 5, "marathonModifier"]; const tapqtyModifier = ["TYPE_NUMBER", "qty height", 16, "tapqtyModifier"]; diff --git a/src/modes/events.asm b/src/modes/events.asm index 7d5ef083..8002ad4d 100644 --- a/src/modes/events.asm +++ b/src/modes/events.asm @@ -7,7 +7,7 @@ practiseInitGameState: jsr practiseEachPiece lda floorModifier bmi @skipFloor - jmp advanceGameFloor + jsr advanceGameFloor @skipFloor: lda crunchModifier beq @skipCrunch @@ -18,16 +18,16 @@ practiseInitGameState: practisePrepareNext: lda paceModifier bmi @skipPace - jmp prepareNextPace + jsr prepareNextPace @skipPace: lda practiseType cmp #MODE_GARBAGE bne @skipGarbo - jmp prepareNextGarbage + jsr prepareNextGarbage @skipGarbo: cmp #MODE_STACKING bne @skipParity - jmp prepareNextParity + jsr prepareNextParity @skipParity: jsr practiseEachPiece rts diff --git a/src/modes/qtap.asm b/src/modes/qtap.asm index 45d8dca9..312a2971 100644 --- a/src/modes/qtap.asm +++ b/src/modes/qtap.asm @@ -1,16 +1,13 @@ advanceGameTap: + @leftSide = $BF + @rightSide = $C6 + @secondLoop = generalCounter jsr clearPlayfield - ldx tapModifier - ; cpx #0 ; ldx sets z flag - beq @skip ; skip if zero - ldy #$BF ; left side - cpx #$11 - bmi @loop - ldy #$C6 ; right side - txa - sbc #$10 - tax - + lda #$00 + sta @secondLoop + ldx tapLeftModifier + beq @checkRight + ldy #@leftSide @loop: lda #$7B sta $400, y @@ -21,5 +18,13 @@ advanceGameTap: tay dex bne @loop -@skip: + lda @secondLoop + bne @ret +@checkRight: + inc @secondLoop + ldx tapRightModifier + beq @ret + ldy #@rightSide + bne @loop +@ret: rts diff --git a/src/ram.asm b/src/ram.asm index ce90b864..579cd9f0 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -410,6 +410,8 @@ hardDropFlag: .res 1 noEntryDelayFlag: .res 1 invisibleOptionFlag: .res 1 killX2Flag: .res 1 +tapLeftModifier: .res 1 +tapRightModifier: .res 1 .if KEYBOARD = 1 From 6c5bd34fc42b16c61f3983d5ab79eb36f889b36c Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 3 Jun 2026 20:23:47 +0000 Subject: [PATCH 24/37] mirror vert & horiz --- src/gamemode/gametypemenu/menudata.js | 4 ++-- src/nmi/render_util.asm | 25 +++++++++++++++++++++++-- src/ram.asm | 2 ++ src/sprites/piece.asm | 19 +++++++++++++++++-- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index e0251d96..a7fafbd2 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -51,8 +51,8 @@ const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; const killX2 = ["TYPE_BOOL", "killX2", "killX2Flag"]; const scrolltris = ["TYPE_BOOL", "scrolltris"]; -const horizMirror = ["TYPE_BOOL", "mirror horiz"]; -const vertMirror = ["TYPE_BOOL", "mirror vert"]; +const horizMirror = ["TYPE_BOOL", "mirror horiz", "mirrorHorizFlag"]; +const vertMirror = ["TYPE_BOOL", "mirror vert", "mirrorVertFlag"]; const presetModifier = ["TYPE_NUMBER", "setups", 8, "presetModifier"]; const typeBModifier = ["TYPE_NUMBER", "type-b height", 9, "typeBModifier"]; diff --git a/src/nmi/render_util.asm b/src/nmi/render_util.asm index 8467ae85..5c45e181 100644 --- a/src/nmi/render_util.asm +++ b/src/nmi/render_util.asm @@ -88,7 +88,19 @@ copyPlayfieldRowToVRAM: cpx #$15 bpl @ret lda multBy10Table,x + ldy mirrorHorizFlag + beq @notHorizMirror + clc + adc #$9 +@notHorizMirror: tay + lda mirrorVertFlag + beq @notVertMirror + lda #$13 + sec + sbc vramRow + tax +@notVertMirror: txa asl a tax @@ -96,15 +108,16 @@ copyPlayfieldRowToVRAM: lda vramPlayfieldRows,x sta PPUADDR dex - lda vramPlayfieldRows,x sta PPUADDR @copyRow: ldx #$0A lda invisibleFlag bne @copyRowInvisible + lda mirrorHorizFlag + bne @copyRowMirrorHoriz @copyByte: - lda (playfieldAddr),y + lda playfield,y sta PPUDATA iny dex @@ -125,3 +138,11 @@ copyPlayfieldRowToVRAM: dex bne @copyByteInvisible jmp @rowCopied + +@copyRowMirrorHoriz: + lda playfield,y + sta PPUDATA + dey + dex + bne @copyRowMirrorHoriz + jmp @rowCopied diff --git a/src/ram.asm b/src/ram.asm index d8abc20c..76e6b878 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -413,6 +413,8 @@ invisibleOptionFlag: .res 1 killX2Flag: .res 1 tapLeftModifier: .res 1 tapRightModifier: .res 1 +mirrorHorizFlag: .res 1 +mirrorVertFlag: .res 1 .if KEYBOARD = 1 diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 6953e3a5..d16a4cd7 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -63,7 +63,9 @@ stageSpriteForCurrentPiece_actual: @currentTile = generalCounter5 lda tetriminoX cmp #TETRIMINO_X_HIDE - beq stageSpriteForCurrentPiece_return + bne @notHidden + rts +@notHidden: asl a asl a asl a @@ -93,8 +95,15 @@ stageSpriteForCurrentPiece_actual: asl a clc adc generalCounter4 - sta oamStaging,y sta originalY + sta oamStaging,y + lda mirrorVertFlag + beq @notMirrorVert + lda #$F6 + sec + sbc originalY + sta oamStaging,y +@notMirrorVert: inc oamStagingLength iny jsr tileModifierForCurrentPiece ; used to just load from orientationTable @@ -127,6 +136,12 @@ stageSpriteForCurrentPiece_actual: clc adc generalCounter3 sta oamStaging,y + lda mirrorHorizFlag + beq @finishLoop + lda #$08 + sec + sbc oamStaging,y + sta oamStaging,y @finishLoop: inc oamStagingLength iny From b03a92d39d5e238fd6f3074c38fe73e96381fed2 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 3 Jun 2026 20:31:32 +0000 Subject: [PATCH 25/37] no scrolltris --- src/gamemode/gametypemenu/menudata.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index a7fafbd2..935c652d 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -50,7 +50,6 @@ const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; const killX2 = ["TYPE_BOOL", "killX2", "killX2Flag"]; -const scrolltris = ["TYPE_BOOL", "scrolltris"]; const horizMirror = ["TYPE_BOOL", "mirror horiz", "mirrorHorizFlag"]; const vertMirror = ["TYPE_BOOL", "mirror vert", "mirrorVertFlag"]; @@ -82,12 +81,11 @@ const modsSubMenu = { ghostPiece, hardDrop, killX2, + horizMirror, + vertMirror, ], }; -const cursedSubmenu = { - "modifiers[mode=default]": [scrolltris, horizMirror, vertMirror], -}; const anydasSubMenu = { "anydas[mode=default]": [anydasDas, anydasArr, anydasEntryDelay], @@ -132,7 +130,6 @@ const tournamentSubMenu = { const goToTournament = ["TYPE_SUBMENU", "tournament", tournamentSubMenu]; const goToMods = ["TYPE_SUBMENU", "board", modsSubMenu]; -const goToCursed = ["TYPE_SUBMENU", "cursed", cursedSubmenu]; const goToMore = ["TYPE_SUBMENU", "more", moreSubMenu]; const goToDisplay = ["TYPE_SUBMENU", "display", displaySubMenu]; const goToAnydas = ["TYPE_SUBMENU", "anydas", anydasSubMenu]; @@ -140,7 +137,6 @@ const goToAnydas = ["TYPE_SUBMENU", "anydas", anydasSubMenu]; const optionsSubmenu = { "options[mode=default]": [ goToMods, - goToCursed, goToDisplay, goToAnydas, goToMore, From 5636edfa27c649815faaa1b6be4f7a45be83a52b Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 3 Jun 2026 22:04:17 +0000 Subject: [PATCH 26/37] tmp fix for strings --- src/gamemode/levelmenu.asm | 4 ++-- src/gamemodestate/pause.asm | 4 ++-- src/util/strings.asm | 40 +++++++++++++++++++++++++++++++------ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/gamemode/levelmenu.asm b/src/gamemode/levelmenu.asm index a0d0c892..2eec95c0 100644 --- a/src/gamemode/levelmenu.asm +++ b/src/gamemode/levelmenu.asm @@ -207,7 +207,7 @@ levelControlClearHighScores: sta spriteXOffset lda #$C8 sta spriteYOffset - lda #STRING_CLEAR + lda #STRING_CLEAR_O sta spriteIndexInOamContentLookup jsr stringSprite @@ -228,7 +228,7 @@ levelControlClearHighScoresConfirm: sta spriteXOffset lda #$C8 sta spriteYOffset - lda #STRING_SURE + lda #STRING_SURE_O sta spriteIndexInOamContentLookup jsr stringSprite diff --git a/src/gamemodestate/pause.asm b/src/gamemodestate/pause.asm index dc1b82ea..332eff87 100644 --- a/src/gamemodestate/pause.asm +++ b/src/gamemodestate/pause.asm @@ -55,10 +55,10 @@ pause: @pauseLoopCommon: clc - lda #STRING_PAUSE + lda #STRING_PAUSE_O ldx debugFlag beq @notDebug - lda #STRING_BLOCK + lda #STRING_BLOCK_O @notDebug: sta spriteIndexInOamContentLookup jsr stringSprite diff --git a/src/util/strings.asm b/src/util/strings.asm index 6ece8b4c..caea0091 100644 --- a/src/util/strings.asm +++ b/src/util/strings.asm @@ -84,18 +84,46 @@ stringLookup: .byte stringFromBelowO-stringLookup .byte stringInvizO-stringLookup .byte stringHaltO-stringLookup + .byte stringPauseO-stringLookup + .byte stringBlockO-stringLookup + .byte stringClearO-stringLookup + .byte stringSureO-stringLookup + .byte stringConfettiO-stringLookup stringLevelO: - .byte $5,'L','E','V','E','L' + .byte $5,"LEVEL" stringLinesO: - .byte $5,'L','I','N','E','S' + .byte $5,"LINES" stringKSX2O: - .byte $4,'K','S',$69,'2' + .byte $4,"KS",$69,"2" stringFromBelowO: - .byte $5,'F','L','O','O','R' + .byte $5,"FLOOR" stringInvizO: - .byte $5,'I','N','V','I','Z' + .byte $5,"INVIZ" stringHaltO: - .byte $4,'H','A','L','T' + .byte $4,"HALT" +stringPauseO: + .byte $5, "PAUSE" +stringBlockO: + .byte $5, "BLOCK" +stringClearO: + .byte $06,"CLEAR?" +stringSureO: + .byte $06,"SURE?!" +stringConfettiO: + .byte $08,"CONFETTI" +.enum +STRING_LEVEL_O +STRING_LINES_O +STRING_KSX2_O +STRING_FLOOR_O +STRING_INVIZ_O +STRING_HALT_O +STRING_PAUSE_O +STRING_BLOCK_O +STRING_CLEAR_O +STRING_SURE_O +STRING_CONFETTI_O +.endenum ; stringBackgroundNotGood: ; tax ; lda choiceSetTable,x From 645cc25d8c4a612df2a8b983937a10ee5b812277 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 10 Jun 2026 19:11:58 +0000 Subject: [PATCH 27/37] ghost & harddrop flags work --- src/playstate/active.asm | 4 ++-- src/sprites/piece.asm | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/playstate/active.asm b/src/playstate/active.asm index ea51485e..ba3d1ccf 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -18,7 +18,7 @@ playState_playerControlsActiveTetrimino_return: harddrop_tetrimino: lda newlyPressedButtons - and #BUTTON_UP+BUTTON_SELECT + and #BUTTON_DOWN+BUTTON_SELECT beq playState_playerControlsActiveTetrimino_return lda tetriminoY sta tmpY @@ -39,7 +39,7 @@ harddrop_tetrimino: rts @noSonic: - ; lda #$20 + lda #$20 sta vramRow lda #1 sta playState diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index d16a4cd7..5bd6cdc8 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -36,9 +36,9 @@ ghostPiece: adc #$0D sta pieceTileModifier jsr stageSpriteForCurrentPiece_actual +@noGhost: lda tmp3 sta tetriminoY -@noGhost: rts tileModifierForCurrentPiece: From 66e44d78167c379f97ccaa88a0293813fdf4ea3e Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 10 Jun 2026 19:19:05 +0000 Subject: [PATCH 28/37] restore correct harddrop button --- src/playstate/active.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/playstate/active.asm b/src/playstate/active.asm index ba3d1ccf..270c0735 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -18,7 +18,7 @@ playState_playerControlsActiveTetrimino_return: harddrop_tetrimino: lda newlyPressedButtons - and #BUTTON_DOWN+BUTTON_SELECT + and #BUTTON_UP+BUTTON_SELECT beq playState_playerControlsActiveTetrimino_return lda tetriminoY sta tmpY From d6a70817504760994c8f72bab885106f8a859830 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 10 Jun 2026 20:08:22 +0000 Subject: [PATCH 29/37] mods --- src/boot.asm | 4 +- src/gamemode/gametypemenu/menudata.js | 165 ++++++++++++++++++++------ src/ram.asm | 2 + 3 files changed, 136 insertions(+), 35 deletions(-) diff --git a/src/boot.asm b/src/boot.asm index 21c4a904..1829d068 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -32,9 +32,9 @@ lda #$10 - sta menuVarDas + sta dasModifier lda #$06 - sta menuVarArr + sta arrModifier lda #MODE_TETRIS sta practiseType diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 935c652d..27570073 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -1,6 +1,11 @@ const seedFlag = ["TYPE_BOOL", "Seed Enabled", "seedEnabled"]; const seedInput = ["TYPE_HEX", "seed", 6, "set_seed_input"]; -const linecapWhen = ["TYPE_CHOICES", "linecap", ["off", "level", "lines"], "linecapWhen"]; +const linecapWhen = [ + "TYPE_CHOICES", + "linecap", + ["off", "level", "lines"], + "linecapWhen", +]; const linecapHow = [ "TYPE_CHOICES", "linecap how", @@ -18,8 +23,8 @@ const scoringModifier = [ "scoringModifier", ]; const paceModifier = ["TYPE_FF_OFF", "Pace", 16, "paceModifier"]; -const hzFlag = ["TYPE_BOOL", "HZ DISPLAY", "hzFlag",]; -const inputDisplayFlag = ["TYPE_BOOL", "Input Display", "inputDisplayFlag",]; +const hzFlag = ["TYPE_BOOL", "HZ DISPLAY", "hzFlag"]; +const inputDisplayFlag = ["TYPE_BOOL", "Input Display", "inputDisplayFlag"]; const disableFlash = ["TYPE_BOOL", "Disable Flash", "disableFlashFlag"]; const darkMode = [ "TYPE_CHOICES", @@ -27,7 +32,12 @@ const darkMode = [ ["off", "on", "neon", "lite", "teal", "og"], "darkModifier", ]; -const paletteSelection = ["TYPE_CHOICES", "palette", ["vanilla", "pride", "white",], "paletteFlag"]; +const paletteSelection = [ + "TYPE_CHOICES", + "palette", + ["vanilla", "pride", "white"], + "paletteFlag", +]; const crashModifier = [ "TYPE_CHOICES", @@ -56,21 +66,42 @@ const vertMirror = ["TYPE_BOOL", "mirror vert", "mirrorVertFlag"]; const presetModifier = ["TYPE_NUMBER", "setups", 8, "presetModifier"]; const typeBModifier = ["TYPE_NUMBER", "type-b height", 9, "typeBModifier"]; const checkerModifier = ["TYPE_NUMBER", "checker height", 9, "checkerModifier"]; -const quickTapLeftModifier = ["TYPE_NUMBER", "left cols", 20, "tapLeftModifier"]; -const quickTapRightModifier = ["TYPE_NUMBER", "right cols", 20, "tapRightModifier"]; -const transitionModifier = ["TYPE_NUMBER", "transition", 16, "transitionModifier"]; +const quickTapLeftModifier = [ + "TYPE_NUMBER", + "left cols", + 20, + "tapLeftModifier", +]; +const quickTapRightModifier = [ + "TYPE_NUMBER", + "right cols", + 20, + "tapRightModifier", +]; +const transitionModifier = [ + "TYPE_NUMBER", + "transition", + 16, + "transitionModifier", +]; const marathonModifier = ["TYPE_NUMBER", "marathon", 5, "marathonModifier"]; const tapqtyModifier = ["TYPE_NUMBER", "qty height", 16, "tapqtyModifier"]; const garbageModifier = ["TYPE_NUMBER", "garbage", 5, "garbageModifier"]; const droughtModifier = ["TYPE_NUMBER", "drought", 20, "droughtModifier"]; -const lowStackRowModifier = ["TYPE_NUMBER", "lowstack", 20, "lowStackRowModifier"]; +const lowStackRowModifier = [ + "TYPE_NUMBER", + "lowstack", + 20, + "lowStackRowModifier", +]; -const anydasDas = ["TYPE_NUMBER", "das", 32]; -const anydasArr = ["TYPE_NUMBER", "arr", 32]; +const anydasDas = ["TYPE_NUMBER", "das", 32, "dasModifier"]; +const anydasArr = ["TYPE_NUMBER", "arr", 32, "arrModifier"]; const anydasEntryDelay = [ "TYPE_CHOICES", "entry delay", ["off", "hydrant", "kitaru"], + "entryDelayModifier", ]; const modsSubMenu = { @@ -86,7 +117,6 @@ const modsSubMenu = { ], }; - const anydasSubMenu = { "anydas[mode=default]": [anydasDas, anydasArr, anydasEntryDelay], }; @@ -134,36 +164,105 @@ const goToMore = ["TYPE_SUBMENU", "more", moreSubMenu]; const goToDisplay = ["TYPE_SUBMENU", "display", displaySubMenu]; const goToAnydas = ["TYPE_SUBMENU", "anydas", anydasSubMenu]; -const optionsSubmenu = { - "options[mode=default]": [ +const mainMenu = { + "play tetris[mode=tetris]": [ + goToTournament, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "t-spins[mode=tspins]": [goToMods, goToDisplay, goToAnydas, goToMore], + "setups[mode=presets]": [ + presetModifier, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "stacking[mode=stacking]": [ + goToTournament, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "b-type[mode=typeb]": [ + typeBModifier, goToMods, goToDisplay, goToAnydas, goToMore, ], -}; - -const goToOptions = ["TYPE_SUBMENU", "options", optionsSubmenu]; - -const mainMenu = { - "play tetris[mode=tetris]": [goToOptions, goToTournament], - "t-spins[mode=tspins]": [goToOptions], - "setups[mode=presets]": [presetModifier, goToOptions], - "stacking[mode=stacking]": [goToOptions, goToTournament], - "b-type[mode=typeb]": [typeBModifier, goToOptions], "(quick)tap[mode=tap]": [ quickTapLeftModifier, quickTapRightModifier, - goToOptions, - ], - "tap quantity[mode=tapqty]": [tapqtyModifier, goToOptions], - "transition[mode=transition]": [transitionModifier, goToOptions, goToTournament], - "marathon[mode=marathon]": [marathonModifier, goToOptions, goToTournament], - "drought[mode=drought]": [droughtModifier, goToOptions, goToTournament], - "checkerboard[mode=checkerboard]": [checkerModifier, goToOptions, goToTournament], - "garbage[mode=garbage]": [garbageModifier, goToOptions, goToTournament], - "lowstack[mode=lowstack]": [lowStackRowModifier, goToOptions, goToTournament], - "tap/roll speed[mode=speed_test]": [goToOptions], + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "tap quantity[mode=tapqty]": [ + tapqtyModifier, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "transition[mode=transition]": [ + transitionModifier, + goToTournament, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "marathon[mode=marathon]": [ + marathonModifier, + goToTournament, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "drought[mode=drought]": [ + droughtModifier, + goToTournament, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "checkerboard[mode=checkerboard]": [ + checkerModifier, + goToTournament, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "garbage[mode=garbage]": [ + garbageModifier, + goToTournament, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "lowstack[mode=lowstack]": [ + lowStackRowModifier, + goToTournament, + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], + "tap/roll speed[mode=speed_test]": [ + goToMods, + goToDisplay, + goToAnydas, + goToMore, + ], }; const extraSpriteStrings = ["pause", "block", "clear?", "sure?!", "confetti"]; diff --git a/src/ram.asm b/src/ram.asm index 76e6b878..a78eee95 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -415,6 +415,8 @@ tapLeftModifier: .res 1 tapRightModifier: .res 1 mirrorHorizFlag: .res 1 mirrorVertFlag: .res 1 +arrModifier: .res 1 +entryDelayModifier: .res 1 .if KEYBOARD = 1 From d8f7adef4bf3d80e5c526851c4f95dd7c94ece8b Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 10 Jun 2026 20:15:40 +0000 Subject: [PATCH 30/37] add anydas build flag --- build.js | 6 ++++ src/boot.asm | 1 - src/constants.asm | 4 +++ src/gamemodestate/updateplayer1.asm | 31 ++++++++++++++++ src/modes/hz.asm | 2 ++ src/nametables/game_type_menu.js | 2 ++ src/playstate/active.asm | 55 +++++++++++++++++++++++++++++ src/playstate/spawnnext.asm | 9 +++++ src/ram.asm | 4 +++ 9 files changed, 113 insertions(+), 1 deletion(-) diff --git a/build.js b/build.js index 40430934..0b7697ce 100644 --- a/build.js +++ b/build.js @@ -23,6 +23,7 @@ if (args.includes('-h')) { -m mapper -a faster aeppoz + press select to end game +-A build anydas -s disable highscores/SRAM -k Famicom Keyboard support -w force WASM compiler @@ -88,6 +89,11 @@ if (args.includes('-o')) { console.log('cnrom override for autodetect'); } +if (args.includes('-A')) { + compileFlags.push('-D', 'ANYDAS=1'); + console.log('anydas enabled'); +} + // pass additional arguments to ca65 if (args.includes('--')) { const ca65Flags = args.slice(1+args.indexOf('--')); diff --git a/src/boot.asm b/src/boot.asm index 1829d068..d4ee3e81 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -31,7 +31,6 @@ sta floorModifier lda #$10 - sta dasModifier lda #$06 sta arrModifier diff --git a/src/constants.asm b/src/constants.asm index a462cac2..767e8df2 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -19,6 +19,10 @@ KEYBOARD := 0 CNROM_OVERRIDE := 0 .endif +.ifndef ANYDAS +ANYDAS = 0 +.endif + NO_MUSIC := 1 ; dev flags diff --git a/src/gamemodestate/updateplayer1.asm b/src/gamemodestate/updateplayer1.asm index a00be232..24db6543 100644 --- a/src/gamemodestate/updateplayer1.asm +++ b/src/gamemodestate/updateplayer1.asm @@ -10,7 +10,38 @@ gameModeState_updatePlayer1: jsr checkDebugGameplay jsr practiseAdvanceGame jsr practiseGameHUD +.if ANYDAS = 1 +; do nothing while piece is active (playstate = 1) + ldx playState + dex + beq @branchOnPlaystate +; do nothing if not kitaru charge + lda anydasARECharge + cmp #2 + bne @branchOnPlaystate +; do nothing when down is held + lda heldButtons + and #BUTTON_DOWN + bne @branchOnPlaystate +; reset das on new input + lda newlyPressedButtons + and #BUTTON_LEFT|BUTTON_RIGHT + bne @resetDas + lda heldButtons + and #BUTTON_LEFT|BUTTON_RIGHT + beq @branchOnPlaystate +; charge das (unless charged) + ldx autorepeatX + dex + beq @branchOnPlaystate + dec autorepeatX ; will clear zero flag + bne @branchOnPlaystate +@resetDas: + lda anydasDASValue + sta autorepeatX +@branchOnPlaystate: jsr branchOnPlayStatePlayer1 +.endif jsr stageSpriteForCurrentPiece jsr stageSpriteForNextPiece diff --git a/src/modes/hz.asm b/src/modes/hz.asm index f61863b4..66d32cc2 100644 --- a/src/modes/hz.asm +++ b/src/modes/hz.asm @@ -80,6 +80,7 @@ hzTap: lda #0 sta hzDebounceCounter +.if ANYDAS <> 1 lda dasOnlyFlag beq :+ lda #0 @@ -104,6 +105,7 @@ hzTap: lda #1 sta dasOnlyShiftDisabled : +.endif ; ignore 1 tap lda hzTapCounter diff --git a/src/nametables/game_type_menu.js b/src/nametables/game_type_menu.js index 86d27bfc..71ba2cff 100644 --- a/src/nametables/game_type_menu.js +++ b/src/nametables/game_type_menu.js @@ -7,6 +7,8 @@ const { flatLookup, } = require('./nametables'); +const anydas = !!process.env['GYM_FLAGS']?.match(/-D ANYDAS=1/); + const lookup = flatLookup(` 0123456789ABCDEF GHIJKLMNOPQRSTUV diff --git a/src/playstate/active.asm b/src/playstate/active.asm index 270c0735..b7903083 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -391,6 +391,7 @@ framesPerDropTablePAL: .byte $02,$02,$02,$01,$01,$01,$01,$01 .byte $01,$01,$01,$01,$01,$01 shift_tetrimino: +.if ANYDAS <> 1 ; dasOnlyFlag lda dasOnlyShiftDisabled beq @dasOnlyEnd @@ -423,6 +424,7 @@ shift_tetrimino: lda #$08 sta dasValuePeriod @shiftTetrimino: +.endif lda tetriminoX sta originalY @@ -435,6 +437,20 @@ shift_tetrimino: lda heldButtons and #$03 beq @ret +.if ANYDAS = 1 + dec autorepeatX + lda autorepeatX + cmp #$01 + bpl @ret +@zeroDas: + lda anydasARRValue + sta autorepeatX + beq @zeroArr + bne @buttonHeldDown +@resetAutorepeatX: + lda anydasDASValue + beq @zeroDas +.else inc autorepeatX lda autorepeatX cmp dasValueDelay @@ -445,6 +461,7 @@ shift_tetrimino: @resetAutorepeatX: lda #$00 +.endif sta autorepeatX @buttonHeldDown: lda heldButtons @@ -471,6 +488,44 @@ shift_tetrimino: @restoreX: lda originalY sta tetriminoX +.if ANYDAS = 1 + lda #$01 +.else lda dasValueDelay +.endif sta autorepeatX @ret: rts + +.if ANYDAS = 1 +@zeroArr: + lda heldButtons + and #BUTTON_RIGHT + beq @checkLeftPressed +@shiftRight: + inc tetriminoX + jsr isPositionValid + bne @shiftBackToLeft + lda #$03 + sta soundEffectSlot1Init + jmp @shiftRight +@checkLeftPressed: + lda heldButtons + and #BUTTON_LEFT + beq @leftNotPressed +@shiftLeft: + dec tetriminoX + jsr isPositionValid + bne @shiftBackToRight + lda #$03 + sta soundEffectSlot1Init + jmp @shiftLeft +@shiftBackToLeft: + dec tetriminoX + dec tetriminoX +@shiftBackToRight: + inc tetriminoX + lda #$01 + sta autorepeatX +@leftNotPressed: + rts +.endif diff --git a/src/playstate/spawnnext.asm b/src/playstate/spawnnext.asm index b706f84a..edec0906 100644 --- a/src/playstate/spawnnext.asm +++ b/src/playstate/spawnnext.asm @@ -52,6 +52,15 @@ playState_spawnNextTetrimino: jsr incrementPieceStat jsr chooseNextTetrimino sta nextPiece +.if ANYDAS = 1 + ldx anydasARECharge + beq @noCharge + txa + dex + bne @noCharge ; kitaru charge handled in playstate branch + sta autorepeatX ; store 1 if ARE Charge is on (hydrant charge) +@noCharge: +.endif @resetDownHold: lda #$00 sta autorepeatY diff --git a/src/ram.asm b/src/ram.asm index a78eee95..61e9117d 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -387,7 +387,9 @@ tapqtyModifier: .res 1 checkerModifier: .res 1 garbageModifier: .res 1 droughtModifier: .res 1 +.if ANYDAS <> 1 dasModifier: .res 1 +.endif lowStackRowModifier: .res 1 scoringModifier: .res 1 crashModifier: .res 1 @@ -400,7 +402,9 @@ darkModifier: .res 1 goofyFlag: .res 1 debugFlag: .res 1 linecapFlag: .res 1 +.if ANYDAS <> 1 dasOnlyFlag: .res 1 +.endif qualFlag: .res 1 palFlag: .res 1 paletteFlag: .res 1 From 9f30e80728d6bcd02165335eda3784b25c9f7b1e Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 10 Jun 2026 20:52:19 +0000 Subject: [PATCH 31/37] anydas is option --- build.js | 5 ----- src/constants.asm | 4 ---- src/gamemodestate/updateplayer1.asm | 6 ++--- src/modes/hz.asm | 2 -- src/nametables/game_type_menu.js | 2 -- src/playstate/active.asm | 35 ++++++++--------------------- src/playstate/spawnnext.asm | 13 +++++------ src/ram.asm | 4 ---- 8 files changed, 16 insertions(+), 55 deletions(-) diff --git a/build.js b/build.js index 0b7697ce..8c61c0ba 100644 --- a/build.js +++ b/build.js @@ -89,11 +89,6 @@ if (args.includes('-o')) { console.log('cnrom override for autodetect'); } -if (args.includes('-A')) { - compileFlags.push('-D', 'ANYDAS=1'); - console.log('anydas enabled'); -} - // pass additional arguments to ca65 if (args.includes('--')) { const ca65Flags = args.slice(1+args.indexOf('--')); diff --git a/src/constants.asm b/src/constants.asm index 767e8df2..a462cac2 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -19,10 +19,6 @@ KEYBOARD := 0 CNROM_OVERRIDE := 0 .endif -.ifndef ANYDAS -ANYDAS = 0 -.endif - NO_MUSIC := 1 ; dev flags diff --git a/src/gamemodestate/updateplayer1.asm b/src/gamemodestate/updateplayer1.asm index 24db6543..1ec613da 100644 --- a/src/gamemodestate/updateplayer1.asm +++ b/src/gamemodestate/updateplayer1.asm @@ -10,13 +10,12 @@ gameModeState_updatePlayer1: jsr checkDebugGameplay jsr practiseAdvanceGame jsr practiseGameHUD -.if ANYDAS = 1 ; do nothing while piece is active (playstate = 1) ldx playState dex beq @branchOnPlaystate ; do nothing if not kitaru charge - lda anydasARECharge + lda entryDelayModifier cmp #2 bne @branchOnPlaystate ; do nothing when down is held @@ -37,11 +36,10 @@ gameModeState_updatePlayer1: dec autorepeatX ; will clear zero flag bne @branchOnPlaystate @resetDas: - lda anydasDASValue + lda 0 sta autorepeatX @branchOnPlaystate: jsr branchOnPlayStatePlayer1 -.endif jsr stageSpriteForCurrentPiece jsr stageSpriteForNextPiece diff --git a/src/modes/hz.asm b/src/modes/hz.asm index 66d32cc2..f61863b4 100644 --- a/src/modes/hz.asm +++ b/src/modes/hz.asm @@ -80,7 +80,6 @@ hzTap: lda #0 sta hzDebounceCounter -.if ANYDAS <> 1 lda dasOnlyFlag beq :+ lda #0 @@ -105,7 +104,6 @@ hzTap: lda #1 sta dasOnlyShiftDisabled : -.endif ; ignore 1 tap lda hzTapCounter diff --git a/src/nametables/game_type_menu.js b/src/nametables/game_type_menu.js index 71ba2cff..86d27bfc 100644 --- a/src/nametables/game_type_menu.js +++ b/src/nametables/game_type_menu.js @@ -7,8 +7,6 @@ const { flatLookup, } = require('./nametables'); -const anydas = !!process.env['GYM_FLAGS']?.match(/-D ANYDAS=1/); - const lookup = flatLookup(` 0123456789ABCDEF GHIJKLMNOPQRSTUV diff --git a/src/playstate/active.asm b/src/playstate/active.asm index b7903083..677d1c6d 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -391,7 +391,6 @@ framesPerDropTablePAL: .byte $02,$02,$02,$01,$01,$01,$01,$01 .byte $01,$01,$01,$01,$01,$01 shift_tetrimino: -.if ANYDAS <> 1 ; dasOnlyFlag lda dasOnlyShiftDisabled beq @dasOnlyEnd @@ -412,9 +411,10 @@ shift_tetrimino: @dasOnlyEnd: ; region stuff - lda #$10 + lda dasModifier sta dasValueDelay - lda #$A + sec + sbc arrModifier sta dasValuePeriod ldy palFlag ; cpy #0 ; ldy sets z flag @@ -424,7 +424,6 @@ shift_tetrimino: lda #$08 sta dasValuePeriod @shiftTetrimino: -.endif lda tetriminoX sta originalY @@ -437,31 +436,21 @@ shift_tetrimino: lda heldButtons and #$03 beq @ret -.if ANYDAS = 1 - dec autorepeatX - lda autorepeatX - cmp #$01 - bpl @ret -@zeroDas: - lda anydasARRValue - sta autorepeatX - beq @zeroArr - bne @buttonHeldDown -@resetAutorepeatX: - lda anydasDASValue - beq @zeroDas -.else inc autorepeatX lda autorepeatX cmp dasValueDelay bmi @ret +@zeroDas: lda dasValuePeriod + cmp dasValueDelay + beq @zeroArr sta autorepeatX jmp @buttonHeldDown @resetAutorepeatX: + lda dasValueDelay + beq @zeroDas lda #$00 -.endif sta autorepeatX @buttonHeldDown: lda heldButtons @@ -488,15 +477,10 @@ shift_tetrimino: @restoreX: lda originalY sta tetriminoX -.if ANYDAS = 1 - lda #$01 -.else lda dasValueDelay -.endif sta autorepeatX @ret: rts -.if ANYDAS = 1 @zeroArr: lda heldButtons and #BUTTON_RIGHT @@ -524,8 +508,7 @@ shift_tetrimino: dec tetriminoX @shiftBackToRight: inc tetriminoX - lda #$01 + lda dasValueDelay sta autorepeatX @leftNotPressed: rts -.endif diff --git a/src/playstate/spawnnext.asm b/src/playstate/spawnnext.asm index edec0906..82ea11d0 100644 --- a/src/playstate/spawnnext.asm +++ b/src/playstate/spawnnext.asm @@ -52,15 +52,12 @@ playState_spawnNextTetrimino: jsr incrementPieceStat jsr chooseNextTetrimino sta nextPiece -.if ANYDAS = 1 - ldx anydasARECharge - beq @noCharge - txa + ldx entryDelayModifier + beq @resetDownHold dex - bne @noCharge ; kitaru charge handled in playstate branch - sta autorepeatX ; store 1 if ARE Charge is on (hydrant charge) -@noCharge: -.endif + bne @resetDownHold ; kitaru charge handled in playstate branch + lda dasModifier + sta autorepeatX ; store full charge for hydrant/1 @resetDownHold: lda #$00 sta autorepeatY diff --git a/src/ram.asm b/src/ram.asm index 61e9117d..a78eee95 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -387,9 +387,7 @@ tapqtyModifier: .res 1 checkerModifier: .res 1 garbageModifier: .res 1 droughtModifier: .res 1 -.if ANYDAS <> 1 dasModifier: .res 1 -.endif lowStackRowModifier: .res 1 scoringModifier: .res 1 crashModifier: .res 1 @@ -402,9 +400,7 @@ darkModifier: .res 1 goofyFlag: .res 1 debugFlag: .res 1 linecapFlag: .res 1 -.if ANYDAS <> 1 dasOnlyFlag: .res 1 -.endif qualFlag: .res 1 palFlag: .res 1 paletteFlag: .res 1 From 1c16f35d3bfd83721e3e1b0c1e43c4eaaad5bad0 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 10 Jun 2026 21:18:17 +0000 Subject: [PATCH 32/37] add anydas flag --- src/boot.asm | 4 +-- src/constants.asm | 9 ++++++- src/gamemodestate/initstate.asm | 10 ++++--- src/playstate/active.asm | 4 +-- src/ram.asm | 1 + src/util/check_region.asm | 4 +++ src/util/modetext.asm | 46 +++++++++++++++++++++++---------- 7 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/boot.asm b/src/boot.asm index d4ee3e81..8e01d24f 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -30,9 +30,9 @@ sta paceModifier sta floorModifier - lda #$10 + lda #NTSC_DAS sta dasModifier - lda #$06 + lda #NTSC_ARR sta arrModifier lda #MODE_TETRIS diff --git a/src/constants.asm b/src/constants.asm index a462cac2..509d980c 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -84,7 +84,7 @@ MODE_CHECKERBOARD MODE_GARBAGE MODE_LOWSTACK MODE_SPEED_TEST -MODE_GAME_QUANTITY +MODE_ANYDAS .endenum ; .endum @@ -150,6 +150,11 @@ MENU_SPRITE_Y_BASE := $46 MENU_MAX_Y_SCROLL := $A0 MENU_TOP_MARGIN_SCROLL := 7 ; in blocks +NTSC_DAS = 16 +NTSC_ARR = 6 + +PAL_DAS = 12 +PAL_ARR = 4 .macro MODENAMES .byte "TETRIS" @@ -165,4 +170,6 @@ MENU_TOP_MARGIN_SCROLL := 7 ; in blocks .byte "CKRBRD" .byte "GARBGE" .byte "LOWSTK" + .byte "KILLX2" + .byte "ANYDAS" .endmacro diff --git a/src/gamemodestate/initstate.asm b/src/gamemodestate/initstate.asm index dbae00d4..c61975e2 100644 --- a/src/gamemodestate/initstate.asm +++ b/src/gamemodestate/initstate.asm @@ -1,8 +1,10 @@ gameModeState_initGameState: - lda #$EF - ldx #$04 - ldy #$04 - jsr memset_page + lda #EMPTY_TILE + ldx #$00 +@clearPlayfield: + sta playfield,x + inx + bne @clearPlayfield ldx #$0F lda #$00 ; statsByType diff --git a/src/playstate/active.asm b/src/playstate/active.asm index 677d1c6d..5689713e 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -419,9 +419,9 @@ shift_tetrimino: ldy palFlag ; cpy #0 ; ldy sets z flag beq @shiftTetrimino - lda #$0C + lda #PAL_DAS sta dasValueDelay - lda #$08 + lda #PAL_DAS - PAL_ARR sta dasValuePeriod @shiftTetrimino: diff --git a/src/ram.asm b/src/ram.asm index a78eee95..a68aa185 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -417,6 +417,7 @@ mirrorHorizFlag: .res 1 mirrorVertFlag: .res 1 arrModifier: .res 1 entryDelayModifier: .res 1 +anydasFlag: .res 1 .if KEYBOARD = 1 diff --git a/src/util/check_region.asm b/src/util/check_region.asm index 3c710f8e..04454bc4 100644 --- a/src/util/check_region.asm +++ b/src/util/check_region.asm @@ -40,5 +40,9 @@ checkRegion: beq @ntsc lda #1 sta palFlag + lda #PAL_DAS + sta dasModifier + lda #PAL_ARR + sta arrModifier @ntsc: rts diff --git a/src/util/modetext.asm b/src/util/modetext.asm index faa473e4..d4efbc2f 100644 --- a/src/util/modetext.asm +++ b/src/util/modetext.asm @@ -1,20 +1,40 @@ displayModeText: - ldx practiseType -@drawModeName: - ; ldx practiseType - lda #0 -@loopAddr: - cpx #0 - beq @addr + lda #$00 + sta anydasFlag +; set anydasFlag + lda entryDelayModifier + bne @anydas + lda palFlag + bne @pal + ldx #NTSC_DAS + ldy #NTSC_ARR + bne @testAnydas +@pal: + ldx #PAL_DAS + ldy #PAL_ARR +@testAnydas: + cpx dasModifier + bne @anydas + + cpy arrModifier + bne @anydas + beq @notanydas +@anydas: + inc anydasFlag +@notanydas: + ldx #MODE_ANYDAS*6 + lda anydasFlag + bne @drawMode + ; practiseType * 6 + lda practiseType + asl + sta generalCounter + asl clc - adc #6 - dex - jmp @loopAddr -@addr: - ; offset in X + adc generalCounter tax - +@drawMode: lda tmp1 sta PPUADDR lda tmp2 From 3117674543d5e6568a1f02af062a502e9e9a3c96 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 10 Jun 2026 21:51:49 +0000 Subject: [PATCH 33/37] trt controlled by flag --- src/gamemode/gametypemenu/menudata.js | 3 ++- src/gamemodestate/initbackground.asm | 13 +++++++++++++ src/nametables/game.js | 6 +++--- src/nmi/render_mode_play_and_demo.asm | 11 ++++------- src/playstate/updatestats.asm | 3 +++ src/ram.asm | 1 + 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 27570073..f60d00b7 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -103,6 +103,7 @@ const anydasEntryDelay = [ ["off", "hydrant", "kitaru"], "entryDelayModifier", ]; +const trtFlag = ["TYPE_BOOL", "trt", "trtFlag"]; const modsSubMenu = { "board[mode=default]": [ @@ -118,7 +119,7 @@ const modsSubMenu = { }; const anydasSubMenu = { - "anydas[mode=default]": [anydasDas, anydasArr, anydasEntryDelay], + "anydas[mode=default]": [anydasDas, anydasArr, anydasEntryDelay, trtFlag,], }; const displaySubMenu = { diff --git a/src/gamemodestate/initbackground.asm b/src/gamemodestate/initbackground.asm index 6582e048..3e024083 100644 --- a/src/gamemodestate/initbackground.asm +++ b/src/gamemodestate/initbackground.asm @@ -10,6 +10,13 @@ gameModeState_initGameBackground: jsr copyRleNametableToPpu .addr game_nametable jsr scoringBackground + + + lda trtFlag + beq @noTrtPatch + jsr bulkCopyToPpu + .addr trt_nametable +@noTrtPatch: jsr debugNametableUI ldy #$20 @@ -221,6 +228,12 @@ seven_digit_nametable: .byte $21, $1E, $41, $0 ; 0 .byte $FF +trt_nametable: + .byte $23,$17,$4,$74,$34,$34,$75 + .byte $23,$37,$4,$35,$00,$00,$36 + .byte $23,$57,$4,$76,$37,$37,$77 + .byte $FF + savestate_nametable: .byte $22,$F7,$8,$74,$34,$34,$34,$34,$34,$34,$75 .byte $23,$17,$8,$35,$1C,$15,$18,$1D,$FF,$FF,$36 diff --git a/src/nametables/game.js b/src/nametables/game.js index 0b80a1cd..b9c0c77a 100644 --- a/src/nametables/game.js +++ b/src/nametables/game.js @@ -86,9 +86,9 @@ drawTiles(buffer, lookup, ` ʞ##ɌɍɎ#####ȱ##########Ȳ#######ʡʟ ʟ##ɜɝɞ#####ȱ##########Ȳ#######ʜʛ ʙ##########ȱ##########Ȳʟʜʕʞʟʒʝʞʡ -ʓ##ɤɥɦ#####ȱ##########Ȳɴȴȴɵʛʡʟʜʝ -ʠ##########ȱ##########Ȳȵ00ȶʡʒʙʒʞ -ʡ##########ɲȳȳȳȳȳȳȳȳȳȳɳɶȷȷɷʟʡʜʙʟ +ʓ##ɤɥɦ#####ȱ##########Ȳʔʞʡʜʛʡʟʜʝ +ʠ##########ȱ##########Ȳʡʜʝʓʡʒʙʒʞ +ʡ##########ɲȳȳȳȳȳȳȳȳȳȳɳʟʐʑʡʟʡʜʙʟ ʟʟʜʕʞʒʝʞʟʜʓʜʓʟʒʞʒʝʞʜʝʝʞʠʖʗʜʛʟʜʝʙ ʠʘʓʡʟʡʟʒʙʟʘʞʠʠʠʟʡʟʐʑʒʞʟʖʞʜʓʡʠʜʝʝ ʖʞʡʜʚʞʠʡʜʚʞʟʡʠʡʠʒʙʖʗʠʟʘʝʞʟʠʜʙʒʞʟ diff --git a/src/nmi/render_mode_play_and_demo.asm b/src/nmi/render_mode_play_and_demo.asm index cc028dba..4d43d1e7 100644 --- a/src/nmi/render_mode_play_and_demo.asm +++ b/src/nmi/render_mode_play_and_demo.asm @@ -15,13 +15,10 @@ render_mode_play_and_demo: lda trtScratch+5 beq LFC0C - ; lda gameMode - ; bne LFC0C - lda #$23 - sta PPUADDR - lda #$38 - sta PPUADDR - lda trtScratch+5 + ldx #$23 + stx PPUADDR + ldx #$38 + stx PPUADDR jsr twoDigsToPPU LFC0C: diff --git a/src/playstate/updatestats.asm b/src/playstate/updatestats.asm index 34261696..531a4974 100644 --- a/src/playstate/updatestats.asm +++ b/src/playstate/updatestats.asm @@ -181,7 +181,10 @@ checkLinecap: ; set linecapState @floorLinecapEnd: addPoints: + lda trtFlag + beq @noTetrisRate jsr trtCalculate +@noTetrisRate: inc playState lda practiseType cmp #MODE_CHECKERBOARD diff --git a/src/ram.asm b/src/ram.asm index aff9bc0e..e7d2b60f 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -421,6 +421,7 @@ mirrorVertFlag: .res 1 arrModifier: .res 1 entryDelayModifier: .res 1 anydasFlag: .res 1 +trtFlag: .res 1 .if KEYBOARD = 1 From 8f8c486eb4e2f905e6c174d876f62aedd15523f5 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 10 Jun 2026 22:21:07 +0000 Subject: [PATCH 34/37] das meter flag --- src/gamemode/gametypemenu/menudata.js | 14 +++++++++++--- src/gamemodestate/updateplayer1.asm | 5 +++-- src/modes/dasmeter.asm | 20 ++++++++++++++++++-- src/ram.asm | 1 + src/util/core.asm | 8 -------- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index f60d00b7..937120cd 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -102,8 +102,10 @@ const anydasEntryDelay = [ "entry delay", ["off", "hydrant", "kitaru"], "entryDelayModifier", + "entryDelayModifier", ]; const trtFlag = ["TYPE_BOOL", "trt", "trtFlag"]; +const dasMeterFlag = ["TYPE_BOOL", "das meter", "dasMeterFlag"]; const modsSubMenu = { "board[mode=default]": [ @@ -119,7 +121,13 @@ const modsSubMenu = { }; const anydasSubMenu = { - "anydas[mode=default]": [anydasDas, anydasArr, anydasEntryDelay, trtFlag,], + "anydas[mode=default]": [ + anydasDas, + anydasArr, + anydasEntryDelay, + trtFlag, + dasMeterFlag, + ], }; const displaySubMenu = { @@ -161,9 +169,9 @@ const tournamentSubMenu = { const goToTournament = ["TYPE_SUBMENU", "tournament", tournamentSubMenu]; const goToMods = ["TYPE_SUBMENU", "board", modsSubMenu]; -const goToMore = ["TYPE_SUBMENU", "more", moreSubMenu]; const goToDisplay = ["TYPE_SUBMENU", "display", displaySubMenu]; -const goToAnydas = ["TYPE_SUBMENU", "anydas", anydasSubMenu]; +const goToAnydas = ["TYPE_SUBMENU", "anydas etc", anydasSubMenu]; +const goToMore = ["TYPE_SUBMENU", "more", moreSubMenu]; const mainMenu = { "play tetris[mode=tetris]": [ diff --git a/src/gamemodestate/updateplayer1.asm b/src/gamemodestate/updateplayer1.asm index 1ec613da..85508049 100644 --- a/src/gamemodestate/updateplayer1.asm +++ b/src/gamemodestate/updateplayer1.asm @@ -31,9 +31,9 @@ gameModeState_updatePlayer1: beq @branchOnPlaystate ; charge das (unless charged) ldx autorepeatX - dex + cpx dasModifier beq @branchOnPlaystate - dec autorepeatX ; will clear zero flag + inc autorepeatX ; will clear zero flag bne @branchOnPlaystate @resetDas: lda 0 @@ -42,6 +42,7 @@ gameModeState_updatePlayer1: jsr branchOnPlayStatePlayer1 jsr stageSpriteForCurrentPiece jsr stageSpriteForNextPiece + jsr stageDasMeterSprites inc gameModeState ; 5 rts diff --git a/src/modes/dasmeter.asm b/src/modes/dasmeter.asm index b8a397be..b3543020 100644 --- a/src/modes/dasmeter.asm +++ b/src/modes/dasmeter.asm @@ -1,18 +1,34 @@ stageDasMeterSprites: + lda dasMeterFlag + beq @ret + lda playState + beq @ret + @dasValue = generalCounter @tile = generalCounter2 +@redCompare = generalCounter3 +@orangeCompare = generalCounter4 @yCoordinate = 211 @xStart = 103 + lda dasModifier + lsr + lsr + sta @orangeCompare + inc @orangeCompare ; 5 when ntsc vanilla + lsr + sta @redCompare + inc @redCompare ; 3 when ntsc vanilla + lda #$FE sta @tile lda autorepeatX lsr php sta @dasValue - cmp #5 + cmp @orangeCompare bcs @stageSprites dec @tile - cmp #3 + cmp @redCompare bcs @stageSprites dec @tile @stageSprites: diff --git a/src/ram.asm b/src/ram.asm index e7d2b60f..abeab605 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -422,6 +422,7 @@ arrModifier: .res 1 entryDelayModifier: .res 1 anydasFlag: .res 1 trtFlag: .res 1 +dasMeterFlag: .res 1 .if KEYBOARD = 1 diff --git a/src/util/core.asm b/src/util/core.asm index 9d5b2a20..aed55a81 100644 --- a/src/util/core.asm +++ b/src/util/core.asm @@ -57,14 +57,6 @@ random10: ; canon is waitForVerticalBlankingInterval updateAudioWaitForNmiAndResetOamStaging: - lda gameMode - cmp #4 - bne @noDasMeter - lda gameModeState - cmp #2 - bcc @noDasMeter - jsr stageDasMeterSprites -@noDasMeter: jsr updateAudio_jmp lda #$00 sta verticalBlankingInterval From 7fedc4bd4254dc30565cb444179dbcb059ebfc92 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Wed, 10 Jun 2026 22:35:28 +0000 Subject: [PATCH 35/37] linecap renders good --- src/nmi/render_mode_linecap.asm | 4 ++-- src/util/strings.asm | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nmi/render_mode_linecap.asm b/src/nmi/render_mode_linecap.asm index f51c8cad..d4ee03bc 100644 --- a/src/nmi/render_mode_linecap.asm +++ b/src/nmi/render_mode_linecap.asm @@ -25,9 +25,9 @@ render_linecap_level_lines: jmp render_mode_static @linecapLines: - lda linecapLines+1 - sta PPUDATA lda linecapLines + sta PPUDATA + lda linecapLines+1 jsr twoDigsToPPU @ret: rts diff --git a/src/util/strings.asm b/src/util/strings.asm index caea0091..1f10a66f 100644 --- a/src/util/strings.asm +++ b/src/util/strings.asm @@ -78,8 +78,8 @@ stringSpriteLoop: rts stringLookup: - .byte stringLinesO-stringLookup .byte stringLevelO-stringLookup + .byte stringLinesO-stringLookup .byte stringKSX2O-stringLookup .byte stringFromBelowO-stringLookup .byte stringInvizO-stringLookup From 7dc586ac855ca3faeb17fd4062e30f0a0e066fba Mon Sep 17 00:00:00 2001 From: zohassadar Date: Thu, 11 Jun 2026 00:12:24 +0000 Subject: [PATCH 36/37] restore SXTOKL --- src/gamemode/gametypemenu/menudata.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 937120cd..1049bd4f 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -81,7 +81,7 @@ const quickTapRightModifier = [ const transitionModifier = [ "TYPE_NUMBER", "transition", - 16, + 17, "transitionModifier", ]; const marathonModifier = ["TYPE_NUMBER", "marathon", 5, "marathonModifier"]; From abf28fd88e70aadb978132345ec055165b1eef97 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Thu, 11 Jun 2026 14:48:42 +0000 Subject: [PATCH 37/37] add todo --- TODO.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 TODO.md diff --git a/TODO.md b/TODO.md new file mode 100644 index 00000000..09d4e6aa --- /dev/null +++ b/TODO.md @@ -0,0 +1,18 @@ +# Pending +* lowstack should be option instead of mode +* pressing b on multi page should go to top of page +* rework tests to fit multi mode +* add animation to cursor arrows +* menu options stored in sram +* option to default all +* multiple scoreboards +* clear scoreboard individually +* lowstack & crunch compatibility + + +# Bugs +* abss from game renders part of playfield in menu +* lowstack line doesn't respond to vert mirror flag +* lowstack nope gets mirrored with horiz mirror flag +* ghost piece briefly flashes at the bottom of the board during entry delay +* harddrop current piece sprite glitchy during lineclears