#include "koopatlas/core.h" #include "koopatlas/camera.h" #include "koopatlas/player.h" extern "C" void LoadMapScene(); dScKoopatlas_c *dScKoopatlas_c::instance = 0; CREATE_STATE_E(dScKoopatlas_c, Limbo); CREATE_STATE(dScKoopatlas_c, ContinueWait); CREATE_STATE_E(dScKoopatlas_c, Normal); CREATE_STATE_E(dScKoopatlas_c, CSMenu); CREATE_STATE_E(dScKoopatlas_c, TitleConfirmOpenWait); CREATE_STATE_E(dScKoopatlas_c, TitleConfirmSelect); CREATE_STATE_E(dScKoopatlas_c, TitleConfirmHitWait); CREATE_STATE_E(dScKoopatlas_c, PlayerChangeWait); CREATE_STATE_E(dScKoopatlas_c, EasyPairingWait); CREATE_STATE_E(dScKoopatlas_c, PowerupsWait); CREATE_STATE_E(dScKoopatlas_c, ShopWait); CREATE_STATE_E(dScKoopatlas_c, CoinsWait); CREATE_STATE_E(dScKoopatlas_c, SaveOpen); CREATE_STATE_E(dScKoopatlas_c, SaveSelect); CREATE_STATE_E(dScKoopatlas_c, SaveWindowClose); CREATE_STATE_E(dScKoopatlas_c, SaveDo); CREATE_STATE_E(dScKoopatlas_c, SaveEndWindow); CREATE_STATE_E(dScKoopatlas_c, SaveEndCloseWait); CREATE_STATE_E(dScKoopatlas_c, QuickSaveOpen); CREATE_STATE_E(dScKoopatlas_c, QuickSaveSelect); CREATE_STATE_E(dScKoopatlas_c, QuickSaveWindowClose); CREATE_STATE_E(dScKoopatlas_c, QuickSaveDo); CREATE_STATE_E(dScKoopatlas_c, QuickSaveEndWindow); CREATE_STATE_E(dScKoopatlas_c, QuickSaveEndCloseWait); CREATE_STATE_E(dScKoopatlas_c, SaveError); dScKoopatlas_c *dScKoopatlas_c::build() { // return new dScKoopatlas_c; MapReport("Creating WorldMap\n"); void *buffer = AllocFromGameHeap1(sizeof(dScKoopatlas_c)); dScKoopatlas_c *c = new(buffer) dScKoopatlas_c; MapReport("Created WorldMap @ %p\n", c); instance = c; return c; } bool WMInit_StartLoading(void*); bool StockWMInit_LoadEffects(void*); bool WMInit_LoadSIAnims(void*); bool WMInit_EndLoading(void*); bool WMInit_LoadResources1(void*); bool WMInit_LoadResources2(void*); bool WMInit_SetupWait(void*); bool WMInit_SetupExtra(void*); bool WMInit_SetupWipe(void*); ChainedFunc initFunctions[] = { WMInit_StartLoading, StockWMInit_LoadEffects, WMInit_LoadSIAnims, WMInit_EndLoading, WMInit_LoadResources1, WMInit_LoadResources2, WMInit_SetupWait, WMInit_SetupExtra, WMInit_SetupWipe }; dScKoopatlas_c::dScKoopatlas_c() : state(this) { initChain.setup(initFunctions, 9); setInitChain(initChain); } #define SELC_SETUP_DONE(sc) (*((bool*)(((u32)(sc))+0xD38))) #define EASYP_SETUP_DONE(ep) (*((bool*)(((u32)(ep))+0x278))) #define EASYP_ACTIVE(ep) (*((bool*)(((u32)(ep))+0x279))) #define CSMENU_SETUP_DONE(csm) (*((bool*)(((u32)(csm))+0x270))) #define CSMENU_ACTIVE(csm) (*((bool*)(((u32)(csm))+0x271))) #define CSMENU_CHOICE_OK(csm) (*((bool*)(((u32)(csm))+0x272))) #define CSMENU_UNK(csm) (*((bool*)(((u32)(csm))+0x273))) #define CSMENU_CURRENT(csm) (*((int*)(((u32)(csm))+0x268))) #define YESNO_SETUP_DONE(ynw) (*((bool*)(((u32)(ynw))+0x294))) #define YESNO_VISIBLE(ynw) (*((bool*)(((u32)(ynw))+0x295))) #define YESNO_CLOSE(ynw) (*((bool*)(((u32)(ynw))+0x296))) #define YESNO_OPENING(ynw) (*((bool*)(((u32)(ynw))+0x297))) #define YESNO_REFUSED(ynw) (*((bool*)(((u32)(ynw))+0x298))) #define YESNO_CANCELLED(ynw) (*((bool*)(((u32)(ynw))+0x299))) #define YESNO_CANCELLED2(ynw) (*((bool*)(((u32)(ynw))+0x29A))) #define YESNO_CURRENT(ynw) (*((int*)(((u32)(ynw))+0x284))) #define YESNO_TYPE(ynw) (*((int*)(((u32)(ynw))+0x28C))) #define NPCHG_SETUP_DONE(npc) (*((bool*)(((u32)(npc))+0x67C))) #define NPCHG_ACTIVE(npc) (*((bool*)(((u32)(npc))+0x67E))) #define NPCHG_HIDE_FOR_EASYP(npc) (*((bool*)(((u32)(npc))+0x67F))) #define NPCHG_READY(npc) (*((bool*)(((u32)(npc))+0x680))) #define NPCHG_CCSB(npc,idx) (((void**)(((u32)(npc))+0x74))[(idx)]) #define NPCHG_CCSC(npc,idx) (((void**)(((u32)(npc))+0x84))[(idx)]) #define NPCHG_CCSA(npc,idx) (((void**)(((u32)(npc))+0x94))[(idx)]) #define NPCHG_CCI(npc,idx) (((void**)(((u32)(npc))+0xA4))[(idx)]) #define NPCHG_2DPLAYER(npc,idx) (((void**)(((u32)(npc))+0x64C))[(idx)]) #define STKI_SETUP_DONE(si) (*((bool*)(((u32)(si))+0x310))) #define STKI_SHADOW(si) (*((void**)(((u32)(si))+0x310))) #define STKI_2DPLAYER(si,idx) (((void**)(((u32)(si))+0x2E4))[(idx)]) #define STKI_ITEM(si,idx) (((void**)(((u32)(si))+0x2F4))[(idx)]) #define STKI_SHOW(si) (*((bool*)(((u32)(si))+0x8DD))) #define SIS_SETUP_DONE(sis) (*((bool*)(((u32)(sis))+0x260))) #define CCSB_ACTIVE(ccsb) (*((bool*)(((u32)(ccsb))+0x29C))) #define CCSC_ACTIVE(ccsc) (*((bool*)(((u32)(ccsc))+0x2A1))) #define PLAYER2D_SHOW_EASY_PAIRING(p2d) (*((bool*)(((u32)(p2d))+0x264))) #define CONT_LIVES(cont,idx) (((int*)(((u32)(cont))+0x2B8))[(idx)]) #define CONT_SETUP_DONE(cont) (*((bool*)(((u32)(cont))+0x2D4))) #define CONT_UNK1(cont) (*((bool*)(((u32)(cont))+0x2D5))) #define CONT_UNK2(cont) (*((bool*)(((u32)(cont))+0x2D6))) #define CONT_DONE(cont) (*((bool*)(((u32)(cont))+0x2D7))) #define CONT_UNK3(cont) (*((bool*)(((u32)(cont))+0x2E0))) bool WMInit_StartLoading(void *ptr) { SpammyReport("WMInit_StartLoading called\n"); DVD_Start(); return true; } bool WMInit_LoadSIAnims(void *ptr) { SpammyReport("WMInit_LoadSIAnims called\n"); DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_kinoko", 0); DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_fireflower", 0); DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_iceflower", 0); DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_penguin", 0); DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_propeller", 0); DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_star", 0); DVD_LoadFile(GetDVDClass(), "Object", "I_hammer", 0); DVD_LoadFile(GetDVDClass(), "Object", "cobCourse", 0); DVD_LoadFile(GetDVDClass(), "Object", "obj_coin", 0); DVD_LoadFile(GetDVDClass(), "Object", "I_kinoko", 0); DVD_LoadFile(GetDVDClass(), "Object", "I_fireflower", 0); DVD_LoadFile(GetDVDClass(), "Object", "I_iceflower", 0); DVD_LoadFile(GetDVDClass(), "Object", "I_penguin", 0); DVD_LoadFile(GetDVDClass(), "Object", "I_propeller", 0); DVD_LoadFile(GetDVDClass(), "Object", "I_star", 0); DVD_LoadFile(GetDVDClass(), "Object", "I_kinoko_bundle", 0); DVD_LoadFile(GetDVDClass(), "Object", "lakitu", 0); DVD_LoadFile(GetDVDClass(), "Object", "star_coin", 0); return true; } bool WMInit_EndLoading(void *ptr) { SpammyReport("WMInit_EndLoading called\n"); if (DVD_StillLoading(GetDVDClass2())) { SpammyReport("WMInit_EndLoading returning false\n"); return false; } DVD_End(); SpammyReport("WMInit_EndLoading returning true\n"); return true; } bool WMInit_LoadResources1(void *ptr) { SpammyReport("WMInit_LoadResources1 returning true\n"); dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr; return wm->mapListLoader.load("/Maps/List.txt"); } bool WMInit_LoadResources2(void *ptr) { SpammyReport("WMInit_LoadResources2 returning true\n"); dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr; if (wm->mapPath == 0) { wm->mapPath = wm->getMapNameForIndex(wm->currentMapID); if (wm->mapPath == 0) wm->mapPath = wm->getMapNameForIndex(0); OSReport("Load map: %s\n", wm->mapPath); } return wm->mapData.load(wm->mapPath); } bool WMInit_SetupWait(void *ptr) { SpammyReport("WMInit_SetupWait called\n"); dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr; bool success = true; success &= CSMENU_SETUP_DONE(wm->csMenu); success &= SELC_SETUP_DONE(wm->selectCursor); success &= NPCHG_SETUP_DONE(wm->numPeopleChange); success &= YESNO_SETUP_DONE(wm->yesNoWindow); success &= CONT_SETUP_DONE(wm->continueObj); success &= STKI_SETUP_DONE(wm->stockItem); success &= SIS_SETUP_DONE(wm->stockItemShadow); success &= EASYP_SETUP_DONE(wm->easyPairing); return success; } bool WMInit_SetupExtra(void *ptr) { SpammyReport("WMInit_SetupExtra called\n"); // ok, now we can set up other required shit dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr; // check if we need to handle Continue if (CheckIfContinueShouldBeActivated()) { SpammyReport("continue is activated\n"); wm->state.setState(&wm->StateID_ContinueWait); } else { SpammyReport("continue is not activated\n"); wm->state.setState(&wm->StateID_Normal); } // first up: player models for Stocked Items for (int i = 0; i < 4; i++) { void *obj = CreateChildObject(WM_2D_PLAYER, wm, i, 0, 0); STKI_2DPLAYER(wm->stockItem,i) = obj; NPCHG_2DPLAYER(wm->numPeopleChange,i) = obj; } // next: items for the Powerup screen for (int i = 0; i < 7; i++) { void *obj = CreateChildObject(WM_ITEM, wm, i, 0, 0); STKI_ITEM(wm->stockItem,i) = obj; } // need Player before we can set up paths SpammyReport("creating player\n"); wm->player = (daWMPlayer_c*)CreateParentedObject(WM_PLAYER, wm, 0, 2); wm->player->modelHandler->mdlClass->setPowerup(Player_Powerup[0]); wm->player->modelHandler->mdlClass->startAnimation(0, 1.2f, 10.0f, 0.0f); // since we've got all the resources, set up the path data too SpammyReport("preparing path manager\n"); wm->pathManager.setup(); // and put the player into position dKPNode_s *cNode = wm->pathManager.currentNode; wm->player->pos = (Vec){cNode->x, -cNode->y, wm->player->pos.z}; // is last param correct? must check :/ SpammyReport("creating MAP\n"); wm->map = (dWMMap_c*)CreateParentedObject(WM_MAP, wm, 0, 0); SpammyReport("creating HUD\n"); wm->hud = (dWMHud_c*)CreateParentedObject(WM_HUD, wm, 0, 0); // note: world_camera is not created here // because we require it earlier // it is created in dScKoopatlas_c::onCreate SpammyReport("creating SHOP\n"); wm->shop = (dWMShop_c*)CreateParentedObject(WM_SHOP, wm, 0, 0); SpammyReport("creating Star Coin Menu\n"); wm->coins = (dWMStarCoin_c*)CreateParentedObject(WM_STARCOIN, wm, 0, 0); SpammyReport("SetupExtra done\n"); return true; } bool WMInit_SetupWipe(void *ptr) { SpammyReport("WMInit_SetupWipe called\n"); dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr; if (wm->hasUninitialisedProcesses()) { SpammyReport("WMInit_SetupWipe returning false\n"); #ifdef WM_SPAMMY_DEBUGGING fBase_c *p = wm->findNextUninitialisedProcess(); SpammyReport("Not done yet: %p [%d]\n", p, p->name); #endif return false; } SpammyReport("WMInit_SetupWipe returning true\n"); wm->playBGM(); return true; } /*void dScKoopatlas_c::startLevel(LevelInfo::Entry *entry) { for (int i = 0; i < 4; i++) { bool isThere = QueryPlayerAvailability(i); int id = Player_ID[i]; Player_Active[i] = isThere ? 1 : 0; if (!isThere) Player_Flags[i] = 0; } StartLevelInfo sl; sl.unk1 = 0; sl.unk2 = 0xFF; sl.unk3 = 0; sl.unk4 = 0; sl.purpose = 0; sl.world1 = entry->world; sl.world2 = entry->world; sl.level1 = entry->level; sl.level2 = entry->level; // hopefully this will fix the Star Coin issues SetSomeConditionShit(entry->world, entry->level, 2); ActivateWipe(WIPE_MARIO); DoStartLevel(GetGameMgr(), &sl); }*/ int dScKoopatlas_c::onCreate() { OSReport("KP scene settings: %08x\n", settings); SpammyReport("onCreate() called\n"); SpammyReport("LoadMapScene()\n"); LoadMapScene(); SpammyReport("GameSetup__LoadScene(0)\n"); GameSetup__LoadScene(0); // lol, stolen from GAME_SETUP SpammyReport("Setting Active Players\n"); for (int i = 0; i < 4; i++) { bool isThere = QueryPlayerAvailability(i); int id = Player_ID[i]; Player_Active[i] = isThere ? 1 : 0; if (!isThere) Player_Flags[i] = 0; } SpammyReport("select cursor\n"); this->selectCursor = CreateParentedObject(SELECT_CURSOR, this, 0, 0); SpammyReport("cs menu\n"); this->csMenu = CreateParentedObject(COURSE_SELECT_MENU, this, 0, 0); SpammyReport("yes no window\n"); this->yesNoWindow = CreateParentedObject(YES_NO_WINDOW, this, 0, 0); SpammyReport("number of people change\n"); this->numPeopleChange = CreateParentedObject(NUMBER_OF_PEOPLE_CHANGE, this, 0, 0); for (int i = 0; i < 4; i++) { SpammyReport("ccsb %d\n", i); void *ccsb = CreateParentedObject(CHARACTER_CHANGE_SELECT_BASE, this, i, 0); SpammyReport("ccsc %d\n", i); void *ccsc = CreateParentedObject(CHARACTER_CHANGE_SELECT_CONTENTS, this, i, 0); SpammyReport("ccsa %d\n", i); void *ccsa = CreateParentedObject(CHARACTER_CHANGE_SELECT_ARROW, this, i, 0); SpammyReport("ccsi %d\n", i); void *cci = CreateParentedObject(CHARACTER_CHANGE_INDICATOR, this, i, 0); NPCHG_CCSB(this->numPeopleChange, i) = ccsb; NPCHG_CCSC(this->numPeopleChange, i) = ccsc; NPCHG_CCSA(this->numPeopleChange, i) = ccsa; NPCHG_CCI(this->numPeopleChange, i) = cci; } SpammyReport("continue\n"); this->continueObj = CreateParentedObject(CONTINUE, this, 0, 0); SpammyReport("stock item\n"); this->stockItem = CreateParentedObject(STOCK_ITEM, this, 0, 0); SpammyReport("stock item shadow\n"); this->stockItemShadow = CreateParentedObject(STOCK_ITEM_SHADOW, this, 0, 0); STKI_SHADOW(this->stockItem) = this->stockItemShadow; SpammyReport("easy pairing\n"); this->easyPairing = CreateParentedObject(EASY_PAIRING, this, 0, 0); SpammyReport("world camera\n"); CreateParentedObject(WORLD_CAMERA, this, 0, 0); SpammyReport("setting NewerMapDrawFunc\n"); *CurrentDrawFunc = NewerMapDrawFunc; SpammyReport("onCreate() completed\n"); // Prepare this first SaveBlock *save = GetSaveFile()->GetBlock(-1); currentMapID = save->current_world; somethingAboutSound(_8042A788); return true; } u8 hijackMusicWithSongName(const char *songName, int themeID, bool hasFast, bool useDrums, int *wantRealStreamID); extern "C" void PlaySoundWithFunctionB4(void *spc, nw4r::snd::SoundHandle *handle, int id, int unk); void dScKoopatlas_c::playBGM() { char cleanName[40]; // find the end const char *mapPathEnd = mapPath; while (*mapPathEnd) mapPathEnd++; // it now points to the zero const char *findSlash = mapPathEnd; while (findSlash > mapPath && *findSlash != '/') findSlash--; // it now points to the slash strcpy(cleanName, "Map_"); strncpy(&cleanName[4], findSlash+1, 36); // nuke everything up to the point for (int i = 4; i < 40; i++) if (cleanName[i] == '.') cleanName[i] = 0; int realStreamID; OSReport("I'm going to play %s!\n", cleanName); hijackMusicWithSongName(cleanName, -1, false, false, &realStreamID); OSReport("Real Stream ID: %d\n", realStreamID); PlaySoundWithFunctionB4(SoundRelatedClass, &bgm, realStreamID, 1); currentBGMTrack = GetSaveFile()->GetBlock(-1)->currentMapMusic; bgm.SetTrackVolume(0xFF ^ (1 << currentBGMTrack), 0, 0.0f); bgm.SetTrackVolume(1 << currentBGMTrack, 0, 1.0f); } void dScKoopatlas_c::setBGMTrack(int trackID) { if (currentBGMTrack == trackID) return; bgm.SetTrackVolume(1 << currentBGMTrack, 30, 0.0f); bgm.SetTrackVolume(1 << trackID, 30, 1.0f); currentBGMTrack = trackID; } int dScKoopatlas_c::onDelete() { if (bgm.Exists()) bgm.Stop(0); FreeScene(0); FreeScene(1); CleanUpEffectThings(); FreeEffects(1); FreeBreff(1); FreeBreft(1); DVD_FreeFile(GetDVDClass2(), "SI_kinoko"); DVD_FreeFile(GetDVDClass2(), "SI_fireflower"); DVD_FreeFile(GetDVDClass2(), "SI_iceflower"); DVD_FreeFile(GetDVDClass2(), "SI_penguin"); DVD_FreeFile(GetDVDClass2(), "SI_propeller"); DVD_FreeFile(GetDVDClass2(), "SI_star"); mapListLoader.unload(); CleanUpEffectThings(); return true; } bool dScKoopatlas_c::canDoStuff() { if (QueryGlobal5758(0xFFFFFFFF)) return false; if (CheckIfWeCantDoStuff()) return false; if (state.getCurrentState() == &StateID_Limbo) return false; return true; } bool dScKoopatlas_c::mapIsRunning() { if (QueryGlobal5758(0xFFFFFFFF)) return false; if (CheckIfWeCantDoStuff()) return false; if (state.getCurrentState() != &StateID_Normal) return false; return true; } int dScKoopatlas_c::onExecute() { if (!canDoStuff()) return true; //SpammyReport("Executing state: %s\n", state.getCurrentState()->getName()); state.execute(); return true; } void dScKoopatlas_c::executeState_Limbo() { } void dScKoopatlas_c::beginState_ContinueWait() { GameMgrP->_AFC = 1; CONT_UNK1(this->continueObj) = true; CONT_UNK2(this->continueObj) = true; CONT_UNK3(this->continueObj) = false; } void dScKoopatlas_c::executeState_ContinueWait() { // Waiting for the Continue anim to finish if (CONT_DONE(this->continueObj)) { CONT_UNK1(this->continueObj) = 0; CONT_UNK2(this->continueObj) = 0; CONT_UNK3(this->continueObj) = 0; for (int i = 0; i < 4; i++) { int idx = SearchForIndexOfPlayerID(i); Player_Lives[Player_ID[idx]] = CONT_LIVES(this->continueObj, i); } state.setState(&StateID_Normal); } } void dScKoopatlas_c::endState_ContinueWait() { GameMgrP->_AFC = 0; } void dScKoopatlas_c::executeState_Normal() { int nowPressed = Remocon_GetPressed(GetActiveRemocon()); // Nothing related to the menu is going on if (nowPressed & WPAD_ONE && !pathManager.isEnteringLevel) { STKI_SHOW(this->stockItem) = true; state.setState(&StateID_PowerupsWait); } else if (nowPressed & WPAD_PLUS && !pathManager.isEnteringLevel) { CSMENU_ACTIVE(this->csMenu) = true; state.setState(&StateID_CSMenu); // } else if (nowPressed & WPAD_A) { // if (pathManager.currentNode->type == dKPNode_s::LEVEL) { // int w = pathManager.currentNode->levelNumber[0]; // if (w == 9) { // int l = pathManager.currentNode->levelNumber[1]; // if ((l < 6) || (l == 33) || (l == 34)) // coins->LoadCoinsForWorld(9); // else if ((l < 11) || (l == 35) || (l == 36)) // coins->LoadCoinsForWorld(10); // else if ((l < 16) || (l == 37) || (l == 38) || (l == 31) ) // coins->LoadCoinsForWorld(11); // else if ((l < 19) || (l == 39) || (l == 40)) // coins->LoadCoinsForWorld(12); // else // coins->LoadCoinsForWorld(13); // state.setState(&StateID_CoinsWait); // } // else { // coins->LoadCoinsForWorld(w-1); // state.setState(&StateID_CoinsWait); // } // } // else { // MapSoundPlayer(SoundRelatedClass, SE_SYS_INVALID, 1); // } } else if (nowPressed & WPAD_MINUS) { pathManager.unlockAllPaths(2); } else if (nowPressed & WPAD_A) { pathManager.unlockAllPaths(0); } } void dScKoopatlas_c::executeState_CSMenu() { // The course select menu is currently being shown // First off, check to see if it's been hidden if (!CSMENU_ACTIVE(this->csMenu)) { // That means something happened if (CSMENU_CHOICE_OK(this->csMenu)) { // Player pressed a button SaveBlock *save = GetSaveFile()->GetBlock(-1); switch (CSMENU_CURRENT(this->csMenu)) { case 0: // Star Coins // if (pathManager.currentNode->type == dKPNode_s::LEVEL) { // int w = pathManager.currentNode->levelNumber[0]; // if (w == 9) { // int l = pathManager.currentNode->levelNumber[1]; // // if ((l < 6) || (l == 33) || (l == 34)) // coins->LoadCoinsForWorld(9); // else if ((l < 11) || (l == 35) || (l == 36)) // coins->LoadCoinsForWorld(10); // else if ((l < 16) || (l == 37) || (l == 38) || (l == 31) ) // coins->LoadCoinsForWorld(11); // else if ((l < 19) || (l == 39) || (l == 40)) // coins->LoadCoinsForWorld(12); // else // coins->LoadCoinsForWorld(13); // // state.setState(&StateID_CoinsWait); // } // else { // coins->LoadCoinsForWorld(w-1); // } // } // else { MapSoundPlayer(SoundRelatedClass, SE_SYS_INVALID, 1); } coins->show(); state.setState(&StateID_CoinsWait); break; case 1: // Add/Drop Players MapReport("Add/Drop Players was pressed\n"); state.setState(&StateID_PlayerChangeWait); NPCHG_ACTIVE(this->numPeopleChange) = true; WpadShit(10); break; case 2: // Save or Quick Save MapReport("Save or Quick Save was pressed\n"); if (GetSaveFile()->GetBlock(-1)->bitfield & 2) { state.setState(&StateID_SaveOpen); YESNO_TYPE(this->yesNoWindow) = 1; YESNO_VISIBLE(this->yesNoWindow) = 1; } else { state.setState(&StateID_QuickSaveOpen); YESNO_TYPE(this->yesNoWindow) = 15; YESNO_VISIBLE(this->yesNoWindow) = 1; } break; case 3: // Title Screen MapReport("Title Screen was pressed\n"); state.setState(&StateID_TitleConfirmOpenWait); YESNO_VISIBLE(this->yesNoWindow) = true; YESNO_TYPE(this->yesNoWindow) = 10; break; } } else { // Ok, change back to STATE_Normal state.setState(&StateID_Normal); } } } void dScKoopatlas_c::executeState_TitleConfirmOpenWait() { // Waiting for the "Go to Title Screen" YesNoWindow to finish opening if (!YESNO_OPENING(this->yesNoWindow)) { state.setState(&StateID_TitleConfirmSelect); } } /**********************************************************************/ // STATE_TitleConfirmSelect : Let the user choose an option on the // "Go to Title Screen" YesNoWindow. void dScKoopatlas_c::executeState_TitleConfirmSelect() { int nowPressed = Remocon_GetPressed(GetActiveRemocon()); if (nowPressed & WPAD_LEFT) { // Select "OK!" YESNO_CURRENT(this->yesNoWindow) = 1; } else if (nowPressed & WPAD_RIGHT) { // Select "Cancel" YESNO_CURRENT(this->yesNoWindow) = 0; } else if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) { // Pick the current option YESNO_CLOSE(this->yesNoWindow) = true; if (YESNO_CURRENT(this->yesNoWindow) != 1) YESNO_REFUSED(this->yesNoWindow) = true; state.setState(&StateID_TitleConfirmHitWait); } else { // Cancel using B or 1 if (CheckIfMenuShouldBeCancelledForSpecifiedWiimote(0)) { YESNO_CANCELLED(this->yesNoWindow) = true; YESNO_CURRENT(this->yesNoWindow) = true; state.setState(&StateID_TitleConfirmHitWait); } } } /**********************************************************************/ // STATE_TitleConfirmHitWait : Process the user's chosen option on // the "Go to Title Screen" YesNoWindow. Also, wait for the // animation to be complete. void dScKoopatlas_c::executeState_TitleConfirmHitWait() { if (!YESNO_OPENING(this->yesNoWindow)) { if (YESNO_CURRENT(this->yesNoWindow) == 1) { state.setState(&StateID_Normal); } else { state.setState(&StateID_Limbo); StartTitleScreenStage(false, 0); } } } /**********************************************************************/ // STATE_PlayerChangeWait : Wait for the user to do something on the // Add/Drop Players screen. void dScKoopatlas_c::executeState_PlayerChangeWait() { int nowPressed = Remocon_GetPressed(GetActiveRemocon()); if (NPCHG_READY(this->numPeopleChange)) { if (nowPressed & WPAD_PLUS) { // activate easy pairing. FUN !! NPCHG_HIDE_FOR_EASYP(this->numPeopleChange) = 1; for (int i = 0; i < 4; i++) { void *obj = NPCHG_2DPLAYER(this->numPeopleChange, i); void *ccsb = NPCHG_CCSB(this->numPeopleChange, i); void *ccsc = NPCHG_CCSC(this->numPeopleChange, i); PLAYER2D_SHOW_EASY_PAIRING(obj) = 1; CCSB_ACTIVE(ccsb) = 1; CCSC_ACTIVE(ccsc) = 1; } EASYP_ACTIVE(this->easyPairing) = 1; state.setState(&StateID_EasyPairingWait); } } else { if (!NPCHG_ACTIVE(this->numPeopleChange)) { for (int i = 0; i < 4; i++) { bool isThere = QueryPlayerAvailability(i); int id = Player_ID[i]; Player_Active[i] = isThere ? 1 : 0; if (!isThere) Player_Flags[i] = 0; } state.setState(&StateID_Normal); } } } /**********************************************************************/ // STATE_EasyPairingWait : Wait for the user to exit Easy Pairing. void dScKoopatlas_c::executeState_EasyPairingWait() { if (!EASYP_ACTIVE(this->easyPairing)) { NPCHG_HIDE_FOR_EASYP(this->numPeopleChange) = 0; for (int i = 0; i < 4; i++) { void *obj = NPCHG_2DPLAYER(this->numPeopleChange, i); void *ccsb = NPCHG_CCSB(this->numPeopleChange, i); void *ccsc = NPCHG_CCSC(this->numPeopleChange, i); PLAYER2D_SHOW_EASY_PAIRING(obj) = 0; CCSB_ACTIVE(ccsb) = 0; CCSC_ACTIVE(ccsc) = 0; } state.setState(&StateID_PlayerChangeWait); WpadShit(10); } } /**********************************************************************/ // STATE_PowerupsWait : Wait for the user to exit the Powerups screen. void dScKoopatlas_c::executeState_PowerupsWait() { if (!STKI_SHOW(this->stockItem)) { dScKoopatlas_c::instance->player->modelHandler->mdlClass->setPowerup(Player_Powerup[0]); state.setState(&StateID_Normal); } } /**********************************************************************/ // STATE_ShopWait : Wait for the user to exit the Shop screen. void dScKoopatlas_c::executeState_ShopWait() { if (shop->isHidden) { state.setState(&StateID_Normal); } } /**********************************************************************/ // STATE_StarCoin : Wait for the user to exit the Star Coin screen. void dScKoopatlas_c::executeState_CoinsWait() { if (!coins->visible) { state.setState(&StateID_Normal); } } /**********************************************************************/ // STATE_SaveOpen : Waiting for the "Save?" YesNoWindow to open void dScKoopatlas_c::executeState_SaveOpen() { if (!YESNO_OPENING(this->yesNoWindow)) { state.setState(&StateID_SaveSelect); } } /**********************************************************************/ // STATE_SaveSelect : Let the user choose an option on the // "Save?" YesNoWindow. void dScKoopatlas_c::executeState_SaveSelect() { int nowPressed = Remocon_GetPressed(GetActiveRemocon()); if (nowPressed & WPAD_LEFT) { // Select "OK!" YESNO_CURRENT(this->yesNoWindow) = 1; } else if (nowPressed & WPAD_RIGHT) { // Select "Cancel" YESNO_CURRENT(this->yesNoWindow) = 0; } else if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) { // Pick the current option YESNO_CLOSE(this->yesNoWindow) = true; if (YESNO_CURRENT(this->yesNoWindow) != 1) YESNO_CANCELLED2(this->yesNoWindow) = true; state.setState(&StateID_SaveWindowClose); } else { // Cancel using B or 1 if (CheckIfMenuShouldBeCancelledForSpecifiedWiimote(0)) { YESNO_CANCELLED(this->yesNoWindow) = true; YESNO_CURRENT(this->yesNoWindow) = 1; state.setState(&StateID_SaveWindowClose); } } } /**********************************************************************/ // STATE_SaveWindowClose : Process the user's chosen option on the // "Save?" YesNoWindow. Also, wait for the animation to be complete. void dScKoopatlas_c::executeState_SaveWindowClose() { if (!YESNO_VISIBLE(this->yesNoWindow)) { if (YESNO_CURRENT(this->yesNoWindow) == 1) { state.setState(&StateID_Normal); } else { state.setState(&StateID_SaveDo); SaveGame(0, false); } } } /**********************************************************************/ // STATE_SaveDo : Save the game. void dScKoopatlas_c::executeState_SaveDo() { if (!GetSaveFile()->CheckIfWriting()) { if (GetSaveHandler()->CurrentError == 0) { YESNO_TYPE(this->yesNoWindow) = 2; YESNO_VISIBLE(this->yesNoWindow) = true; state.setState(&StateID_SaveEndWindow); } else { state.setState(&StateID_SaveError); } } } /**********************************************************************/ // STATE_SaveEndWindow : Handle the Save End window. void dScKoopatlas_c::executeState_SaveEndWindow() { if (!YESNO_OPENING(this->yesNoWindow)) { if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) { YESNO_CLOSE(this->yesNoWindow) = true; state.setState(&StateID_SaveEndCloseWait); } } } /**********************************************************************/ // STATE_SaveEndCloseWait : Wait for the Save End window to close. void dScKoopatlas_c::executeState_SaveEndCloseWait() { if (!YESNO_OPENING(this->yesNoWindow)) { state.setState(&StateID_Normal); } } /**********************************************************************/ // STATE_QuickSaveOpen : Waiting for the "Save?" YesNoWindow to open void dScKoopatlas_c::executeState_QuickSaveOpen() { if (!YESNO_OPENING(this->yesNoWindow)) { state.setState(&StateID_QuickSaveSelect); } } /**********************************************************************/ // STATE_QuickSaveSelect : Let the user choose an option on the // "Save?" YesNoWindow. void dScKoopatlas_c::executeState_QuickSaveSelect() { int nowPressed = Remocon_GetPressed(GetActiveRemocon()); if (nowPressed & WPAD_LEFT) { // Select "OK!" YESNO_CURRENT(this->yesNoWindow) = 1; } else if (nowPressed & WPAD_RIGHT) { // Select "Cancel" YESNO_CURRENT(this->yesNoWindow) = 0; } else if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) { // Pick the current option YESNO_CLOSE(this->yesNoWindow) = true; if (YESNO_CURRENT(this->yesNoWindow) != 1) YESNO_CANCELLED2(this->yesNoWindow) = true; state.setState(&StateID_QuickSaveWindowClose); } else { // Cancel using B or 1 if (CheckIfMenuShouldBeCancelledForSpecifiedWiimote(0)) { YESNO_CANCELLED(this->yesNoWindow) = true; YESNO_CURRENT(this->yesNoWindow) = 1; state.setState(&StateID_QuickSaveWindowClose); } } } /**********************************************************************/ // STATE_QuickSaveWindowClose : Process the user's chosen option on // the "Save?" YesNoWindow. Also, wait for the animation to be complete void dScKoopatlas_c::executeState_QuickSaveWindowClose() { if (!YESNO_VISIBLE(this->yesNoWindow)) { if (YESNO_CURRENT(this->yesNoWindow) == 1) { state.setState(&StateID_Normal); } else { state.setState(&StateID_QuickSaveDo); SaveGame(0, true); } } } /**********************************************************************/ // STATE_QuickSaveDo : Save the game. void dScKoopatlas_c::executeState_QuickSaveDo() { if (!GetSaveFile()->CheckIfWriting()) { if (GetSaveHandler()->CurrentError == 0) { YESNO_TYPE(this->yesNoWindow) = 16; YESNO_VISIBLE(this->yesNoWindow) = true; state.setState(&StateID_QuickSaveEndWindow); } else { state.setState(&StateID_SaveError); } } } // STATE_QuickSaveEndWindow : Handle the Save End window. void dScKoopatlas_c::executeState_QuickSaveEndWindow() { if (!YESNO_OPENING(this->yesNoWindow)) { if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) { YESNO_CLOSE(this->yesNoWindow) = true; YESNO_REFUSED(this->yesNoWindow) = true; state.setState(&StateID_QuickSaveEndCloseWait); } } } void dScKoopatlas_c::executeState_QuickSaveEndCloseWait() { // Wait for Save End window to close if (!YESNO_OPENING(this->yesNoWindow)) { if (YESNO_CURRENT(this->yesNoWindow) == 1) { state.setState(&StateID_Normal); } else { state.setState(&StateID_Limbo); StartTitleScreenStage(false, 0); } } } void dScKoopatlas_c::executeState_SaveError() { } void dScKoopatlas_c::startLevel(dLevelInfo_c::entry_s *entry) { StartLevelInfo sl; sl.unk1 = 0; sl.unk2 = 0xFF; sl.unk3 = 0; sl.unk4 = 0; sl.purpose = 0; sl.world1 = entry->worldSlot; sl.world2 = entry->worldSlot; sl.level1 = entry->levelSlot; sl.level2 = entry->levelSlot; ActivateWipe(WIPE_MARIO); DoStartLevel(GetGameMgr(), &sl); } u32 dScKoopatlas_c::iterateMapList(u32(*callback)(u32,const char *,int,int), u32 userData, int *ptrIndex) { u8 *ptr = (u8*)mapListLoader.buffer; u8 *strStart = ptr; u8 *end = ptr + mapListLoader.size; int index = 0; while (true) { u8 chr = *ptr; if (chr == 13) { *ptr = 0; ++ptr; continue; } if (chr == 10 || chr == 0 || ptr >= end) { if (strStart == ptr) { // Blank string, ignore ++strStart; ++ptr; continue; } // Change the linefeed to a NUL so we can use the line as a C string later if (ptr < end) *ptr = 0; u32 ret = callback(userData, (const char*)strStart, ptr - strStart, index); if (ptrIndex) *ptrIndex = index; if (ret > 0) return ret; strStart = ++ptr; ++index; if (ptr >= end) break; } else { ++ptr; } } return 0; } static u32 _cb_getIndex(u32 userData, const char *str, int size, int index) { if (index == userData) return (u32)str; else return 0; } static u32 _cb_searchName(u32 userData, const char *str, int size, int index) { if (strncmp(str, (const char*)userData, size) == 0) return (u32)(index+1); else return 0; } const char *dScKoopatlas_c::getMapNameForIndex(int index) { return (const char *)iterateMapList(&_cb_getIndex, (u32)index, 0); } int dScKoopatlas_c::getIndexForMapName(const char *name) { return ((int)iterateMapList(&_cb_searchName, (u32)name, 0)) - 1; } void dScKoopatlas_c::showSaveWindow() { state.setState(&StateID_SaveOpen); YESNO_TYPE(yesNoWindow) = 1; YESNO_VISIBLE(yesNoWindow) = 1; } void NewerMapDrawFunc() { Reset3DState(); SetCurrentCameraID(0); DoSomethingCameraRelatedWithEGGScreen(0, &dWorldCamera_c::instance->screen); LinkScene(0); SceneCalcWorld(0); SceneCameraStuff(0); ChangeAlphaUpdate(false); DrawOpa(); DrawXlu(); UnlinkScene(0); // Something SetupLYTDrawing(); DrawAllLayoutsBeforeX(0x81); RenderEffects(0, 3); RenderEffects(0, 2); GXDrawDone(); RemoveAllFromScnRoot(); Reset3DState(); SetCurrentCameraID(1); DoSpecialDrawing1(); LinkScene(1); SceneCalcWorld(1); SceneCameraStuff(1); CalcMaterial(); DrawOpa(); DrawXlu(); UnlinkScene(1); SetCurrentCameraID(0); for (int i = 0; i < 4; i++) RenderEffects(0, 0xB+i); for (int i = 0; i < 4; i++) RenderEffects(0, 7+i); GXDrawDone(); // Leaving out some stuff here DrawAllLayoutsAfterX(0x80); ClearLayoutDrawList(); SetCurrentCameraID(0); }