mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-24 21:15:12 +00:00
Allow coop mods to use the backup save slot independently of the normal one
This commit is contained in:
parent
653ab58a5d
commit
3db42f1700
16 changed files with 156 additions and 462 deletions
|
@ -269,6 +269,10 @@ function SOUND_ARG_LOAD(bank, soundID, priority, flags)
|
||||||
return (bank << 28) | (soundID << 16) | (priority << 8) | flags | SOUND_STATUS_WAITING
|
return (bank << 28) | (soundID << 16) | (priority << 8) | flags | SOUND_STATUS_WAITING
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-------------
|
||||||
|
-- courses --
|
||||||
|
-------------
|
||||||
|
|
||||||
--- @type integer
|
--- @type integer
|
||||||
COURSE_NONE = 0
|
COURSE_NONE = 0
|
||||||
--- @type integer
|
--- @type integer
|
||||||
|
@ -320,4 +324,12 @@ COURSE_WMOTR = 23
|
||||||
--- @type integer
|
--- @type integer
|
||||||
COURSE_SA = 24
|
COURSE_SA = 24
|
||||||
--- @type integer
|
--- @type integer
|
||||||
COURSE_CAKE_END = 25
|
COURSE_CAKE_END = 25
|
||||||
|
--- @type integer
|
||||||
|
COURSE_END = 26
|
||||||
|
--- @type integer
|
||||||
|
COURSE_MAX = 25
|
||||||
|
--- @type integer
|
||||||
|
COURSE_COUNT = 25
|
||||||
|
--- @type integer
|
||||||
|
COURSE_MIN = 1
|
|
@ -271,6 +271,10 @@ function SOUND_ARG_LOAD(bank, soundID, priority, flags)
|
||||||
return (bank << 28) | (soundID << 16) | (priority << 8) | flags | SOUND_STATUS_WAITING
|
return (bank << 28) | (soundID << 16) | (priority << 8) | flags | SOUND_STATUS_WAITING
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-------------
|
||||||
|
-- courses --
|
||||||
|
-------------
|
||||||
|
|
||||||
--- @type integer
|
--- @type integer
|
||||||
COURSE_NONE = 0
|
COURSE_NONE = 0
|
||||||
--- @type integer
|
--- @type integer
|
||||||
|
@ -323,6 +327,14 @@ COURSE_WMOTR = 23
|
||||||
COURSE_SA = 24
|
COURSE_SA = 24
|
||||||
--- @type integer
|
--- @type integer
|
||||||
COURSE_CAKE_END = 25
|
COURSE_CAKE_END = 25
|
||||||
|
--- @type integer
|
||||||
|
COURSE_END = 26
|
||||||
|
--- @type integer
|
||||||
|
COURSE_MAX = 25
|
||||||
|
--- @type integer
|
||||||
|
COURSE_COUNT = 25
|
||||||
|
--- @type integer
|
||||||
|
COURSE_MIN = 1
|
||||||
|
|
||||||
--- @class BehaviorId
|
--- @class BehaviorId
|
||||||
|
|
||||||
|
|
|
@ -7107,6 +7107,12 @@ function movtexqc_register(name, level, area, type)
|
||||||
-- ...
|
-- ...
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- @param usingBackupSlot boolean
|
||||||
|
--- @return nil
|
||||||
|
function save_file_set_using_backup_slot(usingBackupSlot)
|
||||||
|
-- ...
|
||||||
|
end
|
||||||
|
|
||||||
--- @param index integer
|
--- @param index integer
|
||||||
--- @param value integer
|
--- @param value integer
|
||||||
--- @return nil
|
--- @return nil
|
||||||
|
|
|
@ -34,63 +34,6 @@ gLevelValues = {}
|
||||||
--- @type BehaviorValues
|
--- @type BehaviorValues
|
||||||
gBehaviorValues = {}
|
gBehaviorValues = {}
|
||||||
|
|
||||||
---------------
|
|
||||||
-- constants --
|
|
||||||
---------------
|
|
||||||
|
|
||||||
--- @type integer
|
|
||||||
COURSE_NONE = 0
|
|
||||||
--- @type integer
|
|
||||||
COURSE_BOB = 1
|
|
||||||
--- @type integer
|
|
||||||
COURSE_WF = 2
|
|
||||||
--- @type integer
|
|
||||||
COURSE_JRB = 3
|
|
||||||
--- @type integer
|
|
||||||
COURSE_CCM = 4
|
|
||||||
--- @type integer
|
|
||||||
COURSE_BBH = 5
|
|
||||||
--- @type integer
|
|
||||||
COURSE_HMC = 6
|
|
||||||
--- @type integer
|
|
||||||
COURSE_LLL = 7
|
|
||||||
--- @type integer
|
|
||||||
COURSE_SSL = 8
|
|
||||||
--- @type integer
|
|
||||||
COURSE_DDD = 9
|
|
||||||
--- @type integer
|
|
||||||
COURSE_SL = 10
|
|
||||||
--- @type integer
|
|
||||||
COURSE_WDW = 11
|
|
||||||
--- @type integer
|
|
||||||
COURSE_TTM = 12
|
|
||||||
--- @type integer
|
|
||||||
COURSE_THI = 13
|
|
||||||
--- @type integer
|
|
||||||
COURSE_TTC = 14
|
|
||||||
--- @type integer
|
|
||||||
COURSE_RR = 15
|
|
||||||
--- @type integer
|
|
||||||
COURSE_BITDW = 16
|
|
||||||
--- @type integer
|
|
||||||
COURSE_BITFS = 17
|
|
||||||
--- @type integer
|
|
||||||
COURSE_BITS = 18
|
|
||||||
--- @type integer
|
|
||||||
COURSE_PSS = 19
|
|
||||||
--- @type integer
|
|
||||||
COURSE_COTMC = 20
|
|
||||||
--- @type integer
|
|
||||||
COURSE_TOTWC = 21
|
|
||||||
--- @type integer
|
|
||||||
COURSE_VCUTM = 22
|
|
||||||
--- @type integer
|
|
||||||
COURSE_WMOTR = 23
|
|
||||||
--- @type integer
|
|
||||||
COURSE_SA = 24
|
|
||||||
--- @type integer
|
|
||||||
COURSE_CAKE_END = 25
|
|
||||||
|
|
||||||
-----------
|
-----------
|
||||||
-- hooks --
|
-- hooks --
|
||||||
-----------
|
-----------
|
||||||
|
|
|
@ -45,7 +45,7 @@ void DynOS_Lvl_Activate(s32 modIndex, const SysPath &aPackFolder, const char *aL
|
||||||
sDynosCustomLevelScripts.Add({ levelName, _Node });
|
sDynosCustomLevelScripts.Add({ levelName, _Node });
|
||||||
|
|
||||||
// Override vanilla script
|
// Override vanilla script
|
||||||
auto& newScripts = _Node->mLevelScripts; // DO NOT COMMIT
|
auto& newScripts = _Node->mLevelScripts;
|
||||||
auto& newScriptNode = newScripts[newScripts.Count() - 1];
|
auto& newScriptNode = newScripts[newScripts.Count() - 1];
|
||||||
const void* originalScript = DynOS_Builtin_ScriptPtr_GetFromName(newScriptNode->mName.begin());
|
const void* originalScript = DynOS_Builtin_ScriptPtr_GetFromName(newScriptNode->mName.begin());
|
||||||
if (originalScript == NULL) {
|
if (originalScript == NULL) {
|
||||||
|
|
|
@ -1321,6 +1321,7 @@
|
||||||
- [hud_hide](#hud_hide)
|
- [hud_hide](#hud_hide)
|
||||||
- [hud_show](#hud_show)
|
- [hud_show](#hud_show)
|
||||||
- [movtexqc_register](#movtexqc_register)
|
- [movtexqc_register](#movtexqc_register)
|
||||||
|
- [save_file_set_using_backup_slot](#save_file_set_using_backup_slot)
|
||||||
- [set_environment_region](#set_environment_region)
|
- [set_environment_region](#set_environment_region)
|
||||||
- [warp_exit_level](#warp_exit_level)
|
- [warp_exit_level](#warp_exit_level)
|
||||||
- [warp_restart_level](#warp_restart_level)
|
- [warp_restart_level](#warp_restart_level)
|
||||||
|
@ -24841,6 +24842,26 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
## [save_file_set_using_backup_slot](#save_file_set_using_backup_slot)
|
||||||
|
|
||||||
|
### Lua Example
|
||||||
|
`save_file_set_using_backup_slot(usingBackupSlot)`
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
| Field | Type |
|
||||||
|
| ----- | ---- |
|
||||||
|
| usingBackupSlot | `boolean` |
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
- None
|
||||||
|
|
||||||
|
### C Prototype
|
||||||
|
`void save_file_set_using_backup_slot(bool usingBackupSlot);`
|
||||||
|
|
||||||
|
[:arrow_up_small:](#)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
## [set_environment_region](#set_environment_region)
|
## [set_environment_region](#set_environment_region)
|
||||||
|
|
||||||
### Lua Example
|
### Lua Example
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
#include "pc/ini.h"
|
#include "pc/ini.h"
|
||||||
#include "pc/network/network.h"
|
#include "pc/network/network.h"
|
||||||
|
|
||||||
// note: force-disable TEXTSAVES until it's synchronized
|
|
||||||
#undef TEXTSAVES
|
|
||||||
|
|
||||||
#define MENU_DATA_MAGIC 0x4849
|
#define MENU_DATA_MAGIC 0x4849
|
||||||
#define SAVE_FILE_MAGIC 0x4441
|
#define SAVE_FILE_MAGIC 0x4441
|
||||||
|
|
||||||
|
@ -36,6 +33,7 @@ u8 gGotFileCoinHiScore = FALSE;
|
||||||
u8 gCurrCourseStarFlags = 0;
|
u8 gCurrCourseStarFlags = 0;
|
||||||
|
|
||||||
u8 gSpecialTripleJump = FALSE;
|
u8 gSpecialTripleJump = FALSE;
|
||||||
|
u8 gSaveFileUsingBackupSlot = FALSE;
|
||||||
|
|
||||||
#define STUB_LEVEL(_0, _1, courseenum, _3, _4, _5, _6, _7, _8) courseenum,
|
#define STUB_LEVEL(_0, _1, courseenum, _3, _4, _5, _6, _7, _8) courseenum,
|
||||||
#define DEFINE_LEVEL(_0, _1, courseenum, _3, _4, _5, _6, _7, _8, _9, _10) courseenum,
|
#define DEFINE_LEVEL(_0, _1, courseenum, _3, _4, _5, _6, _7, _8, _9, _10) courseenum,
|
||||||
|
@ -49,12 +47,6 @@ s8 gLevelToCourseNumTable[] = {
|
||||||
STATIC_ASSERT(ARRAY_COUNT(gLevelToCourseNumTable) == LEVEL_COUNT - 1,
|
STATIC_ASSERT(ARRAY_COUNT(gLevelToCourseNumTable) == LEVEL_COUNT - 1,
|
||||||
"change this array if you are adding levels");
|
"change this array if you are adding levels");
|
||||||
|
|
||||||
#ifdef TEXTSAVES
|
|
||||||
|
|
||||||
#include "text_save.inc.h"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This was probably used to set progress to 100% for debugging, but
|
// This was probably used to set progress to 100% for debugging, but
|
||||||
// it was removed from the release ROM.
|
// it was removed from the release ROM.
|
||||||
static void stub_save_file_1(void) {
|
static void stub_save_file_1(void) {
|
||||||
|
@ -354,24 +346,14 @@ void save_file_do_save(s32 fileIndex, s8 forceSave) {
|
||||||
if (fileIndex < 0 || fileIndex >= NUM_SAVE_FILES)
|
if (fileIndex < 0 || fileIndex >= NUM_SAVE_FILES)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef TEXTSAVES
|
|
||||||
if (gSaveFileModified && gNetworkType != NT_CLIENT) {
|
|
||||||
// Write to text file
|
|
||||||
write_text_save(fileIndex);
|
|
||||||
gSaveFileModified = FALSE;
|
|
||||||
gMainMenuDataModified = FALSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (gSaveFileModified) {
|
if (gSaveFileModified) {
|
||||||
// Compute checksum
|
// Compute checksum
|
||||||
add_save_block_signature(&gSaveBuffer.files[fileIndex][0],
|
add_save_block_signature(&gSaveBuffer.files[fileIndex][0],
|
||||||
sizeof(gSaveBuffer.files[fileIndex][0]), SAVE_FILE_MAGIC);
|
sizeof(gSaveBuffer.files[fileIndex][0]), SAVE_FILE_MAGIC);
|
||||||
|
|
||||||
// Copy to backup slot
|
// Copy to backup slot
|
||||||
bcopy(&gSaveBuffer.files[fileIndex][0], &gSaveBuffer.files[fileIndex][1],
|
//bcopy(&gSaveBuffer.files[fileIndex][0], &gSaveBuffer.files[fileIndex][1],
|
||||||
sizeof(gSaveBuffer.files[fileIndex][1]));
|
//sizeof(gSaveBuffer.files[fileIndex][1]));
|
||||||
|
|
||||||
// Write to EEPROM
|
// Write to EEPROM
|
||||||
write_eeprom_savefile(fileIndex, 0, 2);
|
write_eeprom_savefile(fileIndex, 0, 2);
|
||||||
|
@ -387,6 +369,7 @@ void save_file_erase(s32 fileIndex) {
|
||||||
|
|
||||||
touch_high_score_ages(fileIndex);
|
touch_high_score_ages(fileIndex);
|
||||||
bzero(&gSaveBuffer.files[fileIndex][0], sizeof(gSaveBuffer.files[fileIndex][0]));
|
bzero(&gSaveBuffer.files[fileIndex][0], sizeof(gSaveBuffer.files[fileIndex][0]));
|
||||||
|
bzero(&gSaveBuffer.files[fileIndex][1], sizeof(gSaveBuffer.files[fileIndex][1]));
|
||||||
|
|
||||||
gSaveFileModified = TRUE;
|
gSaveFileModified = TRUE;
|
||||||
save_file_do_save(fileIndex, TRUE);
|
save_file_do_save(fileIndex, TRUE);
|
||||||
|
@ -400,24 +383,15 @@ BAD_RETURN(s32) save_file_copy(s32 srcFileIndex, s32 destFileIndex) {
|
||||||
touch_high_score_ages(destFileIndex);
|
touch_high_score_ages(destFileIndex);
|
||||||
bcopy(&gSaveBuffer.files[srcFileIndex][0], &gSaveBuffer.files[destFileIndex][0],
|
bcopy(&gSaveBuffer.files[srcFileIndex][0], &gSaveBuffer.files[destFileIndex][0],
|
||||||
sizeof(gSaveBuffer.files[destFileIndex][0]));
|
sizeof(gSaveBuffer.files[destFileIndex][0]));
|
||||||
|
bcopy(&gSaveBuffer.files[srcFileIndex][1], &gSaveBuffer.files[destFileIndex][1],
|
||||||
|
sizeof(gSaveBuffer.files[destFileIndex][1]));
|
||||||
|
|
||||||
gSaveFileModified = TRUE;
|
gSaveFileModified = TRUE;
|
||||||
save_file_do_save(destFileIndex, TRUE);
|
save_file_do_save(destFileIndex, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEXTSAVES
|
|
||||||
static void save_file_load_textsaves(void) {
|
|
||||||
for (s32 file = 0; file < NUM_SAVE_FILES; file++) {
|
|
||||||
read_text_save(file);
|
|
||||||
}
|
|
||||||
gSaveFileModified = TRUE;
|
|
||||||
gMainMenuDataModified = TRUE;
|
|
||||||
stub_save_file_1();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void save_file_load_all(UNUSED u8 reload) {
|
void save_file_load_all(UNUSED u8 reload) {
|
||||||
s32 file;
|
//s32 file;
|
||||||
|
|
||||||
gMainMenuDataModified = FALSE;
|
gMainMenuDataModified = FALSE;
|
||||||
gSaveFileModified = FALSE;
|
gSaveFileModified = FALSE;
|
||||||
|
@ -430,6 +404,7 @@ void save_file_load_all(UNUSED u8 reload) {
|
||||||
save_file_bswap(&gSaveBuffer);
|
save_file_bswap(&gSaveBuffer);
|
||||||
|
|
||||||
// Verify the main menu data and create a backup copy if only one of the slots is valid.
|
// Verify the main menu data and create a backup copy if only one of the slots is valid.
|
||||||
|
/* Disable this so the 'backup' slot can be used
|
||||||
s32 validSlots;
|
s32 validSlots;
|
||||||
validSlots = verify_save_block_signature(&gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0]), MENU_DATA_MAGIC);
|
validSlots = verify_save_block_signature(&gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0]), MENU_DATA_MAGIC);
|
||||||
validSlots |= verify_save_block_signature(&gSaveBuffer.menuData[1], sizeof(gSaveBuffer.menuData[1]),MENU_DATA_MAGIC) << 1;
|
validSlots |= verify_save_block_signature(&gSaveBuffer.menuData[1], sizeof(gSaveBuffer.menuData[1]),MENU_DATA_MAGIC) << 1;
|
||||||
|
@ -461,6 +436,7 @@ void save_file_load_all(UNUSED u8 reload) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
stub_save_file_1();
|
stub_save_file_1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,11 +447,11 @@ void save_file_load_all(UNUSED u8 reload) {
|
||||||
*/
|
*/
|
||||||
void save_file_reload(void) {
|
void save_file_reload(void) {
|
||||||
// Copy save file data from backup
|
// Copy save file data from backup
|
||||||
bcopy(&gSaveBuffer.files[gCurrSaveFileNum - 1][1], &gSaveBuffer.files[gCurrSaveFileNum - 1][0],
|
/*bcopy(&gSaveBuffer.files[gCurrSaveFileNum - 1][1], &gSaveBuffer.files[gCurrSaveFileNum - 1][0],
|
||||||
sizeof(gSaveBuffer.files[gCurrSaveFileNum - 1][0]));
|
sizeof(gSaveBuffer.files[gCurrSaveFileNum - 1][0]));
|
||||||
|
|
||||||
// Copy main menu data from backup
|
// Copy main menu data from backup
|
||||||
bcopy(&gSaveBuffer.menuData[1], &gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0]));
|
bcopy(&gSaveBuffer.menuData[1], &gSaveBuffer.menuData[0], sizeof(gSaveBuffer.menuData[0]));*/
|
||||||
|
|
||||||
gMainMenuDataModified = FALSE;
|
gMainMenuDataModified = FALSE;
|
||||||
gSaveFileModified = FALSE;
|
gSaveFileModified = FALSE;
|
||||||
|
@ -509,7 +485,7 @@ void save_file_collect_star_or_key(s16 coinScore, s16 starIndex, u8 fromNetwork)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coinScore > save_file_get_course_coin_score(fileIndex, courseIndex)) {
|
if (coinScore > save_file_get_course_coin_score(fileIndex, courseIndex)) {
|
||||||
gSaveBuffer.files[fileIndex][0].courseCoinScores[courseIndex] = coinScore;
|
gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].courseCoinScores[courseIndex] = coinScore;
|
||||||
touch_coin_score_age(fileIndex, courseIndex);
|
touch_coin_score_age(fileIndex, courseIndex);
|
||||||
|
|
||||||
gGotFileCoinHiScore = TRUE;
|
gGotFileCoinHiScore = TRUE;
|
||||||
|
@ -602,14 +578,14 @@ void save_file_set_flags(u32 flags) {
|
||||||
flags &= ~(SAVE_FLAG_CAP_ON_GROUND | SAVE_FLAG_CAP_ON_KLEPTO | SAVE_FLAG_CAP_ON_MR_BLIZZARD | SAVE_FLAG_CAP_ON_UKIKI);
|
flags &= ~(SAVE_FLAG_CAP_ON_GROUND | SAVE_FLAG_CAP_ON_KLEPTO | SAVE_FLAG_CAP_ON_MR_BLIZZARD | SAVE_FLAG_CAP_ON_UKIKI);
|
||||||
if (flags == 0) { return; }
|
if (flags == 0) { return; }
|
||||||
|
|
||||||
gSaveBuffer.files[gCurrSaveFileNum - 1][0].flags |= (flags | SAVE_FLAG_FILE_EXISTS);
|
gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].flags |= (flags | SAVE_FLAG_FILE_EXISTS);
|
||||||
gSaveFileModified = TRUE;
|
gSaveFileModified = TRUE;
|
||||||
network_send_save_set_flag(gCurrSaveFileNum - 1, 0, 0, (flags | SAVE_FLAG_FILE_EXISTS));
|
network_send_save_set_flag(gCurrSaveFileNum - 1, 0, 0, (flags | SAVE_FLAG_FILE_EXISTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_file_clear_flags(u32 flags) {
|
void save_file_clear_flags(u32 flags) {
|
||||||
gSaveBuffer.files[gCurrSaveFileNum - 1][0].flags &= ~flags;
|
gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].flags &= ~flags;
|
||||||
gSaveBuffer.files[gCurrSaveFileNum - 1][0].flags |= SAVE_FLAG_FILE_EXISTS;
|
gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].flags |= SAVE_FLAG_FILE_EXISTS;
|
||||||
gSaveFileModified = TRUE;
|
gSaveFileModified = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +593,7 @@ u32 save_file_get_flags(void) {
|
||||||
if (gCurrCreditsEntry != NULL || gCurrDemoInput != NULL) {
|
if (gCurrCreditsEntry != NULL || gCurrDemoInput != NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return gSaveBuffer.files[gCurrSaveFileNum - 1][0].flags;
|
return gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -628,9 +604,9 @@ u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex) {
|
||||||
u32 starFlags;
|
u32 starFlags;
|
||||||
|
|
||||||
if (courseIndex == -1) {
|
if (courseIndex == -1) {
|
||||||
starFlags = SAVE_FLAG_TO_STAR_FLAG(gSaveBuffer.files[fileIndex][0].flags);
|
starFlags = SAVE_FLAG_TO_STAR_FLAG(gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].flags);
|
||||||
} else {
|
} else {
|
||||||
starFlags = gSaveBuffer.files[fileIndex][0].courseStars[courseIndex] & 0x7F;
|
starFlags = gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].courseStars[courseIndex] & 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
return starFlags;
|
return starFlags;
|
||||||
|
@ -642,40 +618,40 @@ u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex) {
|
||||||
*/
|
*/
|
||||||
void save_file_set_star_flags(s32 fileIndex, s32 courseIndex, u32 starFlags) {
|
void save_file_set_star_flags(s32 fileIndex, s32 courseIndex, u32 starFlags) {
|
||||||
if (courseIndex == -1) {
|
if (courseIndex == -1) {
|
||||||
gSaveBuffer.files[fileIndex][0].flags |= STAR_FLAG_TO_SAVE_FLAG(starFlags);
|
gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].flags |= STAR_FLAG_TO_SAVE_FLAG(starFlags);
|
||||||
network_send_save_set_flag(fileIndex, courseIndex, 0, (STAR_FLAG_TO_SAVE_FLAG(starFlags) | SAVE_FLAG_FILE_EXISTS));
|
network_send_save_set_flag(fileIndex, courseIndex, 0, (STAR_FLAG_TO_SAVE_FLAG(starFlags) | SAVE_FLAG_FILE_EXISTS));
|
||||||
} else {
|
} else {
|
||||||
gSaveBuffer.files[fileIndex][0].courseStars[courseIndex] |= starFlags;
|
gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].courseStars[courseIndex] |= starFlags;
|
||||||
network_send_save_set_flag(fileIndex, courseIndex, starFlags, SAVE_FLAG_FILE_EXISTS);
|
network_send_save_set_flag(fileIndex, courseIndex, starFlags, SAVE_FLAG_FILE_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
gSaveBuffer.files[fileIndex][0].flags |= SAVE_FLAG_FILE_EXISTS;
|
gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].flags |= SAVE_FLAG_FILE_EXISTS;
|
||||||
gSaveFileModified = TRUE;
|
gSaveFileModified = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 save_file_get_course_coin_score(s32 fileIndex, s32 courseIndex) {
|
s32 save_file_get_course_coin_score(s32 fileIndex, s32 courseIndex) {
|
||||||
return gSaveBuffer.files[fileIndex][0].courseCoinScores[courseIndex];
|
return gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].courseCoinScores[courseIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return TRUE if the cannon is unlocked in the current course.
|
* Return TRUE if the cannon is unlocked in the current course.
|
||||||
*/
|
*/
|
||||||
s32 save_file_is_cannon_unlocked(void) {
|
s32 save_file_is_cannon_unlocked(void) {
|
||||||
return (gSaveBuffer.files[gCurrSaveFileNum - 1][0].courseStars[gCurrCourseNum] & 0x80) != 0;
|
return (gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].courseStars[gCurrCourseNum] & 0x80) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the cannon status to unlocked in the current course.
|
* Sets the cannon status to unlocked in the current course.
|
||||||
*/
|
*/
|
||||||
void save_file_set_cannon_unlocked(void) {
|
void save_file_set_cannon_unlocked(void) {
|
||||||
gSaveBuffer.files[gCurrSaveFileNum - 1][0].courseStars[gCurrCourseNum] |= 0x80;
|
gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].courseStars[gCurrCourseNum] |= 0x80;
|
||||||
gSaveBuffer.files[gCurrSaveFileNum - 1][0].flags |= SAVE_FLAG_FILE_EXISTS;
|
gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].flags |= SAVE_FLAG_FILE_EXISTS;
|
||||||
gSaveFileModified = TRUE;
|
gSaveFileModified = TRUE;
|
||||||
network_send_save_set_flag(gCurrSaveFileNum - 1, gCurrCourseNum, 0x80, SAVE_FLAG_FILE_EXISTS);
|
network_send_save_set_flag(gCurrSaveFileNum - 1, gCurrCourseNum, 0x80, SAVE_FLAG_FILE_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_file_set_cap_pos(s16 x, s16 y, s16 z) {
|
void save_file_set_cap_pos(s16 x, s16 y, s16 z) {
|
||||||
struct SaveFile *saveFile = &gSaveBuffer.files[gCurrSaveFileNum - 1][0];
|
struct SaveFile *saveFile = &gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot];
|
||||||
|
|
||||||
saveFile->capLevel = gCurrLevelNum;
|
saveFile->capLevel = gCurrLevelNum;
|
||||||
saveFile->capArea = gCurrAreaIndex;
|
saveFile->capArea = gCurrAreaIndex;
|
||||||
|
@ -684,7 +660,7 @@ void save_file_set_cap_pos(s16 x, s16 y, s16 z) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 save_file_get_cap_pos(Vec3s capPos) {
|
s32 save_file_get_cap_pos(Vec3s capPos) {
|
||||||
struct SaveFile *saveFile = &gSaveBuffer.files[gCurrSaveFileNum - 1][0];
|
struct SaveFile *saveFile = &gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot];
|
||||||
s32 flags = save_file_get_flags();
|
s32 flags = save_file_get_flags();
|
||||||
|
|
||||||
if (saveFile->capLevel == gCurrLevelNum && saveFile->capArea == gCurrAreaIndex
|
if (saveFile->capLevel == gCurrLevelNum && saveFile->capArea == gCurrAreaIndex
|
||||||
|
@ -709,7 +685,7 @@ u16 save_file_get_sound_mode(void) {
|
||||||
|
|
||||||
void save_file_move_cap_to_default_location(void) {
|
void save_file_move_cap_to_default_location(void) {
|
||||||
if (save_file_get_flags() & SAVE_FLAG_CAP_ON_GROUND) {
|
if (save_file_get_flags() & SAVE_FLAG_CAP_ON_GROUND) {
|
||||||
switch (gSaveBuffer.files[gCurrSaveFileNum - 1][0].capLevel) {
|
switch (gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].capLevel) {
|
||||||
case LEVEL_SSL:
|
case LEVEL_SSL:
|
||||||
save_file_set_flags(SAVE_FLAG_CAP_ON_KLEPTO);
|
save_file_set_flags(SAVE_FLAG_CAP_ON_KLEPTO);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,334 +0,0 @@
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include "course_table.h"
|
|
||||||
#include "pc/ini.h"
|
|
||||||
#include "pc/platform.h"
|
|
||||||
#include "pc/fs/fs.h"
|
|
||||||
|
|
||||||
#define FILENAME_FORMAT "%s/sm64_save_file_%d.sav"
|
|
||||||
#define NUM_COURSES 15
|
|
||||||
#define NUM_BONUS_COURSES 10
|
|
||||||
#define NUM_FLAGS 21
|
|
||||||
#define NUM_CAP_ON 4
|
|
||||||
|
|
||||||
const char *sav_flags[NUM_FLAGS] = {
|
|
||||||
"file_exists", "wing_cap", "metal_cap", "vanish_cap", "key_1", "key_2",
|
|
||||||
"basement_door", "upstairs_door", "ddd_moved_back", "moat_drained",
|
|
||||||
"pps_door", "wf_door", "ccm_door", "jrb_door", "bitdw_door",
|
|
||||||
"bitfs_door", "", "", "", "", "50star_door" // 4 Cap flags are processed in their own section
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *sav_courses[NUM_COURSES] = {
|
|
||||||
"bob", "wf", "jrb", "ccm", "bbh", "hmc", "lll",
|
|
||||||
"ssl", "ddd", "sl", "wdw", "ttm", "thi", "ttc", "rr"
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *sav_bonus_courses[NUM_BONUS_COURSES] = {
|
|
||||||
"bitdw", "bitfs", "bits", "pss", "cotmc",
|
|
||||||
"totwc", "vcutm", "wmotr", "sa", "hub" // hub is Castle Grounds
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *cap_on_types[NUM_CAP_ON] = {
|
|
||||||
"ground", "klepto", "ukiki", "mrblizzard"
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *sound_modes[3] = {
|
|
||||||
"stereo", "mono", "headset"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Get current timestamp string */
|
|
||||||
static void get_timestamp(char* buffer) {
|
|
||||||
time_t timer;
|
|
||||||
struct tm* tm_info;
|
|
||||||
|
|
||||||
timer = time(NULL);
|
|
||||||
tm_info = localtime(&timer);
|
|
||||||
|
|
||||||
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert 'binary' integer to decimal integer */
|
|
||||||
static u32 bin_to_int(u32 n) {
|
|
||||||
s32 dec = 0, i = 0, rem;
|
|
||||||
while (n != 0) {
|
|
||||||
rem = n % 10;
|
|
||||||
n /= 10;
|
|
||||||
dec += rem * (1 << i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return dec;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert decimal integer to 'binary' integer */
|
|
||||||
static u32 int_to_bin(u32 n) {
|
|
||||||
s32 bin = 0, rem, i = 1;
|
|
||||||
while (n != 0) {
|
|
||||||
rem = n % 2;
|
|
||||||
n /= 2;
|
|
||||||
bin += rem * i;
|
|
||||||
i *= 10;
|
|
||||||
}
|
|
||||||
return bin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write SaveFile and MainMenuSaveData structs to a text-based savefile
|
|
||||||
*/
|
|
||||||
static s32 write_text_save(s32 fileIndex) {
|
|
||||||
FILE* file;
|
|
||||||
struct SaveFile *savedata;
|
|
||||||
struct MainMenuSaveData *menudata;
|
|
||||||
char filename[SYS_MAX_PATH] = { 0 };
|
|
||||||
char value[64];
|
|
||||||
u32 i, bit, flags, coins, stars, starFlags;
|
|
||||||
|
|
||||||
if (snprintf(filename, sizeof(filename), FILENAME_FORMAT, fs_writepath, fileIndex) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
file = fopen(filename, "wt");
|
|
||||||
if (file == NULL) {
|
|
||||||
printf("Savefile '%s' not found!\n", filename);
|
|
||||||
return -1;
|
|
||||||
} else
|
|
||||||
printf("Saving updated progress to '%s'\n", filename);
|
|
||||||
|
|
||||||
fprintf(file, "# Super Mario 64 save file\n");
|
|
||||||
fprintf(file, "# Comment starts with #\n");
|
|
||||||
fprintf(file, "# True = 1, False = 0\n");
|
|
||||||
|
|
||||||
get_timestamp(value);
|
|
||||||
fprintf(file, "# %s\n", value);
|
|
||||||
|
|
||||||
menudata = &gSaveBuffer.menuData[0];
|
|
||||||
fprintf(file, "\n[menu]\n");
|
|
||||||
fprintf(file, "coin_score_age = %d\n", menudata->coinScoreAges[fileIndex]);
|
|
||||||
|
|
||||||
if (menudata->soundMode == 0) {
|
|
||||||
fprintf(file, "sound_mode = %s\n", sound_modes[0]); // stereo
|
|
||||||
}
|
|
||||||
else if (menudata->soundMode == 3) {
|
|
||||||
fprintf(file, "sound_mode = %s\n", sound_modes[1]); // mono
|
|
||||||
}
|
|
||||||
else if (menudata->soundMode == 1) {
|
|
||||||
fprintf(file, "sound_mode = %s\n", sound_modes[2]); // headset
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf("Undefined sound mode!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(file, "\n[flags]\n");
|
|
||||||
for (i = 1; i < NUM_FLAGS; i++) {
|
|
||||||
if (strcmp(sav_flags[i], "")) {
|
|
||||||
flags = save_file_get_flags();
|
|
||||||
flags = (flags & (1 << i)); // Get 'star' flag bit
|
|
||||||
flags = (flags) ? 1 : 0;
|
|
||||||
|
|
||||||
fprintf(file, "%s = %d\n", sav_flags[i], flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(file, "\n[courses]\n");
|
|
||||||
for (i = 0; i < NUM_COURSES; i++) {
|
|
||||||
stars = save_file_get_star_flags(fileIndex, i);
|
|
||||||
coins = save_file_get_course_coin_score(fileIndex, i);
|
|
||||||
starFlags = int_to_bin(stars); // 63 -> 111111
|
|
||||||
|
|
||||||
fprintf(file, "%s = \"%d, %07d\"\n", sav_courses[i], coins, starFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(file, "\n[bonus]\n");
|
|
||||||
for (i = 0; i < NUM_BONUS_COURSES; i++) {
|
|
||||||
char *format;
|
|
||||||
|
|
||||||
if (i == NUM_BONUS_COURSES-1) {
|
|
||||||
// Process Castle Grounds
|
|
||||||
stars = save_file_get_star_flags(fileIndex, -1);
|
|
||||||
format = "%05d";
|
|
||||||
} else if (i == 3) {
|
|
||||||
// Process Princess's Secret Slide
|
|
||||||
stars = save_file_get_star_flags(fileIndex, 18);
|
|
||||||
format = "%02d";
|
|
||||||
} else {
|
|
||||||
// Process bonus courses
|
|
||||||
stars = save_file_get_star_flags(fileIndex, i+15);
|
|
||||||
format = "%d";
|
|
||||||
}
|
|
||||||
|
|
||||||
starFlags = int_to_bin(stars);
|
|
||||||
if (sprintf(value, format, starFlags) < 0)
|
|
||||||
return -1;
|
|
||||||
fprintf(file, "%s = %s\n", sav_bonus_courses[i], value);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(file, "\n[cap]\n");
|
|
||||||
for (i = 0; i < NUM_CAP_ON; i++) {
|
|
||||||
flags = save_file_get_flags();
|
|
||||||
bit = (1 << (i+16)); // Determine current flag
|
|
||||||
flags = (flags & bit); // Get 'cap' flag bit
|
|
||||||
flags = (flags) ? 1 : 0;
|
|
||||||
if (flags) {
|
|
||||||
fprintf(file, "type = %s\n", cap_on_types[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
savedata = &gSaveBuffer.files[fileIndex][0];
|
|
||||||
switch(savedata->capLevel) {
|
|
||||||
case COURSE_SSL:
|
|
||||||
fprintf(file, "level = %s\n", "ssl");
|
|
||||||
break;
|
|
||||||
case COURSE_SL:
|
|
||||||
fprintf(file, "level = %s\n", "sl");
|
|
||||||
break;
|
|
||||||
case COURSE_TTM:
|
|
||||||
fprintf(file, "level = %s\n", "ttm");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (savedata->capLevel) {
|
|
||||||
fprintf(file, "area = %d\n", savedata->capArea);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Backup is nessecary for saving recent progress after gameover
|
|
||||||
bcopy(&gSaveBuffer.files[fileIndex][0], &gSaveBuffer.files[fileIndex][1],
|
|
||||||
sizeof(gSaveBuffer.files[fileIndex][1]));
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read gSaveBuffer data from a text-based savefile
|
|
||||||
*/
|
|
||||||
static s32 read_text_save(s32 fileIndex) {
|
|
||||||
char filename[SYS_MAX_PATH] = { 0 };
|
|
||||||
const char *value;
|
|
||||||
ini_t *savedata;
|
|
||||||
|
|
||||||
u32 i, flag, coins, stars, starFlags;
|
|
||||||
u32 capArea;
|
|
||||||
|
|
||||||
if (snprintf(filename, sizeof(filename), FILENAME_FORMAT, fs_writepath, fileIndex) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
savedata = ini_load(filename);
|
|
||||||
if (savedata == NULL) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
printf("Loading savefile from '%s'\n", filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
ini_sget(savedata, "menu", "coin_score_age", "%d",
|
|
||||||
&gSaveBuffer.menuData[0].coinScoreAges[fileIndex]);
|
|
||||||
|
|
||||||
value = ini_get(savedata, "menu", "sound_mode");
|
|
||||||
if (value) {
|
|
||||||
if (strcmp(value, sound_modes[0]) == 0) {
|
|
||||||
gSaveBuffer.menuData[0].soundMode = 0; // stereo
|
|
||||||
}
|
|
||||||
else if (strcmp(value, sound_modes[1]) == 0) {
|
|
||||||
gSaveBuffer.menuData[0].soundMode = 3; // mono
|
|
||||||
}
|
|
||||||
else if (strcmp(value, sound_modes[2]) == 0) {
|
|
||||||
gSaveBuffer.menuData[0].soundMode = 1; // headset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf("Invalid 'menu:sound_mode' flag!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1; i < NUM_FLAGS; i++) {
|
|
||||||
value = ini_get(savedata, "flags", sav_flags[i]);
|
|
||||||
if (value) {
|
|
||||||
flag = value[0] - '0'; // Flag should be 0 or 1
|
|
||||||
if (flag) {
|
|
||||||
flag = 1 << i; // Flags defined in 'save_file' header
|
|
||||||
gSaveBuffer.files[fileIndex][0].flags |= flag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_COURSES; i++) {
|
|
||||||
value = ini_get(savedata, "courses", sav_courses[i]);
|
|
||||||
if (value) {
|
|
||||||
sscanf(value, "%d, %d", &coins, &stars);
|
|
||||||
starFlags = bin_to_int(stars); // 111111 -> 63
|
|
||||||
|
|
||||||
save_file_set_star_flags(fileIndex, i, starFlags);
|
|
||||||
gSaveBuffer.files[fileIndex][0].courseCoinScores[i] = coins;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_BONUS_COURSES; i++) {
|
|
||||||
value = ini_get(savedata, "bonus", sav_bonus_courses[i]);
|
|
||||||
if (value) {
|
|
||||||
sscanf(value, "%d", &stars);
|
|
||||||
starFlags = bin_to_int(stars);
|
|
||||||
|
|
||||||
if (strlen(value) == 5) {
|
|
||||||
// Process Castle Grounds
|
|
||||||
save_file_set_star_flags(fileIndex, -1, starFlags);
|
|
||||||
} else if (strlen(value) == 2) {
|
|
||||||
// Process Princess's Secret Slide
|
|
||||||
save_file_set_star_flags(fileIndex, 18, starFlags);
|
|
||||||
} else {
|
|
||||||
// Process bonus courses
|
|
||||||
save_file_set_star_flags(fileIndex, i+15, starFlags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_CAP_ON; i++) {
|
|
||||||
value = ini_get(savedata, "cap", "type");
|
|
||||||
if (value) {
|
|
||||||
if (!strcmp(value, cap_on_types[i])) {
|
|
||||||
flag = (1 << (16 + i));
|
|
||||||
gSaveBuffer.files[fileIndex][0].flags |= flag;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = ini_get(savedata, "cap", "level");
|
|
||||||
if (value) {
|
|
||||||
if (strcmp(value, "ssl") == 0) {
|
|
||||||
gSaveBuffer.files[fileIndex][0].capLevel = COURSE_SSL; // ssl
|
|
||||||
}
|
|
||||||
else if (strcmp(value, "sl") == 0) {
|
|
||||||
gSaveBuffer.files[fileIndex][0].capLevel = COURSE_SL; // sl
|
|
||||||
}
|
|
||||||
else if (strcmp(value, "ttm") == 0) {
|
|
||||||
gSaveBuffer.files[fileIndex][0].capLevel = COURSE_TTM; // ttm
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf("Invalid 'cap:level' flag!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = ini_get(savedata, "cap", "area");
|
|
||||||
if (value) {
|
|
||||||
sscanf(value, "%d", &capArea);
|
|
||||||
if (capArea > 1 && capArea < 2) {
|
|
||||||
printf("Invalid 'cap:area' flag: %d!\n", capArea);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gSaveBuffer.files[fileIndex][0].capArea = capArea;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Good, file exists for gSaveBuffer
|
|
||||||
gSaveBuffer.files[fileIndex][0].flags |= SAVE_FLAG_FILE_EXISTS;
|
|
||||||
|
|
||||||
// Backup is nessecary for saving recent progress after gameover
|
|
||||||
bcopy(&gSaveBuffer.files[fileIndex][0], &gSaveBuffer.files[fileIndex][1],
|
|
||||||
sizeof(gSaveBuffer.files[fileIndex][1]));
|
|
||||||
|
|
||||||
ini_free(savedata);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -244,6 +244,9 @@ char gSmluaConstants[] = ""
|
||||||
" if flags == nil then flags = 0 end\n"
|
" if flags == nil then flags = 0 end\n"
|
||||||
" return (bank << 28) | (soundID << 16) | (priority << 8) | flags | SOUND_STATUS_WAITING\n"
|
" return (bank << 28) | (soundID << 16) | (priority << 8) | flags | SOUND_STATUS_WAITING\n"
|
||||||
"end\n"
|
"end\n"
|
||||||
|
"-------------\n"
|
||||||
|
"-- courses --\n"
|
||||||
|
"-------------\n"
|
||||||
"--- @type integer\n"
|
"--- @type integer\n"
|
||||||
"COURSE_NONE = 0\n"
|
"COURSE_NONE = 0\n"
|
||||||
"--- @type integer\n"
|
"--- @type integer\n"
|
||||||
|
@ -296,6 +299,14 @@ char gSmluaConstants[] = ""
|
||||||
"COURSE_SA = 24\n"
|
"COURSE_SA = 24\n"
|
||||||
"--- @type integer\n"
|
"--- @type integer\n"
|
||||||
"COURSE_CAKE_END = 25\n"
|
"COURSE_CAKE_END = 25\n"
|
||||||
|
"--- @type integer\n"
|
||||||
|
"COURSE_END = 26\n"
|
||||||
|
"--- @type integer\n"
|
||||||
|
"COURSE_MAX = 25\n"
|
||||||
|
"--- @type integer\n"
|
||||||
|
"COURSE_COUNT = 25\n"
|
||||||
|
"--- @type integer\n"
|
||||||
|
"COURSE_MIN = 1\n"
|
||||||
"id_bhv1Up = 0\n"
|
"id_bhv1Up = 0\n"
|
||||||
"id_bhv1upJumpOnApproach = 1\n"
|
"id_bhv1upJumpOnApproach = 1\n"
|
||||||
"id_bhv1upRunningAway = 2\n"
|
"id_bhv1upRunningAway = 2\n"
|
||||||
|
|
|
@ -14771,6 +14771,17 @@ int smlua_func_movtexqc_register(lua_State* L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int smlua_func_save_file_set_using_backup_slot(lua_State* L) {
|
||||||
|
if(!smlua_functions_valid_param_count(L, 1)) { return 0; }
|
||||||
|
|
||||||
|
bool usingBackupSlot = smlua_to_boolean(L, 1);
|
||||||
|
if (!gSmLuaConvertSuccess) { return 0; }
|
||||||
|
|
||||||
|
save_file_set_using_backup_slot(usingBackupSlot);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int smlua_func_set_environment_region(lua_State* L) {
|
int smlua_func_set_environment_region(lua_State* L) {
|
||||||
if(!smlua_functions_valid_param_count(L, 2)) { return 0; }
|
if(!smlua_functions_valid_param_count(L, 2)) { return 0; }
|
||||||
|
|
||||||
|
@ -16925,6 +16936,7 @@ void smlua_bind_functions_autogen(void) {
|
||||||
smlua_bind_function(L, "hud_hide", smlua_func_hud_hide);
|
smlua_bind_function(L, "hud_hide", smlua_func_hud_hide);
|
||||||
smlua_bind_function(L, "hud_show", smlua_func_hud_show);
|
smlua_bind_function(L, "hud_show", smlua_func_hud_show);
|
||||||
smlua_bind_function(L, "movtexqc_register", smlua_func_movtexqc_register);
|
smlua_bind_function(L, "movtexqc_register", smlua_func_movtexqc_register);
|
||||||
|
smlua_bind_function(L, "save_file_set_using_backup_slot", smlua_func_save_file_set_using_backup_slot);
|
||||||
smlua_bind_function(L, "set_environment_region", smlua_func_set_environment_region);
|
smlua_bind_function(L, "set_environment_region", smlua_func_set_environment_region);
|
||||||
smlua_bind_function(L, "warp_exit_level", smlua_func_warp_exit_level);
|
smlua_bind_function(L, "warp_exit_level", smlua_func_warp_exit_level);
|
||||||
smlua_bind_function(L, "warp_restart_level", smlua_func_warp_restart_level);
|
smlua_bind_function(L, "warp_restart_level", smlua_func_warp_restart_level);
|
||||||
|
|
|
@ -87,6 +87,11 @@ s16 get_current_save_file_num(void) {
|
||||||
return gCurrSaveFileNum;
|
return gCurrSaveFileNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void save_file_set_using_backup_slot(bool usingBackupSlot) {
|
||||||
|
extern u8 gSaveFileUsingBackupSlot;
|
||||||
|
gSaveFileUsingBackupSlot = usingBackupSlot ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
void movtexqc_register(const char* name, s16 level, s16 area, s16 type) {
|
void movtexqc_register(const char* name, s16 level, s16 area, s16 type) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ f32 get_hand_foot_pos_y(struct MarioState* m, u8 index);
|
||||||
f32 get_hand_foot_pos_z(struct MarioState* m, u8 index);
|
f32 get_hand_foot_pos_z(struct MarioState* m, u8 index);
|
||||||
|
|
||||||
s16 get_current_save_file_num(void);
|
s16 get_current_save_file_num(void);
|
||||||
|
void save_file_set_using_backup_slot(bool usingBackupSlot);
|
||||||
|
|
||||||
void movtexqc_register(const char* name, s16 level, s16 area, s16 type);
|
void movtexqc_register(const char* name, s16 level, s16 area, s16 type);
|
||||||
f32 get_environment_region(u8 index);
|
f32 get_environment_region(u8 index);
|
||||||
|
|
|
@ -109,6 +109,9 @@ bool network_init(enum NetworkType inNetworkType) {
|
||||||
gNetworkType = inNetworkType;
|
gNetworkType = inNetworkType;
|
||||||
|
|
||||||
if (gNetworkType == NT_SERVER) {
|
if (gNetworkType == NT_SERVER) {
|
||||||
|
extern s16 gCurrSaveFileNum;
|
||||||
|
gCurrSaveFileNum = configHostSaveSlot;
|
||||||
|
|
||||||
mods_activate(&gLocalMods);
|
mods_activate(&gLocalMods);
|
||||||
smlua_init();
|
smlua_init();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
extern s16 gCurrSaveFileNum;
|
extern s16 gCurrSaveFileNum;
|
||||||
extern s16 gCurrCourseNum;
|
extern s16 gCurrCourseNum;
|
||||||
|
extern u8 gSaveFileUsingBackupSlot;
|
||||||
|
|
||||||
static f32 dist_to_pos(struct Object* o, f32* pos) {
|
static f32 dist_to_pos(struct Object* o, f32* pos) {
|
||||||
f32 x = o->oPosX - pos[0]; x *= x;
|
f32 x = o->oPosX - pos[0]; x *= x;
|
||||||
|
@ -58,6 +59,7 @@ void network_send_collect_star(struct Object* o, s16 coinScore, s16 starIndex) {
|
||||||
packet_write(&p, &behaviorId, sizeof(u32));
|
packet_write(&p, &behaviorId, sizeof(u32));
|
||||||
packet_write(&p, &coinScore, sizeof(s16));
|
packet_write(&p, &coinScore, sizeof(s16));
|
||||||
packet_write(&p, &starIndex, sizeof(s16));
|
packet_write(&p, &starIndex, sizeof(s16));
|
||||||
|
packet_write(&p, &gSaveFileUsingBackupSlot, sizeof(u8));
|
||||||
|
|
||||||
network_send(&p);
|
network_send(&p);
|
||||||
}
|
}
|
||||||
|
@ -71,6 +73,7 @@ void network_receive_collect_star(struct Packet* p) {
|
||||||
s16 lastStarActNum = gCurrActStarNum;
|
s16 lastStarActNum = gCurrActStarNum;
|
||||||
s16 lastLevelNum = gCurrLevelNum;
|
s16 lastLevelNum = gCurrLevelNum;
|
||||||
s16 lastAreaIndex = gCurrAreaIndex;
|
s16 lastAreaIndex = gCurrAreaIndex;
|
||||||
|
u8 lastBackupSlot = gSaveFileUsingBackupSlot;
|
||||||
|
|
||||||
packet_read(p, &gCurrSaveFileNum, sizeof(s16));
|
packet_read(p, &gCurrSaveFileNum, sizeof(s16));
|
||||||
packet_read(p, &gCurrCourseNum, sizeof(s16));
|
packet_read(p, &gCurrCourseNum, sizeof(s16));
|
||||||
|
@ -81,16 +84,13 @@ void network_receive_collect_star(struct Packet* p) {
|
||||||
packet_read(p, &behaviorId, sizeof(u32));
|
packet_read(p, &behaviorId, sizeof(u32));
|
||||||
packet_read(p, &coinScore, sizeof(s16));
|
packet_read(p, &coinScore, sizeof(s16));
|
||||||
packet_read(p, &starIndex, sizeof(s16));
|
packet_read(p, &starIndex, sizeof(s16));
|
||||||
|
packet_read(p, &gSaveFileUsingBackupSlot, sizeof(u8));
|
||||||
|
if (gSaveFileUsingBackupSlot != 0) { gSaveFileUsingBackupSlot = 1; }
|
||||||
|
|
||||||
const void* behavior = get_behavior_from_id(behaviorId);
|
const void* behavior = get_behavior_from_id(behaviorId);
|
||||||
|
|
||||||
save_file_collect_star_or_key(coinScore, starIndex, 1);
|
save_file_collect_star_or_key(coinScore, starIndex, 1);
|
||||||
|
|
||||||
s32 numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
|
|
||||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
|
||||||
gMarioStates[i].numStars = numStars;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NetworkPlayer* np = gNetworkPlayerLocal;
|
struct NetworkPlayer* np = gNetworkPlayerLocal;
|
||||||
bool levelAreaMismatch = ((np == NULL)
|
bool levelAreaMismatch = ((np == NULL)
|
||||||
|| np->currCourseNum != gCurrCourseNum
|
|| np->currCourseNum != gCurrCourseNum
|
||||||
|
@ -98,11 +98,17 @@ void network_receive_collect_star(struct Packet* p) {
|
||||||
|| np->currLevelNum != gCurrLevelNum
|
|| np->currLevelNum != gCurrLevelNum
|
||||||
|| np->currAreaIndex != gCurrAreaIndex);
|
|| np->currAreaIndex != gCurrAreaIndex);
|
||||||
|
|
||||||
gCurrSaveFileNum = lastSaveFileNum;
|
gCurrSaveFileNum = lastSaveFileNum;
|
||||||
gCurrCourseNum = lastCourseNum;
|
gCurrCourseNum = lastCourseNum;
|
||||||
gCurrActStarNum = lastStarActNum;
|
gCurrActStarNum = lastStarActNum;
|
||||||
gCurrLevelNum = lastLevelNum;
|
gCurrLevelNum = lastLevelNum;
|
||||||
gCurrAreaIndex = lastAreaIndex;
|
gCurrAreaIndex = lastAreaIndex;
|
||||||
|
gSaveFileUsingBackupSlot = lastBackupSlot;
|
||||||
|
|
||||||
|
s32 numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
|
||||||
|
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||||
|
gMarioStates[i].numStars = numStars;
|
||||||
|
}
|
||||||
|
|
||||||
if (!levelAreaMismatch) {
|
if (!levelAreaMismatch) {
|
||||||
struct Object* star = find_nearest_star(behavior, pos, 500);
|
struct Object* star = find_nearest_star(behavior, pos, 500);
|
||||||
|
|
|
@ -3,18 +3,28 @@
|
||||||
#include "game/save_file.h"
|
#include "game/save_file.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
extern u8 gSaveFileUsingBackupSlot;
|
||||||
|
|
||||||
void network_send_save_file(s32 fileIndex) {
|
void network_send_save_file(s32 fileIndex) {
|
||||||
if (gNetworkPlayerServer == NULL) { return; }
|
if (gNetworkPlayerServer == NULL) { return; }
|
||||||
SOFT_ASSERT(gNetworkType == NT_CLIENT);
|
SOFT_ASSERT(gNetworkType == NT_CLIENT);
|
||||||
struct Packet p = { 0 };
|
struct Packet p = { 0 };
|
||||||
packet_init(&p, PACKET_SAVE_FILE, true, PLMT_NONE);
|
packet_init(&p, PACKET_SAVE_FILE, true, PLMT_NONE);
|
||||||
packet_write(&p, &fileIndex, sizeof(s32));
|
packet_write(&p, &fileIndex, sizeof(s32));
|
||||||
|
packet_write(&p, &gSaveFileUsingBackupSlot, sizeof(u8));
|
||||||
network_send_to(gNetworkPlayerServer->localIndex, &p);
|
network_send_to(gNetworkPlayerServer->localIndex, &p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void network_receive_save_file(struct Packet* p) {
|
void network_receive_save_file(struct Packet* p) {
|
||||||
if (gNetworkType != NT_SERVER) { return; }
|
if (gNetworkType != NT_SERVER) { return; }
|
||||||
s32 fileIndex = 0;
|
s32 fileIndex = 0;
|
||||||
|
u8 lastBackupSlot = gSaveFileUsingBackupSlot;
|
||||||
packet_read(p, &fileIndex, sizeof(s32));
|
packet_read(p, &fileIndex, sizeof(s32));
|
||||||
|
packet_read(p, &gSaveFileUsingBackupSlot, sizeof(u8));
|
||||||
|
|
||||||
|
if (gSaveFileUsingBackupSlot != 0) { gSaveFileUsingBackupSlot = 1; }
|
||||||
|
|
||||||
save_file_do_save(fileIndex, FALSE);
|
save_file_do_save(fileIndex, FALSE);
|
||||||
|
|
||||||
|
gSaveFileUsingBackupSlot = lastBackupSlot;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,16 @@
|
||||||
#include "buffers/buffers.h"
|
#include "buffers/buffers.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
|
|
||||||
|
extern u8 gSaveFileUsingBackupSlot;
|
||||||
|
|
||||||
void network_send_save_set_flag(s32 fileIndex, s32 courseIndex, u8 courseStars, u32 flags) {
|
void network_send_save_set_flag(s32 fileIndex, s32 courseIndex, u8 courseStars, u32 flags) {
|
||||||
struct Packet p = { 0 };
|
struct Packet p = { 0 };
|
||||||
packet_init(&p, PACKET_SAVE_SET_FLAG, true, PLMT_NONE);
|
packet_init(&p, PACKET_SAVE_SET_FLAG, true, PLMT_NONE);
|
||||||
packet_write(&p, &fileIndex, sizeof(s32));
|
packet_write(&p, &fileIndex, sizeof(s32));
|
||||||
packet_write(&p, &courseIndex, sizeof(s32));
|
packet_write(&p, &courseIndex, sizeof(s32));
|
||||||
packet_write(&p, &courseStars, sizeof(u8));
|
packet_write(&p, &courseStars, sizeof(u8));
|
||||||
packet_write(&p, &flags, sizeof(u32));
|
packet_write(&p, &flags, sizeof(u32));
|
||||||
|
packet_write(&p, &gSaveFileUsingBackupSlot, sizeof(u8));
|
||||||
network_send(&p);
|
network_send(&p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,10 +22,12 @@ void network_receive_save_set_flag(struct Packet* p) {
|
||||||
s32 courseIndex;
|
s32 courseIndex;
|
||||||
u8 courseStars;
|
u8 courseStars;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
|
u8 backupSlot;
|
||||||
packet_read(p, &fileIndex, sizeof(s32));
|
packet_read(p, &fileIndex, sizeof(s32));
|
||||||
packet_read(p, &courseIndex, sizeof(s32));
|
packet_read(p, &courseIndex, sizeof(s32));
|
||||||
packet_read(p, &courseStars, sizeof(u8));
|
packet_read(p, &courseStars, sizeof(u8));
|
||||||
packet_read(p, &flags, sizeof(u32));
|
packet_read(p, &flags, sizeof(u32));
|
||||||
|
packet_read(p, &backupSlot, sizeof(u8));
|
||||||
|
|
||||||
if (fileIndex >= NUM_SAVE_FILES) {
|
if (fileIndex >= NUM_SAVE_FILES) {
|
||||||
LOG_ERROR("Invalid fileIndex: %d", fileIndex);
|
LOG_ERROR("Invalid fileIndex: %d", fileIndex);
|
||||||
|
@ -34,7 +39,12 @@ void network_receive_save_set_flag(struct Packet* p) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gSaveBuffer.files[fileIndex][0].courseStars[courseIndex] |= courseStars;
|
if (backupSlot > 1) {
|
||||||
gSaveBuffer.files[fileIndex][0].flags |= flags;
|
LOG_ERROR("Invalid backupSlot: %d", backupSlot);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gSaveBuffer.files[fileIndex][backupSlot].courseStars[courseIndex] |= courseStars;
|
||||||
|
gSaveBuffer.files[fileIndex][backupSlot].flags |= flags;
|
||||||
gSaveFileModified = TRUE;
|
gSaveFileModified = TRUE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue