Merge pull request #3 from Agent-11/moon

Add warp menu and god mode
This commit is contained in:
Llennpie 2021-12-24 13:34:52 -05:00 committed by GitHub
commit 61410071d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 136 additions and 253 deletions

View File

@ -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;
}

View File

@ -2,6 +2,7 @@
#define LEVEL_SCRIPT_H
#include <PR/ultratypes.h>
#include <stdbool.h>
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

View File

@ -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 *));

View File

@ -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;
}
}
/**

View File

@ -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) {

View File

@ -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", &current_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));

View File

@ -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();

View File

@ -5,6 +5,7 @@
extern bool enable_head_rotations;
extern bool enable_shadows;
extern bool enable_god;
extern bool enable_dust_particles;
// Color Codes