summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcoco875 <59367621+coco875@users.noreply.github.com>2025-01-26 02:43:30 +0100
committerGitHub <noreply@github.com>2025-01-25 18:43:30 -0700
commit995c60c85cac45d23dbcbfea45f29ec4ed7618b6 (patch)
tree55aa7092635da91e65a6bc1ff9f02134773e5122 /src
parenta37bb5afbd280949411ac9061ce54e92166325d8 (diff)
fix ghost (#175)
* fix ghost * remove a semi colon
Diffstat (limited to 'src')
-rw-r--r--src/menu_items.c160
-rw-r--r--src/port/Game.cpp837
-rw-r--r--src/port/Game.h8
-rw-r--r--src/save.c28
-rw-r--r--src/staff_ghosts.h4
-rw-r--r--src/stubs.c61
6 files changed, 589 insertions, 509 deletions
diff --git a/src/menu_items.c b/src/menu_items.c
index ddad11b1e..9987d17ef 100644
--- a/src/menu_items.c
+++ b/src/menu_items.c
@@ -339,7 +339,14 @@ char* gDebugCharacterNames[] = {
};
char* D_800E76A8[] = {
- "MARIO", "LUIGI", "YOSHI", "TOAD", "D.K.", "WARIO", "PEACH", "BOWSER",
+ "MARIO",
+ "LUIGI",
+ "YOSHI",
+ "TOAD",
+ "D.K.",
+ "WARIO",
+ "PEACH",
+ "BOWSER",
"\xA1\xBC\xA1\xBC\xA1\xBC\xA1\xBC", // These are EUC-JP characters. Looks sort of like - or ー
};
@@ -770,26 +777,27 @@ MenuTexture* D_800E7D74[] = {
D_02001E24,
};
-MenuTexture* D_800E7DC4[] = { seg2_mario_raceway_title_texture,
- seg2_choco_mountain_title_texture,
- D_02004EF8,
- D_02004F20,
- D_02004F48,
- D_02004F70,
- D_02004F98,
- D_02004FC0,
- D_02004FE8,
- D_02005010,
- D_02005038,
- D_02005060,
- D_02005088,
- D_020050B0,
- D_020050D8,
- D_02005100,
- D_02005128,
- D_02005150,
- D_02005178,
- D_020051A0,
+MenuTexture* D_800E7DC4[] = {
+ seg2_mario_raceway_title_texture,
+ seg2_choco_mountain_title_texture,
+ D_02004EF8,
+ D_02004F20,
+ D_02004F48,
+ D_02004F70,
+ D_02004F98,
+ D_02004FC0,
+ D_02004FE8,
+ D_02005010,
+ D_02005038,
+ D_02005060,
+ D_02005088,
+ D_020050B0,
+ D_020050D8,
+ D_02005100,
+ D_02005128,
+ D_02005150,
+ D_02005178,
+ D_020051A0,
};
// Unused?
@@ -820,27 +828,23 @@ MenuTexture* gGlyphTextureLUT[] = {
D_020029B4, D_0200301C, D_020029DC, D_02003044, D_02002A04, D_0200306C, D_02002A2C, D_02003094, D_02002A54,
D_020030BC, D_02002A7C, D_020030E4, D_02002AA4, D_0200310C, D_020033B4, D_02002ACC, D_02003134, D_02002AF4,
D_0200315C, D_02002B1C, D_02003184, D_02002B44, D_02002B6C, D_02002B94, D_02002BBC, D_02002BE4, D_02002C0C,
- D_020031AC, D_02003274, D_02002C34, D_020031D4, D_0200329C, D_02002C5C, D_020031FC, D_020032C4, D_02002C84, D_02003224,
- D_020032EC, D_02002CAC, D_0200324C, D_02003314, D_02002CD4, D_02002CFC, D_02002D24, D_02002D4C, D_02002D74,
- D_0200333C, D_02002D9C, D_02003364, D_02002DC4, D_0200338C, D_02002DEC, D_02002E14, D_02002E3C, D_02002E64,
- D_02002E8C, D_02002EB4, D_02002EDC, D_02002F04, D_02002F2C, D_020033DC, D_02003404, D_0200342C, D_02003454,
- D_0200347C, D_020034A4, D_020034CC, D_020034F4, D_0200351C, D_02003544, D_0200356C, D_02003BD4,
- D_02003594, D_02003BFC, D_020035BC, D_02003C24, D_020035E4, D_02003C4C, D_0200360C, D_02003C74,
- D_02003634, D_02003C9C, D_0200365C, D_02003CC4, D_02003684, D_02003CEC, D_020036AC, D_02003D14,
- D_020036D4, D_02003D3C, D_020036FC, D_02003D64, D_02003724, D_02003D8C, D_02004034, D_0200374C,
- D_02003DB4, D_02003774, D_02003DDC, D_0200379C, D_02003E04,
- D_020037C4, D_020037EC, D_02003814, D_0200383C, D_02003864, D_0200388C, D_02003E2C, D_02003EF4,
- D_020038B4, D_02003E54, D_02003F1C, D_020038DC, D_02003E7C, D_02003F44, D_02003904, D_02003EA4,
- D_02003F6C, D_0200392C, D_02003ECC, D_02003F94, D_02003954, D_0200397C, D_020039A4, D_020039CC,
- D_020039F4,
- D_02003FBC,
- D_02003A1C, D_02003FE4, D_02003A44, D_0200400C, D_02003A6C, D_02003A94, D_02003ABC, D_02003AE4, D_02003B0C,
- D_02003B34, D_02003B5C, D_02003B84, D_02003BAC, D_0200405C, D_02004084, D_020040AC, D_020040D4, D_020040FC,
- D_020043CC, D_02004444, D_0200437C, D_020043F4, D_02004124, D_0200414C, D_02004174, D_0200419C,
+ D_020031AC, D_02003274, D_02002C34, D_020031D4, D_0200329C, D_02002C5C, D_020031FC, D_020032C4, D_02002C84,
+ D_02003224, D_020032EC, D_02002CAC, D_0200324C, D_02003314, D_02002CD4, D_02002CFC, D_02002D24, D_02002D4C,
+ D_02002D74, D_0200333C, D_02002D9C, D_02003364, D_02002DC4, D_0200338C, D_02002DEC, D_02002E14, D_02002E3C,
+ D_02002E64, D_02002E8C, D_02002EB4, D_02002EDC, D_02002F04, D_02002F2C, D_020033DC, D_02003404, D_0200342C,
+ D_02003454, D_0200347C, D_020034A4, D_020034CC, D_020034F4, D_0200351C, D_02003544, D_0200356C, D_02003BD4,
+ D_02003594, D_02003BFC, D_020035BC, D_02003C24, D_020035E4, D_02003C4C, D_0200360C, D_02003C74, D_02003634,
+ D_02003C9C, D_0200365C, D_02003CC4, D_02003684, D_02003CEC, D_020036AC, D_02003D14, D_020036D4, D_02003D3C,
+ D_020036FC, D_02003D64, D_02003724, D_02003D8C, D_02004034, D_0200374C, D_02003DB4, D_02003774, D_02003DDC,
+ D_0200379C, D_02003E04, D_020037C4, D_020037EC, D_02003814, D_0200383C, D_02003864, D_0200388C, D_02003E2C,
+ D_02003EF4, D_020038B4, D_02003E54, D_02003F1C, D_020038DC, D_02003E7C, D_02003F44, D_02003904, D_02003EA4,
+ D_02003F6C, D_0200392C, D_02003ECC, D_02003F94, D_02003954, D_0200397C, D_020039A4, D_020039CC, D_020039F4,
+ D_02003FBC, D_02003A1C, D_02003FE4, D_02003A44, D_0200400C, D_02003A6C, D_02003A94, D_02003ABC, D_02003AE4,
+ D_02003B0C, D_02003B34, D_02003B5C, D_02003B84, D_02003BAC, D_0200405C, D_02004084, D_020040AC, D_020040D4,
+ D_020040FC, D_020043CC, D_02004444, D_0200437C, D_020043F4, D_02004124, D_0200414C, D_02004174, D_0200419C,
D_020041C4, D_020041EC, D_02004214, D_0200423C, D_02004264, D_0200428C, D_020042B4, D_020042DC, D_02004354,
D_020043A4, D_0200441C, D_0200446C, D_02004494, D_020044BC, D_02004304, D_0200432C, D_020044E4, D_0200450C,
- D_02004534,
- D_0200455C,
+ D_02004534, D_0200455C,
};
MenuTexture* D_800E8234[] = {
@@ -1857,7 +1861,7 @@ void print_text0(s32 column, s32 row, char* text, s32 tracking, f32 scaleX, f32
gSPDisplayList(gDisplayListHead++, D_020077D8);
}
-// Time trials
+// Time trials
void print_text0_wide_right(s32 column, s32 row, char* text, s32 tracking, f32 scaleX, f32 scaleY, s32 mode) {
s32 stringWidth = 0;
s32 glyphIndex;
@@ -1868,10 +1872,10 @@ void print_text0_wide_right(s32 column, s32 row, char* text, s32 tracking, f32 s
glyphIndex = char_to_glyph_index(text);
if (glyphIndex >= 0) {
load_menu_img((MenuTexture*) segmented_to_virtual_dupe((const void*) gGlyphTextureLUT[glyphIndex]));
- gDisplayListHead =
- print_letter_wide_right(gDisplayListHead,
- (MenuTexture*) segmented_to_virtual_dupe((const void*) gGlyphTextureLUT[glyphIndex]),
- column + (stringWidth * scaleX), row, mode, scaleX, scaleY);
+ gDisplayListHead = print_letter_wide_right(
+ gDisplayListHead,
+ (MenuTexture*) segmented_to_virtual_dupe((const void*) gGlyphTextureLUT[glyphIndex]),
+ column + (stringWidth * scaleX), row, mode, scaleX, scaleY);
stringWidth += gGlyphDisplayWidth[glyphIndex] + tracking;
} else if ((glyphIndex != -2) && (glyphIndex == -1)) {
stringWidth += tracking + 7;
@@ -2708,10 +2712,9 @@ func_80095BD0_label1:
rmonPrintf("MAX effectcount(760) over!!!!(kawano)\n");
return displayListHead;
func_80095BD0_label2:
- //func_80095AE0(&gGfxPool->mtxEffect[gMatrixEffectCount], arg2, arg3, arg6, arg7);
+ // func_80095AE0(&gGfxPool->mtxEffect[gMatrixEffectCount], arg2, arg3, arg6, arg7);
Mtx* mtx = SetTextMatrix(arg2, arg3, arg6, arg7);
- gSPMatrix(displayListHead++, mtx,
- G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPMatrix(displayListHead++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gMKLoadTextureTile_4b(displayListHead++, arg1, G_IM_FMT_I, arg4, 0, 0, 0, arg4, arg5, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
switch (arg4) {
@@ -2732,7 +2735,8 @@ func_80095BD0_label2:
return func_800959F8(displayListHead, var_a1);
}
-Gfx* func_80095BD0_wide_right(Gfx* displayListHead, u8* arg1, f32 arg2, f32 arg3, u32 arg4, u32 arg5, f32 arg6, f32 arg7) {
+Gfx* func_80095BD0_wide_right(Gfx* displayListHead, u8* arg1, f32 arg2, f32 arg3, u32 arg4, u32 arg5, f32 arg6,
+ f32 arg7) {
Vtx* var_a1;
// A match is a match, but why are goto's required here?
if (gMatrixEffectCount >= 0x2F7) {
@@ -2839,10 +2843,9 @@ Gfx* func_80096CD8(Gfx* displayListHead, s32 xPos, s32 yPos, u32 width, u32 heig
gDPSetCombineMode(displayListHead++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
// Directly load and draw the entire texture
- gDPLoadTextureBlock(
- displayListHead++, ((u8*)LOAD_ASSET(D_0B002A00)) + (random_int(128) * 2), G_IM_FMT_IA, G_IM_SIZ_16b, width, height, 0,
- G_TX_WRAP, G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD
- );
+ gDPLoadTextureBlock(displayListHead++, ((u8*) LOAD_ASSET(D_0B002A00)) + (random_int(128) * 2), G_IM_FMT_IA,
+ G_IM_SIZ_16b, width, height, 0, G_TX_WRAP, G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
// Clamp positions to valid range
s32 xStart = CLAMP(xPos << 2, -32768, 32767); // Ensure no overflow in fixed-point
s32 yStart = CLAMP(yPos << 2, -32768, 32767);
@@ -3253,7 +3256,8 @@ Gfx* draw_box_wide(Gfx* displayListHead, s32 ulx, s32 uly, s32 lrx, s32 lry, u32
}
// Time trials race data cannot be saved for ghost box and time trials replay box
-Gfx* draw_box_wide_right(Gfx* displayListHead, s32 ulx, s32 uly, s32 lrx, s32 lry, u32 red, u32 green, u32 blue, u32 alpha) {
+Gfx* draw_box_wide_right(Gfx* displayListHead, s32 ulx, s32 uly, s32 lrx, s32 lry, u32 red, u32 green, u32 blue,
+ u32 alpha) {
red &= 0xFF;
green &= 0xFF;
blue &= 0xFF;
@@ -4383,7 +4387,8 @@ Gfx* print_letter(Gfx* arg0, MenuTexture* glyphTexture, f32 arg2, f32 arg3, s32
return arg0;
}
-Gfx* print_letter_wide_right(Gfx* arg0, MenuTexture* glyphTexture, f32 arg2, f32 arg3, s32 mode, f32 scaleX, f32 scaleY) {
+Gfx* print_letter_wide_right(Gfx* arg0, MenuTexture* glyphTexture, f32 arg2, f32 arg3, s32 mode, f32 scaleX,
+ f32 scaleY) {
s32 var_v0;
u8* temp_v0_2;
f32 thing0;
@@ -4419,13 +4424,13 @@ Gfx* print_letter_wide_right(Gfx* arg0, MenuTexture* glyphTexture, f32 arg2, f32
switch (mode) {
case 1:
gSPDisplayList(arg0++, D_020077F8);
- arg0 = func_80095BD0_wide_right(arg0, temp_v0_2, var_s0->dX + arg2, var_s0->dY + arg3, var_s0->width,
- var_s0->height, scaleX, scaleY);
+ arg0 = func_80095BD0_wide_right(arg0, temp_v0_2, var_s0->dX + arg2, var_s0->dY + arg3,
+ var_s0->width, var_s0->height, scaleX, scaleY);
break;
case 2:
gSPDisplayList(arg0++, D_02007818);
- arg0 = func_80095BD0_wide_right(arg0, temp_v0_2, var_s0->dX + arg2, var_s0->dY + arg3, var_s0->width,
- var_s0->height, scaleX, scaleY);
+ arg0 = func_80095BD0_wide_right(arg0, temp_v0_2, var_s0->dX + arg2, var_s0->dY + arg3,
+ var_s0->width, var_s0->height, scaleX, scaleY);
break;
}
}
@@ -6245,8 +6250,7 @@ void render_menus(MenuItem* arg0) {
break;
case MENU_ITEM_TYPE_097:
set_text_color(TEXT_BLUE_GREEN_RED_CYCLE_2);
- print_text_mode_1(arg0->column, arg0->row, CM_GetProps()->Name, arg0->param1, arg0->paramf,
- 1.0f);
+ print_text_mode_1(arg0->column, arg0->row, CM_GetProps()->Name, arg0->param1, arg0->paramf, 1.0f);
break;
case MENU_ITEM_TYPE_098:
func_800A2D1C(arg0);
@@ -6756,12 +6760,12 @@ void render_menu_item_data_course_info(MenuItem* arg0) {
arg0->column = 0x14;
// name of the course
set_text_color(TEXT_BLUE_GREEN_RED_CYCLE_1);
- print_text1_center_mode_1(0x69, arg0->row + 0x19, CM_GetProps()->Name, 0, 0.75f, 0.75f);
+ print_text1_center_mode_1(0x69, arg0->row + 0x19, CM_GetPropsCourseId(courseId)->Name, 0, 0.75f, 0.75f);
// distance
set_text_color(TEXT_RED);
print_text_mode_1(0x2D, arg0->row + 0x28, (char*) &gTextDistance, 0, 0.75f, 0.75f);
- print_text1_left(0xA5, arg0->row + 0x28, CM_GetProps()->CourseLength, 1, 0.75f, 0.75f);
+ print_text1_left(0xA5, arg0->row + 0x28, CM_GetPropsCourseId(courseId)->CourseLength, 1, 0.75f, 0.75f);
// Best lap record
set_text_color(TEXT_YELLOW);
@@ -7004,8 +7008,8 @@ void func_800A1FB0(MenuItem* arg0) {
if (var_v1->ghostDataSaved == 0) {
print_text_mode_1(0x2A + (var_s1 * 0x89), 0x96 + (0x1E * var_s2), D_800E7A44, 0, 0.5f, 0.5f);
} else {
- print_text_mode_1(0x2A + (var_s1 * 0x89), 0x96 + (0x1E * var_s2),
- CM_GetProps()->Name, 0, 0.5f, 0.5f);
+ print_text_mode_1(0x2A + (var_s1 * 0x89), 0x96 + (0x1E * var_s2), CM_GetProps()->Name, 0, 0.5f,
+ 0.5f);
}
}
}
@@ -7041,8 +7045,8 @@ void func_800A1FB0(MenuItem* arg0) {
if (var_v1->ghostDataSaved == 0) {
print_text_mode_1(0x2A + (var_s1 * 0x89), 0x96 + (0x1E * var_s2), D_800E7A44, 0, 0.5f, 0.5f);
} else {
- print_text_mode_1(0x2A + (var_s1 * 0x89), 0x96 + (0x1E * var_s2),
- CM_GetProps()->Name, 0, 0.5f, 0.5f);
+ print_text_mode_1(0x2A + (var_s1 * 0x89), 0x96 + (0x1E * var_s2), CM_GetProps()->Name, 0, 0.5f,
+ 0.5f);
}
}
}
@@ -7091,8 +7095,8 @@ void func_800A1FB0(MenuItem* arg0) {
if (var_v1->ghostDataSaved == 0) {
print_text_mode_1(0x2A + (var_s1 * 0x89), 0x96 + (0x1E * var_s2), D_800E7A44, 0, 0.5f, 0.5f);
} else {
- print_text_mode_1(0x2A + (var_s1 * 0x89), 0x96 + (0x1E * var_s2),
- CM_GetProps()->Name, 0, 0.5f, 0.5f);
+ print_text_mode_1(0x2A + (var_s1 * 0x89), 0x96 + (0x1E * var_s2), CM_GetProps()->Name, 0, 0.5f,
+ 0.5f);
}
}
}
@@ -7488,8 +7492,8 @@ void func_800A3E60(MenuItem* arg0) {
if (D_8018EE10[var_s1].ghostDataSaved == 0) {
print_text_mode_1(0xBB - arg0->column, 0xAA + (0x1E * var_s1), D_800E7A44, 0, 0.45f, 0.45f);
} else {
- print_text_mode_1(0xBB - arg0->column, 0xAA + (0x1E * var_s1), CM_GetProps()->Name, 0,
- 0.45f, 0.45f);
+ print_text_mode_1(0xBB - arg0->column, 0xAA + (0x1E * var_s1), CM_GetProps()->Name, 0, 0.45f,
+ 0.45f);
}
}
break;
@@ -7836,8 +7840,7 @@ void render_pause_grand_prix(MenuItem* arg0) {
s32 rightEdge = OTRGetDimensionFromRightEdge(SCREEN_WIDTH);
gDisplayListHead = draw_box_wide(gDisplayListHead, leftEdge - rightEdge, temp_t0 - temp_t4,
leftEdge + rightEdge, temp_t0 + temp_t4, 0, 0, 0, 140);
- }
- break;
+ } break;
default:
gDisplayListHead = draw_box(gDisplayListHead, temp_v1 - temp_t3, temp_t0 - temp_t4, temp_v1 + temp_t3,
temp_t0 + temp_t4, 0, 0, 0, 140);
@@ -7982,8 +7985,8 @@ void render_menu_item_end_course_option(MenuItem* arg0) {
if (arg0->state == 0) {
if ((arg0->param1 >= 0x1E) && ((gGlobalTimer / 16) % 2)) {
why = get_string_width(gTextPauseButton[REPLAY]) * 0.8f;
- gDisplayListHead = draw_box_wide_right(gDisplayListHead, 0x000000C0, 0x00000021, (s32) (why) + 0xC6, 0x00000032,
- 0, 0, 0, 0x00000096);
+ gDisplayListHead = draw_box_wide_right(gDisplayListHead, 0x000000C0, 0x00000021, (s32) (why) + 0xC6,
+ 0x00000032, 0, 0, 0, 0x00000096);
set_text_color(TEXT_GREEN);
print_text_mode_1_wide_right(0x000000BF, 0x00000030, gTextPauseButton[REPLAY], 0, 0.8f, 0.8f);
}
@@ -8062,8 +8065,8 @@ void render_menu_item_end_course_option(MenuItem* arg0) {
if (D_8018EE10[var_s1].ghostDataSaved == 0) {
print_text_mode_1(0x69 - arg0->column, (0x96 + (0x14 * var_s1)), D_800E7A44, 0, 0.75f, 0.75f);
} else {
- print_text_mode_1(0x69 - arg0->column, (0x96 + (0x14 * var_s1)), CM_GetProps()->Name,
- 0, 0.75f, 0.75f);
+ print_text_mode_1(0x69 - arg0->column, (0x96 + (0x14 * var_s1)), CM_GetProps()->Name, 0, 0.75f,
+ 0.75f);
}
}
break;
@@ -8422,8 +8425,7 @@ void func_800A70E8(MenuItem* arg0) {
if (var_s0 < temp_f6) {
var_s0 = temp_f6;
}
- gDisplayListHead =
- draw_box_wide_right(gDisplayListHead, (192), 34, (var_s0 + 198), 57, 0, 0, 0, 150);
+ gDisplayListHead = draw_box_wide_right(gDisplayListHead, (192), 34, (var_s0 + 198), 57, 0, 0, 0, 150);
alpha = 0x180 - ((arg0->param1 % 32) * 8);
if (alpha >= 0x100) {
alpha = 0xFF;
diff --git a/src/port/Game.cpp b/src/port/Game.cpp
index d73f5ccdf..5ac56da94 100644
--- a/src/port/Game.cpp
+++ b/src/port/Game.cpp
@@ -50,7 +50,7 @@ extern "C" {
#include "render_courses.h"
#include "menus.h"
#include "update_objects.h"
-//#include "engine/wasm.h"
+// #include "engine/wasm.h"
}
extern "C" void Graphics_PushFrame(Gfx* data) {
@@ -141,11 +141,16 @@ void CustomEngineInit() {
gWorldInstance.AddCourse(gBigDonut);
gWorldInstance.AddCourse(gTestCourse);
- gMushroomCup = new Cup("mk:mushroom_cup", "mushroom cup", std::vector<Course*>{ gLuigiRaceway, gMooMooFarm, gKoopaTroopaBeach, gKalimariDesert });
- gFlowerCup = new Cup("mk:flower_cup", "flower cup", std::vector<Course*>{ gToadsTurnpike, gFrappeSnowland, gChocoMountain, gMarioRaceway });
- gStarCup = new Cup("mk:star_cup", "star cup", std::vector<Course*>{ gWarioStadium, gSherbetLand, gRoyalRaceway, gBowsersCastle });
- gSpecialCup = new Cup("mk:special_cup", "special cup", std::vector<Course*>{ gDkJungle, gYoshiValley, gBansheeBoardwalk, gRainbowRoad });
- gBattleCup = new Cup("mk:battle_cup", "battle", std::vector<Course*>{ gBigDonut, gBlockFort, gDoubleDeck, gSkyscraper });
+ gMushroomCup = new Cup("mk:mushroom_cup", "mushroom cup",
+ std::vector<Course*>{ gLuigiRaceway, gMooMooFarm, gKoopaTroopaBeach, gKalimariDesert });
+ gFlowerCup = new Cup("mk:flower_cup", "flower cup",
+ std::vector<Course*>{ gToadsTurnpike, gFrappeSnowland, gChocoMountain, gMarioRaceway });
+ gStarCup = new Cup("mk:star_cup", "star cup",
+ std::vector<Course*>{ gWarioStadium, gSherbetLand, gRoyalRaceway, gBowsersCastle });
+ gSpecialCup = new Cup("mk:special_cup", "special cup",
+ std::vector<Course*>{ gDkJungle, gYoshiValley, gBansheeBoardwalk, gRainbowRoad });
+ gBattleCup =
+ new Cup("mk:battle_cup", "battle", std::vector<Course*>{ gBigDonut, gBlockFort, gDoubleDeck, gSkyscraper });
/* Instantiate Cups */
gWorldInstance.AddCup(gMushroomCup);
@@ -172,574 +177,577 @@ void CustomEngineInit() {
// Model loader systems allows cutting pieces out of courses and making them actors.
// Commented out due to alleged stability issues.
- //gModelLoader.Add(bowserStatueList);
+ // gModelLoader.Add(bowserStatueList);
- //gModelLoader.Load();
+ // gModelLoader.Load();
}
extern "C" {
- World* GetWorld(void) {
- return &gWorldInstance;
- }
+World* GetWorld(void) {
+ return &gWorldInstance;
+}
- u32 WorldNextCup(void) {
- return gWorldInstance.NextCup();
- }
+u32 WorldNextCup(void) {
+ return gWorldInstance.NextCup();
+}
- u32 WorldPreviousCup(void) {
- return gWorldInstance.PreviousCup();
- }
+u32 WorldPreviousCup(void) {
+ return gWorldInstance.PreviousCup();
+}
- void CM_SetCup(void* cup) {
- gWorldInstance.SetCup((Cup*)cup);
- }
+void CM_SetCup(void* cup) {
+ gWorldInstance.SetCup((Cup*) cup);
+}
- void* GetCup() {
- return gWorldInstance.CurrentCup;
- }
+void* GetCup() {
+ return gWorldInstance.CurrentCup;
+}
- u32 GetCupIndex(void) {
- return gWorldInstance.GetCupIndex();
- }
+u32 GetCupIndex(void) {
+ return gWorldInstance.GetCupIndex();
+}
- const char* GetCupName(void) {
- return gWorldInstance.CurrentCup->Name;
- }
+const char* GetCupName(void) {
+ return gWorldInstance.CurrentCup->Name;
+}
- void LoadCourse() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->Load();
- }
+void LoadCourse() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->Load();
}
+}
+size_t GetCourseIndex() {
+ return gWorldInstance.CourseIndex;
+}
- size_t GetCourseIndex() {
- return gWorldInstance.CourseIndex;
- }
-
- void SetCourse(const char* name) {
- gWorldInstance.SetCourse(name);
- }
+void SetCourse(const char* name) {
+ gWorldInstance.SetCourse(name);
+}
- void NextCourse() {
- gWorldInstance.NextCourse();
- }
+void NextCourse() {
+ gWorldInstance.NextCourse();
+}
+void PreviousCourse() {
+ gWorldInstance.PreviousCourse();
+}
- void PreviousCourse() {
- gWorldInstance.PreviousCourse();
- }
-
- void SetCourseById(s32 course) {
- if (course < 0 || course >= gWorldInstance.Courses.size()) {
- return;
- }
- gWorldInstance.CourseIndex = course;
- gWorldInstance.CurrentCourse = gWorldInstance.Courses[gWorldInstance.CourseIndex];
+void SetCourseById(s32 course) {
+ if (course < 0 || course >= gWorldInstance.Courses.size()) {
+ return;
}
+ gWorldInstance.CourseIndex = course;
+ gWorldInstance.CurrentCourse = gWorldInstance.Courses[gWorldInstance.CourseIndex];
+}
- void CM_VehicleCollision(s32 playerId, Player* player) {
- for (auto& actor : gWorldInstance.Actors) {
- if (actor) {
- actor->VehicleCollision(playerId, player);
- }
+void CM_VehicleCollision(s32 playerId, Player* player) {
+ for (auto& actor : gWorldInstance.Actors) {
+ if (actor) {
+ actor->VehicleCollision(playerId, player);
}
}
+}
- void CM_BombKartsWaypoint(s32 cameraId) {
- for (auto& object : gWorldInstance.Objects) {
- if (auto kart = dynamic_cast<OBombKart*>(object)) {;
- if (kart) {
- kart->Waypoint(cameraId);
- }
+void CM_BombKartsWaypoint(s32 cameraId) {
+ for (auto& object : gWorldInstance.Objects) {
+ if (auto kart = dynamic_cast<OBombKart*>(object)) {
+ if (kart) {
+ kart->Waypoint(cameraId);
}
}
}
+}
- void CM_DisplayBattleBombKart(s32 playerId, s32 primAlpha) {
+void CM_DisplayBattleBombKart(s32 playerId, s32 primAlpha) {
- if ((playerId < 0) || (playerId > 4)) {
- return;
- }
-
- if (primAlpha == 0) {
- gWorldInstance.playerBombKart[playerId].state = PlayerBombKart::PlayerBombKartState::DISABLED;
- gWorldInstance.playerBombKart[playerId]._primAlpha = primAlpha;
- } else {
- gWorldInstance.playerBombKart[playerId].state = PlayerBombKart::PlayerBombKartState::ACTIVE;
- gWorldInstance.playerBombKart[playerId]._primAlpha = primAlpha;
- }
+ if ((playerId < 0) || (playerId > 4)) {
+ return;
}
- void CM_DrawBattleBombKarts(s32 cameraId) {
- for (size_t i = 0; i < gPlayerCount; i++) {
- gWorldInstance.playerBombKart[i].Draw(i, cameraId);
- }
+ if (primAlpha == 0) {
+ gWorldInstance.playerBombKart[playerId].state = PlayerBombKart::PlayerBombKartState::DISABLED;
+ gWorldInstance.playerBombKart[playerId]._primAlpha = primAlpha;
+ } else {
+ gWorldInstance.playerBombKart[playerId].state = PlayerBombKart::PlayerBombKartState::ACTIVE;
+ gWorldInstance.playerBombKart[playerId]._primAlpha = primAlpha;
}
+}
- void CM_ClearVehicles(void) {
- gWorldInstance.Crossings.clear();
+void CM_DrawBattleBombKarts(s32 cameraId) {
+ for (size_t i = 0; i < gPlayerCount; i++) {
+ gWorldInstance.playerBombKart[i].Draw(i, cameraId);
}
+}
- void CM_CrossingTrigger() {
- for (auto& crossing : gWorldInstance.Crossings) {
- if (crossing) {
- crossing->CrossingTrigger();
- }
- }
- }
+void CM_ClearVehicles(void) {
+ gWorldInstance.Crossings.clear();
+}
- void CM_AICrossingBehaviour(s32 playerId) {
- for (auto& crossing : gWorldInstance.Crossings) {
- if (crossing) {
- crossing->AICrossingBehaviour(playerId);
- }
+void CM_CrossingTrigger() {
+ for (auto& crossing : gWorldInstance.Crossings) {
+ if (crossing) {
+ crossing->CrossingTrigger();
}
}
+}
- s32 CM_GetCrossingOnTriggered(uintptr_t* crossing) {
- TrainCrossing* ptr = (TrainCrossing*) crossing;
- if (ptr) {
- return ptr->OnTriggered;
+void CM_AICrossingBehaviour(s32 playerId) {
+ for (auto& crossing : gWorldInstance.Crossings) {
+ if (crossing) {
+ crossing->AICrossingBehaviour(playerId);
}
}
+}
- void CM_LoadTextures() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->LoadTextures();
- }
+s32 CM_GetCrossingOnTriggered(uintptr_t* crossing) {
+ TrainCrossing* ptr = (TrainCrossing*) crossing;
+ if (ptr) {
+ return ptr->OnTriggered;
}
+}
- void CM_RenderCourse(struct UnkStruct_800DC5EC* arg0) {
- if (gWorldInstance.CurrentCourse->IsMod() == false) {
- if ((CVarGetInteger("gFreecam", 0) == true)) {
- // Render credits courses
- func_8029569C();
- return;
- }
- }
-
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->Render(arg0);
- }
+void CM_LoadTextures() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->LoadTextures();
}
+}
- void CM_RenderCredits() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->RenderCredits();
+void CM_RenderCourse(struct UnkStruct_800DC5EC* arg0) {
+ if (gWorldInstance.CurrentCourse->IsMod() == false) {
+ if ((CVarGetInteger("gFreecam", 0) == true)) {
+ // Render credits courses
+ func_8029569C();
+ return;
}
}
- void CM_TickActors() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.TickActors();
- }
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->Render(arg0);
}
+}
- void CM_DrawActors(Camera* camera, struct Actor* actor) {
- AActor* a = gWorldInstance.ConvertActorToAActor(actor);
- if (a->IsMod()) {
- a->Draw(camera);
- }
+void CM_RenderCredits() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->RenderCredits();
}
+}
- void CM_BeginPlay() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->BeginPlay();
- }
+void CM_TickActors() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.TickActors();
}
+}
- void CM_TickObjects() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.TickObjects();
- }
+void CM_DrawActors(Camera* camera, struct Actor* actor) {
+ AActor* a = gWorldInstance.ConvertActorToAActor(actor);
+ if (a->IsMod()) {
+ a->Draw(camera);
}
+}
- // A couple objects such as lakitu are ticked inside of process_game_tick which support 60fps.
- // This is a fallback to support that.
- void CM_TickObjects60fps() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.TickObjects60fps();
- }
+void CM_BeginPlay() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->BeginPlay();
}
+}
- void CM_DrawObjects(s32 cameraId) {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.DrawObjects(cameraId);
- }
+void CM_TickObjects() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.TickObjects();
}
+}
- void CM_TickParticles() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.TickParticles();
- }
+// A couple objects such as lakitu are ticked inside of process_game_tick which support 60fps.
+// This is a fallback to support that.
+void CM_TickObjects60fps() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.TickObjects60fps();
}
+}
- void CM_DrawParticles(s32 cameraId) {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.DrawParticles(cameraId);
- }
+void CM_DrawObjects(s32 cameraId) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.DrawObjects(cameraId);
}
+}
- // Helps prevents users from forgetting to add a finishline to their course
- bool CM_DoesFinishlineExist() {
- for (AActor* actor : gWorldInstance.Actors) {
- if (dynamic_cast<AFinishline*>(actor)) {
- return true;
- }
- }
- return false;
+void CM_TickParticles() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.TickParticles();
}
+}
- void CM_InitClouds() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->InitClouds();
- }
+void CM_DrawParticles(s32 cameraId) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.DrawParticles(cameraId);
}
+}
- void CM_UpdateClouds(s32 arg0, Camera* camera) {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->UpdateClouds(arg0, camera);
+// Helps prevents users from forgetting to add a finishline to their course
+bool CM_DoesFinishlineExist() {
+ for (AActor* actor : gWorldInstance.Actors) {
+ if (dynamic_cast<AFinishline*>(actor)) {
+ return true;
}
}
+ return false;
+}
- void CM_Waypoints(Player* player, int8_t playerId) {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->Waypoints(player, playerId);
- }
+void CM_InitClouds() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->InitClouds();
}
+}
- void CM_SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5,
- f32* arg6, f32* arg7) {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->SomeCollisionThing(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
- }
+void CM_UpdateClouds(s32 arg0, Camera* camera) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->UpdateClouds(arg0, camera);
}
+}
- void CM_MinimapSettings() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->MinimapSettings();
- }
+void CM_Waypoints(Player* player, int8_t playerId) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->Waypoints(player, playerId);
}
+}
- void CM_InitCourseObjects() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->InitCourseObjects();
- }
+void CM_SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6,
+ f32* arg7) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->SomeCollisionThing(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
+}
- void CM_UpdateCourseObjects() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->UpdateCourseObjects();
- }
- TrainSmokeTick();
+void CM_MinimapSettings() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->MinimapSettings();
}
+}
- void CM_RenderCourseObjects(s32 cameraId) {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->RenderCourseObjects(cameraId);
- }
-
- TrainSmokeDraw(cameraId);
+void CM_InitCourseObjects() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->InitCourseObjects();
}
+}
- void CM_SomeSounds() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->SomeSounds();
- }
+void CM_UpdateCourseObjects() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->UpdateCourseObjects();
}
+ TrainSmokeTick();
+}
- void CM_CreditsSpawnActors() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->CreditsSpawnActors();
- }
+void CM_RenderCourseObjects(s32 cameraId) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->RenderCourseObjects(cameraId);
}
- void CM_WhatDoesThisDo(Player* player, int8_t playerId) {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->WhatDoesThisDo(player, playerId);
- }
+ TrainSmokeDraw(cameraId);
+}
+
+void CM_SomeSounds() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->SomeSounds();
}
+}
- void CM_WhatDoesThisDoAI(Player* player, int8_t playerId) {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->WhatDoesThisDoAI(player, playerId);
- }
+void CM_CreditsSpawnActors() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->CreditsSpawnActors();
}
+}
- void CM_MinimapFinishlinePosition() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->MinimapFinishlinePosition();
- }
+void CM_WhatDoesThisDo(Player* player, int8_t playerId) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->WhatDoesThisDo(player, playerId);
}
+}
- void CM_SetStaffGhost() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->SetStaffGhost();
- }
+void CM_WhatDoesThisDoAI(Player* player, int8_t playerId) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->WhatDoesThisDoAI(player, playerId);
}
+}
- Properties* CM_GetProps() {
- if (gWorldInstance.CurrentCourse) {
- return &gWorldInstance.CurrentCourse->Props;
- }
- return NULL;
+void CM_MinimapFinishlinePosition() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->MinimapFinishlinePosition();
}
+}
- void CM_ScrollingTextures() {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->ScrollingTextures();
- }
+void CM_SetStaffGhost() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->SetStaffGhost();
}
+}
- void CM_DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
- if (gWorldInstance.CurrentCourse) {
- gWorldInstance.CurrentCourse->DrawWater(screen, pathCounter, cameraRot, playerDirection);
- }
+Properties* CM_GetProps() {
+ if (gWorldInstance.CurrentCourse) {
+ return &gWorldInstance.CurrentCourse->Props;
}
+ return NULL;
+}
- /**
- * This should only be ran once per course, otherwise animation/timings might become sped up.
- */
- void CM_SpawnStarterLakitu() {
- if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
- return;
- }
+Properties* CM_GetPropsCourseId(s32 courseId) {
+ return &gWorldInstance.Courses[courseId]->Props;
+}
- for (size_t i = 0; i < gPlayerCountSelection1; i++) {
- OLakitu* lakitu = new OLakitu(i, OLakitu::LakituType::STARTER);
- gWorldInstance.Lakitus[i] = lakitu;
- gWorldInstance.AddObject(lakitu);
- }
+void CM_ScrollingTextures() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->ScrollingTextures();
}
+}
- // Checkered flag lakitu
- void CM_ActivateFinishLakitu(s32 playerId) {
- if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
- return;
- }
- gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINISH);
+void CM_DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot,
+ uint16_t playerDirection) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.CurrentCourse->DrawWater(screen, pathCounter, cameraRot, playerDirection);
}
+}
- void CM_ActivateSecondLapLakitu(s32 playerId) {
- if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
- return;
- }
- gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::SECOND_LAP);
+/**
+ * This should only be ran once per course, otherwise animation/timings might become sped up.
+ */
+void CM_SpawnStarterLakitu() {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
- void CM_ActivateFinalLapLakitu(s32 playerId) {
- if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
- return;
- }
- gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINAL_LAP);
+ for (size_t i = 0; i < gPlayerCountSelection1; i++) {
+ OLakitu* lakitu = new OLakitu(i, OLakitu::LakituType::STARTER);
+ gWorldInstance.Lakitus[i] = lakitu;
+ gWorldInstance.AddObject(lakitu);
}
+}
- void CM_ActivateReverseLakitu(s32 playerId) {
- if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
- return;
- }
- gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::REVERSE);
+// Checkered flag lakitu
+void CM_ActivateFinishLakitu(s32 playerId) {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
+ gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINISH);
+}
- size_t GetCupCursorPosition() {
- return gWorldInstance.CurrentCup->CursorPosition;
+void CM_ActivateSecondLapLakitu(s32 playerId) {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
+ gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::SECOND_LAP);
+}
- void SetCupCursorPosition(size_t position) {
- gWorldInstance.CurrentCup->SetCourse(position);
- //gWorldInstance.CurrentCup->CursorPosition = position;
+void CM_ActivateFinalLapLakitu(s32 playerId) {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
+ gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINAL_LAP);
+}
- size_t GetCupSize() {
- return gWorldInstance.CurrentCup->GetSize();
+void CM_ActivateReverseLakitu(s32 playerId) {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
+ gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::REVERSE);
+}
- void SetCourseFromCup() {
- gWorldInstance.CurrentCourse = gWorldInstance.CurrentCup->GetCourse();
- }
+size_t GetCupCursorPosition() {
+ return gWorldInstance.CurrentCup->CursorPosition;
+}
- void* GetCourse(void) {
- return gWorldInstance.CurrentCourse;
- }
+void SetCupCursorPosition(size_t position) {
+ gWorldInstance.CurrentCup->SetCourse(position);
+ // gWorldInstance.CurrentCup->CursorPosition = position;
+}
- void SetCourseByClass(void* course) {
- gWorldInstance.CurrentCourse = (Course*) course;
- }
+size_t GetCupSize() {
+ return gWorldInstance.CurrentCup->GetSize();
+}
- struct Actor* CM_GetActor(size_t index) {
- if (index < gWorldInstance.Actors.size()) {
- AActor* actor = gWorldInstance.Actors[index];
- return reinterpret_cast<struct Actor*>(reinterpret_cast<char*>(actor) + sizeof(void*));
- } else {
- //throw std::runtime_error("GetActor() index out of bounds");
- return NULL;
- }
- }
+void SetCourseFromCup() {
+ gWorldInstance.CurrentCourse = gWorldInstance.CurrentCup->GetCourse();
+}
- size_t CM_FindActorIndex(Actor* actor) {
- // Move the ptr back to look at the vtable.
- // This gets us the proper C++ class instead of just the variables used in C.
- AActor* a = reinterpret_cast<AActor*>((char*)actor - sizeof(void*));
- auto actors = gWorldInstance.Actors;
+void* GetCourse(void) {
+ return gWorldInstance.CurrentCourse;
+}
- auto it = std::find(actors.begin(), actors.end(), static_cast<AActor*>(a));
- if (it != actors.end()) {
- return std::distance(actors.begin(), it);
- }
- printf("FindActorIndex() actor not found\n");
- return 0;
- }
+void SetCourseByClass(void* course) {
+ gWorldInstance.CurrentCourse = (Course*) course;
+}
- void CM_DeleteActor(size_t index) {
- std::vector<AActor*> actors = gWorldInstance.Actors;
- if (index < actors.size()) {
- actors.erase(actors.begin() + index);
- }
- }
-
- /**
- * Clean up actors and other game objects.
- */
- void CM_CleanWorld(void) {
- gWorldInstance.Actors.clear();
- gWorldInstance.Objects.clear();
- gWorldInstance.Emitters.clear();
- gWorldInstance.Lakitus.clear();
+struct Actor* CM_GetActor(size_t index) {
+ if (index < gWorldInstance.Actors.size()) {
+ AActor* actor = gWorldInstance.Actors[index];
+ return reinterpret_cast<struct Actor*>(reinterpret_cast<char*>(actor) + sizeof(void*));
+ } else {
+ // throw std::runtime_error("GetActor() index out of bounds");
+ return NULL;
}
+}
+
+size_t CM_FindActorIndex(Actor* actor) {
+ // Move the ptr back to look at the vtable.
+ // This gets us the proper C++ class instead of just the variables used in C.
+ AActor* a = reinterpret_cast<AActor*>((char*) actor - sizeof(void*));
+ auto actors = gWorldInstance.Actors;
- struct Actor* CM_AddBaseActor(void) {
- return (struct Actor*) gWorldInstance.AddBaseActor();
+ auto it = std::find(actors.begin(), actors.end(), static_cast<AActor*>(a));
+ if (it != actors.end()) {
+ return std::distance(actors.begin(), it);
}
+ printf("FindActorIndex() actor not found\n");
+ return 0;
+}
- size_t CM_GetActorSize() {
- return gWorldInstance.Actors.size();
+void CM_DeleteActor(size_t index) {
+ std::vector<AActor*> actors = gWorldInstance.Actors;
+ if (index < actors.size()) {
+ actors.erase(actors.begin() + index);
}
+}
- void CM_ActorCollision(Player* player, Actor* actor) {
- AActor* a = gWorldInstance.ConvertActorToAActor(actor);
+/**
+ * Clean up actors and other game objects.
+ */
+void CM_CleanWorld(void) {
+ gWorldInstance.Actors.clear();
+ gWorldInstance.Objects.clear();
+ gWorldInstance.Emitters.clear();
+ gWorldInstance.Lakitus.clear();
+}
- if (a->IsMod()) {
- a->Collision(player, a);
- }
- }
+struct Actor* CM_AddBaseActor(void) {
+ return (struct Actor*) gWorldInstance.AddBaseActor();
+}
- void* GetMarioRaceway(void) {
- return gMarioRaceway;
- }
+size_t CM_GetActorSize() {
+ return gWorldInstance.Actors.size();
+}
- void* GetLuigiRaceway(void) {
- return gLuigiRaceway;
- }
+void CM_ActorCollision(Player* player, Actor* actor) {
+ AActor* a = gWorldInstance.ConvertActorToAActor(actor);
- void* GetChocoMountain(void) {
- return gChocoMountain;
+ if (a->IsMod()) {
+ a->Collision(player, a);
}
+}
- void* GetBowsersCastle(void) {
- return gBowsersCastle;
- }
+void* GetMarioRaceway(void) {
+ return gMarioRaceway;
+}
- void* GetBansheeBoardwalk(void) {
- return gBansheeBoardwalk;
- }
+void* GetLuigiRaceway(void) {
+ return gLuigiRaceway;
+}
- void* GetYoshiValley(void) {
- return gYoshiValley;
- }
+void* GetChocoMountain(void) {
+ return gChocoMountain;
+}
- void* GetFrappeSnowland(void) {
- return gFrappeSnowland;
- }
+void* GetBowsersCastle(void) {
+ return gBowsersCastle;
+}
- void* GetKoopaTroopaBeach(void) {
- return gKoopaTroopaBeach;
- }
+void* GetBansheeBoardwalk(void) {
+ return gBansheeBoardwalk;
+}
- void* GetRoyalRaceway(void) {
- return gRoyalRaceway;
- }
+void* GetYoshiValley(void) {
+ return gYoshiValley;
+}
- void* GetMooMooFarm(void) {
- return gMooMooFarm;
- }
+void* GetFrappeSnowland(void) {
+ return gFrappeSnowland;
+}
- void* GetToadsTurnpike(void) {
- return gToadsTurnpike;
- }
+void* GetKoopaTroopaBeach(void) {
+ return gKoopaTroopaBeach;
+}
- void* GetKalimariDesert(void) {
- return gKalimariDesert;
- }
+void* GetRoyalRaceway(void) {
+ return gRoyalRaceway;
+}
- void* GetSherbetLand(void) {
- return gSherbetLand;
- }
+void* GetMooMooFarm(void) {
+ return gMooMooFarm;
+}
- void* GetRainbowRoad(void) {
- return gRainbowRoad;
- }
+void* GetToadsTurnpike(void) {
+ return gToadsTurnpike;
+}
- void* GetWarioStadium(void) {
- return gWarioStadium;
- }
+void* GetKalimariDesert(void) {
+ return gKalimariDesert;
+}
- void* GetBlockFort(void) {
- return gBlockFort;
- }
+void* GetSherbetLand(void) {
+ return gSherbetLand;
+}
- void* GetSkyscraper(void) {
- return gSkyscraper;
- }
+void* GetRainbowRoad(void) {
+ return gRainbowRoad;
+}
- void* GetDoubleDeck(void) {
- return gDoubleDeck;
- }
+void* GetWarioStadium(void) {
+ return gWarioStadium;
+}
- void* GetDkJungle(void) {
- return gDkJungle;
- }
+void* GetBlockFort(void) {
+ return gBlockFort;
+}
- void* GetBigDonut(void) {
- return gBigDonut;
- }
+void* GetSkyscraper(void) {
+ return gSkyscraper;
+}
- void* GetPodiumCeremony(void) {
- return gPodiumCeremony;
- }
+void* GetDoubleDeck(void) {
+ return gDoubleDeck;
+}
- void* GetMushroomCup(void) {
- return gMushroomCup;
- }
+void* GetDkJungle(void) {
+ return gDkJungle;
+}
- void* GetFlowerCup(void) {
- return gFlowerCup;
- }
+void* GetBigDonut(void) {
+ return gBigDonut;
+}
- void* GetStarCup(void) {
- return gStarCup;
- }
+void* GetPodiumCeremony(void) {
+ return gPodiumCeremony;
+}
- void* GetSpecialCup(void) {
- return gSpecialCup;
- }
+void* GetMushroomCup(void) {
+ return gMushroomCup;
+}
- void* GetBattleCup(void) {
- return gBattleCup;
- }
+void* GetFlowerCup(void) {
+ return gFlowerCup;
+}
- // End of frame cleanup of actors, objects, etc.
- void CM_RunGarbageCollector(void) {
- RunGarbageCollector();
- }
+void* GetStarCup(void) {
+ return gStarCup;
+}
+
+void* GetSpecialCup(void) {
+ return gSpecialCup;
+}
+
+void* GetBattleCup(void) {
+ return gBattleCup;
+}
+
+// End of frame cleanup of actors, objects, etc.
+void CM_RunGarbageCollector(void) {
+ RunGarbageCollector();
+}
}
void push_frame() {
- GameEngine::StartAudioFrame();
- GameEngine::Instance->StartFrame();
- thread5_iteration();
- GameEngine::EndAudioFrame();
+ GameEngine::StartAudioFrame();
+ GameEngine::Instance->StartFrame();
+ thread5_iteration();
+ GameEngine::EndAudioFrame();
// thread5_game_loop();
// Graphics_ThreadUpdate();w
// Timer_Update();
@@ -751,9 +759,10 @@ int SDL_main(int argc, char** argv) {
#if defined(__cplusplus) && defined(PLATFORM_IOS)
extern "C"
#endif
-int main(int argc, char* argv[]) {
+ int
+ main(int argc, char* argv[]) {
#endif
- //load_wasm();
+ // load_wasm();
GameEngine::Create();
audio_init();
sound_init();
diff --git a/src/port/Game.h b/src/port/Game.h
index 832cfc10d..5ef93fa1d 100644
--- a/src/port/Game.h
+++ b/src/port/Game.h
@@ -12,6 +12,7 @@ extern "C" {
#include "actor_types.h"
Properties* CM_GetProps();
+Properties* CM_GetPropsCourseId(s32 courseId);
void CM_DisplayBattleBombKart(s32 playerId, s32 primAlpha);
void CM_DrawBattleBombKarts(s32 cameraId);
@@ -64,8 +65,8 @@ void CM_UpdateClouds(s32 arg0, Camera* camera);
void CM_Waypoints(Player* player, int8_t playerId);
-void CM_SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5,
- f32* arg6, f32* arg7);
+void CM_SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6,
+ f32* arg7);
void CM_MinimapSettings();
@@ -95,7 +96,8 @@ s32 CM_GetCrossingOnTriggered(uintptr_t* crossing);
void CM_BeginPlay();
-void CM_DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection);
+void CM_DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot,
+ uint16_t playerDirection);
void CM_AICrossingBehaviour(s32 playerId);
diff --git a/src/save.c b/src/save.c
index 8197375ba..fd5440f50 100644
--- a/src/save.c
+++ b/src/save.c
@@ -11,6 +11,7 @@
#include "staff_ghosts.h"
#include "code_80057C60.h"
#include "port/Game.h"
+#include "buffers.h"
/*** macros ***/
#define PFS_COMPANY_CODE(c0, c1) ((u16) (((c0) << 8) | ((c1))))
@@ -32,9 +33,7 @@ s8 sControllerPak2State = BAD;
// default time trial records in little endian form
const u8 D_800F2E60[4] = { 0xc0, 0x27, 0x09, 0x00 };
// osPfsFindFile -> gGameName ("MARIOKART64" in nosFont)
-const u8 gGameName[] = {
- 0x26, 0x1a, 0x2b, 0x22, 0x28, 0x24, 0x1a, 0x2b, 0x2d, 0x16, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00
-};
+const u8 gGameName[] = "MARIOKART64";
// ext_name param to osPfsFindFile (four total bytes, but only one is setable)
const u8 gExtCode[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -483,7 +482,7 @@ void func_800B559C(s32 arg0) {
* But only unknown bytes 7 and 8 ever get set, so why the extra 3, and why in chunks of 17?
**/
u8 func_800B578C(s32 arg0) {
- u8* times = (u8*)&gSaveData.onlyBestTimeTrialRecords[arg0];
+ u8* times = (u8*) &gSaveData.onlyBestTimeTrialRecords[arg0];
s32 checksum = 0;
s32 i;
s32 j;
@@ -559,6 +558,7 @@ s32 validate_save_data_checksum_backup(void) {
// Check if controller has a Controller Pak connected.
// Return PAK if it does, otherwise return NO_PAK.
s32 check_for_controller_pak(s32 controller) {
+ return PAK;
u8 controllerBitpattern = 0;
UNUSED s32 phi_v0;
@@ -746,7 +746,7 @@ u8 func_800B60E8(s32 page) {
u32 checksum = 0;
u8* addr;
- for (i = 0, addr = (u8*) &((u8*) gReplayGhostCompressed)[page * 256]; i < 256; i++) {
+ for (i = 0, addr = (u8*) &((u8*) sReplayGhostDecompressed)[page * 256]; i < 256; i++) {
checksum += (*addr++ * (page + 1) + i);
}
return checksum;
@@ -776,8 +776,9 @@ s32 func_800B6178(s32 arg0) {
temp_s3->unk_07[var_s0] = var_s0;
}
} else {
- var_v0 = osPfsReadWriteFile(&gControllerPak1FileHandle, gControllerPak1FileNote, 1U, (arg0 * 0x3C00) + 0x100,
- 0x00003C00, (u8*) gReplayGhostCompressed);
+ var_v0 =
+ osPfsReadWriteFile(&gControllerPak1FileHandle, gControllerPak1FileNote, 1U,
+ (arg0 * (sizeof(u8) * 0x1000)) + 0x100, sizeof(u8) * 0x1000, (u8*) sReplayGhostBuffer);
if (var_v0 == 0) {
temp_s3->ghostDataSaved = 1;
if (gGamestate == 4) {
@@ -865,8 +866,10 @@ s32 func_800B64EC(s32 arg0) {
return -1;
}
- temp_v0 = osPfsReadWriteFile(&gControllerPak1FileHandle, gControllerPak1FileNote, PFS_READ, (arg0 * 0x3C00) + 0x100,
- 0x3C00, (u8*) gReplayGhostCompressed);
+ sReplayGhostDecompressed = (u32*) &D_802BFB80.arraySize8[0][D_80162DC8][3];
+ temp_v0 =
+ osPfsReadWriteFile(&gControllerPak1FileHandle, gControllerPak1FileNote, PFS_READ,
+ (arg0 * (sizeof(u8) * 0x1000)) + 0x100, sizeof(u8) * 0x1000, (u8*) sReplayGhostDecompressed);
if (temp_v0 == 0) {
// clang-format off
phi_s1 = (u8 *) &D_8018EE10[arg0]; temp_s0 = 0; while (1) {
@@ -903,8 +906,9 @@ s32 func_800B65F4(s32 arg0, s32 arg1) {
default:
return -1;
}
- writeStatus = osPfsReadWriteFile(&gControllerPak2FileHandle, gControllerPak2FileNote, 0U, (arg0 * 0x3C00) + 0x100,
- 0x00003C00, (u8*) gReplayGhostCompressed);
+ writeStatus =
+ osPfsReadWriteFile(&gControllerPak2FileHandle, gControllerPak2FileNote, 0U,
+ (arg0 * (sizeof(u8) * 0x1000)) + 0x100, sizeof(u8) * 0x1000, (u8*) sReplayGhostBuffer);
if (writeStatus == 0) {
temp_s3 = &((struct_8018EE10_entry*) gSomeDLBuffer)[arg0];
for (i = 0; i < 0x3C; i++) {
@@ -1000,7 +1004,7 @@ s32 func_800B6A68(void) {
s32 i;
ret = osPfsAllocateFile(&gControllerPak1FileHandle, gCompanyCode, gGameCode, (u8*) &gGameName, (u8*) &gExtCode,
- 0x7900, &gControllerPak1FileNote);
+ sizeof(u8) * 0x1000 * 2 + 0x100, &gControllerPak1FileNote);
if (ret == 0) {
for (i = 0; i < 2; i++) {
func_800B69BC(i);
diff --git a/src/staff_ghosts.h b/src/staff_ghosts.h
index 9e7e316a6..89788d3bb 100644
--- a/src/staff_ghosts.h
+++ b/src/staff_ghosts.h
@@ -39,4 +39,8 @@ extern s32 D_80162DF0;
extern s32 D_80162DF4;
extern s32 D_80162DF8;
+extern u8* sReplayGhostBuffer;
+extern s16 sReplayGhostBufferSize;
+extern u32* sReplayGhostDecompressed;
+
#endif /* STAFF_GHOSTS_H */
diff --git a/src/stubs.c b/src/stubs.c
index 0f383ea6b..fad163043 100644
--- a/src/stubs.c
+++ b/src/stubs.c
@@ -1,7 +1,18 @@
#include <libultraship.h>
#include <libultraship/libultra.h>
#include <string.h>
+#include <stdio.h>
#include <stubs.h>
+#include "save.h"
+
+struct state_pak {
+ OSPfsState state;
+ FILE* file;
+};
+
+struct state_pak openFile[16];
+
+int fileIndex = 0;
u32 osTvType = OS_TV_NTSC;
u32 osResetType;
@@ -54,13 +65,35 @@ OSYieldResult osSpTaskYielded(OSTask* task) {
}
s32 osPfsDeleteFile(OSPfs* pfs, u16 company_code, u32 game_code, u8* game_name, u8* ext_name) {
+ char filename[1024];
+ sprintf(filename, "channel_%d_%hu_%hd_%s.sav", pfs->channel, company_code, game_code, game_name);
+ remove(filename);
+ return PFS_NO_ERROR;
}
s32 osPfsReadWriteFile(OSPfs* pfs, s32 file_no, u8 flag, int offset, int size_in_bytes, u8* data_buffer) {
+ if (flag == PFS_READ) {
+ fseek(openFile[file_no].file, offset, SEEK_SET);
+ fread(data_buffer, size_in_bytes, 1, openFile[file_no].file);
+ } else {
+ fseek(openFile[file_no].file, offset, SEEK_SET);
+ fwrite(data_buffer, size_in_bytes, 1, openFile[file_no].file);
+ }
+ return PFS_NO_ERROR;
}
s32 osPfsAllocateFile(OSPfs* pfs, u16 company_code, u32 game_code, u8* game_name, u8* ext_name, int file_size_in_bytes,
s32* file_no) {
+ char filename[1024];
+ sprintf(filename, "channel_%d_%hu_%hd_%s.sav", pfs->channel, company_code, game_code, game_name);
+ *file_no = fileIndex++;
+ openFile[*file_no].file = fopen(filename, "w+");
+ fwrite("\0", 1, file_size_in_bytes, openFile[*file_no].file);
+ openFile[*file_no].state.company_code = company_code;
+ openFile[*file_no].state.game_code = game_code;
+ strcpy(openFile[*file_no].state.game_name, game_name);
+ strcpy(openFile[*file_no].state.ext_name, ext_name);
+ return PFS_NO_ERROR;
}
void osSetTime(OSTime time) {
@@ -70,9 +103,16 @@ s32 osPfsIsPlug(OSMesgQueue* queue, u8* pattern) {
}
s32 osPfsInit(OSMesgQueue* queue, OSPfs* pfs, int channel) {
+ pfs->queue = queue;
+ pfs->channel = channel;
+ pfs->status = 0;
+ pfs->status |= PFS_INITIALIZED;
+ return PFS_NO_ERROR;
}
s32 osPfsNumFiles(OSPfs* pfs, s32* max_files, s32* files_used) {
+ *max_files = 16;
+ *files_used = fileIndex;
return 0;
}
@@ -83,4 +123,23 @@ s32 osPfsFreeBlocks(OSPfs* pfs, s32* bytes_not_used) {
}
s32 osPfsFindFile(OSPfs* pfs, u16 company_code, u32 game_code, u8* game_name, u8* ext_name, s32* file_no) {
-}
+ char filename[1024];
+ sprintf(filename, "channel_%d_%hu_%hd_%s.sav", pfs->channel, company_code, game_code, game_name);
+ for (int i = 0; i < 16; i++) {
+ if (openFile[i].state.game_code == game_code && openFile[i].state.company_code == company_code &&
+ strcmp(openFile[i].state.game_name, game_name) == 0 && strcmp(openFile[i].state.ext_name, ext_name) == 0) {
+ *file_no = i;
+ return PFS_NO_ERROR;
+ }
+ }
+ *file_no = fileIndex++;
+ openFile[*file_no].file = fopen(filename, "r+");
+ if (openFile[*file_no].file == NULL) {
+ openFile[*file_no].file = fopen(filename, "w+");
+ }
+ openFile[*file_no].state.company_code = company_code;
+ openFile[*file_no].state.game_code = game_code;
+ strcpy(openFile[*file_no].state.game_name, game_name);
+ strcpy(openFile[*file_no].state.ext_name, ext_name);
+ return PFS_NO_ERROR;
+} \ No newline at end of file