From 3268ea358df8773ded3d6fc3b3a66052b75eb12f Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 29 Aug 2025 18:05:14 +0000 Subject: [PATCH 01/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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/79] 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 From 4c6be83f0f9c39f77cd02dcbdae504922d0e3107 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Thu, 11 Jun 2026 16:12:53 +0000 Subject: [PATCH 38/79] shell script to highlight unused variables --- tools/unused | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100755 tools/unused diff --git a/tools/unused b/tools/unused new file mode 100755 index 00000000..cd1bfe0f --- /dev/null +++ b/tools/unused @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# does not support whitespace in filenames +mapfile -t sources < <(find -name '*.asm' ! -name 'ram.asm') +mapfile -t variables < <(grep -oP '\w+(?=:\s*\.res)' src/ram.asm) + +for variable in "${variables[@]}"; do + count=$(wc -l < <(grep -P '\b'$variable'\b' "${sources[@]}")) + if [[ $count = 0 ]]; then + printf "Unused - %s\n" $variable + fi +done From ecab6f5f3cc4f52a3d8fd981744c19f6da77466b Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 12 Jun 2026 00:23:32 +0000 Subject: [PATCH 39/79] entry delay should be entry charge --- src/gamemode/gametypemenu/menudata.js | 5 ++--- src/gamemodestate/updateplayer1.asm | 2 +- src/playstate/spawnnext.asm | 2 +- src/ram.asm | 2 +- src/util/modetext.asm | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 1049bd4f..10b55e7c 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -99,10 +99,9 @@ const anydasDas = ["TYPE_NUMBER", "das", 32, "dasModifier"]; const anydasArr = ["TYPE_NUMBER", "arr", 32, "arrModifier"]; const anydasEntryDelay = [ "TYPE_CHOICES", - "entry delay", + "entry charge", ["off", "hydrant", "kitaru"], - "entryDelayModifier", - "entryDelayModifier", + "entryChargeModifier", ]; const trtFlag = ["TYPE_BOOL", "trt", "trtFlag"]; const dasMeterFlag = ["TYPE_BOOL", "das meter", "dasMeterFlag"]; diff --git a/src/gamemodestate/updateplayer1.asm b/src/gamemodestate/updateplayer1.asm index 85508049..162d77b5 100644 --- a/src/gamemodestate/updateplayer1.asm +++ b/src/gamemodestate/updateplayer1.asm @@ -15,7 +15,7 @@ gameModeState_updatePlayer1: dex beq @branchOnPlaystate ; do nothing if not kitaru charge - lda entryDelayModifier + lda entryChargeModifier cmp #2 bne @branchOnPlaystate ; do nothing when down is held diff --git a/src/playstate/spawnnext.asm b/src/playstate/spawnnext.asm index 82ea11d0..1e55bd04 100644 --- a/src/playstate/spawnnext.asm +++ b/src/playstate/spawnnext.asm @@ -52,7 +52,7 @@ playState_spawnNextTetrimino: jsr incrementPieceStat jsr chooseNextTetrimino sta nextPiece - ldx entryDelayModifier + ldx entryChargeModifier beq @resetDownHold dex bne @resetDownHold ; kitaru charge handled in playstate branch diff --git a/src/ram.asm b/src/ram.asm index abeab605..83042778 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -419,7 +419,7 @@ tapRightModifier: .res 1 mirrorHorizFlag: .res 1 mirrorVertFlag: .res 1 arrModifier: .res 1 -entryDelayModifier: .res 1 +entryChargeModifier: .res 1 anydasFlag: .res 1 trtFlag: .res 1 dasMeterFlag: .res 1 diff --git a/src/util/modetext.asm b/src/util/modetext.asm index d4efbc2f..88215fb6 100644 --- a/src/util/modetext.asm +++ b/src/util/modetext.asm @@ -3,7 +3,7 @@ displayModeText: lda #$00 sta anydasFlag ; set anydasFlag - lda entryDelayModifier + lda entryChargeModifier bne @anydas lda palFlag bne @pal From 9986fbac8569a5df10347f5f91739ec73032c219 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 12 Jun 2026 00:56:07 +0000 Subject: [PATCH 40/79] fix abss bug --- TODO.md | 1 - src/gamemodestate/checkforabss.asm | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 09d4e6aa..628a75cf 100644 --- a/TODO.md +++ b/TODO.md @@ -11,7 +11,6 @@ # 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 diff --git a/src/gamemodestate/checkforabss.asm b/src/gamemodestate/checkforabss.asm index 7d4977b7..8378ba35 100644 --- a/src/gamemodestate/checkforabss.asm +++ b/src/gamemodestate/checkforabss.asm @@ -11,6 +11,8 @@ gameModeState_checkForResetKeyCombo: rts @reset: jsr updateAudio2 + lda #0 + sta renderMode lda #$2 ; straight to menu screen sta gameMode lda qualFlag From 3100d152d048907796e93e19bbec8f76f63532c6 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 12 Jun 2026 16:34:51 +0000 Subject: [PATCH 41/79] instant harddrop --- src/nmi/render.asm | 3 +- src/nmi/render_mode_play_and_demo.asm | 41 +++++++++++++++++++++++++++ src/playstate/active.asm | 1 + src/playstate/spawnnext.asm | 2 ++ src/sprites/piece.asm | 4 +++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/nmi/render.asm b/src/nmi/render.asm index 63cdb700..d43266c4 100644 --- a/src/nmi/render.asm +++ b/src/nmi/render.asm @@ -7,7 +7,8 @@ render: branchTo renderMode, \ render_mode_rocket, \ render_mode_speed_test, \ render_mode_level_menu, \ - render_mode_linecap_menu + render_mode_linecap_menu, \ + render_mode_dump_playfield .include "render_mode_level_menu.asm" ; no rts / jmp diff --git a/src/nmi/render_mode_play_and_demo.asm b/src/nmi/render_mode_play_and_demo.asm index 4d43d1e7..78bc7629 100644 --- a/src/nmi/render_mode_play_and_demo.asm +++ b/src/nmi/render_mode_play_and_demo.asm @@ -496,3 +496,44 @@ L9996: lda generalCounter ora #RENDER_STATS sta renderFlags rts + +stageFullPlayfield: + ldy #18 +@loop: + ldx multBy10Table,y +.repeat 10,i + lda playfield+10+i,x + sta $100+(i*19),y +.endrepeat + dey + bpl @loop + lda #9 + sta renderMode + lda #$20 + sta vramRow + rts + +render_mode_dump_playfield: + lda #$9C + sta PPUCTRL + tsx + txa + ldx #$FF + txs + tax + .repeat 10,i + lda #$20 + sta PPUADDR + lda #$EC+i + sta PPUADDR + .repeat 19 + pla + sta PPUDATA + .endrepeat + .endrepeat + txs + lda #$03 + sta renderMode + rts + +.out .sprintf("instant harddrop rendering: %d", *-stageFullPlayfield) diff --git a/src/playstate/active.asm b/src/playstate/active.asm index 5689713e..220ca550 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -222,6 +222,7 @@ harddropShift: bpl @topRowLoop ; lda #TETRIMINO_X_HIDE ; sta tetriminoX + jsr stageFullPlayfield @noScore: diff --git a/src/playstate/spawnnext.asm b/src/playstate/spawnnext.asm index 1e55bd04..cb0855ee 100644 --- a/src/playstate/spawnnext.asm +++ b/src/playstate/spawnnext.asm @@ -1,6 +1,8 @@ SPAWN_NEXT_ADDONS := 1 playState_spawnNextTetrimino: + lda hardDropFlag + bne :+ lda vramRow cmp #$20 bpl :+ diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 7afae416..ac83d898 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -1,7 +1,11 @@ stageSpriteForCurrentPiece: lda #$0 sta pieceTileModifier + lda renderMode + cmp #9 + beq @skipCurrent jsr stageSpriteForCurrentPiece_actual +@skipCurrent: lda hardDropFlag bne ghostPiece lda ghostPieceFlag From a7c51a8c03f535624e68f9f818da4c8b30cd50cd Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 12 Jun 2026 17:07:04 +0000 Subject: [PATCH 42/79] simpler, faster, supports spaces in filenames --- tools/unused | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/unused b/tools/unused index cd1bfe0f..0779edd1 100755 --- a/tools/unused +++ b/tools/unused @@ -1,12 +1,9 @@ #!/usr/bin/env bash -# does not support whitespace in filenames -mapfile -t sources < <(find -name '*.asm' ! -name 'ram.asm') -mapfile -t variables < <(grep -oP '\w+(?=:\s*\.res)' src/ram.asm) +mapfile -d '' -t sources < <(find -name '*.asm' ! -name 'ram.asm' -print0) -for variable in "${variables[@]}"; do - count=$(wc -l < <(grep -P '\b'$variable'\b' "${sources[@]}")) - if [[ $count = 0 ]]; then +for variable in $(grep -oP '\w+(?=:\s*\.res)' src/ram.asm); do + if ! grep -qP '\b'$variable'\b' "${sources[@]}"; then printf "Unused - %s\n" $variable fi done From 11d9fc23e6b8f2cc40c3b24a1529cf862beeae33 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Fri, 12 Jun 2026 17:13:23 +0000 Subject: [PATCH 43/79] even faster --- tools/unused | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/unused b/tools/unused index 0779edd1..fb674bb6 100755 --- a/tools/unused +++ b/tools/unused @@ -3,7 +3,7 @@ mapfile -d '' -t sources < <(find -name '*.asm' ! -name 'ram.asm' -print0) for variable in $(grep -oP '\w+(?=:\s*\.res)' src/ram.asm); do - if ! grep -qP '\b'$variable'\b' "${sources[@]}"; then + if ! grep -q '\b'$variable'\b' "${sources[@]}"; then printf "Unused - %s\n" $variable fi done From b8413c52d85db591df1923ff87a916c80f1a9358 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 13 Jun 2026 15:57:38 +0000 Subject: [PATCH 44/79] rearrange menu, add das options --- src/gamemode/gametypemenu/menudata.js | 139 ++++++++------------------ src/playstate/active.asm | 6 ++ src/ram.asm | 2 + src/util/modetext.asm | 10 +- 4 files changed, 59 insertions(+), 98 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 10b55e7c..ee9a550b 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -95,19 +95,26 @@ const lowStackRowModifier = [ "lowStackRowModifier", ]; -const anydasDas = ["TYPE_NUMBER", "das", 32, "dasModifier"]; -const anydasArr = ["TYPE_NUMBER", "arr", 32, "arrModifier"]; +const noWallChargeFlag = [ + "TYPE_CHOICES", + "wall charge", + ["on", "off"], + "noWallChargeFlag", +]; +const disableDasFlag = ["TYPE_CHOICES", "das", ["on", "off"], "disableDasFlag"]; +const anydasDas = ["TYPE_NUMBER", "delay", 32, "dasModifier"]; +const anydasArr = ["TYPE_NUMBER", "arrrr", 32, "arrModifier"]; const anydasEntryDelay = [ "TYPE_CHOICES", "entry charge", ["off", "hydrant", "kitaru"], "entryChargeModifier", ]; -const trtFlag = ["TYPE_BOOL", "trt", "trtFlag"]; +const trtFlag = ["TYPE_BOOL", "tetris rate", "trtFlag"]; const dasMeterFlag = ["TYPE_BOOL", "das meter", "dasMeterFlag"]; const modsSubMenu = { - "board[mode=default]": [ + "mods[mode=default]": [ floorModifier, crunchModifier, invisibleFlag, @@ -119,11 +126,21 @@ const modsSubMenu = { ], }; -const anydasSubMenu = { - "anydas[mode=default]": [ +const dasSubMenu = { + "das[mode=default]": [ anydasDas, anydasArr, anydasEntryDelay, + disableDasFlag, + noWallChargeFlag, + ], +}; + +const infoSubMenu = { + "info[mode=default]": [ + hzFlag, + inputDisplayFlag, + paceModifier, trtFlag, dasMeterFlag, ], @@ -132,9 +149,6 @@ const anydasSubMenu = { const displaySubMenu = { "display[mode=default]": [ scoringModifier, - paceModifier, - hzFlag, - inputDisplayFlag, disableFlash, darkMode, paletteSelection, @@ -167,110 +181,41 @@ const tournamentSubMenu = { }; const goToTournament = ["TYPE_SUBMENU", "tournament", tournamentSubMenu]; -const goToMods = ["TYPE_SUBMENU", "board", modsSubMenu]; +const goToMods = ["TYPE_SUBMENU", "mods", modsSubMenu]; const goToDisplay = ["TYPE_SUBMENU", "display", displaySubMenu]; -const goToAnydas = ["TYPE_SUBMENU", "anydas etc", anydasSubMenu]; +const goToDas = ["TYPE_SUBMENU", "das", dasSubMenu]; +const goToInfo = ["TYPE_SUBMENU", "info", infoSubMenu]; const goToMore = ["TYPE_SUBMENU", "more", moreSubMenu]; +const shared = [goToMods, goToInfo, goToDisplay, goToDas, goToMore]; + 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, - ], + "play tetris[mode=tetris]": [goToTournament, ...shared], + "t-spins[mode=tspins]": [...shared], + "setups[mode=presets]": [presetModifier, ...shared], + "stacking[mode=stacking]": [goToTournament, ...shared], + "b-type[mode=typeb]": [typeBModifier, ...shared], "(quick)tap[mode=tap]": [ quickTapLeftModifier, quickTapRightModifier, - goToMods, - goToDisplay, - goToAnydas, - goToMore, - ], - "tap quantity[mode=tapqty]": [ - tapqtyModifier, - goToMods, - goToDisplay, - goToAnydas, - goToMore, + ...shared, ], + "tap quantity[mode=tapqty]": [tapqtyModifier, ...shared], "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, + ...shared, ], + "marathon[mode=marathon]": [marathonModifier, goToTournament, ...shared], + "drought[mode=drought]": [droughtModifier, goToTournament, ...shared], "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, + ...shared, ], + "garbage[mode=garbage]": [garbageModifier, goToTournament, ...shared], + "lowstack[mode=lowstack]": [lowStackRowModifier, goToTournament, ...shared], + "tap/roll speed[mode=speed_test]": [...shared], }; const extraSpriteStrings = ["pause", "block", "clear?", "sure?!", "confetti"]; diff --git a/src/playstate/active.asm b/src/playstate/active.asm index 220ca550..fea1987f 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -437,6 +437,8 @@ shift_tetrimino: lda heldButtons and #$03 beq @ret + lda disableDasFlag + bne @ret inc autorepeatX lda autorepeatX cmp dasValueDelay @@ -478,6 +480,8 @@ shift_tetrimino: @restoreX: lda originalY sta tetriminoX + lda noWallChargeFlag + bne @ret lda dasValueDelay sta autorepeatX @ret: rts @@ -509,6 +513,8 @@ shift_tetrimino: dec tetriminoX @shiftBackToRight: inc tetriminoX + lda noWallChargeFlag + bne @leftNotPressed lda dasValueDelay sta autorepeatX @leftNotPressed: diff --git a/src/ram.asm b/src/ram.asm index 83042778..5a3f3037 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -423,6 +423,8 @@ entryChargeModifier: .res 1 anydasFlag: .res 1 trtFlag: .res 1 dasMeterFlag: .res 1 +noWallChargeFlag: .res 1 +disableDasFlag: .res 1 .if KEYBOARD = 1 diff --git a/src/util/modetext.asm b/src/util/modetext.asm index 88215fb6..aa8e5517 100644 --- a/src/util/modetext.asm +++ b/src/util/modetext.asm @@ -3,25 +3,33 @@ displayModeText: lda #$00 sta anydasFlag ; set anydasFlag + lda disableDasFlag + bne @anydas + lda noWallChargeFlag + bne @anydas lda entryChargeModifier bne @anydas lda palFlag bne @pal + +; set regional differences ldx #NTSC_DAS ldy #NTSC_ARR bne @testAnydas @pal: ldx #PAL_DAS ldy #PAL_ARR + +; test das & arr values @testAnydas: cpx dasModifier bne @anydas cpy arrModifier - bne @anydas beq @notanydas @anydas: inc anydasFlag + @notanydas: ldx #MODE_ANYDAS*6 lda anydasFlag From a95cd3be9c9107ba862df9fd6793f1a8c8f60941 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 13 Jun 2026 15:58:03 +0000 Subject: [PATCH 45/79] embed latest git tag in rom --- src/nametables/game_type_menu.js | 46 ++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/nametables/game_type_menu.js b/src/nametables/game_type_menu.js index 86d27bfc..06c1f8eb 100644 --- a/src/nametables/game_type_menu.js +++ b/src/nametables/game_type_menu.js @@ -5,7 +5,9 @@ const { drawRect, drawAttrs, flatLookup, -} = require('./nametables'); +} = require("./nametables"); + +const { spawnSync } = require("child_process"); const lookup = flatLookup(` 0123456789ABCDEF @@ -27,9 +29,11 @@ WXYZ-,˙>######## `); const buffer = blankNT(); -const extra = [...buffer]; -drawTiles(buffer, lookup, ` +drawTiles( + buffer, + lookup, + ` #a d# #a d# #a d# @@ -57,14 +61,16 @@ drawTiles(buffer, lookup, ` #a d# #a d# #a d# -#a V67 d# #a d# #a d# -`); +#a d# +`, +); -if (process.env['GYM_FLAGS']?.match(/-D KEYBOARD=1/)) { - drawTiles(extra, lookup, "KEYBOARD", 32 * 15 + 6); - } +const gitTag = spawnSync("git", ["describe", "--tags"]).stdout.toString(); +[...gitTag.trim()].forEach( + (c, i) => (buffer[32 * 28 + 6 + i] = lookup.indexOf(c.toUpperCase())), +); const background = ` ɢ##############################ɳ @@ -101,15 +107,16 @@ const background = ` drawTiles(buffer, lookup, background); -drawRect(buffer, 8, 2, 10, 5, 0xB0); // draw logo +drawRect(buffer, 8, 2, 10, 5, 0xb0); // draw logo -const urlX = 3; -const urlY = 27; +// const urlX = 3; +// const urlY = 27; -drawRect(buffer, urlX, urlY, 12, 1, 0x74); -drawRect(buffer, urlX+12, urlY, 12, 1, 0x84); +// drawRect(buffer, urlX, urlY, 12, 1, 0x74); +// drawRect(buffer, urlX+12, urlY, 12, 1, 0x84); -drawAttrs(buffer, [` +drawAttrs(buffer, [ + ` 2222222222222222 2222211111122222 2222211111122222 @@ -118,7 +125,8 @@ drawAttrs(buffer, [` 2222222222222222 2222222222222222 2222222222222222 -`,` +`, + ` 2222222222222222 2222222222222222 2222222222222222 @@ -127,9 +135,7 @@ drawAttrs(buffer, [` 2333333333333332 2222222222222222 2222222222222222 -`]); +`, +]); -writeRLE( - __dirname + '/game_type_menu_nametable_practise.bin', - buffer, -); +writeRLE(__dirname + "/game_type_menu_nametable_practise.bin", buffer); From fdc9a74d5ee30acdae6cb1e8fef60f8a1bfe89e0 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 13 Jun 2026 16:53:06 +0000 Subject: [PATCH 46/79] crunch separated; rename things; make killx2 & speedtest playable --- src/constants.asm | 3 ++- src/gamemode/gametypemenu/menu.asm | 22 +++++++++++++++++++ src/gamemode/gametypemenu/menudata.js | 31 ++++++++++++++------------- src/modes/crunch.asm | 16 ++++++++------ src/modes/events.asm | 6 +----- src/nmi/render_input_log.asm | 5 ++--- src/playstate/completedrows.asm | 2 -- src/playstate/util.asm | 7 ++++-- src/ram.asm | 3 ++- 9 files changed, 59 insertions(+), 36 deletions(-) diff --git a/src/constants.asm b/src/constants.asm index 509d980c..7c0fffac 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -83,8 +83,9 @@ MODE_DROUGHT MODE_CHECKERBOARD MODE_GARBAGE MODE_LOWSTACK -MODE_SPEED_TEST +MODE_KILLX2 MODE_ANYDAS +MODE_SPEED_TEST .endenum ; .endum diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index 32916045..c24aafc2 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -77,6 +77,8 @@ gameMode_gameTypeMenu: lda #$1 sta renderMode lda #0 + sta ppuScrollX + sta ppuScrollY sta hideNextPiece sta byteSpriteTile sta gameStarted @@ -97,7 +99,27 @@ gameMode_gameTypeMenu: gameTypeLoop: lda gameStarted beq @noGame + lda #0 + sta killX2Flag + lda practiseType + cmp #MODE_SPEED_TEST + bne @notSpeedTest + lda #7 + sta gameMode + bne @sfx +@notSpeedTest: + lda practiseType ; is already in A, but this is explicit + cmp #MODE_KILLX2 + bne @notKillX2 + lda #0 + sta renderMode + sta gameModeState + lda #1 + sta killX2Flag + inc gameMode +@notKillX2: inc gameMode +@sfx: lda #$2 sta soundEffectSlot1Init rts diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index ee9a550b..9ef124a8 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -54,43 +54,43 @@ const keyboardFlag = ["TYPE_BOOL", "keyboard"]; const qualFlag = ["TYPE_BOOL", "qual", "qualFlag"]; const floorModifier = ["TYPE_FF_OFF", "floor", 16, "floorModifier"]; -const crunchModifier = ["TYPE_NUMBER", "crunch", 16, "crunchModifier"]; +const crunchLeftModifier = ["TYPE_NUMBER", "crunch left", 4, "crunchLeftModifier"]; +const crunchRightModifier = ["TYPE_NUMBER", "crunch right", 4, "crunchRightModifier"]; const invisibleFlag = ["TYPE_BOOL", "invisible", "invisibleOptionFlag"]; const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; -const killX2 = ["TYPE_BOOL", "killX2", "killX2Flag"]; 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"]; -const checkerModifier = ["TYPE_NUMBER", "checker height", 9, "checkerModifier"]; +const presetModifier = ["TYPE_NUMBER", "preset", 8, "presetModifier"]; +const typeBModifier = ["TYPE_NUMBER", "height", 9, "typeBModifier"]; +const checkerModifier = ["TYPE_NUMBER", "height", 9, "checkerModifier"]; const quickTapLeftModifier = [ "TYPE_NUMBER", - "left cols", + "left", 20, "tapLeftModifier", ]; const quickTapRightModifier = [ "TYPE_NUMBER", - "right cols", + "right", 20, "tapRightModifier", ]; const transitionModifier = [ "TYPE_NUMBER", - "transition", + "modifier", 17, "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 marathonModifier = ["TYPE_NUMBER", "modifier", 5, "marathonModifier"]; +const tapqtyModifier = ["TYPE_NUMBER", "height", 16, "tapqtyModifier"]; +const garbageModifier = ["TYPE_NUMBER", "modifier", 5, "garbageModifier"]; +const droughtModifier = ["TYPE_NUMBER", "modifier", 20, "droughtModifier"]; const lowStackRowModifier = [ "TYPE_NUMBER", - "lowstack", + "height", 20, "lowStackRowModifier", ]; @@ -116,11 +116,11 @@ const dasMeterFlag = ["TYPE_BOOL", "das meter", "dasMeterFlag"]; const modsSubMenu = { "mods[mode=default]": [ floorModifier, - crunchModifier, + crunchLeftModifier, + crunchRightModifier, invisibleFlag, ghostPiece, hardDrop, - killX2, horizMirror, vertMirror, ], @@ -216,6 +216,7 @@ const mainMenu = { "garbage[mode=garbage]": [garbageModifier, goToTournament, ...shared], "lowstack[mode=lowstack]": [lowStackRowModifier, goToTournament, ...shared], "tap/roll speed[mode=speed_test]": [...shared], + "kill*2[mode=killX2]": [...shared], }; const extraSpriteStrings = ["pause", "block", "clear?", "sure?!", "confetti"]; diff --git a/src/modes/crunch.asm b/src/modes/crunch.asm index 6e974c8d..dbb00e96 100644 --- a/src/modes/crunch.asm +++ b/src/modes/crunch.asm @@ -19,6 +19,11 @@ ; clobbers generalCounter3 & generalCounter4 (defined in playstate/util.asm) advanceGameCrunch: + ldx crunchLeftModifier + bne @crunch + ldx crunchRightModifier + beq crunchReturn +@crunch: ; initialize playfield row 19 to 0 ldx #$13 @nextRow: @@ -35,7 +40,7 @@ crunchReturn: advanceSides: ; called in playState_checkForCompletedRows and in advanceGameCrunch ; draws to row defined in playfieldAddr, which defaults to 0 - jsr unpackCrunchModifier + jsr copyCrunchModifier lda #BLOCK_TILES @@ -57,12 +62,9 @@ advanceSides: bpl @rightLoop ; unconditional -unpackCrunchModifier: - lda crunchModifier - lsr - lsr +copyCrunchModifier: + lda crunchLeftModifier sta crunchLeftColumns ; generalCounter3 - lda crunchModifier - and #$03 + lda crunchRightModifier sta crunchRightColumns ; generalCounter4 rts diff --git a/src/modes/events.asm b/src/modes/events.asm index 8002ad4d..0875a9b1 100644 --- a/src/modes/events.asm +++ b/src/modes/events.asm @@ -9,11 +9,7 @@ practiseInitGameState: bmi @skipFloor jsr advanceGameFloor @skipFloor: - lda crunchModifier - beq @skipCrunch - jsr advanceGameCrunch -@skipCrunch: - rts + jmp advanceGameCrunch practisePrepareNext: lda paceModifier diff --git a/src/nmi/render_input_log.asm b/src/nmi/render_input_log.asm index b53a6315..ca0a8768 100644 --- a/src/nmi/render_input_log.asm +++ b/src/nmi/render_input_log.asm @@ -31,7 +31,7 @@ renderHzInputRows: sta inputLogCounter ; enable vertical drawing - lda PPUCTRL + lda currentPpuCtrl ora #%100 sta PPUCTRL @@ -52,8 +52,7 @@ renderHzInputRows: jsr clearInputLine - lda PPUCTRL - and #%11111011 + lda currentPpuCtrl sta PPUCTRL diff --git a/src/playstate/completedrows.asm b/src/playstate/completedrows.asm index 191e0d13..e0ac20ed 100644 --- a/src/playstate/completedrows.asm +++ b/src/playstate/completedrows.asm @@ -141,8 +141,6 @@ playState_checkForCompletedRows: @tapQtyEnd: ; update top row for crunch - lda crunchModifier - beq @crunchEnd jsr advanceSides ; clobbers generalCounter3 and generalCounter4 @crunchEnd: diff --git a/src/playstate/util.asm b/src/playstate/util.asm index 35144f39..f82662a5 100644 --- a/src/playstate/util.asm +++ b/src/playstate/util.asm @@ -74,11 +74,14 @@ updateMusicSpeed: ldy #50 ; replaces above ; check if crunch mode - ldx crunchModifier + ldx crunchLeftModifier + bne @crunch + ldx crunchRightModifier beq @notCrunch +@crunch: ; add crunch left columns to y - jsr unpackCrunchModifier + jsr copyCrunchModifier tya clc adc crunchLeftColumns ; offset y with left column count (generalCounter3) diff --git a/src/ram.asm b/src/ram.asm index 5a3f3037..6b5d5ad2 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -382,7 +382,8 @@ paceModifier: .res 1 presetModifier: .res 1 typeBModifier: .res 1 floorModifier: .res 1 -crunchModifier: .res 1 +crunchLeftModifier: .res 1 +crunchRightModifier: .res 1 tapModifier: .res 1 transitionModifier: .res 1 marathonModifier: .res 1 From 606080a4e992d042dd37ca3e02f47162b5e14198 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 13 Jun 2026 17:18:33 +0000 Subject: [PATCH 47/79] remove unnecessary ppuctrl writes --- src/nmi/render_input_log.asm | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/nmi/render_input_log.asm b/src/nmi/render_input_log.asm index b53a6315..8e23ebbb 100644 --- a/src/nmi/render_input_log.asm +++ b/src/nmi/render_input_log.asm @@ -30,11 +30,6 @@ renderHzInputRows: lda #2 sta inputLogCounter - ; enable vertical drawing - lda PPUCTRL - ora #%100 - sta PPUCTRL - jsr getInputAddr tya sta PPUADDR @@ -52,10 +47,6 @@ renderHzInputRows: jsr clearInputLine - lda PPUCTRL - and #%11111011 - sta PPUCTRL - @checkLimit: lda inputLogCounter From cf14b3dd1e09f7a5e126125761668fbea531b565 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 13 Jun 2026 17:55:29 +0000 Subject: [PATCH 48/79] hide ghost during entry delay --- src/sprites/piece.asm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index ac83d898..51d97772 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -33,6 +33,14 @@ ghostPiece: lda ghostPieceFlag beq @noGhost +; no ghost piece during entry delay + lda playState + cmp #1 + beq @ghost + cmp #8 + bne @noGhost + +@ghost: lda frameCounter and #1 asl From cef6a948f512c95debdaba141358e9d114df25ce Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 13 Jun 2026 17:55:39 +0000 Subject: [PATCH 49/79] killx2 starts at level 39 --- src/gamemode/gametypemenu/menu.asm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index c24aafc2..cd364c76 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -114,6 +114,8 @@ gameTypeLoop: lda #0 sta renderMode sta gameModeState + lda #39 + sta levelNumber lda #1 sta killX2Flag inc gameMode From 3e827fc8a5411b433c6d469a8918a63babcd576f Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 13 Jun 2026 19:41:17 +0000 Subject: [PATCH 50/79] update TODO --- TODO.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/TODO.md b/TODO.md index 628a75cf..fd5671a7 100644 --- a/TODO.md +++ b/TODO.md @@ -7,11 +7,10 @@ * option to default all * multiple scoreboards * clear scoreboard individually -* lowstack & crunch compatibility - # Bugs +* goofy foot toggle is difficult +* lowstack & crunch do not work together +* garbage + crunch or floor does not work well * 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 From 31eb5b079bc9db19b77d8d9277e893a458191e22 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 13 Jun 2026 23:56:34 +0000 Subject: [PATCH 51/79] use menu das settings for pal --- src/playstate/active.asm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/playstate/active.asm b/src/playstate/active.asm index fea1987f..d0586741 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -417,13 +417,13 @@ shift_tetrimino: sec sbc arrModifier sta dasValuePeriod - ldy palFlag - ; cpy #0 ; ldy sets z flag - beq @shiftTetrimino - lda #PAL_DAS - sta dasValueDelay - lda #PAL_DAS - PAL_ARR - sta dasValuePeriod + ; ldy palFlag + ; ; cpy #0 ; ldy sets z flag + ; beq @shiftTetrimino + ; lda #PAL_DAS + ; sta dasValueDelay + ; lda #PAL_DAS - PAL_ARR + ; sta dasValuePeriod @shiftTetrimino: lda tetriminoX From cc881e6b6b06a122d96eea5019de6dc8a34a434c Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sat, 13 Jun 2026 23:56:54 +0000 Subject: [PATCH 52/79] anydas does not overwrite mode name --- src/util/modetext.asm | 74 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/src/util/modetext.asm b/src/util/modetext.asm index aa8e5517..1dacfab2 100644 --- a/src/util/modetext.asm +++ b/src/util/modetext.asm @@ -28,13 +28,71 @@ displayModeText: cpy arrModifier beq @notanydas @anydas: - inc anydasFlag + jsr @notanydas + ldx #MODE_ANYDAS*6 + lda tmp2 + sec + sbc #33 + sta tmp2 + lda tmp1 + sbc #0 + sta tmp1 + sta PPUADDR + lda tmp2 + sta PPUADDR + +; lots of opportunity for efficiency here + lda gameMode + cmp #3 + beq @setupMenuAnydas + lda #$35 + sta PPUDATA + jsr @startLoop + lda #$36 + sta PPUDATA + jmp @setupTopOfBox + +@setupMenuAnydas: + lda #$3B + sta PPUDATA + jsr @startLoop + lda #$3C + sta PPUDATA + +@setupTopOfBox: + lda tmp2 + sec + sbc #32 + sta tmp2 + lda tmp1 + sbc #0 + sta PPUADDR + lda tmp2 + sta PPUADDR + + + ldx #7 + lda gameMode + cmp #3 + beq @menuAnydasBoxLoop + +@gameAnydasBoxLoop: + lda topOfBoxGame,x + sta PPUDATA + dex + bpl @gameAnydasBoxLoop + rts + +@menuAnydasBoxLoop: + lda topOfBoxMenu,x + sta PPUDATA + dex + bpl @menuAnydasBoxLoop + rts + + @notanydas: - ldx #MODE_ANYDAS*6 - lda anydasFlag - bne @drawMode - ; practiseType * 6 lda practiseType asl sta generalCounter @@ -47,7 +105,7 @@ displayModeText: sta PPUADDR lda tmp2 sta PPUADDR - +@startLoop: ldy #6 @writeChar: lda modeText-6, x @@ -124,3 +182,7 @@ bottomOfBoxMenu: .byte $3F,$3E,$3E,$3E,$3E,$3E,$3E,$3D bottomOfBoxGame: .byte $77,$37,$37,$37,$37,$37,$37,$76 +topOfBoxMenu: + .byte $3A,$39,$39,$39,$39,$39,$39,$38 +topOfBoxGame: + .byte $75,$34,$34,$34,$34,$34,$34,$74 From dafb493a7c9b82ccaa56a968bf3c571a6215a019 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 01:21:04 +0000 Subject: [PATCH 53/79] half completed variables in sram --- src/boot.asm | 1 + src/gamemode/bootscreen.asm | 1 - src/gamemode/gametypemenu/linecap.asm | 235 -------------------------- src/highscores/util.asm | 46 +++-- src/io.asm | 2 +- src/nmi/render_mode_scroll.asm | 43 ----- src/ram.asm | 29 ++-- 7 files changed, 50 insertions(+), 307 deletions(-) delete mode 100644 src/gamemode/gametypemenu/linecap.asm delete mode 100644 src/nmi/render_mode_scroll.asm diff --git a/src/boot.asm b/src/boot.asm index 8e01d24f..1134dc36 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -52,6 +52,7 @@ beq @noSRAM jsr checkSavedInit jsr copyScoresFromSRAM + jsr copyVarsFromSRAM @noSRAM: .endif diff --git a/src/gamemode/bootscreen.asm b/src/gamemode/bootscreen.asm index 9d4fcdb3..5ce7594c 100644 --- a/src/gamemode/bootscreen.asm +++ b/src/gamemode/bootscreen.asm @@ -4,7 +4,6 @@ gameMode_bootScreen: ; boot ; reset cursors lda #$0 sta practiseType - sta menuSeedCursorIndex ; levelMenu stuff sta levelControlMode diff --git a/src/gamemode/gametypemenu/linecap.asm b/src/gamemode/gametypemenu/linecap.asm deleted file mode 100644 index e112f078..00000000 --- a/src/gamemode/gametypemenu/linecap.asm +++ /dev/null @@ -1,235 +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: - branchTo linecapCursorIndex, \ - linecapMenuControlsWhen, \ - linecapMenuControlsLinesLevel, \ - 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/highscores/util.asm b/src/highscores/util.asm index 63787033..1d21af6e 100644 --- a/src/highscores/util.asm +++ b/src/highscores/util.asm @@ -10,6 +10,17 @@ resetScores: @continue: rts + +resetMenuVars: + ldx #sramVariableLength -1 + lda #$0 +@loop: + sta menuVars,x + dex + bpl @loop + rts + + .if SAVE_HIGHSCORES detectSRAM: lda #$37 @@ -55,27 +66,42 @@ resetSavedScores: rts copyScoresFromSRAM: - ldx #$0 + ldx #highScoreLength * highScoreQuantity - 1 @copyLoop: - cpx #highScoreLength * highScoreQuantity - beq @continue lda SRAM_highscores,x sta highscores,x - inx - jmp @copyLoop + dex + bpl @copyLoop @continue: rts copyScoresToSRAM: - ldx #$0 + ldx #highScoreLength * highScoreQuantity - 1 @copyLoop: - cpx #highScoreLength * highScoreQuantity - beq @continue lda highscores,x sta SRAM_highscores,x - inx - jmp @copyLoop + dex + bpl @copyLoop @continue: rts +copyVarsFromSRAM: + ldx #sramVariableLength - 1 +@copyLoop: + lda SRAM_variables,x + sta menuVars,x + dex + bpl @copyLoop +@continue: + rts + +copyVarsToSRAM: + ldx #sramVariableLength - 1 +@copyLoop: + lda menuVars,x + sta SRAM_variables,x + dex + bpl @copyLoop +@continue: + rts .endif diff --git a/src/io.asm b/src/io.asm index 1e99e4da..431d1698 100644 --- a/src/io.asm +++ b/src/io.asm @@ -2,7 +2,7 @@ SRAM := $6000 ; 8kb SRAM_states := SRAM SRAM_hsMagic := SRAM+$A00 SRAM_highscores := SRAM_hsMagic+$4 - +SRAM_variables := $6100 PPUCTRL := $2000 PPUMASK := $2001 PPUSTATUS := $2002 diff --git a/src/nmi/render_mode_scroll.asm b/src/nmi/render_mode_scroll.asm deleted file mode 100644 index 13de6fc7..00000000 --- a/src/nmi/render_mode_scroll.asm +++ /dev/null @@ -1,43 +0,0 @@ -render_mode_scroll: - ; handle scroll - lda currentPpuCtrl - and #$FC - sta currentPpuCtrl - lda #0 - sta ppuScrollX - - jsr calc_menuScrollY - cmp menuScrollY - beq @endscroll - ; not equal - cmp menuScrollY - bcc @lessThan - - inc menuScrollY - - jmp @endscroll -@lessThan: - dec menuScrollY -@endscroll: - - lda menuScrollY - cmp #MENU_MAX_Y_SCROLL - bcc @uncapped - lda #MENU_MAX_Y_SCROLL - sta menuScrollY -@uncapped: - - sta ppuScrollY - rts - -calc_menuScrollY: - lda practiseType - cmp #MENU_TOP_MARGIN_SCROLL - bcs @underflow - lda #MENU_TOP_MARGIN_SCROLL+1 -@underflow: - sbc #MENU_TOP_MARGIN_SCROLL - asl - asl - asl - rts diff --git a/src/ram.asm b/src/ram.asm index 6b5d5ad2..80ea36e9 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -364,27 +364,32 @@ highScoreLength := highScoreNameLength + highScoreScoreLength + highScoreLinesLe initMagic: .res 5 ; $075B ; Initialized to a hard-coded number. When resetting, if not correct number then it knows this is a cold boot menuRAM: ; $760 -menuSeedCursorIndex: .res 1 -menuScrollY: .res 1 menuMoveThrottle: .res 1 menuThrottleTmp: .res 1 levelControlMode: .res 1 customLevel: .res 1 classicLevel: .res 1 heartsAndReady: .res 1 ; high nybble used for ready -linecapCursorIndex: .res 1 +practiseType: .res 1 + +; menu +activeMenu: .res 1 +activePage: .res 1 +activeRow: .res 1 +activeColumn: .res 1 +menuStackPtr: .res 1 + +menuVars: linecapWhen: .res 1 linecapHow: .res 1 linecapLevel: .res 1 linecapLines: .res 2 -menuVars: ; $76E paceModifier: .res 1 presetModifier: .res 1 typeBModifier: .res 1 floorModifier: .res 1 crunchLeftModifier: .res 1 crunchRightModifier: .res 1 -tapModifier: .res 1 transitionModifier: .res 1 marathonModifier: .res 1 tapqtyModifier: .res 1 @@ -403,7 +408,6 @@ disablePauseFlag: .res 1 darkModifier: .res 1 goofyFlag: .res 1 debugFlag: .res 1 -linecapFlag: .res 1 dasOnlyFlag: .res 1 qualFlag: .res 1 palFlag: .res 1 @@ -412,7 +416,6 @@ seedEnabled: .res 1 seededPieces: .res 1 ghostPieceFlag: .res 1 hardDropFlag: .res 1 -noEntryDelayFlag: .res 1 invisibleOptionFlag: .res 1 killX2Flag: .res 1 tapLeftModifier: .res 1 @@ -426,23 +429,15 @@ trtFlag: .res 1 dasMeterFlag: .res 1 noWallChargeFlag: .res 1 disableDasFlag: .res 1 +set_seed_input: .res 3 ; $0037 ; copied to set_seed during gameModeState_initGameState +sramVariableLength := * - menuVars .if KEYBOARD = 1 keyboardFlag: .res 1 .endif -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 ; change this to flag if you need it later - .include "gamemode/gametypemenu/menuram.asm" ; ... $7FF From 174df6127a8f0fbcfb6d75fb27eaf62469b911c7 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 01:21:11 +0000 Subject: [PATCH 54/79] update todo --- TODO.md | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO.md b/TODO.md index fd5671a7..bd4c7613 100644 --- a/TODO.md +++ b/TODO.md @@ -10,6 +10,7 @@ # Bugs * goofy foot toggle is difficult +* exiting tap/roll speed causes scroll glitch * lowstack & crunch do not work together * garbage + crunch or floor does not work well * lowstack line doesn't respond to vert mirror flag From 8815dbeeee77627a56344bdfaf0374c3b8f4b012 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 02:14:09 +0000 Subject: [PATCH 55/79] save settings in sram the logic should be combined with the high score logic wedged in for now --- TODO.md | 2 + src/boot.asm | 27 -------------- src/gamemode/gametypemenu/menu.asm | 1 + src/gamemode/levelmenu.asm | 2 + src/highscores/util.asm | 59 ++++++++++++++++++++---------- src/util/check_region.asm | 11 ++++++ src/util/modetext.asm | 5 +++ 7 files changed, 61 insertions(+), 46 deletions(-) diff --git a/TODO.md b/TODO.md index bd4c7613..18e96eb6 100644 --- a/TODO.md +++ b/TODO.md @@ -7,8 +7,10 @@ * option to default all * multiple scoreboards * clear scoreboard individually +* seed should work with drought mode (provided same modifier) # Bugs +* ghost piece displays during entry delay * goofy foot toggle is difficult * exiting tap/roll speed causes scroll glitch * lowstack & crunch do not work together diff --git a/src/boot.asm b/src/boot.asm index 1134dc36..fae9af68 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -17,33 +17,6 @@ jmp @continueWarmBootInit @coldBoot: - ; zero out config memory - lda #$0 - ldx #$A0 -@loop: - dex - sta menuRAM, x - ; cpx #0 ; dex sets z flag - bne @loop - - lda #$FF - sta paceModifier - sta floorModifier - - lda #NTSC_DAS - sta dasModifier - lda #NTSC_ARR - sta arrModifier - - lda #MODE_TETRIS - sta practiseType - - lda #INITIAL_LINECAP_LEVEL - sta linecapLevel - lda #INITIAL_LINECAP_LINES_LO - sta linecapLines+1 - lda #INITIAL_LINECAP_LINES_HI - sta linecapLines jsr resetScores diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index cd364c76..f9ecef57 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -616,6 +616,7 @@ addInputs: sta (udPointer,x) @sfx: inc soundEffectSlot1Init + jsr copyVarsToSram @ret: rts diff --git a/src/gamemode/levelmenu.asm b/src/gamemode/levelmenu.asm index 2eec95c0..4d8dfa97 100644 --- a/src/gamemode/levelmenu.asm +++ b/src/gamemode/levelmenu.asm @@ -94,10 +94,12 @@ gameMode_levelMenu_processPlayer1Navigation: lda #0 sta levelControlMode jsr resetScores + jsr resetMenuVars .if SAVE_HIGHSCORES jsr detectSRAM beq @notResettingSavedScores jsr resetSavedScores + jsr resetSavedVars @notResettingSavedScores: .endif jsr updateAudioWaitForNmiAndResetOamStaging diff --git a/src/highscores/util.asm b/src/highscores/util.asm index 1d21af6e..9ccdbca6 100644 --- a/src/highscores/util.asm +++ b/src/highscores/util.asm @@ -1,12 +1,10 @@ resetScores: - ldx #$0 + ldx #highScoreLength * highScoreQuantity - 1 lda #$0 @initHighScoreTable: - cpx #highScoreLength * highScoreQuantity - beq @continue sta highscores,x - inx - jmp @initHighScoreTable + dex + bpl @initHighScoreTable @continue: rts @@ -18,6 +16,26 @@ resetMenuVars: sta menuVars,x dex bpl @loop + + lda #$FF + sta paceModifier + sta floorModifier + + lda #NTSC_DAS + sta dasModifier + lda #NTSC_ARR + sta arrModifier + + lda #MODE_TETRIS + sta practiseType + + lda #INITIAL_LINECAP_LEVEL + sta linecapLevel + lda #INITIAL_LINECAP_LINES_LO + sta linecapLines+1 + lda #INITIAL_LINECAP_LINES_HI + sta linecapLines + rts @@ -54,17 +72,29 @@ resetSavedScores: lda #$D2 sta SRAM_hsMagic+3 - ldx #$0 + ldx #highScoreLength * highScoreQuantity - 1 lda #$0 @copyLoop: - cpx #highScoreLength * highScoreQuantity - beq @continue sta SRAM_highscores,x - inx - jmp @copyLoop + dex + bpl @copyLoop + +; copy variables + + +resetSavedVars: + jsr resetMenuVars +copyVarsToSram: + ldx #sramVariableLength - 1 +@varsLoop: + lda menuVars,x + sta SRAM_variables,x + dex + bpl @varsLoop @continue: rts + copyScoresFromSRAM: ldx #highScoreLength * highScoreQuantity - 1 @copyLoop: @@ -95,13 +125,4 @@ copyVarsFromSRAM: @continue: rts -copyVarsToSRAM: - ldx #sramVariableLength - 1 -@copyLoop: - lda menuVars,x - sta SRAM_variables,x - dex - bpl @copyLoop -@continue: - rts .endif diff --git a/src/util/check_region.asm b/src/util/check_region.asm index 04454bc4..1b47813e 100644 --- a/src/util/check_region.asm +++ b/src/util/check_region.asm @@ -40,6 +40,17 @@ checkRegion: beq @ntsc lda #1 sta palFlag + + ; check to see if custom settings are applied + ; leave alone if not vanilla + lda dasModifier + cmp #NTSC_DAS + bne @ntsc + lda arrModifier + cmp #NTSC_ARR + bne @ntsc + +; vanilla - ok to change lda #PAL_DAS sta dasModifier lda #PAL_ARR diff --git a/src/util/modetext.asm b/src/util/modetext.asm index 1dacfab2..0269ecc4 100644 --- a/src/util/modetext.asm +++ b/src/util/modetext.asm @@ -45,6 +45,11 @@ displayModeText: lda gameMode cmp #3 beq @setupMenuAnydas + lda gameModeState + beq @setupGameAnydas + rts ; skip when in high score entry screen + +@setupGameAnydas: lda #$35 sta PPUDATA jsr @startLoop From 77f3b7962c72d9ca75965d8cde527d4087ca47e2 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 12:47:05 +0000 Subject: [PATCH 56/79] properly restore tetriminoY --- TODO.md | 1 - src/sprites/piece.asm | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/TODO.md b/TODO.md index 18e96eb6..c93cf1b1 100644 --- a/TODO.md +++ b/TODO.md @@ -10,7 +10,6 @@ * seed should work with drought mode (provided same modifier) # Bugs -* ghost piece displays during entry delay * goofy foot toggle is difficult * exiting tap/roll speed causes scroll glitch * lowstack & crunch do not work together diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index 51d97772..fddffe8e 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -13,11 +13,11 @@ stageSpriteForCurrentPiece: rts ghostPiece: - lda playState - cmp #3 - bpl @noGhost lda tetriminoY sta tmp3 + lda playState + cmp #2 + bpl @noGhost @loop: inc tetriminoY jsr isPositionValid @@ -35,8 +35,8 @@ ghostPiece: ; no ghost piece during entry delay lda playState - cmp #1 - beq @ghost + cmp #2 + bpl @ghost cmp #8 bne @noGhost From 05ef06e4540f691e3406908dc14bcec6dcfb92ca Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 12:54:04 +0000 Subject: [PATCH 57/79] restore no line clear for tap quantity --- src/gamemode/gametypemenu/menudata.js | 39 ++++++++++++++++----------- src/playstate/completedrows.asm | 5 +--- src/ram.asm | 1 + 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index 9ef124a8..d3da31cb 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -54,8 +54,18 @@ const keyboardFlag = ["TYPE_BOOL", "keyboard"]; const qualFlag = ["TYPE_BOOL", "qual", "qualFlag"]; const floorModifier = ["TYPE_FF_OFF", "floor", 16, "floorModifier"]; -const crunchLeftModifier = ["TYPE_NUMBER", "crunch left", 4, "crunchLeftModifier"]; -const crunchRightModifier = ["TYPE_NUMBER", "crunch right", 4, "crunchRightModifier"]; +const crunchLeftModifier = [ + "TYPE_NUMBER", + "crunch left", + 4, + "crunchLeftModifier", +]; +const crunchRightModifier = [ + "TYPE_NUMBER", + "crunch right", + 4, + "crunchRightModifier", +]; const invisibleFlag = ["TYPE_BOOL", "invisible", "invisibleOptionFlag"]; const ghostPiece = ["TYPE_BOOL", "ghost", "ghostPieceFlag"]; const hardDrop = ["TYPE_BOOL", "hardDrop", "hardDropFlag"]; @@ -66,18 +76,8 @@ const vertMirror = ["TYPE_BOOL", "mirror vert", "mirrorVertFlag"]; const presetModifier = ["TYPE_NUMBER", "preset", 8, "presetModifier"]; const typeBModifier = ["TYPE_NUMBER", "height", 9, "typeBModifier"]; const checkerModifier = ["TYPE_NUMBER", "height", 9, "checkerModifier"]; -const quickTapLeftModifier = [ - "TYPE_NUMBER", - "left", - 20, - "tapLeftModifier", -]; -const quickTapRightModifier = [ - "TYPE_NUMBER", - "right", - 20, - "tapRightModifier", -]; +const quickTapLeftModifier = ["TYPE_NUMBER", "left", 20, "tapLeftModifier"]; +const quickTapRightModifier = ["TYPE_NUMBER", "right", 20, "tapRightModifier"]; const transitionModifier = [ "TYPE_NUMBER", "modifier", @@ -86,6 +86,11 @@ const transitionModifier = [ ]; const marathonModifier = ["TYPE_NUMBER", "modifier", 5, "marathonModifier"]; const tapqtyModifier = ["TYPE_NUMBER", "height", 16, "tapqtyModifier"]; +const noLineClearDelayFlag = [ + "TYPE_BOOL", + "no line clear", + "noLineClearDelayFlag", +]; const garbageModifier = ["TYPE_NUMBER", "modifier", 5, "garbageModifier"]; const droughtModifier = ["TYPE_NUMBER", "modifier", 20, "droughtModifier"]; const lowStackRowModifier = [ @@ -200,7 +205,11 @@ const mainMenu = { quickTapRightModifier, ...shared, ], - "tap quantity[mode=tapqty]": [tapqtyModifier, ...shared], + "tap quantity[mode=tapqty]": [ + tapqtyModifier, + noLineClearDelayFlag, + ...shared, + ], "transition[mode=transition]": [ transitionModifier, goToTournament, diff --git a/src/playstate/completedrows.asm b/src/playstate/completedrows.asm index e0ac20ed..6e7775c7 100644 --- a/src/playstate/completedrows.asm +++ b/src/playstate/completedrows.asm @@ -122,14 +122,11 @@ playState_checkForCompletedRows: cmp #MODE_TAPQTY bne @tapQtyEnd lda completedLines - ; cmp #0 ; lda sets z flag beq @tapQtyEnd ; mark as complete lda tqtyNext sta tqtyCurrent - ; handle no burns - lda tapqtyModifier - and #$F0 + lda noLineClearDelayFlag beq @tapQtyEnd lda #0 sta vramRow diff --git a/src/ram.asm b/src/ram.asm index 80ea36e9..a3d51cc9 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -429,6 +429,7 @@ trtFlag: .res 1 dasMeterFlag: .res 1 noWallChargeFlag: .res 1 disableDasFlag: .res 1 +noLineClearDelayFlag: .res 1 set_seed_input: .res 3 ; $0037 ; copied to set_seed during gameModeState_initGameState sramVariableLength := * - menuVars From 19d6201468fc3327c159a94996fada9c8f382fe1 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 13:25:07 +0000 Subject: [PATCH 58/79] seed affects drought mode --- src/playstate/spawnnext.asm | 16 ++++++++++++---- src/seeds.asm | 2 -- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/playstate/spawnnext.asm b/src/playstate/spawnnext.asm index cb0855ee..7050e80a 100644 --- a/src/playstate/spawnnext.asm +++ b/src/playstate/spawnnext.asm @@ -97,8 +97,7 @@ L9934: tax lda spawnTable,x useNewSpawnID: sta spawnID - jsr pickTetriminoPost - rts + jmp pickTetriminoPost pickTetriminoPre: lda practiseType @@ -190,7 +189,7 @@ pickTetriminoSeed: lda spawnTable,x @useNewSpawnID: sta spawnID - rts + jmp pickTetriminoPost setSeedNextRNG: ldx #set_seed @@ -237,10 +236,15 @@ pickTetriminoPost: rts pickTetriminoDrought: + ldx #rng_seed+1 + lda seedEnabled + beq @notSeeded + ldx #set_seed+1 +@notSeeded: lda spawnID ; restore A cmp #$12 bne @droughtDone - lda rng_seed+1 + lda $00,x and #$F adc #1 ; always adds 1 so code continues as normal if droughtModifier is 0 cmp droughtModifier @@ -249,4 +253,8 @@ pickTetriminoDrought: @droughtDone: rts @pickRando: + lda seedEnabled + beq @vanillaRng + jmp pickTetriminoSeed +@vanillaRng: jmp pickRandomTetrimino diff --git a/src/seeds.asm b/src/seeds.asm index 2309be98..e5574ab3 100644 --- a/src/seeds.asm +++ b/src/seeds.asm @@ -10,8 +10,6 @@ checkIfSeeded: beq @noSeed cmp #MODE_PRESETS beq @noSeed - cmp #MODE_DROUGHT - beq @noSeed inc seededPieces @noSeed: rts From 86ff1e606a2199382c6562a237360c21293fd343 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 13:36:07 +0000 Subject: [PATCH 59/79] enabled seed affects checkerboard --- src/modes/initchecker.asm | 6 ++++++ src/seeds.asm | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/modes/initchecker.asm b/src/modes/initchecker.asm index 15d9752b..26eb4054 100644 --- a/src/modes/initchecker.asm +++ b/src/modes/initchecker.asm @@ -10,7 +10,13 @@ CHECKERBOARD_FLIP := CHECKERBOARD_TILE ^ EMPTY_TILE bne @notZero ldx #$BE @notZero: + lda seededPieces + beq @random + lda set_seed_input+1 + jmp @branch +@random: lda frameCounter +@branch: and #1 beq @checkerStartA lda #CHECKERBOARD_TILE diff --git a/src/seeds.asm b/src/seeds.asm index e5574ab3..58177308 100644 --- a/src/seeds.asm +++ b/src/seeds.asm @@ -1,6 +1,8 @@ checkIfSeeded: lda #$00 sta seededPieces + lda seedEnabled + beq @noSeed lda practiseType cmp #MODE_TSPINS beq @noSeed From 4bb7d84257bd9db5bc05292d06de233d31a7b288 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 14:54:21 +0000 Subject: [PATCH 60/79] seeded b type --- TODO.md | 3 --- src/gamemode/gametypemenu/menu.js | 6 ++++-- src/gamemode/gametypemenu/menudata.js | 17 +++++++++++++++- src/gamemodestate/initstate.asm | 29 +++++++++++++++++++++++---- src/nmi/nmi.asm | 2 ++ src/ram.asm | 4 +++- src/util/modetext.asm | 18 +++++++++++++++++ 7 files changed, 68 insertions(+), 11 deletions(-) diff --git a/TODO.md b/TODO.md index c93cf1b1..f384108d 100644 --- a/TODO.md +++ b/TODO.md @@ -3,11 +3,8 @@ * 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 -* seed should work with drought mode (provided same modifier) # Bugs * goofy foot toggle is difficult diff --git a/src/gamemode/gametypemenu/menu.js b/src/gamemode/gametypemenu/menu.js index 943c2ecd..0858ad38 100644 --- a/src/gamemode/gametypemenu/menu.js +++ b/src/gamemode/gametypemenu/menu.js @@ -1,7 +1,6 @@ const { mainMenu, extraSpriteStrings } = require("./menudata"); const { writeFileSync } = require("fs"); - MAX_LENGTH_NAME = 14; MAX_LENGTH_VALUE = 8; DEBUG = false; @@ -207,7 +206,10 @@ function getMemoryLabel(string, bytes) { processPageSet = (pages, name) => { DEBUG && name && console.log(`submenu ${name}`); DEBUG && !name && console.log(`main menu`); - if (name) menuEnums.push(`SUBMENU_${cleanWord(name).toUpperCase()}`); + if (name) { + const enunName = `SUBMENU_${cleanWord(name).toUpperCase()}`; + if (!menuEnums.includes(enunName)) menuEnums.push(enunName); + } startPageByMenu.push( `${getByteLine(getHexByte(pageIndex))} ; ${name ? name : "main menu"}`, ); diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index d3da31cb..b1d6dc0b 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -75,6 +75,8 @@ const vertMirror = ["TYPE_BOOL", "mirror vert", "mirrorVertFlag"]; const presetModifier = ["TYPE_NUMBER", "preset", 8, "presetModifier"]; const typeBModifier = ["TYPE_NUMBER", "height", 9, "typeBModifier"]; +const typeBSeed = ["TYPE_HEX", "seed", 4, "b_seed_input"]; +const typeBSeedFlag = ["TYPE_BOOL", "seed enabled", "typeBSeedFlag"]; const checkerModifier = ["TYPE_NUMBER", "height", 9, "checkerModifier"]; const quickTapLeftModifier = ["TYPE_NUMBER", "left", 20, "tapLeftModifier"]; const quickTapRightModifier = ["TYPE_NUMBER", "right", 20, "tapRightModifier"]; @@ -160,6 +162,7 @@ const displaySubMenu = { ], }; + const moreSubMenu = { "more options[mode=default]": [ crashModifier, @@ -194,12 +197,24 @@ const goToMore = ["TYPE_SUBMENU", "more", moreSubMenu]; const shared = [goToMods, goToInfo, goToDisplay, goToDas, goToMore]; +const optionsSubMenu = { + "options[mode=default]": [ + ...shared, + ], +}; +const goToShared = ["TYPE_SUBMENU", "options", optionsSubMenu]; const mainMenu = { "play tetris[mode=tetris]": [goToTournament, ...shared], "t-spins[mode=tspins]": [...shared], "setups[mode=presets]": [presetModifier, ...shared], "stacking[mode=stacking]": [goToTournament, ...shared], - "b-type[mode=typeb]": [typeBModifier, ...shared], + "b-type[mode=typeb]": [ + typeBModifier, + typeBSeed, + typeBSeedFlag, + goToTournament, + goToShared, + ], "(quick)tap[mode=tap]": [ quickTapLeftModifier, quickTapRightModifier, diff --git a/src/gamemodestate/initstate.asm b/src/gamemodestate/initstate.asm index 8643b94a..aa4c899a 100644 --- a/src/gamemodestate/initstate.asm +++ b/src/gamemodestate/initstate.asm @@ -247,6 +247,27 @@ presetScoreFromBCD: rts initPlayfieldForTypeB: +; decide which seed to use + lda typeBSeedFlag + beq @notSeeded + +; seeded + lda b_seed_input + sta b_seed + lda b_seed_input+1 + sta b_seed+1 + jmp @checkModifier + +@notSeeded: + lda rng_seed + sta b_seed + sta b_seed_input + lda rng_seed+1 + sta b_seed+1 + sta b_seed_input+1 + + +@checkModifier: lda typeBModifier cmp #$6 bmi @normalStart @@ -268,9 +289,9 @@ L87E7: lda generalCounter sta vramRow lda #$09 sta generalCounter3 -L87FC: ldx #rng_seed +L87FC: ldx #b_seed jsr generateNextPseudorandomNumber - lda rng_seed + lda b_seed and #$07 tay lda rngTable,y @@ -287,9 +308,9 @@ L87FC: ldx #rng_seed dec generalCounter3 jmp L87FC -L8824: ldx #rng_seed +L8824: ldx #b_seed jsr generateNextPseudorandomNumber - lda rng_seed + lda b_seed and #$0F cmp #$0A bpl L8824 diff --git a/src/nmi/nmi.asm b/src/nmi/nmi.asm index 57389382..bb6f8102 100644 --- a/src/nmi/nmi.asm +++ b/src/nmi/nmi.asm @@ -28,6 +28,8 @@ renderComplete: ldx #rng_seed jsr generateNextPseudorandomNumber + ldx #b_seed + jsr generateNextPseudorandomNumber jsr pollControllerButtons diff --git a/src/ram.asm b/src/ram.asm index a3d51cc9..ba48c136 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -13,7 +13,7 @@ nmiReturnAddr: .res 1 ; $0010 ; used for crash crashState: .res 1 ; $0011 ; used for crash cycleCount: .res 2 ; $0012 ; 2 bytes ; used for crash oneThirdPRNG: .res 1 ; $0014 ; used for crash - .res $2 +b_seed: .res 2 ; loaded with rng_seed unless seeded rng_seed: .res 2 ; $0017 spawnID: .res 1 ; $0019 @@ -431,6 +431,8 @@ noWallChargeFlag: .res 1 disableDasFlag: .res 1 noLineClearDelayFlag: .res 1 set_seed_input: .res 3 ; $0037 ; copied to set_seed during gameModeState_initGameState +b_seed_input: .res 2 +typeBSeedFlag: .res 1 sramVariableLength := * - menuVars diff --git a/src/util/modetext.asm b/src/util/modetext.asm index 0269ecc4..9f5a30f2 100644 --- a/src/util/modetext.asm +++ b/src/util/modetext.asm @@ -118,6 +118,24 @@ displayModeText: inx dey bne @writeChar + +; cover TYPE with seed if seeded b type + lda practiseType + cmp #MODE_TYPEB + bne @ret + lda typeBSeedFlag + beq @ret + lda tmp1 + sta PPUADDR + lda tmp2 + clc + adc #2 + sta PPUADDR + lda b_seed_input + jsr twoDigsToPPU + lda b_seed_input+1 + jsr twoDigsToPPU +@ret: rts patchSeed: From 10ce1122db417cafb281680cf8b3431dc68a5819 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 15:48:44 +0000 Subject: [PATCH 61/79] fix speedtest exit glitch --- TODO.md | 1 - src/gamemode/speedtest.asm | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index f384108d..d49a2de1 100644 --- a/TODO.md +++ b/TODO.md @@ -8,7 +8,6 @@ # Bugs * goofy foot toggle is difficult -* exiting tap/roll speed causes scroll glitch * lowstack & crunch do not work together * garbage + crunch or floor does not work well * lowstack line doesn't respond to vert mirror flag diff --git a/src/gamemode/speedtest.asm b/src/gamemode/speedtest.asm index 2dc2d143..b7bceda4 100644 --- a/src/gamemode/speedtest.asm +++ b/src/gamemode/speedtest.asm @@ -48,6 +48,11 @@ gameMode_speedTest: jmp @loop @back: + lda #00 + sta renderMode + lda currentPpuMask + and #$E7 + sta PPUMASK lda #$02 sta soundEffectSlot1Init sta gameMode From b16c41e51f49520a49f26001f33aa0f0324d665e Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 15:49:04 +0000 Subject: [PATCH 62/79] custom subroutine, use for goofy toggle --- src/gamemode/gametypemenu/menu.asm | 42 ++++++++++++++++++++++++++- src/gamemode/gametypemenu/menu.js | 8 +++++ src/gamemode/gametypemenu/menudata.js | 6 ++-- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index f9ecef57..aa144df7 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -21,6 +21,12 @@ MENU_STRIPE_WIDTH = 20 MENU_ROWS = 9 MENU_STACK = $DF ; $01C8 - $01DF intended range +.enum +GOOFY_TOGGLE +RESET_DEFAULTS +CLEAR_SCOREBOARD +.endenum + menuDataStart: .include "menudata.asm" .out .sprintf("Menu data: %d", *-menuDataStart) @@ -35,7 +41,7 @@ VALUE_MASK = %00011111 TYPE_MASK = %11100000 ; tttnnnnn -TYPE_UNUSED = %00000000 +TYPE_CUSTOM = %00000000 TYPE_NUMBER = %00100000 ; n = limit TYPE_CHOICES = %01000000 ; n = wordlist index TYPE_FF_OFF = %01100000 ; n = limit @@ -547,8 +553,42 @@ checkIfGameStartOrSubmenu: cmp #TYPE_SUBMENU beq goToSubMenu + + cmp #TYPE_CUSTOM + beq @goToCustom + +@checkPageMode: jmp checkPageMode + +@goToCustom: + lda newlyPressedButtons_player1 + and #BUTTON_A+BUTTON_START + beq customClearScoreboard + branchTo unpackedItemValue, \ + customToggleGoofy, \ + customResetDefaults, \ + customClearScoreboard + +customToggleGoofy: + lda goofyFlag + eor #1 + sta goofyFlag + lda heldButtons_player1 + asl + and #$AA + sta tmp3 + lda heldButtons_player1 + and #$AA + lsr + ora tmp3 + sta heldButtons_player1 +customResetDefaults: +customClearScoreboard: + rts + + + goToSubMenu: lda unpackedItemValue jmp enterSubMenu diff --git a/src/gamemode/gametypemenu/menu.js b/src/gamemode/gametypemenu/menu.js index 0858ad38..19a0a683 100644 --- a/src/gamemode/gametypemenu/menu.js +++ b/src/gamemode/gametypemenu/menu.js @@ -14,6 +14,7 @@ labelMap = { TYPE_MODE_ONLY: getOutputLines, TYPE_SUBMENU: typeSubMenu, TYPE_BOOL: typeBool, + TYPE_CUSTOM: typeCustom, }; addedStrings = []; @@ -195,6 +196,13 @@ function typeSubMenu(label, string) { `${string}`, ); } +function typeCustom(label, string, subroutine, memoryLabel) { + return getOutputLines( + `${label} | ${subroutine}`, + `${string}`, + memoryLabel ? memoryLabel : 1, + ); +} function getMemoryLabel(string, bytes) { if (isNaN(bytes)) return bytes; // if label is specified use that instead diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index b1d6dc0b..b3da1c9a 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -47,7 +47,7 @@ const crashModifier = [ ]; const strictCrashFlag = ["TYPE_BOOL", "strict crash", "strictFlag"]; const disablePause = ["TYPE_BOOL", "disable pause", "disablePauseFlag"]; -const goofyFlag = ["TYPE_BOOL", "goofy foot", "goofyFlag"]; +const goofyFlag = ["TYPE_CUSTOM", "toggle goofy", "GOOFY_TOGGLE", "goofyFlag"]; const debugFlag = ["TYPE_BOOL", "block tool", "debugFlag"]; const palFlag = ["TYPE_BOOL", "pal mode", "palFlag"]; const keyboardFlag = ["TYPE_BOOL", "keyboard"]; @@ -168,11 +168,11 @@ const moreSubMenu = { crashModifier, strictCrashFlag, disablePause, - goofyFlag, debugFlag, palFlag, qualFlag, - keyboardFlag, + // keyboardFlag, + goofyFlag, ], }; From 15548a08f48322e80157a2f714f6d052f81207d7 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 15:53:53 +0000 Subject: [PATCH 63/79] update todo --- TODO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index d49a2de1..752b5c36 100644 --- a/TODO.md +++ b/TODO.md @@ -5,9 +5,9 @@ * add animation to cursor arrows * multiple scoreboards * clear scoreboard individually +* decimal display # Bugs -* goofy foot toggle is difficult * lowstack & crunch do not work together * garbage + crunch or floor does not work well * lowstack line doesn't respond to vert mirror flag From 94dfa90ff8cdef3f43aa5f7d684e9f2e9e70f467 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 18:05:45 +0000 Subject: [PATCH 64/79] wedge in vars reset into qual mode --- src/gamemode/bootscreen.asm | 2 ++ src/gamemode/waitscreen.asm | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/gamemode/bootscreen.asm b/src/gamemode/bootscreen.asm index 5ce7594c..c76079ae 100644 --- a/src/gamemode/bootscreen.asm +++ b/src/gamemode/bootscreen.asm @@ -32,6 +32,8 @@ gameMode_bootScreen: ; boot sta gameMode lda #1 sta qualFlag + jsr resetMenuVars + jsr resetSavedVars jmp gameMode_waitScreen @nonQualBoot: diff --git a/src/gamemode/waitscreen.asm b/src/gamemode/waitscreen.asm index ae95b51d..2cfe78f1 100644 --- a/src/gamemode/waitscreen.asm +++ b/src/gamemode/waitscreen.asm @@ -63,8 +63,12 @@ waitScreenLoad: lda #1 sta byteSpriteLen jsr byteSprite + lda newlyPressedButtons_player1 + and #BUTTON_START + bne @exitLoop lda sleepCounter bne @loop +@exitLoop: inc screenStage jmp @justLegal From 34dcb87332d587c7f1e274e0b746920791bcae70 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 18:16:21 +0000 Subject: [PATCH 65/79] zero out menu memory at bootup --- src/boot.asm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/boot.asm b/src/boot.asm index fae9af68..3e4376d2 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -17,6 +17,14 @@ jmp @continueWarmBootInit @coldBoot: + ; zero out config memory + lda #$0 + ldx #$A0 +@loop: + dex + sta menuRAM, x + ; cpx #0 ; dex sets z flag + bne @loop jsr resetScores From 9526bd56f61b9ae17a4e2efa03a973bed6afc9a6 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 18:40:49 +0000 Subject: [PATCH 66/79] nullify r/l inputs for goofy toggle --- src/gamemode/gametypemenu/menu.asm | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index aa144df7..de9d65b7 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -135,6 +135,18 @@ gameTypeLoop: ; todo: write down which vars are used by which func jsr collectControllerInput jsr setScratch + + ldx activeItem + lda itemTypes,x + cmp #TYPE_CUSTOM | GOOFY_TOGGLE + bne @notGoofyToggle + + lda #0 + sta lrAdjust + + + +@notGoofyToggle: jsr addInputs jsr respondToInput jsr stageCursor From c11764942ec068fb1c646bc52a07bf49e01c78e5 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 19:01:40 +0000 Subject: [PATCH 67/79] don't patch anydas text with b seed --- src/util/modetext.asm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util/modetext.asm b/src/util/modetext.asm index 9f5a30f2..fc7cc55e 100644 --- a/src/util/modetext.asm +++ b/src/util/modetext.asm @@ -119,6 +119,8 @@ displayModeText: dey bne @writeChar + cpx #MODE_ANYDAS*6+6 + beq @ret ; cover TYPE with seed if seeded b type lda practiseType cmp #MODE_TYPEB From c1c35da09162d5df468f142fe63e24dce8b55f74 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Sun, 14 Jun 2026 19:15:36 +0000 Subject: [PATCH 68/79] move aligned table to start of rom --- src/main.asm | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main.asm b/src/main.asm index 0656e880..148dbf46 100644 --- a/src/main.asm +++ b/src/main.asm @@ -16,7 +16,9 @@ .linecont .segment "PRG_chunk1": absolute - +.align $100 +; these tables benefit from page alignment +.include "data/mult_orient.asm" ; region code at start of page to keep cycle count consistent .include "util/check_region.asm" .include "audio.asm" @@ -90,10 +92,6 @@ mainLoop: .include "seeds.asm" .include "modes/dasmeter.asm" -.align $100 -; these tables benefit from page alignment -.include "data/mult_orient.asm" - .segment "PRG_chunk3": absolute .include "reset.asm" From a80551b31915a1f420aa1ca20de3abc2d500a284 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 15 Jun 2026 04:06:56 +0000 Subject: [PATCH 69/79] fix ghost again and save some bytes --- TODO.md | 1 + src/sprites/piece.asm | 10 ++-------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/TODO.md b/TODO.md index 752b5c36..e74183db 100644 --- a/TODO.md +++ b/TODO.md @@ -6,6 +6,7 @@ * multiple scoreboards * clear scoreboard individually * decimal display +* height 6-8 logic can be rearranged to be closer to vanilla # Bugs * lowstack & crunch do not work together diff --git a/src/sprites/piece.asm b/src/sprites/piece.asm index fddffe8e..c5b2e0be 100644 --- a/src/sprites/piece.asm +++ b/src/sprites/piece.asm @@ -15,9 +15,6 @@ stageSpriteForCurrentPiece: ghostPiece: lda tetriminoY sta tmp3 - lda playState - cmp #2 - bpl @noGhost @loop: inc tetriminoY jsr isPositionValid @@ -29,17 +26,14 @@ ghostPiece: ; check if equal to current position cmp tmp3 beq @noGhost - lda ghostPieceFlag beq @noGhost - ; no ghost piece during entry delay lda playState - cmp #2 - bpl @ghost + cmp #1 + beq @ghost cmp #8 bne @noGhost - @ghost: lda frameCounter and #1 From 4836652b50181b34d66d62d8317a54a49e4181d0 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 15 Jun 2026 18:16:19 +0000 Subject: [PATCH 70/79] use latest commit for magic numbers --- .gitignore | 1 + build.js | 22 ++++++++++++++++++++++ src/constants.asm | 2 ++ src/highscores/util.asm | 16 ++++++++-------- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 07ad212d..cef22c10 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ tetris.lst tetris.lbl tetris.map tetris.dbg +src/magicnumbers.asm release/* target .env diff --git a/build.js b/build.js index 8c61c0ba..02cf27eb 100644 --- a/build.js +++ b/build.js @@ -1,6 +1,7 @@ const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); +const { writeFileSync } = require("fs"); console.log('TetrisGYM buildscript'); console.time('build'); @@ -166,6 +167,27 @@ const flags = compileFlags.join(' '); console.time('assemble'); +// embed latest commit id as magic number +const gitCommit = spawnSync("git", ["log", "-1", "--pretty='%H'"]) + .stdout.toString() + .trim() + .slice(1, 9) + .toUpperCase(); + +const magicNumbers = []; +for (let i = 0; i < 4; i++) { + let b = gitCommit.slice(i * 2, i * 2 + 2); + magicNumbers.push(`HIGH_SCORE_MAGIC${i} = $${b}`); +} + +const magicNumbersAsm = `; generated by build.js + +${magicNumbers.join("\n")} +`; + +writeFileSync("src/magicnumbers.asm", magicNumbersAsm); + + exec(`${ca65bin} ${flags} -g src/header.asm -o header.o`); exec(`${ca65bin} ${flags} -l tetris.lst -g src/main.asm -o main.o`); diff --git a/src/constants.asm b/src/constants.asm index 7c0fffac..acccd83f 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -1,3 +1,5 @@ +.include "magicnumbers.asm" + .ifndef INES_MAPPER ; is set via ca65 flags INES_MAPPER := 1000 ; 0 (NROM), 1 (MMC1), 3 (CNROM), 4 (MMC3), 5 (MMC5), and 1000 (autodetect 1/3) .endif diff --git a/src/highscores/util.asm b/src/highscores/util.asm index 9ccdbca6..a677b43e 100644 --- a/src/highscores/util.asm +++ b/src/highscores/util.asm @@ -41,15 +41,15 @@ resetMenuVars: .if SAVE_HIGHSCORES detectSRAM: - lda #$37 + lda #HIGH_SCORE_MAGIC0 sta SRAM_hsMagic - lda #$64 + lda #HIGH_SCORE_MAGIC1 sta SRAM_hsMagic+1 lda SRAM_hsMagic - cmp #$37 + cmp #HIGH_SCORE_MAGIC0 bne @noSRAM lda SRAM_hsMagic+1 - cmp #$64 + cmp #HIGH_SCORE_MAGIC1 bne @noSRAM lda #1 rts @@ -59,17 +59,17 @@ detectSRAM: checkSavedInit: lda SRAM_hsMagic+2 - cmp #$4B + cmp #HIGH_SCORE_MAGIC2 bne resetSavedScores lda SRAM_hsMagic+3 - cmp #$D2 + cmp #HIGH_SCORE_MAGIC3 bne resetSavedScores rts resetSavedScores: - lda #$4B + lda #HIGH_SCORE_MAGIC2 sta SRAM_hsMagic+2 - lda #$D2 + lda #HIGH_SCORE_MAGIC3 sta SRAM_hsMagic+3 ldx #highScoreLength * highScoreQuantity - 1 From a76c68675d51543b7cc589ff7a4bfe7cd3c203d7 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 15 Jun 2026 18:29:34 +0000 Subject: [PATCH 71/79] better js --- build.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/build.js b/build.js index 02cf27eb..ade4d66d 100644 --- a/build.js +++ b/build.js @@ -168,17 +168,14 @@ const flags = compileFlags.join(' '); console.time('assemble'); // embed latest commit id as magic number -const gitCommit = spawnSync("git", ["log", "-1", "--pretty='%H'"]) +const magicNumbers = []; +spawnSync("git", ["log", "-1", "--pretty='%H'"]) .stdout.toString() .trim() .slice(1, 9) - .toUpperCase(); - -const magicNumbers = []; -for (let i = 0; i < 4; i++) { - let b = gitCommit.slice(i * 2, i * 2 + 2); - magicNumbers.push(`HIGH_SCORE_MAGIC${i} = $${b}`); -} + .toUpperCase() + .match(/../g) + .forEach((b, i) => magicNumbers.push(`HIGH_SCORE_MAGIC${i} = $${b}`)); const magicNumbersAsm = `; generated by build.js From 5653559932670a36bf3f06e6052905a152630356 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 15 Jun 2026 18:51:45 +0000 Subject: [PATCH 72/79] even better --- build.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build.js b/build.js index ade4d66d..72a3f714 100644 --- a/build.js +++ b/build.js @@ -168,14 +168,13 @@ const flags = compileFlags.join(' '); console.time('assemble'); // embed latest commit id as magic number -const magicNumbers = []; -spawnSync("git", ["log", "-1", "--pretty='%H'"]) +const magicNumbers = spawnSync("git", ["log", "-1", "--pretty='%H'"]) .stdout.toString() .trim() .slice(1, 9) .toUpperCase() .match(/../g) - .forEach((b, i) => magicNumbers.push(`HIGH_SCORE_MAGIC${i} = $${b}`)); + .map((b, i) => `HIGH_SCORE_MAGIC${i} = $${b}`); const magicNumbersAsm = `; generated by build.js From b92c133511de8ed25717a444e1e875bffcf4d04a Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 15 Jun 2026 23:09:13 +0000 Subject: [PATCH 73/79] arr can be greater than das, das meter adjustments --- src/gamemode/gametypemenu/menudata.js | 4 +- src/modes/dasmeter.asm | 54 +++++++++++++++++++++------ src/playstate/active.asm | 4 +- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index b3da1c9a..e603985a 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -109,8 +109,8 @@ const noWallChargeFlag = [ "noWallChargeFlag", ]; const disableDasFlag = ["TYPE_CHOICES", "das", ["on", "off"], "disableDasFlag"]; -const anydasDas = ["TYPE_NUMBER", "delay", 32, "dasModifier"]; -const anydasArr = ["TYPE_NUMBER", "arrrr", 32, "arrModifier"]; +const anydasDas = ["TYPE_NUMBER", "delay", 31, "dasModifier"]; +const anydasArr = ["TYPE_NUMBER", "arrrr", 31, "arrModifier"]; const anydasEntryDelay = [ "TYPE_CHOICES", "entry charge", diff --git a/src/modes/dasmeter.asm b/src/modes/dasmeter.asm index b3543020..753a1647 100644 --- a/src/modes/dasmeter.asm +++ b/src/modes/dasmeter.asm @@ -1,16 +1,39 @@ stageDasMeterSprites: - lda dasMeterFlag - beq @ret - lda playState - beq @ret - @dasValue = generalCounter @tile = generalCounter2 @redCompare = generalCounter3 @orangeCompare = generalCounter4 +@dasMax = generalCounter5 +@halfTile = tmpX + lda #0 + sta @halfTile @yCoordinate = 211 @xStart = 103 + lda dasMeterFlag + beq @noMeter + lda playState + bne @meter +@noMeter: + rts +@meter: + lda autorepeatX + bpl @notNegative + lda #0 +@notNegative: + sta @dasValue + lda dasModifier + sta @dasMax + + cmp #17 + bcc @setCompare + +; half values for 17 or more (max 30 currently) + lsr @dasMax + lsr @dasValue + +@setCompare: + lda @dasMax lsr lsr sta @orangeCompare @@ -21,10 +44,10 @@ stageDasMeterSprites: lda #$FE sta @tile - lda autorepeatX + lda @dasValue lsr - php sta @dasValue + rol @halfTile cmp @orangeCompare bcs @stageSprites dec @tile @@ -33,9 +56,13 @@ stageDasMeterSprites: dec @tile @stageSprites: ldx oamStagingLength - lda #0 ldy #@xStart - + lda @dasValue + beq @drawHalfTile + cmp #9 + bcc @loop + lda #8 + sta @dasValue @loop: lda @tile sta oamStaging+1,x @@ -55,9 +82,12 @@ stageDasMeterSprites: tay dec @dasValue stx oamStagingLength - bpl @loop - plp - bcc @ret + bne @loop + +; check to see if carry was set for half width tile + lda @halfTile + beq @ret +@drawHalfTile: lda @tile sec sbc #32 diff --git a/src/playstate/active.asm b/src/playstate/active.asm index d0586741..063035e7 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -439,10 +439,10 @@ shift_tetrimino: beq @ret lda disableDasFlag bne @ret - inc autorepeatX lda autorepeatX + inc autorepeatX cmp dasValueDelay - bmi @ret + bne @ret @zeroDas: lda dasValuePeriod cmp dasValueDelay From 7bcb29c97acce2b99d99b19dd662c99bed1d4944 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Mon, 15 Jun 2026 23:52:24 +0000 Subject: [PATCH 74/79] adjust js --- src/nametables/game_type_menu.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/nametables/game_type_menu.js b/src/nametables/game_type_menu.js index 06c1f8eb..ee6bb4ba 100644 --- a/src/nametables/game_type_menu.js +++ b/src/nametables/game_type_menu.js @@ -67,10 +67,12 @@ drawTiles( `, ); -const gitTag = spawnSync("git", ["describe", "--tags"]).stdout.toString(); -[...gitTag.trim()].forEach( - (c, i) => (buffer[32 * 28 + 6 + i] = lookup.indexOf(c.toUpperCase())), -); +spawnSync("git", ["describe", "--tags"]) + .stdout.toString() + .match(/./g) + .forEach( + (c, i) => (buffer[32 * 28 + 6 + i] = lookup.indexOf(c.toUpperCase())), + ); const background = ` ɢ##############################ɳ From ef31d5c2081c703013cf99918549e658345ed172 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 16 Jun 2026 14:40:37 +0000 Subject: [PATCH 75/79] original das mechanics work better --- src/playstate/active.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/playstate/active.asm b/src/playstate/active.asm index 063035e7..d0586741 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -439,10 +439,10 @@ shift_tetrimino: beq @ret lda disableDasFlag bne @ret - lda autorepeatX inc autorepeatX + lda autorepeatX cmp dasValueDelay - bne @ret + bmi @ret @zeroDas: lda dasValuePeriod cmp dasValueDelay From 815032cb045dc8ce5cd7c64ebfb175649385bf0f Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 16 Jun 2026 14:57:25 +0000 Subject: [PATCH 76/79] make linter happier --- src/gamemode/gametypemenu/menu.js | 84 ++++++++++++++++--------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/src/gamemode/gametypemenu/menu.js b/src/gamemode/gametypemenu/menu.js index 19a0a683..e52d8dd8 100644 --- a/src/gamemode/gametypemenu/menu.js +++ b/src/gamemode/gametypemenu/menu.js @@ -1,11 +1,11 @@ const { mainMenu, extraSpriteStrings } = require("./menudata"); const { writeFileSync } = require("fs"); -MAX_LENGTH_NAME = 14; -MAX_LENGTH_VALUE = 8; -DEBUG = false; +const MAX_LENGTH_NAME = 14; +const MAX_LENGTH_VALUE = 8; +const DEBUG = false; -labelMap = { +const labelMap = { TYPE_BCD: typeDigit, TYPE_HEX: typeDigit, TYPE_NUMBER: typeNumber, @@ -17,41 +17,41 @@ labelMap = { TYPE_CUSTOM: typeCustom, }; -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 = {}; +const addedStrings = []; +const buffer = []; +const choiceSetCounts = []; +const choiceSetEnums = []; +const choiceSetIndexes = []; +const choiceSets = []; +let index = 0; +const items = []; +const lookupConstants = []; +const memoryBuffer = []; +const memoryMap = []; +const memoryReservations = {}; +const menuEnums = []; +const newStringLines = []; +const pageCountByMenu = []; +let pageIndex = 0; +const pageLabelText = {}; +const pagesOutput = []; +const startItemByPage = []; +const startPageByMenu = []; +const 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))) { + let match; + 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, ""); + return word.replace(/[- *?!(),/]/g, ""); } function getStringName(word) { @@ -88,7 +88,7 @@ function getOutputLines(itemType, string, memory) { } function getStringByte(c) { - replaceMap = { + const replaceMap = { ",": "$25", "/": "$4F", "(": "$5E", @@ -118,17 +118,19 @@ function getLineString(string, multiline = false) { function getPageLines(title, page, pages) { DEBUG && console.log(`getPageLines`, title, page, pages); - pageType = "PAGE_DEFAULT"; - [_, label, mode] = title.match(/([^[]*)(?:\s*\[mode=(\w+)\])?/i); + const pageType = "PAGE_DEFAULT"; + let label; + let mode; + [, 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 = []; + const pageLabelTextLines = []; pageLabelTextLines.push(`${pagelabelsName}:`); - padding = [...Array(Math.round((MAX_LENGTH_NAME - label.length) / 2))] + const padding = [...Array(Math.round((MAX_LENGTH_NAME - label.length) / 2))] .map(() => " ") .join(""); pageLabelTextLines.push(getLineString(`${padding}${label}`)); @@ -138,8 +140,8 @@ function getPageLines(title, page, pages) { if (i + 1 != page.length) pageLabelTextLines.push(endLabel); }); pageLabelTextLines.push(endLabelSet); - joined = pageLabelTextLines.join("\n"); - existing = pageLabelText[joined]; + const joined = pageLabelTextLines.join("\n"); + const existing = pageLabelText[joined]; if (!existing) pageLabelText[joined] = pagelabelsName; return { @@ -159,13 +161,13 @@ 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; + const 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(""); + const stringSet = [...choiceSet].map((c) => cleanWord(c.slice(0, 6))).join(""); unlabeledStringSets[stringSet] = choiceSet; return getOutputLines( `${label} | ${getChoiceSetConstant(stringSet)}`, @@ -182,7 +184,7 @@ function typeNumber(label, string, limit, memoryLabel) { ); } -function typeBool(label, string, memoryLabel) { +function typeBool(_, string, memoryLabel) { return typeChoices( "TYPE_CHOICES", string, @@ -206,12 +208,12 @@ function typeCustom(label, string, subroutine, memoryLabel) { function getMemoryLabel(string, bytes) { if (isNaN(bytes)) return bytes; // if label is specified use that instead - label = `menuVar${cleanWord(string)}`; + const label = `menuVar${cleanWord(string)}`; memoryReservations[label] = bytes; return label; } -processPageSet = (pages, name) => { +const processPageSet = (pages, name) => { DEBUG && name && console.log(`submenu ${name}`); DEBUG && !name && console.log(`main menu`); if (name) { @@ -250,7 +252,7 @@ processPageSet = (pages, name) => { processPageSet(mainMenu); items.forEach((i) => { - line = getByteLine( + const line = getByteLine( `${i.memory ? "<" + getMemoryLabel(i.string, i.memory) : "NORAM"} ; ${i.string}`, ); memoryMap.push(line); From 31289d7ff20d45f39417085cf2680b492b6f45ae Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 16 Jun 2026 15:19:11 +0000 Subject: [PATCH 77/79] simplify menu.js --- src/gamemode/gametypemenu/menu.asm | 12 +-- src/gamemode/gametypemenu/menu.js | 168 ++++++++++++----------------- src/ram.asm | 3 - 3 files changed, 74 insertions(+), 109 deletions(-) diff --git a/src/gamemode/gametypemenu/menu.asm b/src/gamemode/gametypemenu/menu.asm index de9d65b7..8d5217c2 100644 --- a/src/gamemode/gametypemenu/menu.asm +++ b/src/gamemode/gametypemenu/menu.asm @@ -9,7 +9,7 @@ ; save/restore to/from sram -AUTO_MENU_VARS_HI = >autoMenuVars +MENU_VARS_HI = >menuVars ; valid background chars are 0-253 EOL = $FE @@ -78,7 +78,7 @@ gameMode_gameTypeMenu: jsr updateAudioWaitForNmiAndEnablePpuRendering jsr updateAudioWaitForNmiAndResetOamStaging - lda #AUTO_MENU_VARS_HI + lda #MENU_VARS_HI sta byteSpriteAddr+1 lda #$1 sta renderMode @@ -356,7 +356,7 @@ setupUDDigitChange: @storeDigitMax: sta udMax - lda #AUTO_MENU_VARS_HI + lda #MENU_VARS_HI sta digitPtr+1 ldx activeItem lda memoryOffsets,x @@ -407,7 +407,7 @@ setupLRPageSelect: setupLRValueChange: ; setupLRValueChange - activeRow >= 0 && itemType < 128 - lda #AUTO_MENU_VARS_HI + lda #MENU_VARS_HI sta lrPointer+1 ldx activeItem lda memoryOffsets,x @@ -761,7 +761,7 @@ stageCurrentValues: lda #$00 sta @counter - lda #AUTO_MENU_VARS_HI + lda #MENU_VARS_HI ldx actualPage lda startItemByPage,x @@ -784,7 +784,7 @@ stageCurrentValues: ldy activeItem lda memoryOffsets,y sta byteSpriteAddr - lda #AUTO_MENU_VARS_HI + lda #MENU_VARS_HI sta byteSpriteAddr+1 lda itemTypes,y tax diff --git a/src/gamemode/gametypemenu/menu.js b/src/gamemode/gametypemenu/menu.js index e52d8dd8..b2a30ebc 100644 --- a/src/gamemode/gametypemenu/menu.js +++ b/src/gamemode/gametypemenu/menu.js @@ -18,7 +18,6 @@ const labelMap = { }; const addedStrings = []; -const buffer = []; const choiceSetCounts = []; const choiceSetEnums = []; const choiceSetIndexes = []; @@ -26,9 +25,7 @@ const choiceSets = []; let index = 0; const items = []; const lookupConstants = []; -const memoryBuffer = []; const memoryMap = []; -const memoryReservations = {}; const menuEnums = []; const newStringLines = []; const pageCountByMenu = []; @@ -206,13 +203,6 @@ function typeCustom(label, string, subroutine, memoryLabel) { ); } -function getMemoryLabel(string, bytes) { - if (isNaN(bytes)) return bytes; // if label is specified use that instead - const label = `menuVar${cleanWord(string)}`; - memoryReservations[label] = bytes; - return label; -} - const processPageSet = (pages, name) => { DEBUG && name && console.log(`submenu ${name}`); DEBUG && !name && console.log(`main menu`); @@ -253,19 +243,11 @@ processPageSet(mainMenu); items.forEach((i) => { const line = getByteLine( - `${i.memory ? "<" + getMemoryLabel(i.string, i.memory) : "NORAM"} ; ${i.string}`, + `${i.memory ? "<" + 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], @@ -314,86 +296,72 @@ writeFileSync(__dirname + "/menuram.asm", [...memoryBuffer, ""].join("\n")); }); }); 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")); +const output = ` +; generated by menu.js +; will be overwritten unless built with -M + +${lookupConstants.join('\n')} + +.enum +MAIN_MENU +${menuEnums.join('\n')} +MENU_COUNT +.endenum +.out .sprintf("%d/32 menus", MENU_COUNT) + +.enum +${choiceSetEnums.join('\n')} +CHOICESET_COUNT +.endenum +.out .sprintf("%d/32 choicesets", CHOICESET_COUNT) + +; index activeMenu + +startPageByMenu: +${startPageByMenu.join('\n')} + +pageCountByMenu: +${pageCountByMenu.join('\n')} + +; index activePage +pageTypes: +${pagesOutput.map((p) => p.label).join('\n')} + +itemCountByPage: +${pagesOutput.map((p) => p.count).join('\n')} + +pageLabelsHi: +${pagesOutput.map((p) => p.hibytes).join('\n')} + +pageLabelsLo: +${pagesOutput.map((p) => p.lobytes).join('\n')} + +startItemByPage: +${startItemByPage.join('\n')} + +; index activeItem + +memoryOffsets: +${memoryMap.join('\n')} + +itemTypes: +${items.map((i) => i.label).join('\n')} + +choiceSetIndexes: +${choiceSetIndexes.join('\n')} + +choiceSetCounts: +${choiceSetCounts.join('\n')} + +choiceSets: +${choiceSets.join('\n')} + +${newStringLines.join('\n')} + +${pagesOutput.map((p) => p.choicesets).join('\n')} +.out .sprintf("%d/256 choice set bytes", * - choiceSetTable) +` + +writeFileSync(__dirname + "/menudata.asm", output); diff --git a/src/ram.asm b/src/ram.asm index ba48c136..c374bcdb 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -440,7 +440,4 @@ sramVariableLength := * - menuVars keyboardFlag: .res 1 .endif - -.include "gamemode/gametypemenu/menuram.asm" - ; ... $7FF From f234b838f041bc78b695035c2439e3f9d6e3bcf5 Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 16 Jun 2026 17:00:51 +0000 Subject: [PATCH 78/79] vits scoring --- src/gamemode/gametypemenu/menudata.js | 2 ++ src/playstate/lock.asm | 34 ++++++++++++++++++++++++++- src/ram.asm | 1 + 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/gamemode/gametypemenu/menudata.js b/src/gamemode/gametypemenu/menudata.js index e603985a..1682ff71 100644 --- a/src/gamemode/gametypemenu/menudata.js +++ b/src/gamemode/gametypemenu/menudata.js @@ -15,6 +15,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", "dasOnlyFlag"]; +const vitsScoreFlag = ["TYPE_BOOL", "vits scoring", "vitsScoreFlag"]; const scoringModifier = [ "TYPE_CHOICES", @@ -185,6 +186,7 @@ const tournamentSubMenu = { linecapLevel, linecapLines, dasOnly, + vitsScoreFlag, ], }; diff --git a/src/playstate/lock.asm b/src/playstate/lock.asm index f30e0aa5..f095b2ee 100644 --- a/src/playstate/lock.asm +++ b/src/playstate/lock.asm @@ -1,4 +1,6 @@ playState_lockTetrimino: +I_VERTICAL = $11 +VITS_SCORE = 100000 @currentTile = generalCounter5 jsr isPositionValid beq @notGameOver @@ -45,12 +47,42 @@ playState_lockTetrimino: @notGameOver: lda vramRow cmp #$20 - bmi @ret + bpl @noWait + rts +@noWait: ldy tetriminoY lda multBy10Table,y clc adc tetriminoX sta generalCounter + +; score if vits + ldx vitsScoreFlag + beq @noVits + ldx currentPiece + cpx #I_VERTICAL + bne @noVits + ; check if tile exists above + sec + sbc #30 + tax + lda playfield,x + bmi @noVits + ; tile exists + clc + lda #VITS_SCORE + adc binScore+1 + sta binScore+1 + lda #^VITS_SCORE + adc binScore+2 + sta binScore+2 + lda #0 + adc binScore+3 + sta binScore+3 +@noVits: ldx currentPiece lda tetriminoTileFromOrientation,x sta @currentTile diff --git a/src/ram.asm b/src/ram.asm index c374bcdb..6d5f483b 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -433,6 +433,7 @@ noLineClearDelayFlag: .res 1 set_seed_input: .res 3 ; $0037 ; copied to set_seed during gameModeState_initGameState b_seed_input: .res 2 typeBSeedFlag: .res 1 +vitsScoreFlag: .res 1 sramVariableLength := * - menuVars From f235d2be3325ae1f6c23111c16dffc96588a903e Mon Sep 17 00:00:00 2001 From: zohassadar Date: Tue, 16 Jun 2026 19:10:38 +0000 Subject: [PATCH 79/79] use table for 1/3 rng --- src/modes/crash.asm | 2 +- src/ram.asm | 2 +- src/util/core.asm | 26 ++++++++++++++++++++------ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/modes/crash.asm b/src/modes/crash.asm index 4581e3f8..99c9da40 100644 --- a/src/modes/crash.asm +++ b/src/modes/crash.asm @@ -207,7 +207,7 @@ testCrash: @randomFactors: lda strictFlag bne @noDMA ;for strict crash, do not add random cycles. - lda oneThirdPRNG ; RNG for which cycle of the last instruction the game returns to + jsr getOneThirdRNG adc allegroIndex sta allegroIndex lda frameCounter diff --git a/src/ram.asm b/src/ram.asm index 6d5f483b..6c1e2125 100644 --- a/src/ram.asm +++ b/src/ram.asm @@ -12,7 +12,7 @@ score: .res 4 ; $C ; 4 bytes BCD nmiReturnAddr: .res 1 ; $0010 ; used for crash crashState: .res 1 ; $0011 ; used for crash cycleCount: .res 2 ; $0012 ; 2 bytes ; used for crash -oneThirdPRNG: .res 1 ; $0014 ; used for crash +.res 1 b_seed: .res 2 ; loaded with rng_seed unless seeded rng_seed: .res 2 ; $0017 diff --git a/src/util/core.asm b/src/util/core.asm index aed55a81..c3545438 100644 --- a/src/util/core.asm +++ b/src/util/core.asm @@ -256,12 +256,26 @@ generateNextPseudorandomNumber: lsr ror tmp1,x ror tmp2,x - lda oneThirdPRNG - sbc #$00 - bpl @noReset - lda #$2 -@noReset: - sta oneThirdPRNG + rts + +getOneThirdRNG: +; returns 0,1,2 in A, preserves flags + php + lda rng_seed+1 + cmp #170 + bcc :+ + lda #2 + plp + rts +: + cmp #85 + bcc :+ + lda #1 + plp + rts +: + lda #0 + plp rts ; reg a: value; reg x: start page; reg y: end page (inclusive)