Commits and Anti-Commits
This section deals with copying data from static data to the current file (FC = FA or FB), or vice-versa, known respectively as commit and anti-commit.
This is the data that gets copied (the “committables”). The … denote data that’s not included, but show the spacing in memory. The “tail” commit connects static data to a piece of data in CF that’s not in a file. “sfi” denotes the scene-flag index in a File at offset 0x5318 (2B).
static addr | segment | size | file addr |
---|---|---|---|
80578648 |
temp flags | [8] | FC+30f4 |
80578650 |
… | [4] | |
80578654 |
2a64 | [4] | FC+2a64 |
80578658 |
… | ||
… | … | ||
805aab50 |
scene flags | [10] | FC+1a64 +10 *FC.sfi |
805aab60 |
scratch | [1f8] | FC+30fc |
805aad58 |
2K | [2000] | FC+32f4 |
805acd58 |
story flags | [100] | FC+8e4 |
805ace58 |
item flags | [80] | FC+9e4 |
805aced8 |
heartbeat | [10] | FC+a64 |
805acee8 |
tail | [20] | cf+a788 |
805acf08 |
… |
Commits
The different segments are handled by instances of 3 templated functions. The nearby (in memory) functions with the “-2” suffix are identical to their eponymous functions upto inlining.
C (segment) | commit | getTarget | getOffset | offsetConstant |
---|---|---|---|---|
story | 8000a850 |
8000a450 |
800099b0 |
8e4 |
inventory | 8000a8b0 |
8000a4d0 |
800099d0 |
9e4 |
heartbeat | 8000a910 |
8000a550 |
800099f0 |
a64 |
scene | 8000a970 |
8000a5d0 |
80009a10 |
1a64 |
2a64 | 8000a9d0 |
8000a650 |
80009a30 |
2a64 |
temp | 8000aa30 |
8000a6d0 |
80009a50 |
30f4 |
scratch | 8000aa90 |
8000a750 |
80009a70 |
30fc |
2K | 8000aaf0 |
8000a7d0 |
80009a90 |
32f4 |
tail | 8000ab60 |
800113a0 |
n/a | n/a |
File::getOffset<C>
template <class C> C* File::getOffset(File* this) {
return this + offsetConstant<C>;
}
80011360
| CF::getFileCurrent
File* CF::getFileCurrent(CF* this) {
return CF::isFileInactive(this) == 0 ? this->FileA : this->FileB;
}
CF::getTarget<C>
Except C = tail, which is just {return cf.fileTail}
.
template <class C> C* CF::getTarget(CF* this) {
File* file = this->getFileCurrent()
return file->getOffset<C>();
}
CF::commit<C>
template <class C> void CF::commit(CF* this, void* src, int offsetHalf, int sizeHalf) {
memcpy(this->getTarget<C>() + offsetHalf*2, src, sizeHalf*2);
}
Dynamic Example: Harp CS
Here are all the calls to commit, excluding heartbeat and tail, with arguments, during a run of the Harp cutscene. Heartbeat seems to trigger once per frame in all situations. The first argument (this pointer) is always 8095545c
as expected.
Note: The sources of committed data aren’t always the parts of static data suggested by the table above. Some of the temporary data comes from 8068xxxx
addresses.
C src offsetHalf sizeHalf
[enter lz]
2K 80689410 0 1000
story 805acd58 0 80
[room load delay]
temp 8068b2f0 0 4
scratch 8068b0f0 0 fc
2K 80689300 0 1000
scratch 8068b140 0 fc
scratch 8068b0e0 0 4
story 805acd58 0 80
item 805ace58 0 40
[harp cs plays]
story 805acd58 0 80
item 805ace58 0 40
2K 80689380 0 1000
scratch 8068b130 0 fc
scratch 8068b0d0 0 4
story 805acd58 0 80
item 805ace58 0 40
[save prompt (no save)]
scene 805aab50 38 8
temp 80578648 0 4
scratch 805aab60 0 fc
[fi text about dowsing]
scene 805aab50 38 8
temp 80578648 0 4
scratch 805aab60 0 fc
story 805acd58 0 80
[neutral]
Anti-Commits
This is handled entirely by the (classless) function 800c0740
| loadToCurrent(), which copies from FC into static data according to the table of committables above.
The function is called in these situations, all on the title-screen:
- reset: during cf.reset(), with cf.anticommitFlag unset so FC = FB.
- select: after cf.fileLoad(n) (which copies FS → FA), with cf.anticommitFlag set so FC = FA.
- start: with cf.anticommitFlag set so FC = FA (there’s no additional file copy).
- start blank file: with cf.anticommitFlag set so FC = FA. This is handled by the function
801bbdf0
, and is the only example where the interplay between cf.anticommitFlag and loadToCurrent() is visible in the decompiler.
void loadToCurrent(void) {
uint sfi = cf.getDataCur-5318-SFI(); // scene flag index
FUN_800bdf40( *80578640, sfi ); // scene+temp+scratch
FUN_800bee80( *80578650, sfi ); // 2a64
FUN_800bf8d0( *8057865c ); // story
FUN_800bf8d0( *80578660 ); // items
FUN_800bff30( *80578664, sfi ); // heartbeat
FUN_800c00f0( *80578668 ); // tail [not in file]
FUN_800bf120( *80578658, sfi ); // 2K
}
All static addresses are originally specified as r13 (=8057c6a0) + an offset.
These are the calls to 800043c4 | memcpy
made inside loadToCurrent (in execution order):
src | size | dest | segment | call stack |
---|---|---|---|---|
FC+1a64+10*sfi | [10] | 805aab50 | scene flag | 800c0880, 800bf420, 800bdf40 |
FC+30f4 | [8] | 80578648 | temp flag | 800c0880, 800bf4a0, 800bdf40 (same) |
FC+30fc | [1f8] | 805aab60 | scratch | 800c0880, 800bf4a0, 800bdf40 (same) |
FC+2a64 | [4] | 80578654 | 2a64 | 800c0880, 800bf420, 800bee80 |
FC+8e4 | [100] | 805acd58 | story flag | 800c0880, 800bf4a0, 800bfd80 |
FC+9e4 | [80] | 805ace58 | item flag | 800c0880, 800bf4a0, 800bfd80 (again) |
FC+a64 | [10] | 805aced8 | heartbeat | 800c0880, 800bf4a0, 800bff30→800bfe20 |
cf+a788 | [20] | 805acee8 | tail | 800c0880, 800bf4a0, 800c0190→800c00f0 |
FC+32f4 | [2000] | 805aad58 | 2K | 800c0880, 800bf4a0, 800bf120 |