diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..3dd31e6e --- /dev/null +++ b/.flake8 @@ -0,0 +1,4 @@ +[flake8] +# E203: whitespace before ':' +# E501: line too long +extend-ignore = E203,E501 diff --git a/config/GMPE01_00/rels/safDll/symbols.txt b/config/GMPE01_00/rels/safDll/symbols.txt index 11ae3d8d..44b3c3c7 100644 --- a/config/GMPE01_00/rels/safDll/symbols.txt +++ b/config/GMPE01_00/rels/safDll/symbols.txt @@ -1,13 +1,15 @@ fn_1_0 = .text:0x00000000; // type:function size:0x4 -fn_1_4 = .text:0x00000004; // type:function size:0x284 -fn_1_288 = .text:0x00000288; // type:function size:0x124 +safMarioEyeDim = .text:0x00000004; // type:function size:0x284 +safSaveTest = .text:0x00000288; // type:function size:0x124 _ctors = .ctors:0x00000000; // type:label scope:global _dtors = .dtors:0x00000000; // type:label scope:global -lbl_1_rodata_10 = .rodata:0x00000010; // type:object size:0x4 data:float -lbl_1_rodata_14 = .rodata:0x00000014; // type:object size:0x4 data:float -lbl_1_rodata_18 = .rodata:0x00000018; // type:object size:0x8 data:double -lbl_1_rodata_20 = .rodata:0x00000020; // type:object size:0x4 data:float -lbl_1_data_4 = .data:0x00000004; // type:object size:0xE data:string -lbl_1_data_12 = .data:0x00000012; // type:object size:0xB data:string -lbl_1_data_1D = .data:0x0000001D; // type:object size:0xE data:string -lbl_1_data_2B = .data:0x0000002B; // type:object size:0xE data:string +lbl_1_rodata_10 = .rodata:0x00000010; // type:object size:0x4 scope:local data:float +lbl_1_rodata_14 = .rodata:0x00000014; // type:object size:0x4 scope:local data:float +lbl_1_rodata_18 = .rodata:0x00000018; // type:object size:0x8 scope:local data:double +lbl_1_rodata_20 = .rodata:0x00000020; // type:object size:0x4 scope:local data:float +lbl_1_data_0 = .data:0x00000000; // type:object size:0x4 +lbl_1_data_4 = .data:0x00000004; // type:object size:0xE scope:local data:string +lbl_1_data_12 = .data:0x00000012; // type:object size:0xB scope:local data:string +lbl_1_data_1D = .data:0x0000001D; // type:object size:0xE scope:local data:string +lbl_1_data_2B = .data:0x0000002B; // type:object size:0xE scope:local data:string +lbl_1_bss_0 = .bss:0x00000000; // type:object size:0x300 diff --git a/config/GMPE01_00/symbols.txt b/config/GMPE01_00/symbols.txt index b4c32041..c1a3fc7e 100644 --- a/config/GMPE01_00/symbols.txt +++ b/config/GMPE01_00/symbols.txt @@ -1143,7 +1143,7 @@ BoardPlayerMotionSpeedSet = .text:0x80063AFC; // type:function size:0x80 BoardPlayerMotionTimeSet = .text:0x80063B7C; // type:function size:0x80 BoardPlayerMotionTimeGet = .text:0x80063BFC; // type:function size:0x78 BoardPlayerMotionMaxTimeGet = .text:0x80063C74; // type:function size:0x78 -BoardPlayerMotionTimeRangeSet = .text:0x80063CEC; // type:function size:0xA0 +BoardPlayerMotionStartEndSet = .text:0x80063CEC; // type:function size:0xA0 BoardPlayerModelAttrSet = .text:0x80063D8C; // type:function size:0x80 BoardPlayerModelAttrReset = .text:0x80063E0C; // type:function size:0x80 BoardPlayerCoinsSet = .text:0x80063E8C; // type:function size:0x34 @@ -1798,8 +1798,8 @@ ExecComFortuneWin = .text:0x8009DA78; // type:function size:0x18C scope:local ConfigComFortune = .text:0x8009DC04; // type:function size:0x20C scope:local ComFortuneAddStar = .text:0x8009DE10; // type:function size:0x78 scope:local ComFortuneAddCoin = .text:0x8009DE88; // type:function size:0x78 scope:local -ComFortuneSwapCoin = .text:0x8009DF00; // type:function size:0x68 -ComFortuneSwapStar = .text:0x8009DF68; // type:function size:0x68 +ComFortuneSwapCoin = .text:0x8009DF00; // type:function size:0x68 scope:local +ComFortuneSwapStar = .text:0x8009DF68; // type:function size:0x68 scope:local BoardBooCreate = .text:0x8009DFD0; // type:function size:0x11C BoardBooKill = .text:0x8009E0EC; // type:function size:0x2C BoardBooStealTypeSet = .text:0x8009E118; // type:function size:0x2A8 @@ -5212,9 +5212,9 @@ lbl_80139DA8 = .data:0x80139DA8; // type:object size:0xA data:string itemPrioTbl = .data:0x80139DB2; // type:object size:0x8C scope:local rankItemGroupTbl = .data:0x80139E3E; // type:object size:0x18 scope:local cursorPosTbl = .data:0x80139E58; // type:object size:0x30 scope:local data:float -comInputDraw1 = .data:0x80139E88; // type:object size:0xEE scope:local -comInputDraw2 = .data:0x80139F76; // type:object size:0xBA scope:local -comInputBall = .data:0x8013A030; // type:object size:0xCE scope:local +comInputDraw1 = .data:0x80139E88; // type:object size:0xEE scope:local data:2byte +comInputDraw2 = .data:0x80139F76; // type:object size:0xBA scope:local data:2byte +comInputBall = .data:0x8013A030; // type:object size:0xCE scope:local data:2byte lbl_8013A0FE = .data:0x8013A0FE; // type:object size:0xC data:string lbl_8013A10A = .data:0x8013A10A; // type:object size:0xA data:string lbl_8013A114 = .data:0x8013A114; // type:object size:0x9 data:string @@ -5903,7 +5903,7 @@ lotterySpr = .sdata:0x801D3732; // type:object size:0x2 scope:local data:2byte lotteryInstWin = .sdata:0x801D3734; // type:object size:0x2 scope:local data:2byte gripMdl = .sdata:0x801D3736; // type:object size:0x4 scope:local data:2byte turnMot = .sdata:0x801D373A; // type:object size:0x2 scope:local data:2byte -ballMdl = .sdata:0x801D373C; // type:object size:0x8 scope:local +ballMdl = .sdata:0x801D373C; // type:object size:0x8 scope:local data:2byte loseMot = .sdata:0x801D3744; // type:object size:0x2 scope:local data:2byte ticketSprGrp = .sdata:0x801D3746; // type:object size:0x2 scope:local data:2byte warpSpringMdl = .sdata:0x801D3748; // type:object size:0x2 scope:local data:2byte diff --git a/configure.py b/configure.py index 42a02138..4246d6ed 100644 --- a/configure.py +++ b/configure.py @@ -117,14 +117,22 @@ if not is_windows(): config.wrapper = args.wrapper # Tool versions +config.binutils_tag = "2.42-1" config.compilers_tag = "20231018" -config.dtk_tag = "v0.6.3" +config.dtk_tag = "v0.7.4" config.sjiswrap_tag = "v1.1.1" -config.wibo_tag = "0.6.3" +config.wibo_tag = "0.6.11" # Project config.config_path = Path("config") / config.version / "config.yml" config.check_sha_path = Path("config") / config.version / "build.sha1" +config.asflags = [ + "-mgekko", + "--strip-local-absolute", + "-I include", + f"-I build/{config.version}/include", + f"--defsym version={version_num}", +] config.ldflags = [ "-fp hardware", "-nodefaults", @@ -366,9 +374,9 @@ config.libs = [ Object(Matching, "game/board/audio.c"), Object(Matching, "game/board/com.c"), Object(Matching, "game/board/view.c"), - Object(NonMatching, "game/board/space.c"), + Object(Matching, "game/board/space.c"), Object(NonMatching, "game/board/shop.c"), - Object(NonMatching, "game/board/lottery.c"), + Object(Matching, "game/board/lottery.c"), Object(Matching, "game/board/basic_space.c"), Object(Matching, "game/board/warp.c"), Object(NonMatching, "game/board/char_wheel.c"), @@ -377,7 +385,7 @@ config.libs = [ Object(Matching, "game/board/roll.c"), Object(Matching, "game/board/ui.c"), Object(Matching, "game/board/block.c"), - Object(NonMatching, "game/board/item.c"), + Object(Matching, "game/board/item.c"), Object(NonMatching, "game/board/bowser.c"), Object(NonMatching, "game/board/battle.c"), Object(NonMatching, "game/board/fortune.c"), @@ -992,7 +1000,7 @@ config.libs = [ ), Rel('safDll', objects = { - Object(NonMatching, "REL/safDll/main.c"), + Object(Matching, "REL/safDll/main.c"), } ), Rel('selmenuDll', diff --git a/include/board_unsplit.h b/include/board_unsplit.h index 4115581c..2c7dcf01 100644 --- a/include/board_unsplit.h +++ b/include/board_unsplit.h @@ -14,26 +14,12 @@ typedef void (*BoardLightHook)(void); s32 BoardSpacePosGet(s32, s32, Vec*); void BoardShopTutorialExec(s32); -void BoardLotteryTutorialExec(void); void BoardMGSetupTutorialExec(void); void BoardBooHouseTutorialExec(void); void BoardCharWheelSetTarget(s32); void BoardSpaceStarSetIndex(s32); -s32 BoardModelRotYSet(s16, f32); -f32 BoardModelRotYGet(s16); -s32 BoardModelLayerSet(s16, u8); -s16 BoardModelIDGet(s16); -s32 BoardModelScaleSetV(s16, Vec*); void BoardLightHookSet(BoardLightHook set, BoardLightHook reset); -s16 BoardModelCreate(s32, s32*, s32); -void BoardModelKill(s16); s32 fn_8006DDE8(s16, f32); -s32 BoardModelMotionStart(s16, s32, u32); -s32 BoardModelMotionSpeedSet(s16, f32); -s32 BoardModelPosSetV(s16, Vec*); -s32 BoardModelPosSet(s16, f32, f32, f32); -s32 BoardModelRotSetV(s16 arg0, Vec* arg1); -s32 BoardModelVisibilitySet(s16, s32); void BoardSpaceWalkEventFuncSet(BoardSpaceEventFunc func); void BoardSpaceWalkMiniEventFuncSet(BoardSpaceEventFunc func); void BoardSpaceLandEventFuncSet(BoardSpaceEventFunc func); @@ -41,13 +27,9 @@ s32 BoardSpaceFlagSearch(s32, u32); void BoardSpaceInit(s32); void BoardSpaceDestroy(void); void BoardShopHostSet(s16); -void BoardLotteryHostSet(s16); void BoardBooHouseHostSet(s16); s32 BoardCameraRotGet(Vec*); -s32 BoardModelScaleSet(s16, f32, f32, f32); s32 BoardIsKill(void); -void BoardModelMtxSet(s16, Mtx*); -s32 BoardModelRotSet(s16, f32, f32, f32); void BoardBowserExec(s32 player, s32 space); void BoardBattleExec(s32 player, s32 space); diff --git a/include/game/audio.h b/include/game/audio.h index 09fd50cf..58a9f20d 100644 --- a/include/game/audio.h +++ b/include/game/audio.h @@ -20,7 +20,7 @@ void HuAudFXFadeOut(s32 arg0, s32 arg1); void HuAudFXPanning(s32 arg0, s16 arg1); void HuAudFXListnerSet(Vec* arg0, Vec* arg1, float arg2, float arg3); void HuAudFXListnerSetEX(Vec* arg0, Vec* arg1, float sndDist, float sndSpeed, float arg4, float arg5, float arg6); -void HuAudFXListnerUpdate(s32 arg0, s32 arg1); +void HuAudFXListnerUpdate(Vec *arg0, Vec *arg1); s32 HuAudFXEmiterPlay(s32 arg0, Vec *arg1); void HuAudFXEmiterUpDate(s32 arg0, Vec *arg1); void HuAudFXListnerKill(void); diff --git a/include/game/board/lottery.h b/include/game/board/lottery.h new file mode 100755 index 00000000..d292db5f --- /dev/null +++ b/include/game/board/lottery.h @@ -0,0 +1,13 @@ +#ifndef _BOARD_LOTTERY_H +#define _BOARD_LOTTERY_H + +#include "dolphin/types.h" + +void BoardLotteryHostSet(s16 arg0); +s16 BoardLotteryHostGet(void); +void BoardLotteryExec(void); +void BoardLotteryInit(void); +void BoardLotteryKill(void); +void BoardLotteryTutorialExec(void); + +#endif diff --git a/include/game/board/model.h b/include/game/board/model.h index 479194e6..6945ef9c 100644 --- a/include/game/board/model.h +++ b/include/game/board/model.h @@ -1,5 +1,5 @@ -#ifndef _BOARD_WARP_H -#define _BOARD_WARP_H +#ifndef _BOARD_MODEL_H +#define _BOARD_MODEL_H #include "game/hsfman.h" #include "game/data.h" @@ -37,16 +37,21 @@ s32 fn_8006DDE8(s16 model, float arg1); s32 BoardModelMotionCreate(s16 model, s32 data_num); s32 BoardModelMotionKill(s16 model, s32 motion); s32 BoardModelMotionStartEndSet(s16 model, s16 start, s16 end); +s32 BoardModelMotionUpdateSet(s16 model, s32 flag); +s32 BoardModelVoiceEnableSet(s16 model, s32 motion, s32 flag); s32 BoardModelMotionStart(s16 model, s32 slot, u32 attr); s32 BoardModelMotionShiftSet(s16 model, s32 motion, float time, float shift_time, u32 attr); s32 BoardModelAttrSet(s16 model, u32 attr); +s32 BoardModelAttrReset(s16 model, u32 attr); s32 BoardModelMotionTimeSet(s16 model, float time); float BoardModelMotionTimeGet(s16 model); float BoardModelMotionMaxTimeGet(s16 model); s32 BoardModelMotionSpeedSet(s16 model, float speed); s32 BoardModelMotionEndCheck(s16 model); s32 BoardModelAlphaSet(s16 model, u8 alpha); +s32 BoardModelMtxSet(s16 model, Mtx *src); s32 BoardModelRotYSet(s16 model, float rot); +float BoardModelRotYGet(s16 model); s32 BoardModelPosSet(s16 model, float x, float y, float z); s32 BoardModelPosSetV(s16 model, Vec *pos); s32 BoardModelRotSet(s16 model, float x, float y, float z); diff --git a/include/game/board/player.h b/include/game/board/player.h index 12b4cb49..3956df8b 100644 --- a/include/game/board/player.h +++ b/include/game/board/player.h @@ -82,7 +82,7 @@ void BoardPlayerScaleSetV(s32, Vec*); void BoardPlayerScaleSet(s32, f32, f32, f32); s16 BoardPlayerCurrMotionGet(s32); s32 BoardPlayerMotionCreate(s32, s32); -void BoardPlayerMotionKill(s32, s32); +s32 BoardPlayerMotionKill(s32, s32); s32 BoardPlayerMotionEndCheck(s32); void BoardPlayerMotionEndWait(s32); void BoardPlayerMotionStart(s32, s32, s32); @@ -114,6 +114,7 @@ void BoardPlayerZoomRestore(s32); void BoardJunctionMaskSet(s32); void BoardJunctionMaskReset(s32); void BoardJunctionMaskZero(void); +void BoardPlayerVoiceEnableSet(s32, s32, s32); void InitJunction(s32, s32, f32); static void UpdateJunctionGfx(omObjData*); static void StopJunctionPlayer(s32); diff --git a/include/game/board/star.h b/include/game/board/star.h index 5adc2211..04a87558 100755 --- a/include/game/board/star.h +++ b/include/game/board/star.h @@ -7,8 +7,10 @@ void BoardStarHostSet(s16 arg0); s16 BoardStarHostMdlGet(void); -void BoardStarExec(s32 arg0, BoardSpace *arg1); +void BoardStarExec(s32 arg0, s32 arg1); void BoardStarGive(s32 arg0, Vec *arg1); void BoardStarShowNext(s32 arg0); +extern s32 boardStarSndTbl[]; + #endif diff --git a/include/game/gamework_data.h b/include/game/gamework_data.h index c0333d13..874b1e71 100644 --- a/include/game/gamework_data.h +++ b/include/game/gamework_data.h @@ -58,6 +58,7 @@ typedef struct player_state { u16 character : 4; u16 auto_size : 2; u16 field00_bit9 : 1; + u16 field00_bitA : 6; }; /* 0x02 */ struct { u8 team : 1; diff --git a/include/game/msm.h b/include/game/msm.h index 75f35f19..1885d41e 100644 --- a/include/game/msm.h +++ b/include/game/msm.h @@ -69,7 +69,7 @@ void msmMusStopAll(s32 arg0, s32 arg1); void msmMusStop(s32 arg0, s32 arg1); s32 msmMusPlay(s32 arg0, UnkMsmStruct_03 *arg1); void msmSeDelListener(void); -void msmSeUpdataListener(s32 arg0, s32 arg1); +void msmSeUpdataListener(Vec *arg0, Vec *arg1); void msmSeSetListener(Vec* arg0, Vec* arg1, float arg2, float arg3, UnkMsmStruct_02 *arg4); s32 msmSeGetEntryID(s32 arg0, void *arg1); s32 msmSeGetNumPlay(s32 arg0); diff --git a/src/REL/bootDll/main.c b/src/REL/bootDll/main.c index 4741b7ba..2282e16c 100644 --- a/src/REL/bootDll/main.c +++ b/src/REL/bootDll/main.c @@ -46,8 +46,6 @@ static BOOL TitleProc(void); void *logoReadNintendo(void); -#define M_PI 3.141592653589793 - void ModuleProlog(void) { omOvlHisData *history; diff --git a/src/REL/safDll/main.c b/src/REL/safDll/main.c index 860ad928..6b58f683 100644 --- a/src/REL/safDll/main.c +++ b/src/REL/safDll/main.c @@ -1,12 +1,63 @@ -#include "common.h" -#include "REL/executor.h" +#include "dolphin.h" +#include "game/hsfman.h" +#include "game/gamework_data.h" +#include "game/printfunc.h" +#include "game/pad.h" +#include "rel_sqrt_consts.h" -void fn_1_0(void) { +s32 lbl_1_data_0 = 100; +s32 lbl_1_bss_0[192]; + +void fn_1_0(void) +{ } -//fn_1_4 -// https://decomp.me/scratch/Ii0sV +void safMarioEyeDim(s16 id) +{ + ModelData *model = &Hu3DData[id]; + HsfData *hsf = model->hsfData; + HsfMaterial *material = hsf->material; + s16 i, j; + for(i=0; imaterialCnt; i++, material++) { + for(j=0; jnumAttrs; j++) { + HsfAttribute *attr = &hsf->attribute[material->attrs[j]]; + if(strcmp(attr->bitmap->name, "s3c000m1_eyes") == 0 || strcmp(attr->bitmap->name, "mario_eyes") == 0) { + break; + } + } + if(j == material->numAttrs) { + material->color[0] *= 0.6f; + material->color[1] *= 0.3f; + material->color[2] *= 0.3f; + material->litColor[0] *= 0.6f; + material->litColor[1] *= 0.3f; + material->litColor[2] *= 0.3f; + } + } +} -// fn_1_288 -// https://decomp.me/scratch/VQ3CT \ No newline at end of file +void safSaveTest(void) +{ + OSTick time_write; + OSTick time_read; + s16 character = GWPlayerCfg[0].character; + SLLoad(); + time_write = time_read = 0; + while(1) { + print8(16, 420, 1.5f, "READ TIME %d", OSTicksToMilliseconds(time_read)); + print8(16, 430, 1.5f, "WRITE TIME %d", OSTicksToMilliseconds(time_write)); + HuPrcVSleep(); + if(HuPadBtnDown[0] & PAD_BUTTON_Y) { + HuAudCharVoicePlayEntry(character, 282); + time_write = OSGetTick(); + SLSave(); + time_write = OSGetTick()-time_write; + } + if(HuPadBtnDown[0] & PAD_BUTTON_X) { + time_read = OSGetTick(); + SLLoad(); + time_read = OSGetTick()-time_read; + } + } +} \ No newline at end of file diff --git a/src/REL/w03Dll/main.c b/src/REL/w03Dll/main.c index 732301f8..8671684d 100644 --- a/src/REL/w03Dll/main.c +++ b/src/REL/w03Dll/main.c @@ -1,9 +1,13 @@ #include "dolphin.h" #include "REL/executor.h" -#include "game/process.h" +#include "game/audio.h" #include "game/data.h" #include "game/gamework_data.h" +#include "game/process.h" +#include "game/wipe.h" #include "REL/w03Dll.h" +#include "game/board/lottery.h" +#include "game/board/model.h" #include "game/board/space.h" #include "game/board/star.h" #include "game/object.h" @@ -12,9 +16,6 @@ #include "board_unsplit.h" #include "game/hsfman.h" -s32 BoardModelPosSet(s16, f32, f32, f32); -s32 BoardModelMotionStart(s16, s32, u32); - void fn_8005B150(void*, void*); void fn_1_740(void); void fn_1_E0(void); @@ -35,14 +36,6 @@ extern const VoidFunc _ctors[]; extern const VoidFunc _dtors[]; -f32 BoardModelMotionTimeGet(s16); -s16 BoardModelCreate(s32, s32*, s32); -void BoardModelKill(s16); -void BoardModelMotionStartEndSet(s16, s32, s32); -void Hu3DFogSet(f32, f32, u8, u8, u8); -void HuAudFXListnerSetEX(Vec* arg0, Vec* arg1, float sndDist, float sndSpeed, float arg4, float arg5, float arg6); -u8 WipeStatGet(void); - //DATA w03StructUnk0 lbl_1_data_0[] = { {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, DATA_MAKE_NUM(DATADIR_W03, 0x0004)}, @@ -328,7 +321,7 @@ void fn_1_B5C(s32 arg0) { } BoardModelAttrSet(lbl_1_bss_C[0], 0x40000001); BoardModelMotionTimeSet(lbl_1_bss_C[0], var_f31); - BoardModelMotionStartEndSet(lbl_1_bss_C[0], (s32) var_f31, (s32) var_f28); + BoardModelMotionStartEndSet(lbl_1_bss_C[0], var_f31, var_f28); } void fn_1_CF4(void) { diff --git a/src/REL/w03Dll/mg_coin.c b/src/REL/w03Dll/mg_coin.c index e76ce248..c73112fd 100644 --- a/src/REL/w03Dll/mg_coin.c +++ b/src/REL/w03Dll/mg_coin.c @@ -4,6 +4,7 @@ #include "REL/w03Dll.h" #include "board_unsplit.h" #include "game/board/main.h" +#include "game/board/model.h" #include "game/board/player.h" extern u16 HuPadBtnDown[4]; @@ -67,9 +68,6 @@ double cos(double x); double atan2(double y, double x); extern s16 MGSeqCreate(s32, ...); u8 MGSeqStatGet(s16); -float BoardModelMotionTimeGet(s16 model); -float BoardModelMotionMaxTimeGet(s16 model); -s32 BoardModelMotionShiftSet(s16 model, s32 motion, float time, float shift_time, u32 attr); void Hu3DModelObjPosGet(s16 arg0, char *arg1, Vec *arg2); //DATA @@ -206,7 +204,7 @@ s32 fn_1_7D18(s32 arg0) { BoardSpacePosGet(0, temp_r28, &sp38); PSVECSubtract(&sp38, &sp2C, &sp20); PSVECNormalize(&sp20, &sp20); - BoardPlayerRotYSet(arg0, 180.0 * (atan2(-sp20.x, -sp20.z) / 3.141592653589793)); + BoardPlayerRotYSet(arg0, 180.0 * (atan2(-sp20.x, -sp20.z) / M_PI)); HuPrcSleep(0x1E); model = BoardModelIDGet(lbl_1_bss_C[7]); Hu3DModelObjPosGet(model, phei_str, &sp38); @@ -215,15 +213,15 @@ s32 fn_1_7D18(s32 arg0) { } else { var_f31 = 39.0f; } - sp38.x = sp38.x + (var_f31 * sin((3.141592653589793 * (180.0f + BoardModelRotYGet(lbl_1_data_456))) / 180.0)); - sp38.z = sp38.z + (var_f31 * cos((3.141592653589793 * (180.0f + BoardModelRotYGet(lbl_1_data_456))) / 180.0)); + sp38.x = sp38.x + (var_f31 * sin((M_PI * (180.0f + BoardModelRotYGet(lbl_1_data_456))) / 180.0)); + sp38.z = sp38.z + (var_f31 * cos((M_PI * (180.0f + BoardModelRotYGet(lbl_1_data_456))) / 180.0)); BoardPlayerPosGet(arg0, &sp2C); BoardPlayerPosLerpStart(arg0, &sp2C, &sp38, 0x14); while (GWPlayer[arg0].moving != 0) { BoardModelPosGet(lbl_1_bss_C[10], &sp2C); BoardPlayerPosGet(arg0, &sp38); PSVECSubtract(&sp38, &sp2C, &sp20); - arctan = atan2(sp20.x, sp20.z) / 3.141592653589793 * 180.0; + arctan = atan2(sp20.x, sp20.z) / M_PI * 180.0; BoardModelRotYSet(lbl_1_bss_C[10], arctan); HuPrcVSleep(); } @@ -482,7 +480,7 @@ void fn_1_8C08(omObjData* arg0, someBits3* arg1) { BoardPlayerMotionSpeedSet(arg1->unk00_bit5, 0.0f); BoardModelAttrSet(lbl_1_bss_C[7], 0x40000002); BoardModelAttrSet(lbl_1_data_456, 0x40000002); - arg1->unk00_bit1 = 2; + arg1->unk00_bit1 = 2; arg1->unk1 = 0x3C; arg1->unk2 = 0; } @@ -549,7 +547,7 @@ void fn_1_9044(omObjData* arg0, someBits3* arg1) { } } } - sp8.z = arg0->trans.x * sin((3.141592653589793 * arg0->trans.y) / 180.0); + sp8.z = arg0->trans.x * sin((M_PI * arg0->trans.y) / 180.0); BoardModelRotSetV(lbl_1_data_456, &sp8); } @@ -580,7 +578,7 @@ void fn_1_9230(s32 arg0) { BoardModelPosGet(lbl_1_bss_C[10], &sp20); BoardPlayerPosGet(arg0, &sp14); PSVECSubtract(&sp14, &sp20, &sp8); - rotY = atan2(sp8.x, sp8.z) / 3.141592653589793 * 180.0; + rotY = atan2(sp8.x, sp8.z) / M_PI * 180.0; BoardModelRotYSet(lbl_1_bss_C[10], rotY); HuPrcVSleep(); } @@ -712,8 +710,8 @@ void fn_1_97F8(s32 arg0) { } temp_r31 = &temp_r30->unk_0C[i]; temp_r31->unk0 = 1; - temp_r31->unk8.x = sp8.x + (50.0f * sin((3.141592653589793 * var_f31) / 180.0)); - temp_r31->unk8.z = sp8.z + (50.0f * cos((3.141592653589793 * var_f31) / 180.0)); + temp_r31->unk8.x = sp8.x + (50.0f * sin((M_PI * var_f31) / 180.0)); + temp_r31->unk8.z = sp8.z + (50.0f * cos((M_PI * var_f31) / 180.0)); temp_r31->unk8.y = 600.0f + sp8.y + (500.0f * BoardRandFloat()); temp_r31->unk1 = 0; temp_r31->unk4 = BoardRandFloat() * 360.0f; diff --git a/src/REL/w03Dll/mg_item.c b/src/REL/w03Dll/mg_item.c index d9bfc3be..6740b263 100644 --- a/src/REL/w03Dll/mg_item.c +++ b/src/REL/w03Dll/mg_item.c @@ -5,6 +5,7 @@ #include "game/gamework_data.h" #include "REL/w03Dll.h" #include "game/board/main.h" +#include "game/board/model.h" #include "game/board/space.h" #include "game/object.h" #include "game/objsub.h" @@ -54,7 +55,7 @@ typedef struct w03UnkMG { /* 0x10 */ s16 unk_10; /* 0x12 */ s16 unk_12; /* 0x14 */ s16 unk_14; - /* 0x16 */ s16 unk_16; + /* 0x16 */ s16 unk_16; } w03UnkMG; //external symbols @@ -64,23 +65,13 @@ extern Process *boardObjMan; extern u16 HuPadBtnDown[4]; //function signatures -s32 BoardModelMotionShiftSet(s16, s32, f32, f32, u32); s32 BoardVecDAngleCalcRange(float *value, float min, float range); void BoardCameraQuakeSet(s32 duration, float strength); s16 MGSeqCreate(s32, ...); u8 MGSeqStatGet(s16); -f32 BoardPlayerRotYGet(s32); -f32 BoardModelMotionTimeGet(s16); s32 BoardVecMinDistCheck(Vec *vec1, Vec *vec2, float min_dist); -s32 BoardModelScaleGet(s16 model, Vec *dst); -s32 BoardModelMotionTimeSet(s16 model, float time); -s32 BoardDAngleCalcRange(float *value, float min, float range); -u32 BoardRandMod(u32 value); -void BoardModelMotionStartEndSet(s16, s32, s32); void Hu3DModelObjPosGet(s16 arg0, char *arg1, Vec *arg2); -s32 BoardModelPosGet(s16 model, Vec *dst); s16 Hu3DMotionShiftIDGet(s16 arg0); -f32 BoardPlayerMotionTimeGet(s32); s32 frand(void); void fn_1_BE30(s32 arg0, ParticleData* arg1); @@ -654,7 +645,7 @@ void fn_1_B0A4(s32 arg0) { temp_r30->unk00_bit4 = arg0; for (i = 0; i < 3;) { - spC[i] = BoardRandMod(14); + spC[i] = BoardRandMod(14); if ((spC[i] != 10) && (spC[i] != 13)) { for (j = 0; j < i; j++) { if (spC[i] == spC[j]) { diff --git a/src/REL/w03Dll/river.c b/src/REL/w03Dll/river.c index 64b99a24..b77ebef2 100644 --- a/src/REL/w03Dll/river.c +++ b/src/REL/w03Dll/river.c @@ -3,6 +3,7 @@ #include "REL/w03Dll.h" #include "board_unsplit.h" #include "game/board/main.h" +#include "game/board/model.h" #include "game/board/player.h" double sin(double x); @@ -10,14 +11,8 @@ double cos(double x); double atan2(double y, double x); s16 BoardModelIDGet(s16 model); void Hu3DModelObjPosGet(s16 arg0, char *arg1, Vec *arg2); -float BoardModelMotionTimeGet(s16 model); -s32 BoardModelMotionShiftSet(s16 model, s32 motion, float time, float shift_time, u32 attr); -void BoardPlayerPosSet(s32, f32, f32, f32); -s32 BoardModelHookSet(s16 model, char *name, s16 hook); -#define OM_GET_WORK_PTR(object, type) ((type *)(&((object)->work[0]))) - extern s16 lbl_1_bss_C[14]; extern s16 boardPlayerMdl[4]; @@ -244,9 +239,7 @@ s32 fn_1_6898(s32 arg0) { return 1; } -float BoardModelRotYGet(s16 model); s32 BoardDAngleCalcRange(float *value, float min, float range); -float BoardModelRotYGet(s16 model); void fn_1_6B98(s32 arg0) { Vec sp30; diff --git a/src/REL/w03Dll/smoke.c b/src/REL/w03Dll/smoke.c index 65a1088e..c9731903 100644 --- a/src/REL/w03Dll/smoke.c +++ b/src/REL/w03Dll/smoke.c @@ -3,6 +3,7 @@ #include "REL/w03Dll.h" #include "board_unsplit.h" #include "game/board/main.h" +#include "game/board/model.h" typedef struct w03UnkWorkStruct { s16 unk_00[5]; @@ -16,7 +17,6 @@ extern Process *boardObjMan; extern s16 lbl_1_data_1E0; void fn_1_79E0(omObjData* arg0); -f32 BoardModelMotionMaxTimeGet(s16); char kemuri1[] = "kemuri1"; char kemuri2[] = "kemuri2"; diff --git a/src/REL/w03Dll/statue.c b/src/REL/w03Dll/statue.c index 38273508..f5b5fd67 100644 --- a/src/REL/w03Dll/statue.c +++ b/src/REL/w03Dll/statue.c @@ -5,8 +5,9 @@ #include "game/gamework_data.h" #include "REL/w03Dll.h" #include "game/audio.h" -#include "game/board/space.h" +#include "game/board/model.h" #include "game/board/player.h" +#include "game/board/space.h" #include "game/board/ui.h" #include "board_unsplit.h" #include "game/hsfman.h" @@ -26,12 +27,7 @@ void fn_1_2AC0(void); void fn_1_2818(void); void fn_1_2A40(void); void fn_1_2B44(void); -s32 BoardDAngleCalcRange(f32*, f32, f32); -s32 BoardPlayerMotBlendCheck(s32); -f32 BoardPlayerRotYGet(s32); -void BoardConfettiCreate(Point3d*, s16, f32); double atan2(double y, double x); -f32 BoardModelMotionTimeGet(s16); //DATA s16 lbl_1_data_280 = -1; diff --git a/src/REL/w10Dll/host.c b/src/REL/w10Dll/host.c index ce7465a1..275264d2 100644 --- a/src/REL/w10Dll/host.c +++ b/src/REL/w10Dll/host.c @@ -1,5 +1,6 @@ #include "REL/w10Dll.h" #include "game/data.h" +#include "game/board/model.h" #include "game/board/tutorial.h" #include "game/board/window.h" diff --git a/src/REL/w10Dll/main.c b/src/REL/w10Dll/main.c index 9bd9f796..c38b242f 100644 --- a/src/REL/w10Dll/main.c +++ b/src/REL/w10Dll/main.c @@ -1,6 +1,8 @@ #include "include/REL/w10Dll.h" #include "game/data.h" #include "game/hsfman.h" +#include "game/board/lottery.h" +#include "game/board/model.h" #include "game/board/star.h" #include "game/board/tutorial.h" diff --git a/src/REL/w10Dll/scene.c b/src/REL/w10Dll/scene.c index 881ea98b..0570fce7 100644 --- a/src/REL/w10Dll/scene.c +++ b/src/REL/w10Dll/scene.c @@ -1,5 +1,7 @@ #include "include/REL/w10Dll.h" +#include "game/board/lottery.h" #include "game/board/main.h" +#include "game/board/model.h" #include "game/board/star.h" #include "game/board/tutorial.h" #include "game/board/ui.h" @@ -185,7 +187,7 @@ void fn_1_13A4(void) { fn_1_C10(0); fn_1_BA0(0x2E002B); sp8.x = -33.0f; - sp8.y = sp8.z = 0.0f; + sp8.y = sp8.z = 0.0f; temp_r3_2 = BoardSpaceFlagSearch(0, 0x80000); BoardSpacePosGet(0, temp_r3_2, &sp14); BoardModelPosSetV(lbl_1_bss_0->unk8, &sp14); diff --git a/src/game/audio.c b/src/game/audio.c index ca9ddb0a..2a1e1dd5 100644 --- a/src/game/audio.c +++ b/src/game/audio.c @@ -190,7 +190,7 @@ void HuAudFXListnerSetEX(Vec* arg0, Vec* arg1, float sndDist, float sndSpeed, fl } } -void HuAudFXListnerUpdate(s32 arg0, s32 arg1) { +void HuAudFXListnerUpdate(Vec *arg0, Vec *arg1) { if (omSysExitReq == 0) { msmSeUpdataListener(arg0, arg1); } diff --git a/src/game/board/basic_space.c b/src/game/board/basic_space.c index 894f5e31..7dc7f24b 100644 --- a/src/game/board/basic_space.c +++ b/src/game/board/basic_space.c @@ -1,5 +1,6 @@ #include "game/board/basic_space.h" #include "game/board/main.h" +#include "game/board/model.h" #include "game/board/player.h" #include "game/board/tutorial.h" #include "game/data.h" @@ -37,7 +38,6 @@ static void CoinChgDisappear(omObjData*, coinChg*); extern void BoardCameraViewSet(s32); extern void BoardPlayerPosGet(s32, Vec*); -extern void BoardModelPosGet(s16, Vec*); extern void BoardPlayerMotionEndWait(s32); extern void BoardPlayerCoinsAdd(s32, s32); extern void BoardRotateDiceNumbers(s32); diff --git a/src/game/board/item.c b/src/game/board/item.c index 59176efc..5a330494 100755 --- a/src/game/board/item.c +++ b/src/game/board/item.c @@ -18,6 +18,12 @@ #include "game/board/space.h" #include "game/board/ui.h" #include "game/board/window.h" +#include "game/board/view.h" + +#include "game/board/star.h" +#include "game/board/boo.h" + +void BoardCharWheelWait(void); typedef struct { /* 0x00 */ s16 unk00; @@ -47,10 +53,8 @@ typedef struct { } UnkGenieCameraStruct; // Size 0x1C u32 frandmod(u32); -void CharModelCreateParticle(s32, Vec*); void BoardBowserSuitInit(s32); s16 BoardBowserSuitPlayerModelGet(void); -void fn_8004F578(s16, s32); static void ItemProcess(void); static void RestoreProcess(void); @@ -103,6 +107,9 @@ static s8 currItem; static s16 suitMdl; static s32 suitMot[2]; static s32 suitCommonMot[2]; +static s16 booBallMdl; +static float booBallAlpha; +static char booCoinStr[8]; // ... static float genieFov; static AnimData *genieParticleAnim; @@ -439,8 +446,9 @@ static void BoardUiInlineFunc02(void) { static inline void BoardUiInlineFunc03(s32 arg0) { Vec sp8; Vec sp14; - - BoardSpacePosGet(0, GWPlayerSpaceCurrGet(arg0), &sp14); + s32 space = GWPlayer[arg0].space_curr; + + BoardSpacePosGet(0, space, &sp14); BoardPlayerPosGet(arg0, &sp8); BoardPlayerPosLerpStart(arg0, &sp8, &sp14, 0x14); while (GWPlayer[arg0].moving) { @@ -499,7 +507,7 @@ static Process *ItemShowProc(UnkItemShowProcStruct *arg0, Vec *arg1) { sp20.y += 35.0f; sp20.z += 50.0 * cos(sp14.y * M_PI / 180.0); sp20.x += 50.0 * sin(sp14.y * M_PI / 180.0); - CharModelCreateParticle(1, &sp20); + CharModelEffectCreate(1, &sp20); HuPrcSleep(0xA); } if (suitMdl >= 0) { @@ -765,35 +773,448 @@ static void ExecItemHammer(void) { } } -// https://decomp.me/scratch/QqVh2 static void ExecItemPipe(void) { + Vec spE4[2]; + Vec spCC[2]; + Vec spB4[2]; + Vec spA8; + Vec sp9C; + Vec sp90; + Vec sp84; + Vec sp78; + Vec sp6C; + Vec sp60; + s32 sp58[2]; + float sp50[2]; + float sp48[2]; + s16 sp30[2]; + s16 sp2C[2]; + float temp_f28; + float var_f30; + float var_f29; + float var_f31; + s16 temp_r26; + s16 temp_r28; + s32 temp_r25; + s32 temp_r29; + s32 temp_r19; + s32 temp_r18; + s16 var_r27; + s32 var_r30; + s32 var_r31; + + HuAudFXPlay(0x350); + ItemShowProc(NULL, NULL); + for (var_r31 = 0; var_r31 < 2; var_r31++) { + sp30[var_r31] = BoardModelCreate(itemMdlTbl[currItem], NULL, 1); + BoardModelLayerSet(sp30[var_r31], 2); + sp9C.x = sp9C.z = 2.0f; + sp9C.y = 0.0f; + BoardModelScaleSetV(sp30[var_r31], &sp9C); + BoardModelVisibilitySet(sp30[var_r31], 0); + } + BoardCharWheelInit(currItemRestore, 3); + BoardCharWheelWait(); + temp_r26 = BoardCharWheelResultGet(); + sp2C[0] = currItemRestore; + sp2C[1] = temp_r26; + for (var_r31 = 0; var_r31 < 2; var_r31++) { + sp58[var_r31] = GWPlayer[sp2C[var_r31]].space_curr; + BoardSpacePosGet(0, sp58[var_r31], &spE4[var_r31]); + BoardModelPosSetV(sp30[var_r31], &spE4[var_r31]); + } + if (sp58[0] == sp58[1]) { + HuWinMesMaxSizeGet(1, sp48, 0x120012); + temp_r28 = HuWinCreate(-10000.0f, -10000.0f, sp48[0], sp48[1], 0); + HuWinMesSet(temp_r28, 0x120012); + HuWinMesWait(temp_r28); + HuPrcSleep(0xB4); + HuWinKill(temp_r28); + } else { + BoardUiInlineFunc03(sp2C[1]); + HuAudFXPlay(0x318); + for (var_r31 = 0; var_r31 < 2; var_r31++) { + BoardModelVisibilitySet(sp30[var_r31], 1); + BoardPlayerPosGet(sp2C[var_r31], &spCC[var_r31]); + } + for (var_r31 = 0; var_r31 < 0x3C; var_r31++) { + sp9C.y += 0.033333335f; + for (var_r30 = 0; var_r30 < 2; var_r30++) { + BoardModelScaleSetV(sp30[var_r30], &sp9C); + spCC[var_r30].y += 3.3333333f; + BoardPlayerPosSetV(sp2C[var_r30], &spCC[var_r30]); + } + HuPrcVSleep(); + } + sp9C.y = 2.0f; + for (var_r31 = 0; var_r31 < 2; var_r31++) { + BoardModelScaleSetV(sp30[var_r31], &sp9C); + } + HuPrcSleep(0xA); + HuAudFXPlay(0x35A); + omVibrate(sp2C[0], 0xC, 4, 2); + var_f30 = 5.0f; + sp50[0] = spCC[0].y; + sp50[1] = spCC[1].y; + var_f31 = 1.0f; + while (1) { + for (var_r31 = 0; var_r31 < 2; var_r31++) { + spCC[var_r31].y -= var_f30; + BoardPlayerPosSetV(sp2C[var_r31], &spCC[var_r31]); + if (GWPlayer[sp2C[var_r31]].character == 5) { + var_f31 -= 0.05f; + if (var_f31 < 0.65f) { + var_f31 = 0.65f; + } + sp90.x = sp90.y = sp90.z = var_f31; + BoardPlayerScaleSetV(sp2C[var_r31], &sp90); + } + } + var_f30 *= 1.08f; + if (sp50[0] - spCC[0].y >= 300.0f && sp50[1] - spCC[1].y >= 300.0f) { + break; + } + HuPrcVSleep(); + } + WipeColorSet(0, 0, 0); + WipeCreate(2, 0, 0x1E); + while (WipeStatGet() != 0) { + HuPrcVSleep(); + } + BoardCameraMoveSet(0); + spA8 = spCC[0]; + spCC[0] = spCC[1]; + spCC[1] = spA8; + var_r31 = sp58[0]; + sp58[0] = sp58[1]; + sp58[1] = var_r31; + for (var_r31 = 0; var_r31 < 2; var_r31++) { + GWPlayer[sp2C[var_r31]].space_curr = sp58[var_r31]; + } + for (var_r31 = 0; var_r31 < 2; var_r31++) { + BoardPlayerMoveAwayStartCurr(sp58[var_r31], 1); + BoardPlayerPosGet(sp2C[var_r31], &spE4[var_r31]); + BoardPlayerPosSetV(sp2C[var_r31], &spCC[var_r31]); + } + HuPrcVSleep(); + BoardCameraMoveSet(1); + for (var_r31 = 0; var_r31 < 2; var_r31++) { + BoardPlayerMotionStart(sp2C[var_r31], 4, 0); + BoardPlayerVoiceEnableSet(sp2C[var_r31], 4, 0); + BoardModelVisibilitySet(BoardPlayerModelGet(sp2C[var_r31]), 0); + } + WipeCreate(1, 0, 0x1E); + while (WipeStatGet() != 0) { + HuPrcVSleep(); + } + temp_f28 = 19.0f; + var_f29 = 0.0f; + for (var_r31 = 0; var_r31 < 2; var_r31++) { + PSVECSubtract(&spE4[var_r31], &spCC[var_r31], &spB4[var_r31]); + PSVECScale(&spB4[var_r31], &spB4[var_r31], 0.03f); + BoardModelVisibilitySet(BoardPlayerModelGet(sp2C[var_r31]), 1); + } + HuAudPlayerVoicePlay(currItemRestore, 0x122); + var_f31 = 0.65f; + var_r27 = 5; + while (1) { + var_f30 = temp_f28 - 0.06666667f * (var_f29 * var_f29 * 0.25f); + var_r30 = 0; + for (var_r31 = 0; var_r31 < 2; var_r31++) { + if (GWPlayer[sp2C[var_r31]].character == 5) { + if (var_r27 != 0) { + var_r27--; + } else { + var_f31 += 0.05f; + if (var_f31 > 1.0f) { + var_f31 = 1.0f; + } + sp90.x = sp90.y = sp90.z = var_f31; + BoardPlayerScaleSetV(sp2C[var_r31], &sp90); + } + } + spCC[var_r31].y += var_f30; + if (fabs(spCC[var_r31].x - spE4[var_r31].x) <= fabs(spB4[var_r31].x)) { + spCC[var_r31].x = spE4[var_r31].x; + var_r30++; + } else { + spCC[var_r31].x += spB4[var_r31].x; + } + if (fabs(spCC[var_r31].z - spE4[var_r31].z) <= fabs(spB4[var_r31].z)) { + spCC[var_r31].z = spE4[var_r31].z; + var_r30++; + } else { + spCC[var_r31].z += spB4[var_r31].z; + } + if (spCC[var_r31].y < spE4[var_r31].y) { + spCC[var_r31].y = spE4[var_r31].y; + var_r30++; + } + BoardPlayerPosSetV(sp2C[var_r31], &spCC[var_r31]); + } + var_f29 += 1.0f; + if (var_r30 == 6) { + break; + } + HuPrcVSleep(); + } + BoardPlayerMotionShiftSet(sp2C[1], 6, 0.0f, 8.0f, 0x40000001); + BoardModelVoiceEnableSet(BoardPlayerModelGet(sp2C[1]), 6, 0); + CharModelLayerSetAll(2); + BoardRotateDiceNumbers(sp2C[0]); + for (var_r31 = 0; var_r31 < 0x2D; var_r31++) { + sp9C.y -= 0.044444446f; + for (var_r30 = 0; var_r30 < 2; var_r30++) { + BoardModelScaleSetV(sp30[var_r30], &sp9C); + } + HuPrcVSleep(); + } + for (var_r31 = 0; var_r31 < 2; var_r31++) { + BoardModelVisibilitySet(sp30[var_r31], 0); + } + BoardUiInlineFunc03(sp2C[0]); + BoardWinCreate(2, 0x12001D, -1); + BoardWinInsertMesSet(GWPlayerCfg[sp2C[0]].character, 0); + BoardWinInsertMesSet(GWPlayerCfg[sp2C[1]].character, 1); + BoardWinWait(); + BoardWinKill(); + BoardRotateDiceNumbers(sp2C[1]); + HuPrcSleep(8); + BoardModelVoiceEnableSet(BoardPlayerModelGet(sp2C[1]), 6, 1); + } + BoardPlayerVoiceEnableSet(sp2C[0], 4, 1); + BoardPlayerVoiceEnableSet(sp2C[1], 4, 1); + for (var_r31 = 0; var_r31 < 2; var_r31++) { + BoardModelKill(sp30[var_r31]); + } + HuPrcKill(NULL); + while (1) { + HuPrcVSleep(); + } } -// https://decomp.me/scratch/r8MWA static void ExecItemSwap(void) { - (void) 0.033333335f; - (void) 3.3333333f; - (void) 5.0f; - (void) 0.05f; - (void) 0.65f; - (void) 1.08f; - (void) 19.0f; - (void) 0.06666667f; - (void) 0.25f; - (void) 8.0f; - (void) 0.044444446f; - (void) 45.0f; - (void) 0.94f; - (void) 6.0f; - (void) 0.6f; - (void) 255.0f; - (void) 1.02f; - (void) 5.6666665f; - (void) 4503601774854144.0; - (void) 106.0; + Vec sp1A4[3]; + Vec sp180[3]; + Vec sp15C[3]; + Vec sp138[3]; + s32 spC0[6]; + Vec spB4; + Vec spA8; + Vec sp9C; + Vec sp90; + Vec sp84; + Vec sp78; + Vec sp6C; + Vec sp60; + s16 sp54[6]; + Vec sp48; + Vec sp3C; + float temp_f29; + float var_f30; + s16 temp_r29; + s32 var_r23; + s32 var_r22; + s32 var_r28; + s32 var_r27; + s32 var_r26; + s32 var_r30; + s32 var_r31; + s32 temp_r24; + s8 var_r21; + Mtx sp108; + Mtx spD8; + + HuAudFXPlay(0x350); + ItemShowProc(NULL, NULL); + BoardCharWheelInit(currItemRestore, 3); + BoardCharWheelWait(); + temp_r24 = BoardCharWheelResultGet(); + suitMdl = BoardModelCreate(itemMdlTbl[currItem], NULL, 0); + BoardModelLayerSet(suitMdl, 7); + BoardModelAttrSet(suitMdl, 0x400000); + sp9C.x = sp9C.y = sp9C.z = 0.0f; + sp9C.y = 45.0f; + HuAudFXPlay(0x364); + BoardUiInlineFunc01(&sp9C); + BoardModelPosGet(suitMdl, &spB4); + BoardPlayerRotGet(currItemRestore, &sp90); + for (var_r27 = 0; var_r27 < 3; var_r27++) { + if (((float*) &sp90)[var_r27] < 0.0f) { + ((float*) &sp90)[var_r27] += 360.0f; + } + if (((float*) &sp90)[var_r27] >= 360.0f) { + ((float*) &sp90)[var_r27] -= 360.0f; + } + } + BoardModelRotGet(suitMdl, &spA8); + while (1) { + PSVECAdd(&spA8, &sp9C, &spA8); + for (var_r26 = 0; var_r26 < 3; var_r26++) { + if (((float*) &spA8)[var_r26] < 0.0f) { + ((float*) &spA8)[var_r26] += 360.0f; + } + if (((float*) &spA8)[var_r26] >= 360.0f) { + ((float*) &spA8)[var_r26] -= 360.0f; + } + } + sp9C.y *= 0.94f; + if (sp9C.y <= 6.0f) { + sp9C.y = 6.0f; + if (fabs(sp90.y - spA8.y) <= sp9C.y) { + spA8.y = sp90.y; + break; + } + } + BoardModelRotSetV(suitMdl, &spA8); + HuPrcVSleep(); + } + BoardModelRotSetV(suitMdl, &spA8); + var_r23 = var_r22 = 0; + for (var_r31 = 0; var_r31 < 3; var_r31++) { + if (GWPlayer[currItemRestore].items[var_r31] != -1) { + var_r23++; + } + if (GWPlayer[temp_r24].items[var_r31] != -1) { + var_r22++; + } + } + if (var_r23 >= var_r22) { + var_r28 = var_r23 * 2; + } else { + var_r28 = var_r22 * 2; + } + BoardModelRotGet(suitMdl, &sp3C); + Hu3DCameraSet(0, sp108); + PSMTXInverse(sp108, spD8); + Hu3DMtxRotGet(spD8, &sp48); + sp3C.x = sp48.x; + for (var_r31 = 0; var_r31 < var_r28 / 2; var_r31++) { + temp_r29 = sp54[var_r31] = BoardModelCreate(itemMdlTbl[currItem], NULL, 1); + BoardModelLayerSet(temp_r29, 6); + BoardModelPassSet(temp_r29, 0); + BoardModelRotSetV(temp_r29, &sp3C); + BoardModelVisibilitySet(temp_r29, 0); + BoardModelAttrSet(temp_r29, 0x400000); + temp_r29 = sp54[var_r31 + 3] = BoardModelCreate(itemMdlTbl[currItem], NULL, 1); + BoardModelLayerSet(temp_r29, 6); + BoardModelPassSet(temp_r29, 0); + BoardModelRotSetV(temp_r29, &sp3C); + BoardModelVisibilitySet(temp_r29, 0); + BoardModelAttrSet(temp_r29, 0x400000); + } + BoardItemGetDestPos(currItemRestore, &sp15C[0]); + BoardItemGetDestPos(temp_r24, &sp138[0]); + BoardModelPosGet(suitMdl, &sp90); + PSVECSubtract(&sp90, &Hu3DCamera->pos, &sp90); + temp_f29 = PSVECMag(&sp90); + for (var_r31 = 0; var_r31 < 3; var_r31++) { + sp15C[var_r31].z = temp_f29; + sp138[var_r31].z = temp_f29; + } + for (var_r31 = 0; var_r31 < var_r28 / 2; var_r31++) { + HuAudFXPlay(0x319); + BoardModelVisibilitySet(sp54[var_r31], 1); + BoardModelVisibilitySet(sp54[var_r31 + 3], 1); + sp1A4[var_r31] = sp180[var_r31] = spB4; + Hu3D2Dto3D(&sp15C[var_r31], 1, &sp84); + Hu3D2Dto3D(&sp138[var_r31], 1, &sp78); + PSVECSubtract(&sp84, &sp1A4[var_r31], &sp6C); + PSVECScale(&sp6C, &sp6C, 0.033333335f); + PSVECSubtract(&sp78, &sp180[var_r31], &sp60); + PSVECScale(&sp60, &sp60, 0.033333335f); + for (var_r30 = 0; var_r30 < 0x1E; var_r30++) { + BoardModelPosSetV(sp54[var_r31], &sp1A4[var_r31]); + BoardModelPosSetV(sp54[var_r31 + 3], &sp180[var_r31]); + PSVECAdd(&sp1A4[var_r31], &sp6C, &sp1A4[var_r31]); + PSVECAdd(&sp180[var_r31], &sp60, &sp180[var_r31]); + HuPrcVSleep(); + } + sp1A4[var_r31] = sp84; + sp180[var_r31] = sp78; + BoardModelPosSetV(sp54[var_r31], &sp1A4[var_r31]); + BoardModelPosSetV(sp54[var_r31 + 3], &sp180[var_r31]); + } + omVibrate(currItemRestore, 0xB4, 6, 6); + omVibrate(temp_r24, 0xB4, 6, 6); + for (var_r31 = 0; var_r31 < 0x3C; var_r31++) { + for (var_r30 = 0; var_r30 < var_r28 / 2; var_r30++) { + sp6C = sp1A4[var_r30]; + sp6C.x += 3.0 * sin((M_PI * (frand() % 360)) / 180.0); + sp6C.y += 3.0 * sin((M_PI * (frand() % 360)) / 180.0); + BoardModelPosSetV(sp54[var_r30], &sp6C); + sp6C = sp180[var_r30]; + sp6C.x += 3.0 * sin((M_PI * (frand() % 360)) / 180.0); + sp6C.y += 3.0 * sin((M_PI * (frand() % 360)) / 180.0); + BoardModelPosSetV(sp54[var_r30 + 3], &sp6C); + } + HuPrcSleep(2); + } + for (var_r31 = 0; var_r31 < var_r28 / 2; var_r31++) { + BoardModelPosSetV(sp54[var_r31], &sp1A4[var_r31]); + BoardModelPosSetV(sp54[var_r31 + 3], &sp180[var_r31]); + } + for (var_r31 = 0; var_r31 < 3; var_r31++) { + spC0[var_r31] = BoardPlayerItemRemove(currItemRestore, 0); + spC0[var_r31 + 3] = BoardPlayerItemRemove(temp_r24, 0); + } + for (var_r31 = 0; var_r31 < 3; var_r31++) { + if (spC0[var_r31 + 3] != -1) { + BoardPlayerItemAdd(currItemRestore, spC0[var_r31 + 3]); + } + if (spC0[var_r31] != -1) { + BoardPlayerItemAdd(temp_r24, spC0[var_r31]); + } + } + for (var_r31 = (var_r28 / 2) - 1; var_r31 >= 0; var_r31--) { + HuAudFXPlay(0x32C); + PSVECSubtract(&spB4, &sp1A4[var_r31], &sp6C); + PSVECScale(&sp6C, &sp6C, 0.033333335f); + PSVECSubtract(&spB4, &sp180[var_r31], &sp60); + PSVECScale(&sp60, &sp60, 0.033333335f); + for (var_r30 = 0; var_r30 < 0x1E; var_r30++) { + BoardModelPosSetV(sp54[var_r31], &sp1A4[var_r31]); + BoardModelPosSetV(sp54[var_r31 + 3], &sp180[var_r31]); + PSVECAdd(&sp1A4[var_r31], &sp6C, &sp1A4[var_r31]); + PSVECAdd(&sp180[var_r31], &sp60, &sp180[var_r31]); + HuPrcVSleep(); + } + BoardModelVisibilitySet(sp54[var_r31], 0); + BoardModelVisibilitySet(sp54[var_r31 + 3], 0); + } + sp9C.y = 0.6f; + var_f30 = 255.0f; + var_r21 = 0; + while (1) { + BoardModelRotSetV(suitMdl, &spA8); + BoardModelAlphaSet(suitMdl, var_f30); + PSVECAdd(&spA8, &sp9C, &spA8); + sp9C.y *= 1.02f; + if (sp9C.y >= 35.0f) { + if (var_r21 == 0) { + HuAudFXPlay(0x365); + var_r21 = 1; + } + sp9C.y = 45.0f; + var_f30 -= 5.6666665f; + if (var_f30 <= 0.0f) { + break; + } + } + HuPrcVSleep(); + } + BoardModelKill(suitMdl); + for (var_r31 = 0; var_r31 < var_r28 / 2; var_r31++) { + BoardModelKill(sp54[var_r31]); + BoardModelKill(sp54[var_r31 + 3]); + } + HuPrcKill(NULL); + while (1) { + HuPrcVSleep(); + } } -void ExecItemSpark(void) { +static void ExecItemSpark(void) { Vec sp68; Vec sp5C; Vec sp50; @@ -806,7 +1227,8 @@ void ExecItemSpark(void) { s32 temp_r28; s16 temp_r30; s32 i; - + + (void)106.0; temp_r30 = BoardModelCreate(0x70067, NULL, 0); BoardModelLayerSet(temp_r30, 3); BoardModelVisibilitySet(temp_r30, 0); @@ -915,28 +1337,246 @@ static void ExecItemLight(void) { // https://decomp.me/scratch/gbgTk static void ExecItemWhistle(void) { - (void) 0.003921569f; - (void) 0.5f; - (void) 120.0f; - (void) 120.0; - (void) 100.0f; - (void) 90.0f; - (void) 200.0f; - (void) 0.03448276f; - (void) 30.0f; - (void) 95.0f; - (void) 185.0f; - (void) 275.0f; - (void) -1.0f; - (void) -35.0f; - (void) 0.16f; - (void) 1.0; - (void) 4.0f; - (void) 4.5f; - (void) 1.7f; - (void) 0.083333336f; - (void) 0.945f; - (void) 500.0f; + Vec spF0[4]; + Vec spC0[4]; + Vec spB4; + Vec spA8; + Vec sp9C; + Vec sp90; + Vec sp84; + Vec sp78; + float sp68[4]; + float sp58[4]; + float sp48[4]; + float sp38[4]; + float sp28[4]; + s16 sp20[4]; + s16 sp8; + float var_f30; + float var_f31; + s32 temp_r23; + char *temp_r22; + s32 temp_r18; + s16 temp_r17; + s16 temp_r21; + s16 temp_r20; + s32 temp_r31; + s16 temp_r28; + s16 temp_r19; + s32 var_r26; + s16 var_r25; + s16 var_r27; + s32 var_r29; + s32 var_r31; + + + var_r31 = GWPlayerCfg[currItemRestore].character; + temp_r23 = BoardPlayerMotionCreate(currItemRestore, callMotTbl[var_r31]); + temp_r22 = callHookTbl[var_r31]; + temp_r28 = BoardStarHostMdlGet(); + BoardModelPosGet(temp_r28, &spB4); + sp9C = spB4; + temp_r19 = GWBoardGet(); + temp_r21 = BoardModelMotionCreate(temp_r28, callAttackMotTbl[temp_r19]); + temp_r20 = BoardModelMotionCreate(temp_r28, callAttackMotTbl2[temp_r19]); + var_f31 = 360.0f * (0.003921569f * (s32)((u8) frand())); + spA8.x = spA8.y = spA8.z = 0.5f; + for (var_r31 = 0; var_r31 < 4; var_r31++) { + sp20[var_r31] = BoardModelCreate(0x20027, NULL, 1); + BoardModelLayerSet(sp20[var_r31], 2); + temp_r17 = BoardModelMotionCreate(sp20[var_r31], 0x20028); + BoardModelMotionStart(sp20[var_r31], temp_r17, 0x40000001); + sp28[var_r31] = 120.0f; + spF0[var_r31].x = spB4.x + 120.0 * sin(M_PI * var_f31 / 180.0); + spF0[var_r31].y = 1000.0f + spB4.y + 100.0f * var_r31; + spF0[var_r31].z = spB4.z + 120.0 * cos(M_PI * var_f31 / 180.0); + spC0[var_r31].x = spC0[var_r31].z = 0.0f; + spC0[var_r31].y = var_f31 + 90.0f; + if (spC0[var_r31].y >= 360.0f) { + spC0[var_r31].y -= 360.0f; + } + BoardModelRotSetV(sp20[var_r31], &spC0[var_r31]); + BoardModelPosSetV(sp20[var_r31], &spF0[var_r31]); + BoardModelScaleSetV(sp20[var_r31], &spA8); + var_f31 += 90.0f; + if (var_f31 >= 360.0f) { + var_f31 -= 360.0f; + } + sp38[var_r31] = var_f31; + BoardModelVisibilitySet(sp20[var_r31], 0); + } + HuAudFXPlay(0x350); + suitMdl = BoardModelCreate(itemMdlTbl[currItem], NULL, 0); + BoardModelLayerSet(suitMdl, 2); + ItemShowProc(NULL, NULL); + BoardModelPosGet(suitMdl, &sp90); + BoardPlayerPosGet(currItemRestore, &sp84); + sp84.y += 200.0f; + sp84.z += 100.0f; + PSVECSubtract(&sp84, &sp90, &sp78); + PSVECScale(&sp78, &sp78, 0.03448276f); + BoardPlayerMotionStart(currItemRestore, temp_r23, 0); + BoardPlayerMotionTimeSet(currItemRestore, 1.0f); + for (var_r31 = 0; var_r31 < 0x1D; var_r31++) { + sp90.y += sp78.y; + sp90.z += sp78.z; + BoardModelPosSetV(suitMdl, &sp90); + HuPrcVSleep(); + } + while (BoardPlayerMotionTimeGet(currItemRestore) < 30.0f) { + HuPrcVSleep(); + } + sp8 = BoardPlayerModelGet(currItemRestore); + BoardModelPosSetV(suitMdl, &sp84); + BoardModelHookSet(sp8, temp_r22, suitMdl); + while (BoardPlayerMotionTimeGet(currItemRestore) < BoardPlayerMotionMaxTimeGet(currItemRestore)) { + if (BoardPlayerMotionTimeGet(currItemRestore) == 95.0f + || BoardPlayerMotionTimeGet(currItemRestore) == 185.0f + || BoardPlayerMotionTimeGet(currItemRestore) == 275.0f) { + HuAudFXPlay(0x31F); + } + HuPrcVSleep(); + } + WipeColorSet(0, 0, 0); + WipeCreate(2, 0, 0x3C); + while (WipeStatGet() != 0) { + HuPrcVSleep(); + } + BoardModelHookObjReset(sp8, temp_r22); + BoardRotateDiceNumbers(currItemRestore); + BoardModelKill(suitMdl); + BoardCameraMoveSet(0); + temp_r18 = BoardSpaceStarGetCurr(); + BoardCameraTargetSpaceSet(temp_r18); + HuPrcVSleep(); + BoardCameraMoveSet(1); + for (var_r31 = 0; var_r31 < 4; var_r31++) { + BoardModelVisibilitySet(sp20[var_r31], 1); + } + WipeCreate(1, 0, 0x3C); + while (WipeStatGet() != 0) { + HuPrcVSleep(); + } + HuAudFXPlay(0x320); + for (var_r31 = 0; var_r31 < 4; var_r31++) { + sp58[var_r31] = 0.0f; + sp48[var_r31] = 1.0f; + } + var_r27 = 0; + for (var_r25 = 0; var_r25 < 4;) { + for (var_r31 = 0; var_r31 < 4; var_r31++) { + if (sp48[var_r31] != -1.0f) { + sp68[var_r31] = sp58[var_r31] - 0.06666667f * (sp48[var_r31] * sp48[var_r31] * 0.25f); + if (sp68[var_r31] < -35.0f) { + sp68[var_r31] = -35.0f; + } + if (sp68[var_r31] > 35.0f) { + sp68[var_r31] = 35.0f; + } + sp48[var_r31] += 1.0f; + spF0[var_r31].y += sp68[var_r31]; + if (spF0[var_r31].y <= spB4.y) { + if (var_r27 == 0) { + var_r27 = 1; + for (var_r29 = 0; var_r29 < 4; var_r29++) { + omVibrate(var_r29, 0xC, 6, 6); + } + HuAudFXPlay(0x321); + } + spF0[var_r31].y = spB4.y; + sp58[var_r31] = 0.16f * -sp68[var_r31]; + if (fabs(sp58[var_r31]) <= 1.0) { + sp48[var_r31] = -1.0f; + var_r25++; + } + sp48[var_r31] = 1.0f; + } + BoardModelPosSetV(sp20[var_r31], &spF0[var_r31]); + } + } + HuPrcVSleep(); + } + BoardModelMotionShiftSet(temp_r28, temp_r20, 0.0f, 5.0f, 0x40000001); + HuAudFXPlay(0x322); + for (var_r29 = 0; var_r29 < 0xB4; var_r29++) { + for (var_r31 = 0; var_r31 < 4; var_r31++) { + sp38[var_r31] += 4.0f; + if (sp38[var_r31] >= 360.0f) { + sp38[var_r31] -= 360.0f; + } + spC0[var_r31].y = 90.0f + sp38[var_r31]; + if (spC0[var_r31].y >= 360.0f) { + spC0[var_r31].y -= 360.0f; + } + spF0[var_r31].x = spB4.x + 120.0 * sin(M_PI * sp38[var_r31] / 180.0); + spF0[var_r31].z = spB4.z + 120.0 * cos(M_PI * sp38[var_r31] / 180.0); + BoardModelPosSetV(sp20[var_r31], &spF0[var_r31]); + BoardModelRotSetV(sp20[var_r31], &spC0[var_r31]); + } + HuPrcVSleep(); + } + for (var_r29 = 0; var_r29 < 0x14; var_r29++) { + for (var_r31 = 0; var_r31 < 4; var_r31++) { + spC0[var_r31].y += 4.5f; + BoardModelRotSetV(sp20[var_r31], &spC0[var_r31]); + } + HuPrcVSleep(); + } + HuPrcSleep(0x1E); + var_f30 = 35.0f; + var_r26 = 0; + for (var_r31 = 0; var_r31 < 4; var_r31++) { + sp58[var_r31] = 8.0f; + sp48[var_r31] = 1.0f; + } + var_r27 = 0; + while (1) { + for (var_r31 = 0; var_r31 < 4; var_r31++) { + if (sp48[var_r31] != -1.0f) { + sp28[var_r31] -= 1.7f; + sp68[var_r31] = sp58[var_r31] - 0.083333336f * (sp48[var_r31] * sp48[var_r31] * 0.25f); + sp48[var_r31] += 1.0f; + spF0[var_r31].y += sp68[var_r31]; + if (spF0[var_r31].y <= spB4.y) { + spF0[var_r31].y = spB4.y; + sp48[var_r31] = -1.0f; + } + spF0[var_r31].x = spB4.x + sp28[var_r31] * sin(M_PI * sp38[var_r31] / 180.0); + spF0[var_r31].z = spB4.z + sp28[var_r31] * cos(M_PI * sp38[var_r31] / 180.0); + BoardModelPosSetV(sp20[var_r31], &spF0[var_r31]); + } + } + if (sp28[0] < 100.0f) { + if (var_r27 == 0) { + var_r27 = 1; + BoardModelMotionShiftSet(temp_r28, temp_r21, 0.0f, 3.0f, 0x40000001); + HuAudFXPlay(forceMoveSfxTbl[GWBoardGet()]); + } + sp9C.y += var_f30; + BoardModelPosSetV(temp_r28, &sp9C); + var_f30 *= 0.945f; + if (sp9C.y >= 500.0f && var_r26 == 0) { + WipeCreate(2, 0, 0x2D); + BoardAudSeqFadeOut(0, 0x3E8); + var_r26 = 1; + } + } + if (var_r26 != 0 && WipeStatGet() == 0) { + break; + } + HuPrcVSleep(); + } + BoardPlayerMotionKill(currItemRestore, temp_r23); + for (var_r31 = 0; var_r31 < 4; var_r31++) { + BoardModelKill(sp20[var_r31]); + } + BoardModelMotionKill(temp_r28, temp_r21); + BoardModelMotionKill(temp_r28, temp_r20); + BoardStarShowNext(currItemRestore); + HuPrcKill(NULL); + while (1) { + HuPrcVSleep(); + } } static void ExecItemBowser(void) { @@ -1013,23 +1653,300 @@ static void ExecItemBowser(void) { } } -// DATA + 0x218 -// ... -static u8 data_offset_temp[0xC] = { 0 }; +static s32 booMotTbl[3] = { + 0x00020018, + 0x00020016, + -1 +}; + +static inline void ExecItemBooBallInlineFunc01(s32 speed) { + Vec sp20; + s32 var_r20; + + sp20 = booBallPos; + booBallScale.x = booBallScale.y = booBallScale.z = 1.0f; + booBallAlpha = 255.0f; + BoardModelPosSetV(booBallMdl, &booBallPos); + BoardModelScaleSetV(booBallMdl, &booBallScale); + BoardModelAlphaSet(booBallMdl, booBallAlpha); + BoardModelVisibilitySet(booBallMdl, 1); + for (var_r20 = 0; var_r20 < speed; var_r20++) { + booBallAlpha -= (255.0f/speed); + if (booBallAlpha < 0.0f) { + booBallAlpha = 0.0f; + } + booBallScale.x -= (1.0f/speed); + booBallScale.y -= (1.0f/speed); + booBallScale.z -= (1.0f/speed); + booBallPos.y -= (20.0f/speed); + BoardModelAlphaSet(booBallMdl, booBallAlpha); + BoardModelScaleSetV(booBallMdl, &booBallScale); + BoardModelPosSetV(booBallMdl, &booBallPos); + HuPrcVSleep(); + } + booBallScale.x = booBallScale.y = booBallScale.z = 0.0f; + booBallAlpha = 0.0f; + BoardModelScaleSetV(booBallMdl, &booBallScale); + BoardModelAlphaSet(booBallMdl, booBallAlpha); +} + +static inline void ExecItemBooBallInlineFunc02(s32 speed) { + Vec sp20; + s32 var_r20; + + sp20 = booBallPos; + booBallScale.x = booBallScale.y = booBallScale.z = 0.0f; + booBallAlpha = 0.0f; + BoardModelPosSetV(booBallMdl, &booBallPos); + BoardModelScaleSetV(booBallMdl, &booBallScale); + BoardModelAlphaSet(booBallMdl, booBallAlpha); + BoardModelVisibilitySet(booBallMdl, 1); + for (var_r20 = 0; var_r20 < speed; var_r20++) { + booBallAlpha += (255.0f/speed); + if (booBallAlpha > 255.0f) { + booBallAlpha = 255.0f; + } + booBallScale.x += (1.0f/speed); + booBallScale.y += (1.0f/speed); + booBallScale.z += (1.0f/speed); + booBallPos.y += (20.0f/speed); + BoardModelAlphaSet(booBallMdl, booBallAlpha); + BoardModelScaleSetV(booBallMdl, &booBallScale); + BoardModelPosSetV(booBallMdl, &booBallPos); + HuPrcVSleep(); + } + booBallPos.y = sp20.y + 20.0f; + booBallScale.x = booBallScale.y = booBallScale.z = 1.0f; + booBallAlpha = 255.0f; + BoardModelPosSetV(booBallMdl, &booBallPos); + BoardModelScaleSetV(booBallMdl, &booBallScale); + BoardModelAlphaSet(booBallMdl, booBallAlpha); +} // https://decomp.me/scratch/0M6lm static void ExecItemBooBall(void) { - (void) 4.25f; - (void) 0.016666668f; - (void) 0.33333334f; - (void) 8.5f; - (void) 0.6666667f; - (void) 325.0f; - (void) -0.5f; - (void) 40.0f; - (void) 125.0f; - (void) booBallPos; - (void) booBallScale; + UnkItemShowProcStruct spA0; + UnkItemShowProcStruct sp80; + Vec sp74; + Vec sp68; + Process *temp_r17; + Process *sp1C; + s16 spC; + s16 spA; + s32 sp18; + s32 var_r26; + s32 var_r28; + s32 var_r29; + s32 var_r30; + s32 var_r31; + + BoardAudSeqPause(0, 1, 0x3E8); + suitMdl = BoardBooCreate(currItemRestore, &sp74); + booBallMdl = BoardModelCreate(0x20012, booMotTbl, 0); + BoardModelMotionStart(booBallMdl, 1, 0x40000001); + BoardModelLayerSet(booBallMdl, 2); + BoardModelAttrSet(booBallMdl, 2); + BoardModelVisibilitySet(booBallMdl, 0); + // Inline? (same pattern in ExecItemGenie) + spA0.unk02 = suitMdl; + spA0.unk04 = 4.0f; + spA0.unk08 = 3.0f; + spA0.unk10 = spA0.unk14 = spA0.unk18 = 0.0f; + spA0.unk1C = 1; + HuAudFXPlay(0x350); + temp_r17 = ItemShowProc(&spA0, NULL); + // ====================================== + BoardModelPosGet(suitMdl, &booBallPos); + ExecItemBooBallInlineFunc02(60); + // Inline? ================================= + sp80.unk02 = booBallMdl; + sp80.unk04 = 4.0f; + sp80.unk08 = 4.0f; + sp80.unk10 = sp80.unk14 = sp80.unk18 = 0.0f; + sp80.unk1C = 1; + sp1C = BoardUiInlineFunc05(&sp80); + // ====================================== + BoardMusStart(1, 1, 0x7F, 0); + HuAudFXPlay(0x4C); + BoardWinCreate(2, 0x120015, 3); + BoardWinWait(); + BoardWinKill(); + if (BoardPlayerCoinsGet(currItemRestore) < 5) { + BoardWinCreate(2, 0x120016, 3); + BoardWinWait(); + BoardWinKill(); + } else { + var_r28 = 0; + for (var_r31 = 0; var_r31 < 4; var_r31++) { + if (var_r31 != currItemRestore) { + var_r28 += GWStarsGet(var_r31); + } + } + var_r26 = 0; + for (var_r31 = 0; var_r31 < 4; var_r31++) { + if (var_r31 != currItemRestore) { + var_r26 += BoardPlayerCoinsGet(var_r31); + } + } + do { + BoardWinCreateChoice(4, 0x120018, 3, 0); + BoardWinAttrSet(0x10); + if (BoardPlayerCoinsGet(currItemRestore) < 0x32 || var_r28 == 0) { + BoardWinChoiceDisable(1); + } + if (var_r26 == 0) { + BoardWinChoiceDisable(0); + } + if (GWPlayer[currItemRestore].com) { + if (var_r28 != 0 && BoardPlayerCoinsGet(currItemRestore) >= 0x32) { + BoardComKeySetDown(); + } else { + BoardComKeySetUp(); + } + } + BoardWinWait(); + BoardWinKill(); + var_r29 = BoardWinChoiceGet(); + switch (var_r29) { + case 0: + for (var_r31 = 0; var_r31 < 5; var_r31++) { + BoardPlayerCoinsAdd(currItemRestore, -1); + HuAudFXPlay(0xE); + HuPrcSleep(6); + } + HuAudFXPlay(0xF); + BoardBooStealTypeSet(0); + BoardStatusShowSetAll(0); + HuAudFXPlay(0x34F); + ExecItemBooBallInlineFunc01(30); + sp68.x = 0.0f; + sp68.y = 0.0f; + sp68.z = 0.0f; + BoardCameraMotionStartEx(suitMdl, 0, &sp68, 325.0f, -1.0f, 0x15); + BoardBooStealMain(); + BoardCameraViewSet(2); + BoardCameraMotionWait(); + ExecItemBooBallInlineFunc02(30); + var_r29 = BoardBooStealValueGet(&spC, &spA); + if (var_r29 == 0) { + var_r30 = 0x7000B; + } else if (spA == 0) { + var_r30 = 0x70009; + } else if (spA >= 1 && spA <= 3) { + var_r30 = 0x70008; + } else if (spA >= 4 && spA <= 6) { + var_r30 = 0x70007; + } else if (spA >= 7 && spA <= 8) { + var_r30 = 0x70006; + } else { + var_r30 = 0x70005; + } + sprintf(booCoinStr, "%d", spC); + HuAudFXPlay(0x4C); + BoardWinCreate(2, var_r30, 3); + BoardWinInsertMesSet((u32) (booCoinStr), 0); + BoardWinWait(); + BoardWinKill(); + BoardStatusShowSetAll(1); + if (var_r29 != 0) { + BoardPlayerMotionShiftSet(currItemRestore, 7, 0.0f, 8.0f, 0); + HuPrcSleep(0x1E); + for (var_r31 = 0; var_r31 < spC; var_r31++) { + BoardPlayerCoinsAdd(currItemRestore, 1); + HuAudFXPlay(7); + HuPrcVSleep(); + } + BoardPlayerMotionEndWait(currItemRestore); + HuPrcSleep(0xA); + BoardPlayerMotionShiftSet(currItemRestore, 1, 0.0f, 8.0f, 0x40000001); + } + break; + case 1: + for (var_r31 = 0; var_r31 < 0x32; var_r31++) { + BoardPlayerCoinsAdd(currItemRestore, -1); + HuAudFXPlay(0xE); + HuPrcSleep(1); + } + HuAudFXPlay(0xF); + BoardBooStealTypeSet(1); + BoardStatusShowSetAll(0); + ExecItemBooBallInlineFunc01(30); + sp68.x = 0.0f; + sp68.y = 0.0f; + sp68.z = 0.0f; + BoardCameraMotionStartEx(suitMdl, 0, &sp68, 325.0f, -1.0f, 0x15); + BoardBooStealMain(); + var_r29 = BoardBooStealLightCheck(); + BoardCameraViewSet(2); + BoardCameraMotionWait(); + ExecItemBooBallInlineFunc02(30); + if (var_r29 != 0) { + var_r30 = 0x7000A; + } else { + var_r30 = 0x7000B; + } + HuAudFXPlay(0x4C); + BoardWinCreate(2, var_r30, 3); + BoardWinWait(); + BoardWinKill(); + BoardStatusShowSetAll(1); + BoardAudSeqFadeOut(1, 0x3E8); + HuPrcSleep(0x17); + if (var_r29 != 0) { + BoardPlayerVoiceEnableSet(currItemRestore, 7, 0); + sp18 = HuAudSStreamPlay(6); + BoardPlayerMotionShiftSet(currItemRestore, 7, 0.0f, 8.0f, 0); + HuAudFXPlay(boardStarSndTbl[GWPlayer[currItemRestore].character]); + BoardPlayerStarsAdd(currItemRestore, 1); + HuAudFXPlay(8); + HuPrcVSleep(); + BoardPlayerMotionEndWait(currItemRestore); + BoardPlayerVoiceEnableSet(currItemRestore, 7, 1); + while (msmStreamGetStatus(sp18) != 0) { + HuPrcVSleep(); + } + } + BoardPlayerMotionShiftSet(currItemRestore, 1, 0.0f, 8.0f, 0x40000001); + break; + case 3: + BoardViewMapExec(currItemRestore); + break; + case 2: + case -1: + HuAudFXPlay(0x4C); + BoardWinCreate(2, 0x120017, 3); + BoardWinWait(); + BoardWinKill(); + break; + } + } while (var_r29 == 3); + } + BoardAudSeqFadeOut(1, 0x3E8); + HuPrcKill(sp1C); + BoardModelPosGet(booBallMdl, &booBallPos); + HuAudFXPlay(0x34F); + ExecItemBooBallInlineFunc01(60); + HuPrcKill(temp_r17); + BoardAudSeqPause(0, 0, 0x3E8); + CharModelLayerSetAll(3); + BoardModelPosGet(suitMdl, &sp74); + CharModelEffectCreate(1, &sp74); + HuAudFXPlay(0x351); + HuPrcSleep(0xA); + BoardModelKill(suitMdl); + BoardModelKill(booBallMdl); + HuPrcSleep(0xF); + HuPrcKill(NULL); + while (1) { + HuPrcVSleep(); + } +} + +static void ForceConsts(void) +{ + (void)-0.5f; + (void)40.0f; + (void)125.0f; } static void LampParticleUpdate(s32 arg0, ParticleData *arg1) { @@ -1565,7 +2482,7 @@ static void ExecItemGenie(void) { HuPrcVSleep(); } HuAudFXPlay(0x35E); - fn_8004F578(GWPlayer[currItemRestore].character, 0); + CharModelEffectEnableSet(GWPlayer[currItemRestore].character, 0); BoardPlayerMotionStart(currItemRestore, 6, 0x40000001); var_f29 = 0.0f; var_f31 = 1.0f; @@ -1597,7 +2514,7 @@ static void ExecItemGenie(void) { HuPrcVSleep(); } BoardRotateDiceNumbers(currItemRestore); - fn_8004F578(GWPlayer[currItemRestore].character, 1); + CharModelEffectEnableSet(GWPlayer[currItemRestore].character, 1); HuSprAnimKill(genieParticleAnim); BoardPlayerMotionKill(currItemRestore, geniePlayerMot[0]); BoardPlayerMotionKill(currItemRestore, geniePlayerMot[1]); @@ -1650,7 +2567,7 @@ static void ExecItemBagJump(void) { HuPrcVSleep(); } CharModelLayerSetAll(3); - CharModelCreateParticle(1, &sp14); + CharModelEffectCreate(1, &sp14); BoardModelVisibilitySet(temp_r31, 0); HuAudFXPlay(0x30D); HuPrcKill(NULL); @@ -1786,7 +2703,7 @@ static void ExecItemBag(void) { HuWinKill(temp_r28); BoardModelPosGet(suitMdl, &sp30); CharModelLayerSetAll(3); - CharModelCreateParticle(1, &sp30); + CharModelEffectCreate(1, &sp30); HuAudFXPlay(0x351); HuPrcSleep(0xA); HuPrcKill(temp_r24); diff --git a/src/game/board/lottery.c b/src/game/board/lottery.c new file mode 100755 index 00000000..e08f6781 --- /dev/null +++ b/src/game/board/lottery.c @@ -0,0 +1,2013 @@ +#include "game/board/lottery.h" +#include "game/audio.h" +#include "game/chrman.h" +#include "game/data.h" +#include "game/esprite.h" +#include "game/gamework_data.h" +#include "game/hsfdraw.h" +#include "game/hsfex.h" +#include "game/hsfman.h" +#include "game/objsub.h" +#include "game/pad.h" +#include "game/process.h" +#include "game/sprite.h" +#include "game/board/audio.h" +#include "game/board/com.h" +#include "game/board/main.h" +#include "game/board/model.h" +#include "game/board/player.h" +#include "game/board/space.h" +#include "game/board/tutorial.h" +#include "game/board/ui.h" +#include "game/board/window.h" + +#include "math.h" + +#define ABS(x) (((x) < 0) ? -(x) : (x)) + +typedef struct { + struct { + u8 unk00_field0 : 1; + s8 unk00_field1 : 1; + u8 unk00_field2 : 4; + }; + u8 unk01; + s16 unk02; + s16 unk04; + char unk06[2]; + AnimData *unk08; +} TicketWork; + +typedef struct { + struct { + u8 unk00_field0 : 1; + }; + s8 unk01; + s8 unk02; + s8 unk03; + u8 unk04; + char unk05[1]; + s16 unk06; + s16 unk08; +} LotteryTicketPickWork; + +extern s32 BoardShopHostGet(void); + +static void CreateModel(void); +static void KillModel(void); +static void DestroyLottery(void); +static void ExecLottery(void); +static void DoMiniJumpUp(s32 arg0); +static void DoMiniJumpDown(s32 arg0); +static void PayEnterFee(s32 arg0); +static void ShowTicket(void); +static void SetupTicket(s32 arg0); +static void ExecBallGame(void); +static void SetBallPrize(void); +static void ExecBallPrize(void); +static void ExecScratchTicket(s32 arg0); +static void ExecScratch(void); +static void KillScratch(void); +static void ExecScratchSpr(omObjData *arg0); +static void HideScratchSpr(void); +static void InitScratchSpr(void); +static void ExecScratchPick(omObjData *arg0); +static void InitScratchPick(void); +static void InitTicketPrizes(void); +static void ExecTicketFocus(s32 arg0); +static BOOL ScratchTicketCheckDone(AnimBmpData *arg0); +static u16 TicketGetPixel(u16 arg0, u16 arg1, u16 arg2); +static s32 TicketUpdate(AnimBmpData *arg0, Vec *arg1, s32 arg2); +static void ExecCoinPrize(void); +static void ExecItemPrize(void); +static void KillCoin(void); +static void ExecPrize(void); +static void ExecLose(s32 arg0); +static void CreateLotteryWin(s32 arg0); +static void KillLotteryWin(void); + +static s16 lotteryMdl[6]; +static s8 coinF[12]; +static s16 coinMdl[10]; + +static s32 lotteryMessBase; +static s16 lotterySpace; +static s8 currPrize; +s8 lbl_801D401B; +static s8 comLotteryType; +static s8 comLotteryWinType; +static u8 comInputPos; +static s32 handUpdateF; +// ... +static omObjData *lotteryTicketPickObj; +static s8 (*comInputDrawP)[2]; +Process *lotteryProc; + +static s16 hostMdl = -1; +static s16 lotteryMot[4] = { -1, -1, -1, -1 }; +static s16 lotterySpr = -1; +static s16 lotteryInstWin = -1; +static s16 gripMdl[2] = { 0, 0 }; +static s16 turnMot = -1; +static s16 ballMdl[4] = { -1, -1, -1, -1 }; +static s16 loseMot = -1; +static s16 ticketSprGrp = -1; + +static s8 comInputDraw1[][2] = { + { 0x0B, 0xF8 }, { 0x2B, 0xDD }, { 0x2A, 0xDC }, { 0x2B, 0xDC }, + { 0x2B, 0xDC }, { 0x29, 0xDB }, { 0x24, 0xD6 }, { 0x02, 0xE8 }, + { 0x00, 0x00 }, { 0xFC, 0x02 }, { 0xD8, 0x27 }, { 0xD8, 0x28 }, + { 0xD8, 0x28 }, { 0xD8, 0x27 }, { 0xDA, 0x29 }, { 0xDE, 0x2C }, + { 0xE4, 0x31 }, { 0xF0, 0x3A }, { 0x00, 0x3C }, { 0x06, 0x3A }, + { 0x1B, 0x32 }, { 0x23, 0x2B }, { 0x24, 0x2A }, { 0x25, 0x29 }, + { 0x26, 0x29 }, { 0x28, 0x27 }, { 0x28, 0x27 }, { 0x28, 0x26 }, + { 0x28, 0x26 }, { 0x2E, 0x20 }, { 0x39, 0x11 }, { 0x48, 0x00 }, + { 0x48, 0x00 }, { 0x35, 0xEA }, { 0x29, 0xDB }, { 0x24, 0xD5 }, + { 0x17, 0xCB }, { 0x00, 0xB8 }, { 0x00, 0xB8 }, { 0x00, 0xB8 }, + { 0x00, 0xB8 }, { 0x00, 0xB8 }, { 0xEB, 0xCA }, { 0xD6, 0xDB }, + { 0xD6, 0xDB }, { 0xD4, 0xDE }, { 0xD1, 0xE2 }, { 0xC4, 0xF2 }, + { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, + { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xC1, 0x0B }, + { 0xC6, 0x10 }, { 0xC9, 0x14 }, { 0xCB, 0x16 }, { 0xCB, 0x17 }, + { 0xCE, 0x1A }, { 0xD1, 0x1E }, { 0xD5, 0x23 }, { 0xD4, 0x22 }, + { 0xDB, 0x29 }, { 0xF5, 0x3E }, { 0x00, 0x48 }, { 0x00, 0x42 }, + { 0x0D, 0x3D }, { 0x24, 0x2A }, { 0x29, 0x26 }, { 0x29, 0x26 }, + { 0x29, 0x25 }, { 0x2D, 0x21 }, { 0x34, 0x18 }, { 0x40, 0x09 }, + { 0x48, 0x00 }, { 0x48, 0x00 }, { 0x43, 0xFA }, { 0x33, 0xE6 }, + { 0x29, 0xDB }, { 0x1B, 0xCF }, { 0x05, 0xBD }, { 0x00, 0xB8 }, + { 0x00, 0xB8 }, { 0x00, 0xB8 }, { 0xFB, 0xBD }, { 0xDD, 0xD5 }, + { 0xD6, 0xDC }, { 0xD6, 0xDC }, { 0xD4, 0xDE }, { 0xCB, 0xE9 }, + { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xC5, 0x0F }, + { 0xD0, 0x1D }, { 0xD5, 0x23 }, { 0xDC, 0x2A }, { 0xF0, 0x3B }, + { 0x00, 0x3D }, { 0x08, 0x3F }, { 0x15, 0x36 }, { 0x24, 0x2A }, + { 0x29, 0x26 }, { 0x2A, 0x24 }, { 0x30, 0x1C }, { 0x3B, 0x0F }, + { 0x48, 0x00 }, { 0x48, 0x00 }, { 0x3E, 0xF4 }, { 0x2D, 0xE0 }, + { 0x22, 0xD4 }, { 0x02, 0xBB }, { 0x00, 0xB8 }, { 0xFB, 0xBD }, + { 0xD9, 0xD8 }, { 0xD4, 0xDE }, { 0x7F, 0x7F } +}; + +static s8 comInputDraw2[][2] = { + { 0x07, 0x00 }, { 0x1F, 0x00 }, { 0x3A, 0x00 }, { 0x48, 0x00 }, + { 0x48, 0x00 }, { 0x48, 0x00 }, { 0x48, 0x00 }, { 0x48, 0x00 }, + { 0x43, 0xFA }, { 0x35, 0xEA }, { 0x2A, 0xDB }, { 0x1A, 0xCE }, + { 0x00, 0xB9 }, { 0x00, 0xB8 }, { 0x00, 0xB8 }, { 0x00, 0xB8 }, + { 0x00, 0xBA }, { 0xE9, 0xCC }, { 0xD5, 0xDD }, { 0xD4, 0xDE }, + { 0xD4, 0xDE }, { 0xD0, 0xE3 }, { 0xBD, 0xFB }, { 0xB8, 0x00 }, + { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, + { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xBC, 0x03 }, { 0xC2, 0x0C }, + { 0xCB, 0x17 }, { 0xD5, 0x23 }, { 0xD8, 0x27 }, { 0xF0, 0x3A }, + { 0x00, 0x43 }, { 0x18, 0x34 }, { 0x29, 0x26 }, { 0x29, 0x26 }, + { 0x29, 0x26 }, { 0x29, 0x25 }, { 0x29, 0x26 }, { 0x29, 0x25 }, + { 0x29, 0x25 }, { 0x2C, 0x22 }, { 0x31, 0x1B }, { 0x39, 0x12 }, + { 0x47, 0x00 }, { 0x48, 0x00 }, { 0x48, 0x00 }, { 0x37, 0xEC }, + { 0x26, 0xD7 }, { 0x00, 0xB8 }, { 0x00, 0xB8 }, { 0x00, 0xB8 }, + { 0x00, 0xB8 }, { 0x00, 0xB8 }, { 0x00, 0xB8 }, { 0xFB, 0xBD }, + { 0xE5, 0xCE }, { 0xD6, 0xDC }, { 0xD6, 0xDC }, { 0xD6, 0xDC }, + { 0xD5, 0xDD }, { 0xD2, 0xE0 }, { 0xCC, 0xE8 }, { 0xC4, 0xF2 }, + { 0xBE, 0xFA }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, + { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, + { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xB8, 0x00 }, + { 0xC7, 0x12 }, { 0xD8, 0x27 }, { 0xF6, 0x3E }, { 0x00, 0x47 }, + { 0x00, 0x44 }, { 0x05, 0x42 }, { 0x16, 0x35 }, { 0x28, 0x27 }, + { 0x29, 0x26 }, { 0x29, 0x26 }, { 0x29, 0x26 }, { 0x29, 0x26 }, + { 0x7F, 0x7F } +}; + +static s8 comInputBall[][2] = { + { 0xE5, 0x00 }, { 0xC0, 0x03 }, { 0xBC, 0x04 }, { 0xBC, 0x03 }, + { 0xBF, 0x07 }, { 0xC3, 0x0C }, { 0xCB, 0x17 }, { 0xD5, 0x24 }, + { 0xDE, 0x2C }, { 0xF9, 0x3E }, { 0x00, 0x48 }, { 0x00, 0x45 }, + { 0x06, 0x40 }, { 0x21, 0x2C }, { 0x28, 0x27 }, { 0x28, 0x26 }, + { 0x29, 0x25 }, { 0x30, 0x1D }, { 0x43, 0x05 }, { 0x48, 0x00 }, + { 0x33, 0xE7 }, { 0x24, 0xD6 }, { 0x07, 0xBF }, { 0x00, 0xB8 }, + { 0x00, 0xB8 }, { 0xE4, 0xCF }, { 0xD4, 0xDE }, { 0xC6, 0xF0 }, + { 0xB8, 0x00 }, { 0xC7, 0x11 }, { 0xD2, 0x20 }, { 0xD5, 0x24 }, + { 0xD6, 0x25 }, { 0xD8, 0x27 }, { 0xE1, 0x2E }, { 0x00, 0x43 }, + { 0x00, 0x48 }, { 0x00, 0x44 }, { 0x1D, 0x30 }, { 0x28, 0x27 }, + { 0x28, 0x27 }, { 0x2C, 0x22 }, { 0x39, 0x12 }, { 0x48, 0x00 }, + { 0x34, 0xE8 }, { 0x23, 0xD5 }, { 0x0A, 0xC1 }, { 0x00, 0xB8 }, + { 0x00, 0xB8 }, { 0xF4, 0xC3 }, { 0xD4, 0xDE }, { 0xC3, 0xF4 }, + { 0xB8, 0x00 }, { 0xC6, 0x10 }, { 0xD3, 0x21 }, { 0xD6, 0x25 }, + { 0xD8, 0x27 }, { 0xDF, 0x2D }, { 0xEA, 0x36 }, { 0x00, 0x48 }, + { 0x00, 0x48 }, { 0x00, 0x48 }, { 0x17, 0x35 }, { 0x28, 0x27 }, + { 0x29, 0x25 }, { 0x33, 0x19 }, { 0x48, 0x00 }, { 0x48, 0x00 }, + { 0x34, 0xE8 }, { 0x23, 0xD5 }, { 0x00, 0xB9 }, { 0x00, 0xB8 }, + { 0x00, 0xB8 }, { 0xFA, 0xBE }, { 0xD4, 0xDE }, { 0xC8, 0xED }, + { 0xB8, 0x00 }, { 0xB8, 0x00 }, { 0xC0, 0x09 }, { 0xD0, 0x1C }, + { 0xD6, 0x24 }, { 0xDC, 0x2A }, { 0xED, 0x38 }, { 0x00, 0x48 }, + { 0x00, 0x48 }, { 0x00, 0x48 }, { 0x1B, 0x31 }, { 0x28, 0x27 }, + { 0x29, 0x26 }, { 0x2D, 0x21 }, { 0x3D, 0x0C }, { 0x48, 0x00 }, + { 0x33, 0xE7 }, { 0x20, 0xD3 }, { 0x00, 0xB8 }, { 0x00, 0xB8 }, + { 0x00, 0xBB }, { 0xDB, 0xD7 }, { 0xD4, 0xDE }, { 0xD3, 0xDF }, + { 0xBB, 0xFD }, { 0xB8, 0x00 }, { 0x7F, 0x7F } +}; + +void BoardLotteryHostSet(s16 arg0) { + hostMdl = arg0; +} + +s16 BoardLotteryHostGet(void) { + return hostMdl; +} + +void BoardLotteryExec(void) { + if (BoardPlayerSizeGet(GWSystem.player_curr) == 2) { + return; + } + BoardDiceDigit2DShowSet(0); + lotteryProc = HuPrcChildCreate(ExecLottery, 0x2003, 0x3800, 0, boardMainProc); + HuPrcDestructorSet2(lotteryProc, DestroyLottery); + while (lotteryProc) { + HuPrcVSleep(); + } + BoardDiceDigit2DShowSet(1); +} + +void BoardLotteryInit(void) { + Vec sp14; + Vec sp8; + s32 i; + + for (i = 0; i < 5; i++) { + lotteryMdl[i] = -1; + } + for (i = 0; i < 4; i++) { + lotteryMot[i] = -1; + } + for (i = 0; i < 4; i++) { + ballMdl[i] = -1; + } + turnMot = -1; + loseMot = -1; + if (GWBoardGet() != 8) { + BoardModelVisibilitySet(BoardLotteryHostGet(), 0); + BoardSpaceLinkTransformGet(0x10000000, &sp14, &sp8, NULL); + lotteryMdl[0] = BoardModelCreate(0x50000, NULL, 0); + BoardModelMotionStart(lotteryMdl[0], 0, 0); + BoardModelMotionSpeedSet(lotteryMdl[0], 0.0f); + BoardModelPosSetV(lotteryMdl[0], &sp14); + BoardModelRotSetV(lotteryMdl[0], &sp8); + HuDataDirClose(0x50000); + } +} + +static void CreateModel(void) { + s32 i; + s32 sp10[4] = { 0x00050005, 0x00050006, 0x00050007, 0x00050008 }; + s32 sp8[2] = { 0x00050003, 0x00050004 }; + s32 sp20[9][4] = { + { 0x00020001, 0x00020002, 0x00020003, 0x00020004 }, + { 0x00020009, 0x0002000A, 0x0002000B, 0x0002000C }, + { 0x0002000E, 0x0002000F, 0x00020010, 0x00020011 }, + { 0x00020018, 0x00020019, 0x0002001A, 0x0002001B }, + { 0x0002001D, 0x0002001E, 0x0002001F, 0x00020020 }, + { 0x00020022, 0x00020023, 0x00020024, 0x00020025 }, + { 0x0002000E, 0x0002000F, 0x00020010, 0x00020011 }, + { 0x0002002A, 0x0002002B, 0x0002002C, 0x0002002D }, + { 0x0002002A, 0x0002002B, 0x0002002C, 0x0002002D } + }; + + lotteryMdl[1] = BoardModelCreate(0x50001, NULL, 0); + fn_8006DDE8(lotteryMdl[1], -1.0f); + BoardModelMotionSpeedSet(lotteryMdl[1], 0.0f); + lotteryMdl[2] = BoardModelCreate(0x50002, NULL, 0); + BoardModelVisibilitySet(lotteryMdl[2], 0); + fn_8006DDE8(lotteryMdl[2], -1.0f); + BoardModelMotionStart(lotteryMdl[2], 0, 0); + BoardModelMotionSpeedSet(lotteryMdl[2], 0.0f); + for (i = 0; i < 4; i++) { + ballMdl[i] = BoardModelCreate(sp10[i], NULL, 0); + BoardModelVisibilitySet(ballMdl[i], 0); + fn_8006DDE8(ballMdl[i], -1.0f); + } + for (i = 0; i < 2; i++) { + gripMdl[i] = BoardModelCreate(sp8[i], NULL, 0); + BoardModelVisibilitySet(gripMdl[i], 0); + fn_8006DDE8(gripMdl[i], -1.0f); + BoardModelMotionSpeedSet(gripMdl[i], 0.0f); + } + lotteryMdl[3] = BoardModelCreate(0x50011, NULL, 0); + BoardModelVisibilitySet(lotteryMdl[3], 0); + fn_8006DDE8(lotteryMdl[3], -1.0f); + BoardModelPosSet(BoardLotteryHostGet(), 0.0f, 0.0f, 0.0f); + BoardModelVisibilitySet(BoardLotteryHostGet(), 1); + for (i = 0; i < 4; i++) { + lotteryMot[i] = BoardModelMotionCreate(BoardLotteryHostGet(), sp20[GWBoardGet()][i]); + } + BoardModelMotionStart(BoardLotteryHostGet(), lotteryMot[0], 0x40000001); + BoardModelHookSet(lotteryMdl[0], "toto_heyhoo", BoardLotteryHostGet()); + BoardModelHookSet(lotteryMdl[0], "toto_gara", lotteryMdl[1]); + BoardModelHookSet(lotteryMdl[0], "toto_efe", lotteryMdl[2]); + BoardModelHookSet(lotteryMdl[0], "toto_chibidai", lotteryMdl[3]); + BoardModelHookSet(lotteryMdl[1], "toto_grip", gripMdl[0]); + BoardModelHookSet(lotteryMdl[1], "toto_grip1", gripMdl[1]); +} + +static void KillModel(void) { + s32 i; + + if (lotteryMdl[1] != -1) { + BoardModelHookReset(lotteryMdl[0]); + } + BoardModelMotionStart(BoardLotteryHostGet(), 1, 0x40000001); + if (turnMot != -1) { + BoardPlayerMotionKill(GWSystem.player_curr, turnMot); + turnMot = -1; + } + for (i = 0; i < 4; i++) { + if (lotteryMot[i] != -1) { + BoardModelMotionKill(BoardLotteryHostGet(), lotteryMot[i]); + lotteryMot[i] = -1; + } + } + for (i = 0; i < 4; i++) { + if (ballMdl[i] != -1) { + BoardModelKill(ballMdl[i]); + ballMdl[i] = -1; + } + } + for (i = 0; i < 2; i++) { + if (gripMdl[i] != -1) { + BoardModelKill(gripMdl[i]); + gripMdl[i] = -1; + } + } + for (i = 0; i < 5; i++) { + if (i != 0 && lotteryMdl[i] != -1) { + BoardModelKill(lotteryMdl[i]); + lotteryMdl[i] = -1; + } + } + BoardModelVisibilitySet(BoardLotteryHostGet(), 0); +} + +void BoardLotteryKill(void) { + if (lotteryProc) { + HuPrcKill(lotteryProc); + } + if (lotteryMdl[0] != -1) { + BoardModelKill(lotteryMdl[0]); + lotteryMdl[0] = -1; + } +} + +static void DestroyLottery(void) { + s32 i; + + for (i = 0; i < 4; i++) { + if (i != GWSystem.player_curr) { + BoardPlayerMotBlendSet(i, 0, 7); + } + } + if (loseMot != -1) { + BoardPlayerMotionKill(GWSystem.player_curr, loseMot); + loseMot = -1; + } + KillLotteryWin(); + BoardConfettiKill(); + BoardWinKill(); + KillScratch(); + KillCoin(); + HuDataDirClose(0x50000); + lotteryProc = NULL; +} + +static void ExecLottery(void) { + Vec sp38; + Vec sp2C; + Vec sp20; + Vec sp14; + Vec sp8; + s16 temp_r26; + s16 temp_r28; + u32 var_r25; + s32 var_r27; + s32 temp_r31; + s32 i; + s32 temp_r29; + + switch (GWBoardGet()) { + case 0: + lotteryMessBase = 0x60002; + break; + case 1: + lotteryMessBase = 0x6000F; + break; + case 2: + lotteryMessBase = 0x6001C; + break; + case 3: + lotteryMessBase = 0x60029; + break; + case 4: + lotteryMessBase = 0x60036; + break; + case 5: + lotteryMessBase = 0x60043; + break; + case 6: + lotteryMessBase = 0x60002; + break; + case 7: + lotteryMessBase = 0x60052; + break; + case 8: + lotteryMessBase = 0x60052; + break; + } + temp_r29 = BoardDataDirReadAsync(0x50000); + temp_r31 = GWSystem.player_curr; + temp_r28 = GWPlayer[temp_r31].space_curr; + BoardRotateDiceNumbers(temp_r31); + BoardWinCreateChoice(0, 0x60000, -1, 0); + if (GWPlayer[temp_r31].com) { + if (BoardPlayerCoinsGet(temp_r31) >= 5) { + BoardComKeySetLeft(); + } else { + BoardComKeySetRight(); + } + } + BoardWinWait(); + if (BoardWinChoiceGet() != 0) { + if (temp_r29 != -1) { + BoardDataAsyncWait(temp_r29); + } + HuPrcEnd(); + } + if (BoardPlayerCoinsGet(temp_r31) < 5) { + BoardWinCreate(0, 0x60001, -1); + BoardWinWait(); + BoardWinKill(); + if (temp_r29 != -1) { + BoardDataAsyncWait(temp_r29); + } + HuPrcEnd(); + } + BoardWinKill(); + if (temp_r29 != -1) { + BoardDataAsyncWait(temp_r29); + } + BoardModelMotionStart(BoardLotteryHostGet(), 1, 0x40000001); + BoardAudSeqPause(0, 1, 1000); + CreateModel(); + BoardStatusShowSetAll(0); + lotterySpace = BoardSpaceLinkFlagSearch(0, temp_r28, 0x02000000); + BoardSpacePosGet(0, temp_r28, &sp38); + BoardSpacePosGet(0, lotterySpace, &sp2C); + PSVECSubtract(&sp2C, &sp38, &sp20); + if (GWBoardGet() == 2 || GWBoardGet() == 3) { + PSVECScale(&sp20, &sp20, 0.95f); + PSVECAdd(&sp20, &sp38, &sp2C); + } + temp_r26 = 180.0 * (atan2(-sp20.x, -sp20.z) / M_PI); + if (BoardPlayerSizeGet(temp_r31) == 1) { + BoardModelVisibilitySet(gripMdl[0], 0); + BoardModelVisibilitySet(gripMdl[1], 1); + } else { + BoardModelVisibilitySet(gripMdl[0], 1); + BoardModelVisibilitySet(gripMdl[1], 0); + } + sp14.x = -3.0f; + sp14.y = temp_r26; + sp14.z = 0.0f; + sp8.x = 0.0f; + sp8.y = 200.0f; + sp8.z = 0.0f; + BoardCameraMotionStartEx(lotteryMdl[0], &sp14, &sp8, 1300.0f, -1.0f, 0x1B); + if (BoardPlayerSizeGet(temp_r31) == 1) { + BoardModelVisibilitySet(lotteryMdl[3], 1); + } + omVibrate(temp_r31, 0xC, 6, 6); + HuAudFXPlay(0x331); + HuAudFXPlay(0x344); + BoardModelMotionStart(lotteryMdl[0], 0, 0); + while (!BoardModelMotionEndCheck(lotteryMdl[0])) { + HuPrcVSleep(); + } + BoardModelMotionShiftSet(BoardLotteryHostGet(), lotteryMot[3], 0.0f, 10.0f, 0); + BoardPlayerRotSet(temp_r31, 0.0f, temp_r26, 0.0f); + BoardPlayerPosLerpStart(temp_r31, &sp38, &sp2C, 0x14); + while (GWPlayer[temp_r31].moving) { + HuPrcVSleep(); + } + if (BoardPlayerSizeGet(temp_r31) == 1) { + DoMiniJumpUp(temp_r31); + } + BoardPlayerPosGet(temp_r31, &sp2C); + for (i = 0; i < 4; i++) { + if (i != temp_r31) { + BoardPlayerPosGet(i, &sp38); + PSVECSubtract(&sp2C, &sp38, &sp20); + PSVECNormalize(&sp20, &sp20); + BoardPlayerMotBlendSet(i, 180.0 * (atan2(sp20.x, sp20.z) / M_PI), 7); + } + } + BoardMusStart(1, 2, 0x7F, 0); + BoardRotateDiceNumbers(temp_r31); + while (!BoardStatusStopCheck(temp_r31)) { + HuPrcVSleep(); + } + BoardModelMotionShiftSet(BoardLotteryHostGet(), lotteryMot[0], 0.0f, 10.0f, 0x40000001); + if (GWPlayer[temp_r31].field00_bit9 == 0 && GWSystem.max_turn - GWSystem.turn >= 5) { + SetupTicket(temp_r31); + ShowTicket(); + var_r27 = 1; + } else { + var_r27 = 0; + } + if (GWBoardGet() == 7 || GWBoardGet() == 8) { + var_r27 = 0; + } + PayEnterFee(var_r27); + var_r25 = BoardRandMod(100) & 0xFF; + if (var_r25 < 50) { + ExecBallGame(); + } else { + ExecScratch(); + } + ExecPrize(); + if (BoardPlayerSizeGet(temp_r31) == 1) { + DoMiniJumpDown(temp_r31); + } + BoardPlayerMoveBetween(temp_r31, lotterySpace, temp_r28); + while (GWPlayer[temp_r31].moving) { + HuPrcVSleep(); + } + BoardRotateDiceNumbers(temp_r31); + BoardModelVisibilitySet(ballMdl[currPrize & 3], 0); + BoardAudSeqFadeOut(1, 1000); + BoardCameraTargetPlayerSet(temp_r31); + BoardCameraViewSet(1); + BoardStatusShowSet(temp_r31, 0); + BoardModelMotionStart(lotteryMdl[0], 0, 0x40000004); + while (!BoardModelMotionEndCheck(lotteryMdl[0])) { + HuPrcVSleep(); + } + BoardModelMotionSpeedSet(lotteryMdl[0], 0.0f); + BoardModelAttrReset(lotteryMdl[0], 0x40000004); + HuAudFXPlay(0x32F); + KillModel(); + BoardStatusShowSetAll(1); + BoardAudSeqPause(0, 0, 1000); + HuPrcEnd(); +} + +static void DoMiniJumpUp(s32 arg0) { + Mtx sp34; + Vec sp28; + Vec sp1C; + Vec sp10; + float temp_f29; + float temp_f30; + float var_f27; + s16 var_r27; + s16 temp_r26; + s16 i; + + var_r27 = BoardModelIDGet(lotteryMdl[0]); + Hu3DModelObjMtxGet(var_r27, "toto_chibidai", sp34); + Hu3DMtxTransGet(sp34, &sp28); + BoardPlayerMotionStart(arg0, 4, 0); + temp_f29 = BoardPlayerMotionMaxTimeGet(arg0); + BoardPlayerPosGet(arg0, &sp1C); + sp28.y += 52.5308f; + PSVECSubtract(&sp28, &sp1C, &sp10); + sp10.x /= temp_f29; + sp10.z /= temp_f29; + sp10.y /= temp_f29; + OSf32tos16(&temp_f29, &temp_r26); + for (i = 0; i < temp_r26; i++) { + OSs16tof32(&i, &temp_f30); + if (i < 4) { + var_f27 = 5.0f; + } else { + var_f27 = 0.0f; + } + sp1C.x += sp10.x; + sp1C.y += sp10.y + var_f27 - 0.016666668f * temp_f30 * temp_f30; + sp1C.z += sp10.z; + BoardPlayerPosSetV(arg0, &sp1C); + HuPrcVSleep(); + } + sp1C.y = sp28.y; + BoardPlayerPosSetV(arg0, &sp1C); + BoardRotateDiceNumbers(arg0); +} + +static void DoMiniJumpDown(s32 arg0) { + Vec sp24; + Vec sp18; + Vec spC; + float temp_f31; + float var_f29; + s16 i; + + BoardPlayerPosGet(arg0, &sp18); + BoardSpacePosGet(0, lotterySpace, &sp24); + PSVECSubtract(&sp24, &sp18, &spC); + BoardPlayerMotionStart(arg0, 4, 0); + spC.x /= 30.0f; + spC.z /= 30.0f; + for (i = 0; i < 30; i++) { + OSs16tof32(&i, &temp_f31); + if (i < 3) { + var_f29 = 10.0f; + } else { + var_f29 = 0.0f; + } + sp18.x += spC.x; + sp18.y += var_f29 + -0.016666668f * temp_f31 * temp_f31 * 0.75f; + sp18.z += spC.z; + if (sp24.y > sp18.y) { + sp18.y = sp24.y; + break; + } + BoardPlayerPosSetV(arg0, &sp18); + HuPrcVSleep(); + } + BoardPlayerMotionStart(arg0, 5, 0); + BoardPlayerPosSetV(arg0, &sp24); + while (!BoardPlayerMotionEndCheck(arg0)) { + HuPrcVSleep(); + } +} + +static void PayEnterFee(s32 arg0) { + s32 var_r29; + s32 temp_r31; + s32 i; + + temp_r31 = GWSystem.player_curr; + BoardStatusShowSetForce(temp_r31); + BoardStatusShowSet(temp_r31, 1); + if (arg0 != 0) { + var_r29 = lotteryMessBase + 0xC; + } else { + var_r29 = lotteryMessBase; + } + BoardWinCreate(2, var_r29, BoardWinPortraitGet()); + BoardWinWait(); + BoardWinKill(); + while (!BoardStatusStopCheck(temp_r31)) { + HuPrcVSleep(); + } + for (i = 0; i < 5; i++) { + BoardPlayerCoinsAdd(temp_r31, -1); + HuAudFXPlay(0xE); + HuPrcSleep(6); + } + HuAudFXPlay(0xF); + BoardStatusShowSet(temp_r31, 0); +} + +static void ShowTicket(void) { + s16 sp10; + s16 spE; + s16 spC; + s16 spA; + s8 sp8; + float var_f31; + s16 temp_r31; + s32 var_r29; + s32 i; + u8 *var_r28; + s32 sp14[] = { + 0x00050015, + 0x00050016, + 0x00050017, + 0x00050018, + 0x00050019, + 0x0005001A, + 0x0005001B, + 0x0005001C + }; + + if (GWBoardGet() == 7 || GWBoardGet() == 8) { + return; + } + sp8 = GWPlayer[GWSystem.player_curr].field00_bitA; + var_r28 = (u8*) &sp8; + temp_r31 = HuSprGrpCreate(4); + BoardSpriteCreate(0x50014, 0x7531, 0, &spA); + HuSprGrpMemberSet(temp_r31, 0, spA); + HuSprAttrSet(temp_r31, 0, 9); + HuSprPosSet(temp_r31, 0, 288.0f, 240.0f); + HuSprTPLvlSet(temp_r31, 0, 0.0f); + var_r29 = GWPlayer[(*var_r28 >> 4) & 3].character; + BoardSpriteCreate(sp14[var_r29], 0x7530, 0, &spC); + HuSprGrpMemberSet(temp_r31, 1, spC); + HuSprAttrSet(temp_r31, 1, 9); + HuSprPosSet(temp_r31, 1, 200.0f, 237.0f); + HuSprTPLvlSet(temp_r31, 1, 0.0f); + var_r29 = GWPlayer[(*var_r28 >> 2) & 3].character; + BoardSpriteCreate(sp14[var_r29], 0x7530, 0, &spE); + HuSprGrpMemberSet(temp_r31, 2, spE); + HuSprAttrSet(temp_r31, 2, 9); + HuSprPosSet(temp_r31, 2, 294.0f, 237.0f); + HuSprTPLvlSet(temp_r31, 2, 0.0f); + var_r29 = GWPlayer[*var_r28 & 3].character; + BoardSpriteCreate(sp14[var_r29], 0x7530, 0, &sp10); + HuSprGrpMemberSet(temp_r31, 3, sp10); + HuSprAttrSet(temp_r31, 3, 9); + HuSprPosSet(temp_r31, 3, 388.0f, 237.0f); + HuSprTPLvlSet(temp_r31, 3, 0.0f); + BoardWinCreate(2, lotteryMessBase + 10, BoardWinPortraitGet()); + BoardWinWait(); + for (var_f31 = 0.0f; var_f31 <= 1.0f; var_f31 += 0.15f) { + if (var_f31 >= 1.0f) { + var_f31 = 1.0f; + } + for (i = 0; i < 4; i++) { + HuSprTPLvlSet(temp_r31, i, var_f31); + } + HuPrcVSleep(); + } + BoardWinCreate(2, lotteryMessBase + 11, BoardWinPortraitGet()); + BoardWinWait(); + BoardWinKill(); + for (var_f31 = 1.0f; var_f31 > 0.0f; var_f31 -= 0.15f) { + if (var_f31 < 0.0f) { + var_f31 = 0.0f; + } + for (i = 0; i < 4; i++) { + HuSprTPLvlSet(temp_r31, i, var_f31); + } + HuPrcVSleep(); + } + HuSprGrpKill(temp_r31); + (void) var_r29; // Required to match +} + +static void SetupTicket(s32 arg0) { + u8 sp8[4]; + u8 var_r29; + s32 var_r28; + s32 var_r30; + s32 var_r31; + + for (var_r30 = var_r31 = 0; var_r31 < 4; var_r31++) { + if (arg0 != var_r31 && GWPlayer[var_r31].field00_bit9 != 0) { + sp8[var_r30] = GWPlayer[var_r31].field00_bitA; + var_r30++; + } + } + for (var_r28 = 0; var_r28 < 1000; var_r28++) { + var_r29 = BoardRandMod(0x40) & 0x3F; + for (var_r31 = 0; var_r30 != 0 && var_r31 < var_r30; var_r31++) { + if (sp8[var_r31] == var_r29) { + var_r29 = 0x80; + break; + } + } + if (var_r29 != 0x80) { + break; + } + } + GWPlayer[arg0].field00_bitA = var_r29; + GWPlayer[arg0].field00_bit9 = 1; +} + +static void LotteryInlineFunc00(s32 arg0, s32 arg1) { + s32 sp20[2] = { 0x00050012, 0x00050013 }; + s16 sp10[2] = { 0x0098, 0x0078 }; + s16 sp14[2] = { 0x0078, 0x0078 }; + Vec sp34; + float temp_f30; + s16 var_r30; + + sp34.x = (sp14[arg0] / 2) + 32; + if (arg1 == 0) { + sp34.y = -sp10[arg0] / 2; + temp_f30 = 4.0f; + if (lotterySpr == -1) { + lotterySpr = espEntry(sp20[arg0], 0x7531, 0); + espAttrSet(lotterySpr, 1); + } + } else { + sp34.y = (sp10[arg0] / 2) + 40; + temp_f30 = -4.0f; + } + for (var_r30 = sp10[arg0] + 40; var_r30 > 0; var_r30 -= 4) { + sp34.y += temp_f30; + espPosSet(lotterySpr, sp34.x, sp34.y); + HuPrcVSleep(); + } + if (arg1 != 0 && lotterySpr >= 0) { + espKill(lotterySpr); + lotterySpr = -1; + } +} + +static void ExecBallGame(void) { + Vec sp4C; + float temp_f24; + float var_f23; + float var_f25; + float var_f26; + float var_f27; + float var_f19; + float var_f28; + s32 var_r22; + s32 var_r21; + s32 var_r20 = 0; + s32 temp_r25; + s32 var_r24; + s32 temp_r27; + u8 var_r26; + s8 var_r17; + s8 spB; + s8 spA; + s8 sp9; + s8 *temp_r23; + s32 sp58[] = { + 0x005F001D, + 0x001A001D, + 0x006D001D, + 0x008A001D, + 0x0085001D, + 0x0011001D, + 0x000D001D, + 0x0081001D + }; + + temp_r27 = GWSystem.player_curr; + currPrize = -1; + sp4C.x = 0.0f; + sp4C.y = 210.0f; + sp4C.z = 0.0f; + BoardCameraMotionStartEx(lotteryMdl[0], NULL, &sp4C, 980.0f, -1.0f, 0x15); + LotteryInlineFunc00(0, 0); + BoardCameraMotionWait(); + BoardWinCreate(2, lotteryMessBase + 1, BoardWinPortraitGet()); + BoardWinWait(); + BoardWinKill(); + HuPrcSleep(0x12); + CreateLotteryWin(0); + turnMot = BoardPlayerMotionCreate(temp_r27, sp58[GWPlayer[temp_r27].character]); + BoardPlayerMotionSpeedSet(temp_r27, 0.0f); + BoardModelAttrSet(lotteryMdl[1], 0x40000001); + BoardModelMotionSpeedSet(lotteryMdl[1], 0.0f); + BoardModelMotionTimeSet(lotteryMdl[1], 0.0f); + BoardModelAttrSet(gripMdl[0], 0x40000001); + BoardModelAttrSet(gripMdl[1], 0x40000001); + BoardPlayerMotionShiftSet(temp_r27, turnMot, 0.0f, 8.0f, 0x40000001); + BoardPlayerMotionSpeedSet(temp_r27, 0.0f); + temp_f24 = BoardModelMotionMaxTimeGet(lotteryMdl[1]); + temp_f24 -= 4.0f; + comInputPos = 0; + var_r20 = 0; + spB = spA = sp9 = var_r17 = 0; + var_r26 = var_f28 = var_f27 = var_f25 = var_f23 = var_r21 = 0; + HuPrcSleep(0x18); + var_r24 = var_r22 = 0; + while (1) { + HuPrcVSleep(); + BoardModelMotionSpeedSet(lotteryMdl[1], var_f28); + BoardModelMotionSpeedSet(gripMdl[0], var_f28); + BoardModelMotionSpeedSet(gripMdl[1], var_f28); + BoardPlayerMotionSpeedSet(temp_r27, var_f28); + if (var_r22 != 0 && var_f28 <= 0.1f) { + BoardModelMotionSpeedSet(lotteryMdl[1], 0.0f); + BoardModelMotionSpeedSet(gripMdl[0], 0.0f); + BoardModelMotionSpeedSet(gripMdl[1], 0.0f); + BoardPlayerMotionSpeedSet(temp_r27, 0.0f); + break; + } + if (var_r24 == 0) { + if (BoardModelMotionTimeGet(lotteryMdl[1]) >= temp_f24) { + var_r21++; + if ((var_r26++) != 0 || var_r21 >= 1 || var_r20 != 0) { + var_r22 = 1; + if (currPrize == -1) { + var_f27 *= 128.0f; + OSf32tos8(&var_f27, &lbl_801D401B); + SetBallPrize(); + } + } + var_r24 = 1; + } + } + if (var_r24 != 0 && BoardModelMotionTimeGet(lotteryMdl[1]) < 2.0f) { + var_r24 = 0; + } + if (var_r22 == 0) { + var_r17 = spB; + sp9 = spA; + if (!GWPlayer[temp_r27].com) { + temp_r25 = GWPlayer[temp_r27].port; + spB = HuPadStkX[temp_r25]; + spA = HuPadStkY[temp_r25]; + } else { + temp_r23 = comInputBall[comInputPos++]; + spB = temp_r23[0]; + spA = temp_r23[1]; + } + } else { + spB = spA = 0; + } + if (spB == 0x7F || spA == 0x7F) { + var_r20 = 1; + } else { + if ((abs(spB) < 57.600002f && abs(spA) < 57.600002f) || (var_r17 == spB && sp9 == spA) || (spB == 0 && spA == 0)) { + var_f28 *= 0.93f; + var_f27 *= 0.8f; + if (var_f27 < 0.01f && var_r26 != 0) { + var_r26--; + } + } else { + OSs8tof32(&spB, &var_f26); + OSs8tof32(&spA, &var_f19); + var_f25 = 180.0 * (atan2(var_f26, var_f19) / M_PI); + if (var_f25 < 0.0f) { + var_f25 += 360.0f; + } + if (var_f25 < 20.0f) { + HuAudFXPlay(0x333); + } + var_f26 = var_f25 - var_f23; + if (!(var_f26 < 0.0f)) { + if (ABS(var_f26) > 30.0f) { + var_f26 = 10.0f; + } + var_f27 += 0.01f * var_f26; + if (var_f28 + var_f27 < 2.0f) { + var_f28 += var_f27; + } else { + var_f28 = 2.0f; + } + } + } + } + var_f23 = var_f25; + } + KillLotteryWin(); + LotteryInlineFunc00(0, 1); +} + +static void SetBallPrize(void) { + Process *sp8; + s32 temp_r31; + + while (1) { + temp_r31 = BoardRandMod(100); + if (temp_r31 > 97) { + currPrize = 0; + } else if (temp_r31 > 87) { + currPrize = 1; + } else if (temp_r31 > 67) { + currPrize = 2; + } else { + currPrize = 3; + } + if (GWSystem.max_turn - GWSystem.turn != 0 || currPrize != 2) { + break; + } + } + sp8 = HuPrcChildCreate(ExecBallPrize, 0x2004, 0x3800, 0, lotteryProc); +} + +static void ExecBallPrize(void) { + Vec sp30; + Vec sp24; + Vec sp18; + Vec spC; + float var_f25; + float temp_f28; + float temp_f27; + float temp_f26; + float var_f29; + float var_f30; + s32 var_r28; + s16 temp_r29; + s16 var_r27; + s16 sp8; + HsfObject *temp_r3; + Mtx sp6C; + Mtx sp3C; + + var_r28 = 0; + HuAudFXPlay(0x34C); + temp_r29 = ballMdl[currPrize & 3]; + BoardModelPosGet(lotteryMdl[0], &sp30); + BoardModelRotGet(lotteryMdl[0], &sp18); + PSMTXRotRad(sp6C, 'Y', MTXDegToRad(sp18.y)); + var_r27 = BoardModelIDGet(lotteryMdl[0]); + temp_r3 = Hu3DModelObjPtrGet(var_r27, "toto_gara"); + temp_f28 = sp30.y + temp_r3->data.curr.pos.y + 100.0f; + PSMTXTrans(sp3C, temp_r3->data.curr.pos.x, temp_r3->data.curr.pos.y + 210.0f, temp_r3->data.curr.pos.z + -40.0f); + PSMTXConcat(sp6C, sp3C, sp3C); + Hu3DMtxTransGet(sp3C, &spC); + PSVECAdd(&spC, &sp30, &sp30); + BoardModelVisibilitySet(temp_r29, 1); + sp24.x = 10.5f; + sp24.y = -3.0f; + sp24.z = 0.0f; + PSMTXMultVec(sp6C, &sp24, &sp24); + var_f29 = 0.0f; + var_f30 = 1.8f; + temp_f27 = 0.016666668f; + sp8 = 0; + while (1) { + OSs16tof32(&sp8, &var_f25); + temp_f26 = 4.9f * (2.0f * var_f25 - temp_f27) * temp_f27; + sp24.y -= temp_f26; + sp24.x *= 0.92f; + sp24.z *= 0.92f; + PSVECAdd(&sp24, &sp30, &sp30); + var_f29 += sp24.z; + if (sp30.y - 25.0f < temp_f28) { + if (var_r28 == 0) { + HuAudFXPlay(0x334); + var_r28 = 1; + } + sp30.y = 25.0f + temp_f28 + temp_f26 * var_f30; + if (var_f30 > 0.0f) { + var_f30 -= 0.1f; + } + } + BoardModelPosSetV(temp_r29, &sp30); + BoardModelRotSet(temp_r29, 0.0f, var_f29, 0.0f); + HuPrcVSleep(); + sp8++; + } +} + +const s32 lbl_8011DFD0[] = { + 0x0007001E, + 0x0007001F, + 0x00070020, + 0x00070021, + 0x00070022, + 0x00070023, + 0x00070024, + 0x00070025 +}; + +const s32 lbl_8011DFF0[] = { + 0x00050009, + 0x0005000A, + 0x0005000B, + 0x0005000C, + 0x0005000D, + 0x0005000E, + 0x0005000F, + 0x00050010 +}; + +const s32 lbl_8011E010[] = { + 0x0005001D, + 0x0005001E, + 0x0005001F, + 0x00050020 +}; + +static omObjData *ticketObj[12] = { NULL }; +static s8 ticketPrize[12] = { 0 }; +static Vec handLastPos = { 0.0f, 0.0f, 0.0f }; + +static s32 loseSoundTbl[] = { + 0x0000012E, + 0x0000016E, + 0x000001AE, + 0x000001EE, + 0x0000022E, + 0x0000026E, + 0x000002AE, + 0x000002EE +}; + +static s32 loseMotTbl[] = { + 0x005F0033, + 0x001A0033, + 0x006D0033, + 0x008A0033, + 0x00850033, + 0x00110033, + 0x000D0033, + 0x00810033 +}; + +static void ExecScratchTicket(s32 arg0) { + Vec sp24; + Vec sp18; + Vec spC; + u16 var_r29; + u16 var_r28; + s16 *temp_r25; + s32 var_r24; + s32 temp_r27; + u16 var_r23; + omObjData *var_r22; + TicketWork *temp_r30; + AnimBmpData *temp_r31; + + var_r24 = GWPlayer[GWSystem.player_curr].character; + var_r22 = ticketObj[arg0]; + temp_r30 = OM_GET_WORK_PTR(var_r22, TicketWork); + lotteryMdl[4] = BoardModelCreate(lbl_8011DFF0[var_r24], NULL, 0); + BoardModelLayerSet(lotteryMdl[4], 6); + BoardModelPassSet(lotteryMdl[4], 0); + BoardCameraDirGet(&spC); + BoardModelRotYSet(lotteryMdl[4], 180.0 * (atan2(-spC.x, -spC.z) / M_PI)); + BoardModelScaleSet(lotteryMdl[4], 3.0f, 3.0f, 3.0f); + sp24.x = 320.0f; + sp24.y = 480.0f; + sp24.z = 500.0f; + CreateLotteryWin(1); + while (1) { + HuPrcVSleep(); + if (sp24.y <= 240.0f) { + break; + } + sp24.y -= 4.0f; + Hu3D2Dto3D(&sp24, 1, &sp18); + BoardModelPosSetV(lotteryMdl[4], &sp18); + } + comInputPos = 0; + if (BoardRandMod(100) < 50) { + comInputDrawP = comInputDraw1; + } else { + comInputDrawP = comInputDraw2; + } + temp_r27 = HuAudFXPlay(0x335); + HuAudFXVolSet(temp_r27, 0); + while (1) { + HuPrcVSleep(); + if (TicketUpdate(temp_r30->unk08->bmp, &sp24, temp_r27) != 0) { + break; + } + if (ScratchTicketCheckDone(temp_r30->unk08->bmp)) { + break; + } + } + HuAudFXStop(temp_r27); + while (1) { + HuPrcVSleep(); + if (sp24.y >= 480.0f) { + break; + } + sp24.y += 4.0f; + Hu3D2Dto3D(&sp24, 1, &sp18); + BoardModelPosSetV(lotteryMdl[4], &sp18); + } + BoardModelVisibilitySet(lotteryMdl[4], 0); + temp_r31 = temp_r30->unk08->bmp; + temp_r25 = temp_r31->data; + for (var_r28 = 0; var_r28 < temp_r31->sizeY; var_r28++) { + for (var_r29 = 0; var_r29 < temp_r31->sizeX; var_r29++) { + var_r23 = TicketGetPixel(temp_r31->sizeX, var_r29, var_r28); + temp_r25[var_r23] = 0; + } + HuPrcVSleep(); + } + KillLotteryWin(); + BoardModelKill(lotteryMdl[4]); + lotteryMdl[4] = -1; +} + +static void ExecScratch(void) { + TicketWork *temp_r28; + float var_f31; + s32 temp_curr; + s32 temp_r31; + + currPrize = -1; + BoardFilterFadeInit(0x1E, 0xA0); + InitTicketPrizes(); + InitScratchSpr(); + temp_curr = GWSystem.player_curr; + if (GWPlayer[temp_curr].com) { + comLotteryType = BoardRandMod(4); + comLotteryWinType = BoardRandMod(3); + } + BoardWinCreate(2, lotteryMessBase + 9, BoardWinPortraitGet()); + BoardWinWait(); + BoardWinKill(); + CreateLotteryWin(2); + InitScratchPick(); + while (currPrize == -1) { + HuPrcVSleep(); + } + temp_r31 = currPrize; + currPrize = ticketPrize[temp_r31]; + ExecTicketFocus(temp_r31); + KillLotteryWin(); + LotteryInlineFunc00(1, 0); + ExecScratchTicket(temp_r31); + LotteryInlineFunc00(1, 1); + temp_r28 = OM_GET_WORK_PTR(ticketObj[temp_r31], TicketWork); + for (var_f31 = 1.0f; var_f31 > 0.0f; var_f31 -= 0.078125f) { + if (var_f31 < 0.0f) { + var_f31 = 0.0f; + } + HuSprTPLvlSet(ticketSprGrp, temp_r28->unk00_field2, var_f31); + HuPrcVSleep(); + } + HideScratchSpr(); + BoardFilterFadeOut(30); +} + +static void KillScratch(void) { + if (ticketSprGrp != -1) { + HuSprGrpKill(ticketSprGrp); + ticketSprGrp = -1; + } + if (lotteryTicketPickObj) { + OM_GET_WORK_PTR(lotteryTicketPickObj, LotteryTicketPickWork)->unk00_field0 = 1; + } + memset(ticketObj, 0, sizeof(ticketObj)); +} + +static void ExecScratchSpr(omObjData *arg0) { + Vec sp20; + Vec sp14; + Vec sp8; + s32 temp_r29; + TicketWork *temp_r30; + + temp_r30 = OM_GET_WORK_PTR(arg0, TicketWork); + if (temp_r30->unk00_field0 != 0 || BoardIsKill()) { + temp_r29 = temp_r30->unk00_field2; + HuSprAttrSet(ticketSprGrp, temp_r29, 4); + HuSprAttrSet(ticketSprGrp, temp_r29 + 12, 4); + ticketObj[temp_r29] = NULL; + omDelObjEx(HuPrcCurrentGet(), arg0); + return; + } + if (temp_r30->unk01 != 0) { + temp_r30->unk01--; + return; + } + sp14.x = arg0->trans.x; + sp14.y = arg0->trans.y; + sp20.x = arg0->rot.x; + sp20.y = arg0->rot.y; + PSVECSubtract(&sp14, &sp20, &sp8); + if (ABS(sp8.x) < 1.0f && ABS(sp8.y) < 1.0f) { + sp8 = sp14; + temp_r30->unk00_field1 = 1; + } else { + PSVECScale(&sp8, &sp8, 0.2f); + PSVECAdd(&sp20, &sp8, &sp8); + temp_r30->unk00_field1 = 0; + } + HuSprPosSet(ticketSprGrp, temp_r30->unk00_field2, sp8.x, sp8.y); + HuSprPosSet(ticketSprGrp, temp_r30->unk00_field2 + 12, sp8.x, sp8.y); + arg0->rot.x = sp8.x; + arg0->rot.y = sp8.y; +} + +static void HideScratchSpr(void) { + s32 i; + + for (i = 0; i < 12; i++) { + if (ticketObj[i]) { + OM_GET_WORK_PTR(ticketObj[i], TicketWork)->unk00_field0 = 1; + } + } +} + +static void InitScratchSpr(void) { + Vec sp18; + Vec spC; + omObjData *temp_r31; + TicketWork *temp_r29; + s32 temp_curr; + s16 temp_r28; + s16 sp8; + s16 i; + + temp_curr = GWSystem.player_curr; + BoardPlayerRotGet(temp_curr, &sp18); + memset(ticketObj, 0, sizeof(ticketObj)); + BoardCameraRotGet(&spC); + temp_r28 = HuSprGrpCreate(0x18); + ticketSprGrp = temp_r28; + for (i = 0; i < 12; i++) { + temp_r31 = omAddObjEx(boardObjMan, 0x101, 0, 0, -1, ExecScratchSpr); + ticketObj[i] = temp_r31; + temp_r29 = OM_GET_WORK_PTR(temp_r31, TicketWork); + temp_r29->unk00_field0 = 0; + temp_r29->unk00_field2 = i; + temp_r29->unk01 = (i / 4) * 2; + temp_r29->unk02 = temp_r29->unk04 = -1; + temp_r31->trans.x = 107.0f + 110.0f * (i % 4); + temp_r31->trans.y = 98.0f + 110.0f * (i / 4); + temp_r31->rot.x = -56.0f; + temp_r31->rot.y = temp_r31->trans.y; + BoardSpriteCreate(lbl_8011E010[ticketPrize[i]], 0x157C, NULL, &sp8); + HuSprGrpMemberSet(temp_r28, i, sp8); + HuSprPosSet(temp_r28, i, temp_r31->rot.x, temp_r31->rot.y); + HuSprAttrSet(temp_r28, i, 8); + temp_r29->unk02 = sp8; + BoardSpriteCreate(0x50021, 0x1388, &temp_r29->unk08, &sp8); + HuSprGrpMemberSet(temp_r28, i + 12, sp8); + HuSprPosSet(temp_r28, i + 12, temp_r31->rot.x, temp_r31->rot.y); + HuSprAttrSet(temp_r28, i + 12, 8); + temp_r29->unk04 = sp8; + } + HuSprGrpDrawNoSet(temp_r28, 0x40); +} + +static inline u32 ExecStratchPickInlineFunc(LotteryTicketPickWork *temp_r29) { + s32 var_r21; + s32 temp_r23; + u32 var_r26; + + var_r21 = GWSystem.player_curr; + var_r26 = 0; + if (!GWPlayer[var_r21].com) { + temp_r23 = GWPlayer[GWSystem.player_curr].port; + var_r26 = HuPadDStkRep[temp_r23] | HuPadBtnDown[temp_r23]; + } else if (comLotteryType != temp_r29->unk02) { + var_r26 = 2; + } else if (comLotteryWinType != temp_r29->unk03) { + var_r26 = 4; + } else if (comLotteryType == temp_r29->unk02 && comLotteryWinType == temp_r29->unk03) { + var_r26 = 0x100; + } + return var_r26; +} + +static void ExecScratchPick(omObjData *arg0) { + float var_f29; + float var_f28; + s8 var_r28; + s8 var_r25; + s8 var_r24; + u32 var_r26; + LotteryTicketPickWork *temp_r29; + + temp_r29 = OM_GET_WORK_PTR(arg0, LotteryTicketPickWork); + if (temp_r29->unk00_field0 || BoardIsKill()) { + HuSprGrpKill(temp_r29->unk08); + lotteryTicketPickObj = 0; + omDelObjEx(HuPrcCurrentGet(), arg0); + return; + } + if (temp_r29->unk04 != 0) { + temp_r29->unk04--; + return; + } + var_r25 = var_r24 = 0; + var_r26 = ExecStratchPickInlineFunc(temp_r29); + if (var_r26 == 0x100) { + currPrize = (temp_r29->unk02 + (temp_r29->unk03 * 4)); + temp_r29->unk00_field0 = 1; + HuAudFXPlay(2); + return; + } + var_r28 = 0; + if (var_r26 == 8) { + var_r24 = -1; + var_r28 = 1; + } + if (var_r26 == 4) { + var_r24 = 1; + var_r28 = 1; + } + if (var_r26 == 1) { + var_r25 = -1; + var_r28 = 1; + } + if (var_r26 == 2) { + var_r25 = 1; + var_r28 = 1; + } + if ((var_r25 != 0 || var_r24 != 0) && GWPlayer[GWSystem.player_curr].com) { + temp_r29->unk04 = 0x14; + } + temp_r29->unk02 += var_r25; + temp_r29->unk03 += var_r24; + if (temp_r29->unk02 < 0) { + temp_r29->unk02 = 0; + var_r28 = 0; + } else if (temp_r29->unk03 < 0) { + temp_r29->unk03 = 0; + var_r28 = 0; + } + if (temp_r29->unk02 >= 4) { + temp_r29->unk02 = 3; + var_r28 = 0; + } else if (temp_r29->unk03 >= 3) { + temp_r29->unk03 = 2; + var_r28 = 0; + } + if (var_r28 != 0) { + HuAudFXPlay(0); + } + OSs8tof32(&temp_r29->unk02, &var_f29); + OSs8tof32(&temp_r29->unk03, &var_f28); + var_f29 = 107.0f + 110.0f * var_f29 - 32.0f + 16.0f; + var_f28 = 98.0f + 110.0f * var_f28 + 32.0f - 24.0f; + HuSprPosSet(temp_r29->unk08, 0, var_f29, var_f28); +} + +static void InitScratchPick(void) { + float temp_f31 = 91.0f; + float temp_f30 = 106.0f; + omObjData *temp_r30; + LotteryTicketPickWork *var_r31; + + temp_r30 = omAddObjEx(boardObjMan, 0x101, 0, 0, -1, ExecScratchPick); + lotteryTicketPickObj = temp_r30; + var_r31 = OM_GET_WORK_PTR(temp_r30, LotteryTicketPickWork); + var_r31->unk02 = var_r31->unk03 = 0; + var_r31->unk04 = 6; + var_r31->unk00_field0 = 0; + var_r31->unk01 = GWPlayer[GWSystem.player_curr].character; + var_r31->unk08 = HuSprGrpCreate(1); + BoardSpriteCreate(lbl_8011DFD0[var_r31->unk01], 0x1388, 0, &var_r31->unk06); + HuSprGrpMemberSet(var_r31->unk08, 0, var_r31->unk06); + HuSprAttrSet(var_r31->unk08, 0, 8); + HuSprPosSet(var_r31->unk08, 0, temp_f31, temp_f30); + HuSprGrpDrawNoSet(var_r31->unk08, 0x40); +} + +static void InitTicketPrizes(void) { + s32 temp_r31; + s32 i; + + memset(ticketPrize, 3, sizeof(ticketPrize)); + for (i = 0; i < 3; i++) { + do { + temp_r31 = BoardRandMod(12); + } while (ticketPrize[temp_r31] != 3); + ticketPrize[temp_r31] = i; + if (GWSystem.max_turn - GWSystem.turn == 0 && i == 2) { + ticketPrize[temp_r31] = 3; + } + } +} + +static void ExecTicketFocus(s32 arg0) { + float var_f31; + float temp_f30; + omObjData *var_r30; + TicketWork *temp_r29; + s32 i; + + var_r30 = ticketObj[arg0]; + var_r30->trans.x = 288.0f; + var_r30->trans.y = 240.0f; + for (i = 0; i < 12; i++) { + if (i != arg0) { + OM_GET_WORK_PTR(ticketObj[i], TicketWork)->unk00_field0 = 1; + } + } + temp_r29 = OM_GET_WORK_PTR(ticketObj[arg0], TicketWork); + for (var_f31 = 0.0f; var_f31 < 90.0f; var_f31 += 2.0f) { + temp_f30 = 1.0 + 1.2999999523162842 * sin(var_f31 * M_PI / 180.0); + HuSprScaleSet(ticketSprGrp, temp_r29->unk00_field2, temp_f30, temp_f30); + HuSprScaleSet(ticketSprGrp, temp_r29->unk00_field2 + 12, temp_f30, temp_f30); + HuPrcVSleep(); + } +} + +static BOOL ScratchTicketCheckDone(AnimBmpData *arg0) { + s32 var_r29; + s32 var_r31; + s32 var_r30; + u16 *var_r28; + + var_r28 = arg0->data; + for (var_r29 = var_r30 = 0; var_r30 < arg0->sizeY; var_r30++) { + for (var_r31 = 0; var_r31 < arg0->sizeX; var_r31++) { + if (var_r28[var_r31 + var_r30 * arg0->sizeX] == 0) { + var_r29++; + } + } + } + if (var_r29 >= arg0->sizeX * arg0->sizeY - 300) { + return TRUE; + } else { + return FALSE; + } +} + +static u16 TicketGetPixel(u16 arg0, u16 arg1, u16 arg2) { + u16 var_r31; + u16 var_r30; + u16 var_r29; + u16 var_r28; + + var_r29 = (arg1 & 3); + var_r28 = (arg2 & 3); + var_r31 = (arg1 >> 2); + var_r30 = (arg2 >> 2); + return var_r29 + (var_r28 << 2) + ((var_r31 + var_r30 * (arg0 >> 2)) << 4); +} + +static s32 TicketUpdate(AnimBmpData *arg0, Vec *arg1, s32 arg2) { + Vec sp48; + Vec sp3C; + float temp_f25; + float temp_f20; + s32 var_r18; + s16 var_r17; + s32 var_r21; + s32 var_r20; + s8 *temp_r19; + s16 *sp38; + s32 sp34; + s16 sp26; + s16 sp24; + s16 sp22; + s8 spD; + + if (GWPlayer[GWSystem.player_curr].com) { + temp_r19 = comInputDrawP[comInputPos++]; + if (temp_r19[0] == 0x7F && temp_r19[1] == 0x7F) { + return -1; + } + OSs8tof32(&temp_r19[0], &sp48.x); + OSs8tof32(&temp_r19[1], &sp48.y); + } else { + sp34 = GWPlayer[GWSystem.player_curr].port; + sp48.x = HuPadStkX[sp34]; + sp48.y = HuPadStkY[sp34]; + } + sp48.z = 0.0f; + if (sp48.x == 0.0f && sp48.y == 0.0f) { + handLastPos = *arg1; + handUpdateF = 0; + HuAudFXVolSet(arg2, 0); + return 0; + } + if (handUpdateF == 0) { + handUpdateF = 1; + } + PSVECNormalize(&sp48, &sp48); + temp_f20 = atan2f(sp48.x, -sp48.y); + sp48.x = sin(temp_f20); + sp48.y = cos(temp_f20); + temp_f25 = 127.0f * PSVECMag(&sp48); + OSf32tos8(&temp_f25, &spD); + HuAudFXVolSet(arg2, spD); + sp48.x *= 8.0f; + sp48.y *= 8.0f; + PSVECAdd(&sp48, arg1, &sp3C); + var_r18 = 0; + if (sp3C.x < 192.0f) { + sp3C.x = 192.0f; + var_r18 = 1; + } + if (sp3C.y < 192.0f) { + sp3C.y = 192.0f; + var_r18 = 1; + } + if (sp3C.x >= 384.0f) { + sp3C.x = 384.0f; + var_r18 = 1; + } + if (sp3C.y >= 288.0f) { + sp3C.y = 288.0f; + var_r18 = 1; + } + if (var_r18 != 0) { + HuAudFXVolSet(arg2, 0); + } + *arg1 = sp3C; + Hu3D2Dto3D(&sp3C, 1, &sp3C); + BoardModelPosSetV(lotteryMdl[4], &sp3C); + sp3C = *arg1; + sp3C.x -= 192.0f; + sp3C.y -= 192.0f; + sp3C.x *= arg0->sizeX / 192.0f; + sp3C.y *= arg0->sizeY / 96.0f; + sp24 = arg0->sizeX; + sp38 = arg0->data; + for (var_r20 = -8; var_r20 < 9; var_r20++) { + for (var_r21 = -8; var_r21 < 9; var_r21++) { + OSf32tos16(&sp3C.x, &var_r17); + OSf32tos16(&sp3C.y, &sp26); + if (var_r17 + var_r21 < arg0->sizeX && sp26 + var_r20 < arg0->sizeY && var_r17 + var_r21 >= 0 && sp26 + var_r20 >= 0) { + var_r17 += var_r21; + sp26 += var_r20; + sp22 = TicketGetPixel(sp24, var_r17, sp26); + if (sp22 < arg0->sizeX * arg0->sizeY) { + sp38[sp22] = 0; + } + } + } + } + DCFlushRange(arg0->data, (u32) (arg0->sizeX * arg0->sizeY * 2) >> 3); + handLastPos = *arg1; + return 0; +} + +static s32 ExecCoinPrizeInlineFunc(void) { + s32 i; + + for (i = 0; i < 10; i++) { + if (coinF[i] == 0) { + return i; + } + } + return -1; +} + +static void ExecCoinPrize(void) { + Vec sp64[10]; + Vec sp8; + float sp3C[10]; + float sp14[10]; + float var_f31; + s32 var_r26; + s32 var_r28; + s32 temp_r27; + s32 var_r30; + s32 i; + + temp_r27 = GWSystem.player_curr; + if (currPrize == 0) { + var_r28 = 100; + } else { + var_r28 = 30; + } + memset(coinMdl, 0, sizeof(coinMdl)); + memset(coinF, 0, 10); + BoardPlayerPosGet(temp_r27, &sp8); + var_f31 = 150.0f + sp8.y; + if (BoardPlayerSizeGet(temp_r27) == 1) { + var_f31 = 110.0f + (52.5308f + (0.3f * var_f31)); + } + for (i = 0; i < 10; i++) { + coinMdl[i] = BoardModelCreate(0x7000A, NULL, 0); + BoardModelVisibilitySet(coinMdl[i], 0); + } + while (1) { + HuPrcVSleep(); + if (var_r28 > 0) { + var_r30 = ExecCoinPrizeInlineFunc(); + if (var_r30 != -1) { + coinF[var_r30] = 1; + sp64[var_r30].x = sp8.x + 100.0f * (BoardRandFloat() - 0.5f); + sp64[var_r30].y = sp8.y + 700.0f; + sp64[var_r30].z = sp8.z + 100.0f * (BoardRandFloat() - 0.5f); + sp14[var_r30] = -20.0f + -10.0f * BoardRandFloat(); + sp3C[var_r30] = BoardRandMod(360); + BoardModelVisibilitySet(coinMdl[var_r30], 1); + BoardModelScaleSet(coinMdl[var_r30], 0.5f, 0.5f, 0.5f); + var_r28--; + } + } else { + var_r26 = 0; + for (i = 0; i < 10; i++) { + if (coinF[i] != 0) { + var_r26 = 1; + } + } + if (var_r26 == 0) { + return; + } + } + for (i = 0; i < 10; i++) { + if (coinF[i] != 0) { + if (sp64[i].y < var_f31) { + sp64[i].y = var_f31; + CharModelLayerSetAll(2); + CharModelCoinEffectCreate(1, &sp64[i]); + BoardModelVisibilitySet(coinMdl[i], 0); + coinF[i] = 0; + BoardPlayerCoinsAdd(temp_r27, 1); + HuAudFXPlay(7); + omVibrate(temp_r27, 0xC, 6, 6); + } else { + BoardModelPosSetV(coinMdl[i], &sp64[i]); + BoardModelRotSet(coinMdl[i], 0.0f, sp3C[i], 0.0f); + sp3C[i] = BoardDAngleCalc(45.0f + sp3C[i]); + sp64[i].y += sp14[i]; + } + } + } + } +} + +static void ExecItemPrize(void) { + Vec sp20; + Vec sp14; + float temp_f29; + float var_f28; + float var_f30; + float var_f31; + s32 temp_r26; + s32 var_r28; + s32 temp_r29; + s16 *var_r31; + s16 i; + s32 spC[2] = { + 0x0007006F, + 0x00070070 + }; + s8 sp8[2] = { + 0x02, 0x03 + }; + + temp_r29 = GWSystem.player_curr; + var_r28 = (BoardRandFloat() < 0.5f) ? 1 : 0; + memset(coinMdl, 0, sizeof(coinMdl)); + var_r31 = &coinMdl[0]; + *var_r31 = BoardModelCreate(spC[var_r28], NULL, 0); + var_f30 = BoardPlayerRotYGet(temp_r29); + BoardModelRotYSet(*var_r31, var_f30); + BoardModelScaleSet(*var_r31, 1.0f, 1.0f, 1.0f); + BoardSpacePosGet(0, GWPlayer[temp_r29].space_curr, &sp20); + BoardPlayerPosGet(temp_r29, &sp14); + sp14.y = sp20.y; + sp20 = sp14; + sp14.y += 700.0f; + sp20.y += 280.0f; + temp_f29 = (sp20.y - sp14.y) / 60.0f; + temp_r26 = HuAudFXPlay(0x35F); + for (i = 0; i < 60; i++) { + sp14.y += temp_f29; + BoardModelPosSetV(*var_r31, &sp14); + HuPrcVSleep(); + } + HuPrcSleep(30); + BoardPlayerPosGet(temp_r29, &sp20); + if (BoardPlayerSizeGet(temp_r29) == 0) { + sp20.y += 100.0f; + } else { + sp20.y += 30.000002f; + } + temp_f29 = (sp20.y - sp14.y) / 30.0f; + var_f28 = 0.0f; + HuAudFXPlay(0x30D); + for (i = 0; i < 30; i++) { + sp14.y += temp_f29; + var_f30 = BoardDAngleCalc(15.0f + var_f30); + var_f31 = cos(var_f28 * M_PI / 180.0); + if (var_f31 <= 0.0f) { + var_f31 = 0.01f; + } + var_f28 += 3.3333333f; + BoardModelPosSetV(*var_r31, &sp14); + BoardModelRotYSet(*var_r31, var_f30); + BoardModelScaleSet(*var_r31, var_f31, var_f31, var_f31); + HuPrcVSleep(); + } + HuAudFXStop(temp_r26); + BoardModelKill(*var_r31); + *var_r31 = -1; + BoardPlayerItemAdd(GWSystem.player_curr, sp8[var_r28]); + omVibrate(GWSystem.player_curr, 0xC, 6, 6); +} + +static void KillCoin(void) { + s32 i; + + for (i = 0; i < 10; i++) { + BoardModelKill(coinMdl[i]); + coinMdl[i] = -1; + } +} + +static void ExecPrize(void) { + Vec sp14; + Vec sp8; + s16 var_r29; + s16 var_r23; + s32 var_r26; + s32 var_r28; + s32 var_r27; + s32 temp_r30; + s32 var_r31; + s32 i; + s32 var_r24; + + var_r28 = -1; + var_r29 = 0; + var_r27 = -1; + sp14.x = 0.0f; + sp14.y = 200.0f; + sp14.z = 0.0f; + BoardCameraMotionStartEx(lotteryMdl[0], 0, &sp14, 1300.0f, -1.0f, 0x15); + temp_r30 = GWSystem.player_curr; + BoardStatusShowSetForce(temp_r30); + BoardStatusShowSet(temp_r30, 1); + for (var_r24 = i = 0; i < 3; i++) { + if (GWPlayer[GWSystem.player_curr].items[i] != -1) { + var_r24++; + } + } + var_r31 = currPrize; + if (var_r31 == 0) { + BoardModelVisibilitySet(lotteryMdl[2], 1); + BoardModelMotionStart(lotteryMdl[2], 0, 0x40000001); + BoardModelMotionSpeedSet(lotteryMdl[2], 2.0f); + } + var_r26 = 0; + switch (var_r31) { + case 0: + var_r28 = lotteryMessBase + 2; + var_r29 = 7; + var_r26 = 0x64; + break; + case 1: + var_r28 = lotteryMessBase + 4; + var_r29 = 7; + var_r26 = 0x50; + break; + case 2: + var_r28 = lotteryMessBase + 5; + if (var_r24 < 3) { + var_r29 = 7; + var_r26 = 0x50; + } else { + var_r29 = 8; + } + break; + case 3: + var_r28 = lotteryMessBase + 7; + var_r29 = 8; + break; + } + if (var_r31 != 3) { + HuAudFXPlay(0x332); + } + if (var_r29 == 7) { + BoardModelMotionShiftSet(BoardLotteryHostGet(), lotteryMot[1], 0.0f, 10.0f, 0x40000001); + } + if (var_r26 != 0) { + BoardPlayerPosGet(temp_r30, &sp8); + sp8.y = 700.0f; + BoardConfettiCreate(&sp8, var_r26, 150.0f); + } + if (var_r31 == 0 || var_r31 == 1) { + BoardAudSeqPause(1, 1, 0x1F4); + HuPrcSleep(0x14); + if (var_r31 == 0) { + var_r27 = HuAudSStreamPlay(0xA); + } else { + var_r27 = HuAudSStreamPlay(9); + } + } + var_r23 = (s32) BoardPlayerRotYGet(temp_r30) + 180; + BoardPlayerMotBlendSet(temp_r30, var_r23, 0xF); + while (!BoardPlayerMotBlendCheck(temp_r30)) { + HuPrcVSleep(); + } + if (var_r31 == 0 || var_r31 == 1) { + while (HuAudSStreamStatGet(var_r27) != 0) { + HuPrcVSleep(); + } + var_r27 = -1; + BoardAudSeqPause(1, 0, 1000); + } + BoardWinCreate(2, var_r28, BoardWinPortraitGet()); + BoardWinWait(); + if (var_r31 == 2) { + if (var_r24 == 3) { + BoardWinCreate(2, lotteryMessBase + 6, BoardWinPortraitGet()); + BoardWinWait(); + } else { + BoardAudSeqPause(1, 1, 1000); + HuPrcSleep(0x30); + var_r27 = HuAudSStreamPlay(2); + } + } + if (var_r29 == 8) { + HuAudFXPlay(loseSoundTbl[GWPlayer[temp_r30].character]); + BoardPlayerVoiceEnableSet(temp_r30, var_r29, 0); + } + BoardPlayerMotionShiftSet(temp_r30, var_r29, 0.0f, 8.0f, 0); + switch (var_r31) { + case 0: + case 1: + ExecCoinPrize(); + break; + case 2: + if (var_r24 < 3) { + ExecItemPrize(); + } else { + var_r31 = 3; + } + break; + } + if (var_r27 != -1) { + while (HuAudSStreamStatGet(var_r27) != 0) { + HuPrcVSleep(); + } + var_r27 = -1; + BoardAudSeqPause(1, 0, 1000); + } + while (!BoardPlayerMotionEndCheck(temp_r30)) { + HuPrcVSleep(); + } + if (var_r31 != 3) { + var_r28 = lotteryMessBase + 3; + } else { + var_r28 = lotteryMessBase + 8; + } + BoardModelMotionShiftSet(BoardLotteryHostGet(), lotteryMot[2], 0.0f, 10.0f, 0x40000001); + BoardWinCreate(2, var_r28, BoardWinPortraitGet()); + BoardWinWait(); + BoardWinKill(); + if (var_r26 != 0) { + BoardConfettiStop(); + } + if (var_r31 == 3) { + ExecLose(temp_r30); + } +} + +static void ExecLose(s32 arg0) { + s32 temp_r30; + + temp_r30 = GWPlayer[arg0].character; + loseMot = BoardPlayerMotionCreate(arg0, loseMotTbl[temp_r30]); + BoardPlayerMotionShiftSet(arg0, loseMot, 0.0f, 10.0f, 0); + HuPrcSleep(10); + while (!BoardPlayerMotionEndCheck(arg0)) { + HuPrcVSleep(); + } +} + +static void CreateLotteryWin(s32 arg0) { + float sp8[2]; + float temp_f30; + float var_f31; + s32 var_r31; + + temp_f30 = -10000.0f; + if (arg0 == 0) { + var_r31 = 0x60050; + var_f31 = 352.0f; + } else if (arg0 == 1) { + var_f31 = 352.0f; + var_r31 = 0x60051; + } else { + var_f31 = 364.0f; + var_r31 = 0x200016; + } + HuWinMesMaxSizeGet(1, sp8, var_r31); + lotteryInstWin = HuWinCreate(temp_f30, var_f31, sp8[0], sp8[1], 0); + HuWinBGTPLvlSet(lotteryInstWin, 0.0f); + HuWinMesSpeedSet(lotteryInstWin, 0); + HuWinMesSet(lotteryInstWin, var_r31); +} + +static void KillLotteryWin(void) { + if (lotteryInstWin != -1) { + HuWinKill(lotteryInstWin); + lotteryInstWin = -1; + } +} + +void BoardLotteryTutorialExec(void) { + Vec sp38; + Vec sp2C; + Vec sp20; + Vec sp14; + Vec sp8; + s16 temp_r29; + s16 temp_r28; + s16 temp_r31; + s32 temp_r30; + + temp_r30 = BoardDataDirReadAsync(0x50000); + temp_r31 = BoardSpaceFlagSearch(0, 0x10000000); + if (temp_r30 != -1) { + BoardDataAsyncWait(temp_r30); + } + BoardModelMotionStart(BoardLotteryHostGet(), 1, 0x40000001); + CreateModel(); + temp_r29 = BoardSpaceLinkFlagSearch(0, temp_r31, 0x02000000); + BoardSpacePosGet(0, temp_r31, &sp38); + BoardSpacePosGet(0, temp_r29, &sp2C); + PSVECSubtract(&sp2C, &sp38, &sp20); + PSVECNormalize(&sp20, &sp20); + temp_r28 = 180.0 * (atan2(-sp20.x, -sp20.z) / M_PI); + sp14.x = -3.0f; + sp14.y = temp_r28; + sp14.z = 0.0f; + sp8.x = 0.0f; + sp8.y = 200.0f; + sp8.z = 0.0f; + BoardCameraMotionStartEx(lotteryMdl[0], &sp14, &sp8, 1300.0f, -1.0f, 0x15); + HuAudFXPlay(0x331); + HuAudFXPlay(0x344); + BoardModelMotionStart(lotteryMdl[0], 0, 0); + while (!BoardModelMotionEndCheck(lotteryMdl[0])) { + HuPrcVSleep(); + } + BoardModelMotionShiftSet(BoardLotteryHostGet(), lotteryMot[3], 0.0f, 10.0f, 0); + HuPrcSleep(10); + while (!BoardModelMotionEndCheck(BoardShopHostGet())) { + HuPrcVSleep(); + } + BoardModelMotionShiftSet(BoardLotteryHostGet(), lotteryMot[0], 0.0f, 10.0f, 0x40000001); + BoardTutorialHookExec(0x1C, 0); + BoardModelMotionShiftSet(BoardLotteryHostGet(), lotteryMot[2], 0.0f, 10.0f, 0x40000001); + HuPrcSleep(30); + BoardModelMotionStart(lotteryMdl[0], 0, 0x40000004); + while (!BoardModelMotionEndCheck(lotteryMdl[0])) { + HuPrcVSleep(); + } + BoardModelMotionSpeedSet(lotteryMdl[0], 0.0f); + BoardModelAttrReset(lotteryMdl[0], 0x40000004); + HuAudFXPlay(0x32F); + KillModel(); +} diff --git a/src/game/board/main.c b/src/game/board/main.c index 900c5738..41990f14 100644 --- a/src/game/board/main.c +++ b/src/game/board/main.c @@ -8,7 +8,9 @@ #include "string.h" #include "game/hsfman.h" #include "game/hsfdraw.h" +#include "game/board/lottery.h" #include "game/board/main.h" +#include "game/board/model.h" #include "game/board/pause.h" #include "game/board/player.h" #include "game/board/tutorial.h" @@ -58,7 +60,6 @@ static CameraView camViewTbl[] = { }; -extern void BoardModelPosGet(s16 model, Vec *pos); extern s32 BoardSpacePosGet(s32 layer, s32 space, Vec *pos); extern void BoardMGSetupPlayClear(void); diff --git a/src/game/board/player.c b/src/game/board/player.c index 49e45eed..b8235a3c 100644 --- a/src/game/board/player.c +++ b/src/game/board/player.c @@ -7,37 +7,10 @@ #include "game/board/tutorial.h" #include "game/board/ui.h" #include "game/board/view.h" +#include "game/board/model.h" +#include "game/pad.h" -//// #include "game/board/model.h" -extern s16 BoardModelCreateCharacter(s32, s32, s32*, s32); -extern void BoardModelExistCheck(s16, s32); -extern void BoardModelExistDupe(s16, s32); -extern void BoardModelCameraSet(s16, u16); -extern void BoardItemStatusKill(s32); -extern void BoardModelAmbSet(s16, f32, f32, f32); -extern s32 BoardModelPosGet(s16, Vec*); -extern s32 BoardModelRotGet(s16, Vec*); -extern f32 BoardModelRotYGet(s16); -extern void BoardModelScaleGet(s16, s32*); -extern void BoardModelVoiceEnableSet(s16, s32, s32); -extern s32 BoardModelMotionCreate(s16, s32); -extern void BoardModelMotionKill(s16, s32); -extern s32 BoardModelMotionEndCheck(s16); -extern s32 BoardModelMotionShiftSet(s16, s32, f32, f32, u32); -extern void BoardModelMotionTimeSet(s16, f32); -extern f32 BoardModelMotionTimeGet(s16); -extern f32 BoardModelMotionMaxTimeGet(s16); -extern void BoardModelMotionTimeRangeSet(s16, s32, s32); -extern void BoardModelAttrSet(s16, s32); -extern void BoardModelAttrReset(s16, s32); -//// #include "game/board/overhead.h" -//// #include "game/board/pad.h" -extern s8 HuPadStkX[4]; -extern s8 HuPadStkY[4]; -extern u16 HuPadBtnDown[4]; -extern u8 HuPadDStk[4]; -//// - +//TODO: Give better name typedef struct bitcopy { struct { u8 field00_bit0 : 1; @@ -394,7 +367,7 @@ void BoardPlayerCornerPosSet(s32 arg0) { BoardPlayerPosSetV(arg0, &sp8); } -void BoardPlayerCornerPosGet(s32 arg0, Point3d* arg1) { +void BoardPlayerCornerPosGet(s32 arg0, Vec* arg1) { s32 var_r31; s32 var_r30; s32 var_r29; @@ -496,7 +469,7 @@ void BoardPlayerScaleSet(s32 arg0, f32 arg8, f32 arg9, f32 argA) { BoardModelScaleSet(BoardPlayerModelGet(arg0), arg8, arg9, argA); } -void BoardPlayerScaleGet(s32 arg0, s32 *arg1) { +void BoardPlayerScaleGet(s32 arg0, Vec *arg1) { BoardModelScaleGet(BoardPlayerModelGet(arg0), arg1); } @@ -514,8 +487,8 @@ s32 BoardPlayerMotionCreate(s32 arg0, s32 arg1) { return BoardModelMotionCreate(BoardPlayerModelGet(arg0), arg1); } -void BoardPlayerMotionKill(s32 arg0, s32 arg1) { - BoardModelMotionKill(BoardPlayerModelGet(arg0), arg1); +s32 BoardPlayerMotionKill(s32 arg0, s32 arg1) { + return BoardModelMotionKill(BoardPlayerModelGet(arg0), arg1); } s32 BoardPlayerMotionEndCheck(s32 arg0) { @@ -574,8 +547,8 @@ f32 BoardPlayerMotionMaxTimeGet(s32 arg0) { return BoardModelMotionMaxTimeGet(BoardPlayerModelGet(arg0)); } -void BoardPlayerMotionTimeRangeSet(s32 arg0, f32 arg8, f32 arg9) { - BoardModelMotionTimeRangeSet(BoardPlayerModelGet(arg0), arg8, arg9); +void BoardPlayerMotionStartEndSet(s32 arg0, f32 arg8, f32 arg9) { + BoardModelMotionStartEndSet(BoardPlayerModelGet(arg0), arg8, arg9); } void BoardPlayerModelAttrSet(s32 arg0, s32 arg1) { @@ -878,21 +851,8 @@ void BoardPlayerPostTurnHookExec(s32 arg0) { } void BoardPlayerSizeRestore(s32 arg0) { - PlayerState* temp_r24; - PlayerState* temp_r23; - s32 var_r28; - s32 var_r27; - - temp_r24 = BoardPlayerGet(arg0); - if (temp_r24 != 0) { - var_r28 = temp_r24->size; - } - if (var_r28 != 0) { - temp_r23 = BoardPlayerGet(arg0); - if (temp_r23 != 0) { - var_r27 = temp_r23->size; - } - if (var_r27 == 1) { + if (BoardPlayerSizeGet(arg0) != 0) { + if (BoardPlayerSizeGet(arg0) == 1) { HuAudFXPlay(0x313); } else { HuAudFXPlay(0x311); @@ -916,19 +876,18 @@ void BoardPlayerZoomRestore(s32 arg0) { Vec spC; sp8 = BoardPlayerGet(arg0); - BoardModelPosGet(BoardPlayerModelGet(arg0), &spC); + BoardPlayerPosGet(arg0, &spC); temp_r27 = GWPlayer[arg0].space_curr; var_r31 = GWSystem.player_curr; if (var_r31 == -1) { var_r31 = 0; } - for (var_r28 = 0, var_r29 = var_r28; var_r28 < 4; var_r28++) { + for (var_r29 = var_r28 = 0; var_r28 < 4; var_r28++) { if (var_r31 == arg0) break; if (temp_r27 == GWPlayer[var_r31].space_curr) { var_r29++; } var_r31 = (var_r31 + 1) & 3; - (void)var_r29; // hack } BoardSpaceCornerPosGet(temp_r27, var_r29, &sp18); BoardPlayerMotBlendSet(arg0, 0, 0xF); @@ -978,17 +937,17 @@ static inline GetLinkCount(s32 playerIdx, s32 boardIdx) { || ((boardSpaceFlag->flag & 0x04000000) != 0) || ((boardSpaceFlag->flag & BoardJunctionMaskGet()) != 0)) { - linkCount -= 1; + linkCount--; } } return linkCount; } static void InitJunction(s32 arg0, s32 arg1, f32 arg8) { - Point3d sp68; - Point3d sp5C; - Point3d sp50; - Point3d sp44; + Vec sp68; + Vec sp5C; + Vec sp50; + Vec sp44; f32 sp40; f32 sp3C; s32 sp38; @@ -1015,7 +974,7 @@ static void InitJunction(s32 arg0, s32 arg1, f32 arg8) { if (sp38 > 1) { var_r28 = omAddObjEx(boardObjMan, 0x100, 0, 0, -1, UpdateJunctionGfx); junctionObj = var_r28; - temp_r29 = (bitcopy*) var_r28->work; + temp_r29 = OM_GET_WORK_PTR(var_r28, bitcopy); temp_r29->field00_bit0 = 0; temp_r29->field00_bit7 = 0; temp_r29->field00_bit1 = arg0; @@ -1089,7 +1048,7 @@ static void UpdateJunctionGfx(omObjData* arg0) { s32 var_r28; bitcopy* temp_r30; - temp_r30 = (bitcopy*)arg0->work; + temp_r30 = OM_GET_WORK_PTR(arg0, bitcopy); if ((temp_r30->field00_bit0 != 0) || (BoardIsKill() != 0)) { for (var_r28 = 0; var_r28 < temp_r30->field00_bit3; var_r28++) { BoardModelKill(temp_r30->unk_06[var_r28]); @@ -1119,7 +1078,7 @@ static void StopJunctionPlayer(s32 arg0) { bitcopy* temp_r31; if (junctionObj != 0) { - temp_r31 = (bitcopy*)junctionObj->work; + temp_r31 = OM_GET_WORK_PTR(junctionObj, bitcopy); temp_r31->field00_bit7 = 1; temp_r31->unk_01 = 0; if (arg0 != 0) { @@ -1130,14 +1089,14 @@ static void StopJunctionPlayer(s32 arg0) { } static void RestoreJunction(f32 arg8, s32 arg0) { - Point3d sp1C; + Vec sp1C; f32 spC[4]; s16 var_r30; s16 temp_r29; bitcopy* temp_r31; if (junctionObj != 0) { - temp_r31 = (bitcopy*) junctionObj->work; + temp_r31 = OM_GET_WORK_PTR(junctionObj, bitcopy); if (temp_r31->unk_01 == 0) { arg8 = 90.0f * (((90.0f + arg8) - 1.0f) / 90.0f); @@ -1331,7 +1290,7 @@ static inline f32 JunctionArrowRotGetCurr(void) { if (!junctionObj) { return 0.0f; } else { - juncObj = (bitcopy*) junctionObj->work; + juncObj = OM_GET_WORK_PTR(junctionObj, bitcopy); OSs16tof32(&(junctionArrowRot[juncObj->field00_bit5]), &ret); return ret; } @@ -1345,7 +1304,7 @@ static inline s32 CheckArrowRot(float value) if (!junctionObj) { return 0; } else { - sp5C = (bitcopy*) junctionObj->work; + sp5C = OM_GET_WORK_PTR(junctionObj, bitcopy); OSf32tos16(&value, &spE); if (spE > 0x15E) { spE = 0; @@ -1614,6 +1573,7 @@ void BoardPlayerPosLerpStart(s32 arg0, Vec* arg1, Vec* arg2, s16 arg3) { if (GWPlayer[arg0].bowser_suit != 0) { BoardModelPosSetV(suitMdl, arg1); } + //TODO: Make work struct for this temp_r3->work[0] = arg0; *(f32 *)(&temp_r3->work[1]) = var_f27; temp_r3->work[2] = arg3; @@ -1651,6 +1611,7 @@ static void PlayerPosLerpFunc(omObjData* arg0) { BoardPlayerPosSet(temp_r30, temp_f31, temp_f30, temp_f29); } +//TODO: Make this 2 structs and give better names typedef struct bitcopy2 { struct { u8 field00_bit0 : 1; @@ -1680,7 +1641,7 @@ typedef struct bitcopy2 { } bitcopy2; void BoardPlayerDiceJumpStart(s32 arg0) { - Point3d sp8; + Vec sp8; PlayerState* temp_r25; bitcopy2* temp_r31; s32 var_r28; @@ -1697,7 +1658,7 @@ void BoardPlayerDiceJumpStart(s32 arg0) { } diceJumpObj[arg0] = omAddObjEx(boardObjMan, 0x100, 0, 0, -1, DiceJumpFunc); BoardModelPosGet(BoardPlayerModelGet(arg0), &sp8); - temp_r31 = (bitcopy2*) diceJumpObj[arg0]->work; + temp_r31 = OM_GET_WORK_PTR(diceJumpObj[arg0], bitcopy2); temp_r31->field00_bit0 = 0; temp_r31->field00_bit1 = arg0; temp_r31->unk_04 = 0; @@ -1711,7 +1672,7 @@ s32 BoardPlayerDiceJumpCheck(s32 arg0) { if (!diceJumpObj[arg0]) { return 0; } - if (diceJumpObj[arg0]->work[1] == 0) { + if (OM_GET_WORK_PTR(diceJumpObj[arg0], bitcopy2)->unk_04 == 0) { return 0; } return 1; @@ -1726,7 +1687,7 @@ static void DiceJumpFunc(omObjData* arg0) { s32 var_r23; s32 var_r17; - temp_r31 = (bitcopy2*) arg0->work; + temp_r31 = OM_GET_WORK_PTR(arg0, bitcopy2); if ((temp_r31->field00_bit0 != 0) || (BoardIsKill() != 0)) { GWPlayer[temp_r31->field00_bit1].field08_bit3 = 0; BoardRotateDiceNumbers(temp_r31->field00_bit1); @@ -1806,7 +1767,7 @@ void BoardPlayerMotBlendSet(s32 arg0, s16 arg1, s16 arg2) { var_r20 = 0; if (motDoneF[arg0] != 0) { temp_r3 = motDoneF[arg0]; - temp_r26 = (bitcopy2*) temp_r3->work; + temp_r26 = OM_GET_WORK_PTR(temp_r3, bitcopy2); temp_r26->field00_bit0 = 1; for (var_r19 = 0; var_r19 < 0xB4U; var_r19++) { @@ -1818,7 +1779,7 @@ void BoardPlayerMotBlendSet(s32 arg0, s16 arg1, s16 arg2) { if (arg2 > 0) { var_r18 = GWPlayer[arg0].character; temp_r3 = omAddObjEx(boardObjMan, 0x100, 0, 0, -1, &BoardPlayerMotBlendExec); - temp_r26 = (bitcopy2*) temp_r3->work; + temp_r26 = OM_GET_WORK_PTR(temp_r3, bitcopy2); temp_r26->field00_bit0 = 0; temp_r26->unk_02 = arg2; temp_r26->unk_01 = arg0; @@ -1873,7 +1834,7 @@ void BoardPlayerMotBlendExec(omObjData* arg0) { f32 var_f27; bitcopy2* temp_r30; - temp_r30 = (bitcopy2*) arg0->work; + temp_r30 = OM_GET_WORK_PTR(arg0, bitcopy2); if ((temp_r30->field00_bit0 != 0) || (BoardIsKill() != 0)) { if (temp_r30->unk_04h > 0) { BoardPlayerMotionKill(temp_r30->unk_01, temp_r30->unk_04h); @@ -1907,6 +1868,8 @@ s32 BoardPlayerMotBlendCheck(s32 arg0) { return 1; } +//TODO: Make this 3 structs and give better names + typedef struct bitcopy3 { struct { u8 field00_bit0 : 1; @@ -1929,7 +1892,7 @@ void BoardDiceDigit2DInit(s32 arg0, s32 arg1) { bitcopy3* temp_r31; temp_r3 = omAddObjEx(boardObjMan, 0x105, 0, 0, -1, &UpdateDiceDigit2D); - temp_r31 = (bitcopy3*) temp_r3->work; + temp_r31 = OM_GET_WORK_PTR(temp_r3, bitcopy3);; temp_r31->field00_bit0 = 0; temp_r31->field00_bit1 = 1; temp_r31->unk_01 = 0; @@ -1954,7 +1917,7 @@ void BoardDiceDigit2DUpdateEnable(s32 arg0) { bitcopy3* temp_r31; if (diceDigit2DObj != 0) { - temp_r31 = (bitcopy3*) diceDigit2DObj->work; + temp_r31 = OM_GET_WORK_PTR(diceDigit2DObj, bitcopy3); temp_r31->field00_bit0 = 1; } } @@ -1964,7 +1927,7 @@ void BoardDiceDigit2DShowSet(s32 arg0) { bitcopy3* temp_r31; if (diceDigit2DObj != 0) { - temp_r31 = (bitcopy3*) diceDigit2DObj->work; + temp_r31 = OM_GET_WORK_PTR(diceDigit2DObj, bitcopy3); for (var_r30 = 0; var_r30 < 2; var_r30++) { if (arg0 != 0) { @@ -1984,14 +1947,14 @@ void BoardDiceDigit2DShowSet(s32 arg0) { } static void UpdateDiceDigitSprite(omObjData* arg0) { - f32 sp1C[2]; + Vec sp1C; s32 sp14[2]; f32 spC[2] = { 320.0f, 256.0f }; s32 var_r30; s32 temp_r29; bitcopy3* temp_r31; - temp_r31 = (bitcopy3*) arg0->work; + temp_r31 = OM_GET_WORK_PTR(arg0, bitcopy3); temp_r29 = GWPlayer[temp_r31->unk_02].roll; if (temp_r29 != 0) { sp14[0] = temp_r29 % 10; @@ -2005,14 +1968,14 @@ static void UpdateDiceDigitSprite(omObjData* arg0) { HuSprAttrSet(temp_r31->unk_04, var_r30, 4); } else { if ((sp14[1] == 0) && (var_r30 == 0)) { - sp1C[0] = 288.0f; + sp1C.x = 288.0f; } else { - sp1C[0] = spC[var_r30]; + sp1C.x = spC[var_r30]; } - sp1C[1] = 176.0f; + sp1C.y = 176.0f; HuSprAttrReset(temp_r31->unk_04, var_r30, 4); HuSprBankSet(temp_r31->unk_04, var_r30, sp14[var_r30]); - HuSprPosSet(temp_r31->unk_04, var_r30, sp1C[0], sp1C[1]); + HuSprPosSet(temp_r31->unk_04, var_r30, sp1C.x, sp1C.y); } } } @@ -2021,7 +1984,7 @@ static void UpdateDiceDigit2D(omObjData* arg0) { f32 var_f30; bitcopy3* temp_r30; - temp_r30 = (bitcopy3*) diceDigit2DObj->work; + temp_r30 = OM_GET_WORK_PTR(diceDigit2DObj, bitcopy3); if ((temp_r30->field00_bit0 != 0) || (BoardIsKill() != 0)) { if (temp_r30->unk_04 != -1) { HuSprGrpKill(temp_r30->unk_04); @@ -2043,40 +2006,7 @@ static void UpdateDiceDigit2D(omObjData* arg0) { var_f30 -= 90.0f; } } - - { // hack until the compiler does what we want - f32 sp1C[2]; - f32 spC[2] = { 320.0f, 256.0f }; - s32 sp14[2]; - s32 var_r30; - s32 temp_r29; - bitcopy3* temp_r31; - - temp_r31 = (bitcopy3*) arg0->work; - temp_r29 = GWPlayer[temp_r31->unk_02].roll; - if (temp_r29 != 0) { - sp14[0] = temp_r29 % 10; - sp14[1] = temp_r29 / 10; - } else { - temp_r31->field00_bit0 = 1; - } - - for (var_r30 = 0; var_r30 < 2; var_r30++) { - if (((var_r30 == 1) && (sp14[1] == 0)) || (temp_r31->field00_bit1 == 0)) { - HuSprAttrSet(temp_r31->unk_04, var_r30, 4); - } else { - if ((sp14[1] == 0) && (var_r30 == 0)) { - sp1C[0] = 288.0f; - } else { - sp1C[0] = spC[var_r30]; - } - sp1C[1] = 176.0f; - HuSprAttrReset(temp_r31->unk_04, var_r30, 4); - HuSprBankSet(temp_r31->unk_04, var_r30, sp14[var_r30]); - HuSprPosSet(temp_r31->unk_04, var_r30, sp1C[0], sp1C[1]); - } - } - } + UpdateDiceDigitSprite(arg0); } void BoardPlayerBtnDownWait(s32 arg0, u32 arg1) { @@ -2122,9 +2052,9 @@ u32 BoardPlayerMoveAwayIsDone(void) { void BoardPlayerMoveAwayStart(s32 arg0, s32 arg1, s32 arg2) { bitcopy3* temp_r25; - Point3d sp28; - Point3d sp1C; - Point3d sp10; + Vec sp28; + Vec sp1C; + Vec sp10; s32 temp_r29; s32 var_r30; s32 var_r31; @@ -2160,7 +2090,7 @@ void BoardPlayerMoveAwayStart(s32 arg0, s32 arg1, s32 arg2) { } if (arg2 == 0) { moveAwayObj = omAddObjEx(boardObjMan, 0x100, 0U, 0U, -1, &MoveAwayObjFunc); - temp_r25 = (bitcopy3*) moveAwayObj->work; + temp_r25 = OM_GET_WORK_PTR(moveAwayObj, bitcopy3); temp_r25->field00_bit0 = 0; } } @@ -2173,9 +2103,9 @@ static void MoveAwayObjFunc(omObjData* arg0) { s32 var_r31; bitcopy3* temp_r30; - temp_r30 = (bitcopy3*) arg0->work; + temp_r30 = OM_GET_WORK_PTR(arg0, bitcopy3); if ((temp_r30->field00_bit0 != 0) || (BoardIsKill() != 0)) { - moveAwayObj = 0; + moveAwayObj = NULL; omDelObjEx(HuPrcCurrentGet(), arg0); return; } @@ -2209,19 +2139,19 @@ void BoardBowserSuitInit(s32 arg0) { GWPlayer[arg0].bowser_suit = 1; temp_r3 = omAddObjEx(boardObjMan, 0x100, 0U, 0U, -1, &UpdateBowserSuit); bowserSuitObj = temp_r3; - temp_r31 = (bitcopy3 *) temp_r3->work; + temp_r31 = OM_GET_WORK_PTR(temp_r3, bitcopy3); temp_r31->field00_bit0 = 0; temp_r31->unk_01 = arg0; temp_r31->unk_02 = 0; - BoardModelVoiceEnableSet(BoardPlayerModelGet(arg0), 3, 0); - BoardModelVoiceEnableSet(BoardPlayerModelGet(arg0), 4, 0); + BoardPlayerVoiceEnableSet(arg0, 3, 0); + BoardPlayerVoiceEnableSet(arg0, 4, 0); } void BoardBowserSuitKill(s32 arg0) { bitcopy3* temp; if (bowserSuitObj != 0) { - ((bitcopy3*) bowserSuitObj->work)->field00_bit0 = 1; + OM_GET_WORK_PTR(bowserSuitObj, bitcopy3)->field00_bit0 = 1; } GWPlayer[arg0].bowser_suit = 0; BoardModelVoiceEnableSet(BoardPlayerModelGet(arg0), 3, 1); @@ -2290,7 +2220,7 @@ void UpdateBowserSuit(omObjData* arg0) { s16 temp_r30; bitcopy3* temp_r31; - temp_r31 = (bitcopy3*) arg0->work; + temp_r31 = OM_GET_WORK_PTR(arg0, bitcopy3); if ((temp_r31->field00_bit0 != 0) || (BoardIsKill() != 0)) { bowserSuitObj = NULL; omDelObjEx(HuPrcCurrentGet(), arg0); diff --git a/src/game/board/space.c b/src/game/board/space.c index e117bf18..cd504e5f 100644 --- a/src/game/board/space.c +++ b/src/game/board/space.c @@ -1,6 +1,8 @@ #include "game/gamework_data.h" #include "game/flag.h" +#include "game/board/lottery.h" #include "game/board/main.h" +#include "game/board/model.h" #include "game/board/player.h" #include "game/board/space.h" #include "game/board/star.h" @@ -14,9 +16,6 @@ #include "string.h" -extern s16 BoardModelCreate(s32 file, s32 *data, s32 arg3); -extern s16 BoardModelIDGet(s16 model); - static BoardSpace spaceData[2][256]; s16 boardSpaceStarTbl[8]; static GXTexObj spaceHiliteTex; @@ -637,7 +636,7 @@ s32 BoardSpaceWalkExec(s32 player, s32 space) return 1; } if(space_ptr->flag & 0x600000) { - u16 mg_param = GWSystem.unk_38; + s32 mg_param = GWSystem.unk_38; if(BoardPlayerSizeGet(player) == 1) { BoardRotateDiceNumbers(player); BoardMGCreate(mg_param); @@ -756,6 +755,32 @@ void BoardSpaceHide(s32 value) } } +static inline void InitGXSpace() +{ + GXColor color = {0xFF, 0xFF, 0xFF, 0xFF}; + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GXInvalidateTexAll(); + GXLoadTexObj(&spaceTex, GX_TEXMAP0); + GXSetNumTexGens(1); + GXSetNumTevStages(1); + GXSetTevColor(GX_TEVREG0, color); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); + GXSetNumChans(1); + GXSetChanAmbColor(GX_COLOR0A0, color); + GXSetChanMatColor(GX_COLOR0A0, color); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 1, GX_DF_CLAMP, GX_AF_SPOT); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); + GXSetAlphaCompare(GX_GEQUAL, 1, GX_AOP_AND, GX_GEQUAL, 1); + GXSetCullMode(GX_CULL_BACK); +} + //Some stack allocation issues. code around BoardPlayerGetCurr is incorrect too static void DrawSpaces(ModelData *model, Mtx matrix) { @@ -781,41 +806,19 @@ static void DrawSpaces(ModelData *model, Mtx matrix) GXSetViewport(camera->viewport_x, camera->viewport_y, camera->viewport_w, camera->viewport_h, camera->viewport_near, camera->viewport_far); GXSetScissor(camera->viewport_x, camera->viewport_y, camera->viewport_w, camera->viewport_h); { - GXColor color = { 0xFF, 0xFF, 0xFF, 0xFF }; BoardSpace *space_curr; BoardSpace *space_hilite; PlayerState *player; - PlayerState *player_temp; s16 player_mdl; float y_dist; s32 space_img; u16 space_type; float uv_x, uv_y, uv_size; + InitGXSpace(); - GXClearVtxDesc(); - GXSetVtxDesc(GX_VA_POS, GX_DIRECT); - GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); - GXInvalidateTexAll(); - GXLoadTexObj(&spaceTex, GX_TEXMAP0); - GXSetNumTexGens(1); - GXSetNumTevStages(1); - GXSetTevColor(GX_TEVREG0, color); - GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); - GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); - GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); - GXSetNumChans(1); - GXSetChanAmbColor(GX_COLOR0A0, color); - GXSetChanMatColor(GX_COLOR0A0, color); - GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); - GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_REG, 1, GX_DF_CLAMP, GX_AF_SPOT); - GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); - GXSetAlphaCompare(GX_GEQUAL, 1, GX_AOP_AND, GX_GEQUAL, 1); - GXSetCullMode(GX_CULL_BACK); - player = player_temp = BoardPlayerGetCurr(); + player = BoardPlayerGet(GWSystem.player_curr); BoardPlayerPosGet(GWSystem.player_curr, &player_pos); - player_mdl = BoardModelIDGet(BoardPlayerModelGetCurr()); + player_mdl = BoardModelIDGet(BoardPlayerModelGet(GWSystem.player_curr)); space_curr = &spaceData[0][0]; space_hilite = NULL; GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); @@ -834,7 +837,7 @@ static void DrawSpaces(ModelData *model, Mtx matrix) if(player_pos.y-space_curr->pos.y < 0.0f) { y_dist = -(player_pos.y-space_curr->pos.y); } else { - y_dist = player_pos.y-space_curr->pos.y; + y_dist = player_pos.y-space_curr->pos.y; } if(y_dist < 10.0f) { space_hilite = space_curr; diff --git a/src/game/board/star.c b/src/game/board/star.c index 59815c40..c761b559 100755 --- a/src/game/board/star.c +++ b/src/game/board/star.c @@ -157,7 +157,7 @@ s16 BoardStarHostMdlGet(void) { return hostMdl; } -void BoardStarExec(s32 arg0, BoardSpace *arg1) { +void BoardStarExec(s32 arg0, s32 arg1) { if (GWBoardGet() == 7 || GWBoardGet() == 8) { return; } @@ -717,8 +717,8 @@ void BoardStarShowNext(s32 arg0) { Hu3D2Dto3D(&sp44, 1, &sp44); BoardModelPosSetV(BoardStarHostMdlGet(), &sp44); BoardCameraRotGet(&sp2C); - PSMTXRotRad(sp5C, 'y', 0.17453292f); - PSMTXRotRad(sp8C, 'x', 0.017453292f * sp2C.x); + PSMTXRotRad(sp5C, 'y', MTXDegToRad(10.0f)); + PSMTXRotRad(sp8C, 'x', MTXDegToRad(sp2C.x)); PSMTXConcat(sp8C, sp5C, spBC); BoardModelMtxSet(BoardStarHostMdlGet(), &spBC); BoardModelRotSet(BoardStarHostMdlGet(), 0.0f, 0.0f, 0.0f); diff --git a/src/game/board/view.c b/src/game/board/view.c index 46dc6f6d..1d11d83c 100755 --- a/src/game/board/view.c +++ b/src/game/board/view.c @@ -578,8 +578,8 @@ static void UpdateOverheadView(omObjData *arg0) { sp20.y = var_r29[1]; sp20.z = 1000.0f; BoardCameraRotGet(&sp8); - PSMTXRotRad(sp5C, 0x78, sp8.x * 0.017453292f); - PSMTXRotRad(sp2C, 0x79, sp8.y * 0.017453292f); + PSMTXRotRad(sp5C, 'x', MTXDegToRad(sp8.x)); + PSMTXRotRad(sp2C, 'y', MTXDegToRad(sp8.y)); PSMTXConcat(sp2C, sp5C, sp2C); BoardModelMtxSet(temp_r31->unk04, &sp2C); Hu3D2Dto3D(&sp20, 1, &sp20); diff --git a/src/game/board/warp.c b/src/game/board/warp.c index e623e207..f5b45068 100644 --- a/src/game/board/warp.c +++ b/src/game/board/warp.c @@ -1,5 +1,6 @@ #include "game/board/warp.h" #include "game/board/main.h" +#include "game/board/model.h" #include "game/board/player.h" #include "game/board/tutorial.h" #include "game/wipe.h" @@ -21,10 +22,6 @@ extern void BoardCharWheelInit(s32, s32); extern void BoardCharWheelSpeedSet(f32); extern void BoardCharWheelWait(void); extern s32 BoardCharWheelResultGet(void); -extern f32 BoardModelMotionTimeGet(s16); -extern void BoardModelHookReset(s16); -extern s32 BoardModelHookSet(s16, char*, s16); -extern s32 BoardModelMotionEndCheck(s16); static Vec warpPos; diff --git a/tools/decompctx.py b/tools/decompctx.py index c42b1828..e86d5ef3 100644 --- a/tools/decompctx.py +++ b/tools/decompctx.py @@ -13,60 +13,74 @@ import argparse import os import re +from typing import List script_dir = os.path.dirname(os.path.realpath(__file__)) root_dir = os.path.abspath(os.path.join(script_dir, "..")) src_dir = os.path.join(root_dir, "src") -include_dir = os.path.join(root_dir, "include") +include_dirs = [ + os.path.join(root_dir, "include"), + # Add additional include directories here +] include_pattern = re.compile(r'^#include\s*[<"](.+?)[>"]$') -guard_pattern = re.compile(r'^#ifndef\s+(.*)$') +guard_pattern = re.compile(r"^#ifndef\s+(.*)$") defines = set() -def import_h_file(in_file: str, r_path: str) -> str: - rel_path = os.path.join(root_dir, r_path, in_file) - inc_path = os.path.join(include_dir, in_file) - if os.path.exists(rel_path): - return import_c_file(rel_path) - elif os.path.exists(inc_path): - return import_c_file(inc_path) - else: - print("Failed to locate", in_file) - exit(1) -def import_c_file(in_file) -> str: +def import_h_file(in_file: str, r_path: str, deps: List[str]) -> str: + rel_path = os.path.join(root_dir, r_path, in_file) + if os.path.exists(rel_path): + return import_c_file(rel_path, deps) + for include_dir in include_dirs: + inc_path = os.path.join(include_dir, in_file) + if os.path.exists(inc_path): + return import_c_file(inc_path, deps) + else: + print("Failed to locate", in_file) + return "" + + +def import_c_file(in_file: str, deps: List[str]) -> str: in_file = os.path.relpath(in_file, root_dir) - out_text = '' + deps.append(in_file) + out_text = "" try: - with open(in_file, encoding="utf-8") as file: - out_text += process_file(in_file, list(file)) + with open(in_file, encoding="utf-8") as file: + out_text += process_file(in_file, list(file), deps) except Exception: - with open(in_file) as file: - out_text += process_file(in_file, list(file)) + with open(in_file) as file: + out_text += process_file(in_file, list(file), deps) return out_text -def process_file(in_file: str, lines) -> str: - out_text = '' + +def process_file(in_file: str, lines: List[str], deps: List[str]) -> str: + out_text = "" for idx, line in enumerate(lines): - guard_match = guard_pattern.match(line.strip()) - if idx == 0: - if guard_match: - if guard_match[1] in defines: - break - defines.add(guard_match[1]) - print("Processing file", in_file) - include_match = include_pattern.match(line.strip()) - if include_match and not include_match[1].endswith(".s"): - out_text += f"/* \"{in_file}\" line {idx} \"{include_match[1]}\" */\n" - out_text += import_h_file(include_match[1], os.path.dirname(in_file)) - out_text += f"/* end \"{include_match[1]}\" */\n" - else: - out_text += line + guard_match = guard_pattern.match(line.strip()) + if idx == 0: + if guard_match: + if guard_match[1] in defines: + break + defines.add(guard_match[1]) + print("Processing file", in_file) + include_match = include_pattern.match(line.strip()) + if include_match and not include_match[1].endswith(".s"): + out_text += f'/* "{in_file}" line {idx} "{include_match[1]}" */\n' + out_text += import_h_file(include_match[1], os.path.dirname(in_file), deps) + out_text += f'/* end "{include_match[1]}" */\n' + else: + out_text += line return out_text + +def sanitize_path(path: str) -> str: + return path.replace("\\", "/").replace(" ", "\\ ") + + def main(): parser = argparse.ArgumentParser( description="""Create a context file which can be used for decomp.me""" @@ -75,13 +89,32 @@ def main(): "c_file", help="""File from which to create context""", ) + parser.add_argument( + "-o", + "--output", + help="""Output file""", + default="ctx.c", + ) + parser.add_argument( + "-d", + "--depfile", + help="""Dependency file""", + ) args = parser.parse_args() - output = import_c_file(args.c_file) + deps = [] + output = import_c_file(args.c_file, deps) - with open(os.path.join(root_dir, "ctx.c"), "w", encoding="utf-8") as f: + with open(os.path.join(root_dir, args.output), "w", encoding="utf-8") as f: f.write(output) + if args.depfile: + with open(os.path.join(root_dir, args.depfile), "w", encoding="utf-8") as f: + f.write(sanitize_path(args.output) + ":") + for dep in deps: + path = sanitize_path(dep) + f.write(f" \\\n\t{path}") + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/tools/download_tool.py b/tools/download_tool.py index 681c65b5..7b386a4b 100644 --- a/tools/download_tool.py +++ b/tools/download_tool.py @@ -16,14 +16,31 @@ import os import platform import shutil import stat -import sys import urllib.request import zipfile - +from typing import Callable, Dict from pathlib import Path -def dtk_url(tag): +def binutils_url(tag): + uname = platform.uname() + system = uname.system.lower() + arch = uname.machine.lower() + if system == "darwin": + system = "macos" + arch = "universal" + elif arch == "amd64": + arch = "x86_64" + + repo = "https://github.com/encounter/gc-wii-binutils" + return f"{repo}/releases/download/{tag}/{system}-{arch}.zip" + + +def compilers_url(tag: str) -> str: + return f"https://files.decomp.dev/compilers_{tag}.zip" + + +def dtk_url(tag: str) -> str: uname = platform.uname() suffix = "" system = uname.system.lower() @@ -39,28 +56,26 @@ def dtk_url(tag): return f"{repo}/releases/download/{tag}/dtk-{system}-{arch}{suffix}" -def sjiswrap_url(tag): +def sjiswrap_url(tag: str) -> str: repo = "https://github.com/encounter/sjiswrap" return f"{repo}/releases/download/{tag}/sjiswrap-windows-x86.exe" -def wibo_url(tag): +def wibo_url(tag: str) -> str: repo = "https://github.com/decompals/wibo" return f"{repo}/releases/download/{tag}/wibo" -def compilers_url(tag): - return f"https://files.decomp.dev/compilers_{tag}.zip" - -TOOLS = { +TOOLS: Dict[str, Callable[[str], str]] = { + "binutils": binutils_url, + "compilers": compilers_url, "dtk": dtk_url, "sjiswrap": sjiswrap_url, "wibo": wibo_url, - "compilers": compilers_url, } -def main(): +def main() -> None: parser = argparse.ArgumentParser() parser.add_argument("tool", help="Tool name") parser.add_argument("output", type=Path, help="output file path") @@ -77,7 +92,11 @@ def main(): data = io.BytesIO(response.read()) with zipfile.ZipFile(data) as f: f.extractall(output) - output.touch(mode=0o755) + # Make all files executable + for root, _, files in os.walk(output): + for name in files: + os.chmod(os.path.join(root, name), 0o755) + output.touch(mode=0o755) # Update dir modtime else: with open(output, "wb") as f: shutil.copyfileobj(response, f) @@ -86,4 +105,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/tools/ninja_syntax.py b/tools/ninja_syntax.py index ffd88a01..7306ee1d 100644 --- a/tools/ninja_syntax.py +++ b/tools/ninja_syntax.py @@ -21,50 +21,67 @@ use Python. import re import textwrap +import os +from io import StringIO +from pathlib import Path +from typing import Dict, List, Match, Optional, Tuple, Union + +NinjaPath = Union[str, Path] +NinjaPaths = Union[ + List[str], + List[Path], + List[NinjaPath], + List[Optional[str]], + List[Optional[Path]], + List[Optional[NinjaPath]], +] +NinjaPathOrPaths = Union[NinjaPath, NinjaPaths] -def escape_path(word): +def escape_path(word: str) -> str: return word.replace("$ ", "$$ ").replace(" ", "$ ").replace(":", "$:") class Writer(object): - def __init__(self, output, width=78): + def __init__(self, output: StringIO, width: int = 78) -> None: self.output = output self.width = width - def newline(self): + def newline(self) -> None: self.output.write("\n") - def comment(self, text): + def comment(self, text: str) -> None: for line in textwrap.wrap( text, self.width - 2, break_long_words=False, break_on_hyphens=False ): self.output.write("# " + line + "\n") - def variable(self, key, value, indent=0): - if value is None: - return - if isinstance(value, list): - value = " ".join(filter(None, value)) # Filter out empty strings. + def variable( + self, + key: str, + value: Optional[NinjaPathOrPaths], + indent: int = 0, + ) -> None: + value = " ".join(serialize_paths(value)) self._line("%s = %s" % (key, value), indent) - def pool(self, name, depth): + def pool(self, name: str, depth: int) -> None: self._line("pool %s" % name) - self.variable("depth", depth, indent=1) + self.variable("depth", str(depth), indent=1) def rule( self, - name, - command, - description=None, - depfile=None, - generator=False, - pool=None, - restat=False, - rspfile=None, - rspfile_content=None, - deps=None, - ): + name: str, + command: str, + description: Optional[str] = None, + depfile: Optional[NinjaPath] = None, + generator: bool = False, + pool: Optional[str] = None, + restat: bool = False, + rspfile: Optional[NinjaPath] = None, + rspfile_content: Optional[NinjaPath] = None, + deps: Optional[NinjaPathOrPaths] = None, + ) -> None: self._line("rule %s" % name) self.variable("command", command, indent=1) if description: @@ -86,32 +103,39 @@ class Writer(object): def build( self, - outputs, - rule, - inputs=None, - implicit=None, - order_only=None, - variables=None, - implicit_outputs=None, - pool=None, - dyndep=None, - ): - outputs = as_list(outputs) + outputs: NinjaPathOrPaths, + rule: str, + inputs: Optional[NinjaPathOrPaths] = None, + implicit: Optional[NinjaPathOrPaths] = None, + order_only: Optional[NinjaPathOrPaths] = None, + variables: Optional[ + Union[ + List[Tuple[str, Optional[NinjaPathOrPaths]]], + Dict[str, Optional[NinjaPathOrPaths]], + ] + ] = None, + implicit_outputs: Optional[NinjaPathOrPaths] = None, + pool: Optional[str] = None, + dyndep: Optional[NinjaPath] = None, + ) -> List[str]: + outputs = serialize_paths(outputs) out_outputs = [escape_path(x) for x in outputs] - all_inputs = [escape_path(x) for x in as_list(inputs)] + all_inputs = [escape_path(x) for x in serialize_paths(inputs)] if implicit: - implicit = [escape_path(x) for x in as_list(implicit)] + implicit = [escape_path(x) for x in serialize_paths(implicit)] all_inputs.append("|") - all_inputs.extend(implicit) + all_inputs.extend(map(str, implicit)) if order_only: - order_only = [escape_path(x) for x in as_list(order_only)] + order_only = [escape_path(x) for x in serialize_paths(order_only)] all_inputs.append("||") - all_inputs.extend(order_only) + all_inputs.extend(map(str, order_only)) if implicit_outputs: - implicit_outputs = [escape_path(x) for x in as_list(implicit_outputs)] + implicit_outputs = [ + escape_path(x) for x in serialize_paths(implicit_outputs) + ] out_outputs.append("|") - out_outputs.extend(implicit_outputs) + out_outputs.extend(map(str, implicit_outputs)) self._line( "build %s: %s" % (" ".join(out_outputs), " ".join([rule] + all_inputs)) @@ -119,7 +143,7 @@ class Writer(object): if pool is not None: self._line(" pool = %s" % pool) if dyndep is not None: - self._line(" dyndep = %s" % dyndep) + self._line(" dyndep = %s" % serialize_path(dyndep)) if variables: if isinstance(variables, dict): @@ -132,16 +156,16 @@ class Writer(object): return outputs - def include(self, path): + def include(self, path: str) -> None: self._line("include %s" % path) - def subninja(self, path): + def subninja(self, path: str) -> None: self._line("subninja %s" % path) - def default(self, paths): - self._line("default %s" % " ".join(as_list(paths))) + def default(self, paths: NinjaPathOrPaths) -> None: + self._line("default %s" % " ".join(serialize_paths(paths))) - def _count_dollars_before_index(self, s, i): + def _count_dollars_before_index(self, s: str, i: int) -> int: """Returns the number of '$' characters right in front of s[i].""" dollar_count = 0 dollar_index = i - 1 @@ -150,7 +174,7 @@ class Writer(object): dollar_index -= 1 return dollar_count - def _line(self, text, indent=0): + def _line(self, text: str, indent: int = 0) -> None: """Write 'text' word-wrapped at self.width characters.""" leading_space = " " * indent while len(leading_space) + len(text) > self.width: @@ -187,19 +211,26 @@ class Writer(object): self.output.write(leading_space + text + "\n") - def close(self): + def close(self) -> None: self.output.close() -def as_list(input): - if input is None: - return [] +def serialize_path(input: Optional[NinjaPath]) -> str: + if not input: + return "" + if isinstance(input, Path): + return str(input).replace("/", os.sep) + else: + return str(input) + + +def serialize_paths(input: Optional[NinjaPathOrPaths]) -> List[str]: if isinstance(input, list): - return input - return [input] + return [serialize_path(path) for path in input if path] + return [serialize_path(input)] if input else [] -def escape(string): +def escape(string: str) -> str: """Escape a string such that it can be embedded into a Ninja file without further interpretation.""" assert "\n" not in string, "Ninja syntax does not allow newlines" @@ -207,17 +238,17 @@ def escape(string): return string.replace("$", "$$") -def expand(string, vars, local_vars={}): +def expand(string: str, vars: Dict[str, str], local_vars: Dict[str, str] = {}) -> str: """Expand a string containing $vars as Ninja would. Note: doesn't handle the full Ninja variable syntax, but it's enough to make configure.py's use of it work. """ - def exp(m): + def exp(m: Match[str]) -> str: var = m.group(1) if var == "$": return "$" return local_vars.get(var, vars.get(var, "")) - return re.sub(r"\$(\$|\w*)", exp, string) \ No newline at end of file + return re.sub(r"\$(\$|\w*)", exp, string) diff --git a/tools/project.py b/tools/project.py index 0f5ad89b..8f8c6e07 100644 --- a/tools/project.py +++ b/tools/project.py @@ -12,12 +12,15 @@ import io import json +import math import os import platform import sys - from pathlib import Path +from typing import Any, Dict, List, Optional, Set, Tuple, Union + from . import ninja_syntax +from .ninja_syntax import serialize_path if sys.platform == "cygwin": sys.exit( @@ -27,46 +30,80 @@ if sys.platform == "cygwin": ) +class Object: + def __init__(self, completed: bool, name: str, **options: Any) -> None: + self.name = name + self.base_name = Path(name).with_suffix("") + self.completed = completed + self.options: Dict[str, Any] = { + "add_to_all": True, + "asflags": None, + "extra_asflags": None, + "cflags": None, + "extra_cflags": None, + "mw_version": None, + "shift_jis": None, + "source": name, + } + self.options.update(options) + + class ProjectConfig: - def __init__(self): + def __init__(self) -> None: # Paths - self.build_dir = Path("build") - self.src_dir = Path("src") - self.tools_dir = Path("tools") + self.build_dir: Path = Path("build") # Output build files + self.src_dir: Path = Path("src") # C/C++/asm source files + self.tools_dir: Path = Path("tools") # Python scripts + self.asm_dir: Path = Path("asm") # Override incomplete objects (for modding) # Tooling - self.dtk_tag = None # Git tag - self.build_dtk_path = None # If None, download - self.compilers_tag = None # 1 - self.compilers_path = None # If None, download - self.wibo_tag = None # Git tag - self.wrapper = None # If None, download wibo on Linux - self.sjiswrap_tag = None # Git tag - self.sjiswrap_path = None # If None, download + self.binutils_tag: Optional[str] = None # Git tag + self.binutils_path: Optional[Path] = None # If None, download + self.dtk_tag: Optional[str] = None # Git tag + self.build_dtk_path: Optional[Path] = None # If None, download + self.compilers_tag: Optional[str] = None # 1 + self.compilers_path: Optional[Path] = None # If None, download + self.wibo_tag: Optional[str] = None # Git tag + self.wrapper: Optional[Path] = None # If None, download wibo on Linux + self.sjiswrap_tag: Optional[str] = None # Git tag + self.sjiswrap_path: Optional[Path] = None # If None, download # Project config - self.build_rels = True # Build REL files - self.check_sha_path = None # Path to version.sha1 - self.config_path = None # Path to config.yml - self.debug = False # Build with debug info - self.generate_map = False # Generate map file(s) - self.ldflags = None # Linker flags - self.libs = None # List of libraries - self.linker_version = None # mwld version - self.version = None # Version name - self.warn_missing_config = False # Warn on missing unit configuration - self.warn_missing_source = False # Warn on missing source file - self.rel_strip_partial = True # Generate PLFs with -strip_partial - self.rel_empty_file = None # Path to empty.c for generating empty RELs + self.build_rels: bool = True # Build REL files + self.check_sha_path: Optional[Path] = None # Path to version.sha1 + self.config_path: Optional[Path] = None # Path to config.yml + self.debug: bool = False # Build with debug info + self.generate_map: bool = False # Generate map file(s) + self.asflags: Optional[List[str]] = None # Assembler flags + self.ldflags: Optional[List[str]] = None # Linker flags + self.libs: Optional[List[Dict[str, Any]]] = None # List of libraries + self.linker_version: Optional[str] = None # mwld version + self.version: Optional[str] = None # Version name + self.warn_missing_config: bool = False # Warn on missing unit configuration + self.warn_missing_source: bool = False # Warn on missing source file + self.rel_strip_partial: bool = True # Generate PLFs with -strip_partial + self.rel_empty_file: Optional[str] = ( + None # Object name for generating empty RELs + ) + self.shift_jis = ( + True # Convert source files from UTF-8 to Shift JIS automatically + ) # Progress output and progress.json config - self.progress_all = True # Include combined "all" category - self.progress_modules = True # Include combined "modules" category - self.progress_each_module = ( + self.progress_all: bool = True # Include combined "all" category + self.progress_modules: bool = True # Include combined "modules" category + self.progress_each_module: bool = ( True # Include individual modules, disable for large numbers of modules ) - def validate(self): + # Progress fancy printing + self.progress_use_fancy: bool = False + self.progress_code_fancy_frac: int = 0 + self.progress_code_fancy_item: str = "" + self.progress_data_fancy_frac: int = 0 + self.progress_data_fancy_item: str = "" + + def validate(self) -> None: required_attrs = [ "build_dir", "src_dir", @@ -82,33 +119,18 @@ class ProjectConfig: if getattr(self, attr) is None: sys.exit(f"ProjectConfig.{attr} missing") - def find_object(self, name): - for lib in self.libs: + def find_object(self, name: str) -> Optional[Tuple[Dict[str, Any], Object]]: + for lib in self.libs or {}: for obj in lib["objects"]: if obj.name == name: - return [lib, obj] + return lib, obj return None - def out_path(self): - return self.build_dir / self.version + def out_path(self) -> Path: + return self.build_dir / str(self.version) -class Object: - def __init__(self, completed, name, **options): - self.name = name - self.completed = completed - self.options = { - "add_to_all": True, - "cflags": None, - "extra_cflags": None, - "mw_version": None, - "shiftjis": True, - "source": name, - } - self.options.update(options) - - -def is_windows(): +def is_windows() -> bool: return os.name == "nt" @@ -118,36 +140,25 @@ CHAIN = "cmd /c " if is_windows() else "" EXE = ".exe" if is_windows() else "" -# Replace forward slashes with backslashes on Windows -def os_str(value): - return str(value).replace("/", os.sep) - - -# Replace backslashes with forward slashes on Windows -def unix_str(value): - return str(value).replace(os.sep, "/") - - -# Stringify paths for ninja_syntax -def path(value): - if value is None: - return None - elif isinstance(value, list): - return list(map(os_str, filter(lambda x: x is not None, value))) +def make_flags_str(cflags: Union[str, List[str]]) -> str: + if isinstance(cflags, list): + return " ".join(cflags) else: - return [os_str(value)] + return cflags # Load decomp-toolkit generated config.json -def load_build_config(config, build_config_path): +def load_build_config( + config: ProjectConfig, build_config_path: Path +) -> Optional[Dict[str, Any]]: if not build_config_path.is_file(): return None - def versiontuple(v): + def versiontuple(v: str) -> Tuple[int, ...]: return tuple(map(int, (v.split(".")))) f = open(build_config_path, "r", encoding="utf-8") - build_config = json.load(f) + build_config: Dict[str, Any] = json.load(f) config_version = build_config.get("version") if not config_version: # Invalid config.json @@ -155,7 +166,7 @@ def load_build_config(config, build_config_path): os.remove(build_config_path) return None - dtk_version = config.dtk_tag[1:] # Strip v + dtk_version = str(config.dtk_tag)[1:] # Strip v if versiontuple(config_version) < versiontuple(dtk_version): # Outdated config.json f.close() @@ -167,14 +178,16 @@ def load_build_config(config, build_config_path): # Generate build.ninja and objdiff.json -def generate_build(config): +def generate_build(config: ProjectConfig) -> None: build_config = load_build_config(config, config.out_path() / "config.json") generate_build_ninja(config, build_config) generate_objdiff_config(config, build_config) # Generate build.ninja -def generate_build_ninja(config, build_config): +def generate_build_ninja( + config: ProjectConfig, build_config: Optional[Dict[str, Any]] +) -> None: config.validate() out = io.StringIO() @@ -182,9 +195,9 @@ def generate_build_ninja(config, build_config): n.variable("ninja_required_version", "1.3") n.newline() - configure_script = os.path.relpath(os.path.abspath(sys.argv[0])) - python_lib = os.path.relpath(__file__) - python_lib_dir = os.path.dirname(python_lib) + configure_script = Path(os.path.relpath(os.path.abspath(sys.argv[0]))) + python_lib = Path(os.path.relpath(__file__)) + python_lib_dir = python_lib.parent n.comment("The arguments passed to configure.py, for rerunning it.") n.variable("configure_args", sys.argv[1:]) n.variable("python", f'"{sys.executable}"') @@ -194,13 +207,15 @@ def generate_build_ninja(config, build_config): # Variables ### n.comment("Variables") - ldflags = " ".join(config.ldflags) + ldflags = " ".join(config.ldflags or []) if config.generate_map: ldflags += " -mapunused" if config.debug: ldflags += " -g" n.variable("ldflags", ldflags) - n.variable("mw_version", config.linker_version) + if not config.linker_version: + sys.exit("ProjectConfig.linker_version missing") + n.variable("mw_version", Path(config.linker_version)) n.newline() ### @@ -209,6 +224,7 @@ def generate_build_ninja(config, build_config): n.comment("Tooling") build_path = config.out_path() + progress_path = build_path / "progress.json" build_tools_path = config.build_dir / "tools" download_tool = config.tools_dir / "download_tool.py" n.rule( @@ -217,20 +233,29 @@ def generate_build_ninja(config, build_config): description="TOOL $out", ) + decompctx = config.tools_dir / "decompctx.py" + n.rule( + name="decompctx", + command=f"$python {decompctx} $in -o $out -d $out.d", + description="CTX $in", + depfile="$out.d", + deps="gcc", + ) + if config.build_dtk_path: dtk = build_tools_path / "release" / f"dtk{EXE}" n.rule( name="cargo", command="cargo build --release --manifest-path $in --bin $bin --target-dir $target", description="CARGO $bin", - depfile=path(Path("$target") / "release" / "$bin.d"), + depfile=Path("$target") / "release" / "$bin.d", deps="gcc", ) n.build( - outputs=path(dtk), + outputs=dtk, rule="cargo", - inputs=path(config.build_dtk_path / "Cargo.toml"), - implicit=path(config.build_dtk_path / "Cargo.lock"), + inputs=config.build_dtk_path / "Cargo.toml", + implicit=config.build_dtk_path / "Cargo.lock", variables={ "bin": "dtk", "target": build_tools_path, @@ -239,9 +264,9 @@ def generate_build_ninja(config, build_config): elif config.dtk_tag: dtk = build_tools_path / f"dtk{EXE}" n.build( - outputs=path(dtk), + outputs=dtk, rule="download_tool", - implicit=path(download_tool), + implicit=download_tool, variables={ "tool": "dtk", "tag": config.dtk_tag, @@ -255,9 +280,9 @@ def generate_build_ninja(config, build_config): elif config.sjiswrap_tag: sjiswrap = build_tools_path / "sjiswrap.exe" n.build( - outputs=path(sjiswrap), + outputs=sjiswrap, rule="download_tool", - implicit=path(download_tool), + implicit=download_tool, variables={ "tool": "sjiswrap", "tag": config.sjiswrap_tag, @@ -268,7 +293,7 @@ def generate_build_ninja(config, build_config): # Only add an implicit dependency on wibo if we download it wrapper = config.wrapper - wrapper_implicit = None + wrapper_implicit: Optional[Path] = None if ( config.wibo_tag is not None and sys.platform == "linux" @@ -278,33 +303,53 @@ def generate_build_ninja(config, build_config): wrapper = build_tools_path / "wibo" wrapper_implicit = wrapper n.build( - outputs=path(wrapper), + outputs=wrapper, rule="download_tool", - implicit=path(download_tool), + implicit=download_tool, variables={ "tool": "wibo", "tag": config.wibo_tag, }, ) if not is_windows() and wrapper is None: - wrapper = "wine" + wrapper = Path("wine") wrapper_cmd = f"{wrapper} " if wrapper else "" - compilers_implicit = None + compilers_implicit: Optional[Path] = None if config.compilers_path: compilers = config.compilers_path elif config.compilers_tag: compilers = config.build_dir / "compilers" compilers_implicit = compilers n.build( - outputs=path(compilers), + outputs=compilers, rule="download_tool", - implicit=path(download_tool), + implicit=download_tool, variables={ "tool": "compilers", "tag": config.compilers_tag, }, ) + else: + sys.exit("ProjectConfig.compilers_tag missing") + + binutils_implicit = None + if config.binutils_path: + binutils = config.binutils_path + elif config.binutils_tag: + binutils = config.build_dir / "binutils" + binutils_implicit = binutils + n.build( + outputs=binutils, + rule="download_tool", + implicit=download_tool, + variables={ + "tool": "binutils", + "tag": config.binutils_tag, + }, + ) + else: + sys.exit("ProjectConfig.binutils_tag missing") n.newline() @@ -316,16 +361,24 @@ def generate_build_ninja(config, build_config): # MWCC mwcc = compiler_path / "mwcceppc.exe" mwcc_cmd = f"{wrapper_cmd}{mwcc} $cflags -MMD -c $in -o $basedir" - mwcc_implicit = [compilers_implicit or mwcc, wrapper_implicit] + mwcc_implicit: List[Optional[Path]] = [compilers_implicit or mwcc, wrapper_implicit] # MWCC with UTF-8 to Shift JIS wrapper mwcc_sjis_cmd = f"{wrapper_cmd}{sjiswrap} {mwcc} $cflags -MMD -c $in -o $basedir" - mwcc_sjis_implicit = [*mwcc_implicit, sjiswrap] + mwcc_sjis_implicit: List[Optional[Path]] = [*mwcc_implicit, sjiswrap] # MWLD mwld = compiler_path / "mwldeppc.exe" mwld_cmd = f"{wrapper_cmd}{mwld} $ldflags -o $out @$out.rsp" - mwld_implicit = [compilers_implicit or mwld, wrapper_implicit] + mwld_implicit: List[Optional[Path]] = [compilers_implicit or mwld, wrapper_implicit] + + # GNU as + gnu_as = binutils / f"powerpc-eabi-as{EXE}" + gnu_as_cmd = ( + f"{CHAIN}{gnu_as} $asflags -o $out $in -MD $out.d" + + f" && {dtk} elf fixup $out $out" + ) + gnu_as_implicit = [binutils_implicit or gnu_as, dtk] if os.name != "nt": transform_dep = config.tools_dir / "transform_dep.py" @@ -372,6 +425,16 @@ def generate_build_ninja(config, build_config): ) n.newline() + n.comment("Assemble asm") + n.rule( + name="as", + command=gnu_as_cmd, + description="AS $out", + depfile="$out.d", + deps="gcc", + ) + n.newline() + n.comment("Host build") n.variable("host_cflags", "-I include -Wno-trigraphs") n.variable( @@ -394,66 +457,67 @@ def generate_build_ninja(config, build_config): # Source files ### n.comment("Source files") + build_asm_path = build_path / "mod" build_src_path = build_path / "src" build_host_path = build_path / "host" build_config_path = build_path / "config.json" - def map_path(path): + def map_path(path: Path) -> Path: return path.parent / (path.name + ".MAP") class LinkStep: - def __init__(self, config): - self.name = config["name"] - self.module_id = config["module_id"] - self.ldscript = config["ldscript"] + def __init__(self, config: Dict[str, Any]) -> None: + self.name: str = config["name"] + self.module_id: int = config["module_id"] + self.ldscript: Optional[Path] = Path(config["ldscript"]) self.entry = config["entry"] - self.inputs = [] + self.inputs: List[str] = [] - def add(self, obj): - self.inputs.append(obj) + def add(self, obj: Path) -> None: + self.inputs.append(serialize_path(obj)) - def output(self): + def output(self) -> Path: if self.module_id == 0: return build_path / f"{self.name}.dol" else: return build_path / self.name / f"{self.name}.rel" - def partial_output(self): + def partial_output(self) -> Path: if self.module_id == 0: return build_path / f"{self.name}.elf" else: return build_path / self.name / f"{self.name}.plf" - def write(self, n): + def write(self, n: ninja_syntax.Writer) -> None: n.comment(f"Link {self.name}") if self.module_id == 0: elf_path = build_path / f"{self.name}.elf" dol_path = build_path / f"{self.name}.dol" - elf_ldflags = f"$ldflags -lcf {self.ldscript}" + elf_ldflags = f"$ldflags -lcf {serialize_path(self.ldscript)}" if config.generate_map: elf_map = map_path(elf_path) - elf_ldflags += f" -map {elf_map}" + elf_ldflags += f" -map {serialize_path(elf_map)}" else: elf_map = None n.build( - outputs=path(elf_path), + outputs=elf_path, rule="link", - inputs=path(self.inputs), - implicit=path([self.ldscript, *mwld_implicit]), - implicit_outputs=path(elf_map), + inputs=self.inputs, + implicit=[self.ldscript, *mwld_implicit], + implicit_outputs=elf_map, variables={"ldflags": elf_ldflags}, ) n.build( - outputs=path(dol_path), + outputs=dol_path, rule="elf2dol", - inputs=path(elf_path), - implicit=path(dtk), + inputs=elf_path, + implicit=dtk, ) else: preplf_path = build_path / self.name / f"{self.name}.preplf" plf_path = build_path / self.name / f"{self.name}.plf" - preplf_ldflags = f"$ldflags -sdata 0 -sdata2 0 -r" - plf_ldflags = f"$ldflags -sdata 0 -sdata2 0 -r1 -lcf {self.ldscript}" + preplf_ldflags = "$ldflags -sdata 0 -sdata2 0 -r" + plf_ldflags = f"$ldflags -sdata 0 -sdata2 0 -r1 -lcf {serialize_path(self.ldscript)}" if self.entry: plf_ldflags += f" -m {self.entry}" # -strip_partial is only valid with -m @@ -461,44 +525,140 @@ def generate_build_ninja(config, build_config): plf_ldflags += " -strip_partial" if config.generate_map: preplf_map = map_path(preplf_path) - preplf_ldflags += f" -map {preplf_map}" + preplf_ldflags += f" -map {serialize_path(preplf_map)}" plf_map = map_path(plf_path) - plf_ldflags += f" -map {plf_map}" + plf_ldflags += f" -map {serialize_path(plf_map)}" else: preplf_map = None plf_map = None n.build( - outputs=path(preplf_path), + outputs=preplf_path, rule="link", - inputs=path(self.inputs), - implicit=path(mwld_implicit), - implicit_outputs=path(preplf_map), + inputs=self.inputs, + implicit=mwld_implicit, + implicit_outputs=preplf_map, variables={"ldflags": preplf_ldflags}, ) n.build( - outputs=path(plf_path), + outputs=plf_path, rule="link", - inputs=path(self.inputs), - implicit=path([self.ldscript, preplf_path, *mwld_implicit]), - implicit_outputs=path(plf_map), + inputs=self.inputs, + implicit=[self.ldscript, preplf_path, *mwld_implicit], + implicit_outputs=plf_map, variables={"ldflags": plf_ldflags}, ) n.newline() if build_config: - link_steps = [] - used_compiler_versions = set() - source_inputs = [] - host_source_inputs = [] - source_added = set() + link_steps: List[LinkStep] = [] + used_compiler_versions: Set[str] = set() + source_inputs: List[Path] = [] + host_source_inputs: List[Path] = [] + source_added: Set[Path] = set() - def make_cflags_str(cflags): - if isinstance(cflags, list): - return " ".join(cflags) - else: - return cflags + def c_build( + obj: Object, options: Dict[str, Any], lib_name: str, src_path: Path + ) -> Optional[Path]: - def add_unit(build_obj, link_step): + cflags_str = make_flags_str(options["cflags"]) + if options["extra_cflags"] is not None: + extra_cflags_str = make_flags_str(options["extra_cflags"]) + cflags_str += " " + extra_cflags_str + used_compiler_versions.add(options["mw_version"]) + + src_obj_path = build_src_path / f"{obj.base_name}.o" + src_base_path = build_src_path / obj.base_name + + # Avoid creating duplicate build rules + if src_obj_path in source_added: + return src_obj_path + source_added.add(src_obj_path) + + shift_jis = options["shift_jis"] + if shift_jis is None: + shift_jis = config.shift_jis + + # Add MWCC build rule + n.comment(f"{obj.name}: {lib_name} (linked {obj.completed})") + n.build( + outputs=src_obj_path, + rule="mwcc_sjis" if shift_jis else "mwcc", + inputs=src_path, + variables={ + "mw_version": Path(options["mw_version"]), + "cflags": cflags_str, + "basedir": os.path.dirname(src_base_path), + "basefile": src_base_path, + }, + implicit=mwcc_sjis_implicit if shift_jis else mwcc_implicit, + ) + + # Add ctx build rule + ctx_path = build_src_path / f"{obj.base_name}.ctx" + n.build( + outputs=ctx_path, + rule="decompctx", + inputs=src_path, + implicit=decompctx, + ) + + # Add host build rule + if options.get("host", False): + host_obj_path = build_host_path / f"{obj.base_name}.o" + host_base_path = build_host_path / obj.base_name + n.build( + outputs=host_obj_path, + rule="host_cc" if src_path.suffix == ".c" else "host_cpp", + inputs=src_path, + variables={ + "basedir": os.path.dirname(host_base_path), + "basefile": host_base_path, + }, + ) + if options["add_to_all"]: + host_source_inputs.append(host_obj_path) + n.newline() + + if options["add_to_all"]: + source_inputs.append(src_obj_path) + + return src_obj_path + + def asm_build( + obj: Object, options: Dict[str, Any], lib_name: str, src_path: Path + ) -> Optional[Path]: + asflags = options["asflags"] or config.asflags + if asflags is None: + sys.exit("ProjectConfig.asflags missing") + asflags_str = make_flags_str(asflags) + if options["extra_asflags"] is not None: + extra_asflags_str = make_flags_str(options["extra_asflags"]) + asflags_str += " " + extra_asflags_str + + asm_obj_path = build_asm_path / f"{obj.base_name}.o" + + # Avoid creating duplicate build rules + if asm_obj_path in source_added: + return asm_obj_path + source_added.add(asm_obj_path) + + # Add assembler build rule + n.comment(f"{obj.name}: {lib_name} (linked {obj.completed})") + n.build( + outputs=asm_obj_path, + rule="as", + inputs=src_path, + variables={"asflags": asflags_str}, + implicit=gnu_as_implicit, + ) + n.newline() + + if options["add_to_all"]: + source_inputs.append(asm_obj_path) + + return asm_obj_path + + def add_unit(build_obj, link_step: LinkStep): obj_path, obj_name = build_obj["object"], build_obj["name"] result = config.find_object(obj_name) if not result: @@ -509,70 +669,47 @@ def generate_build_ninja(config, build_config): lib, obj = result lib_name = lib["lib"] - src_dir = Path(lib.get("src_dir", config.src_dir)) - options = obj.options - completed = obj.completed + # Use object options, then library options + options = lib.copy() + for key, value in obj.options.items(): + if value is not None or key not in options: + options[key] = value - unit_src_path = src_dir / options["source"] - if not unit_src_path.exists(): - if config.warn_missing_source or completed: + unit_src_path = Path(lib.get("src_dir", config.src_dir)) / options["source"] + if config.asm_dir is not None: + unit_asm_path = ( + Path(lib.get("asm_dir", config.asm_dir)) / options["source"] + ).with_suffix(".s") + + link_built_obj = obj.completed + if unit_src_path.exists(): + if unit_src_path.suffix in (".c", ".cp", ".cpp"): + # Add MWCC & host build rules + built_obj_path = c_build(obj, options, lib_name, unit_src_path) + elif unit_src_path.suffix == ".s": + # Add assembler build rule + built_obj_path = asm_build(obj, options, lib_name, unit_src_path) + else: + sys.exit(f"Unknown source file type {unit_src_path}") + else: + if config.warn_missing_source or obj.completed: print(f"Missing source file {unit_src_path}") + link_built_obj = False + + # Assembly overrides + if unit_asm_path is not None and unit_asm_path.exists(): + link_built_obj = True + built_obj_path = asm_build(obj, options, lib_name, unit_asm_path) + + if link_built_obj and built_obj_path is not None: + # Use the source-built object + link_step.add(built_obj_path) + elif obj_path is not None: + # Use the original (extracted) object link_step.add(obj_path) - return - - mw_version = options["mw_version"] or lib["mw_version"] - cflags_str = make_cflags_str(options["cflags"] or lib["cflags"]) - if options["extra_cflags"] is not None: - extra_cflags_str = make_cflags_str(options["extra_cflags"]) - cflags_str += " " + extra_cflags_str - used_compiler_versions.add(mw_version) - - base_object = Path(obj.name).with_suffix("") - src_obj_path = build_src_path / f"{base_object}.o" - src_base_path = build_src_path / base_object - - if src_obj_path not in source_added: - source_added.add(src_obj_path) - - n.comment(f"{obj_name}: {lib_name} (linked {completed})") - n.build( - outputs=path(src_obj_path), - rule="mwcc_sjis" if options["shiftjis"] else "mwcc", - inputs=path(unit_src_path), - variables={ - "mw_version": path(Path(mw_version)), - "cflags": cflags_str, - "basedir": os.path.dirname(src_base_path), - "basefile": path(src_base_path), - }, - implicit=path( - mwcc_sjis_implicit if options["shiftjis"] else mwcc_implicit - ), - ) - - if lib["host"]: - host_obj_path = build_host_path / f"{base_object}.o" - host_base_path = build_host_path / base_object - n.build( - outputs=path(host_obj_path), - rule="host_cc" if unit_src_path.suffix == ".c" else "host_cpp", - inputs=path(unit_src_path), - variables={ - "basedir": os.path.dirname(host_base_path), - "basefile": path(host_base_path), - }, - ) - if options["add_to_all"]: - host_source_inputs.append(host_obj_path) - n.newline() - - if options["add_to_all"]: - source_inputs.append(src_obj_path) - - if completed: - obj_path = src_obj_path - link_step.add(obj_path) + else: + sys.exit(f"Missing object for {obj_name}: {unit_src_path} {lib} {obj}") # Add DOL link step link_step = LinkStep(build_config) @@ -608,7 +745,7 @@ def generate_build_ninja(config, build_config): sys.exit(f"Compiler {mw_path} does not exist") # Check if linker exists - mw_path = compilers / config.linker_version / "mwldeppc.exe" + mw_path = compilers / str(config.linker_version) / "mwldeppc.exe" if config.compilers_path and not os.path.exists(mw_path): sys.exit(f"Linker {mw_path} does not exist") @@ -648,7 +785,7 @@ def generate_build_ninja(config, build_config): rels_to_generate = list( filter( lambda step: step.module_id != 0 - and not step.name in generated_rels, + and step.name not in generated_rels, link_steps_local, ) ) @@ -669,15 +806,13 @@ def generate_build_ninja(config, build_config): ) rel_names_arg = " ".join(map(lambda name: f"-n {name}", rel_names)) n.build( - outputs=path(rel_outputs), + outputs=rel_outputs, rule="makerel", - inputs=path( - list(map(lambda step: step.partial_output(), link_steps_local)) - ), - implicit=path([dtk, config.config_path]), + inputs=list(map(lambda step: step.partial_output(), link_steps_local)), + implicit=[dtk, config.config_path], variables={ - "config": path(config.config_path), - "rspfile": path(config.out_path() / f"rel{idx}.rsp"), + "config": config.config_path, + "rspfile": config.out_path() / f"rel{idx}.rsp", "names": rel_names_arg, }, ) @@ -690,7 +825,7 @@ def generate_build_ninja(config, build_config): n.build( outputs="all_source", rule="phony", - inputs=path(source_inputs), + inputs=source_inputs, ) n.newline() @@ -701,7 +836,7 @@ def generate_build_ninja(config, build_config): n.build( outputs="all_source_host", rule="phony", - inputs=path(host_source_inputs), + inputs=host_source_inputs, ) n.newline() @@ -717,10 +852,10 @@ def generate_build_ninja(config, build_config): description="CHECK $in", ) n.build( - outputs=path(ok_path), + outputs=ok_path, rule="check", - inputs=path(config.check_sha_path), - implicit=path([dtk, *map(lambda step: step.output(), link_steps)]), + inputs=config.check_sha_path, + implicit=[dtk, *map(lambda step: step.output(), link_steps)], ) n.newline() @@ -728,16 +863,15 @@ def generate_build_ninja(config, build_config): # Calculate progress ### n.comment("Calculate progress") - progress_path = build_path / "progress.json" n.rule( name="progress", command=f"$python {configure_script} $configure_args progress", description="PROGRESS", ) n.build( - outputs=path(progress_path), + outputs=progress_path, rule="progress", - implicit=path([ok_path, configure_script, python_lib, config.config_path]), + implicit=[ok_path, configure_script, python_lib, config.config_path], ) ### @@ -753,7 +887,7 @@ def generate_build_ninja(config, build_config): description=f"DIFF {dol_elf_path}", ) n.build( - inputs=path([config.config_path, dol_elf_path]), + inputs=[config.config_path, dol_elf_path], outputs="dol_diff", rule="dol_diff", ) @@ -771,10 +905,10 @@ def generate_build_ninja(config, build_config): description=f"APPLY {dol_elf_path}", ) n.build( - inputs=path([config.config_path, dol_elf_path]), + inputs=[config.config_path, dol_elf_path], outputs="dol_apply", rule="dol_apply", - implicit=path([ok_path]), + implicit=[ok_path], ) n.build( outputs="apply", @@ -795,11 +929,11 @@ def generate_build_ninja(config, build_config): deps="gcc", ) n.build( - inputs=path(config.config_path), - outputs=path(build_config_path), + inputs=config.config_path, + outputs=build_config_path, rule="split", - implicit=path(dtk), - variables={"out_dir": path(build_path)}, + implicit=dtk, + variables={"out_dir": build_path}, ) n.newline() @@ -816,14 +950,12 @@ def generate_build_ninja(config, build_config): n.build( outputs="build.ninja", rule="configure", - implicit=path( - [ - build_config_path, - configure_script, - python_lib, - Path(python_lib_dir) / "ninja_syntax.py", - ] - ), + implicit=[ + build_config_path, + configure_script, + python_lib, + python_lib_dir / "ninja_syntax.py", + ], ) n.newline() @@ -832,9 +964,9 @@ def generate_build_ninja(config, build_config): ### n.comment("Default rule") if build_config: - n.default(path(progress_path)) + n.default(progress_path) else: - n.default(path(build_config_path)) + n.default(build_config_path) # Write build.ninja with open("build.ninja", "w", encoding="utf-8") as f: @@ -843,12 +975,14 @@ def generate_build_ninja(config, build_config): # Generate objdiff.json -def generate_objdiff_config(config, build_config): +def generate_objdiff_config( + config: ProjectConfig, build_config: Optional[Dict[str, Any]] +) -> None: if not build_config: return - objdiff_config = { - "min_version": "0.4.3", + objdiff_config: Dict[str, Any] = { + "min_version": "1.0.0", "custom_make": "ninja", "build_target": False, "watch_patterns": [ @@ -866,18 +1000,50 @@ def generate_objdiff_config(config, build_config): "units": [], } + # decomp.me compiler name mapping + # Commented out versions have not been added to decomp.me yet + COMPILER_MAP = { + "GC/1.0": "mwcc_233_144", + "GC/1.1": "mwcc_233_159", + "GC/1.2.5": "mwcc_233_163", + "GC/1.2.5e": "mwcc_233_163e", + "GC/1.2.5n": "mwcc_233_163n", + "GC/1.3.2": "mwcc_242_81", + "GC/1.3.2r": "mwcc_242_81r", + "GC/2.0": "mwcc_247_92", + "GC/2.5": "mwcc_247_105", + "GC/2.6": "mwcc_247_107", + "GC/2.7": "mwcc_247_108", + "GC/3.0": "mwcc_41_60831", + # "GC/3.0a3": "mwcc_41_51213", + "GC/3.0a3.2": "mwcc_41_60126", + # "GC/3.0a3.3": "mwcc_41_60209", + # "GC/3.0a3.4": "mwcc_42_60308", + # "GC/3.0a5": "mwcc_42_60422", + "GC/3.0a5.2": "mwcc_41_60831", + "Wii/0x4201_127": "mwcc_42_142", + # "Wii/1.0": "mwcc_43_145", + # "Wii/1.0RC1": "mwcc_42_140", + "Wii/1.0a": "mwcc_42_142", + "Wii/1.1": "mwcc_43_151", + "Wii/1.3": "mwcc_43_172", + # "Wii/1.5": "mwcc_43_188", + "Wii/1.6": "mwcc_43_202", + "Wii/1.7": "mwcc_43_213", + } + build_path = config.out_path() - def add_unit(build_obj, module_name): + def add_unit(build_obj: Dict[str, Any], module_name: str) -> None: if build_obj["autogenerated"]: # Skip autogenerated objects return obj_path, obj_name = build_obj["object"], build_obj["name"] base_object = Path(obj_name).with_suffix("") - unit_config = { - "name": unix_str(Path(module_name) / base_object), - "target_path": unix_str(obj_path), + unit_config: Dict[str, Any] = { + "name": Path(module_name) / base_object, + "target_path": obj_path, } result = config.find_object(obj_name) @@ -888,13 +1054,21 @@ def generate_objdiff_config(config, build_config): lib, obj = result src_dir = Path(lib.get("src_dir", config.src_dir)) - unit_src_path = src_dir / obj.options["source"] + # Use object options, then library options + options = lib.copy() + for key, value in obj.options.items(): + if value is not None or key not in options: + options[key] = value + + unit_src_path = src_dir / str(options["source"]) + if not unit_src_path.exists(): objdiff_config["units"].append(unit_config) return - cflags = obj.options["cflags"] or lib["cflags"] - src_obj_path = build_path / "src" / f"{base_object}.o" + cflags = options["cflags"] + src_obj_path = build_path / "src" / f"{obj.base_name}.o" + src_ctx_path = build_path / "src" / f"{obj.base_name}.ctx" reverse_fn_order = False if type(cflags) is list: @@ -907,9 +1081,32 @@ def generate_objdiff_config(config, build_config): elif value == "nodeferred": reverse_fn_order = False - unit_config["base_path"] = unix_str(src_obj_path) + # Filter out include directories + def keep_flag(flag): + return not flag.startswith("-i ") and not flag.startswith("-I ") + + cflags = list(filter(keep_flag, cflags)) + + # Add appropriate lang flag + if unit_src_path.suffix in (".cp", ".cpp"): + cflags.insert(0, "-lang=c++") + else: + cflags.insert(0, "-lang=c") + + unit_config["base_path"] = src_obj_path unit_config["reverse_fn_order"] = reverse_fn_order unit_config["complete"] = obj.completed + compiler_version = COMPILER_MAP.get(options["mw_version"]) + if compiler_version is None: + print(f"Missing scratch compiler mapping for {options['mw_version']}") + else: + unit_config["scratch"] = { + "platform": "gc_wii", + "compiler": compiler_version, + "c_flags": make_flags_str(cflags), + "ctx_path": src_ctx_path, + "build_ctx": True, + } objdiff_config["units"].append(unit_config) # Add DOL units @@ -923,28 +1120,36 @@ def generate_objdiff_config(config, build_config): # Write objdiff.json with open("objdiff.json", "w", encoding="utf-8") as w: - json.dump(objdiff_config, w, indent=4) + + def unix_path(input: Any) -> str: + return str(input).replace(os.sep, "/") if input else "" + + json.dump(objdiff_config, w, indent=4, default=unix_path) # Calculate, print and write progress to progress.json -def calculate_progress(config): +def calculate_progress(config: ProjectConfig) -> None: out_path = config.out_path() build_config = load_build_config(config, out_path / "config.json") if not build_config: return class ProgressUnit: - def __init__(self, name): - self.name = name - self.code_total = 0 - self.code_progress = 0 - self.data_total = 0 - self.data_progress = 0 - self.objects_progress = 0 - self.objects_total = 0 - self.objects = set() + def __init__(self, name: str) -> None: + self.name: str = name + self.code_total: int = 0 + self.code_fancy_frac: int = config.progress_code_fancy_frac + self.code_fancy_item: str = config.progress_code_fancy_item + self.code_progress: int = 0 + self.data_total: int = 0 + self.data_fancy_frac: int = config.progress_data_fancy_frac + self.data_fancy_item: str = config.progress_data_fancy_item + self.data_progress: int = 0 + self.objects_progress: int = 0 + self.objects_total: int = 0 + self.objects: Set[Object] = set() - def add(self, build_obj): + def add(self, build_obj: Dict[str, Any]) -> None: self.code_total += build_obj["code_size"] self.data_total += build_obj["data_size"] @@ -971,10 +1176,10 @@ def calculate_progress(config): if include_object: self.objects_progress += 1 - def code_frac(self): + def code_frac(self) -> float: return self.code_progress / self.code_total - def data_frac(self): + def data_frac(self) -> float: return self.data_progress / self.data_total # Add DOL units @@ -987,7 +1192,7 @@ def calculate_progress(config): # Add REL units rels_progress = ProgressUnit("Modules") if config.progress_modules else None - modules_progress = [] + modules_progress: List[ProgressUnit] = [] for module in build_config["modules"]: progress = ProgressUnit(module["name"]) modules_progress.append(progress) @@ -1001,7 +1206,10 @@ def calculate_progress(config): # Print human-readable progress print("Progress:") - def print_category(unit): + def print_category(unit: Optional[ProgressUnit]) -> None: + if unit is None: + return + code_frac = unit.code_frac() data_frac = unit.data_frac() print( @@ -1009,6 +1217,17 @@ def calculate_progress(config): ) print(f" Code: {unit.code_progress} / {unit.code_total} bytes") print(f" Data: {unit.data_progress} / {unit.data_total} bytes") + if config.progress_use_fancy: + print( + "\nYou have {} out of {} {} and collected {} out of {} {}.".format( + math.floor(code_frac * unit.code_fancy_frac), + unit.code_fancy_frac, + unit.code_fancy_item, + math.floor(data_frac * unit.data_fancy_frac), + unit.data_fancy_frac, + unit.data_fancy_item, + ) + ) if all_progress: print_category(all_progress) @@ -1021,9 +1240,9 @@ def calculate_progress(config): print_category(progress) # Generate and write progress.json - progress_json = {} + progress_json: Dict[str, Any] = {} - def add_category(category, unit): + def add_category(category: str, unit: ProgressUnit) -> None: progress_json[category] = { "code": unit.code_progress, "code/total": unit.code_total, diff --git a/tools/transform_dep.py b/tools/transform_dep.py index 86bd2ecb..124de04b 100644 --- a/tools/transform_dep.py +++ b/tools/transform_dep.py @@ -25,7 +25,7 @@ def in_wsl() -> bool: return "microsoft-standard" in uname().release -def import_d_file(in_file) -> str: +def import_d_file(in_file: str) -> str: out_text = "" with open(in_file) as file: @@ -60,7 +60,7 @@ def import_d_file(in_file) -> str: return out_text -def main(): +def main() -> None: parser = argparse.ArgumentParser( description="""Transform a .d file from Wine paths to normal paths""" ) @@ -81,4 +81,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/tools/upload_progress.py b/tools/upload_progress.py index 673bb3d5..dc61d156 100644 --- a/tools/upload_progress.py +++ b/tools/upload_progress.py @@ -51,7 +51,7 @@ if __name__ == "__main__": args = parser.parse_args() api_key = args.api_key or os.environ.get("PROGRESS_API_KEY") if not api_key: - raise "API key required" + raise KeyError("API key required") url = generate_url(args) entries = [] @@ -68,9 +68,12 @@ if __name__ == "__main__": print("Publishing entry to", url) json.dump(entries[0], sys.stdout, indent=4) print() - r = requests.post(url, json={ - "api_key": api_key, - "entries": entries, - }) + r = requests.post( + url, + json={ + "api_key": api_key, + "entries": entries, + }, + ) r.raise_for_status() - print("Done!") \ No newline at end of file + print("Done!")