Script/Code mod support with TinyCC#156
Open
Mickemoose wants to merge 3 commits into
Open
Conversation
Script/Code mods in C using Tiny C Compiler. - Mods are compiled at runtime - Mods are packaged into o2r files - Hot Reload for mod development (can be a little finicky) - some tools to convert pngs and wavs for mods
MSVC's WINDOWS_EXPORT_ALL_SYMBOLS exports functions but not non-trivial global data, preventing mods from resolving engine globals like gGCCommonLinks. Add a tiny accessor function gGCCommonLinks_Ref(int) that returns entries from the engine's gGCCommonLinks array, and expose its address via sModBridgeAnchorFighterListRef so TCC/mods can resolve it. Note: no bounds checks are performed (callers are expected to use engine enums).
Add a wrapper gMPCollisionGroundData_Ref and anchor symbol sModBridgeAnchorGroundDataRef in port/port.cpp to expose the engine's MP ground collision data pointer to modules. This lets mods read map_bound_left/right/bottom (used for distributing spawn positions and stage geometry) via the same export hole used by gGCCommonLinks.
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add TCC mod loader and workspace template
What this adds
The runtime side of TCC source-compiled mods. Mods drop into
mods/next to the executable as folders or
.o2rarchives. At startup theengine compiles each mod's
.csource via libtcc, links it againstBattleShip.def, and callsModInit. The Mods menu has a Hot Reloadbutton that unloads everything, recompiles from disk, and re-runs
ModInit.Files
port/mods/(new): HookManager (per-mod hook ownership + safehot-reload), SymbolResolver (engine symbol lookup by name),
mod_bridge (
mod_install_hook+mod_resolve_symbolexposed viaBattleShip.deffor mods to call).port/hooks/(new): event firing system. Mods subscribe withREGISTER_LISTENERfromMOD_INIT. Engine events fire fromport.cppandgameloop.cpp.port/audio/mixer.{c,h}(new): PCM voice mixer hooked intoAudioPlayerPlayFrameso mods can play custom audio.port/gui/PortMenu.cpp: adds a Mods section with a Reload button.port/port.cpp: brings up SymbolResolver / HookManager at startup,mounts
mods/, runs ScriptLoaderCompileAll+LoadAll. Tearsdown in reverse on shutdown.
port/gameloop.cpp: fires the per-frame engine event so mods canhook into the frame loop.
tools/merge_mod.py(new): the asset preprocessor and TUamalgamator every mod's CMakeLists invokes. Walks
.cincludes,decodes PNG/WAV/AIFC assets to N64-format inline bytes, and
produces the single
.cfile libtcc compiles.tools/{aifc_to_wav,wav_to_pcm_inc_c,png_to_rgba16_inc_c, png_to_ia8_inc_c}.py(new): asset converters for authoring.workspace/template/(new): starter scaffold for new mods withmanifest.json,CMakeLists,mod.h,demo.c, README.cmake/ModO2R.cmake(new):ssb64_add_mod_o2r_target()helperthat wires
cmake --build . --target mod_<NAME>_o2rtotorch.exe pack.CMakeLists.txt: vendors MinHook via FetchContent for the runtimedetour primitive, copies libtcc headers and the runtime DLL into
the build dir, generates
BattleShip.defviatcc -impdefpost-build.
What's not in this PR
workspace/ships only the template.bump in this PR depends on that PR landing first.
Dependencies
requires this LUS PR
How to test
mods/directory; engine shouldrun normally with the loader idle.
workspace/template/output/into<install>/mods/as afolder and relaunch. Engine logs
Initializing script: templatein
ssb64.log; the demo mod'sMOD_INITruns..o2rviacmake --build . --target mod_template_o2r, drop the.o2rinmods/, relaunch. Same behavior.src/demo.c, runcmake --build .in thetemplate, click Hot Reload.
ssb64.logshows the unload +recompile + re-init cycle without restarting the engine.
Notes for review
MOD_INITruns inside aSetCurrentOwner/ClearCurrentOwnerwrapper so everyInstallHookcall gets tagged.UnloadAllcallsUninstallHooksForOwnerper mod before the mod's PE image isfreed. This is the part most likely to bite if mod lifecycle
order changes.
workspace/<NAME>isn't compiled by the enginebuild;
merge_mod.pyjust preprocesses + copies. The runtimecompile happens via libtcc when the mod loads. So mod build
errors don't surface until launch +
ssb64.log.mod_bridge.cppis anchored explicitly inport.cppso thelinker doesn't drop the bridge
.objat link time. If a futureport.cpprefactor removes those anchor lines, mods stop beingable to resolve
mod_install_hook/mod_resolve_symbol.Suggestions welcome
workspace/folder belongs in the repo or in the shipyard (unsure of its current status).merge_mod.pytooling makes sense attools/rootor under
tools/mods/. or if any of the mod related tools belong in here or in the shipyard.based on this Starship PR