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{ gLuigiRaceway, gMooMooFarm, gKoopaTroopaBeach, gKalimariDesert }); - gFlowerCup = new Cup("mk:flower_cup", "flower cup", std::vector{ gToadsTurnpike, gFrappeSnowland, gChocoMountain, gMarioRaceway }); - gStarCup = new Cup("mk:star_cup", "star cup", std::vector{ gWarioStadium, gSherbetLand, gRoyalRaceway, gBowsersCastle }); - gSpecialCup = new Cup("mk:special_cup", "special cup", std::vector{ gDkJungle, gYoshiValley, gBansheeBoardwalk, gRainbowRoad }); - gBattleCup = new Cup("mk:battle_cup", "battle", std::vector{ gBigDonut, gBlockFort, gDoubleDeck, gSkyscraper }); + gMushroomCup = new Cup("mk:mushroom_cup", "mushroom cup", + std::vector{ gLuigiRaceway, gMooMooFarm, gKoopaTroopaBeach, gKalimariDesert }); + gFlowerCup = new Cup("mk:flower_cup", "flower cup", + std::vector{ gToadsTurnpike, gFrappeSnowland, gChocoMountain, gMarioRaceway }); + gStarCup = new Cup("mk:star_cup", "star cup", + std::vector{ gWarioStadium, gSherbetLand, gRoyalRaceway, gBowsersCastle }); + gSpecialCup = new Cup("mk:special_cup", "special cup", + std::vector{ gDkJungle, gYoshiValley, gBansheeBoardwalk, gRainbowRoad }); + gBattleCup = + new Cup("mk:battle_cup", "battle", std::vector{ 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(); - } - } - - - size_t GetCourseIndex() { - return gWorldInstance.CourseIndex; - } - - void SetCourse(const char* name) { - gWorldInstance.SetCourse(name); - } - - void NextCourse() { - gWorldInstance.NextCourse(); - } - - - 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 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(object)) {; - if (kart) { - kart->Waypoint(cameraId); - } - } - } - } - - 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; - } - } - - void CM_DrawBattleBombKarts(s32 cameraId) { - for (size_t i = 0; i < gPlayerCount; i++) { - gWorldInstance.playerBombKart[i].Draw(i, cameraId); - } - } - - void CM_ClearVehicles(void) { - gWorldInstance.Crossings.clear(); - } - - void CM_CrossingTrigger() { - for (auto& crossing : gWorldInstance.Crossings) { - if (crossing) { - crossing->CrossingTrigger(); - } - } - } - - void CM_AICrossingBehaviour(s32 playerId) { - for (auto& crossing : gWorldInstance.Crossings) { - if (crossing) { - crossing->AICrossingBehaviour(playerId); - } - } - } - - s32 CM_GetCrossingOnTriggered(uintptr_t* crossing) { - TrainCrossing* ptr = (TrainCrossing*) crossing; - if (ptr) { - return ptr->OnTriggered; - } - } - - void CM_LoadTextures() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->LoadTextures(); - } - } - - 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_RenderCredits() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->RenderCredits(); - } - } - - void CM_TickActors() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.TickActors(); - } - } - - void CM_DrawActors(Camera* camera, struct Actor* actor) { - AActor* a = gWorldInstance.ConvertActorToAActor(actor); - if (a->IsMod()) { - a->Draw(camera); - } - } - - void CM_BeginPlay() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->BeginPlay(); - } - } - - void CM_TickObjects() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.TickObjects(); - } - } - - // 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_DrawObjects(s32 cameraId) { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.DrawObjects(cameraId); - } - } - - void CM_TickParticles() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.TickParticles(); - } - } - - void CM_DrawParticles(s32 cameraId) { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.DrawParticles(cameraId); - } - } - - // Helps prevents users from forgetting to add a finishline to their course - bool CM_DoesFinishlineExist() { - for (AActor* actor : gWorldInstance.Actors) { - if (dynamic_cast(actor)) { - return true; - } - } - return false; - } - - void CM_InitClouds() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->InitClouds(); - } - } - - void CM_UpdateClouds(s32 arg0, Camera* camera) { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->UpdateClouds(arg0, camera); - } - } - - void CM_Waypoints(Player* player, int8_t playerId) { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->Waypoints(player, playerId); - } - } - - 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_MinimapSettings() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->MinimapSettings(); - } - } - - void CM_InitCourseObjects() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->InitCourseObjects(); - } - } - - void CM_UpdateCourseObjects() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->UpdateCourseObjects(); - } - TrainSmokeTick(); - } - - void CM_RenderCourseObjects(s32 cameraId) { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->RenderCourseObjects(cameraId); - } - - TrainSmokeDraw(cameraId); - } - - void CM_SomeSounds() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->SomeSounds(); - } - } - - void CM_CreditsSpawnActors() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->CreditsSpawnActors(); - } - } - - void CM_WhatDoesThisDo(Player* player, int8_t playerId) { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->WhatDoesThisDo(player, playerId); - } - } - - void CM_WhatDoesThisDoAI(Player* player, int8_t playerId) { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->WhatDoesThisDoAI(player, playerId); - } - } - - void CM_MinimapFinishlinePosition() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->MinimapFinishlinePosition(); - } - } - - void CM_SetStaffGhost() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->SetStaffGhost(); - } - } - - Properties* CM_GetProps() { - if (gWorldInstance.CurrentCourse) { - return &gWorldInstance.CurrentCourse->Props; - } - return NULL; - } - - void CM_ScrollingTextures() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->ScrollingTextures(); - } - } - - 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); - } - } - - /** - * This should only be ran once per course, otherwise animation/timings might become sped up. - */ - void CM_SpawnStarterLakitu() { - if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { - return; - } - - for (size_t i = 0; i < gPlayerCountSelection1; i++) { - OLakitu* lakitu = new OLakitu(i, OLakitu::LakituType::STARTER); - gWorldInstance.Lakitus[i] = lakitu; - gWorldInstance.AddObject(lakitu); - } - } - - // Checkered flag lakitu - void CM_ActivateFinishLakitu(s32 playerId) { - if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { - return; - } - gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINISH); - } - - void CM_ActivateSecondLapLakitu(s32 playerId) { - if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { - return; - } - gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::SECOND_LAP); - } - - void CM_ActivateFinalLapLakitu(s32 playerId) { - if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { - return; - } - gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINAL_LAP); - } - - void CM_ActivateReverseLakitu(s32 playerId) { - if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { - return; - } - gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::REVERSE); - } - - size_t GetCupCursorPosition() { - return gWorldInstance.CurrentCup->CursorPosition; - } - - void SetCupCursorPosition(size_t position) { - gWorldInstance.CurrentCup->SetCourse(position); - //gWorldInstance.CurrentCup->CursorPosition = position; - } - - size_t GetCupSize() { - return gWorldInstance.CurrentCup->GetSize(); - } - - void SetCourseFromCup() { - gWorldInstance.CurrentCourse = gWorldInstance.CurrentCup->GetCourse(); - } - - void* GetCourse(void) { - return gWorldInstance.CurrentCourse; - } - - void SetCourseByClass(void* course) { - gWorldInstance.CurrentCourse = (Course*) course; - } - - struct Actor* CM_GetActor(size_t index) { - if (index < gWorldInstance.Actors.size()) { - AActor* actor = gWorldInstance.Actors[index]; - return reinterpret_cast(reinterpret_cast(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((char*)actor - sizeof(void*)); - auto actors = gWorldInstance.Actors; - - auto it = std::find(actors.begin(), actors.end(), static_cast(a)); - if (it != actors.end()) { - return std::distance(actors.begin(), it); - } - printf("FindActorIndex() actor not found\n"); - return 0; - } - - void CM_DeleteActor(size_t index) { - std::vector 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_AddBaseActor(void) { - return (struct Actor*) gWorldInstance.AddBaseActor(); - } - - size_t CM_GetActorSize() { - return gWorldInstance.Actors.size(); - } - - void CM_ActorCollision(Player* player, Actor* actor) { - AActor* a = gWorldInstance.ConvertActorToAActor(actor); - - if (a->IsMod()) { - a->Collision(player, a); - } - } - - void* GetMarioRaceway(void) { - return gMarioRaceway; - } - - void* GetLuigiRaceway(void) { - return gLuigiRaceway; - } - - void* GetChocoMountain(void) { - return gChocoMountain; - } - - void* GetBowsersCastle(void) { - return gBowsersCastle; - } - - void* GetBansheeBoardwalk(void) { - return gBansheeBoardwalk; - } - - void* GetYoshiValley(void) { - return gYoshiValley; - } - - void* GetFrappeSnowland(void) { - return gFrappeSnowland; - } - - void* GetKoopaTroopaBeach(void) { - return gKoopaTroopaBeach; - } - - void* GetRoyalRaceway(void) { - return gRoyalRaceway; - } - - void* GetMooMooFarm(void) { - return gMooMooFarm; - } - - void* GetToadsTurnpike(void) { - return gToadsTurnpike; - } - - void* GetKalimariDesert(void) { - return gKalimariDesert; - } - - void* GetSherbetLand(void) { - return gSherbetLand; - } - - void* GetRainbowRoad(void) { - return gRainbowRoad; - } - - void* GetWarioStadium(void) { - return gWarioStadium; - } - - void* GetBlockFort(void) { - return gBlockFort; - } - - void* GetSkyscraper(void) { - return gSkyscraper; - } - - void* GetDoubleDeck(void) { - return gDoubleDeck; - } - - void* GetDkJungle(void) { - return gDkJungle; - } - - void* GetBigDonut(void) { - return gBigDonut; - } - - void* GetPodiumCeremony(void) { - return gPodiumCeremony; - } - - void* GetMushroomCup(void) { - return gMushroomCup; - } - - void* GetFlowerCup(void) { - return gFlowerCup; - } - - 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 LoadCourse() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->Load(); } } +size_t GetCourseIndex() { + return gWorldInstance.CourseIndex; +} + +void SetCourse(const char* name) { + gWorldInstance.SetCourse(name); +} + +void NextCourse() { + gWorldInstance.NextCourse(); +} + +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 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(object)) { + if (kart) { + kart->Waypoint(cameraId); + } + } + } +} + +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; + } +} + +void CM_DrawBattleBombKarts(s32 cameraId) { + for (size_t i = 0; i < gPlayerCount; i++) { + gWorldInstance.playerBombKart[i].Draw(i, cameraId); + } +} + +void CM_ClearVehicles(void) { + gWorldInstance.Crossings.clear(); +} + +void CM_CrossingTrigger() { + for (auto& crossing : gWorldInstance.Crossings) { + if (crossing) { + crossing->CrossingTrigger(); + } + } +} + +void CM_AICrossingBehaviour(s32 playerId) { + for (auto& crossing : gWorldInstance.Crossings) { + if (crossing) { + crossing->AICrossingBehaviour(playerId); + } + } +} + +s32 CM_GetCrossingOnTriggered(uintptr_t* crossing) { + TrainCrossing* ptr = (TrainCrossing*) crossing; + if (ptr) { + return ptr->OnTriggered; + } +} + +void CM_LoadTextures() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->LoadTextures(); + } +} + +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_RenderCredits() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->RenderCredits(); + } +} + +void CM_TickActors() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.TickActors(); + } +} + +void CM_DrawActors(Camera* camera, struct Actor* actor) { + AActor* a = gWorldInstance.ConvertActorToAActor(actor); + if (a->IsMod()) { + a->Draw(camera); + } +} + +void CM_BeginPlay() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->BeginPlay(); + } +} + +void CM_TickObjects() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.TickObjects(); + } +} + +// 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_DrawObjects(s32 cameraId) { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.DrawObjects(cameraId); + } +} + +void CM_TickParticles() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.TickParticles(); + } +} + +void CM_DrawParticles(s32 cameraId) { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.DrawParticles(cameraId); + } +} + +// Helps prevents users from forgetting to add a finishline to their course +bool CM_DoesFinishlineExist() { + for (AActor* actor : gWorldInstance.Actors) { + if (dynamic_cast(actor)) { + return true; + } + } + return false; +} + +void CM_InitClouds() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->InitClouds(); + } +} + +void CM_UpdateClouds(s32 arg0, Camera* camera) { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->UpdateClouds(arg0, camera); + } +} + +void CM_Waypoints(Player* player, int8_t playerId) { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->Waypoints(player, playerId); + } +} + +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_MinimapSettings() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->MinimapSettings(); + } +} + +void CM_InitCourseObjects() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->InitCourseObjects(); + } +} + +void CM_UpdateCourseObjects() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->UpdateCourseObjects(); + } + TrainSmokeTick(); +} + +void CM_RenderCourseObjects(s32 cameraId) { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->RenderCourseObjects(cameraId); + } + + TrainSmokeDraw(cameraId); +} + +void CM_SomeSounds() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->SomeSounds(); + } +} + +void CM_CreditsSpawnActors() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->CreditsSpawnActors(); + } +} + +void CM_WhatDoesThisDo(Player* player, int8_t playerId) { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->WhatDoesThisDo(player, playerId); + } +} + +void CM_WhatDoesThisDoAI(Player* player, int8_t playerId) { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->WhatDoesThisDoAI(player, playerId); + } +} + +void CM_MinimapFinishlinePosition() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->MinimapFinishlinePosition(); + } +} + +void CM_SetStaffGhost() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->SetStaffGhost(); + } +} + +Properties* CM_GetProps() { + if (gWorldInstance.CurrentCourse) { + return &gWorldInstance.CurrentCourse->Props; + } + return NULL; +} + +Properties* CM_GetPropsCourseId(s32 courseId) { + return &gWorldInstance.Courses[courseId]->Props; +} + +void CM_ScrollingTextures() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->ScrollingTextures(); + } +} + +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); + } +} + +/** + * This should only be ran once per course, otherwise animation/timings might become sped up. + */ +void CM_SpawnStarterLakitu() { + if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { + return; + } + + for (size_t i = 0; i < gPlayerCountSelection1; i++) { + OLakitu* lakitu = new OLakitu(i, OLakitu::LakituType::STARTER); + gWorldInstance.Lakitus[i] = lakitu; + gWorldInstance.AddObject(lakitu); + } +} + +// Checkered flag lakitu +void CM_ActivateFinishLakitu(s32 playerId) { + if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { + return; + } + gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINISH); +} + +void CM_ActivateSecondLapLakitu(s32 playerId) { + if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { + return; + } + gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::SECOND_LAP); +} + +void CM_ActivateFinalLapLakitu(s32 playerId) { + if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { + return; + } + gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINAL_LAP); +} + +void CM_ActivateReverseLakitu(s32 playerId) { + if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) { + return; + } + gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::REVERSE); +} + +size_t GetCupCursorPosition() { + return gWorldInstance.CurrentCup->CursorPosition; +} + +void SetCupCursorPosition(size_t position) { + gWorldInstance.CurrentCup->SetCourse(position); + // gWorldInstance.CurrentCup->CursorPosition = position; +} + +size_t GetCupSize() { + return gWorldInstance.CurrentCup->GetSize(); +} + +void SetCourseFromCup() { + gWorldInstance.CurrentCourse = gWorldInstance.CurrentCup->GetCourse(); +} + +void* GetCourse(void) { + return gWorldInstance.CurrentCourse; +} + +void SetCourseByClass(void* course) { + gWorldInstance.CurrentCourse = (Course*) course; +} + +struct Actor* CM_GetActor(size_t index) { + if (index < gWorldInstance.Actors.size()) { + AActor* actor = gWorldInstance.Actors[index]; + return reinterpret_cast(reinterpret_cast(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((char*) actor - sizeof(void*)); + auto actors = gWorldInstance.Actors; + + auto it = std::find(actors.begin(), actors.end(), static_cast(a)); + if (it != actors.end()) { + return std::distance(actors.begin(), it); + } + printf("FindActorIndex() actor not found\n"); + return 0; +} + +void CM_DeleteActor(size_t index) { + std::vector 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_AddBaseActor(void) { + return (struct Actor*) gWorldInstance.AddBaseActor(); +} + +size_t CM_GetActorSize() { + return gWorldInstance.Actors.size(); +} + +void CM_ActorCollision(Player* player, Actor* actor) { + AActor* a = gWorldInstance.ConvertActorToAActor(actor); + + if (a->IsMod()) { + a->Collision(player, a); + } +} + +void* GetMarioRaceway(void) { + return gMarioRaceway; +} + +void* GetLuigiRaceway(void) { + return gLuigiRaceway; +} + +void* GetChocoMountain(void) { + return gChocoMountain; +} + +void* GetBowsersCastle(void) { + return gBowsersCastle; +} + +void* GetBansheeBoardwalk(void) { + return gBansheeBoardwalk; +} + +void* GetYoshiValley(void) { + return gYoshiValley; +} + +void* GetFrappeSnowland(void) { + return gFrappeSnowland; +} + +void* GetKoopaTroopaBeach(void) { + return gKoopaTroopaBeach; +} + +void* GetRoyalRaceway(void) { + return gRoyalRaceway; +} + +void* GetMooMooFarm(void) { + return gMooMooFarm; +} + +void* GetToadsTurnpike(void) { + return gToadsTurnpike; +} + +void* GetKalimariDesert(void) { + return gKalimariDesert; +} + +void* GetSherbetLand(void) { + return gSherbetLand; +} + +void* GetRainbowRoad(void) { + return gRainbowRoad; +} + +void* GetWarioStadium(void) { + return gWarioStadium; +} + +void* GetBlockFort(void) { + return gBlockFort; +} + +void* GetSkyscraper(void) { + return gSkyscraper; +} + +void* GetDoubleDeck(void) { + return gDoubleDeck; +} + +void* GetDkJungle(void) { + return gDkJungle; +} + +void* GetBigDonut(void) { + return gBigDonut; +} + +void* GetPodiumCeremony(void) { + return gPodiumCeremony; +} + +void* GetMushroomCup(void) { + return gMushroomCup; +} + +void* GetFlowerCup(void) { + return gFlowerCup; +} + +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 #include #include +#include #include +#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