From 8cbf7e0bb85adedf74eddd2f32d20fcf22face6d Mon Sep 17 00:00:00 2001 From: Treeki Date: Mon, 28 Mar 2011 00:09:19 +0200 Subject: added tileset Pa1/2/3 swap hack --- NewerProject.yaml | 1 + include/game.h | 218 +++++++++++++++++++++++++++++++++++++++++++++++++-- kamek_ntsc.x | 25 ++++++ kamek_ntsc2.x | 25 ++++++ kamek_pal.x | 25 ++++++ kamek_pal2.x | 25 ++++++ src/tilesetfixer.cpp | 94 ++++++++++++++++++++++ tilesetfixer.yaml | 9 +++ 8 files changed, 416 insertions(+), 6 deletions(-) create mode 100644 src/tilesetfixer.cpp create mode 100644 tilesetfixer.yaml diff --git a/NewerProject.yaml b/NewerProject.yaml index ffe9cf8..20a7d9a 100644 --- a/NewerProject.yaml +++ b/NewerProject.yaml @@ -12,6 +12,7 @@ modules: # - processed/heapbar.yaml - processed/tilegod.yaml - processed/linegod.yaml + - processed/tilesetfixer.yaml # - processed/msgbox.yaml # - processed/replay.yaml diff --git a/include/game.h b/include/game.h index cb567f3..b26842b 100755 --- a/include/game.h +++ b/include/game.h @@ -5,6 +5,7 @@ #include #include #include +#include extern "C" { @@ -34,6 +35,7 @@ inline void *GetDVDClass2() { } void *DVD_GetFile(void *dvdclass2, const char *arc, const char *file); +void *DVD_GetFile(void *dvdclass2, const char *arc, const char *file, u32 *length); extern int Player_Active[4]; @@ -288,11 +290,13 @@ namespace ut { // I don't need the methods anyway. class LinkListNode { + public: LinkListNode *next; LinkListNode *prev; }; class LinkList { + public: int count; LinkListNode initialNode; }; @@ -300,6 +304,7 @@ namespace ut { class Color : public GXColor { }; class Rect { + public: f32 left; f32 top; f32 right; @@ -457,6 +462,45 @@ namespace lyt { u8 paneIsOwnedBySomeoneElse; u8 _D7; }; + + class TextBox : public Pane { + public: + TextBox(void *, void *); // todo: TextBox((res::TextBox const *,ResBlockSet const &)) + ~TextBox(); + + void *GetRuntimeTypeInfo() const; + + void DrawSelf(const DrawInfo &info); + + ut::Color GetVtxColor(ulong id) const; + void SetVtxColor(ulong id, ut::Color color); + uchar GetVtxColorElement(ulong id) const; + void SetVtxColorElement(ulong id, uchar value); + + virtual void LoadMtx(const DrawInfo &info); + + virtual void AllocStringBuffer(u16 size); + virtual void FreeStringBuffer(); + + virtual u16 SetString(const wchar_t *str, u16 destOffset = 0); + virtual u16 SetString(const wchar_t *str, u16 destOffset, u16 length); + + wchar_t *stringBuf; + + ut::Color colour1, colour2; + void *font; // actually a ut::ResFont or whatever + + float fontSizeX, fontSizeY; + float lineSpace, charSpace; + + void *tagProc; // actually a TagProcessor + + u16 bufferLength; + u16 stringLength; + + u8 alignment; + u8 flags; + }; } @@ -663,17 +707,21 @@ extern "C" void GXDrawDone(); // 801C4FE0 namespace m2d { class Base_c /*: public nw4r::ut::Link what's this? */ { + public: u32 _00; u32 _04; Base_c(); virtual ~Base_c(); - virtual void _vf0C(); + virtual void draw(); // don't call this directly + + void scheduleForDrawing(); - u8 _0C; + u8 drawOrder; }; class Simple_c : public Base_c { + public: nw4r::lyt::Layout layout; nw4r::lyt::DrawInfo drawInfo; @@ -686,7 +734,7 @@ namespace m2d { Simple_c(); ~Simple_c(); - void _vf0C(); + void draw(); virtual void _vf10(); virtual void _vf14(); }; @@ -696,6 +744,7 @@ namespace m2d { namespace EGG { class Frustum { + public: GXProjectionType projType; int isCentered; float width; @@ -792,10 +841,13 @@ struct Tree { typedef bool (*ChainedFunc)(void*); -struct FunctionChain { +class FunctionChain { +public: ChainedFunc *functions; u16 count; u16 current; + + void setup(ChainedFunc *functions, u16 count); // 8015F740 }; @@ -850,6 +902,8 @@ public: fBase_c *GetParent(); fBase_c *GetChild(); fBase_c *GetNext(); + + bool hasUninitialisedProcesses(); // 80162B60 }; class dBase_c : public fBase_c { @@ -876,7 +930,7 @@ public: class dScene_c : public dBase_c { public: - FunctionChain *funcChain; + FunctionChain *ptrToInitChain; dScene_c(); @@ -890,6 +944,11 @@ public: int afterDraw(); ~dScene_c(); + + + void setInitChain(FunctionChain &initChain) { + ptrToInitChain = &initChain; + } }; class dActor_c : public dBase_c { @@ -1081,7 +1140,7 @@ public: dDvdLoader_c(); // 8008F140 virtual ~dDvdLoader_c(); // 8008F170 - void *load(const char *filename, u8 unk = 0); // 8008F1B0 + void *load(const char *filename, u8 unk = 0, void *heap = 0); // 8008F1B0 bool close(); // 8008F2B0 -- Frees command, DON'T USE THIS unless you free the buffer yourself bool unload(); // 8008F310 -- Frees command and buffer, USE THIS @@ -1098,5 +1157,152 @@ private: +// More layout crap +// This file REALLY needs to be reorganised. + +namespace nw4r { +namespace lyt { + + class ResourceAccessor { + public: + ResourceAccessor(); + virtual ~ResourceAccessor(); + + virtual void *GetResource(u32 dirKey, const char *filename, u32 *sizePtr) = 0; + virtual void *GetFont(const char *name); + }; + + class ArcResourceAccessor : public ResourceAccessor { + public: + ArcResourceAccessor(); + ~ArcResourceAccessor(); + + bool Attach(void *data, const char *rootDirName); + void *GetResource(u32 dirKey, const char *filename, u32 *sizePtr); + void *GetFont(const char *name); + + ARCHandle arc; + u32 unk_20; + ut::LinkList list; // 0x24 + char rootDirName[0x80]; // 0x30 + // class ends at 0xB0 + }; + +} +} + +namespace m2d { + class ResAcc_c { + public: + ResAcc_c(); + virtual ~ResAcc_c(); + virtual void initialSetup(); + + nw4r::lyt::ResourceAccessor *resAccPtr; // 0x04 + u32 unk_08; // 0x08 + nw4r::lyt::ArcResourceAccessor resAcc; // 0x0C + // class ends at 0xBC + }; + + class ResAccLoader_c : public ResAcc_c { + public: + ResAccLoader_c(); + ~ResAccLoader_c(); + + void *buffer; + dDvdLoader_c loader; // 0xC0 + // ends at 0xD4 + + bool loadArc(const char *path); + bool loadArc(const char *path, u8 unk); + void free(); + }; + + class EmbedLayoutBase_c : public Base_c { + public: + EmbedLayoutBase_c(); + ~EmbedLayoutBase_c(); + + void draw(); // don't call this directly + + virtual void update(); + virtual bool build(const char *brlytPath, ResAcc_c *resAcc = 0); + + nw4r::lyt::Pane *getRootPane(); + nw4r::lyt::Pane *findPaneByName(const char *name) const; + nw4r::lyt::TextBox *findTextBoxByName(const char *name) const; + nw4r::lyt::Pane *findPictureByName(const char *name) const; // TODO: change to others + nw4r::lyt::Pane *findWindowByName(const char *name) const; + + void animate(); + void calculateMtx(); + + nw4r::lyt::Layout layout; // 0x10 -- actually m2d::Layout_c but I'll add that later + nw4r::lyt::DrawInfo drawInfo; // 0x30 + void *unk_84; // 0x84 -- a ResAcc? referenced in Build() + float posX; // 0x88 + float posY; // 0x8C + float clipX; // 0x90 + float clipY; // 0x94 + float clipWidth; // 0x98 + float clipHeight; // 0x9C + bool clippingEnabled; // 0xA0 + u32 hasAnimations; // 0xA4 + u32 unk_A8; // 0xA8 + }; + + class EmbedLayout_c : public EmbedLayoutBase_c { + public: + EmbedLayout_c(); + ~EmbedLayout_c(); + + bool build(const char *brlytPath, ResAcc_c *resAcc = 0); + + bool loadArc(const char *name, bool isLangSpecific); + bool loadArc(const char *name, u8 unk, bool isLangSpecific); + + bool loadArcForRegion(const char *name); // uses EU/Layout/$name + + // there's also a NedEU one, but should it really be listed here...? + + bool free(); + + // does NSMBW even use consts? I have no idea. maybe not + + void getPanes(const char **names, nw4r::lyt::Pane *output, int count) const; + void getWindows(const char **names, nw4r::lyt::Pane *output, int count) const; // TODO: change to others + void getPictures(const char **names, nw4r::lyt::Pane *output, int count) const; + void getTextBoxes(const char **names, nw4r::lyt::TextBox *output, int count) const; + + void setLangStrings(const char **names, const int *msgIDs, int category, int count); + + void loadAnimations(const char **names, int count); + void loadGroups(const char **names, int *animLinkIDs, int count); + + void enableNonLoopAnim(int num, bool goToLastFrame = false); + void enableLoopAnim(int num); + void resetAnim(int num, bool goToLastFrame = false); + void disableAnim(int num); + void disableAllAnimations(); + + bool isAnimOn(int num = -1); + bool isAnyAnimOn(); + + void execAnimations(); + + ResAccLoader_c loader; // 0xAC + void *brlanHandlers; // 0x180 + void *grpHandlers; // 0x184 + bool *animsEnabled; // 0x188 + int brlanCount; // 0x18C + int grpCount; // 0x190 + int lastAnimTouched; // 0x194 + + private: + void fixTextBoxesRecursively(nw4r::lyt::Pane *pane); + }; +} + + #endif diff --git a/kamek_ntsc.x b/kamek_ntsc.x index 45f1063..e93be35 100644 --- a/kamek_ntsc.x +++ b/kamek_ntsc.x @@ -86,12 +86,18 @@ SECTIONS { __nw__FUl = 0x802B9210; __dl__FPv = 0x802B9280; + __construct_new_array = 0x802DC7E0; + __destroy_new_array = 0x802DCB10; + + + setup__13FunctionChainFPPFPv_bUs = 0x8015F600; willBeDeleted__7fBase_cFv = 0x801622D0; moreHeapShit__7fBase_cFUiPv = 0x801625F0; createHeap__7fBase_cFUiPv = 0x801627F0; heapCreated__7fBase_cFv = 0x801628B0; Delete__7fBase_cFv = 0x80162510; + hasUninitialisedProcesses__7fBase_cFv = 0x80162A20; GetExplanationString__7dBase_cFv = 0x8006C660; @@ -167,6 +173,13 @@ SECTIONS { DrawAllLayoutsAfterX__Fi = 0x80163390; DrawAllLayoutsAfterXandBeforeY__Fii = 0x80163420; + __ct__Q23m2d13EmbedLayout_cFv = 0x800C8950; + __dt__Q23m2d13EmbedLayout_cFv = 0x800C89A0; + loadArc__Q23m2d13EmbedLayout_cFPCcb = 0x800C8CB0; + free__Q23m2d13EmbedLayout_cFv = 0x800C9930; + execAnimations__Q23m2d13EmbedLayout_cFv = 0x800C9560; + scheduleForDrawing__Q23m2d6Base_cFv = 0x80163850; + RenderEffects__Fii = 0x80093F10; RemoveAllFromScnRoot__Fv = 0x80164E70; @@ -220,6 +233,9 @@ SECTIONS { GameHeaps = 0x80377C48; + BGDatClass = 0x80429DF0; + GetTilesetName__FPvii = 0x800813F0; + IsWideScreen__Fv = 0x800B54B0; Player_Active = 0x80354E50; @@ -236,6 +252,8 @@ SECTIONS { GetObjectParent = 0x80162590; OSReport = 0x8015F730; + StagePtr = 0x8042A1C8; + _Z20CreateParentedObjectsPvic = 0x80162B00; _Z47CheckIfMenuShouldBeCancelledForSpecifiedWiimotei = 0x800B53A0; _Z21StartTitleScreenStagebi = 0x801017D0; @@ -252,6 +270,7 @@ SECTIONS { QueueArcLoad = 0x800DF840; RetrieveFileFromArc = 0x800DF180; RetrieveFileFromArcAlt = 0x800DF3C0; + SpawnSprite = 0x80064610; StoreObjectState = 0x800B1100; TriggerEventFlag = 0x800E4A30; @@ -274,6 +293,12 @@ SECTIONS { DVD_StillLoading__FPv = 0x800DF4E0; DVD_End__Fv = 0x8006A760; DVD_GetFile__FPvPCcPCc = 0x800DF180; + DVD_GetFile__FPvPCcPCcPUi = 0x800DF1E0; + + __ct__12dDvdLoader_cFv = 0x8008F140; + __dt__12dDvdLoader_cFv = 0x8008F170; + load__12dDvdLoader_cFPCcUcPv = 0x8008F1B0; + unload__12dDvdLoader_cFv = 0x8008F310; _Z22BgTexMng__LoadAnimTilePvisPcS0_c = 0x80087B60; /* same for ntsc */ BgTexMng__LoadAnimTile__FPvisPcPcc = 0x80087B60; /* same for ntsc */ diff --git a/kamek_ntsc2.x b/kamek_ntsc2.x index 50d951e..2d48f72 100644 --- a/kamek_ntsc2.x +++ b/kamek_ntsc2.x @@ -86,12 +86,18 @@ SECTIONS { __nw__FUl = 0x802B9210; __dl__FPv = 0x802B9280; + __construct_new_array = 0x802DC7E0; + __destroy_new_array = 0x802DCB10; + + + setup__13FunctionChainFPPFPv_bUs = 0x8015F600; willBeDeleted__7fBase_cFv = 0x801622D0; moreHeapShit__7fBase_cFUiPv = 0x801625F0; createHeap__7fBase_cFUiPv = 0x801627F0; heapCreated__7fBase_cFv = 0x801628B0; Delete__7fBase_cFv = 0x80162510; + hasUninitialisedProcesses__7fBase_cFv = 0x80162A20; GetExplanationString__7dBase_cFv = 0x8006C660; @@ -167,6 +173,13 @@ SECTIONS { DrawAllLayoutsAfterX__Fi = 0x80163390; DrawAllLayoutsAfterXandBeforeY__Fii = 0x80163420; + __ct__Q23m2d13EmbedLayout_cFv = 0x800C8950; + __dt__Q23m2d13EmbedLayout_cFv = 0x800C89A0; + loadArc__Q23m2d13EmbedLayout_cFPCcb = 0x800C8CB0; + free__Q23m2d13EmbedLayout_cFv = 0x800C9930; + execAnimations__Q23m2d13EmbedLayout_cFv = 0x800C9560; + scheduleForDrawing__Q23m2d6Base_cFv = 0x80163850; + RenderEffects__Fii = 0x80093F10; RemoveAllFromScnRoot__Fv = 0x80164E70; @@ -220,6 +233,9 @@ SECTIONS { GameHeaps = 0x80377C48; + BGDatClass = 0x80429DF0; + GetTilesetName__FPvii = 0x800813F0; + IsWideScreen__Fv = 0x800B54B0; Player_Active = 0x80354E50; @@ -236,6 +252,8 @@ SECTIONS { GetObjectParent = 0x80162590; OSReport = 0x8015F730; + StagePtr = 0x8042A1C8; + _Z20CreateParentedObjectsPvic = 0x80162B00; _Z47CheckIfMenuShouldBeCancelledForSpecifiedWiimotei = 0x800B53A0; _Z21StartTitleScreenStagebi = 0x801017D0; @@ -252,6 +270,7 @@ SECTIONS { QueueArcLoad = 0x800DF840; RetrieveFileFromArc = 0x800DF180; RetrieveFileFromArcAlt = 0x800DF3C0; + SpawnSprite = 0x80064610; StoreObjectState = 0x800B1100; TriggerEventFlag = 0x800E4A30; @@ -274,6 +293,12 @@ SECTIONS { DVD_StillLoading__FPv = 0x800DF4E0; DVD_End__Fv = 0x8006A760; DVD_GetFile__FPvPCcPCc = 0x800DF180; + DVD_GetFile__FPvPCcPCcPUi = 0x800DF1E0; + + __ct__12dDvdLoader_cFv = 0x8008F140; + __dt__12dDvdLoader_cFv = 0x8008F170; + load__12dDvdLoader_cFPCcUcPv = 0x8008F1B0; + unload__12dDvdLoader_cFv = 0x8008F310; _Z22BgTexMng__LoadAnimTilePvisPcS0_c = 0x80087B60; /* same for ntsc */ BgTexMng__LoadAnimTile__FPvisPcPcc = 0x80087B60; /* same for ntsc */ diff --git a/kamek_pal.x b/kamek_pal.x index cbfa970..34bbba8 100644 --- a/kamek_pal.x +++ b/kamek_pal.x @@ -86,12 +86,18 @@ SECTIONS { __nw__FUl = 0x802B9350; __dl__FPv = 0x802B93C0; + __construct_new_array = 0x802DCAD0; + __destroy_new_array = 0x802DCE00; + + + setup__13FunctionChainFPPFPv_bUs = 0x8015F740; willBeDeleted__7fBase_cFv = 0x80162410; moreHeapShit__7fBase_cFUiPv = 0x80162730; createHeap__7fBase_cFUiPv = 0x80162930; heapCreated__7fBase_cFv = 0x801629F0; Delete__7fBase_cFv = 0x80162650; + hasUninitialisedProcesses__7fBase_cFv = 0x80162B60; GetExplanationString__7dBase_cFv = 0x8006C660; @@ -167,6 +173,13 @@ SECTIONS { DrawAllLayoutsAfterX__Fi = 0x801634D0; DrawAllLayoutsAfterXandBeforeY__Fii = 0x80163560; + __ct__Q23m2d13EmbedLayout_cFv = 0x800C89A0; + __dt__Q23m2d13EmbedLayout_cFv = 0x800C89F0; + loadArc__Q23m2d13EmbedLayout_cFPCcb = 0x800C8D00; + free__Q23m2d13EmbedLayout_cFv = 0x800C9A20; + execAnimations__Q23m2d13EmbedLayout_cFv = 0x800C9650; + scheduleForDrawing__Q23m2d6Base_cFv = 0x80163990; + RenderEffects__Fii = 0x80093F10; RemoveAllFromScnRoot__Fv = 0x80164FB0; @@ -220,6 +233,9 @@ SECTIONS { GameHeaps = 0x80377F48; + BGDatClass = 0x8042A0D0; + GetTilesetName__FPvii = 0x800813F0; + IsWideScreen__Fv = 0x800B5500; Player_Active = 0x80355150; @@ -236,6 +252,8 @@ SECTIONS { GetObjectParent = 0x801626D0; OSReport = 0x8015F870; + StagePtr = 0x8042A4A8; + _Z20CreateParentedObjectsPvic = 0x80162C40; _Z47CheckIfMenuShouldBeCancelledForSpecifiedWiimotei = 0x800B53F0; _Z21StartTitleScreenStagebi = 0x801018E0; @@ -252,6 +270,7 @@ SECTIONS { QueueArcLoad = 0x800DF930; RetrieveFileFromArc = 0x800DF270; RetrieveFileFromArcAlt = 0x800DF4B0; + SpawnSprite = 0x80064610; StoreObjectState = 0x800B1100; TriggerEventFlag = 0x800E4B20; @@ -274,6 +293,12 @@ SECTIONS { DVD_StillLoading__FPv = 0x800DF5D0; DVD_End__Fv = 0x8006A760; DVD_GetFile__FPvPCcPCc = 0x800DF270; + DVD_GetFile__FPvPCcPCcPUi = 0x800DF2D0; + + __ct__12dDvdLoader_cFv = 0x8008F140; + __dt__12dDvdLoader_cFv = 0x8008F170; + load__12dDvdLoader_cFPCcUcPv = 0x8008F1B0; + unload__12dDvdLoader_cFv = 0x8008F310; _Z22BgTexMng__LoadAnimTilePvisPcS0_c = 0x80087B60; /* same for ntsc */ BgTexMng__LoadAnimTile__FPvisPcPcc = 0x80087B60; /* same for ntsc */ diff --git a/kamek_pal2.x b/kamek_pal2.x index 684d968..c18de20 100644 --- a/kamek_pal2.x +++ b/kamek_pal2.x @@ -86,12 +86,18 @@ SECTIONS { __nw__FUl = 0xDEADBEEF; __dl__FPv = 0xDEADBEEF; + __construct_new_array = 0xDEADBEEF; + __destroy_new_array = 0xDEADBEEF; + + + setup__13FunctionChainFPPFPv_bUs = 0xDEADBEEF; willBeDeleted__7fBase_cFv = 0xDEADBEEF; moreHeapShit__7fBase_cFUiPv = 0xDEADBEEF; createHeap__7fBase_cFUiPv = 0xDEADBEEF; heapCreated__7fBase_cFv = 0xDEADBEEF; Delete__7fBase_cFv = 0xDEADBEEF; + hasUninitialisedProcesses__7fBase_cFv = 0xDEADBEEF; GetExplanationString__7dBase_cFv = 0xDEADBEEF; @@ -167,6 +173,13 @@ SECTIONS { DrawAllLayoutsAfterX__Fi = 0xDEADBEEF; DrawAllLayoutsAfterXandBeforeY__Fii = 0xDEADBEEF; + __ct__Q23m2d13EmbedLayout_cFv = 0xDEADBEEF; + __dt__Q23m2d13EmbedLayout_cFv = 0xDEADBEEF; + loadArc__Q23m2d13EmbedLayout_cFPCcb = 0xDEADBEEF; + free__Q23m2d13EmbedLayout_cFv = 0xDEADBEEF; + execAnimations__Q23m2d13EmbedLayout_cFv = 0xDEADBEEF; + scheduleForDrawing__Q23m2d6Base_cFv = 0xDEADBEEF; + RenderEffects__Fii = 0xDEADBEEF; RemoveAllFromScnRoot__Fv = 0xDEADBEEF; @@ -220,6 +233,9 @@ SECTIONS { GameHeaps = 0xDEADBEEF; + BGDatClass = 0xDEADBEEF; + GetTilesetName__FPvii = 0xDEADBEEF; + IsWideScreen__Fv = 0xDEADBEEF; Player_Active = 0xDEADBEEF; @@ -236,6 +252,8 @@ SECTIONS { GetObjectParent = 0xDEADBEEF; OSReport = 0xDEADBEEF; + StagePtr = 0xDEADBEEF; + _Z20CreateParentedObjectsPvic = 0xDEADBEEF; _Z47CheckIfMenuShouldBeCancelledForSpecifiedWiimotei = 0xDEADBEEF; _Z21StartTitleScreenStagebi = 0xDEADBEEF; @@ -252,6 +270,7 @@ SECTIONS { QueueArcLoad = 0xDEADBEEF; RetrieveFileFromArc = 0xDEADBEEF; RetrieveFileFromArcAlt = 0xDEADBEEF; + SpawnSprite = 0xDEADBEEF; StoreObjectState = 0xDEADBEEF; TriggerEventFlag = 0xDEADBEEF; @@ -274,6 +293,12 @@ SECTIONS { DVD_StillLoading__FPv = 0xDEADBEEF; DVD_End__Fv = 0xDEADBEEF; DVD_GetFile__FPvPCcPCc = 0xDEADBEEF; + DVD_GetFile__FPvPCcPCcPUi = 0xDEADBEEF; + + __ct__12dDvdLoader_cFv = 0xDEADBEEF; + __dt__12dDvdLoader_cFv = 0xDEADBEEF; + load__12dDvdLoader_cFPCcUcPv = 0xDEADBEEF; + unload__12dDvdLoader_cFv = 0xDEADBEEF; _Z22BgTexMng__LoadAnimTilePvisPcS0_c = 0xDEADBEEF; /* same for ntsc */ BgTexMng__LoadAnimTile__FPvisPcPcc = 0xDEADBEEF; /* same for ntsc */ diff --git a/src/tilesetfixer.cpp b/src/tilesetfixer.cpp new file mode 100644 index 0000000..a66fc14 --- /dev/null +++ b/src/tilesetfixer.cpp @@ -0,0 +1,94 @@ +#include +#include + +extern void *BGDatClass, *StagePtr; +const char *GetTilesetName(void *cls, int areaNum, int slotNum); + +asm int GetAreaNum() { + nofralloc + lis r9, StagePtr@h + ori r9, r9, StagePtr@l + lwz r9, 0(r9) + lbz r3, 0x120E(r9) + blr +} + + +void DoFixes(int slotNumber); +void SwapObjData(u8 *data, int slotNumber); + +// Main hook +void TilesetFixerHack() { + for (int i = 1; i < 4; i++) { + DoFixes(i); + } +} + + + +// File format definitions +struct ObjLookupEntry { + u16 offset; + u8 width; + u8 height; +}; + + +void DoFixes(int slotNumber) { + // This is where it all starts + const char *tsName = GetTilesetName(BGDatClass, GetAreaNum(), slotNumber); + + if (tsName == 0 || tsName[0] == 0) { + OSReport("Skipping set %d\n", slotNumber); + return; + } + + OSReport("Processing %d = %s\n", slotNumber, tsName); + + char untHDname[64], untname[64]; + snprintf(untHDname, 64, "BG_unt/%s_hd.bin", tsName); + snprintf(untname, 64, "BG_unt/%s.bin", tsName); + + u32 unt_hd_length; + void *bg_unt_hd_data = DVD_GetFile(GetDVDClass2(), tsName, untHDname, &unt_hd_length); + void *bg_unt = DVD_GetFile(GetDVDClass2(), tsName, untname); + + OSReport("Unt: %p - Unt_HD: %p\n", bg_unt, bg_unt_hd_data); + + ObjLookupEntry *lookups = (ObjLookupEntry*)bg_unt_hd_data; + + int objCount = unt_hd_length / sizeof(ObjLookupEntry); + OSReport("%d objects\n", objCount); + + for (int i = 0; i < objCount; i++) { + // process each object + u8 *thisObj = (u8*)((u32)bg_unt + lookups[i].offset); + //OSReport("processing %d[%p][%04x]\n", i, thisObj, lookups[i].offset); + + SwapObjData(thisObj, slotNumber); + } +} + + +void SwapObjData(u8 *data, int slotNumber) { + // rudimentary parser which will hopefully work + + while (*data != 0xFF) { + u8 cmd = *data; + //OSReport("Command: %02x\n", cmd); + + if (cmd == 0xFE || (cmd & 0x80) != 0) { + data++; + continue; + } + + if ((data[2] & 3) != 0) { + data[2] &= 0xFC; + data[2] |= slotNumber; + } + data += 3; + } + + //OSReport("Ended @ %p\n", data); +} + diff --git a/tilesetfixer.yaml b/tilesetfixer.yaml new file mode 100644 index 0000000..409c443 --- /dev/null +++ b/tilesetfixer.yaml @@ -0,0 +1,9 @@ +--- +source_files: [../src/tilesetfixer.cpp] +hooks: + - name: TilesetFixHack + type: branch_insn + branch_type: b + src_addr_pal: 0x80081694 + target_func: 'TilesetFixerHack(void)' + -- cgit v1.2.3