Skip to content

Conversation

@Mushie64
Copy link

@Mushie64 Mushie64 commented Apr 25, 2025

This adds a check on ROM load through the 0x13 behavior scripts area, wherever it is as pointed to by segment 0x15 segment load level scripts (shoutouts to Pie for repointing to an extended copy of the vanilla area far into extended ROM territory EDIT: apparently that's due to ROM Manager and "global object bank"). The check reads through all scripts to find which behaviors contain the calls to the default functions for reds/secrets/panels loop (= wouldn't work for collectables with custom ASM).

Currently this helps detect SS4 secrets and nothing more AFAIK, but if someone else does a funny behav scripts area copy/repoint in the future, it should be covered too. To my knowledge (tested with ~10 hacks), whatever collectables were already getting detected, still get detected the same.

A few places rely on imperfect but reasonable assumptions, as far as I checked. (For example: that a 09 command always ends a behav script; in vanilla, a couple places don't immediately start a new one with a 00 command, but in practice we don't care for the behaviors that follow them, so this still works). EDIT: Outdated after implementing aglab's suggested approach. Still has a few potentially-breaking assumptions.

This seems to have little overhead, but is probably not as optimized as possible in speed or memory usage. Suggestions to improve are appreciated. As well as requests for tweaking like datatypes or cleaning up excessive comments.

Trying a new SearchObject-like function. The idea is to take the pointer
to behav script of the current object (already retrieved), but read into
it through the script commands, find any 0C calls in a 08-09 loop, and
if THAT matches the specified function address (pass in a reds/secrets
function), consider the object a collectible.

A direct example that this tries to detect is Shining Stars 4 secrets -
custom behav script, but using the vanilla bhv_hidden_star_trigger_loop.
This function tries to expand on the locating of bank 13 in
GetBehaviourRAMAddress() without thrashing said function. The intention
is to mirror the functionality of the decomp function. Possible edge
cases are untested.
Should offset from ramPtrBase instead of 0x80000000 when trying to read
data at a pointer (thanks aglab). "behaviour" from obj->0x20C is bit
shifted for that.
Data is read in little endian, so for each 4-byte behav line search the
command bit at last instead of first index.

The new search function works now (at least in SS4 c1). Mirrored
functionality for the display (ROMManager.cs) still not implemented.

Quirks:
- TODO: Still not using "state" (for panels).
- No caching of already read scripts.
- Still small chance to break on longer behav cmds inside a 08-09 loop.
Use the same logic as the decomp counterpart (otherwise using this
function in SearchObjects() returns the address without the leading
0x80, resulting in garbage.)

Difference: If the address does not look segmented (first byte is
bigger than 1F), return it without changes. The decomp counterpart
seems like undefined behavior for this case.
Adds support for Shining Stars 4's secrets.

Same algorithm as in MemoryManager (commit 72fb886 and fixes up to
ed87a71), but based on behav scripts' ROM addresses instead of live
process addresses. Those are deduced from level scripts' loading of
segment 13. On the way it is assumed that the segment 15 start address
in ROM is constant.

The implementation in GetAmountOfObjectsInternal has hacky parts (filling
the 3-byte behavior array to 4 bytes, reliance on segment 13, reliance on
indices for read bytes). Future commits are welcome to clean up.
Should avoid "leaks" into unintended behaviors while reading the current
one. For example, the common Warp (Mario Start 1) is one of many 0A 00
00 00s. That this region falls into an unused script that eventually
   hits a loop and terminates (i.e. the previous commits didn't break
   immediately) is a lucky coincidence.
calls

Why copied function instead of overload with default parameter?
I decided that checking state for every object would be wasteful for 98%
of them, so don't have such a check in the function for everyday usage.
(I can already hear future me's curses over the footshots when changing
the function code though.)
Moves checking for customized behavs(ala SS4) effectively from
UpdateStars() of main to init of ROMManager instances. Restores
GetAmountOfObjectsInternal() to original code and signatures from before
this branch, since checking directly for ASM call addresses is not
necessary after ROM init.
MemoryManager still uses ASM-call checking for collected collectables,
optimizing this is for another commit.

Tested on SS4, Eureka, vanilla. No functional regression, delay between
loading level/area and drawing its collectables minimized.
Should not break in practice, just adds a shady dependency on static
variable through class instance.
Tested (again) with SS4, Eureka, vanilla. No major overhead noticed
versus official 1.36.
@Mushie64
Copy link
Author

Commits mention some added functions like SegmentedToVirtual() and SearchObjectsByBehavCalls(). I removed most unused ones in the last commits, except for a couple of helpers in ROMManager that I forgot to check for being unused. It shouldn't hurt to keep them.

!! BREAKS SS4 secrets detection - detects only vanilla secrets behav
instead of only SS4 secrets behav in that ROM (first instead of last).
Will improve per aglab advice in next commit (find all eligible behavs).

Changed behav scanning logic per
aglab2#18 (comment).
Now only parses actual function call and "start script" command.
Still has a `while(true)` loop and while-possibly-breakable loops, will
seek to improve in next commits.
Fixes SS4 secrets tracking. For each listed function call, tracks all
behaviors using it, so all "reds/secrets/panels-like" objects will be
summed up for the level count if multiple exist, and unused copies won't trip up deterministic counting.

Refactors some code - cleanups and format changes. Collectible behaviors
in ROMManager.cs changed from byte arrays to uints (in Lists) and default to being
scanned for. MemoryManager will only search for the hardcoded vanilla
values if it is somehow initialized but a ROMManager isn't.
Resolves requested changes. I chose magic values based on reasonable
worst-case scenarios considering vanilla code (further explained in code
comments). Weird hacks may break the assumptions, but they're as good as
it gets.
@Mushie64 Mushie64 requested a review from aglab2 August 28, 2025 15:15
@Mushie64 Mushie64 changed the title Detect Shining Stars 4 secrets Detect collectibles with behavs repointed by ROM Manager global bank Aug 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants