While helping my friend out with his emulator, I found some info on the itemEntity struct and 2 functions. We used a dump of the RAM in his emulator to see what was going on.
The field currently named unk_34
seems to hold only 4 byte sized values. There is a function called update_item_entities
, that should update item entities. In the ROM this is located at 900c85ec
. This function is copied to RAM location 80131eec
. In a for loop, this function checks if the itemID of some itemEntity structs is equal to 0x157
, which from https://tcrf.net/Notes:Paper_Mario I gathered were coins. If they are coins, there is a 10% chance some values get updated in the struct, which I believe are values related to a (sparkling) animation sequence. The more interesting function call is that to FUN_90130acc
, which is nothing, but after being copied to RAM this is a call to 80130acc
corresponding to a function at 900c71cc
. The decompilation for this function should be something like
void do_animation(itemEntity* item_entity) {
if (--item_entity->frames_left < 1) { // Ghidra says < 1, presumably this is just == 0 and the field is an unsigned integer
do { } while (next_step(item_entity));
}
}
The frames_left
field is the field at offset 0x3c
in the itemEntity
struct. Essentially, every animation sequence step (I am just guessing it is an animation sequence, it might be some other sequence) lasts for a certain amount of frames.
The next_step
function in ROM is a call to 90130a04
, which again points to nothing, but in RAM this is a call to 80130a04
, corresponding to 900c7104
in the ROM. This function essentially does one step in the animation and returns whether a next step should be taken. It should look something like this:
int next_sequence_step(ItemEntity *item_entity)
{
undefined4 uVar1;
int *current_state_ptr;
uint *next_ptr;
current_state_ptr = item_entity->current_state_ptr;
next_ptr = (uint *)(current_state_ptr + 1); // this pointer has a different meaning depending on the state
switch(*current_state_ptr) {
case 0: // this is an error state it seems, and will hang the above function
return 1;
case 1:
item_entity->frames_left = *next_ptr;
uVar1 = current_state_ptr[2];
item_entity->current_state_ptr = current_state_ptr + 3;
item_entity->field_0x44 = uVar1;
break;
case 2:
item_entity->current_state_ptr = item_entity->sequence_start;
return 1;
case 3:
item_entity->sequence_start = (int *)next_ptr;
item_entity->current_state_ptr = (int *)next_ptr;
return 1;
case 4:
item_entity->current_state_ptr = current_state_ptr + 2;
return 1;
case 5:
case 6:
break;
case 7:
item_entity->frames_left = *next_ptr;
item_entity->field_0x4c = (int *)current_state_ptr[2];
item_entity->field_0x50 = (int *)current_state_ptr[3];
item_entity->field_0x54 = current_state_ptr[4];
uVar1 = current_state_ptr[5];
item_entity->current_state_ptr = current_state_ptr + 6;
item_entity->field_0x58 = uVar1;
break;
default:
return 0;
}
return 0;
}
essentially, the current_state_ptr
(field offset 0x40) points to a struct, which varies on what state it is. In all cases it starts with an int showing what state it actually is. In the case of 0 it is just an int, and the do_animation
function will hang. In case of 1, it looks like
struct sequence_state_1 {
int state; // is always 1
uint frames_left; // amount of frames it stays in this state
int field_0x44; // struct field 0x44 is set to this value
}
case 2 resets the animation. The struct is also just an int then. case 3 switches to a new animation, and the struct looks like
struct {
int state; // is always 3
int* next_animation;
}
case 4 simply advances the state. The struct does hold an extra 32 bit piece of information, but this is not really used here it seems. case 5 or 6 do nothing, but will not hang the do_animation
function. case 7 is the most interesting one, it holds a struct that looks like
struct {
int state; // always 7
uint frames_left; // amount of frames it stays in this state
void* pointer_0x4c; // pointer to 0x20 bytes of data
void* pointer_0x50; // pointer to at least 0x20 bytes of data
int field_0x54;
int field_0x58;
}
Of course, the integers showing the state are likely some enum. The struct sizes can be checked by the amount that item_entity->current_state_ptr
is advanced (in strides of 4 bytes). An example of such a sequence can be found in ROM at 9009df70
, copied to RAM at 80104ac0
. This is a sequence that starts at state 4, then state 7 a few times and then state 0 (which presumably the N64 never reaches, have not figured this out yet). Looking at the values for the pointers of field 0x4c and 0x50, 4c seems to point at 0x20 bytes of data, and 0x50 at some multiple of 0x20.
Because of this, I also think that the itemEntity
struct will look something like
typedef struct ItemEntity {
/* 0x00 */ s32 flags;
/* 0x04 */ s16 boundVar; /* see make_item_entity */
/* 0x06 */ char unk_06[2];
/* 0x08 */ Vec3f position;
/* 0x14 */ struct ItemEntityPhysicsData* physicsData;
/* 0x18 */ s16 itemID; /* into item table, also worldIconID */
/* 0x1A */ u8 state;
/* 0x1B */ u8 type;
/* 0x1C */ u8 pickupDelay; /* num frames before item can be picked up */
/* 0x1D */ char unk_1D;
/* 0x1E */ s16 wsFaceAngle; /* < 0 means none */
/* 0x20 */ s16 shadowIndex;
/* 0x22 */ char unk_22[2];
/* 0x24 */ u32* readPos;
/* 0x28 */ u32* savedReadPos;
/* 0x2C */ char unk_2C[2];
/* 0x2E */ u8 unkCounter;
/* 0x2F */ s8 unk_2F;
/* 0x30 */ f32 scale;
/* 0x34 */ u32 unk_34;
/* 0x38 */ u32 unk_38;
/* 0x3c */ u32 frames_left;
/* 0x40 */ u32* current_state_ptr;
/* 0x44 */ u32 unk_44;
/* 0x48 */ u32* sequence_start_ptr;
/* 0x4c */ u32* unk_4c; // 32 bytes of data
/* 0x50 */ u32* unk_50; // 32 bytes or multiple of 32 bytes of data
/* 0x54 */ u32 unk_54;
/* 0x58 */ u32 unk_58;
} ItemEntity; // size = 0x5C