This improves the function readability from the already decompiled PSX
functions. Since the PSP build is compiled with `-O0`, the statement
order is much clearer. Even `if (entity->facingLeft != 0)` and `if
(!entity->facingLeft)` produces different output on the PSP build. I was
able to remove a couple of temp variables too.
---
There are a few functions I cannot match due to a trailing `nop` at the
end of the function. It looks like the overlay have functions aligned by
`8`. I do not know how to trigger that using MWCC or if it is a linker
thing. Two functions that have this problem are `DestroyEntity` and
`func_801746A0`.
![image](https://github.com/Xeeynamo/sotn-decomp/assets/6128729/754fe1ef-5d2d-4b86-a3fb-736a8058347d)
TT_000 is the first overlay from PlayStation 1 that we are now able to
compile from the source and produce a 1:1 binary. This lead me to start
exploring the same overlay from the game Castlevania: Dracula X
Chronicles, which contains a PSP re-build of Symphony of the Night.
This PR adds all the infrastructure to add the same flow for a PSP
matching decomp. Use `export VERSION=pspeu` and then the usual `sotn`
command to splat the overlay, build it and check if it matches. Running
`make extract_disk` should not be necessary as the same ISO used from
`VERSION=hd` is also used for `pspeu`, so you will probably have it
extracted already.
Some important notes about the PSP build:
* The whole PSP build seems to be compiled with `-O0`, which makes it
much easier to decompile
* Having ŧhe PSX, PSP and Saturn builds will allow to easily
cross-reference the code and reduce fake matches
* `disks/pspeu/PSP_GAME/USRDIR/res/ps/hdbin/tt_000.bin` is the HD PSX
build
* `disks/pspeu/PSP_GAME/USRDIR/res/ps/PSPBIN/tt_000.bin` has the same
code from the HD build, but for PSP
* `disks/pspeu/PSP_GAME/USRDIR/res/ps/PACK_E/TP00.BIN` is the same as
above, but it packs both overlay and graphics. This is the file the PSP
game seems to actually use
* The PSP build uses the Metrowerk CodeWarrior's C compiler, which is
very different from the GCC one used on PSX.
* Thanks to @mkst lead, we found a way to still use the GNU assembler
and linker
* MWCC uses [wibo](https://github.com/decompals/WiBo/), a think
compatibility layer to run Windows CLI tools on Linux. It is much more
lightweight than Wine.
* MWCC does not support the `INCLUDE_ASM` dialect, so the custom
pre-processor `tools/mwcpp` had to be created
* The exact MWCC compiler version is unknown, but I suspect it is `build
147`
* I am not yet sure of any implications for using GNU AS and GNU LD
instead of the MW correspondent tools
* Not all the functions can be correctly disassembled, spimdisasm will
just produce a bunch of `.word 0x________` due to the in-progress effort
of adding the Allegrex-specific opcodes support
---
TO-DO list before marking the PR as ready:
- [X] Add PSP build to the CI
- [x] Add progress reporting to the PSP build
- [x] Integrate source file from `src/servant/tt_000_psp` to
`src/servant/tt_000` to promote the psp build as first-citizen
---
TO-DO in a follow-up PR:
* Figure out what `header` is: can we extract it as assembly code? or
maybe as custom re-compilable asset via splat? Is it a MW stuff or a
Castlevania-specific file?
* Get rid of the last line in `Makefile.psp.mk`
100% decompiled.
`US` adds some padding to have the file exactly 40KB long. The HD
version does not add any padding, hence why I ended up producing
`tt_000_raw.bin`. I would have used just `tt_000.bin` as a name as found
in `disks/pspeu/PSP_GAME/USRDIR/res/ps/hdbin/tt_000.bin`, but on
Windows-based file system it would collide with `TT_000.BIN` due to the
OS having case insensitive names.
I modified `make clean` as I found annoying that `VERSION=hd make clean`
would wipe out `us` build stuff.
The only different function in HD is `ProcessEvent`, which has a weaker
check. Another hint suggesting HD being older than US.
`s32 _unused[26];` added enough padding in the bss section to get an
🆗 . I am pretty sure it is unused data because the final binary is
not aligned by any power of 2.
Big thanks to @mkst and @Xeeynamo for looking into my rodata issue on
this one! Still not sure why it worked the way it did but glad we got it
working and we can now get this function in.
Solves an annoying fake match that made the US version to match but not
in the HD version. Special thanks to @Gillou68310 for figuring out the
right switch/case pattern!
Don't get fooled by the size of this function. I struggled more than I
thought I would. I think it generates the map bitmap but I am not yet
sure. There is a lot that I still do not understand of how the map gets
filled while walking through the castle. I do not even know how
partially explored maps work (e.g. when you get the Castle Map 1 or 2
from the Librarian but you do not actually pass by those unexplored
areas). I would like to wait to know more of the logic here before
documenting.
![image](https://github.com/Xeeynamo/sotn-decomp/assets/6128729/e3b9b89c-6a6b-49a9-8804-b0f49da6dc79)
This thing here. Special thanks to @sonicdcer who helped me on the final
reg swaps!
I renamed `D_8003C104` as `g_ClutIds`. I am not a fan of the name, but
it gets used by `poly->clut = g_ClutIds[xyz]`, the function that
populates the table is called `GetClut` and the [official
docs](file:///run/media/xeeynamo/wd_black/SDK/sony_ps1/psyq_sdk/DOCS/LIBREF46.PDF)
mentions _Calculates and returns the texture CLUT ID_ . So that seems to
be the most appropriate name.
A relatively small but complicated function. I matched it by decompiling
from scratch while taking some inspiration from an old scratch made by
@sonicdcer
Some data belong to `7A4D0.c` but I had to import to `7E4BC.c` instead
due to the `factory_blueprint` getting extracted in the between. I think
in the future those JSON assets need to generate C files.
Completes `90264.c` with the exception of the BSS section.
After this PR I am thinking to either decompile and move
`func_8012F178`, `func_8012F83C` and `func_8012F894` into `90264.c` as
they all follow the same pattern, or move back `90264.c` before the
split back into `8D3E8.c` as all the code seem to be related to the wolf
form.
As per title.
`#if !defined(VERSION_PC) && !defined(M2CTX)` allows
`tools/decompile.py` to work on files where the GTE instructions are
used. Otherwise it wouldn't normally work.
Big function, does a bunch of stuff with DRAWENV which is neat.
Had to create an inline for addition, otherwise all my `lh` instructions
were becoming `lhu`. Maybe there's a better solution, I'm not sure.
This is going out to a new file due to weird rodata stuff, I'm hoping
decompiling EntityDraculaFinalForm (which I have a working scratch of)
will allow everything to settle into place, but we'll see.
First function of my new effort to make progress in ST0.
There's a fun bug in case 5 where they forgot to increment their prim.
This required the creation of a new variety of Primitive, since there's
strong evidence of an `f32` at offset 0x20. For now it's
draculaPrimitive, but maybe we'll find more uses of it in the future.
I think those are the main highlights. No pressure to merge this one
quickly, I'm expecting progress on ST0 to be slow.
Another disappointing non-match, even closer than #1008 . There is only
one registry swap in one single line. I've been permuting for a day
without success. Putting this here if anyone wants to give it a try:
https://decomp.me/scratch/AuSvv
There were some symbols overlapping with the `g_Entities` array. By
fixing them I also de-faked `func_801B519C`. I included the removal of
`g_api_AllocPrimitives` too as I did not see much point of doing it in a
separate PR.
I am still unsure of the size of `g_CastleFlags` and unfortunately I
doubt it will be clearer before start decompiling new stage overlays.
A side-project I've been working on that helped me understanding some
structures that are now a bit better documented in #1034 . Richter
sprites are extracted as usual. Doing `python3
tools/splat_ext/spritesheet.py decode disks/us/BIN/ARC_F.BIN assets/arc
alucard disks/us/BIN/F_GAME.BIN 1` can extract Alucard sprites too.
There is no repacking yet as I want to avoid using splat for this one.
Big file shuffle to get this one working, but it works!
I have now made some degree of attempt at every function in RIC. Now we
circle back to finish the hard ones!
Required splitting to a new file.
Yet another instance of PRIM_LINE_G2 using its own type of Primitive,
which is neat.
Also resolved another member of that primitive. This is getting wild!
RIC is so close!
This one was pretty complicated but I'm glad I got it working. Not
completely certain what this does but good enough for now. The two
functions are even more similar than DRA and RIC functions usually are.
For any comments to be made, feel free to only comment on one of the two
instances and I will make the change on both.
Did the DRA version of this a while ago, now here is RIC. Very little
overlap, generally speaking, which kind of surprises me. Anyway, more
progress on RIC!
This monster is finally done thanks to the assistance of @ser-pounce .
Really not sure what any of this logic is for, but there you go. Great
to have more collaboration happening!
------------------
Co-authored-by: ser-pounce <ser-pounce@users.noreply.github.com>
Tried to comment this one pretty heavily since it's a relatively more
comprehensible function than usual.
Otherwise nothing too special or surprising here. I'm surprised at how
case 1 works though, I wonder what condition it's actually testing for.
Oh, and there was one pesky fake variable in there, but it's not too
egregious. It's in case 5.
This is the entity that runs when Richter dies in the prologue, gets
revived, and makes a glowing white pillar effect out from his body. You
can see it at 1:33 here: https://www.youtube.com/watch?v=7_RhQR3aQ_0
It is extremely similar to the column that appears when the cross
subweapon crash is used (visible at 1:15 in the same video), but lacks
the screen-filling giant white flash that comes after. A huge amount of
the code is copy-pasted between these two entities, even the `one` and
`three` variables from the cross entity that was just merged.
It's hard to come up with a good descriptive name for this, but I think
this one is at least good enough.
Similar thing to what I've had a lot of lately - I decompiled the RIC
version, then went through the process of cross-referencing RIC and DRA
to identify the duplicate function. There are a fair number of
differences between these, so it wasn't super straightforward to go from
the RIC match to the DRA match.
There's a lot of weird stuff in these, especially the "one" and "three"
variables. Probably some weirdness that I didn't quite write the same as
the original, but a match is a match.
Scratches here if you'd like to take a crack at any of the weird junk.
RIC: https://decomp.me/scratch/rRANW
DRA: https://decomp.me/scratch/jWF5h
There is already EntityHolyWater in DRA, but this one is quite different
(which makes sense, because Richter's is very different in behavior from
Alucard's). Still, there are some small overlaps here and there.
Due to the ongoing failure to match `func_80166784` (the previous
rodata-using function), this is being split out to a new file, even
though I'm pretty sure they're supposed to be in the same file. We will
reunify the files once `func_80166784` can be solved.
There is a function which is identical in the overlays, and is only used
by this function. I have gone ahead and named it identically in both
overlays.
This one was tricky and required some restructuring of an area of
memory, but it matches now, so that's cool!
No big comments from me but this one has a lot of random stuff so let me
know if I missed some enum or something!