diff --git a/build.js b/build.js index aaa24637..d61f3b58 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('--')); @@ -100,6 +106,7 @@ console.log(); // build / compress nametables console.time('nametables'); +process.env['GYM_FLAGS'] = compileFlags.join(' '); require('./src/nametables/build'); console.timeEnd('nametables'); diff --git a/src/boot.asm b/src/boot.asm index f6d496e8..b9dcd0cf 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -31,7 +31,13 @@ sta paceModifier lda #$10 +.if ANYDAS <> 1 sta dasModifier +.else + sta anydasDASValue + lda #$06 + sta anydasARRValue +.endif lda #INITIAL_LINECAP_LEVEL sta linecapLevel diff --git a/src/constants.asm b/src/constants.asm index 6d9143ed..a481311f 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 @@ -81,7 +85,9 @@ MODE_TAPQTY MODE_CHECKERBOARD MODE_GARBAGE MODE_DROUGHT +.if ANYDAS <> 1 MODE_DAS +.endif MODE_LOWSTACK MODE_KILLX2 MODE_INVISIBLE @@ -98,12 +104,19 @@ MODE_DARK MODE_GOOFY MODE_DEBUG MODE_LINECAP +.if ANYDAS <> 1 MODE_DASONLY +.endif MODE_QUAL MODE_PAL +.if ANYDAS = 1 +MODE_DAS_VALUE +MODE_ARR_VALUE +MODE_ARE_CHARGE +.endif +MODE_QUANTITY .endenum -MODE_QUANTITY = MODE_PAL + 1 MODE_GAME_QUANTITY = MODE_HARDDROP + 1 SCORING_CLASSIC := 0 ; for scoringModifier @@ -149,7 +162,9 @@ MENU_TOP_MARGIN_SCROLL := 7 ; in blocks .byte $8 ; MODE_CHECKERBOARD .byte $4 ; MODE_GARBAGE .byte $12 ; MODE_DROUGHT +.if ANYDAS <> 1 .byte $10 ; MODE_DAS +.endif .byte $12 ; MODE_LOWSTACK .byte $0 ; MODE_KILLX2 .byte $0 ; MODE_INVISIBLE @@ -166,9 +181,16 @@ MENU_TOP_MARGIN_SCROLL := 7 ; in blocks .byte $1 ; MODE_GOOFY .byte $1 ; MODE_DEBUG .byte $1 ; MODE_LINECAP +.if ANYDAS <> 1 .byte $1 ; MODE_DASONLY +.endif .byte $1 ; MODE_QUAL .byte $1 ; MODE_PAL +.if ANYDAS = 1 + .byte $40 ; MODE_DAS_VALUE + .byte $40 ; MODE_ARR_VALUE + .byte $1 ; MODE_ARE_CHARGE +.endif .endmacro .macro MODENAMES @@ -188,7 +210,9 @@ MENU_TOP_MARGIN_SCROLL := 7 ; in blocks .byte "CKRBRD" .byte "GARBGE" .byte "LOBARS" +.if ANYDAS <> 1 .byte "DASDLY" +.endif .byte "LOWSTK" .byte "KILLX2" .byte "INVZBL" 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 45cc8a47..f9893668 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 @@ -29,71 +31,72 @@ WXYZ-,˙>######## const buffer = blankNT(); const extra = [...buffer]; -drawTiles(buffer, lookup, ` -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a TETRIS d# -#a T-SPINS d# -#a SEED d# -#a STACKING d# -#a PACE d# -#a SETUPS d# -#a B-TYPE d# -#a FLOOR d# -#a CRUNCH d# -#a (QUICK)TAP d# -#a TRANSITION d# -#a MARATHON d# -#a TAP QUANTITY d# -#a CHECKERBOARD d# -#a GARBAGE d# -#a DROUGHT d# -#a DAS DELAY d# -#a LOW STACK d# -#a KILLSCREEN »2 d# -#a INVISIBLE d# -#a HARD DROP d# -`);drawTiles(extra, lookup, ` -#a TAP/ROLL SPEED d# -#a SCORING d# -#a CRASH d# -#a STRICT CRASH d# -#a HZ DISPLAY d# -#a INPUT DISPLAY d# -#a DISABLE FLASH d# -#a DISABLE PAUSE d# -#a DARK MODE d# -#a GOOFY FOOT d# -#a BLOCK TOOL d# -#a LINECAP d# -#a DAS ONLY d# -#a QUAL MODE d# -#a PAL MODE d# -#a d# -#a d# -#a V6 d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -#a d# -`); +modes = ` +TETRIS +T-SPINS +SEED +STACKING +PACE +SETUPS +B-TYPE +FLOOR +CRUNCH +(QUICK)TAP +TRANSITION +MARATHON +TAP QUANTITY +CHECKERBOARD +GARBAGE +DROUGHT +DAS DELAY +LOW STACK +KILLSCREEN »2 +INVISIBLE +HARD DROP +TAP/ROLL SPEED +SCORING +CRASH +STRICT CRASH +HZ DISPLAY +INPUT DISPLAY +DISABLE FLASH +DISABLE PAUSE +DARK MODE +GOOFY FOOT +BLOCK TOOL +LINECAP +DAS ONLY +QUAL MODE +PAL MODE +` + .trim() + .split('\n'); + +if (anydas) { + modes.splice(modes.indexOf('DAS DELAY'), 1); + modes.splice(modes.indexOf('DAS ONLY'), 1); + modes.push('DAS', 'ARR', 'ARE CHARGE'); +} + +const modeStartRow = 9; +const modeOffset = 6; +const modeIdx = modeStartRow * 32 + modeOffset; + +const urlX = 3; +const urlY = 17; + +menuScreens = [...Array(30 * 2)] + .map(() => '#a d#'.split('')) + .flat(); + +modes.forEach((mode, i) => + menuScreens.splice(i * 32 + modeIdx, mode.length, ...mode), +); + +menuScreens.splice((30 + urlY) * 32 + urlX, 2, ...'V6'); + +drawTiles(buffer, lookup, menuScreens.splice(0, 32*30).join('')); +drawTiles(extra, lookup, menuScreens.join('')); const background = ` ɢ##############################ɳ @@ -133,8 +136,6 @@ drawTiles(extra, lookup, background); drawRect(buffer, 8, 2, 10, 5, 0xB0); // draw logo -const urlX = 3; -const urlY = 17; drawRect(extra, urlX, urlY, 12, 1, 0x74); drawRect(extra, urlX+12, urlY, 12, 1, 0x84); diff --git a/src/playstate/active.asm b/src/playstate/active.asm index e60cb685..93c3bc3a 100644 --- a/src/playstate/active.asm +++ b/src/playstate/active.asm @@ -400,6 +400,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 @@ -445,6 +446,7 @@ shift_tetrimino: lda #$08 sta dasValuePeriod @shiftTetrimino: +.endif lda tetriminoX sta originalY @@ -457,6 +459,18 @@ shift_tetrimino: lda heldButtons and #$03 beq @ret +.if ANYDAS = 1 + dec autorepeatX + lda autorepeatX + cmp #$01 + bpl @ret + lda anydasARRValue + sta autorepeatX + beq @zeroArr + bne @buttonHeldDown +@resetAutorepeatX: + lda anydasDASValue +.else inc autorepeatX lda autorepeatX cmp dasValueDelay @@ -467,6 +481,7 @@ shift_tetrimino: @resetAutorepeatX: lda #$00 +.endif sta autorepeatX @buttonHeldDown: lda heldButtons @@ -493,6 +508,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 3cd6fcc2..491b5573 100644 --- a/src/playstate/spawnnext.asm +++ b/src/playstate/spawnnext.asm @@ -52,6 +52,12 @@ playState_spawnNextTetrimino: jsr incrementPieceStat jsr chooseNextTetrimino sta nextPiece +.if ANYDAS = 1 + lda anydasARECharge + beq :+ + sta autorepeatX ; store 1 if ARE Charge is on +: +.endif @resetDownHold: lda #$00 sta autorepeatY diff --git a/src/ram.asm b/src/ram.asm index f021f206..c730978d 100755 --- a/src/ram.asm +++ b/src/ram.asm @@ -335,7 +335,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 @@ -348,8 +350,15 @@ 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 +.if ANYDAS = 1 +anydasDASValue: .res 1 +anydasARRValue: .res 1 +anydasARECharge: .res 1 +.endif ; ... $7FF