diff --git a/include/variables.h b/include/variables.h index c2f8e9ab..e7f69e60 100644 --- a/include/variables.h +++ b/include/variables.h @@ -14,6 +14,31 @@ #define POOL_END_4MB 0x80400000 #define POOL_END_6MB 0x80600000 +// game states +#define STATE_N64_LOGO_INTRO 0x01 // N64 Logo + Intro +#define STATE_TITLE_SCREEN 0x02 // Title screen +#define STATE_N64DD_BOOT_UNUSED 0x03 // seems to be unused, but boots an N64DD disk. Leftover from JP. +#define STATE_MENU_SELECT 0x04 // Menu Select (select Battle Now!, POKeMON Stadium, etc) +#define STATE_AREA_SELECT 0x10 // Area Select (select Stadium, GB Tower, Gym Leader Castle, etc) +#define STATE_GALLERY 0x11 // Gallery +#define STATE_EVENT_BATTLE 0x12 // Event Battle +#define STATE_OPTIONS 0x13 // Options +#define STATE_FAST_N64_LOGO 0x40 // N64 Logo but no Intro. The Sticker Station might use this for booting quickly and into Gallery mode. +#define STATE_STADIUM_MENU 0x20 // POKeMON Stadium (the main Stadium mode) +#define STATE_FREE_BATTLE 0x21 // Free Battle +#define STATE_VS_MEWTWO 0x22 // VS Mewtwo +#define STATE_KIDS_CLUB 0x23 // Kids Club +#define STATE_VICTORY_PALACE 0x24 // Victory Palace +#define STATE_POKEMON_LAB 0x25 // POKeMON Lab +#define STATE_GB_TOWER 0x26 // GB Tower +#define STATE_GYM_LEADER_CASTLE 0x27 // Gym Leader Castle +#define STATE_BATTLE_NOW_1P 0x28 // Battle Now! (1P) +#define STATE_BATTLE_NOW_2P 0x29 // Battle Now! (2P) +#define STATE_BATTLE_FROM_EVENT 0x2A // Battle menu from Event Battle +#define STATE_STUBBED_DEBUG 0x80 // stubbed/removed debug menu. This could have been the Early Pokedex Menu seen in the JP version. +#define STATE_FAST_BATTLE 0x81 // most likely the P97/P98 mode(s) and uses GB Pak 1 and 2 for the teams for an immediate battle; skips even the VS screen and Battle Rule screen. However, the music/stadium used is probably set by some other menu, because it seems to use the outdoor Free Battle area + Poke Cup 1-3, which isnt correct. +#define STATE_KIDS_CLUB_TITLE 0x82 // Kids Club, but it returns to the title screen. Possibly for a Kiosk/demo version. + /* * Dynamic heap with an indetermate amount of space. This pool can either end at 4MB or * 6MB depending on osMemSize, which is really strange as it should be using the whole @@ -219,4 +244,8 @@ extern u8 D_87B000CC; extern u8 D_87B000D0; extern u8 D_87B000D4; +extern s32 gCurrentGameState; +extern s32 gLastGameState; +extern s8 D_800AF732; + #endif diff --git a/linker_scripts/us/symbol_addrs.txt b/linker_scripts/us/symbol_addrs.txt index fcc879e9..2dd33989 100644 --- a/linker_scripts/us/symbol_addrs.txt +++ b/linker_scripts/us/symbol_addrs.txt @@ -251,3 +251,6 @@ D_87B000F0 = 0x87B000F0; D_87B000F2 = 0x87B000F2; D_87B000F4 = 0x87B000F4; D_86402848 = 0x86402848; +gCurrentGameState = 0x80075668; // size:0x4 +gLastGameState = 0x8007566C; // size:0x4 + diff --git a/linker_scripts/us/symbol_addrs_code.txt b/linker_scripts/us/symbol_addrs_code.txt index bbb3cc5d..403298cd 100644 --- a/linker_scripts/us/symbol_addrs_code.txt +++ b/linker_scripts/us/symbol_addrs_code.txt @@ -922,7 +922,7 @@ func_80028C7C = 0x80028C7C; // type:func func_80028D60 = 0x80028D60; // type:func func_80028E68 = 0x80028E68; // type:func func_80028EB8 = 0x80028EB8; // type:func -func_80028FA0 = 0x80028FA0; // type:func +Game_DoCopyProtection = 0x80028FA0; // type:func func_80029008 = 0x80029008; // type:func func_80029048 = 0x80029048; // type:func func_80029074 = 0x80029074; // type:func diff --git a/src/29BA0.c b/src/29BA0.c index 90efc8c9..78221018 100644 --- a/src/29BA0.c +++ b/src/29BA0.c @@ -1,7 +1,16 @@ #include "global.h" #include "memory.h" -#pragma GLOBAL_ASM("asm/us/nonmatchings/29BA0/func_80028FA0.s") +s32 Game_DoCopyProtection(s32 state) { + u32 intr = osSetIntMask(1); + + // if the 16-bit value at ROM offset 0xE38 is not 0x828A, make the state an invalid one. + if (!(HW_REG(PI_STATUS_REG, u32) & 3) && ((*(u32*)0xB0000E38 & 0xFFFF) != 0x828A)) { + state = -0x10; + } + osSetIntMask(intr); + return state; +} s32 func_80029008(s32 arg0, s32 romStart, s32 romEnd, s32 arg3, s32 arg4) { s32 result; @@ -83,4 +92,47 @@ s32 func_80029008(s32 arg0, s32 romStart, s32 romEnd, s32 arg3, s32 arg4) { #pragma GLOBAL_ASM("asm/us/nonmatchings/29BA0/func_8002B310.s") -#pragma GLOBAL_ASM("asm/us/nonmatchings/29BA0/func_8002B330.s") +void Game_Thread(void *arg) { + s32 state; + + __osSetFpcCsr(0x01000C01U); + Cont_SetupControllers(); + func_800196DC(); + main_pool_push_state('GAME'); + D_800AF732 = 0; + // is this game connected to a Sticker Station? + if (func_8000B4C4() != 0) { + gCurrentGameState = STATE_FAST_N64_LOGO; + } + while(1) { + state = Game_DoCopyProtection(gCurrentGameState); + switch (state) { + case STATE_N64_LOGO_INTRO: func_80029310(); break; + case STATE_TITLE_SCREEN: func_800293CC(); break; + case STATE_N64DD_BOOT_UNUSED: func_800296AC(); break; + case STATE_AREA_SELECT: func_80029828(); break; + case STATE_GALLERY: func_8002A698(); break; + case STATE_EVENT_BATTLE: func_80029884(); break; + case STATE_OPTIONS: func_800298D4(); break; + case STATE_MENU_SELECT: func_80029924(); break; + case STATE_STADIUM_MENU: func_80029BC0(); break; + case STATE_FREE_BATTLE: func_8002A06C(); break; + case STATE_VS_MEWTWO: func_8002A400(); break; + case STATE_KIDS_CLUB: func_8002A670(); break; + case STATE_VICTORY_PALACE: func_8002A6C0(); break; + case STATE_POKEMON_LAB: func_8002EF44(); break; + case STATE_GB_TOWER: func_8002A728(); break; + case STATE_GYM_LEADER_CASTLE: func_8002AAA8(); break; + case STATE_BATTLE_NOW_1P: func_8002ADE8(1); break; + case STATE_BATTLE_NOW_2P: func_8002ADE8(2); break; + case STATE_BATTLE_FROM_EVENT: func_8002AF38(); break; + case STATE_STUBBED_DEBUG: func_800296E0(); break; + case STATE_FAST_BATTLE: func_8002B180(); break; + case STATE_KIDS_CLUB_TITLE: func_8002B24C(); break; + case STATE_FAST_N64_LOGO: func_8002B07C(); break; + // same as state 1: N64 Logo + Intro. + default: func_80029310(); break; + } + gLastGameState = state; + } +} diff --git a/src/C030.c b/src/C030.c index 82e6cd51..9b110f9e 100644 --- a/src/C030.c +++ b/src/C030.c @@ -23,6 +23,7 @@ void func_8000B430(long ms) { } } +// Is this a Sticker Station? s32 func_8000B4C4(void) { s32 i; s32 ret; @@ -31,6 +32,7 @@ s32 func_8000B4C4(void) { if (D_800697E0 == 0) { u8* buffer; osPfsIsPlug(&gSIEventMesgQueue, &sp2F); + // is controller 4 plugged in? (why?) if (sp2F & 8) { Cont_BlockEepromQueue(); for (buffer = D_800A82B0, i = 0; i < 32; i++) { diff --git a/src/main.c b/src/main.c index 978e50c5..940da1f5 100644 --- a/src/main.c +++ b/src/main.c @@ -5,7 +5,7 @@ #include "reset.h" #include "util.h" -extern void func_8002B330(); // thread 6 function +extern void Game_Thread(void *arg); // thread 6 function // entry .bss u8 D_8007ED80[0xF180 - 0xED80]; // unknown, start of .bss @@ -30,7 +30,7 @@ void Idle_ThreadEntry(UNUSED void* unused) { func_8000D564(); func_800019C8(); SoftReset_CreateThread(); - osCreateThread(&pThreads, 6, &func_8002B330, 0, &D_800818E0, 20); + osCreateThread(&pThreads, 6, &Game_Thread, 0, &D_800818E0, 20); osStartThread(&pThreads); osSetThreadPri(NULL, 0); diff --git a/yamls/us/rom.yaml b/yamls/us/rom.yaml index ba0392d5..19740190 100644 --- a/yamls/us/rom.yaml +++ b/yamls/us/rom.yaml @@ -386,6 +386,7 @@ - [0x7CD10, rodata, rom_rodata_7CD10] - [0x7CD40, rodata, rom_rodata_7CD40] - [0x7CEC0, rodata, rom_rodata_7CEC0] + - [0x7CED0, .rodata, 29BA0] - [0x7CFD0, rodata, rom_rodata_7CFD0] - [0x7D030, rodata, rom_rodata_7D030] - [0x7D040, rodata, rom_rodata_7D040]