This commit is contained in:
petrie911 2024-05-20 09:28:13 -05:00 committed by GitHub
parent 53c05e51a4
commit 566f9db5a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 391 additions and 28 deletions

View File

@ -146,7 +146,8 @@
"bgm.h": "c", "bgm.h": "c",
"*.tcc": "c", "*.tcc": "c",
"object_ram.h": "c", "object_ram.h": "c",
"sf64dma.h": "c" "sf64dma.h": "c",
"string": "c"
}, },
"C_Cpp_Runner.msvcBatchPath": "" "C_Cpp_Runner.msvcBatchPath": ""
} }

View File

@ -40,14 +40,21 @@
#define MODS_FPS_COUNTER 0 #define MODS_FPS_COUNTER 0
/** /**
* Object Ram Watch: * RAM modifier:
* Press C> while paused to cycle modes
*
* Cheats:
* Use D-Pad up and down to select a cheat
* Use D-Pad left and right to set its value
* Press L to set the value or twice to lock it
*
* Object Ram Editor:
* Watch up to seven addresses from the player and object arrays * Watch up to seven addresses from the player and object arrays
* Press C> while paused to enable/disable * Use D-Pad to move the cursor and change values
* Use D-PAD to move the cursor and change values
* Press L to edit the highlighted value * Press L to edit the highlighted value
*/ */
#define MODS_OBJECT_RAM 0 #define MODS_RAM_MOD 0
/* ************************* */ /* ************************* */
@ -59,8 +66,8 @@ void Map_LevelSelect(void);
static void Play_RenderFps(void); static void Play_RenderFps(void);
#endif #endif
#if MODS_OBJECT_RAM == 1 #if MODS_RAM_MOD == 1
void ObjectRam_Update(void); void RamMod_Update(void);
#endif #endif
#endif #endif

View File

@ -16,6 +16,7 @@ typedef enum MissionStatus {
/* 0 */ MISSION_COMPLETE, /* 0 */ MISSION_COMPLETE,
/* 1 */ MISSION_ACCOMPLISHED, /* 1 */ MISSION_ACCOMPLISHED,
/* 2 */ MISSION_WARP, /* 2 */ MISSION_WARP,
/* 3 */ MISSION_MAX,
} MissionStatus; } MissionStatus;
typedef struct Environment { typedef struct Environment {

View File

@ -48,12 +48,14 @@ typedef enum DrawMode {
/* 6 */ DRAW_UNK_VS, /* 6 */ DRAW_UNK_VS,
/* 7 */ DRAW_UNK_7, /* 7 */ DRAW_UNK_7,
/* 8 */ DRAW_ENDING, /* 8 */ DRAW_ENDING,
/* 9 */ DRAW_MAX,
} DrawMode; } DrawMode;
typedef enum LevelMode { typedef enum LevelMode {
/* 0 */ LEVELMODE_ON_RAILS, /* 0 */ LEVELMODE_ON_RAILS,
/* 1 */ LEVELMODE_ALL_RANGE, /* 1 */ LEVELMODE_ALL_RANGE,
/* 2 */ LEVELMODE_UNK_2, /* 2 */ LEVELMODE_UNK_2,
/* 3 */ LEVELMODE_MAX,
} LevelMode; } LevelMode;
typedef enum PlayerState1C8 { typedef enum PlayerState1C8 {
@ -71,6 +73,7 @@ typedef enum PlayerState1C8 {
/* 11 */ PLAYERSTATE_1C8_ANDROSS_MOUTH, /* 11 */ PLAYERSTATE_1C8_ANDROSS_MOUTH,
/* 12 */ PLAYERSTATE_1C8_12, /* 12 */ PLAYERSTATE_1C8_12,
/* 13 */ PLAYERSTATE_1C8_VS_STANDBY, /* 13 */ PLAYERSTATE_1C8_VS_STANDBY,
/* 14 */ PLAYERSTATE_1C8_MAX,
} PlayerState1C8; } PlayerState1C8;
typedef enum PlayerShotStatus { typedef enum PlayerShotStatus {
@ -102,6 +105,7 @@ typedef enum LaserStrength {
/* 1 */ LASERS_TWIN, /* 1 */ LASERS_TWIN,
/* 2 */ LASERS_HYPER, /* 2 */ LASERS_HYPER,
/* 3 */ LASERS_UNK_3, /* 3 */ LASERS_UNK_3,
/* 4 */ LASERS_MAX,
} LaserStrength; } LaserStrength;
typedef struct PlayerShot { typedef struct PlayerShot {

View File

@ -579,8 +579,8 @@ void Game_Update(void) {
gFillScreenGreen, gFillScreenBlue, gFillScreenAlpha); gFillScreenGreen, gFillScreenBlue, gFillScreenAlpha);
} }
Audio_dummy_80016A50(); Audio_dummy_80016A50();
#if MODS_OBJECT_RAM == 1 #if MODS_RAM_MOD == 1
ObjectRam_Update(); RamMod_Update();
#endif #endif
#if MODS_FPS_COUNTER == 1 #if MODS_FPS_COUNTER == 1
Play_RenderFps(); Play_RenderFps();
@ -591,7 +591,7 @@ void Game_Update(void) {
#if MODS_FPS_COUNTER == 1 #if MODS_FPS_COUNTER == 1
#include "../mods/fpscounter.c" #include "../mods/fpscounter.c"
#endif #endif
#if MODS_OBJECT_RAM == 1 #if MODS_RAM_MOD == 1
#include "../mods/object_ram.c" #include "../mods/object_ram.c"
#endif #endif

View File

@ -10,9 +10,10 @@ static RamEntry oRamEntries[7] = {
ORAM_OFF, ORAM_OFF,
}; };
static u32 selectNum = 0; static s32 holdTimer = 0;
static s32 oRamActive = true; static s32 selectNum = 0;
static u32 editMode = EDM_TYPE; static RamModMode oRamActive = RAMMOD_OFF;
static s32 editMode = EDM_TYPE;
static s32 editing = false; static s32 editing = false;
static s32 editingValue = false; static s32 editingValue = false;
static fu dataTemp; static fu dataTemp;
@ -272,14 +273,14 @@ void ObjectRam_DrawEntry(RamEntry* entry, s32 num) {
SET_DRAW_COLOR(EDM_INDEX) SET_DRAW_COLOR(EDM_INDEX)
Graphics_Printf("%02d", index); Graphics_Printf("%02d", index);
Graphics_DisplaySmallText(entry->x + 32, y, 1.0f, 1.0f, D_801619A0); Graphics_DisplaySmallText(x + 32, y, 1.0f, 1.0f, D_801619A0);
SET_DRAW_COLOR(EDM_MAX) SET_DRAW_COLOR(EDM_MAX)
Graphics_DisplaySmallText(x + 50, y, 1.0f, 1.0f, "."); Graphics_DisplaySmallText(x + 50, y, 1.0f, 1.0f, ".");
SET_DRAW_COLOR(EDM_OFFSET) SET_DRAW_COLOR(EDM_OFFSET)
Graphics_Printf("%03X", offset); Graphics_Printf("%03X", offset);
Graphics_DisplaySmallText(entry->x + 56, y, 1.0f, 1.0f, D_801619A0); Graphics_DisplaySmallText(x + 56, y, 1.0f, 1.0f, D_801619A0);
SET_DRAW_COLOR(EDM_FORMAT) SET_DRAW_COLOR(EDM_FORMAT)
Graphics_DisplaySmallText(x + 90, y, 1.0f, 1.0f, fmtTypes[entry->fmt]); Graphics_DisplaySmallText(x + 90, y, 1.0f, 1.0f, fmtTypes[entry->fmt]);
@ -321,15 +322,7 @@ void ObjectRam_Update(void) {
objArrays[ORAM_Player].ptr = gPlayer; objArrays[ORAM_Player].ptr = gPlayer;
objArrays[ORAM_Scenery360].ptr = gScenery360; objArrays[ORAM_Scenery360].ptr = gScenery360;
objArrays[ORAM_Player].count = gCamCount; objArrays[ORAM_Player].count = gCamCount;
contPress = &gControllerPress[gMainController];
contHold = &gControllerHold[gMainController];
if ((gPlayState == PLAY_PAUSE) && (contPress->button & R_CBUTTONS)) {
oRamActive = 1 - oRamActive;
}
if (!oRamActive || (gPlayState <= PLAY_INIT)) {
return;
}
if (contPress->button & L_TRIG) { if (contPress->button & L_TRIG) {
editing ^= 1; editing ^= 1;
} }
@ -391,3 +384,312 @@ void ObjectRam_Update(void) {
gTexturedLines[99].posBB.z = oRamEntries[selectNum].objPtr->pos.z; gTexturedLines[99].posBB.z = oRamEntries[selectNum].objPtr->pos.z;
} }
} }
bool sCheatSetup = false;
s32 sCheatOptions[] = { 2, 5, 1, 2, 1, 4, 2, 1, 2 };
s32 sCheatStates[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
CheatEntry cheats[CHEAT_MAX];
void CheatRam_Select(void) {
if (contPress->button & (U_JPAD | D_JPAD)) {
editMode += (contPress->button & D_JPAD) ? 1 : -1;
editMode = WRAP_MODE(editMode, ARRAY_COUNT(cheats));
selectNum = cheats[editMode].option;
} else if (contPress->button & (L_JPAD | R_JPAD)) {
selectNum += (contPress->button & R_JPAD) ? 1 : -1;
}
selectNum = WRAP_MODE(selectNum, cheats[editMode].optionMax + 1);
cheats[editMode].option = selectNum;
}
void CheatRam_RepairWings(void) {
if ((gPlayer[0].wings.rightState <= WINGSTATE_BROKEN) || (gPlayer[0].wings.leftState <= WINGSTATE_BROKEN)) {
func_enmy_80067A40();
}
}
void CheatRam_SpawnCheckpoint(void) {
static ItemCheckpoint* checkpoint = NULL;
s32 i;
if ((gLevelMode != LEVELMODE_ON_RAILS) || (gPlayer[0].state_1C8 != PLAYERSTATE_1C8_ACTIVE)) {
return;
}
if ((checkpoint != NULL) && (checkpoint->obj.status != OBJ_FREE)) {
return;
}
for (i = 0; i < ARRAY_COUNT(gItems); i++) {
if (gItems[i].obj.status == OBJ_FREE) {
Item_Initialize(&gItems[i]);
gItems[i].obj.status = OBJ_ACTIVE;
gItems[i].obj.id = OBJ_ITEM_CHECKPOINT;
gItems[i].obj.pos.x = gPlayer[0].pos.x + gPlayer[0].vel.x;
gItems[i].obj.pos.y = gPlayer[0].pos.y + gPlayer[0].vel.y;
gItems[i].obj.pos.z = gPlayer[0].trueZpos + gPlayer[0].vel.z;
Object_SetInfo(&gItems[i].info, gItems[i].obj.id);
break;
}
}
if (i == ARRAY_COUNT(gItems)) {
checkpoint = NULL;
}
}
void CheatRam_Setup(void) {
s32 i;
for (i = 0; i < ARRAY_COUNT(cheats); i++) {
CheatEntry* cheat = &cheats[i];
cheat->mode = i;
switch (cheat->mode) {
case CHEAT_SHIELDS:
cheat->option = cheat->optionMax = 100;
SET_CHEAT_RAM(&cheat->ram[0], &gPlayer[0].shields, Play_GetMaxShields())
break;
case CHEAT_LASERS:
cheat->option = LASERS_HYPER;
cheat->optionMax = LASERS_MAX - 1;
SET_CHEAT_RAM(&cheat->ram[0], &gLaserStrength[0], cheat->option)
cheat->ram[1].func = CheatRam_RepairWings;
break;
case CHEAT_BOMBS:
cheat->option = cheat->optionMax = 9;
SET_CHEAT_RAM(&cheat->ram[0], &gBombCount[0], cheat->option)
break;
case CHEAT_BOOST:
SET_CHEAT_RAM(&cheat->ram[0], &gPlayer[0].boostMeter, 0)
SET_CHEAT_RAM(&cheat->ram[1], &gPlayer[0].boostCooldown, false)
cheat->action = 1;
break;
case CHEAT_LIVES:
cheat->option = cheat->optionMax = 99;
SET_CHEAT_RAM(&cheat->ram[0], &gLifeCount[0], cheat->option)
break;
case CHEAT_TEAMMATES:
cheat->option = 0;
cheat->optionMax = 7;
SET_CHEAT_RAM(&cheat->ram[0], &gTeamShields[TEAM_ID_FALCO], 255)
SET_CHEAT_RAM(&cheat->ram[1], &gTeamShields[TEAM_ID_SLIPPY], 255)
SET_CHEAT_RAM(&cheat->ram[2], &gTeamShields[TEAM_ID_PEPPY], 255)
break;
case CHEAT_SPEED:
cheat->option = 60;
cheat->optionMax = 100;
cheat->action = 1;
SET_CHEAT_RAM(&cheat->ram[0], &gPlayer[0].baseSpeed, cheat->option)
break;
case CHEAT_HITS:
cheat->option = 500;
cheat->optionMax = 999;
SET_CHEAT_RAM(&cheat->ram[0], &gHitCount, cheat->option);
break;
case CHEAT_CHECKPOINT:
cheat->action = -1;
cheat->ram[0].func = CheatRam_SpawnCheckpoint;
break;
case CHEAT_COMPLETE:
cheat->option = MISSION_COMPLETE;
cheat->optionMax = MISSION_WARP;
cheat->action = 1;
if ((gCurrentLevel == LEVEL_METEO) || (gCurrentLevel == LEVEL_SECTOR_X)) {}
SET_CHEAT_RAM(&cheat->ram[0], &gMissionStatus, cheat->option)
break;
}
}
}
void CheatRam_SetValues(CheatRamEntry* cheat) {
s32 i;
for (i = 0; i < 4; i++) {
if (cheat[i].addr != NULL) {
switch (cheat[i].size) {
case 0:
cheat[i].func();
break;
case 1:
*((u8*) cheat[i].addr) = cheat[i].data.i;
break;
case 2:
*((u16*) cheat[i].addr) = cheat[i].data.i;
break;
case 3:
break;
case 4:
*cheat[i].addr = cheat[i].data;
break;
}
}
}
}
void CheatRam_UpdateEntry(CheatEntry* cheat) {
s32 teamnum;
s32 i;
s32 press = false;
s32 doublepress = false;
if (holdTimer == 0) {
holdTimer = 10;
press = true;
} else if (holdTimer != 0) {
doublepress = true;
}
if (cheat->action == 0) {
cheat->hold ^= doublepress;
} else if (cheat->action == 1) {
cheat->hold ^= press;
}
switch (editMode) {
case CHEAT_SHIELDS:
cheat->ram[0].data.i = (cheat->option / 100.0f) * Play_GetMaxShields();
break;
case CHEAT_BOOST:
break;
case CHEAT_SPEED:
cheat->ram[0].data.f = cheat->hold ? cheat->option : 40.0f;
break;
case CHEAT_TEAMMATES:
teamnum = (cheat->option % 4) - 1;
for (i = 0; i < 3; i++) {
cheat->ram[i].data.i = (cheat->option > 3) ? -1 : 255;
cheat->ram[i].size = (teamnum == -1) ? 4 : 3;
}
if (teamnum != -1) {
cheat->ram[teamnum].size = 4;
}
break;
case CHEAT_COMPLETE:
if ((gCurrentLevel == LEVEL_CORNERIA) && (gPlayer[0].state_1C8 != PLAYERSTATE_1C8_LEVEL_COMPLETE)) {
if ((gLevelMode == LEVELMODE_ON_RAILS) && (cheat->option == MISSION_COMPLETE)) {
gScenery360 = Memory_Allocate(200 * sizeof(Scenery360));
gLevelMode = LEVELMODE_ALL_RANGE;
} else if ((gLevelMode == LEVELMODE_ALL_RANGE) && (cheat->option == MISSION_ACCOMPLISHED)) {
gLevelMode = LEVELMODE_ON_RAILS;
}
}
gPlayer[0].state_1C8 = PLAYERSTATE_1C8_LEVEL_COMPLETE;
default:
cheat->ram[0].data.i = cheat->option;
break;
}
CheatRam_SetValues(cheat->ram);
}
const char* cheatNames[] = { "SHIELDS", "LASERS", "BOMBS", "BOOST", "LIVES",
"TEAM", "SPEED", "HITS", "CHECKPOINT", "MISSION" };
const char* laserNames[] = { "SINGLE", "TWIN", "HYPER", "UNUSED" };
const char* teamNames[] = { "ALL", "FALCO", "SLIPPY", "PEPPY" };
const char* statusNames[] = { "COMPLETE", "ACCOMPLISHED", "WARP" };
void CheatRam_DrawEntry(CheatMode mode, s32 x, s32 y, s32 option) {
switch (mode) {
case CHEAT_SHIELDS:
case CHEAT_HITS:
Graphics_Printf("%s: %3d", cheatNames[mode], option);
break;
case CHEAT_LASERS:
Graphics_Printf("%s: %s", cheatNames[mode], laserNames[option]);
break;
case CHEAT_COMPLETE:
Graphics_Printf("%s: %s", cheatNames[mode], statusNames[option]);
break;
case CHEAT_LIVES:
case CHEAT_BOMBS:
case CHEAT_SPEED:
Graphics_Printf("%s: %d", cheatNames[mode], option);
break;
case CHEAT_CHECKPOINT:
case CHEAT_BOOST:
Graphics_Printf("%s", cheatNames[mode]);
break;
case CHEAT_TEAMMATES:
Graphics_Printf("%s: %s %s", cheatNames[mode], (option > 3) ? "DOWN" : "HEAL", teamNames[option % 4]);
break;
}
Graphics_DisplaySmallText(x, y, 1.0f, 1.0f, D_801619A0);
}
s32 medalCount[] = { 150, 200, 150, 300, 0, 200, 100, 250, 200, 0, 150, 100, 150, 50, 0, 150, 150, 100, 200 };
void CheatRam_Update(void) {
s32 i;
s32 x = 10;
s32 y = 50;
if (!sCheatSetup) {
CheatRam_Setup();
selectNum = cheats[editMode].option;
sCheatSetup = true;
}
CheatRam_Select();
if (holdTimer != 0) {
holdTimer--;
}
if (contPress->button & L_TRIG) {
CheatRam_UpdateEntry(&cheats[editMode]);
}
for (i = 0; i < ARRAY_COUNT(cheats); i++) {
if ((cheats[i].action != -1) && (cheats[i].hold || ((i == editMode) && (holdTimer != 0)))) {
CheatRam_SetValues(cheats[i].ram);
}
}
RCP_SetupDL(&gMasterDisp, SETUPDL_76);
gDPSetPrimColor(gMasterDisp++, 0, 0, 255, 255, 0, 255);
Graphics_DisplaySmallText(x, y, 1.0f, 1.0f, "CHEATS");
y += 14;
for (i = 0; i < ARRAY_COUNT(cheats); i++) {
if (cheats[i].hold) {
gDPSetPrimColor(gMasterDisp++, 0x00, 0x00, 255, 0, 0, 255);
} else if (i == editMode) {
if (holdTimer == 0) {
gDPSetPrimColor(gMasterDisp++, 0x00, 0x00, 255, 170, 0, 255);
} else {
gDPSetPrimColor(gMasterDisp++, 0x00, 0x00, 255, 85, 0, 255);
}
} else {
gDPSetPrimColor(gMasterDisp++, 0x00, 0x00, 255, 255, 0, 255);
}
CheatRam_DrawEntry(cheats[i].mode, x, y + 11 * i, cheats[i].option);
}
}
void RamMod_Update(void) {
contPress = &gControllerPress[gMainController];
contHold = &gControllerHold[gMainController];
if ((gGameState != GSTATE_PLAY) || (gPlayState <= PLAY_INIT)) {
return;
}
if ((contPress->button & START_BUTTON) && (gPlayer[0].state_1C8 == PLAYERSTATE_1C8_LEVEL_COMPLETE)) {
gPlayer[0].state_1C8 = PLAYERSTATE_1C8_NEXT;
Audio_FadeOutAll(10);
gFadeoutType = 4;
gLeveLClearStatus[gCurrentLevel] = Play_CheckMedalStatus(medalCount[gCurrentLevel]) + 1;
cheats[CHEAT_COMPLETE].hold = false;
}
if ((gPlayState == PLAY_PAUSE) && (contPress->button & R_CBUTTONS)) {
oRamActive++;
oRamActive = WRAP_MODE(oRamActive, RAMMOD_MAX);
}
switch (oRamActive) {
case RAMMOD_OFF:
break;
case RAMMOD_CHEAT:
CheatRam_Update();
break;
case RAMMOD_OBJECT:
ObjectRam_Update();
break;
}
}

View File

@ -8,7 +8,7 @@
#define ORAM_OFF \ #define ORAM_OFF \
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 } { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
#define WRAP_MODE(val, max) ((u8) ((val) + (max)) % max) #define WRAP_MODE(val, max) ((u8) ((val) + (max)) % (max))
#define OBJ_ARRAY_INFO(objarr, name) \ #define OBJ_ARRAY_INFO(objarr, name) \
{ objarr, sizeof(*objarr), ARRAY_COUNT(objarr), name } { objarr, sizeof(*objarr), ARRAY_COUNT(objarr), name }
@ -21,17 +21,65 @@ typedef struct ObjArrayInfo {
} ObjArrayInfo; } ObjArrayInfo;
typedef struct RamEntry { typedef struct RamEntry {
u8 type; s16 type;
u8 index; s16 index;
s16 offset; s16 offset;
Object* objPtr; Object* objPtr;
void* dataPtr; void* dataPtr;
u8 fmt; s16 fmt;
u8 width; u8 width;
u16 x; u16 x;
u16 y; u16 y;
} RamEntry; } RamEntry;
typedef enum RamModMode {
RAMMOD_OFF,
RAMMOD_CHEAT,
RAMMOD_OBJECT,
RAMMOD_MAX,
} RamModMode;
typedef enum CheatMode {
CHEAT_SHIELDS,
CHEAT_LASERS,
CHEAT_BOMBS,
CHEAT_BOOST,
CHEAT_LIVES,
CHEAT_TEAMMATES,
CHEAT_SPEED,
CHEAT_HITS,
CHEAT_CHECKPOINT,
CHEAT_COMPLETE,
CHEAT_MAX,
} CheatMode;
typedef struct CheatRamEntry {
union {
fu* addr;
void (*func)(void);
};
s32 size;
fu data;
} CheatRamEntry;
#define SET_CHEAT_RAM(ram, address, value) \
{ \
(ram)->addr = (void*)(address); \
(ram)->size = sizeof(*(address)); \
(ram)->data.i = (value); \
}
typedef struct CheatEntry {
CheatMode mode;
CheatRamEntry ram[4];
s32 option;
s32 optionMax;
s32 action;
bool hold;
} CheatEntry;
typedef enum ObjectRamType { typedef enum ObjectRamType {
ORAM_NONE, ORAM_NONE,
ORAM_Player, ORAM_Player,

View File

@ -2263,7 +2263,7 @@ void Map_801A116C(void) {
Matrix_SetGfxMtx(&gMasterDisp); Matrix_SetGfxMtx(&gMasterDisp);
wings.rightState = wings.leftState = 2; wings.rightState = wings.leftState = WINGSTATE_INTACT;
// clang-format off // clang-format off
wings.unk_18 = wings.unk_1C = wings.unk_20 = wings.unk_24 = wings.unk_04 = wings.unk_18 = wings.unk_1C = wings.unk_20 = wings.unk_24 = wings.unk_04 =
wings.unk_08 = wings.unk_0C = wings.unk_10 = wings.unk_28 = 0.0f; wings.unk_08 = wings.unk_0C = wings.unk_10 = wings.unk_28 = 0.0f;