diff --git a/assets/compile_resources.py b/assets/compile_resources.py index 3e51cd1..5fa5036 100644 --- a/assets/compile_resources.py +++ b/assets/compile_resources.py @@ -235,6 +235,10 @@ kLmFeature_MusicRegTweak = 1 << 17 kLmFeature_TideWaterTweak = 1 << 18 kLmFeature_EnemyCollTweak = 1 << 19 kLmFeature_Ow4bppGfx = 1 << 20 +kLmFeature_DontResetOwPlayersMap = 1 << 21 +kLmFeature_NonStdGfxAA8D = 1 << 22 +kLmFeature_TimerTweaks = 1 << 23 +kLmFeature_NoDefaultSavePrompts = 1 << 24 kHack_Walljump = 1 << 0 @@ -734,10 +738,15 @@ def print_all(args): lm_feat.flags |= kLmFeature_TideWaterTweak if get_byte(0xa045) == 0x22 else 0 lm_feat.flags |= kLmFeature_EnemyCollTweak if get_byte(0x194B6) == 0x5c else 0 lm_feat.flags |= kLmFeature_Ow4bppGfx if get_bytes(0xA149, 4) != b'\x22\x28\xBA\x00' else 0 + lm_feat.flags |= kLmFeature_DontResetOwPlayersMap if get_byte(0xa0a0) == 0xea else 0 + lm_feat.flags |= kLmFeature_NonStdGfxAA8D if get_byte(0xAA8D) != 0x08 else 0 + lm_feat.flags |= kLmFeature_TimerTweaks if get_byte(0x58E24) == 0x8f else 0 + lm_feat.flags |= kLmFeature_NoDefaultSavePrompts if get_byte(0x3BA26) == 0 else 0 + # Allows Mario to perform a wall kick by sliding along a wall and pressing the # B button. - lm_feat.hacks |= kHack_Walljump if get_24(0xA2A2) != 0x586F1 else 0 + lm_feat.hacks |= kHack_Walljump if get_24(0xA2A1) != 0x86F122 else 0 def add_custom_ow_palette(): r = b'' diff --git a/assets/util.py b/assets/util.py index b38fbff..7625560 100644 --- a/assets/util.py +++ b/assets/util.py @@ -52,6 +52,7 @@ kHackInfo = { 'enhanced' : ('Super Mario World Enhanced.ips', '2882a39ac64b597e9260e92aaba610d0b6f03adb', 'Super Mario World Enhanced.bsdiff', '5a53369916fd728033d16db3abceb487900f903a', 'ebe23d8a26759ba1b5c2f4d6d8f8db3ab88e902f'), 'redrawn' : ('smw_redrawn.ips', '7168df51ba025a12177ce00e88540c1341ef3efc', 'smw_redrawn.bsdiff', '13b658e626020aa35dca4e1c3648c6a6d8afa901', '50702ffc8c2e7115c9ba0c80c8ec40da5a487651'), 'nsmb' : ('SMW with Levels from NSMB.bps', '4277edf003340021ce4e68fe2278d1d73f4d798c', 'SMW with Levels from NSMB.bsdiff', 'e2d2487324374aea1d67a6aa6b3b47f8b3e6727c', '877e9c6fce29e80e4c52892120af06748550487a'), + 'return_dino_land' : ('Return to Dinosaur Land.bps', 'e9a891ecd0f6f43a4592487ca2590311be00396d', 'Return to Dinosaur Land.bsdiff', 'ad2ebd7b416cbfd3cd7cac833b0ca7f690b9144b', '1d03777086f3c86b1693f9ce2411f560813732a8') } kModsPath = os.path.join(DEFAULT_ROM_DIRECTORY, '../smw_hacks/mods') diff --git a/src/common_cpu_infra.c b/src/common_cpu_infra.c index 033dea1..571e8a8 100644 --- a/src/common_cpu_infra.c +++ b/src/common_cpu_infra.c @@ -279,6 +279,7 @@ Snes *SnesInit(const uint8 *data, int data_size) { } } g_rtl_game_info->initialize(); + snes_reset(g_snes, true); // reset after loading PatchBugs(1, 0); } else { g_runmode = RM_MINE; diff --git a/src/funcs.h b/src/funcs.h index 43e72a4..cfc433c 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -1534,7 +1534,7 @@ void SubmapSwitchProcess01_UpdateLayer1(void); void SubmapSwitchProcess05_UpdatePalette(void); void SubmapSwitchProcess06_EndWindowHDMA(void); void SubmapSwitchProcess07_EndSubmapSwitch(void); -void UnlockOverworldPathBasedOnExit(void); +uint16 UnlockOverworldPathBasedOnExit(void); uint16 UpdateLevelName_049D7F(uint16 j, uint16 k, uint16 r2w); void UpdateLevelName(uint16 r0w); void UpdateOverworldSpritePosition(uint8 k); @@ -2114,6 +2114,10 @@ enum { kLmFeature_TideWaterTweak = 1 << 18, kLmFeature_EnemyCollTweak = 1 << 19, kLmFeature_Ow4bppGfx = 1 << 20, + kLmFeature_DontResetOwPlayersMap = 1 << 21, + kLmFeature_NonStdGfxAA8D = 1 << 22, + kLmFeature_TimerTweaks = 1 << 23, + kLmFeature_NoDefaultSavePrompts = 1 << 24, }; // Non lunar magic hacks diff --git a/src/smw_00.c b/src/smw_00.c index 17fc6bc..5b0f72b 100644 --- a/src/smw_00.c +++ b/src/smw_00.c @@ -2135,7 +2135,8 @@ void GameMode0C_LoadOverworld() { // 00a087 ClearOverworldAndCutsceneRAM(); if (misc_intro_level_flag) { timer_title_screen_input_timer = -80; - ow_players_map[0] = 0; + if (!HAS_LM_FEATURE(kLmFeature_DontResetOwPlayersMap)) + ow_players_map[0] = 0; mirror_mosaic_size_and_bgenable = -16; misc_game_mode = 16; return; @@ -2710,8 +2711,9 @@ void UploadGraphicsFiles_UploadGFXFile(uint16 dst_addr, uint8 j, uint8 index) { } bool lm_flag = HAS_LM_FEATURE(kLmFeature_4bppgfx); + bool lm_flag2 = HAS_LM_FEATURE(kLmFeature_NonStdGfxAA8D); - if (misc_level_tileset_setting >= 0x11 && j == (lm_flag ? 0x32 : 8) || j == (lm_flag ? 0x32 : 30)) { + if (misc_level_tileset_setting >= 0x11 && j == (lm_flag2 ? 0x32 : 8) || j == (lm_flag2 ? 0x32 : 30)) { uint16 r10w = -256; for (int8 i = 127; i >= 0; --i) { for (int8 k = 7; k >= 0; --k) { @@ -2720,11 +2722,12 @@ void UploadGraphicsFiles_UploadGFXFile(uint16 dst_addr, uint8 j, uint8 index) { *(uint16 *)&graphics_3_bppto4_bppbuffer[(uint8)k] = WORD(p0[0]) | swap16(v11); p0 += 2; } + int step = lm_flag ? 2 : 1; for (int8 m = 7; m >= 0; --m) { const uint8 *v14 = p0; uint16 r12w = *v14; *dst++ = r12w | r10w & (*(uint16 *)&graphics_3_bppto4_bppbuffer[(uint8)m] | swap16(*(uint16 *)v14)); - p0 += 1; + p0 += step; } } } else { @@ -4267,7 +4270,8 @@ void PlayerState09_Death() { // 00d0b6 if (!flag_prevent_yoshi_carry_over) yoshi_carry_over_levels_flag = 0; if ((--player_current_life_count & 0x80) == 0) { - if (counter_timer_ones | counter_timer_tens | counter_timer_hundreds) { + if (HAS_LM_FEATURE(kLmFeature_TimerTweaks) && lm_timer_var != 0 || + counter_timer_ones | counter_timer_tens | counter_timer_hundreds) { misc_game_mode = 11; return; } diff --git a/src/smw_04.c b/src/smw_04.c index 7ae349d..231d81d 100644 --- a/src/smw_04.c +++ b/src/smw_04.c @@ -741,9 +741,20 @@ LABEL_11: } void OwProcess02_HandleLevelBeaten() { // 048f87 - UnlockOverworldPathBasedOnExit(); + uint16 r4 = UnlockOverworldPathBasedOnExit(); uint8 v0 = 7; - while ((uint8)ow_tile_player_is_standing_on != kOwTriggerSaveTiles_048F7F[v0]) { + uint8 a = (uint8)ow_tile_player_is_standing_on; + + if (g_lunar_magic) { + if (ow_level_tile_settings[ow_level_number_of_each_tiletbl[r4]] & 0x10) { + a = 0x80; + } else { + if (HAS_LM_FEATURE(kLmFeature_NoDefaultSavePrompts)) + a = 0xff; + } + } + + while (a != kOwTriggerSaveTiles_048F7F[v0]) { if ((--v0 & 0x80) != 0) goto LABEL_10; } @@ -1279,27 +1290,29 @@ void OwProcess0C_IntroMarch() { // 0498c6 } } -void UnlockOverworldPathBasedOnExit() { // 049903 - if ((int8)misc_exit_level_action > 0) { - uint16 r8 = kSharedOverworldPathTables_DATA_049060[(uint8)(misc_exit_level_action - 1)]; - uint8 v0 = player_current_characterx4; - PointU16 *pt = get_PointU16(ow_players_pos, player_current_characterx4); - uint16 r0w = pt->x >> 4; - PointU16 *v2 = get_PointU16(ow_players_grid_aligned_pos, player_current_characterx4); - v2->x = r0w; - uint16 r2w = pt->y >> 4; - v2->y = r2w; - uint16 r4w = CalculateOverworldPlayerPosition(v0 >> 2, r0w, r2w); - uint16 v3 = ow_level_direction_flags[r4w]; - int16 v4 = r8; - if (r8) { - do { - v3 >>= 1; - --v4; - } while (v4 >= 0); - } - *(uint16 *)&ow_level_tile_settings[ow_level_number_of_each_tiletbl[r4w]] |= kBitTable_Bank04[(uint16)(2 * (v3 & 3)) >> 1]; +uint16 UnlockOverworldPathBasedOnExit() { // 049903 + if ((int8)misc_exit_level_action <= 0) + return 0; + + uint16 r8 = kSharedOverworldPathTables_DATA_049060[(uint8)(misc_exit_level_action - 1)]; + uint8 v0 = player_current_characterx4; + PointU16 *pt = get_PointU16(ow_players_pos, player_current_characterx4); + uint16 r0w = pt->x >> 4; + PointU16 *v2 = get_PointU16(ow_players_grid_aligned_pos, player_current_characterx4); + v2->x = r0w; + uint16 r2w = pt->y >> 4; + v2->y = r2w; + uint16 r4w = CalculateOverworldPlayerPosition(v0 >> 2, r0w, r2w); + uint16 v3 = ow_level_direction_flags[r4w]; + int16 v4 = r8; + if (r8) { + do { + v3 >>= 1; + --v4; + } while (v4 >= 0); } + *(uint16 *)&ow_level_tile_settings[ow_level_number_of_each_tiletbl[r4w]] |= kBitTable_Bank04[(uint16)(2 * (v3 & 3)) >> 1]; + return r4w; } void HandleOverworldPathExits() { // 049a24 @@ -2043,7 +2056,7 @@ void OwEventProcess07_SilentEventsAndEndOfEvent_Entry2(uint8 a, bool from_where) if (HAS_LM_FEATURE(kLmFeature_EventStuff)) { LmHook_EventStuff(a, from_where); } else { - for (uint8 i = 43; (i & 0x80) == 0; --i) { + for (uint8 i = kOwEventProcess07_SilentEventsAndEndOfEvent_SilentEventTiles_SIZE - 1; (i & 0x80) == 0; --i) { if (a == kOwEventProcess07_SilentEventsAndEndOfEvent_SilentEventTiles[i]) { uint8 v4 = i; uint8 r2 = kOwEventProcess07_SilentEventsAndEndOfEvent_SilentEventTiles_TileLayer[i]; diff --git a/src/smw_05.c b/src/smw_05.c index b2c5495..cb88596 100644 --- a/src/smw_05.c +++ b/src/smw_05.c @@ -594,6 +594,8 @@ void LoadLevelHeader() { // 0584e3 r0 = hdr[3]; if (!counter_sublevels_entered) { counter_timer_hundreds = kLoadLevelHeader_TimerTable[r0 >> 6]; + if (HAS_LM_FEATURE(kLmFeature_TimerTweaks)) + lm_timer_var = counter_timer_hundreds; counter_timer_tens = 0; counter_timer_ones = 0; } diff --git a/src/smw_cpu_infra.c b/src/smw_cpu_infra.c index 76a9503..9d66071 100644 --- a/src/smw_cpu_infra.c +++ b/src/smw_cpu_infra.c @@ -245,6 +245,17 @@ void SmwCpuInitialize(void) { static const uint8 kRevert_0x2e6ec[] = { 0xa9, 0x38, 0x9d, 0xea, 0x15 }; memcpy(SnesRomPtr(0x2e6ec), kRevert_0x2e6ec, sizeof(kRevert_0x2e6ec)); } + + // fast rom + static const uint8 kRevert_0xfffc[] = { 0x00, 0x80 }; + memcpy(SnesRomPtr(0xfffc), kRevert_0xfffc, sizeof(kRevert_0xfffc)); + static const uint8 kRevert_0xffea[] = { 0x6a, 0x81 }; + memcpy(SnesRomPtr(0xffea), kRevert_0xffea, sizeof(kRevert_0xffea)); + static const uint8 kRevert_0x801c[] = { 0xfb }; + memcpy(SnesRomPtr(0x801c), kRevert_0x801c, sizeof(kRevert_0x801c)); + static const uint8 kRevert_0x8713[] = { 0xb7, 0x02, 0x85, 0x01 }; + memcpy(SnesRomPtr(0x8713), kRevert_0x8713, sizeof(kRevert_0x8713)); + } } diff --git a/src/snes/cpu.c b/src/snes/cpu.c index 9232683..6e838c5 100644 --- a/src/snes/cpu.c +++ b/src/snes/cpu.c @@ -751,14 +751,16 @@ static void cpu_doOpcode(Cpu* cpu, uint8_t opcode) { pc_hist[pc_hist_ctr] = cur_pc; pc_hist_ctr = (pc_hist_ctr + 1) & 15; - if (0 && cur_pc == 0x5D83B) { + if (cur_pc == 0x3FDE0) { + DumpCpuHistory(); g_snes->debug_cycles = 0; } if (cur_pc == pc_bp) { - printf("Reached BP 0x%x. A=0x%.2x, X=0x%.2x, Y=0x%.2x. C=%d. lm_var13CD=%x\n", - cur_pc, cpu->a, cpu->x, cpu->y, cpu->c, - *(uint16*)&g_ram[14]); + printf("Reached BP 0x%x. A=0x%.2x, X=0x%.2x, Y=0x%.2x. C=0x%.2x,0x%.2x\n", + cur_pc, cpu->a, cpu->x, cpu->y, + g_ram[0xbcee], + g_ram[0xad10]); // printf("T: 16 j=%d, %d\n", g_cpu->y, g_cpu->a); bp_cnt += 1; //g_snes->debug_cycles = 1; @@ -776,7 +778,7 @@ restart: break; case 2: // rtl cpu->pc = cpu_pullWord(cpu) + 1; - cpu->k = cpu_pullByte(cpu); + cpu->k = cpu_pullByte(cpu) & 0x7f; break; case 0xe5: case 0xe9: @@ -1002,7 +1004,7 @@ restart: cpu_pushByte(cpu, cpu->k); cpu_pushWord(cpu, cpu->pc - 1); cpu->pc = value; - cpu->k = newK; + cpu->k = newK & 0x7f; break; } case 0x23: { // and sr @@ -1378,7 +1380,7 @@ restart: DumpCpuHistory(); Die("The game has crashed!\n"); } - cpu->k = new_k; + cpu->k = new_k & 0x7f; cpu->pc = value; break; } @@ -1488,7 +1490,7 @@ restart: } cpu->pc = cpu_pullWord(cpu) + 1; - cpu->k = cpu_pullByte(cpu); + cpu->k = cpu_pullByte(cpu) & 0x7f; break; } case 0x6c: { // jmp ind @@ -2175,7 +2177,7 @@ restart: case 0xdc: { // jml ial uint16_t adr = cpu_readOpcodeWord(cpu); cpu->pc = cpu_readWord(cpu, adr, (adr + 1) & 0xffff); - cpu->k = cpu_read(cpu, (adr + 2) & 0xffff); + cpu->k = cpu_read(cpu, (adr + 2) & 0xffff) & 0x7f; break; } case 0xdd: { // cmp abx(r) diff --git a/src/snes/snes_other.c b/src/snes/snes_other.c index d00560a..84d94d9 100644 --- a/src/snes/snes_other.c +++ b/src/snes/snes_other.c @@ -98,7 +98,7 @@ bool snes_loadRom(Snes* snes, const uint8_t* data, int length) { snes->cart, headers[used].cartType, newData, newLength, headers[used].chips > 0 ? headers[used].ramSize : 0 ); - snes_reset(snes, true); // reset after loading + free(newData); return true; } diff --git a/src/variables.h b/src/variables.h index 26fc236..72efe01 100644 --- a/src/variables.h +++ b/src/variables.h @@ -1048,4 +1048,6 @@ typedef struct ExAnimationInfo { #define lm_title_screen_var (*(uint16 *)(g_ram + 0x1fffe)) +#define lm_timer_var (*(uint8 *)(g_ram + 0x1ffe0)) + extern bool g_lunar_magic; \ No newline at end of file