mirror of https://github.com/sm64pc/sm64pc.git
commit
61410071d2
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 *));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
extern bool enable_head_rotations;
|
||||
extern bool enable_shadows;
|
||||
extern bool enable_god;
|
||||
extern bool enable_dust_particles;
|
||||
|
||||
// Color Codes
|
||||
|
|
Loading…
Reference in New Issue