Found this function in RIC, it's very similar to the one in DRA, which
is nice.
Patterns of zeros in the rodata indicated that this should be the start
of a new file, which also makes sense since CreateEntFactoryFromEntity
comes with it.
RIC has its own array of blueprints, I'll probably add that to the splat
later on but that seems like material for a separate PR. For now we
focus on the entity function.
This appears to control Richter using an item crash.
We add an enum for the subweapon IDs. This should be useful in other
places but for now makes the switch much more readable.
Loops in EntityAlucard and UpdateEntityRichter indicate that these 16
elements of g_Player are an array of 16 values. The known ones appear to
be player status effect timers.
While those functions have a long-standing issue preventing them from
matching, they provide enough evidence to suggest that we should make
this change. I have changed all existing uses, and changed the symbols
so that any remaining non-decompiled functions will use the proper form.
It would probably be beneficial to make an enum for the 16 elements of
this new array, but I'll hold off on that for now until we can identify
the purpose of more of them.
---------
Co-authored-by: Luciano Ciccariello <Xeeynamo@users.noreply.github.com>
This one has a corresponding DRA function. I believe these relate to the
fading shadows that appear behind the player, but I'm not confident
enough about that to go ahead and rename things. For now, it's
decompiled at least.
I had the suspect menu strings were part of a string of arrays since a
while. So I come up with a `g_MenuStr[]`, which removed the need of many
fake symbols. I did not yet come with a bunch of `#define`s to resolve
some magic numbers. Luckily you can guess which string is which from the
context of the function. Resolving the HD strings might give me more
clues on how to come up with good defines.
I decided to go for the route of having a `lang_us.c` and a `lang_jp.c`
for the sake of maintaining things simpler. This is also due to the fact
the HD build orders the japanese strings in a different way, making
things a bit harder. Any modder can just come up with their own
`lang_XX.c`, translate the menu in the language they want and just link
it, without touching the original files.
For the test app things were tricky. I've been debating how to implement
it as SOTN-encoded strings are not pre-encoded on compilation time like
the PSX toolchain does. Instead they are burnt into the executable as
UTF-8 characters. Instead of encoding them on-the-fly in `MenuDrawChar`,
I decided to re-use `AnsiToSotnMenuString` to pre-encode all the strings
and re-route each `g_MenuStr` pointer to the converted strings. This is
both efficient at runtime and prevents to modify the existing matching
code. Now the menu looks amazing.
I thought this was going to be much harder to do. I ended up doing
incremental steps in each commit to ensure having healthy checkpoints in
case things were going south. The tool ` ./tools/sotn-str.py parse
disks/us/DRA.BIN 0xOFFSET` saved me sooo much time. But we need to tweak
it to deal with Japanese characters.
This one was very complicated. It has 4 different switches in it, all
with their own rodata!
It also interacts with a lot of different parts of the game, including
various unknown members of structs like g_Player, so it might be a
useful resource for starting to understand what some of that stuff is.
One goto left in it that I couldn't get rid of, the jump is between two
unexpected locations that seem very different from each other.
Scratch here if anyone would like to attempt improvements:
https://decomp.me/scratch/0k84D
Not totally sure what this one is for, but it's connected to saving the
game.
D_801379C8.vy is very heavily used, I'm not sure what the purpose of
that SVECTOR is. But anyway, it matches.
Mostly a proof of concept to extract resources from `BIN/F_GAME.BIN`.
There are tons of hacks to make this work:
* Tweaked png2s to decode binaries into PNGs
* Add a `config/gfx.game.json` that describes how to extract different
sprites out of a binary file
* Coded the palette location by reading the `clut` parameter in the
source code. A clut value of `0x196` corresponds to `"palette": "0x96"`
or `"palette": 150`.
* Coded the bits per pixel for a couple of 8-bit images
* Coded the palette location of those graphics that expects the palette
from DRA.BIN instead of F_GAME.BIN
* For all the undiscovered palette, I called the files `unk` and
defaulted their palette to grey
The expectation is that sprites will slowly be documented and added into
`config/gfx.game.json` by modders and enthusiasts. This does not yet
pack back these PNGs into the binary file. The way these assets are
extracted is probably not final or perfect, but we have to start from
somewhere.

The next subweapon entity. This is for the lightning subweapon. Happy to
take name suggestions but for now we have a comment on the function so
doesn't really matter if we name it immediately.
Remove a bunch of fake symbols that were overlapping with `D_80097488`.
I created a new struct called `Pos`. Since it is very similar to
`Camera` I placed them close-by as in future we might want to merge
them.
I created some symbol hints like `D_8009748A_x_i_hi` as there are a few
functions that still use them.
Nothing super special here, just another RIC function. I believe this is
a helper function for Richter's state machine, since it switches on
PLAYER.step_s.
This was done by comparing the src/servant/tt_000/spriteparts.c file to
the data I found in RIC 170AC.data.s. I then wrote a Python script to
take the data in the data file and output a C file which has all the
same formatting as that existing spriteparts.c file. This is a big chunk
of the .data section for RIC, so it's nice to have it pulled out to a C
file now.
The `const int PRIM = -5;` is very weird, I am not sure what's going on
there. The struct makes sense on the surrounding functions. I am not
even sure if the function is ever called as it involves the use of a
cutscene dialogue, never seen in the SEL overlay.
Mostly a duplicate of a DRA function but enough different logic to be
fairly different.
Interesting that this uses the "dead player" string which matches HD but
is different from in US DRA.
There are 3 strings in DRA that were being left in rodata and printed
with `FntPrint(&whatever)`, this fixes two of them (the third will first
require other stuff in rodata before it to be extracted).
I also discovered that HD uses a different string in one of those spots
which was a big surprise! Weirdly, US has a string written in Japanese
(though using Latin characters) and HD has a string written in English.
The function that keeps track of if Richter has pressed down-up-cross to
do a High Jump move.
This is the first time we have a button combo being tracked outside of
DRA, so I moved the ButtonComboState struct from dra.h to game.h.
When the input succeeds, a function is called, so I've named that
function DoHighJump and also made general changes to that function to
bring it up to date with our current code standards (like FIX()).
I think those are the main highlights!
More data importing and more documentation as data is providing more
context.
I also found a good amount of "fake" symbols, like in `DrawHud` and
`DrawHudSubweapon`.
Quite big PR that aims to document most of `menu.c` and make the code
more portable.
I had to declare `u16* func_80106A28(u32 arg0, u16 kind);` on the top of
`main.c`. Without it the compiler assumes it returns an `int`, which is
not big enough for 64-bit pointers. It took me a while to realise that
was the cause of the crash. We will have more of them in the future.
EDIT: Ignore the commit `******* FIX`. It was meant to be squashed for a
clearer commit history but I forgot to do it.
Highlights:
* Move `MenuContextInit` into `main.c`
* Document `Unkstruct_800A2D98` as `EquipMenuHelper`
* Use shorter global variable names
* Change `D_801375CC` type on Saturn
* `g_MenuInit` is different between JP and US due to different window
arrangement and text width differences
As per title. I also added a new tool called `dirt_patch`. As I
mentioned in our Discord server there is some left-over data from
previous dev builds in DRA.BIN and potentially elsewhere too. The tool
uses the new file `config/dirt.us.json` which stores a list of patches
to avoid crazy hacks and `#ifdef` for the sake of getting a match. I
hope this tool will not be abused.
Extract the memory card icons out of DRA.BIN and SEL.BIN.

I also took the opportunity to extract `g_MemcardPortMask` into its own
source file `save_mgr_pre.c`. Unfortunately this is required to keep the
original data order. This suggests that most likely the icon palette and
bitmap were baked into the original `save_mgr.c` as byte arrays. I
decided to take a different approach and extracted them as PNGs for
better moddability.
I had to spin-off Splat into a new fork due to some breaking changes on
0.18.0.
This is actually the last function in RIC (by which I mean "There are no
functions in RIC which are located later in the ROM than this one"), so
that's neat. There was a mistake with the splat, where the nop in the
delay slot for the return instruction of this function was being treated
as the first 4 bytes of SBSS, rather than as the final instruction of
this function, but luckily I worked that out and fixed it in the splat.
This is extremely similar to the one in DRA. However, it stores to 0xB0
in the entity. This is interesting, I've seen that being a significant
address in other RIC functions too. I added it to the extension that was
used for this entity in DRA.
Next entity function in the same file I've been chewing through. Only
one left in here!
There's a really weird block with a bunch of trig functions that I can't
make sense of. Might be doing some kind of weird 3D transformation? Not
sure, but it matches. Would have never gotten it without the permuter.
Scratch here if you want to play with anything, especially if you can
remove the temp_a1 being used in the block of trig.
https://decomp.me/scratch/xdNx7
temp_v0 is also a bit funny, not sure why it would use lhu to load a
variable which is explicitly an s16 and we're negating, but whatever.
Everything matches so submitting now.
Refactoring with no functional changes. `5087C.c` is currently a bloated
file that contains both a game state machine to handle the gameplay and
the menu handler.
This PR splits the menu handler into its own new file `menu.c`.
The way I detected the file split is the amount of `.rodata` strings
defined between the new last function of `5087C.c` and everything else
related to the menu.
This is a pretty big function, and I'll admit that my code for it is
pretty low quality. But it matches. Scratch is here if you'd like to
make improvements:
https://decomp.me/scratch/xok2Z
A lot of the things that I tried to remove the gotos and temp variables
didn't work.
The entity extension for this uses f32 variables. Those are defined in
`game.h`, but `game.h` is not accessible to `entity.h`, so I moved the
definition of f32 to `types.h` which is accessible in all places and
overall seems like a better place for it anyway.
After finding a copy of GetFreeDraEntity in RIC, I decided to rename the
function (in both DRA and RIC) to GetFreeEntity. Similarly, the function
right after it is GetFreeEntityReverse (since its logic runs in
reverse).
I also found CreateEntFactoryFromEntity in RIC, so I renamed that to
match the version in DRA. We will need to go through and use the FACTORY
macro for its uses, but I'm not going to tackle that quite yet.
Seems there is a lot of work to be done making RIC catch up to DRA,
we'll see if I keep working on that moving forward, it's neat to find
the ways the two match.
Another entity function in RIC, continuing to work through these to
remove the rodata padding.
Still no knowledge of what this function is for but once I get these
done I'll focus on getting the entity factory system working in RIC like
we have it in DRA, I've found a lot of the important functions already.
This appears to be an entity updating function unique to RIC. I do not
know what it is for yet.
Main reason for doing it is that it has rodata and the file it is in
currently requires a rodata padding to be present. Having this one
working and parsing the rodata into it means we can move the padding,
and once we finish everything in this file, we will be able to remove
the padding entirely.
As mentioned in the previous PR, this removes a few rodata_padding
variables by simply un-splitting the files involved here.
There are two more paddings I found in other places; I will look into
those next but don't want to do too much file reshuffling in one PR.
This PR takes 3 files and merges them into one, removing the padding in
the process.
Another function, not sure what it really does besides messing with a
bunch of primitives.
Some clues in the rodata (particularly 00 00 00 00 bytes) indicated that
we should merge these C files, so I did.
An issue with maspsx was discovered in the process of decompiling this
one. I submitted a PR to maspsx which was accepted, and therefore I also
updated maspsx in this PR in order to capture the fix.
For some reason this was included as:
```
#if defined(VERSION_US)
INCLUDE_ASM("asm/us/dra/nonmatchings/627C4", func_801028AC);
#elif defined(VERSION_HD)
INCLUDE_ASM("asm/hd/dra/nonmatchings/627C4", func_801028AC);
#endif
```
But that wasn't actually needed, the functions are identical. Not sure
why it was that way but it's fixed now.
- Main focus is an update of func_8015D020. That had a TODO to remove a
variable, which I have now removed. I also used enums for player steps,
and changed the speeds to use FIX(). I also cleaned up the control flow
to remove the goto.
- While working on that function, I noticed that it calls an unnamed
function. The duplicates list at
https://raw.githubusercontent.com/Xeeynamo/sotn-decomp/gh-duplicates/duplicates.txt
indicates that SetSpeedX was missing from RIC. I added that in now and
adjusted all uses in RIC, including the ones in func_8015D020.
That's about it; these are two different changes but given that we're
just changing the format of them, I'm assuming this will not be an issue
to have them in one PR.
Had to add PlayerSteps into RIC since we're using enums for Player.step
and SetPlayerStep. I think maybe these should be moved out of dra.h and
into somewhere more generic, but for now copying it over works well
enough. If there are steps that are reused between Alucard and Richter
for mutually exclusive moves (ie, step N is an Alucard-specific move for
Alucard and a Richter-specific move for Richter) then we will need to
maintain separate lists. This works for now.
Handles a bunch of the internal logic of saving the game. There is a
small group of functions that deal with the process of saving; once we
get them all decompiled it makes sense to rename them once we understand
the individual steps involved.
This appears to generate the menu that appears when you use a save room.
This is obvious by the strings present in the many calls to
`func_800F9D88`.
Appears to be closely related to some other functions which may make the
logic a bit more obvious. Cool to have this working though, might be
useful for some types of research into how saving works. I wonder if all
these messages have actually showed up before for real players.
Many of the strings feature Shift-JIS characters (specifically, the
periods, question marks, and the 0, 1, and 2 numerals). Big thank you to
Sozud for helping me understand those weird bytes in the strings!
Parsing rodata for strings is pretty fun!
Happy to change the name of this function, but wanted to at least
replace the numerical placeholder.
Follow-up to #797 by decompiling the MAD counterpart and share all the
functions within the same file. I renamed the function as
`UnkPrimHelper` as I do not know what it does.
This is an old one that I had almost-matching, I set the permuter
running for a few hours while I was doing something else and came back
to a match!
It appears to be responsible for managing some type of alternate player
status. This is evidenced by the
```
if (!(g_Player.unk0C & 0x10000)) {
DestroyEntity(entity);
return;
}
```
That variable holds statuses like PLAYER_STATUS_STONE,
PLAYER_STATUS_POISON, PLAYER_STATUS_CURSE. We do not have 0x10000
identified yet. The entity is made by an entity factory which currently
does not have any decompiled calls, so hopefully when that happens, we
will know exactly what this entity is responsible for.
Not sure what this one does, but it's in all the overlays.
I couldn't get `mad` to work, since it gives errors when I reference
functions like `RotMatrixZ` (which isn't even one of the new `gte_`
defines). I figured we can leave that for later since `mad` is its own
weird thing.
I also found an issue with the splat for `no3` where some boundaries
were being drawn in the wrong places; this is now corrected which allows
the function to work in that location.
The function takes a primitive as its argument and does some stuff with
it. I don't know what it actually does. It appears that the different
overlays use it in different places (and some overlays don't call it at
all). The function loads an external SVECTOR from a variable, which I
added to the `.h` file for each overlay. The vector is in a weird
location in some overlays, especially in no3 where it appears to be the
last few bytes of the rodata.
Anyway, happy to take naming ideas for either the function or the
SVECTOR that it loads. And I imagine we'll end up renaming those sp
variables.
We have a lot of casts and especially LOH calls in this one. Maybe we're
interpreting the primitive wrong. It doesn't match up with the FakePrim
we've been using lately, so I don't know what to make of this.
I think those are the main highlights! There aren't many functions that
use the GTE and it's nice that there is so much duplication so we can
deal with a lot of them all at once. I expect a lot of changes on this
one so please don't hold back :)
Here's the scratch for one instance of the function, in case you'd like
to play around with anything: https://decomp.me/scratch/N5RR5