-
Notifications
You must be signed in to change notification settings - Fork 24
Description
Existing information
The game implements an interface over the IPC (Inter Process Communication) system the hardware features, which simplifies sending data between both processors for different purposes, over a total of 32 channels. Currently I've only possibly identified one of those channels being used for the purpose of setting the Sound Registers, which only the ARM7 can manipulate, although the system seems to be used with plenty of other channels; who knows on what we could be missing!
The way the messages are sent is very simple: 5 bits for the channel (giving the total of 32 channels), 1 bit for an error flag, and the remaining 26 bits for the payload. Obviously that's not a lot of space, so what the game does is usually using those 26 bits for passing a pointer to the data that wants to be sent
Relevant functions, symbols and addresses
enum processor {
ARM9 = 0,
ARM7 = 1
};
enum ipc_send_result {
FIFO_FULL = -2,
ERROR = -1
OK = 0
};
enum ipc_channel {
SOUND = 7
};
struct ipc_message {
uint8_t channel : 5;
bool error : 1;
uint32_t payload : 26;
};
typedef void ChannelReceiveHandler(enum ipc_channel channel, uint32_t payload, bool error);
// -- ARM9
void __veneer_InitIPC(void); //@ 0x207d9a4
void InitIPC(void); //@ 0x207d9b0
void OpenChannel(enum ipc_channel channel, ChannelReceiveHandler* handler); //@ 0x207dab0
bool IsChannelOpen(enum ipc_channel, enum processor processor); //@ 0x207dafc
ipc_send_result SendChannel(enum ipc_channel, uint32_t payload, bool is_error); //@ 0x207db20
void ReceiveIPC(void); //@ 0x207dba8
// This function doesn't seem to be called manually under normal circumstances, instead it's called via IRQ
uint16_t InitializedIPC; //@ 0x22bb564
ChannelReceiveHandler* OpenChannelMessageHandlers[32]; //@ 0x22bb568
// A mapping of functions that each open channel may call to process incoming messages.
// Closed channel functions are NULL
// -- ARM7
// Most functions are similar or identical to the ARM9, so their notes apply here
void __veneer_InitIPC(void); //@ 0x37fe2b4
void InitIPC(void); //@ 0x37fe2c0
void OpenChannel(enum ipc_channel channel, ChannelReceiveHandler* handler); //@ 0x37fe39c
bool IsChannelOpen(enum ipc_channel, enum processor processor); //@ 0x37fe3ec
ipc_send_result SendChannel(enum ipc_channel, uint32_t payload, bool is_error); //@ 0x37fe410
ipc_send_result SendMessage(struct ipc_message message); //@ 0x37fe448
void ReceiveIPC(void); //@ 0x37fe4a8
uint16_t InitializedIPC; //@ 0x380785c
ChannelReceiveHandler* OpenChannelMessageHandlers[32]; //@ 0x3807860
// -- Shared
uint32_t OpenChannels[2]; //@ 0x27fff88
// Represents all IPC channels that have a handler assigned to them (aka, open), one bit per channel
// Sending a message to a closed channel will bounce the message with an error
// This is an array; index 0 represents ARM9 channels, index 1 are ARM7 channels