mirror of
https://github.com/zeldaret/ph
synced 2026-05-25 07:22:58 -04:00
Merge pull request #50 from AetiasHax/objdiff-integration
`objdiff` integration
This commit is contained in:
+4
-2
@@ -12,13 +12,12 @@ Contents:
|
||||
1. Use one of these platforms:
|
||||
- Windows (MSYS)
|
||||
- Linux via WSL
|
||||
- Recommended for Windows users
|
||||
- Linux
|
||||
2. Install the following:
|
||||
- Python 3.11+ and pip
|
||||
- GCC 9+
|
||||
- Make
|
||||
- **On Linux/WSL**: Wine
|
||||
- **On Linux/WSL**: Wine/Wibo
|
||||
3. Install the Python dependencies:
|
||||
```shell
|
||||
python -m pip install -r tools/requirements.txt
|
||||
@@ -28,6 +27,9 @@ python -m pip install -r tools/requirements.txt
|
||||
python tools/setup.py
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For Linux users: If you plan to use Wibo instead of Wine, run make with `make WINE=<path/to/wibo> ...`.
|
||||
|
||||
## Build the ROM
|
||||
|
||||
This repository does not include any of the game's assets, and you will need an original decrypted base ROM.
|
||||
|
||||
@@ -27,11 +27,13 @@ ASSETS_TXT := assets.txt
|
||||
|
||||
ASM_FILES := $(shell find asm -name *.s)
|
||||
CXX_FILES := $(shell find src -name *.cpp) $(shell find libs -name *.cpp)
|
||||
C_FILES := $(shell find src -name *.c) $(shell find libs -name *.c)
|
||||
ASM_OBJS = $(ASM_FILES:%.s=$(TARGET_DIR)/%.s.o)
|
||||
ASM_INCS = $(ASM_FILES:%.s=%.inc)
|
||||
CXX_OBJS = $(CXX_FILES:%.cpp=$(TARGET_DIR)/%.cpp.o)
|
||||
C_OBJS = $(C_FILES:%.c=$(TARGET_DIR)/%.c.o)
|
||||
C_FILES := $(shell find src -name *.c) $(shell find libs -name *.c)
|
||||
ASM_OBJS = $(ASM_FILES:%.s=$(TARGET_DIR)/%.s.o)
|
||||
ASM_INCS = $(ASM_FILES:%.s=%.inc)
|
||||
CXX_OBJS = $(CXX_FILES:%.cpp=$(TARGET_DIR)/%.cpp.o)
|
||||
C_OBJS = $(C_FILES:%.c=$(TARGET_DIR)/%.c.o)
|
||||
CXX_CTXS = $(CXX_FILES:%.cpp=$(TARGET_DIR)/%.cpp.ctx)
|
||||
C_CTXS = $(C_FILES:%.c=$(TARGET_DIR)/%.c.ctx)
|
||||
|
||||
OV_BINS := $(wildcard $(TARGET_DIR)/overlays/*.bin)
|
||||
OV_LZS = $(OV_BINS:%.bin=%.lz)
|
||||
@@ -124,16 +126,20 @@ $(ASM_OBJS): $(TARGET_DIR)/%.o: %
|
||||
mkdir -p $(dir $@)
|
||||
LM_LICENSE_FILE=$(MW_LICENSE) $(WINE) $(MW_ASM) $(ASM_FLAGS) $< -o $@
|
||||
|
||||
$(CXX_OBJS): $(TARGET_DIR)/%.o: %
|
||||
$(CXX_OBJS): $(TARGET_DIR)/%.o: % $(TARGET_DIR)/%.ctx
|
||||
mkdir -p $(dir $@)
|
||||
LM_LICENSE_FILE=$(MW_LICENSE) $(WINE) $(MW_CC) $(CC_FLAGS) $(CXX_FLAGS) $< -o $@
|
||||
$(TOOLS_DIR)/elf/elfkill -s $< -e $@
|
||||
|
||||
$(C_OBJS): $(TARGET_DIR)/%.o: %
|
||||
$(C_OBJS): $(TARGET_DIR)/%.o: % $(TARGET_DIR)/%.ctx
|
||||
mkdir -p $(dir $@)
|
||||
LM_LICENSE_FILE=$(MW_LICENSE) $(WINE) $(MW_CC) $(CC_FLAGS) $(C_FLAGS) $< -o $@
|
||||
$(TOOLS_DIR)/elf/elfkill -s $< -e $@
|
||||
|
||||
$(CXX_CTXS) $(C_CTXS): $(TARGET_DIR)/%.ctx: %
|
||||
mkdir -p $(dir $@)
|
||||
$(PYTHON) $(TOOLS_DIR)/m2ctx.py -f $@ $<
|
||||
|
||||
.PHONY: link
|
||||
link: lcf $(ASM_OBJS) $(CXX_OBJS) $(C_OBJS)
|
||||
cd $(TARGET_DIR) && LM_LICENSE_FILE=$(MW_LICENSE) $(WINE) $(MW_LD) $(LD_FLAGS) $(LCF_FILE) @$(OBJS_FILE)
|
||||
|
||||
@@ -56,7 +56,7 @@ When the code is linked, all code of the same section will be written adjacent t
|
||||
## Compiling code
|
||||
This game was written in C++, so most of the code we decompile will be in this programming language. In C++, we typically don't
|
||||
have to express which section we want the code to be written to. Instead, the compiler determines the section automatically.
|
||||
Here are a few examples of how to
|
||||
Here are a few examples of how to generate code for different section types.
|
||||
|
||||
- `.text`
|
||||
- Functions and member functions (aka methods)
|
||||
|
||||
+46
-34
@@ -20,43 +20,55 @@ again. Remember to make a pull request of any notable progress you made on the s
|
||||
[non-matching functions](/CONTRIBUTING.md#non-matching-functions).
|
||||
|
||||
## Decompiling a source file
|
||||
It can be tricky to fully decompile an assembly file into a C/C++ source file, so here's some advice to make it easier:
|
||||
- C/C++ code is built before assembly code
|
||||
- This means you can take one function from the top of your assembly file, decompile it, and append it to the bottom of
|
||||
your C/C++ file.
|
||||
- Build the ROM often
|
||||
- We recommend building every time you decompile a function.
|
||||
- This is because functions can sometimes match in decomp.me, but not when building.
|
||||
- If your ROM doesn't match, it's easier to know which function is wrong if it's the only function added since the last
|
||||
successful build.
|
||||
We use the object diffing tool [`objdiff`](https://github.com/encounter/objdiff) to track differences between C++ and assembly
|
||||
code.
|
||||
1. [Download the latest release.](https://github.com/encounter/objdiff/releases/latest)
|
||||
1. Run `python tools/objdiff.py <EUR|USA>` to generate `objdiff.json` in the project root.
|
||||
1. In `objdiff`, set the project directory to the root of this project. This will load `objdiff.json`.
|
||||
1. Select your source file in the left sidebar:
|
||||

|
||||
5. See the list of functions and data to decompile:
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
> If a source file is missing in `objdiff`, or `objdiff` fails to build a file, first rerun `objdiff.py` to update
|
||||
> `objdiff.json`. If the problem persists, feel free to ask for help.
|
||||
|
||||
## Decompiling a function
|
||||
Say you've found a function you want to decompile. Here are the steps we recommend for decompiling it:
|
||||
1. Visit [decomp.me](https://decomp.me/) and start decomping.
|
||||
1. Under the platforms, select "Nintendo DS".
|
||||
1. Select compiler preset "Phantom Hourglass".
|
||||
1. Copy and paste the target assembly for your function, including the `func_start` and `func_end` macros, and the pool
|
||||
constants. For example:
|
||||
```arm
|
||||
.global func_ov09_0211bf48
|
||||
thumb_func_start func_ov09_0211bf48
|
||||
func_ov09_0211bf48: ; 0x0211bf48
|
||||
ldr r0, _0211bf50 ; =data_ov09_0211f59c
|
||||
ldrb r0, [r0]
|
||||
bx lr
|
||||
nop
|
||||
thumb_func_end func_ov09_0211bf48
|
||||
_0211bf50: .word data_ov09_0211f59c
|
||||
Once you've opened a source file in `objdiff`, you can choose to decompile the functions in any order. We recommend starting
|
||||
with a small function if you're unfamiliar with decompilation. Here's an example:
|
||||
|
||||

|
||||
|
||||
As a starting point, we look at the decompiler output in Ghidra. You can request access to our shared Ghidra project [in this section](#the-ghidra-project).
|
||||
|
||||

|
||||
|
||||
Looking at this output, we might try writing something like this:
|
||||
```cpp
|
||||
ARM bool Actor::SetVelocity(Vec3p *vel) {
|
||||
if (mUnk_11b) {
|
||||
mVel = *vel;
|
||||
mUnk_11b = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
5. Run `m2ctx.py include/MyHeader.hpp -c` to generate a context and put it in your clipboard.
|
||||
- If no suitable header file exists, make a new one and put any structs and types you need in there.
|
||||
1. Paste the context into decomp.me, and create the scratch.
|
||||
1. Decompile the function and try to get a 100% match.
|
||||
- There's no ARM decompiler in decomp.me yet, but Ghidra does the job quite well. See [the Ghidra section](#the-ghidra-project)
|
||||
for more info.
|
||||
- If you're unable to get a 100% match, share your decomp.me scratch with other contributors and they may assist you.
|
||||
- In the worst case, you can also contribute [non-matching functions](/CONTRIBUTING.md#non-matching-functions) to this
|
||||
project.
|
||||
|
||||
Now we can go back to `objdiff` and look at the result:
|
||||
|
||||

|
||||
|
||||
Success! Note that this was a simple example and that you'll sometimes get stuck on a function. In that case, try the
|
||||
following:
|
||||
- Decompile a different function and come back later.
|
||||
- Export to [decomp.me](https://decomp.me/):
|
||||
1. Press the `decomp.me` button in `objdiff`.
|
||||
1. Once you're sent to `decomp.me`, go to "Options" and change the preset to "Phantom Hourglass".
|
||||
1. Paste your code into the "Source code" tab.
|
||||
1. Share the link with us!
|
||||
- In the worst case, add the function as a [non-matching function](/CONTRIBUTING.md#non-matching-functions).
|
||||
|
||||
## Decompiling `.init` functions
|
||||
> [!NOTE]
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -21,7 +21,7 @@ dcd 0x1234
|
||||
|
||||
#### `ldconst`: Loads a literal 32-bit value
|
||||
```asm
|
||||
ldconst 0x1234
|
||||
ldconst r0, 0x1234
|
||||
bx lr
|
||||
```
|
||||
This code is equivalent to the above example using `dcd`.
|
||||
|
||||
@@ -75,6 +75,7 @@ struct ActorType {
|
||||
/* 10 */ ActorType *next;
|
||||
/* 14 */
|
||||
|
||||
inline ActorType() {}
|
||||
ActorType(ActorTypeId id, ActorCreateFunc create, unk32 (*unk_08)());
|
||||
~ActorType();
|
||||
unk32 func_0203e7c8();
|
||||
|
||||
@@ -42,4 +42,5 @@ public:
|
||||
|
||||
void func_ov00_020aee58(s16 param1, u16 param2);
|
||||
void func_ov00_020aee84();
|
||||
bool func_ov00_020aeeac();
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Actor/Actor.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
Actor::Actor() {}
|
||||
Actor::~Actor() {}
|
||||
bool Actor::vfunc_08() {}
|
||||
@@ -105,5 +103,3 @@ void Actor::vfunc_b0() {}
|
||||
void Actor::GetLinkPos(Vec3p *result) {}
|
||||
void Actor::GetLinkDummyPos(Vec3p *result) {}
|
||||
Actor_UnkStruct_09c::Actor_UnkStruct_09c() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#include "Actor/ActorManager.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void ActorManager::DeleteActor(u32 index, bool param2) {}
|
||||
void ActorManager::func_ov00_020c3484(ActorRef *ref, Actor *actor, unk32 param3) {}
|
||||
void ActorManager::Actor_vfunc_10(u32 param1) {}
|
||||
Actor* ActorManager::FindActorById(u32 id) {}
|
||||
Actor* ActorManager::GetActor(ActorRef *ref) {}
|
||||
bool FilterActor::Filter(Actor *actor) {}
|
||||
s32 ActorManager::FilterActors(ActorFilterBase *filter, ActorList *filteredActors) {}
|
||||
s32 ActorManager::FilterActors(FilterActorBase *filter, ActorList *filteredActors) {}
|
||||
void ActorManager::FindActorByType(ActorRef *ref, ActorManager *manager, u32 type) {}
|
||||
void ActorManager::FindNearestActorOfType(ActorRef *ref, ActorManager *manager, u32 type, Vec3p *pos) {}
|
||||
void ActorManager::func_ov00_020c398c() {}
|
||||
@@ -19,5 +17,3 @@ s32 ActorManager::func_ov00_020c3bb0(unk32 param1, s32 *param2) {}
|
||||
void ActorManager::func_ov00_020c3ce8(unk32 param1, unk32 param2) {}
|
||||
void ActorManager::Actor_vfunc_28() {}
|
||||
bool ActorManager::ActorTypeIsOneOf(u32 type, u32 *types) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
#include "Item/Item.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
bool Item::func_ov00_020ad020(ItemId item) {}
|
||||
bool Item::func_ov00_020ad068(ItemId item) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Map/Course.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void Course::GetDungeonProgress(CourseProgress *param_2) {}
|
||||
void Course::func_ov00_0207ca28(s32 param_2, unk32 param_3, unk32 param_4) {}
|
||||
char* Course::SetCourseName(char *src) {}
|
||||
@@ -51,5 +49,3 @@ void Course::SetMapDataFlag4(unk32 param_2, unk32 param_3) {}
|
||||
bool Course::GetMapDataFlag4(unk32 param_2) {}
|
||||
MapData* Course::FindMapData(u32 map) {}
|
||||
MapData* Course::FindCurrentMapData() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "Map/MapBase.hpp"
|
||||
#include "Map/MapManager.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
MapBase::~MapBase() {}
|
||||
MapBase_Unk_180::~MapBase_Unk_180() {}
|
||||
void MapBase::SetBounds(unk32 map, unk32 course) {}
|
||||
@@ -112,5 +110,3 @@ unk32 TriggerBase::vfunc_10() {}
|
||||
void MapBase::func_ov00_02080de4() {}
|
||||
unk8 MapBase::func_ov00_02080de8(unk32 param_2) {}
|
||||
void MapBase::func_ov00_02080edc() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Map/MapManager.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void MapManager::func_ov00_020820ec(unk32 *param_2) {}
|
||||
void MapManager::func_ov00_020820fc(s32 param_2, unk32 param_3, unk32 param_4) {}
|
||||
unk8 MapManager::func_ov00_0208210c(unk32 param_2, unk32 param_3) {}
|
||||
@@ -200,5 +198,3 @@ unk8 MapManager::func_ov00_02085c60(unk32 param_2, unk32 param_3, unk32 param_4,
|
||||
unk8 MapManager::func_ov00_02086044(unk32 param_2, unk32 param_3, unk32 param_4) {}
|
||||
bool MapManager::func_ov00_02086284(s32 *param_2, Vec3p *param_3, Vec3p *param_4, s32 param_5, u16 param_6, Vec3p *param_7, Vec3p *param_8) {}
|
||||
bool MapManager::func_ov00_02086a84(s32 *param_2, Vec3p *param_3, Vec3p *param_4, s32 param_5, s32 param_6, unk32 param_7, Vec3p *param_8, Vec3p *param_9) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/LinkStateBase.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void LinkStateBase::vfunc_00() {}
|
||||
void LinkStateBase::OnStateEnter() {}
|
||||
void LinkStateBase::OnStateLeave(s32 param1) {}
|
||||
@@ -85,5 +83,3 @@ unk32 LinkStateBase::Get_PlayerControlData_Unk120() {}
|
||||
s32 LinkStateBase::Get_PlayerLinkBase_Unk38() {}
|
||||
DebugHierarchy* LinkStateBase::GetDebugHierarchy0() {}
|
||||
DebugHierarchy* LinkStateBase::GetDebugHierarchy1() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/LinkStateDamage.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void LinkStateDamage::vfunc_00() {}
|
||||
void LinkStateDamage::CreateDebugHierarchy() {}
|
||||
void LinkStateDamage::OnStateEnter() {}
|
||||
@@ -16,5 +14,3 @@ bool LinkStateDamage::vfunc_24(s32 param1) {}
|
||||
bool LinkStateDamage::vfunc_20(s32 param1) {}
|
||||
void LinkStateDamage::func_ov00_020acfe8(bool param1) {}
|
||||
LinkStateId LinkStateDamage::GetId() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/LinkStateFollow.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void LinkStateFollow::vfunc_00() {}
|
||||
LinkStateId LinkStateFollow::GetId() {}
|
||||
void LinkStateFollow::MoveTowardTarget() {}
|
||||
@@ -12,5 +10,3 @@ LinkStateCutscene* LinkStateFollow::GetLinkStateCutscene() {}
|
||||
bool LinkStateFollow::vfunc_34(Vec3p *param1) {}
|
||||
bool LinkStateFollow::func_ov00_020a9180(Vec3p *param1) {}
|
||||
bool LinkStateFollow::func_ov00_020a9210(Vec3p *param1, Actor *param2) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/LinkStateInteract.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void LinkStateInteract::vfunc_00() {}
|
||||
LinkStateId LinkStateInteract::GetId() {}
|
||||
void LinkStateInteract::CreateDebugHierarchy() {}
|
||||
@@ -30,5 +28,3 @@ void LinkStateInteract::func_ov00_020abbdc(ActorRef *ref) {}
|
||||
void LinkStateInteract::func_ov00_020abc18(ActorRef *ref) {}
|
||||
bool LinkStateInteract::func_ov00_020abc40() {}
|
||||
bool LinkStateInteract::func_ov00_020abc78(ActorRef *ref) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/LinkStateItem.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void LinkStateItem::vfunc_00() {}
|
||||
LinkStateId LinkStateItem::GetId() {}
|
||||
s32 LinkStateItem::IsHammerEquipped() {}
|
||||
@@ -10,5 +8,3 @@ EquipBombchu* LinkStateItem::GetEquipBombchu() {}
|
||||
LinkStateMove* LinkStateItem::GetLinkStateMove() {}
|
||||
bool LinkStateItem::func_ov00_020abf70() {}
|
||||
bool LinkStateItem::vfunc_28() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/LinkStateMove.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void LinkStateMove::vfunc_00() {}
|
||||
LinkStateId LinkStateMove::GetId() {}
|
||||
void LinkStateMove::CreateDebugHierarchy() {}
|
||||
@@ -10,5 +8,3 @@ void LinkStateMove::OnStateLeave(s32 param1) {}
|
||||
bool LinkStateMove::vfunc_24(s32 param1) {}
|
||||
bool LinkStateMove::func_ov00_020a8f2c() {}
|
||||
bool LinkStateMove::func_ov00_020a8f4c() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/LinkStateRoll.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
void LinkStateRoll::vfunc_00() {}
|
||||
LinkStateId LinkStateRoll::GetId() {}
|
||||
void LinkStateRoll::CreateDebugHierarchy() {}
|
||||
@@ -12,5 +10,3 @@ bool LinkStateRoll::vfunc_24(s32 param1) {}
|
||||
void LinkStateRoll::func_ov00_020aee58(s16 param1, u16 param2) {}
|
||||
void LinkStateRoll::func_ov00_020aee84() {}
|
||||
bool LinkStateRoll::func_ov00_020aeeac() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/PlayerLinkBase.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
bool PlayerBase::vfunc_04() {}
|
||||
ItemFlag PlayerBase::GetEquipId() {}
|
||||
bool PlayerBase::CanMove() {}
|
||||
@@ -20,5 +18,3 @@ void PlayerBase::AddHealth(s16 amount) {}
|
||||
bool PlayerBase::Teleport(Vec3p *pos, s16 angle, unk32 param3, bool param4, bool param5) {}
|
||||
bool PlayerBase::TeleportToEntrance(unk32 entranceId, bool param2) {}
|
||||
bool PlayerBase::TeleportToLastEntrance(bool param1) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/PlayerControl.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
bool PlayerControl::func_ov00_020aeeac() {}
|
||||
void PlayerControl::func_ov00_020aeef8() {}
|
||||
void PlayerControl::func_ov00_020aef30() {}
|
||||
@@ -52,5 +50,3 @@ bool PlayerControl::IsNotTouching() {}
|
||||
bool PlayerControl::IsTouchingFast() {}
|
||||
bool PlayerControl::IsTappedNow() {}
|
||||
bool PlayerControl::func_ov00_020b13c4() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/TouchControl.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
TouchControl::TouchControl() {}
|
||||
void TouchControl::IncreaseSpeed(s16 increase) {}
|
||||
void TouchControl::UpdateFlags(u16 speed) {}
|
||||
@@ -11,5 +9,3 @@ bool TouchControl::func_ov00_0207aeac() {}
|
||||
void TouchControl::UpdateConditionally(TouchState *state, u16 speed) {}
|
||||
void TouchControl::func_ov00_0207af38(u16 speed, bool param2) {}
|
||||
TouchControl::~TouchControl() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Player/TouchGesture.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
TouchGesture::TouchGesture() {}
|
||||
void TouchGesture::ResetTouchHistory() {}
|
||||
void TouchGesture::Update(void *param1) {}
|
||||
@@ -9,5 +7,3 @@ TouchGesture::~TouchGesture() {}
|
||||
|
||||
void TouchGestureBase::ResetTouchHistory() {}
|
||||
TouchGestureBase::~TouchGestureBase() {}
|
||||
|
||||
#endif STUBS
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "Save/AdventureFlags.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
bool AdventureFlags::Exists() {}
|
||||
void AdventureFlags::CopyTo(unk32 *flags) {}
|
||||
void AdventureFlags::func_ov00_02097674() {}
|
||||
@@ -50,5 +48,3 @@ bool AdventureFlags::func_ov00_0209809c() {}
|
||||
bool AdventureFlags::func_ov00_020980ac() {}
|
||||
void AdventureFlags::func_ov00_020980bc(s32 param1) {}
|
||||
void AdventureFlags::func_ov00_020980d0() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#include "Actor/ActorRupee.hpp"
|
||||
|
||||
#ifdef STUBS
|
||||
|
||||
Resource ActorRupee::gResource;
|
||||
ActorType ActorRupee::gType;
|
||||
|
||||
ActorRupee* ActorRupee::Create() {}
|
||||
@@ -21,5 +18,3 @@ void ActorRupee::func_ov14_0213b5f4(RupeeId id, unk32 param2, Vec3p *param3, boo
|
||||
void ActorRupee::func_ov14_0213b6a4(RupeeId id, void *param2) {}
|
||||
bool ActorRupee::func_ov14_0213b70c(RupeeId id) {}
|
||||
ActorRupee::~ActorRupee() {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,63 +33,45 @@ DTCM_OBJECTS = [
|
||||
ov00 = Overlay(name='ov00', after='ARM9', objects=[
|
||||
'asm/ov00/ov00_020773c0.s',
|
||||
|
||||
'src/00_Core/Player/TouchControl.cpp',
|
||||
'asm/ov00/Player/TouchControl.s',
|
||||
|
||||
'asm/ov00/ov00_0207afa0.s',
|
||||
|
||||
'asm/ov00/Map/Course.s',
|
||||
'src/00_Core/Map/Course.cpp',
|
||||
'asm/ov00/Map/MapBase.s',
|
||||
'src/00_Core/Map/MapBase.cpp',
|
||||
|
||||
'asm/ov00/ov00_0207da38.s',
|
||||
|
||||
'asm/ov00/Map/MapManager.s',
|
||||
'src/00_Core/Map/MapManager.cpp',
|
||||
|
||||
'asm/ov00/ov00_02086cd0.s',
|
||||
|
||||
'src/00_Core/Save/AdventureFlags.cpp',
|
||||
'asm/ov00/Save/AdventureFlags.s',
|
||||
|
||||
'asm/ov00/ov00_020980f4.s',
|
||||
|
||||
'src/00_Core/Player/PlayerBase.cpp',
|
||||
'asm/ov00/Player/PlayerBase.s',
|
||||
'src/00_Core/Player/LinkStateBase.cpp',
|
||||
'asm/ov00/Player/LinkStateBase.s',
|
||||
'src/00_Core/Player/LinkStateMove.cpp',
|
||||
'asm/ov00/Player/LinkStateMove.s',
|
||||
'src/00_Core/Player/LinkStateFollow.cpp',
|
||||
'asm/ov00/Player/LinkStateFollow.s',
|
||||
'src/00_Core/Player/TouchGesture.cpp',
|
||||
'asm/ov00/Player/TouchGesture.s',
|
||||
|
||||
'asm/ov00/ov00_020a8e04.s',
|
||||
|
||||
'src/00_Core/Player/LinkStateInteract.cpp',
|
||||
'asm/ov00/Player/LinkStateInteract.s',
|
||||
'src/00_Core/Player/LinkStateItem.cpp',
|
||||
'asm/ov00/Player/LinkStateItem.s',
|
||||
'src/00_Core/Player/LinkStateDamage.cpp',
|
||||
'asm/ov00/Player/LinkStateDamage.s',
|
||||
'src/00_Core/Item/Item.cpp',
|
||||
'asm/ov00/Item/Item.s',
|
||||
'src/00_Core/Item/ItemManager.cpp',
|
||||
'src/00_Core/Player/LinkStateRoll.cpp',
|
||||
'asm/ov00/Player/LinkStateRoll.s',
|
||||
'src/00_Core/Player/PlayerControl.cpp',
|
||||
'asm/ov00/Player/PlayerControl.s',
|
||||
|
||||
'asm/ov00/ov00_020b1498.s',
|
||||
|
||||
'src/00_Core/Actor/Actor.cpp',
|
||||
'asm/ov00/Actor/Actor.s',
|
||||
|
||||
'asm/ov00/ov00_020c3348.s',
|
||||
|
||||
'src/00_Core/Actor/ActorManager.cpp',
|
||||
'asm/ov00/Actor/ActorManager.s',
|
||||
|
||||
'asm/ov00/ov00_020c3e54.s',
|
||||
@@ -136,7 +118,6 @@ ov13 = Overlay(name='ov13', after=[ov04, ov05, ov06, ov07], objects=[
|
||||
ov14 = Overlay(name='ov14', after=[ov08, ov09, ov10, ov13], objects=[
|
||||
'asm/ov14/ov14_0211f640.s',
|
||||
|
||||
'src/14_Land/Actor/ActorRupee.cpp',
|
||||
'asm/ov14/Actor/ActorRupee.s',
|
||||
|
||||
'asm/ov14/ov14_0213b778.s',
|
||||
|
||||
+35
-12
@@ -6,6 +6,8 @@ import subprocess
|
||||
import os
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
import re
|
||||
import tempfile
|
||||
|
||||
parser = argparse.ArgumentParser(description="Generates a context for decomp.me")
|
||||
parser.add_argument('file', help="Input file to preprocess")
|
||||
@@ -28,19 +30,40 @@ root_dir = script_dir / ".."
|
||||
def eprint(*args, **kwargs):
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
try:
|
||||
ctx: str = subprocess.check_output([
|
||||
'gcc',
|
||||
'-E', '-P', '-fworking-directory', '-undef', '-dD',
|
||||
*CXX_FLAGS,
|
||||
args.file
|
||||
], cwd=root_dir, encoding=args.encoding)
|
||||
except subprocess.CalledProcessError as e:
|
||||
eprint(f"Failed to preprocess '{args.file}'")
|
||||
if args.verbose: eprint(e)
|
||||
else: eprint("Use -v for more verbose error output")
|
||||
exit(1)
|
||||
# Finds all lines starting with #include followed by <...> or "..."
|
||||
INCLUDE_REGEX = r'^\s*#\s*include\s*([<"][\S ]+[>"])\s*$'
|
||||
# Finds all line comments and multiline comments
|
||||
COMMENT_REGEX = r'\/\/.*$|\/\*(?:.|\r|\n)+?\*\/'
|
||||
# Finds all lines from #ifndef NONMATCHING to #else
|
||||
NONMATCH_REGEX = r'^\s*#\s*ifndef\s*NONMATCHING\s*(?:.|\r|\n)*\n\s*#\s*else\s*$'
|
||||
|
||||
with open(args.file, 'r') as f:
|
||||
contents = f.read()
|
||||
contents = re.sub(COMMENT_REGEX, '', contents, 0, re.MULTILINE)
|
||||
contents = re.sub(NONMATCH_REGEX, '', contents, 0, re.MULTILINE)
|
||||
includes = re.findall(INCLUDE_REGEX, contents, re.MULTILINE)
|
||||
|
||||
_, suffix = os.path.splitext(args.file)
|
||||
|
||||
with tempfile.NamedTemporaryFile(delete=True, suffix=suffix) as tmp_file:
|
||||
# Write includes
|
||||
for include in includes:
|
||||
tmp_file.write(f'#include {include}\n'.encode())
|
||||
tmp_file.flush()
|
||||
|
||||
# Run preprocessor
|
||||
try:
|
||||
ctx: str = subprocess.check_output([
|
||||
'gcc',
|
||||
'-E', '-P', '-fworking-directory', '-undef', '-dD',
|
||||
*CXX_FLAGS,
|
||||
tmp_file.name
|
||||
], cwd=root_dir, encoding=args.encoding)
|
||||
except subprocess.CalledProcessError as e:
|
||||
eprint(f"Failed to preprocess '{args.file}'")
|
||||
if args.verbose: eprint(e)
|
||||
else: eprint("Use -v for more verbose error output")
|
||||
exit(1)
|
||||
|
||||
lines = ctx.splitlines(True)
|
||||
for i in reversed(range(len(lines))):
|
||||
|
||||
@@ -38,7 +38,6 @@ cc.extend([
|
||||
'-i', include_dir,
|
||||
'-i', libc_include_dir,
|
||||
'-i', libcpp_include_dir,
|
||||
'-DSTUBS',
|
||||
args.file
|
||||
])
|
||||
|
||||
|
||||
+13
-3
@@ -35,14 +35,15 @@ def find_asm_path(src_path: Path) -> Path | None:
|
||||
return asm_path
|
||||
|
||||
|
||||
def get_build_path(path: Path) -> Path:
|
||||
def get_build_path(path: Path, extension='.o') -> Path:
|
||||
region = args.region.lower()
|
||||
return Path('build') / region / path.parent / (path.name + '.o')
|
||||
return Path('build') / region / path.parent / (path.name + extension)
|
||||
|
||||
|
||||
config = dict()
|
||||
config["custom_make"] = "make"
|
||||
config["custom_args"] = [
|
||||
"-B",
|
||||
f"REGION={args.region}"
|
||||
]
|
||||
config["build_target"] = True
|
||||
@@ -61,6 +62,7 @@ for (root, dirs, files) in os.walk(src_dir):
|
||||
src_path = Path(f'{root}/{file}')
|
||||
src_path = src_path.relative_to(src_dir)
|
||||
asm_path = find_asm_path(src_path)
|
||||
src_path = 'src' / src_path
|
||||
|
||||
if asm_path: asm_path = 'asm' / asm_path
|
||||
|
||||
@@ -69,9 +71,17 @@ for (root, dirs, files) in os.walk(src_dir):
|
||||
obj = dict()
|
||||
obj["name"] = name
|
||||
if asm_path.exists(): obj["target_path"] = str(get_build_path(asm_path))
|
||||
obj["base_path"] = str(get_build_path('src' / src_path))
|
||||
obj["base_path"] = str(get_build_path(src_path))
|
||||
obj["reverse_fn_order"] = False
|
||||
|
||||
scratch = dict()
|
||||
scratch["platform"] = "nds_arm9"
|
||||
scratch["compiler"] = "mwcc_30_131"
|
||||
scratch["ctx_path"] = str(get_build_path(src_path, '.ctx'))
|
||||
scratch["build_ctx"] = True
|
||||
|
||||
obj["scratch"] = scratch
|
||||
|
||||
config["objects"].append(obj)
|
||||
|
||||
with open(config_path, 'w') as f:
|
||||
|
||||
Reference in New Issue
Block a user