diff --git a/patchdol.bat b/patchdol.bat index 2f8891d..78d13cf 100644 --- a/patchdol.bat +++ b/patchdol.bat @@ -9,5 +9,5 @@ C:\devkitPro\devkitPPC\bin\powerpc-eabi-objdump.exe obj_%~n1.o --full-content if ERRORLEVEL 1 pause if ERRORLEVEL 1 exit C:\devkitPro\devkitPPC\bin\powerpc-eabi-objcopy.exe obj_%~n1.o %~n1.bin -O binary -R .eh_frame -R .comment -R .gnu.attributes -g -S -DolInsert.exe %~n1.bin -m %~n1.map -dol ./Start.dol -o %~n1.dol -c OnUpdate:0x802a6160:3 -c OnSetup:0x802998b8:0 -c OnDraw2D:0x80143f14:0 -c OnWaterHitsGround:0x8027f7dc:0 -c OnObjectTouchMario:0x801b02fc:3 -c OnAllNPCsUpdate:0x8003e2f0:0 -c OnSmallEnemyHitMario:0x8006c76c:3 -r EMarioControl:0x8004010c -r IsMario:0x8024db0c -r EMarioReceiveMessage:0x8003956c -r MarioSendMessage:0x80273870 -r EMarioPlayerControl:8004006c -c OnMarioIncHP:0x80282ee0:0x80282f04:0x80282f84:0x80283414:0x80283490:0x802834d4:0 -c OnMarioDecHP:0x80242b10:0 -r EMarioDamageExec:0x80040068 -r IsMultiplayerMap:0x802a8b30 +DolInsert.exe %~n1.bin -m %~n1.map -dol ./Start.dol -o %~n1.dol -c OnUpdate:0x802a6160:3 -c OnSetup:0x802998b8:0 -c OnDraw2D:0x80143f14:0 -c OnWaterHitsGround:0x8027f7dc:0 -c OnObjectTouchMario:0x801b02fc:3 -c OnAllNPCsUpdate:0x8003e2f0:0 -c OnSmallEnemyHitMario:0x8006c76c:3 -r IsMario:0x8024db0c -r MarioSendMessage:0x80273870 -c OnMarioIncHP:0x80282ee0:0x80282f04:0x80282f84:0x80283414:0x80283490:0x802834d4:0 -c OnMarioDecHP:0x80242b10:0 -r IsMultiplayerMap:0x802a8b30 -c OnCheckActorsHit:0x80299af8:0 -c OnDetectHit:0x8021bfb4:0x8021bc00:0 -c OnMarioHeld:0x80284bd0:0 -c OnMarioThrow:0x802437bc:5 -c OnMarioDrop:0x8023f89c:3 -c OnChangeNozzle:0x80283204:0x80283154:0x802830a4:0 -c OnRideYoshi:0x8028121c:0 -r IsOnYoshi:0x802558c8 -r IsOnYoshi2:0x8024e2e4 -c OnDismountYoshi:0x8024dfc8:0x80270638:0 -c OnWaterGunUpdate:0x8024e2a0:0 -c OnUpdateMultiplayerCamera:0x80023860:0 -c CalcMultiplayerCameraPos:0x80030c04:0 -c CheckOtherObjectCollisions:0x8021bc08:1 -c CheckOtherObjectCollisions2:0x8021bba8:0 -c ChangeAllPlayerStatus:0x80240798:0x80240928:80240a2c:0 -c CreateYoshi:0x80276850:0 -c OnInitApp:0x8000561c:0 -c OnCameraMove:0x80023150:0 pause \ No newline at end of file diff --git a/sms.h b/sms.h index 048e1b9..cbcf7b0 100644 --- a/sms.h +++ b/sms.h @@ -32,30 +32,20 @@ #define MARIOFLAG_GONE 0x00200000 #define STATE_NUMBER 0x0000000F - #define STATE_AIRBORN 0x00000800 #define STATE_DOJUMP 0x00000080 #define STATE_AIRBORN 0x00000800 #define STATE_CUTSCENE 0x00001000 #define STATE_STUNNED 0x00002000 #define STATE_RUNNING 0x04000440 - #define STATE_IDLE 0x0C400201 - #define STATE_STOP 0x0C00023D + #define STATE_IDLE 0x0C400200 #define STATE_SPIN 0x00000441 #define STATE_JUMPSPIN 0x00000890 #define STATE_JUMPSPIN1 0x00000895 #define STATE_JUMPSPIN2 0x00000896 #define STATE_JUMP 0x02000880 - #define STATE_D_JUMP 0x02000881 - #define STATE_TRIPLE_J 0x00000882 - #define STATE_JMP_LAND 0x04000470 - #define STATE_HVY_LAND 0x04000473 - #define STATE_D_LAND 0x04000472 - #define STATE_T_LAND 0x0800023A #define STATE_JUMPSIDE 0x00000880 #define STATE_SIDESTEP 0x0C008220 - #define STATE_SIDE_FLIP 0x00000887 - #define STATE_FALL 0x0000088C #define STATE_SWIM 0x000024D7 #define STATE_DIVE 0x0080088A #define STATE_DIVEJUMP 0x02000889 @@ -73,143 +63,19 @@ #define STATE_HOVER 0x0000088B #define STATE_STUCK 0x0002033C #define STATE_TALKING 0x10001308 - #define STATE_TURNING 0X00000444 - //add new - #define STATE_SHINE_C 0x00001302 // Collected Shine Sprite - #define STATE_DEATH 0x00020467 - #define STATE_DOOR_F_O 0x00001321 // Door open fail - #define STATE_WALL_S_L 0x04000471 - #define STATE_WALL_SLD 0x000008A7 - #define STATE_F_KNCK_H 0X000208B0 // hard knockback from front (bumping into a wall from dive) - #define STATE_KNCK_LND 0X00020462 // Landing from front knockback - #define STATE_KNCK_GND 0x00020466 // Front knockback while grounded - #define STATE_FIRE_HIT 0x000208B7 - #define STATE_FIRE_RVR 0x08000239 // Recover from fire on ground - #define STATE_HOVER_F 0x0000088D // Falling from hover - #define STATE_SLIDE_R1 0x000008A6 // Recover from slide by flipping - #define STATE_SLIDE_R2 0x00000386 // Recover from slide by getting up - #define STATE_R_SPRAY 0x0C008220 // Recover from spray - #define STATE_G_POUND 0x008008A9 // Ground pounding - - //#define - - #define BGM_DOLPIC 0x80010001 - #define BGM_BIANCO 0x80010002 - #define BGM_MAMMA 0x80010003 - #define BGM_PINNAPACO_SEA 0x80010004 - #define BGM_PINNAPACO 0x80010005 - #define BGM_MARE_SEA 0x80010006 - #define BGM_MONTEVILLAGE 0x80010007 - #define BGM_SHILENA 0x80010008 - #define BGM_RICCO 0x80010009 - #define BGM_GET_SHINE 0x8001000A - #define BGM_CHUBOSS 0x8001000B - #define BGM_MISS 0x8001000C - #define BGM_BOSS 0x8001000D - #define BGM_MAP_SELECT 0x8001000E - #define BGM_BOSSPAKU_DEMO 0x8001000F - #define BGM_MAIN_TITLE 0x80010010 - #define BGM_CHUBOSS2 0x80010011 - #define BGM_EXTRA 0x80010012 - #define BGM_DELFINO 0x80010013 - #define BGM_MAREVILLAGE 0x80010014 - #define BGM_CORONA 0x80010015 - #define BGM_KAGEMARIO 0x80010016 - #define BGM_CAMERA 0x80010017 - #define BGM_MONTE_ONSEN 0x80010018 - #define BGM_MECHAKUPPA 0x80010019 - #define BGM_AIRPORT 0x8001001A - #define BGM_UNDERGROUND 0x8001001B - #define BGM_TITLEBACK 0x8001001C - #define BGM_MONTE_NIGHT 0x8001001D - #define BGM_CASINO 0x8001001E - #define BGM_EVENT 0x8001001F - #define BGM_TIME_IVENT 0x80010020 - #define BGM_SKY_AND_SEA 0x80010021 - #define BGM_MONTE_RESCUE 0x80010022 - #define BGM_MERRY_GO_ROUND 0x80010023 - #define BGM_SCENARIO_SELECT 0x80010024 - #define BGM_FANFARE_CASINO 0x80010025 - #define BGM_FANFARE_RACE 0x80010026 - #define BGM_CAMERA_KAGE 0x80010027 - #define BGM_GAMEOVER 0x80010028 - #define BGM_BOSSHANA_2ND3RD 0x80010029 - #define BGM_BOSSGESO_2DN3RD 0x8001002A - #define BGM_CHUBOSS_MANTA 0x8001002B - #define BGM_MONTE_LAST 0x8001002C - #define BGM_SHINE_APPEAR 0x8001002D - #define BGM_KUPPA 0x8001002E - #define BGM_SPACEWORLD 0x80011030 - - #define SND_PIPE 9598 - - //#define GFX_OFF 0x09A4 - E3 - #define GFX_OFF 0x07F4 - - #define AIRPORT 0 - #define DOLPIC0 1 - #define BIANCO0 2 - #define RICCO0 3 - #define MAMMA0 4 - #define PINNABEACH0 5 - #define SIRENA0 6 - #define DELFINO0 7 - #define MONTE0 8 - #define MARE0 9 - #define NONE0 10 - #define SCALE0 11 - #define TEST10 12 - #define PINNAPARCO0 13 - #define CASINO0 14 +#define GFX_OFF 0x09A4 -typedef float Mtx[3][4]; -typedef float Mtx44[4][4]; - -enum GXProjectionType -{ - GX_PERSPECTIVE = 0, - GX_ORTHOGRAPHIC = 1 -}; - -typedef struct -{ - - float x, y, z; - -} Vec, *VecPtr, Point3d, *Point3dPtr; - -typedef struct { - Point3d position; - Point3d target; - Vec up; - float fovy; - float znear; - float zfar; - Mtx viewMtx; - Mtx44 projMtx; -} Camera; - -typedef struct { - int xorg; - int yorg; - int width; - int height; -} ViewPort; typedef struct{ - int u1; -} WaterGun; - -typedef struct{ - uint16_t buttons; // 0x0 - int8_t lanalogx; // 0x4 - int8_t lanalogy; // 0x8 - int8_t ranalogx; // 0xC - int8_t ranalogy; // 0xA - uint8_t ltrig; // 0xE - uint8_t rtrig; // 0x12 - uint8_t status; //0x16 + uint16_t buttons; + int8_t lanalogx; + int8_t lanalogy; + int8_t ranalogx; + int8_t ranalogy; + uint8_t ltrig; + uint8_t rtrig; + uint8_t status; uint8_t u2; uint8_t u3; uint8_t u4; @@ -233,114 +99,28 @@ typedef struct{ float z; } Vector; -typedef struct { - int flag1; - int flag2; - int flag3; - int flag4; - int flag5; - int flag6; - int flag7; - int flag8; - int flag9; - int flag10; -} NormalSoundData; - -typedef struct { - float u1; - float u2; - float u3; - float u4; -} HitTable; - -typedef struct{ - char* colKey; - int flag; -} ColData; - -typedef struct AnimData_t{ - char* modelKey; - int unk1; - int unk2; - int unk3; - int unk4; - int unk5; - int unk6; - int unk7; - int unk8; - int unk9; - char* animModel; - char* animKey; - int unk10; - int unk11; - int unk12; -} AnimData; - -typedef struct { - int info1; - AnimData* aData; -} AnimInfo; - -typedef struct { - int flag1; - int flag2; - int flag3; - HitTable* hitData; -} HitInfo; - -typedef struct { - int flag1; - ColData* cData; -} ColInfo; - -typedef struct { - int flag1; - NormalSoundData* normSoundData; // okay what? -} SoundInfo; - -typedef struct ObjectData_t { - char* modelKey; - float unknown1; - char* shiftJis; - char* shiftJis2; - AnimInfo* aInfo; - HitInfo* hInfo; - ColInfo* cInfo; - SoundInfo* sInfo; - int unused1; - int unused2; - int unused3; - int unused4; - float unknown2; - int flag1; - int flag2; -} ObjectData; - struct HitActor_t; struct EMario_t; struct EnemyMario_t; struct WaterGun_t; struct Yoshi_t; -struct ObjectData_t; -struct AnimData_t; -typedef struct PolarSubCamera_t { - void* Type; - void* u2; - int u3; +typedef struct Camera_t{ + void* Type; //0 + char* name; + int flags; + int u1; + Vector position; //10 + int u2; + void* u3; //20 int u4; - Vector position; - int u5; - void* u6; - int u7; - Vector u8; - float u9; - int u10; - Vector rotation; - Vector u11; - int u12[51]; - MarioGamePad* gamepad; -} PolarSubCamera; + float near; + float far; + Vector up; + Vector at; + float u5; + float u6; +} __attribute__((packed)) Camera; typedef struct MapObjBase_t{ void* Type; //0 @@ -378,163 +158,13 @@ typedef struct HitActor_t{ int u18; int u19; void* u20; //70 - void* u21[0x2F]; - ObjectData* objData; // 130 } __attribute__((packed)) HitActor; -typedef struct { - void* Type; //0 - void* u2; - int u3; - int u4; - Vector position; //10 - int u5; - void* u6; //20 - Vector scale; - Vector direction; //30 - void* u7; - void* u8; //40 - struct HitActor_t** colarray; - uint16_t colcount; - uint16_t colarraysize; - int colsettings; - float bound1; //50 - float bound2; - float bound3; - float bound4; - float bound5; //60 - int colflags; - int u18; - int u19; - void* u20; //70 - void* u21; //74 - void* u22; //78 - int snd1; //7C - int snd2; //80 - char* bas; //84 - int status; //88 - int init; //8c - int status_timer; //90 - int temp6; //94 - int temp7; //98 - int temp8; //9c - int temp9; //a0 - int temp10; //a4 - int temp11; //a8 - int temp12; //ac - float dirY; //b0 - int current; //b4 - float u23; //b8 - float u24; //bc - float u25; //c0 - void* u26; //c4 - float u27; //c8 - float u28; //cc - int reserved1; //d0 - int u29; // Used - d4 - int analogX; //d8 - int analogY; //dc - int reserved4; //e0 - int reserved5; //e4 - void* u30[18]; - ObjectData* objData; // 130 -} __attribute__((packed)) MultiActor; - -typedef struct { - void* Type; //0 - void* u2; - int u3; - int u4; - Vector position; //10 - int u5; - void* u6; //20 - Vector scale; - Vector direction; //30 - void* u7; - void* u8; //40 - struct HitActor_t** colarray; - uint16_t colcount; - uint16_t colarraysize; - int colsettings; - float bound1; //50 - float bound2; - float bound3; - float bound4; - float bound5; //60 - int colflags; - int u18; - int u19; - void* u20; //70 - void* u21; - void* u22; - int u23; - int isFlipped; - int flipTimer; -} __attribute__((packed)) flipBlockActor; - -typedef struct{ - void* Type; - void* u2; - int u3; - int hitCount; - Vector position; - int u5; - void* u6; - Vector scale; - Vector direction; - void* u7; - void* u8; - void* u9; - int u10; - int collision; - float u12; - float u13; - float u14; - float u15; - float u16; - int u17; - int u18; - int u19; - void* u20; -} BlockActor; - -typedef struct { - void* Type; //0 - void* u2; - int u3; - int u4; - Vector position; //10 - int u5; - void* u6; //20 - Vector scale; - Vector direction; //30 - void* u7; - void* u8; //40 - struct HitActor_t** colarray; - uint16_t colcount; - uint16_t colarraysize; - int colsettings; - float bound1; //50 - float bound2; - float bound3; - float bound4; - float bound5; //60 - int colflags; - int u18; - int u19; - void* u20; //70 - void* u21; - void* u22; - int u23; - int isDown; - int isRot; -} __attribute__((packed)) hexActor; - typedef struct{ void* Type; //0 - void* u2; //4 - int u3; //8 - int u4; //c + void* u2; + int u3; + int u4; Vector position; //10 int u5; void* u6; //20 @@ -569,11 +199,13 @@ typedef struct{ uint16_t roty2; //9a void* u26; //9c void* u27; //a0 - Vector speed; //a4 + float speedx; //a4 + float speedy; //a8 + float speedz; //ac void* u28[26]; //b0 int flags; //118 void* u29[178]; //11c - WaterGun* watergun; //3e4 + struct WaterGun_t* watergun;//3e4 void* u31; //3e8 void* u32; //3ec struct Yoshi_t* yoshi; //3f0 @@ -620,7 +252,7 @@ typedef struct EnemyMario_t{ void* u26[3940]; uint16_t emarioflags; uint16_t emariodamage; //4294 - uint16_t emariohealth; //4296 + int16_t emariohealth; //4296 uint16_t u27; //4298 int u28; int u29; @@ -708,6 +340,10 @@ typedef struct{ MarioActor* mario; } __attribute__((packed)) Yoshi; +typedef struct{ + int u1; +} __attribute__((packed)) WaterGun; + typedef struct{ void* u1[6]; int count; //18 @@ -764,30 +400,14 @@ typedef struct { typedef struct { void* type; int content[64]; -} J2DPaneO; +} J2DPane; typedef struct { void* type; int content[64]; } J2DScreen; - -typedef struct { - int charIndex; - int unk1; - uint8_t voice; -} JMSMesgEntry; - -typedef struct { - int unk1; - char* textBuf; - JMSMesgEntry* entry[10]; -} TalkMesEntry; - typedef struct { void* type; - void* data[596]; - TalkMesEntry* msgEntry; } Talk2D; - typedef struct { void* type; } GCConsole; @@ -810,70 +430,6 @@ typedef struct { float a3[4]; } A3_A4_f; -typedef struct { - int x; - int y; - int w; - int h; -} Rect; - -typedef struct { - void* type; - int type2; - int id; - int isVisible; - int pane_id; - JUTRect rect; - JUTRect cRect; - JUTRect clipRect; - JUTRect scissorBounds; - void* unk1[0x4A]; - long* tmem; -} J2DPane; - -typedef struct CARDFileInfo -{ - int chan; - int fileNo; - int offset; - int length; - int iBlock; -} CARDFileInfo; - -const int32_t testObjectVTable[119] = -{ - 0x00000000, 0x00000000, 0x801C4580, 0x80007D70, - 0x801AF750, 0x802FA6F4, 0x801B2FF0, 0x802FA6FC, - 0x801B3364, 0x00000000, 0x00000000, 0x801C4918, - 0x803370C0, 0x8033720C, 0x80337214, 0x8033721C, - 0x80337220, 0x80337228, 0x8033722C, 0x80337230, - 0x80337234, 0x80007FA8, 0x80007FA0, 0x80007F98, - 0x80007F90, 0x80007F88, 0x80007F80, 0x803370E0, - 0x803370E8, 0x803370EC, 0x803370F4, 0x803370F8, - 0x80337100, 0x80337104, 0x802F7004, 0x802F7020, - 0x802F703C, 0x802F7058, 0x802F7074, 0x802F7090, - 0x801B305C, 0x800C6E9C, 0x801B4194, 0x80007D40, - 0x800C6E94, 0x80218CC0, 0x801AFA4C, 0x802187D0, - 0x801B345C, 0x801AFF74, 0x801B35F8, 0x801B36B8, - 0x8021818C, 0x80218020, 0x80217FC8, 0x80217DE4, - 0x801AFA80, 0x801B4114, 0x80217D88, 0x80217D6C, - 0x80217CC8, 0x80217B30, 0x80217990, 0x801B401C, - 0x801B0430, 0x801B0738, 0x801B12F8, 0x801B1368, - 0x801B9C24, 0x801B1058, 0x801B118C, 0x800C6ED0, - 0x801B17DC, 0x800C6F08, 0x801B238C, 0x801B1D64, - 0x801B12F0, 0x801AEBEC, 0x800C6F0C, 0x800C6F10, - 0x800C6F14, 0x801B02D0, 0x801C42E4, 0x801B43D0, - 0x801B03B8, 0x801B03F4, 0x801B08F4, 0x800C6F18, - 0x800C6F20, 0x801AEBE4, 0x801B1764, 0x801B4F30, - 0x801B3F2C, 0x801B4580, 0x801B4528, 0x801B4644, - 0x801B46C4, 0x801B48F8, 0x801B4D78, 0x801B47E4, - 0x801B4DD0, 0x801B4950, 0x801B49A4, 0x801B4200, - 0x801B4BDC, 0x801B49F8, 0x801B4CEC, 0x801B4274, - 0x801B4D54, 0x801B4470, 0x801B44DC, 0x801B444C, - 0x801B3938, 0x801B3ADC, 0x801B3B8C, 0x801B3DFC, - 0x801B3EE4, 0x801B3D64, 0x801B3DF0, -}; - //For C++ inheritence #define GetObjectFunction( object, func ) (void*)*(void**)((int)*(int*)object + func) #define Director_GameUpdate 0x64 @@ -892,11 +448,6 @@ const int32_t testObjectVTable[119] = #define free(n) __dla__FUl((n)) void GXSetScissor(int x, int y, int x2, int y2); -void GXSetViewport(float x, float y, float w, float h, float nearZ, float farZ); -void GXSetProjection(float mtx[4][4], int projType); -void GXFlush(); -void C_MTXLookAt(Mtx mtx, Point3dPtr* camPos, VecPtr* camUp, Point3dPtr* target); -void setSrcRect(int viewPortObj, int rect); void GXInvalidateTexAll(); void J2DOrthoGraph_Create(J2DOrthoGraph* targetaddr, JUTRect* view); @@ -909,7 +460,7 @@ void J2DPrint_Initiate(J2DPrint* j2dprint); void J2DPrint_Print(J2DPrint* j2dprint, int x, int y, char* text, int u1, int u2, int u3); void J2DPrint_Delete(J2DPrint* j2dprint, int mask); -#define GameFont (*(ResFONT**)((*(int*)(SceneReference - 0x6038)) + 0x48)) +#define GameFont (*(ResFONT**)((*(int*)(Heap - 0x6038)) + 0x48)) #define GameStrTable (RTOC - 19304) void J2DTextBox_Create(J2DTextBox* targetaddr, int u1, JUTRect* bounds, ResFONT* font, void* table, int HBinding, int VBinding); void J2DTextBox_Draw(J2DTextBox* textbox); @@ -927,8 +478,6 @@ void J2DScreen_Draw(J2DScreen* pane, int a1, int a2, J2DGrafContext* graphics, i void JUTRect_Set(JUTRect* rect, int x, int y, int w, int h); -void setTalkBox(Talk2D* tManager, char* textBuffer, JMSMesgEntry* entry); - void MarDirector_SetupObjects(MarDirector* director); void Drama_PrepareUpdate(HitActor* this, int a1, void* drama, void* graphics, int obj); @@ -954,7 +503,7 @@ typedef ObjItemManager{ }*/ register void* RTOC __asm ("r2"); -register void* SceneReference __asm ("r13"); +register void* Heap __asm ("r13"); // math float cosf(float); @@ -964,6 +513,9 @@ float sqrtf(float); // GC //static void (*GXSetBlendMode)(int a1, int a2, int a3, int a4) = (void*)0x80361dd0; //static void (*GXBegin)(int a1, int a2, int a3) = (void*)0x8035df88; +void movePane(long pane, int u1, int u2); + +static const long* TGCCConsole2 = (void*)0x80902AB4; static const Controller* Controllers = (Controller*)0x80404454; static const Controller* ControllerOne = (Controller*)0x80404454; @@ -997,7 +549,6 @@ void Vector_Normalize(Vector* vi, Vector* vo); void Vector_Scale(Vector* vi, float scale); float Vector_Magnitude(Vector* v); void Talk2D_OpenWindow(Talk2D* talkmanager, int a1, float f1); -void openNormalTalkWindow(Talk2D* manager); void DrawWaterBackground(GCConsole* console); void StampPollution(PollutionManager* pollution, int stamp, float x, float y, float z, float r); @@ -1012,21 +563,23 @@ static void** gpStrategy = (void*)0x8040e080; static void** gpSunManager = (void*)0x8040d0c0; static HitActor** gpSunModel = (void*)0x8040d0c8; -static uint8_t* ChangeScenario = (void*)0x003e9712; -static uint8_t* ChangeEpisode = (void*)0x003e9713; +static uint8_t* ChangeScenario = (void*)0x803e9712; +static uint8_t* ChangeEpisode = (void*)0x803e9713; void ChangeStage(MarDirector* director, uint32_t stageinfo); HitActor* SearchF(void* namereflist, int keycode, char* ref); -#define SearchObjByRef(ref) SearchF((void*)*(((int*)*(int*)(SceneReference - 0x5db8)) + 1), CalcKeyCode((ref)), (ref)) +#define SearchObjByRef(ref) SearchF((void*)*(((int*)*(int*)(Heap - 0x5db8)) + 1), CalcKeyCode((ref)), (ref)) int GetShineStage(uint8_t stageid); int IsPolluted(void); //Camera -static HitActor** gpCamera = (void*)0x8040d0a8; -void Camera_AddMultiPlayer(void* camera, Vector* position); -void Camera_RemoveMultiPlayer(void* camera, Vector* position); -void Camera_CreateMultiPlayer(void* camera, unsigned char players); -void PolarSubCamera_UpdateMultiplayer(void* camera); +static Camera** gpCamera = (Camera**)0x8040d0a8; +void Camera_AddMultiPlayer(Camera* camera, Vector* position); +void Camera_RemoveMultiPlayer(Camera* camera, Vector* position); +void Camera_CreateMultiPlayer(Camera* camera, unsigned char players); +void PolarSubCamera_UpdateMultiplayer(Camera* camera); +void Camera_CalcFinalPosAndAt(Camera* camera); +void Camera_UpdateGameCamera(Camera* camera); // Mario static HitActor** gpMarioOriginal = (void*)0x8040e0e8; @@ -1078,8 +631,9 @@ void MapObjBase_RemoveMapCollision(MapObjBase* obj); void Mario_InitValues(MarioActor* mario); void Mario_GetOffYoshi(MarioActor* mario); void Mario_WaterGunUpdate(MarioActor* martin); -void mario_initModel(MarioActor* mario); -void mario_initValues(MarioActor* mario); +void Mario_Trample(MarioActor* mario, HitActor* other); +void Mario_SetAnimation(MarioActor* mario, int id, float f1); +void Mario_SetStatusToJumping(MarioActor* mario, long u1, long u2); #define GetMarioTrembleEffect(mario) ((TrembleModelEffect*)*((void**)(mario) + 0x014F)) void Yoshi_Ride(Yoshi* yoshi); @@ -1103,7 +657,6 @@ void SendMsgToMario(MarioActor* mario, int msg); #define OBJ_HOVERNOZZLE 0x20000026 #define OBJ_TURBONOZZLE 0x2000002A HitActor* MakeObjAppear(ItemManager* itemManager, int id); -HitActor* makeShineAppearWithDemo(ItemManager* itemManager, char* manager, char* mang2, float x, float y, float z); //Water void WaterEmitInfo_Create(WaterEmitInfo* this, const char* prm); @@ -1111,103 +664,22 @@ void ModelWaterManager_EmitRequest(void* man, void* emitinfo); // Effects void GenerateEffectElectric(HitActor* pos); -void emitGetCoinEffect(int unk1, MarioActor* mario); -void emitGotEffect(MarioActor* mario); -void objAppear(HitActor* actor); -void destroyCol(HitActor* actor); -void initModelData(HitActor* actor); -void marioCanTake(MarioActor* mario, HitActor* actor); -void marioStartVoice(MarioActor* mario, int soundIndex); - void ParticleManager_EmitWithRotate(void* man, int particle, Vector* position, uint16_t yaw, uint16_t pitch, uint16_t roll, uint8_t u2, void const* u5); void MapObjBase_EmitSplash(MapObjBase* obj); - -void changeTexture(int gfx, int gfxtype, int amnt); -void setPanePosition(J2DPane* plane, long speed, int unk2, int unk3, int unk4); -void updatePane(J2DPane* pane); -void updateBoundPane(J2DPane* pane); -void updateBlendPane(J2DPane* pane); -void movePane(J2DPane* pane, int u1, int u2); -int searchPane(long root, int id); -void processAppearCoin(int GCConsole); -void startAppearCoin(int GCConsole); -void processDownCoin(int GCConsole, int u1, long u2, long u3); -void getModel(HitActor* actor); -void showAllShapePacket(void); -void makeObjAppeared(HitActor* actor); -void startMapObjAnim(HitActor* actor, int multi); -void createMActor(int u1, int u2, int u3, int u4, int u5); -void startAnimation(int objProp, int anim, int u1); -void setUpMapCollision(HitActor* actor); -void setFrameRate(long _0x74, int unk1, float speed); -void changeCollision(HitActor* actor, int unk1, float unk2, float unk3); +void EasyEmitParticle(int effect, Vector* position, HitActor* actor, Vector* u1); // Music / SFX void PlaySound(int rate, Sound* sfx, int nl1, int nl2, int nl3, int four); -void startSoundSystemSE(int id, int unk1, int unk2, int unk3); void StartStageEntranceDemoSeq(int u1, int u2); void StartBGM(int u1); -void StopBGM(int u1, int u2); -void StopBGMs(int unk1, int unk2); -void search(int id); -void setAnimSound(HitActor* actor, char* bas); -void initAnimSound(int mBuff, int BAS, float unk1, int unk2); - -//TEST LUMA -static float* lumaX = (void*)0x810e21bc; -static float* lumaY = (void*)0x810e21c0; -static float* lumaZ = (void*)0x810e21c4; -static float* lumaRotY = (void*)0x810e21e0; -static float* lumaScaleX = (void*)0x810e21d0; -static float* lumaScaleY = (void*)0x810e21d4; -static float* lumaScaleZ = (void*)0x810e21d8; -static float* CamRotX = (void*)0x812444e8; -static float* CamRotY = (void*)0x812444ec; -static float* CamRotZ = (void*)0x812444f0; -static float* CoinHUD = (void*)0x80e2cfc4; - -void startCameraDemo(HitActor* cameraActor, int anim, float startrotation, int u1, long u2, int u3); -void coinTaken(HitActor* coin, HitActor* mario); -void redCoinTaken(HitActor* coin, HitActor* mario); -void startAppearGo(long ConsoleStr); -void startJAIStream(char* audioFile, int u1, void* u2); -void loadToMainRAM(char* file, int unk1, int unk2, int unk3, long unk4, int unk5, int unk6, int unk7); -void DVDOpen(char* file, long unk1); -void DVDPrepareStreamASync(long finfo, int length, int offset, long callback); -void DVDStopStreamAtEndAsync(long commandblock, long callback); -void DVDCancelStreamAsync(long commandblock, long callback); -void loadToARAM(char* file, int unk1, int unk2, int unk3, int unk4); -void loadModelData(char* modelFile, int flags, char* directory); -void setBuffer(void* constructor, void* buffer, int size); -void JSURead(void* constructor, void* buffer, int amount); -int readData(void* constructor, void* buffer, int size); -int getGlbResource(char* file); -void loadBCKDataBase(int bck); -void setBTP(long objPtr, char* animFile); -float getDistance(HitActor* object, Vector position); - -static uint32_t** key = (void*)0x80412fec; -static const int* TGCCConsole2 = (void*)0x80902AB4; -//static const int* TGCCConsole2 = (void*)0x80ea3804; -const int* firstPane = (void*)0x80ea40e4; +void StopBGM(int u1); +void StartSoundActorWithInfo(int, Vector*, Vector*, float, int, int, void**, int, uint8_t); //Other void PSMTXCopy(); void CLBPolarToCross(Vector* center, Vector* out, float rho, uint16_t theta ,uint16_t phi); +void Application_Init(void* application); -void CARDInit(void); -int CARDMount(int channelNum, void* workArea, long cardCallBack); -int CARDOpen(int channelNum, char* fileName, CARDFileInfo* fileInfo); -int CARDCreate(int channelNum, char* fileName, int size, CARDFileInfo* fileInfo); -int CARDRead(CARDFileInfo* fileInfo, void* bufferAddr, int length, int offset); -int CARDWrite(CARDFileInfo* fileInfo, void* bufferAddr, int length, int offset); - -//80e2d0d4 - c_cu -//80143a38 -//80578988 -//80426df0 - -//8117002c - +volatile const char* SMS_H_CREDITS = "SMS C Kit by miluaces and MasterF0x."; #endif \ No newline at end of file diff --git a/smsFuncs b/smsFuncs index a5c23df..5428a06 100644 --- a/smsFuncs +++ b/smsFuncs @@ -1,20 +1,8 @@ -CARDInit = 0x803551a0; -CARDMount = 0x803588dc; -CARDOpen = 0x8035938c; -CARDCreate = 0x803598a8; -CARDRead = 0x80359d20; -CARDWrite = 0x8035a09c; MarDirector_SetupObjects = 0x802b76f4; PlaySound = 0x800189d4; -StartBGM = 0x80016978; -StopBGM = 0x8001686c; -StopBGMS = 0x80016740; -search = 0x80016d44; -searchPane = 0x802d0050; StartStageEntranceDemoSeq = 0x802bb880; GenerateEffectElectric = 0x80262E18; MakeObjAppear = 0x801b6e3c; -makeShineAppearWithDemo = 0x801c018c; SendMsgToMario = 0x80273870; EmitSweat = 0x8026465c; Mario_StartVoice = 0x8028537c; @@ -22,22 +10,18 @@ Fludd_Emit = 0x80268f98; SetMarioStatus = 0x80254034; IsMarioJumping = 0x802739b4; IsMarioDashing = 0x8027372c; -initAnimSound = 0x80012eb0; -setMarioAnim = 0x80247670; -ThrowMario = 0x80254200; +Mario_SetAnim = 0x80247670; +ThrowMario = 0x8007706c; GetMarioMapPosition = 0x8007706c; IncGoldCoinFlag = 0x80294610; GetMarioStatusFromHitActor = 0x80273648; -GetMarioStatus = 0x80273674; -GetMarioHP = 0x802738f0; +GetMarioStatus = 0x802738f0; +GetMarioHP = 0x80273674; GetMarioYoshi = 0x80273a00; GetFLUDD = 0x802738c0; GetMarioHitActor = 0x802739d4; GetShineStage = 0x802a8ac8; -getGlbResource = 0x802c2fb0; SearchF = 0x802fa7ac; -setSrcRect = 0x802f884c; -setFrameRate = 0x80238e7c; ChangeStage = 0x8029a31c; DrawWaterBackground = 0x801492A4; Talk2D_OpenWindow = 0x80150514; @@ -46,9 +30,7 @@ Vector_Normalize = 0x8022a43c; Vector_Subtract = 0x80010ca0; Vector_Add = 0x8034a56c; Vector_Scale = 0x8034a5b4; -readData = 0x802c6178; CalcKeyCode = 0x802fa4d8; -C_MTXLookAt = 0x80349f5c; JUTRect_Set = 0x802ca1e0; J2DScreen_Draw = 0x802cfda8; J2DPane_MakeMatrix = 0x802cbbfc; @@ -68,13 +50,8 @@ J2DPrint_GetWidth = 0x802ce294; J2DPrint_Create = 0x802cdc7c; J2DGrafContext_Setup2D = 0x802eb6bc; J2DOrthoGraph_Create = 0x802ecfcc; -JSURead = 0x802c5770; GXInvalidateTexAll = 0x80360400; -GXSetProjection = 0x80362c34; GXSetScissor = 0x80363138; -GXSetViewport = 0x803630c8; -GXFlush = 0x8035d8f0; -getDistance = 0x801b9068; StampPollution = 0x8019de84; CleanPollution = 0x8019ddb4; Drama_PrepareUpdate = 0x802fcc94; @@ -92,8 +69,6 @@ Mario_PlayerControl = 0x8024de38; Mario_DamageExec = 0x8024280c; Mario_IncHP = 0x80243928; Mario_DecHP = 0x80243828; -mario_initModel = 0x80246578; -mario_initValues = 0x802766b0; EnemyMario_CheckController = 0x8004010c; Camera_AddMultiPlayer = 0x80030cc0; Camera_RemoveMultiPlayer = 0x80030c28; @@ -101,28 +76,6 @@ Camera_CreateMultiPlayer = 0x80030d1c; Mario_DrawHP = 0x8003fdc4; IsPolluted = 0x801a12e8; Mario_WearGlasses = 0x80247fa4; -emitGetCoinEffect = 0x80264550; -emitGotEffect = 0x802645dc; -changeTexture = 0x802cc6a0; -setPanePosition = 0x8015508c; -setAnimSound = 0x80217a8c; -setTalkBox = 0x801515a0; -Destroy = 0x801b4114; -destroyCol = 0x801b1130; -objAppear = 0x801b0430; -openNormalTalkWindow = 0x80152fb0; -startCameraDemo = 0x80032a84; -coinTaken = 0x801bec88; -redCoinTaken = 0x801be428; -startAppearGo = 0x80171bb8; -updatePane = 0x8013ebf0; -updateBoundPane = 0x80154c98; -updateBlendPane = 0x8017900c; -movePane = 0x8013eeb0; -processAppearCoin = 0x80146104; -startAppearCoin = 0x8014c7e8; -processDownCoin = 0x801466f0; -initModelData = 0x801b1c34; ObjHitCheck_CheckActorsHit = 0x8021b900; ObjHitCheck_DetectHit = 0x8021c29c; MapObjBase_RemoveMapCollision = 0x801b1130; @@ -140,29 +93,16 @@ CLBPolarToCross = 0x800289b4; ModelWaterManager_EmitRequest = 0x8027fc84; WaterEmitInfo_Create = 0x802806f4; MapObjBase_EmitSplash = 0x801b8d34; +Mario_Trample = 0x802432b8; +Mario_SetAnimation = 0x80247670; +Mario_SetStatusToJumping = 0x802543a0; +Application_Init = 0x802a73c4; +EasyEmitParticle = 0x8000e3a4; +StartSoundActorWithInfo = 0x800185f4; +Camera_CalcFinalPosAndAt = 0x80023950; +Camera_UpdateGameCamera = 0x800234e8; +movePane = 0x8013eeb0; cosf = 0x8033c610; sinf = 0x8033c630; sqrtf = 0x800067e8; -PSMTXCopy = 0x803499bc; -marioCanTake = 0x80243550; -marioStartVoice = 0x8028537c; -getModel = 0x80218a50; -showAllShapePacket = 0x80235728; -makeObjAppeared = 0x801b0430; -startMapObjAnim = 0x801b09d4; -startSoundSystemSE = 0x80018864; -setBuffer = 0x802c6164; -createMActor = 0x8021cc74; -startAnimation = 0x80239e64; -setBTP = 0x80238898; -setUpMapCollision = 0x801b238c; -changeCollision = 0x8018e5e0; -startJAIStream = 0x80309504; -loadToMainRAM = 0x802ea8fc; -loadToARAM = 0x802ebba0; -loadModelData = 0x8021d5a4; -loadBCKDataBase = 0x802e8ca4; -DVDOpen = 0x8034b914; -DVDPrepareStreamASync = 0x8034beb0; -DVDStopStreamAtEndAsync = 0x8034de6c; -DVDCancelStreamAsync = 0x8034ddb0; \ No newline at end of file +PSMTXCopy = 0x803499bc; \ No newline at end of file diff --git a/smsmulti.c b/smsmulti.c new file mode 100644 index 0000000..5cfa07e --- /dev/null +++ b/smsmulti.c @@ -0,0 +1,1039 @@ +/* Super Mario Sunshine Multiplayer */ + +#include +#include +#include +#include +#include +#include "sms.h" + +#define NUM_PLAYERS 2 + +volatile const char* CREDITS = "Super Mario Sunshine Multiplayer https://egaddsworkshop.com/"; + +const float PI = 3.14159265f; +const int MARIO_COLSIZE = 6; +const float MULTI_MAXDISTANCE = 4000.0f; +const char* MARIO_EMITTER = "/barrel.prm"; +const float MARIO_TRAMPLEHEIGHT = 60.0f; + +const int32_t ENEMYMARIO_VTABLE[0x3b]; +const int32_t EMARIO_VTABLE[0x45]; + +//static J2DTextBox textbox; +//static char* info; + +int LimitDistance; + +MarioActor* Players[NUM_PLAYERS]; +EMario* EMarios[NUM_PLAYERS]; + +Yoshi* CurrentYoshi; +int IsPlaying[NUM_PLAYERS]; +int HeldPlayer[NUM_PLAYERS]; +int MarioOnYoshi[NUM_PLAYERS]; +WaterEmitInfo* ShadowMarioEmitters[NUM_PLAYERS]; +int WaterSprayTimer[NUM_PLAYERS]; + +int Started; + +int16_t CameraPhi; +int16_t CameraTheta; +int CameraModeTimer; +int CameraMode; + +int playerLoopIndex; + +int multimode; + +//int bBx, bBy, mX, mY, cX, cY; // Background x, y - MENU x, y - Cursor x,y +//int tX, tY; // TextBox x,y +//int isMenuEnabled, menuTimer, isExit, exitTimer, repTimer, chooseTimer, hasChosen; + +//const char *optAry[] = {"Enabled", "Disabled"}; +//int opt, boolDis; + +//float camDis; + +Vector cameraGuide; +Vector playerAverage; +Vector difplayerAverage; + +int OnUpdate(MarDirector* director) { + int (*GameUpdate)(MarDirector* director) = GetObjectFunction(director, Director_GameUpdate); + + Players[0] = *gpMarioAddress; + if (Players[0] == 0 || gpMarioAddress == 0) + return GameUpdate(director); + + int realcount = 1; + difplayerAverage.x = playerAverage.x; + difplayerAverage.y = playerAverage.y; + difplayerAverage.z = playerAverage.z; + playerAverage.x = Players[0]->position.x; + playerAverage.y = Players[0]->position.y; + playerAverage.z = Players[0]->position.z; + + if (!Started) + CameraPhi = Players[0]->roty + 0x7FFF; + for (int i = 1; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + + if (IsPlaying[i] && ((EnemyMario*)Players[i])->emariohealth > 0){ + realcount++; + playerAverage.x += Players[i]->position.x; + playerAverage.y += Players[i]->position.y; + playerAverage.z += Players[i]->position.z; + } + + if (!Started){ + if (IsPlaying[i]) + { + Players[i]->position = Players[0]->position; + Players[i]->position.y += 180 * i; + Camera_AddMultiPlayer(*gpCamera, &(Players[i]->position)); + } + + Players[i]->gamepad = &(GamePads[i]); + ((EnemyMario*)Players[i])->emarioflags = 0x0082; //Show healthbar and visible shadow mario + ((EnemyMario*)Players[i])->emariodamage = 0x000D; //Doesnt hurt mario + + GamePadTwo->u2 = 2; + GamePadThree->u2 = 3; + Players[i]->colsettings = 0x80000001; //item collision + EMarios[i]->colsettings = 0x80000001; + + *(int*)((int)Players[i] + 0x388) = 0x0000FFFF; //Pollution collision + } + if (!IsPlaying[i] && (Controllers[i].buttons & PRESS_START)){ + Players[i]->flags = MARIOFLAG_ALIVE; + Players[i]->position = Players[0]->position; + Players[i]->position.y += 180; + Camera_AddMultiPlayer(*gpCamera, &(Players[i]->position)); + + IsPlaying[i] = 1; + } + + if (((EnemyMario*)Players[i])->emariohealth <= 0 || ((MarioActor*)Players[i])->flags & MARIOFLAG_GAMEOVER){ + SetMarioStatus(Players[i], STATE_STUNNED, 0, 0); + Camera_RemoveMultiPlayer(*gpCamera, &(Players[i]->position)); + ((EnemyMario*)Players[i])->emariohealth = 0; + } + + int rstate = Players[i]->status & 0xFFFFFFF0; + if (Players[0]->flags & MARIOFLAG_HASFLUDD){ + if ((rstate == STATE_IDLE || rstate == STATE_RUNNING || rstate == STATE_JUMP || rstate == STATE_JUMPSIDE) && rstate != STATE_JUMPSPIN){ + WaterSprayTimer[i] = 30; + if (Controllers[i].buttons & PRESS_R){ + MapObjBase_EmitSplash(Players[i]); + SetMarioStatus(Players[i], STATE_JUMPSPIN1, 0, 0); + Players[i]->speedy = 40.0f; + WaterSprayTimer[i] = 0; + } + } + else if (rstate == STATE_JUMPSPIN && Controllers[i].buttons & PRESS_R){ + MapObjBase_EmitSplash(Players[i]); + WaterSprayTimer[i] = 0; + } + + if (rstate == STATE_JUMPSPIN && WaterSprayTimer[i] < 30){ + ShadowMarioEmitters[i]->position = Players[i]->position; + ShadowMarioEmitters[i]->u3 = 0.35f; + ShadowMarioEmitters[i]->u5 = 5.0f; + ShadowMarioEmitters[i]->u7 = 5.0f; + ShadowMarioEmitters[i]->u9 = 5.0f; + ShadowMarioEmitters[i]->u11 = 0; + ShadowMarioEmitters[i]->count = 16; + ModelWaterManager_EmitRequest(*gpModelWaterManager, ShadowMarioEmitters[i]); + + WaterSprayTimer[i]++; + } + } + + if (!(Players[0]->status & STATE_CUTSCENE) && Players[i]->status & STATE_CUTSCENE) + Players[i]->status = Players[0]->status; + + if (IsPlaying[i] && LimitDistance && ((EnemyMario*)Players[i])->emariohealth > 0){ + float xdist = Players[i]->position.x - Players[0]->position.x; + float zdist = Players[i]->position.z - Players[0]->position.z; + float yplanedist = sqrtf((xdist * xdist) + (zdist * zdist)); + if (yplanedist > MULTI_MAXDISTANCE){ + ParticleManager_EmitWithRotate(*gpMarioParticleManager, 0x15, &Players[i]->position, 0x4000, 0, 0, 0, 0); + Players[i]->position.y += 60; + ParticleManager_EmitWithRotate(*gpMarioParticleManager, 0x15, &Players[i]->position, 0x4000, 0, 0, 0, 0); + Players[i]->position = Players[0]->position; + ParticleManager_EmitWithRotate(*gpMarioParticleManager, 0x15, &Players[i]->position, 0x4000, 0, 0, 0, 0); + Players[i]->position.y += 60; + ParticleManager_EmitWithRotate(*gpMarioParticleManager, 0x15, &Players[i]->position, 0x4000, 0, 0, 0, 0); + Players[i]->position.y += 240; + Players[i]->speedy = 0.0f; + } + } + } + + //if (Started) + //{ + // checkMultiplayerMenu(); // Check if the multiplayer menu is active :) + //} + //else { //When not started, add mario and cursor to camera + if (!Started){ + Camera_AddMultiPlayer(*gpCamera, &(Players[0]->position)); + Camera_AddMultiPlayer(*gpCamera, &cameraGuide); + } + + playerAverage.x /= (float)realcount; + playerAverage.y /= (float)realcount; + playerAverage.z /= (float)realcount; + difplayerAverage.x = playerAverage.x - difplayerAverage.x; + difplayerAverage.y = playerAverage.y - difplayerAverage.y; + difplayerAverage.z = playerAverage.z - difplayerAverage.z; + cameraGuide.x = playerAverage.x; + cameraGuide.y = playerAverage.y; + cameraGuide.z = playerAverage.z; + + for (int i = 0; i < NUM_PLAYERS; i++) + { + if (Players[i] == 0) + continue; + if (!IsPlaying[i]) + continue; + //Camera controls + if (Controllers[i].buttons & PRESS_L && (!(Players[i]->status & (STATE_AIRBORN | STATE_DOJUMP))) || (Players[i]->flags & 0x3000)) + CameraPhi = Players[i]->roty + 0x7FFF; + + if (CameraModeTimer == 0){ + if (Controllers[i].buttons & PRESS_DL){ + CameraMode++; + CameraModeTimer = 30; + } + else if (Controllers[i].buttons & PRESS_DR){ + CameraMode--; + CameraModeTimer = 30; + } + } + + CameraTheta += Controllers[i].ranalogy * 2; + CameraPhi += Controllers[i].ranalogx * 4; + } + if (CameraTheta > 6000) + CameraTheta = 6000; + if (CameraTheta < -1000) + CameraTheta = -1000; + if (CameraModeTimer > 0) + CameraModeTimer--; + if (CameraMode > 3) + CameraMode = 0; + if (CameraMode < 0) + CameraMode = 2; + + Started = 1; + + return GameUpdate(director); +} + +/* +void OnDraw2D(J2DOrthoGraph* graphics) +{ + snprintf(info, 128, "\33CC[FFFFFFFF]\33GC[FF0000FF]Distance Limit \n%s \n \nCamera Distance \n%f", + optAry[opt], camDis); + J2DTextBox_SetString(&textbox, info); + + J2DGrafContext_Setup2D((J2DGrafContext*)graphics); //Run replaced branch + + J2DScreen_Draw((J2DScreen*)&textbox, tX, tY, (J2DGrafContext*)graphics, 0x81); + GXSetScissor(0, 0, 0x0280, 0x01c0); + +} +*/ + +void OnSetup(MarDirector* director) +{ + playerLoopIndex = 0; + + HeldPlayer[0] = 0; + IsPlaying[0] = 1; + LimitDistance = 1; + + CameraPhi = 0; + CameraTheta = 0; + CameraModeTimer = 0; + CameraMode = 0; + + cameraGuide.x = cameraGuide.y = cameraGuide.z = 0.0f; + playerAverage.x = playerAverage.y = playerAverage.z = 0.0f; + difplayerAverage.x = difplayerAverage.y = difplayerAverage.z = 0.0f; + + //assembly edit to allow shadow mario to slide on water + int* address = 0x8024fc98; + *address = 0x60000000; + //and to disable loading params that arent needed and crash on console + address = 0x8004370c; + *address = 0x60000000; + + //Run replaced branch + MarDirector_SetupObjects(director); + + EMarios[1] = (EMario*)SearchObjByRef("MarMP2"); + if (NUM_PLAYERS > 2) + EMarios[2] = (EMario*)SearchObjByRef("MarMP3"); + if (NUM_PLAYERS > 3) + EMarios[3] = (EMario*)SearchObjByRef("MarMP4"); + + MarioOnYoshi[0] = 0; + for (int i = 1; i < NUM_PLAYERS; i++){ + Players[i] = 0; + HeldPlayer[i] = 0; //Clear to 0 for real hw + MarioOnYoshi[i] = 0; + ShadowMarioEmitters[i] = 0; + WaterSprayTimer[i] = 0; + + if (EMarios[i] == 0) + continue; + HeldPlayer[i] = 0; + + Players[i] = (MarioActor*)(EMarios[i]->enemymario); //Get EnemyMario + Players[i]->Type = ENEMYMARIO_VTABLE; + EMarios[i]->Type = EMARIO_VTABLE; + + Players[i]->yoshi = CurrentYoshi; //Add yoshi, prevent some crashes on hw + + //Mario_InitValues(Players[i]); + + Players[i]->position.x = 10000; + Players[i]->position.y = 10000; + Players[i]->position.y = -10000; + Players[i]->flags |= MARIOFLAG_INVISIBLE | MARIOFLAG_GONE; + Players[i]->status = 0x0000133f; + + ((EnemyMario*)Players[i])->emariohealth = 0x40; + + Players[i]->colarray = malloc(sizeof(void*) * MARIO_COLSIZE); + + //Give shadow mario fludd to prevent yoshi crash... + WaterGun* gun = malloc(7632); //fludd is fat + if (gun != 0){ + WaterGun_Create(gun, Players[i]); + WaterGun_Init(gun); + Players[i]->watergun = gun; + } + + //Let shadow mario make water + ShadowMarioEmitters[i] = malloc(sizeof(WaterEmitInfo)); + if (ShadowMarioEmitters[i] != 0) + WaterEmitInfo_Create(ShadowMarioEmitters[i], MARIO_EMITTER); + } + + /* + int* menuTrans = *TGCCConsole2 + GFX_OFF + 0xCC; + int* blackTrans = *TGCCConsole2 + GFX_OFF - 0x1B0 + 0xCC; + int* sMarioCTrans = *TGCCConsole2 + GFX_OFF + 0x1B0 + 0xCC; + movePane(*TGCCConsole2 + GFX_OFF - 0x1B0, bBx, bBy); // Black background + movePane(*TGCCConsole2 + GFX_OFF, mX + 170, mY + 50); // MENU Text (Add 0x1B0 for next entry) + movePane(*TGCCConsole2 + GFX_OFF + 0x1B0, 50, 150); // Shadow Mario Cursor + *menuTrans = 0x00000000; + *blackTrans = 0x00000000; + *sMarioCTrans = 0x00000000; + + JUTRect rect; + JUTRect_Set(&rect, 0, 0, 512, 512); + J2DTextBox_Create(&textbox, 0, &rect, GameFont, GameStrTable, 2, 0); + + tX = 100; + tY = -35; + + boolDis = 1; + */ + + Started = 0; +} + +//Should only really be used for initializing +void OnInitApp(void* application){ + Application_Init(application); + + if (CalcKeyCode(CREDITS) != 9397) + *(int*)MarDirector_SetupObjects = 0x4e800020; + + //Disable default multiplayer camera + *(int*)0x80276b44 = 0x60000000; + *(int*)0x800397f8 = 0x60000000; + + //info = (char*)malloc(128); + + //camDis = 0.667f; + multimode = 1; + for (int i = 0; i < NUM_PLAYERS; i++) + IsPlaying[i] = 0; +} + +void SetMarioAddresses(MarioActor* mario){ + *gpMarioAddress = mario; + *gpMarioPos = (int)mario + 0x10; + *gpMarioAngleX = (int)mario + 0x94; + *gpMarioAngleY = (int)mario + 0x96; + *gpMarioAngleZ = (int)mario + 0x98; + *gpMarioSpeedX = (int)mario + 0xA4; + *gpMarioSpeedY = (int)mario + 0xA8; + *gpMarioSpeedZ = (int)mario + 0xAC; +} + +void EMarioControl(MarioActor* enemymario, void* drama, void* graphics){ + for (int i = 0; i < NUM_PLAYERS; i++) + { + if (Players[i] == 0) + continue; + + if (enemymario == Players[i] && IsPlaying[i]) + return Mario_CheckController(enemymario, drama, graphics); + } +} + +void MarioSendMessage(HitActor* sender, unsigned long message){ + //if (CurrentCollision == 0) + // return 0; + + MarioActor* closest = 0; + float distance = 1000000; + for (int i = 0; i < NUM_PLAYERS; i++) + { + if (Players[i] == 0) + continue; + + Vector dif = Players[i]->position; + Vector_Subtract(&dif, &(sender->position)); + float magnitude = Vector_Magnitude(&dif); + if (magnitude < distance) + { + closest = Players[i]; + distance = magnitude; + } + } + if (closest == 0) + return; + + int (*receiveMessage)(HitActor* t, HitActor* s, unsigned long m) = GetObjectFunction(closest, HitActor_ReceiveMessage); + if (receiveMessage(closest, sender, message) == 0) + return 0; + else + return 1; +} + +void EMarioDamageExec(HitActor* this, HitActor* other, int u1, int u2, int u3, float f1, int u4, float f2, short u5) +{ + for (int i = 1; i < NUM_PLAYERS; i++) + if (Players[i] == this && ((EnemyMario*)Players[i])->emariohealth <= 0) + return; + + Mario_DamageExec(this, other, u1, u2, u3, f1, u4, f2, u5); +} + +void EMarioReceiveMessage(HitActor* this, HitActor* sender, unsigned long message){ + for (int i = 1; i < NUM_PLAYERS; i++) + if (Players[i] == this && ((EnemyMario*)Players[i])->emariohealth <= 0) + return; + + Mario_ReceiveMessage(this, sender, message); +} + +void EMarioPlayerControl(HitActor* this, void* drama, void* graphics){ + Mario_PlayerControl(this, drama, graphics); +} + +int IsMultiplayerMap(){ + if (*ChangeScenario == 58 || *ChangeScenario == 30 || (*ChangeScenario == 3 && *ChangeEpisode == 5)) + return 0; + return multimode; +} + +void OnMarioIncHP(HitActor* mario, int n){ + if (mario == Players[0]) + Mario_IncHP(mario, n); + else + { + EnemyMario* enemymario = ((EnemyMario*)mario); + if (enemymario->emariohealth < 0x40) + enemymario->emariohealth += 8 * n; + enemymario->hpmetertimer = 0x400; + } +} +void OnMarioDecHP(HitActor* mario, int n){ + if (mario == Players[0]) + Mario_DecHP(mario, n); + else + { + EnemyMario* enemymario = ((EnemyMario*)mario); + if (enemymario->emariohealth > 0) + enemymario->emariohealth -= 8 * n; + enemymario->hpmetertimer = 0x400; + } +} + +void RemoveObjectFromColArray(HitActor* actor, HitActor* col){ + if (actor->colcount == 0) + return; + + int i = actor->colcount - 1; + while (i >= 0){ + if (actor->colarray[i] == col) + break; + i--; + } + actor->colcount--; + if (i == actor->colcount){ + return; + } + while (i < actor->colcount) + actor->colarray[i] = actor->colarray[++i]; +} + +void BounceMario(MarioActor* mario1, MarioActor* mario2){ + int rstatus = mario1->status & 0xFFFFFFF0; + if (rstatus != STATE_JUMPSPIN && rstatus != STATE_JUMP && rstatus != STATE_JUMPSIDE && rstatus != 0x02000890) + { + if (rstatus == 0x00800230 || rstatus == 0x008008A0){ + //knock over other mario + if (mario2->status & 0xFFFFFFF0 != 0x000024D0) + SetMarioStatus(mario2, 0x000208b0, 0, 0); + } + return; + } + + Vector temp; + temp.x = 0.5f; + temp.y = 0.5f; + temp.z = 0.5f; + + mario1->speedy = 300.0f; + Mario_SetAnimation(mario1, 211, 1.0f); //triple trample animation + SetMarioStatus(mario1, 0x02000890, 0, 0); + Mario_SetStatusToJumping(mario1, 0x02000890, 0); + EasyEmitParticle(8, &(mario1->position), mario1, &temp); + EasyEmitParticle(9, &(mario1->position), mario1, &temp); + StartSoundActorWithInfo(6168, &(mario1->position), 0, 0.0f, 3, 0, 0, 0, 4); + + rstatus = mario2->status & 0xFFFFFFF0; + if (rstatus == STATE_JUMPSPIN || rstatus == STATE_JUMP || rstatus == STATE_JUMPSIDE) + { + mario2->speedy = -mario1->speedy; + } + + RemoveObjectFromColArray(mario1, mario2); +} + +void OnCheckActorsHit(void* hitcheckobj){ + //Set up EMario bounds + for (int i = 1; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + + EMarios[i]->bound1 = 80.0f; //Manually + EMarios[i]->bound2 = 50.0f; + EMarios[i]->bound3 = 42.0f; + EMarios[i]->bound4 = 130.0f; + EMarios[i]->bound5 = 215.880554f; + EMarios[i]->colflags = 0xFC000000; + } + + playerLoopIndex = 0; + + //Run collision check + ObjHitCheck_CheckActorsHit(hitcheckobj); + + for (int i = 1; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + + //Give EnemyMario EMario's collision data + Players[i]->colcount = EMarios[i]->colcount; + Players[i]->colarraysize = EMarios[i]->colarraysize; + for (int j = 0; j < Players[i]->colcount; j++) + Players[i]->colarray[j] = EMarios[i]->colarray[j]; + + //Remove held players from collision + if (HeldPlayer[i]) + RemoveObjectFromColArray(Players[i], HeldPlayer[i]); + } + + if (Started){ + //Add in some trample for fun + for (int i = 0; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if (Players[i]->speedy > 0) + continue; + if ((int)Players[i]->colarray & 0x80000000 == 0) + continue; + for (int j = 0; j < Players[i]->colcount; j++){ + if (GetType((Players[i]->colarray[j])) == ENEMYMARIO_VTABLE || GetType((Players[i]->colarray[j])) == 0x803dd660){ + if (Players[i]->position.y > ((MarioActor*)Players[i]->colarray[j])->position.y + MARIO_TRAMPLEHEIGHT){ + BounceMario(Players[i], (MarioActor*)(Players[i]->colarray[j])); + } + } + } + } + } +} + +void OnDetectHit(void* hitcheckobj, HitActor* one, HitActor* two){ + EMario* held = 0; + for (int i = 1; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if (Players[i] == HeldPlayer[0]) + held = EMarios[i]; + } + + if (one == held && two == Players[0]) + return; + if (two == held && one == Players[0]) + return; + + ObjHitCheck_DetectHit(hitcheckobj, one, two); + + if (Started){ + //Hacky have things direct collide with shadowmario + for (int i = 1; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if (one->colcount >= 1 && one->colarray[one->colcount - 1] == EMarios[i]) + one->colarray[one->colcount - 1] = Players[i]; + if (two->colcount >= 1 && two->colarray[two->colcount - 1] == EMarios[i]) + two->colarray[two->colcount - 1] = Players[i]; + } + } +} + +void OnMarioHeld(MarioActor* mario, int a2, int a3, int a4){ + MarioActor* other = 0; + + __asm__ ("addi %0,29,0" //Forces compiler to stop overwriting r31 + : "=r" (other) + : + : "r29"); + + if (Started) + { + SetMarioStatus(mario, a2, a3, a4); + + for (int i = 0; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if (Players[i] == other) + HeldPlayer[i] = mario; + } + } +} + +//I placed branch right after r3 is set to the thrown object. +//r31 holds mario's address +void OnMarioThrow(HitActor* thrownobject){ + MarioActor* mario = 0; + + __asm__ ("addi %0,31,0" //Forces compiler to stop overwriting r31 + : "=r" (mario) + : + : "r31"); + + int (*receiveMessage)(HitActor* t, HitActor* s, unsigned long m) = GetObjectFunction(thrownobject, HitActor_ReceiveMessage); + + + SetMarioAddresses(mario); + + receiveMessage(thrownobject, mario, 7); + + for (int i = 0; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if (thrownobject == Players[i]){ + Vector newPos = **gpMarioPos; + float angle = 2.0f * PI * **gpMarioAngleY / 65535.0f; + newPos.x += sinf(angle) * 120.0f; + newPos.z += cosf(angle) * 120.0f; + Players[i]->position = newPos; + + Players[i]->status = STATE_DIVE; + Players[i]->roty = **gpMarioAngleY; + + float speed = sqrtf((**gpMarioSpeedX * **gpMarioSpeedX) + (**gpMarioSpeedZ * **gpMarioSpeedZ)); + SetMarioVelocity(Players[i], 40.0f + speed); + Players[i]->speedy = 75.0f; + } + if (HeldPlayer[i] == thrownobject) + HeldPlayer[i] = 0; + } + + SetMarioAddresses(Players[0]); +} + +//Same for OnMarioDrop +void OnMarioDrop(HitActor* thrownobject){ + MarioActor* mario = 0; + + __asm__ ("addi %0,31,0" //Forces compiler to stop overwriting r31 + : "=r" (mario) + : + : "r31"); + + int (*receiveMessage)(HitActor* t, HitActor* s, unsigned long m) = GetObjectFunction(thrownobject, HitActor_ReceiveMessage); + + SetMarioAddresses(mario); + + receiveMessage(thrownobject, mario, 6); + + SetMarioAddresses(Players[0]); +} + +void OnObjectTouchMario(HitActor* this, HitActor* other) +{ + //Block certain objects from touching shadow mario + if ((GetType(other) == TYPE_ENEMYMARIO || GetType(other) == TYPE_EMARIO) && + GetType(this) == TYPE_ITEMNOZZLE) + return; + + //Run replaced branch + HitActor* (*TouchPlayer)(void* t, void* o) = GetObjectFunction(this, HitActor_TouchPlayer); + TouchPlayer((void*)this, (void*)other); +} + +void OnChangeNozzle(HitActor* this, int nozzletype, int nozzleslot){ + int (*touchPlayer)(HitActor* t, HitActor* o) = GetObjectFunction(this, HitActor_TouchPlayer); + + //If this is shadow mario, ignore + for (int i = 1; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if (this == Players[i]->watergun) + return; + } + + WaterGun_ChangeNozzle(this, nozzletype, nozzleslot); +} + +void OnRideYoshi(Yoshi* yoshi){ + MarioActor* mario = 0; + + __asm__ ("addi %0,31,0" //Forces compiler to stop overwriting r31 + : "=r" (mario) + : + : "r31"); + + for (int i = 0; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if (Players[i] == mario) + MarioOnYoshi[i] = 1; + } + yoshi->mario = mario; + + SetMarioAddresses(mario); + + Yoshi_Ride(yoshi); + + SetMarioAddresses(Players[0]); +} + +void OnDismountYoshi(MarioActor* mario){ + for (int i = 0; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if (Players[i] == mario) + MarioOnYoshi[i] = 0; + } + + SetMarioAddresses(mario); + + Mario_GetOffYoshi(mario); + + SetMarioAddresses(Players[0]); +} + +int IsOnYoshi(MarioActor* mario){ + for (int i = 0; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if (mario == Players[i] && MarioOnYoshi[i]) + return 1; + } + return 0; +} + +//Doesnt get more hacky than this +//The way its written: if yoshi has mario on him, then all marios must be on yoshi +//This should fix that +int IsOnYoshi2(MarioActor* mario){ + MarioActor* pmario1 = 0; + MarioActor* pmario2 = 0; + MarioActor* pmario3 = 0; + + __asm__ ("addi %0,31,0\n\t" //Forces compiler to stop overwriting possible mario registers + "addi %1,30,0\n\t" + "addi %2,29,0" + : "=r" (pmario1), "=r" (pmario2), "=r" (pmario3) + : + : "r29", "r30", "r31"); + + for (int i = 0; i < NUM_PLAYERS; i++){ + if (Players[i] == 0) + continue; + if ((pmario1 == Players[i] || pmario2 == Players[i] || pmario3 == Players[i]) && MarioOnYoshi[i]) + return 1; + } + return 0; +} + +void OnWaterGunUpdate(MarioActor* mario){ + if (mario == Players[0]) + Mario_WaterGunUpdate(mario); +} + +//Normally converts polar coordinates to cartesian +void CalcMultiplayerCameraPos(Vector* center, Vector* out, float rho, uint16_t theta ,uint16_t phi){ + switch (CameraMode){ + case 2: rho *= 0.667f; break; + case 1: rho *= 1.5f; break; + } + + CLBPolarToCross(center, out, rho, CameraTheta + theta, CameraPhi + phi); +} + +int* CheckOtherObjectCollisions(volatile int* next){ //ugh + volatile void* res = 0; + int donext = 0; + + do { + res = (void*)EMarios[++playerLoopIndex]; + } while (res == 0 && playerLoopIndex < NUM_PLAYERS); //Loop through players, but dont allow non existent ones to pass + + if (playerLoopIndex >= NUM_PLAYERS){ //If end of list reached, reset list and continue + playerLoopIndex = 0; + donext = 1; + res = (void*)Players[0]; + + __asm__ volatile ( //continue asm + "lwz 0,0(%0)\n" + "\tstw 0,0xa8(1)\n" + : "=r" (next) + : + : "r0", "r3", "r4", "r5", "r30"); + } + __asm__ volatile ( //set current mario + "addi 31,%0,0\n" + : + : "r" (res) + : "r0", "r3", "r4", "r5", "r30"); //don't clobber r31 so it stays changed + return next; +} +void CheckOtherObjectCollisions2(){ //ugh + if (playerLoopIndex == 0) + { + __asm__ volatile ( //Only reset count on first loop + "sth 0, 0x0048(3)\n" + : + : + : "r0", "r1", "r2", "r3", "r4"); + } +} + +void ChangeAllPlayerStatus(MarioActor* mario, uint32_t u1, uint32_t u2, int u3){ + for (int i = 1; i < NUM_PLAYERS; i++) + if (Players[i] != 0) + SetMarioStatus(Players[i], u1, u2, u3); + SetMarioStatus(mario, u1, u2, u3); +} +Yoshi* CreateYoshi(int size){ + CurrentYoshi = malloc(size); + return CurrentYoshi; +} + +/* +int checkMultiplayerMenu() +{ + int* menuTrans = *TGCCConsole2 + GFX_OFF + 0xCC; + int* blackTrans = *TGCCConsole2 + GFX_OFF - 0x1B0 + 0xCC; + int* sMarioCTrans = *TGCCConsole2 + GFX_OFF + 0x1B0 + 0xCC; + //*menuTrans -= 0x10000000; + //*blackTrans -= 0x10000000; + + if (isExit) // exiting timer + { + exitTimer++; + } + + if (!isMenuEnabled) // Controls re-pause timer + { + repTimer++; + tX = 0xffff; + tY = 0xffff; + } + + if (isMenuEnabled) + { + if (hasChosen) + { + chooseTimer++; + if (chooseTimer >= 15) + { + hasChosen = 0; + chooseTimer = 0; + } + } + + if (ControllerOne->buttons & PRESS_DD) + { + movePane(*TGCCConsole2 + GFX_OFF + 0x1B0, 50, 150 + 60); + boolDis = 0; + } + if (ControllerOne->buttons & PRESS_DU) + { + movePane(*TGCCConsole2 + GFX_OFF + 0x1B0, 50, 150); + boolDis = 1; + } + if (ControllerOne->buttons & PRESS_A && boolDis && !hasChosen) + { + if (opt == 0) + { + opt = 1; + LimitDistance = 0; + } + else + { + opt = 0; + LimitDistance = 1; + } + + hasChosen = 1; + } + + if (ControllerOne->buttons & PRESS_A && !boolDis && !hasChosen) + { + camDis += 0.5f; + hasChosen = 1; + } + + if (ControllerOne->buttons & PRESS_B && !boolDis && !hasChosen) + { + camDis -= 0.5f; + hasChosen = 1; + } + tX = 100; + tY = -35; + *menuTrans += 0x10000000; + *blackTrans += 0x10000000; + *sMarioCTrans += 0x10000000; + menuTimer++; + if (menuTimer >= 5) *blackTrans = 0x60000000; + if (menuTimer >= 10) + { + *menuTrans = 0xf0000000; + *sMarioCTrans = 0xf0000000; + } + } + + if (ControllerOne->buttons & PRESS_Y) + { + if (!isMenuEnabled && repTimer >= 15) + { + isMenuEnabled = 1; + } + if (isMenuEnabled) + { + isExit = 1; + menuTimer = 0; + tX = 0xffff; + tY = 0xffff; + if (isExit && exitTimer >= 15) + { + while (*menuTrans > 0) + { + *menuTrans -= 0x10000000; + *blackTrans -= 0x10000000; + *sMarioCTrans -= 0x10000000; + } + + if (*menuTrans <= 0) + { + *menuTrans = 0x00000000; + *blackTrans = 0x00000000; + *sMarioCTrans = 0x00000000; + isMenuEnabled = 0; + isExit = 0; + exitTimer = 0; + repTimer = 0; + } + } + } + } +} +*/ + +// Generated by wxHexEditor // +const int32_t ENEMYMARIO_VTABLE[0x3b] = { + 0x00000000, 0x00000000, + 0x8003F738, 0x80007D70, + 0x80276BD0, 0x802FA6F4, + 0x80276ADC, 0x802FA6FC, + 0x8003F814, 0x00000000, + 0x00000000, 0x800452D0, + 0x803370C0, 0x8033720C, + 0x80337214, 0x8033721C, + 0x80337220, 0x80337228, + 0x8033722C, 0x80337230, + 0x80337234, 0x80007FA8, + 0x80007FA0, 0x80007F98, + 0x80007F90, 0x80007F88, + 0x80007F80, 0x803370E0, + 0x803370E8, 0x803370EC, + 0x803370F4, 0x803370F8, + 0x80337100, 0x80337104, + 0x802F7004, 0x802F7020, + 0x802F703C, 0x802F7058, + 0x802F7074, 0x802F7090, + 0x80282AF4, 0x80247E50, + 0x80007CFC, 0x80255A8C, + 0x80007D60, 0x00000000, + 0x00000000, 0x800452D8, + 0x80044CA4, 0x800406CC, + EMarioControl, EMarioPlayerControl, + 0x8004440C, 0x80244520, + 0x80280FE8, EMarioDamageExec, + 0x802853F8, 0x8024D17C, + 0x80042E48 }; + + // Generated by wxHexEditor // +const int32_t EMARIO_VTABLE[0x45] = { + 0x00000000, 0x00000000, + 0x80039BF4, 0x80007D70, + 0x80039810, 0x802FA6F4, + 0x800397B4, 0x802FA6FC, + 0x80039148, 0x00000000, + 0x00000000, 0x80039F5C, + 0x803370C0, 0x8033720C, + 0x80337214, 0x8033721C, + 0x80337220, 0x80337228, + 0x8033722C, 0x80337230, + 0x80337234, 0x80007FA8, + 0x80007FA0, 0x80007F98, + 0x80007F90, 0x80007F88, + 0x80007F80, 0x803370E0, + 0x803370E8, 0x803370EC, + 0x803370F4, 0x803370F8, + 0x80337100, 0x80337104, + 0x802F7004, 0x802F7020, + 0x802F703C, 0x802F7058, + 0x802F7074, 0x802F7090, + EMarioReceiveMessage, 0x80217CA8, + 0x80007CFC, 0x80007D40, + 0x80007D60, 0x80218CC0, + 0x80218A48, 0x80039600, + 0x8003BF44, 0x802182F0, + 0x80218414, 0x802184DC, + 0x8021818C, 0x80218020, + 0x80217FC8, 0x80217DE4, + 0x80218344, 0x8003952C, + 0x80217D88, 0x80217D6C, + 0x80217CC8, 0x80217B30, + 0x80217990, 0x8003C460, + 0x8003BE2C, 0x8003BCE0, + 0x8003BF38, 0x80007DFC, + 0x80007E04 };