Reading Stan’s Thread is a prerequisite to reading this one. Come back once you’ve read it. Alright, you ready? Throw most of that knowledge out.
Intro: A (FE5) Proc
Surprise, surprise, these little popup windows are handled with procs in FE5, too. Procs in FE5 are a bit different from the GBAFE ones.
#Proc format
Here’s the format of a proc type:
+00 word: 2 letter ascii proc name
+02 word: start routine pointer
+04 word: on-cycle routine pointer
+06 word: proc code pointer
There’s something very goofy going on here, though. Each of these pointers can only point to things within the current bank. This’ll be important later. All of this data gets copied into the proc state stuct, so let’s move on to that.
Just like GBAFE procs, FE5 procs have a proc state struct in RAM. Rather than being a contiguous block like GBAFE, each word in a single struct is spaced every 0x20 bytes (There’ll be a visualization of that in a moment, don’t worry). Here’s the layout:
Header:
$053D | $055B - (2 * slot) | Proc Type offset
$055D | $057B - (2 * slot) | Proc Type bank
$057D | $059B - (2 * slot) | Proc name
$059D | $05BB - (2 * slot) | Bitfield
$05BD | $05DB - (2 * slot) | OnCycle offset
$05DD | $05FB - (2 * slot) | Code offset
$05FD | $061B - (2 * slot) | Sleep timer
$061D | $063B - (2 * slot) | Unknown timer
Body:
$063D | $065B - (2 * slot) | These are free to
$065D | $067B - (2 * slot) | be used however the
$067D | $069B - (2 * slot) | proc likes
$069D | $06BB - (2 * slot) |
$06BD | $06DB - (2 * slot) |
$06DD | $06FB - (2 * slot) |
$06FD | $071B - (2 * slot) |
$071D | $073B - (2 * slot) |
Unknown:
$073D | $075B - (2 * slot) | copy of header bitfield
Procs are added in reverse order, where the first proc has its type lower word at $055B, the second at $0559, etc. This lower word is used to determine if a proc slot is occupied, and is cleared on the proc’s destruction. There is room for 0x20 procs.
Here’s what this popup looks like in RAM:
This format is pretty readable when there are only a few active.
An important difference between GBAFE procs and FE5 procs is that FE5 procs need no proc code at all. They can mix and match having a start routine, an on-cycle routine, and a proc code (You could have a proc that has none of these, but that’s pretty pointless). Start routines are executed immediately after the proc state is written, and then the on-cycle routine is executed before moving on.
#A little bit about the proc code:
FE5’s proc code isn’t as convenient as GBAFE’s. There are two types of codes, the first being timer numbers. A timer number simply sets the timer in the proc state. They’re a word long.
The other type is rather annoying. GBAFE proc instructions are an index in a table of routines, whereas FE5 instructions are pointers to routines.
Routine pointers are also only a word long. Remember when I said that the pointers in the proc type referred to the bank the type was in? Proc code routine pointers all point to things in bank $82 (mapped). To get around this limitation, these routines usually take parameters like long pointers to other routines. Anyway, each instruction being a short pointer in bank $82 leaves me to hunt down possible routines, so I don’t have a convenient list, yet.
Confused? I’ll have an example ready soon.
This is super WIP and will be updated as I learn things.