N64Recomp / N64Recomp

Tool to statically recompile N64 games into native executables

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unknown symbols with `_recomp` suffix, from ignored and reimplemented funcs

dpchamps opened this issue · comments

Wondering what I'm doing wrong / missing here:

I see that https://github.com/N64Recomp/N64Recomp/blob/main/src/main.cpp#L693-L700 adds this suffix. When I run the recomp tool on the current elf/rom that I'm working with, it generates functions with unknown symbols for each reimplemented/ignored function.

If I dump the context, I see something different from what https://github.com/Zelda64Recomp/Zelda64Recomp/blob/dev/us.rev1.syms.toml has. For example, I see a lot of this in my recompilation:

# Autogenerated from an ELF via N64Recomp
[[section]]
// snip

functions = [
    { name = "recomp_entrypoint", vram = 0x80025C00, size = 0x50 },
]

# Autogenerated from an ELF via N64Recomp
[[section]]
// snip

functions = [
  // lots of good stuff here, but also:
  { name = "__osCheckId_recomp", vram = 0x8010AA24, size = 0xB8 },
  { name = "__osPfsRWInode_recomp", vram = 0x8010AADC, size = 0x344 },
  // etc
]

But these functions are not defined anywhere. I think I would expect that? Since they're explicitly ignored. However, I do see their counterparts in the MM symbols toml, e.g. __osCheckId and __osPfsRWInode.

So what am I supposed to do with these functions in order to compile with a runtime? Should they be getting emitted with my RecompiledFunctions? For example, should I be seeing a __osCheckId_recomp.c file?

It looks like this is the full list of fns that are undefined:

osPfsRepairId_recomp
__osCheckId_recomp
__osPfsSelectBank_recomp
__osContRamRead_recomp
__osPfsRWInode_recomp
__osContRamWrite_recomp
__osViGetCurrentContext_recomp
__osViSwapContext_recomp
__osTimerInterrupt_recomp

A very important part of the recompilation process involves manually reimplementing the functions from the SDK that the game uses (The N64 SDK is called libultra) instead of directly recompiling them. The SDK is in charge of interacting with the N64 hardware, like drawing to the screen, reading inputs from the controllers, reading the game from the ROM, saving the data to the cartridge, etc.

Since we need the game to interact with a different hardware then we need to reimplement those functions, that's why the recompiler tool do not emit them.

So you are getting these linker errors because the recomp tool expects those functions to be reimplemented by the recomp runtime, but the runtime haven't implemented them yet. You would need to wait for a proper implementation for those functions or try to implement them yourself, which can be kinda difficult because of the nature of recompiled functions and because you would need to figure out how those functions should behave.
Alternatively you could implement them as stubs and hope those are not critical for the game. The Zelda64Recomp repo has a few of them

Btw what game is this?

This is what I was suspecting, thanks. I got past it by stubbing them out for now, and will implement them in the runtime.

Would you all be open to accepting a "runtime boiler plate"? I spent some time stripping the MM runtime of MM specific things to get a binary compiled for the game in question. It's non-functioning at the moment (meaning -- it can compile, but not much interesting happens) , but I can see a pretty clear path to an "empty runtime".

There's currently an on going effort to create a minimal example of a recomp project so other people can use it as an starting point. It would of course be stripped from everything MM related.
Thanks for the interest anyways!

Great to hear! I'm happy to help if yall are looking for it :)

Is there an active branch of ongoing work?

Hey @dpchamps, just curious if this is Harvest Moon 64 since we had some discussion about it and the repo makes use of the same libultra functions you listed. I recently updated all the libultra symbols in the decomp repo and when I run the recomp (using this branch), and I'm also getting these tagged with the _recomp suffix during the recomp process. All of them look to be libc/libkmc:

bzero_recomp.c
cosf_recomp.c
ldiv_recomp.c
lldiv_recomp.c
memcpy_recomp.c
rand_recomp.c
sinf_recomp.c
sqrtf_recomp.c
strchr_recomp.c
strlen_recomp.c
__assert_recomp.c
__divdi3_recomp.c
__muldi3_recomp.c
__udivdi3_recomp.c
__umoddi3_recomp.c

Is this expected for non-libultra library funcs?

This is expected behavior. The functions you listed are either part of the C standard library or libgcc. Those are renamed to avoid symbol conflicts with the host's real implementation for those functions.

@harvestwhisperer yep! Sorry @AngheloAlf I missed you asking what game it was, it's harvest moon 64. Unfortunately been too busy with writing code for work to make more progress here.

Closing this issue seeing as https://github.com/N64Recomp/N64ModernRuntime exists, and the question has been answered. Thanks @AngheloAlf !

Most of these functions in the original list are internal libultra functions and should only be being referenced by other libultra functions. This indicates there are probably libultra functions that haven't been named yet in the decomp, or that the names aren't coming through in the elf (due to them being static). For example, __osViSwapContext is only ever referenced by __osViInit and viMgrMain, both of which are themselves ignored by the recompiler (since they themselves are only referenced by osCreateViManager, which is reimplemented).

If the issue is that the functions are static and therefore missing in the elf (which tends to happen if the game uses ido), then you can manually name them in the toml instead via the manual_funcs mechanism. Here's an example from another game I've tested:

manual_funcs = [
    { name = "func_8023DA20", section = ".core1", vram = 0x8023DA20, size = 0x54 },
    { name = "__CSPHandleNextSeqEvent", section = ".core1", vram = 0x8025E438, size = 0x684 },
    { name = "_gcdialog_freeZoomboxes", section = ".core2", vram = 0x8030F030, size = 0x48 },
    { name = "__actor_free", section = ".core2", vram = 0x80328028, size = 0xF4 },
    { name = "_baModel_preDraw", section = ".core2", vram = 0x80291ac4, size = 0x2C },
    { name = "__chFrogMinigame_spawnJiggy", section = ".BGS", vram = 0x8038cb20, size = 0x28 },
    { name = "__chFrogMinigame_textCallback", section = ".BGS", vram = 0x8038cb48, size = 0x6C },
]