N64Recomp / N64Recomp

Tool to statically recompile N64 games into native executables

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to handle handwritten assembly functions

harvestwhisperer opened this issue · comments

I'm trying to recompile Harvest Moon 64 and am running into an issue when the recompiler reaches the osInvalDCache libultra func (handwritten assembly).

Unhandled instruction: cache
Error in recompiling static_5_800FF3A0, clearing output file
Error recompiling static_5_800FF3A0

(0x800FF3A0 is where this function starts in VRAM)

I see there are manual_funcs and ignored values in the toml file, but I'm not sure if those are where to put handwritten assembly functions. When I tried to put the function in the manual_funcs list, I got this error:

Missing required value in manual_funcs array
Failed to load config file: us.toml

The recompiler tool does a lot of special treatment for libultra functions like osInvalDCache. since that kind of function is better to be reimplemented by hand on the recomp runtime.

Your error contains Error in recompiling static_5_800FF3A0, clearing output file, meaning that the function isn't osInvalDCache or it is not properly named in the elf.
How did you build the elf? Note that the elf must be the product of building a proper disassembly and/or building source code, trying to hardcode symbols by using a linker script won't work.

Interesting. I'm using my repo here, which uses Splat to generate the elf file: https://github.com/harvestwhisperer/hm64-decomp/tree/master

Running Splat, I get this disassembly:

/* Handwritten function */
glabel osInvalDCache
/* DA7A0 800FF3A0 18A00020 */  blez       $a1, .L800FF424

Searching for static_5_800FF3A0 returns nothing anywhere

I have osInvalDCache = 0x800FF3A0; in my symbol_addrs.txt as well, so I'm really not sure where this static_5_800FF3A0 symbol is coming from. I can try to inspect the generated elf file more closely

Can confirm my elf has that address labeled as osInvalDCache

Checking my RecompiledFuncs folder, I do see quite a few static_5_<address> c files that don't use the symbols from the elf. Looks like the recompilations worked fine for those, but what's the cause/purpose of that behavior?

If you run readelf -s on the elf and search for osInvalDCache (or any of the symbols that aren't working correctly), what does it show as the symbol's size? The recompiler can only use symbols that have valid sizes in the elf, so it may be ignoring them and then finding the function later on via the static function detection process.

They're varying sizes, it looks like, but osInvalDCache is size 0

800ff3a0 0 FUNC GLOBAL DEFAULT ABS osInvalDCache

It looks like your splat yaml has asm_emit_size_directive: false, which will cause extracted asm to have 0-sized symbols. I believe turning that on will fix this case. If you have other functions that have issues, make sure readelf says their type is FUNC as that's another requirement for the recompiler to recognize a given symbol as a function.

Hm, still running into the same error with the invalid cache instruction and seeing the same amount of static_5_ functions

The new elf has this:

800ff3a0 272 FUNC GLOBAL DEFAULT ABS osInvalDCache

Another behavior in the recompiler is that by default it won't accept ABS symbols (meaning they have an absolute address and aren't in a section). You can enable that behavior with use_absolute_symbols option in the toml. However that can cause issues when dealing with overlays, since the recompiler won't know what overlay an ABS function belongs to, so I'd avoid it if possible. Alternatively it should be doable to make the symbol not be marked as absolute. I think the cause is usually that the symbol is present in one of your linker scripts (e.g. the undefined_syms/funcs files).

Ok, I cleaned up my linker scripts and that symbol is no longer marked as ABS, and it's working! Thanks for that insight.

Unfortuntately, I ran into another issue with an asm library function:

Tail call in __divdi3_recomp to 0x801107C0
Tail call in __divdi3_recomp to 0x801107E0
Negative offset for sw to stack: -8
Failed to analyze __ptException
Error recompiling __ptException

My elf file has: 164 FUNC GLOBAL DEFAULT 5 __ptException

Going to dig a bit deeper to see if I can tell if there's anything misconfigured in my project

Oh, yes, I have a branch to fix that. I can make a PR

I opened the PR ( #60 ).
Could you checkout it test it?

Sweet, looks like everything got decompiled successfully! Thanks for the fix!

I'm still getting these logs on these library funcs if it's worth anything:

Tail call in __divdi3_recomp to 0x801107C0
Tail call in __divdi3_recomp to 0x801107E0
Tail call in __udivdi3_recomp to 0x80110584
Tail call in __udivdi3_recomp to 0x80110488

Those tail call messages are just informative.

If you didn't got any other error then you should the process was succesful and you should have the generated functions in your output_func_path path.

Yep, no errors. Looks good to me