diff --git a/src/engine/level_script.c b/src/engine/level_script.c index 9a2a94c3..cd5f2047 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -57,6 +57,8 @@ static struct LevelCommand *sCurrentCmd; static struct MemoryPool *sMemPoolForGoddard; +bool mario_loaded = false; + static s32 eval_script_op(s8 op, s32 arg) { s32 result = 0; @@ -421,6 +423,8 @@ static void level_cmd_init_mario(void) { gMarioSpawnInfo->unk18 = get_graph_node(model); gMarioSpawnInfo->next = NULL; + mario_loaded = true; + sCurrentCmd = CMD_NEXT; } diff --git a/src/engine/level_script.h b/src/engine/level_script.h index d41a91c8..d1bd4f37 100644 --- a/src/engine/level_script.h +++ b/src/engine/level_script.h @@ -2,6 +2,7 @@ #define LEVEL_SCRIPT_H #include +#include struct LevelCommand; @@ -9,4 +10,6 @@ extern u8 level_script_entry[]; struct LevelCommand *level_script_execute(struct LevelCommand *cmd); +extern bool mario_loaded; + #endif // LEVEL_SCRIPT_H diff --git a/src/game/level_update.h b/src/game/level_update.h index ecf9c3a3..3c71e1af 100644 --- a/src/game/level_update.h +++ b/src/game/level_update.h @@ -119,6 +119,7 @@ enum HUDDisplayFlag { u16 level_control_timer(s32 timerOp); void fade_into_special_warp(u32 arg, u32 color); +void initiate_warp(s16 destLevel, s16 destArea, s16 destWarpNode, s32 arg3); void load_level_init_text(u32 arg); s16 level_trigger_warp(struct MarioState *m, s32 warpOp); void level_set_transition(s16 length, void (*updateFunction)(s16 *)); diff --git a/src/game/mario.c b/src/game/mario.c index 41dc4a56..8a256404 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -35,6 +35,7 @@ #include "thread6.h" #include "pc/configfile.h" #include "pc/cheats.h" +#include "moon/saturn/saturn_types.h" #ifdef BETTERCAMERA #include "bettercamera.h" #endif @@ -1544,6 +1545,9 @@ void update_mario_health(struct MarioState *m) { gRumblePakTimer = 0; } } + if (enable_god) { + m->health = 0x880; + } } /** diff --git a/src/game/save_file.c b/src/game/save_file.c index 95618742..9470e893 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -17,8 +17,6 @@ #define MENU_DATA_MAGIC 0x4849 #define SAVE_FILE_MAGIC 0x4441 -STATIC_ASSERT(sizeof(struct SaveBuffer) == EEPROM_SIZE, "eeprom buffer size must match"); - extern struct SaveBuffer gSaveBuffer; struct WarpCheckpoint gWarpCheckpoint; @@ -46,207 +44,6 @@ s8 gLevelToCourseNumTable[] = { STATIC_ASSERT(ARRAY_COUNT(gLevelToCourseNumTable) == LEVEL_COUNT - 1, "change this array if you are adding levels"); -// This was probably used to set progress to 100% for debugging, but -// it was removed from the release ROM. -static void stub_save_file_1(void) { - UNUSED s32 pad; -} - -/** - * Byteswap all multibyte fields in a SaveBlockSignature. - */ -static inline void bswap_signature(struct SaveBlockSignature *data) { - data->magic = BSWAP16(data->magic); - data->chksum = BSWAP16(data->chksum); // valid as long as the checksum is a literal sum -} - -/** - * Byteswap all multibyte fields in a MainMenuSaveData. - */ -static inline void bswap_menudata(struct MainMenuSaveData *data) { - for (int i = 0; i < NUM_SAVE_FILES; ++i) - data->coinScoreAges[i] = BSWAP32(data->coinScoreAges[i]); - data->soundMode = BSWAP16(data->soundMode); -#ifdef VERSION_EU - data->language = BSWAP16(data->language); -#endif - bswap_signature(&data->signature); -} - -/** - * Byteswap all multibyte fields in a SaveFile. - */ -static inline void bswap_savefile(struct SaveFile *data) { - data->capPos[0] = BSWAP16(data->capPos[0]); - data->capPos[1] = BSWAP16(data->capPos[1]); - data->capPos[2] = BSWAP16(data->capPos[2]); - data->flags = BSWAP32(data->flags); - bswap_signature(&data->signature); -} - -/** - * Read from EEPROM to a given address. - * The EEPROM address is computed using the offset of the destination address from gSaveBuffer. - * Try at most 4 times, and return 0 on success. On failure, return the status returned from - * osEepromLongRead. It also returns 0 if EEPROM isn't loaded correctly in the system. - */ -static s32 read_eeprom_data(void *buffer, s32 size) { - s32 status = 0; - - if (gEepromProbe != 0) { - s32 triesLeft = 4; - u32 offset = (u32)((u8 *) buffer - (u8 *) &gSaveBuffer) / 8; - - do { - block_until_rumble_pak_free(); - triesLeft--; - status = osEepromLongRead(&gSIEventMesgQueue, offset, buffer, size); - release_rumble_pak_control(); - } while (triesLeft > 0 && status != 0); - } - - return status; -} - -/** - * Write data to EEPROM. - * The EEPROM address was originally computed using the offset of the source address from gSaveBuffer. - * Try at most 4 times, and return 0 on success. On failure, return the status returned from - * osEepromLongWrite. Unlike read_eeprom_data, return 1 if EEPROM isn't loaded. - */ -static s32 write_eeprom_data(void *buffer, s32 size, const uintptr_t baseofs) { - s32 status = 1; - - if (gEepromProbe != 0) { - s32 triesLeft = 4; - u32 offset = (u32)baseofs >> 3; - - do { - block_until_rumble_pak_free(); - triesLeft--; - status = osEepromLongWrite(&gSIEventMesgQueue, offset, buffer, size); - release_rumble_pak_control(); - } while (triesLeft > 0 && status != 0); - } - - return status; -} - -/** - * Wrappers that byteswap the data on LE platforms before writing it to 'EEPROM' - */ - -static inline s32 write_eeprom_savefile(const u32 file, const u32 slot, const u32 num) { - // calculate the EEPROM address using the file number and slot - const uintptr_t ofs = (u8*)&gSaveBuffer.files[file][slot] - (u8*)&gSaveBuffer; - -#if IS_BIG_ENDIAN - return write_eeprom_data(&gSaveBuffer.files[file][slot], num * sizeof(struct SaveFile), ofs); -#else - // byteswap the data and then write it - struct SaveFile sf[num]; - bcopy(&gSaveBuffer.files[file][slot], sf, num * sizeof(sf[0])); - for (u32 i = 0; i < num; ++i) bswap_savefile(&sf[i]); - return write_eeprom_data(&sf, sizeof(sf), ofs); -#endif -} - -static inline s32 write_eeprom_menudata(const u32 slot, const u32 num) { - // calculate the EEPROM address using the slot - const uintptr_t ofs = (u8*)&gSaveBuffer.menuData[slot] - (u8*)&gSaveBuffer; - -#if IS_BIG_ENDIAN - return write_eeprom_data(&gSaveBuffer.menuData[slot], num * sizeof(struct MainMenuSaveData), ofs); -#else - // byteswap the data and then write it - struct MainMenuSaveData md[num]; - bcopy(&gSaveBuffer.menuData[slot], md, num * sizeof(md[0])); - for (u32 i = 0; i < num; ++i) bswap_menudata(&md[i]); - return write_eeprom_data(&md, sizeof(md), ofs); -#endif -} - -/** - * Sum the bytes in data to data + size - 2. The last two bytes are ignored - * because that is where the checksum is stored. - */ -static u16 calc_checksum(u8 *data, s32 size) { - u16 chksum = 0; - - while (size-- > 2) { - chksum += *data++; - } - return chksum; -} - -/** - * Verify the signature at the end of the block to check if the data is valid. - */ -static s32 verify_save_block_signature(void *buffer, s32 size, u16 magic) { - struct SaveBlockSignature *sig = (struct SaveBlockSignature *) ((size - 4) + (u8 *) buffer); - - if (sig->magic != magic) { - return FALSE; - } - if (sig->chksum != calc_checksum(buffer, size)) { - return FALSE; - } - return TRUE; -} - -/** - * Write a signature at the end of the block to make sure the data is valid - */ -static void add_save_block_signature(void *buffer, s32 size, u16 magic) { - struct SaveBlockSignature *sig = (struct SaveBlockSignature *) ((size - 4) + (u8 *) buffer); - - sig->magic = magic; - sig->chksum = calc_checksum(buffer, size); -} - -/** - * Copy main menu data from one backup slot to the other slot. - */ -static void restore_main_menu_data(s32 srcSlot) { - s32 destSlot = srcSlot ^ 1; - - // Compute checksum on source data - add_save_block_signature(&gSaveBuffer.menuData[srcSlot], sizeof(gSaveBuffer.menuData[srcSlot]), MENU_DATA_MAGIC); - - // Copy source data to destination - bcopy(&gSaveBuffer.menuData[srcSlot], &gSaveBuffer.menuData[destSlot], sizeof(gSaveBuffer.menuData[destSlot])); - - // Write destination data to EEPROM - write_eeprom_menudata(destSlot, 1); -} - -static void save_main_menu_data(void) { - if (gMainMenuDataModified) { - // Compute checksum - add_save_block_signature(&gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0]), MENU_DATA_MAGIC); - - // Back up data - bcopy(&gSaveBuffer.menuData[0], &gSaveBuffer.menuData[1], sizeof(gSaveBuffer.menuData[1])); - - // Write to EEPROM - write_eeprom_menudata(0, 2); - - gMainMenuDataModified = FALSE; - } -} - -static void wipe_main_menu_data(void) { - bzero(&gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0])); - - // Set score ages for all courses to 3, 2, 1, and 0, respectively. - gSaveBuffer.menuData[0].coinScoreAges[0] = 0x3FFFFFFF; - gSaveBuffer.menuData[0].coinScoreAges[1] = 0x2AAAAAAA; - gSaveBuffer.menuData[0].coinScoreAges[2] = 0x15555555; - - gMainMenuDataModified = TRUE; - save_main_menu_data(); -} - static s32 get_coin_score_age(s32 fileIndex, s32 courseIndex) { return (gSaveBuffer.menuData[0].coinScoreAges[fileIndex] >> (2 * courseIndex)) & 0x3; } @@ -290,52 +87,6 @@ static void touch_high_score_ages(s32 fileIndex) { } } -/** - * Copy save file data from one backup slot to the other slot. - */ -static void restore_save_file_data(s32 fileIndex, s32 srcSlot) { - s32 destSlot = srcSlot ^ 1; - - // Compute checksum on source data - add_save_block_signature(&gSaveBuffer.files[fileIndex][srcSlot], - sizeof(gSaveBuffer.files[fileIndex][srcSlot]), SAVE_FILE_MAGIC); - - // Copy source data to destination slot - bcopy(&gSaveBuffer.files[fileIndex][srcSlot], &gSaveBuffer.files[fileIndex][destSlot], - sizeof(gSaveBuffer.files[fileIndex][destSlot])); - - // Write destination data to EEPROM - write_eeprom_savefile(fileIndex, destSlot, 1); -} - -/** - * Check if the 'EEPROM' save has different endianness (e.g. it's from an actual N64). - */ -static u8 save_file_need_bswap(const struct SaveBuffer *buf) { - // check all signatures just in case - for (int i = 0; i < 2; ++i) { - if (buf->menuData[i].signature.magic == BSWAP16(MENU_DATA_MAGIC)) - return TRUE; - for (int j = 0; j < NUM_SAVE_FILES; ++j) { - if (buf->files[j][i].signature.magic == BSWAP16(SAVE_FILE_MAGIC)) - return TRUE; - } - } - return FALSE; -} - -/** - * Byteswap all multibyte fields in a SaveBuffer. - */ -static void save_file_bswap(struct SaveBuffer *buf) { - bswap_menudata(buf->menuData + 0); - bswap_menudata(buf->menuData + 1); - for (int i = 0; i < NUM_SAVE_FILES; ++i) { - bswap_savefile(buf->files[i] + 0); - bswap_savefile(buf->files[i] + 1); - } -} - void save_file_do_save(s32 fileIndex) { if (fileIndex < 0 || fileIndex >= NUM_SAVE_FILES) return; @@ -386,7 +137,6 @@ void save_file_load_all(void) { } gSaveFileModified = TRUE; gMainMenuDataModified = TRUE; - stub_save_file_1(); } /** @@ -614,7 +364,6 @@ void save_file_set_sound_mode(u16 mode) { gSaveBuffer.menuData[0].soundMode = mode; gMainMenuDataModified = TRUE; - save_main_menu_data(); } u16 save_file_get_sound_mode(void) { diff --git a/src/moon/imgui/imgui_impl.cpp b/src/moon/imgui/imgui_impl.cpp index 87141f9f..f8cdc9c9 100644 --- a/src/moon/imgui/imgui_impl.cpp +++ b/src/moon/imgui/imgui_impl.cpp @@ -72,6 +72,9 @@ extern "C" { #include "pc/pc_main.h" #include "game/camera.h" #include "game/mario.h" +#include "game/level_update.h" +#include "engine/level_script.h" +#include "level_table.h" } #include "pc/configfile.h" @@ -100,6 +103,16 @@ static void HelpMarker(const char* desc) } } +void warp_to(s16 destLevel, s16 destArea = 0x01, s16 destWarpNode = 0x0A) { + if (gCurrLevelNum == destLevel || !mario_loaded) { + return; + } + + mario_loaded = false; + initiate_warp(destLevel, destArea, destWarpNode, 0); + fade_into_special_warp(0,0); +} + #ifdef TARGET_SWITCH namespace MoonNX { SwkbdConfig kbd; @@ -192,6 +205,8 @@ namespace MoonInternal { int selected_sky_item = 0; int current_sky_item = 0; + int current_level_sel = 0; + void setupFonts() { ImGuiIO& io = ImGui::GetIO(); // for (auto entry = Moon::fonts.begin(); entry != Moon::fonts.end(); entry++){ @@ -388,7 +403,7 @@ namespace MoonInternal { if (ImGui::BeginMenu("View")) { ImGui::MenuItem("Stats", NULL, &configImGui.s_stats); ImGui::MenuItem("Machinima", NULL, &configImGui.s_machinima); - ImGui::MenuItem("Quick Toggles", NULL, &configImGui.s_toggles); + ImGui::MenuItem("Quick Options", NULL, &configImGui.s_toggles); ImGui::MenuItem("Appearance", NULL, &configImGui.s_appearance); //ImGui::MenuItem("Debug Textures", NULL, &configImGui.texture_debug); ImGui::EndMenu(); @@ -460,7 +475,7 @@ namespace MoonInternal { } if (configImGui.s_toggles && show_menu_bar){ ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); - ImGui::Begin("Quick Toggles", NULL, ImGuiWindowFlags_None); + ImGui::Begin("Quick Options", NULL, ImGuiWindowFlags_None); ImGui::Dummy(ImVec2(0, 5)); @@ -479,6 +494,110 @@ namespace MoonInternal { ImGui::Dummy(ImVec2(0, 5)); + ImGui::Checkbox("God Mode", &enable_god); + + ImGui::Dummy(ImVec2(0, 5)); + + const char* levelList[] = { + "Castle Grounds", "Castle Inside", "Bob-omb Battlefield", + "Whomp's Fortress", "Princess's Secret Slide", "Tower of the Wing Cap", + "Jolly Roger Bay", "Secret Aquarium", "Cool, Cool Mountain", + "Bowser in the Dark World", "Big Boo's Haunt", "Hazy Maze Cave", + "Cavern of the Metal Cap", "Lethal Lava Land", "Shifting Sand Land", + "Vanish Cap under the Moat", "Dire, Dire Docks", "Bowser in the Fire Sea", + "Snowman's Land", "Wet-Dry World", "Tall, Tall Mountain", "Tiny, Huge Island", + "Tick Tock Clock", "Wing Mario Over the Rainbow", "Rainbow Ride", "Bowser in the Sky" + }; + ImGui::Combo("Level", ¤t_level_sel, levelList, IM_ARRAYSIZE(levelList)); + + if (ImGui::Button("Warp")) { + switch (current_level_sel) { + case 0: + warp_to(LEVEL_CASTLE_GROUNDS, 0x01, 0x04); + break; + case 1: + warp_to(LEVEL_CASTLE, 0x01, 0x01); + break; + case 2: + warp_to(LEVEL_BOB); + break; + case 3: + warp_to(LEVEL_WF); + break; + case 4: + warp_to(LEVEL_PSS); + break; + case 5: + warp_to(LEVEL_TOTWC); + break; + case 6: + warp_to(LEVEL_JRB); + break; + case 7: + warp_to(LEVEL_SA); + break; + case 8: + warp_to(LEVEL_CCM); + break; + case 9: + warp_to(LEVEL_BITDW); + break; + case 10: + warp_to(LEVEL_BBH); + break; + case 11: + warp_to(LEVEL_HMC); + break; + case 12: + warp_to(LEVEL_COTMC); + break; + case 13: + warp_to(LEVEL_LLL); + break; + case 14: + warp_to(LEVEL_SSL); + break; + case 15: + warp_to(LEVEL_VCUTM); + break; + case 16: + warp_to(LEVEL_DDD); + break; + case 17: + warp_to(LEVEL_BITFS); + break; + case 18: + warp_to(LEVEL_SL); + break; + case 19: + warp_to(LEVEL_WDW); + break; + case 20: + warp_to(LEVEL_TTM); + break; + case 21: + warp_to(LEVEL_THI); + break; + case 22: + warp_to(LEVEL_TTC); + break; + case 23: + warp_to(LEVEL_WMOTR); + break; + case 24: + warp_to(LEVEL_RR); + break; + case 25: + warp_to(LEVEL_BITS); + break; + default: + warp_to(LEVEL_CASTLE_GROUNDS); + break; + } + } + + ImGui::Dummy(ImVec2(0, 5)); + /* const char* skyStates[] = { "Default", "Night", "Green", "Blue", "Pink"}; ImGui::Combo("Skybox", &selected_sky_item, skyStates, IM_ARRAYSIZE(skyStates)); diff --git a/src/moon/saturn/saturn.cpp b/src/moon/saturn/saturn.cpp index b98edc1e..7607b0e0 100644 --- a/src/moon/saturn/saturn.cpp +++ b/src/moon/saturn/saturn.cpp @@ -35,6 +35,7 @@ extern "C" { bool camera_frozen; bool enable_head_rotations; bool enable_shadows; +bool enable_god; bool enable_dust_particles; bool show_menu_bar; @@ -70,6 +71,7 @@ namespace MoonInternal { camera_frozen = false; enable_shadows = true; + enable_god = false; enable_yoshi = false; MoonInternal::load_cc_directory(); diff --git a/src/moon/saturn/saturn_types.h b/src/moon/saturn/saturn_types.h index 5606a3f9..08244fdd 100644 --- a/src/moon/saturn/saturn_types.h +++ b/src/moon/saturn/saturn_types.h @@ -5,6 +5,7 @@ extern bool enable_head_rotations; extern bool enable_shadows; +extern bool enable_god; extern bool enable_dust_particles; // Color Codes