Implement actor extension data

This commit is contained in:
Mr-Wiseguy
2025-02-19 03:26:37 -05:00
parent 2003f1babd
commit 4138612324
12 changed files with 691 additions and 39 deletions
+1
View File
@@ -151,6 +151,7 @@ set (SOURCES
${CMAKE_SOURCE_DIR}/src/game/config.cpp
${CMAKE_SOURCE_DIR}/src/game/debug.cpp
${CMAKE_SOURCE_DIR}/src/game/recomp_api.cpp
${CMAKE_SOURCE_DIR}/src/game/recomp_mem_api.cpp
${CMAKE_SOURCE_DIR}/src/game/rom_decompression.cpp
${CMAKE_SOURCE_DIR}/src/ui/ui_renderer.cpp
+9
View File
@@ -0,0 +1,9 @@
#ifndef __RECOMP_DATA_H__
#define __RECOMP_DATA_H__
namespace recomp {
void init_extended_actor_data();
void reset_actor_data();
}
#endif
+1 -1
View File
@@ -6,7 +6,7 @@ LD ?= ld.lld
CFLAGS := -target mips -mips2 -mabi=32 -O2 -G0 -mno-abicalls -mno-odd-spreg -mno-check-zero-division \
-fomit-frame-pointer -ffast-math -fno-unsafe-math-optimizations -fno-builtin-memset \
-Wall -Wextra -Wno-incompatible-library-redeclaration -Wno-unused-parameter -Wno-unknown-pragmas -Wno-unused-variable -Wno-missing-braces -Wno-unsupported-floating-point-opt
CPPFLAGS := -nostdinc -D_LANGUAGE_C -DMIPS -I ../lib/bk-decomp/include -I ../lib/bk-decomp/include/2.0L -I../lib/rt64/include
CPPFLAGS := -nostdinc -D_LANGUAGE_C -DMIPS -I ../lib/bk-decomp/include -I ../lib/bk-decomp/include/2.0L -I ../lib/bk-decomp/include/2.0L/PR -I../lib/rt64/include
LDFLAGS := -nostdlib -T patches.ld -T syms.ld -Map patches.map --unresolved-symbols=ignore-all --emit-relocs
C_SRCS := $(wildcard *.c)
+379
View File
@@ -0,0 +1,379 @@
#include "patches.h"
#include "prop.h"
#include "actor.h"
#include "functions.h"
#include "mem_funcs.h"
#include "bk_api.h"
extern ActorArray *suBaddieActorArray;
extern Actor *suLastBaddie;
void func_803255FC(Actor *this);
void func_8032B5C0(ActorMarker *arg0, ActorMarker *arg1, struct5Cs *arg2);
s32 func_80326C18(void);
void func_8032FFD4(ActorMarker *this, s32 arg1);
void marker_setModelId(ActorMarker *this, enum asset_e modelIndex);
s32 func_80306DDC(s32 *position);
s32 func_80307258(f32 arg0[3], s32 arg1, s32 arg2);
struct5Bs *func_8034A2C8(void);
void func_8033F738(ActorMarker *arg0);
void func_8034BFF8(ActorMarker *marker);
Struct83s *func_803406B0(void);
// @recomp Patched to create extension data for the actor.
RECOMP_PATCH Actor *actor_new(s32 position[3], s32 yaw, ActorInfo* actorInfo, u32 flags){
ActorAnimationInfo * sp54;
s32 i;
f32 sp44[3];
if(suBaddieActorArray == NULL){
// @recomp Reset actor data when suBaddieActorArray is initially allocated.
recomp_clear_all_actor_data();
suBaddieActorArray = (ActorArray *)malloc(sizeof(ActorArray) + 20*sizeof(Actor));
suBaddieActorArray->cnt = 0;
suBaddieActorArray->max_cnt = 20;
}
if(suBaddieActorArray->cnt + 1 > suBaddieActorArray->max_cnt){
suBaddieActorArray->max_cnt = suBaddieActorArray->cnt + 5;
suBaddieActorArray = (ActorArray *)realloc(suBaddieActorArray, sizeof(ActorArray) + suBaddieActorArray->max_cnt*sizeof(Actor));
}
++suBaddieActorArray->cnt;
suLastBaddie = &suBaddieActorArray->data[suBaddieActorArray->cnt - 1];
suLastBaddie->actor_info = actorInfo;
suLastBaddie->unk10_25 = 0;
suLastBaddie->unk10_18 = 0;
suLastBaddie->state = actorInfo->startAnimation;
suLastBaddie->position_x = (f32)position[0];
suLastBaddie->position_y = (f32)position[1];
suLastBaddie->position_z = (f32)position[2];
suLastBaddie->unkF4_8 = 0;
suLastBaddie->yaw = (f32) yaw;
suLastBaddie->yaw_ideal = (f32) yaw;
suLastBaddie->pitch = 0.0f;
suLastBaddie->roll = 0.0f;
suLastBaddie->unk6C = 0.0f;
suLastBaddie->actor_specific_1_f = 0.0f;
suLastBaddie->unk10_12 = 0;
suLastBaddie->unk38_0 = 0;
suLastBaddie->unk38_31 = 0;
suLastBaddie->unk58_0 = 1;
suLastBaddie->unk40 = 0;
suLastBaddie->unk44_31 = 0;
suLastBaddie->despawn_flag = 0;
suLastBaddie->unk44_14 = -1;
suLastBaddie->unk48 = 0.0f;
suLastBaddie->unk4C = 100.0f;
suLastBaddie->unk10_1 = 1;
suLastBaddie->unkF4_30 = 0;
suLastBaddie->unkF4_29 = 0;
suLastBaddie->scale = 1.0f;
suLastBaddie->unk124_7 = 0;
suLastBaddie->unk124_6 = 1;
suLastBaddie->modelCacheIndex = actorInfo->actorId;
suLastBaddie->unk44_2 = func_80326C18();
suLastBaddie->marker = marker_init(position, actorInfo->draw_func, (asset_getFlag(actorInfo->modelId) == 1) ? 0 : 1, actorInfo->markerId, (flags & 0x400) ? 1 : 0);
suLastBaddie->marker->unk3E_0 = 1;
suLastBaddie->unk138_28 = 1;
suLastBaddie->unk10_3 = -1;
suLastBaddie->unk10_4 = 0;
suLastBaddie->unk10_8 = 0;
suLastBaddie->unk10_7 = 0;
suLastBaddie->unk10_6 = 0;
suLastBaddie->unk54 = 0.0f;
suLastBaddie->anctrl_asset_id = 0;
suLastBaddie->unk5C = 0.0f;
suLastBaddie->unkF4_31 = 0;
suLastBaddie->unk138_30 = 0;
suLastBaddie->unk138_3 = 0;
suLastBaddie->unk38_21 = 0;
suLastBaddie->unk38_13 = 0;
suLastBaddie->unk78_22 = 0;
suLastBaddie->unk78_31 = 0;
suLastBaddie->unk74 = 0.0f;
suLastBaddie->unk70 = 0.0f;
suLastBaddie->unkF4_24 = 0;
suLastBaddie->unk140 = 0.0f;
suLastBaddie->unk144 = 0.0f;
suLastBaddie->unk44_1 = 0;
suLastBaddie->unk44_0 = 0;
suLastBaddie->initialized = FALSE;
suLastBaddie->volatile_initialized = FALSE;
suLastBaddie->lifetime_value = 0.0f;
suLastBaddie->is_bundle = FALSE;
suLastBaddie->unk104 = NULL;
suLastBaddie->unk100 = NULL;
suLastBaddie->unk158[0] = NULL;
suLastBaddie->unk158[1] = NULL;
suLastBaddie->unk78_13 = 0;
suLastBaddie->unk124_31 = 0;
suLastBaddie->unkF4_20 = 0;
suLastBaddie->sound_timer = 0.0f;
func_8032FFD4(suLastBaddie->marker, suBaddieActorArray->cnt - 1);
marker_setModelId(suLastBaddie->marker, actorInfo->modelId);
marker_setActorUpdateFunc(suLastBaddie->marker, actorInfo->update_func);
marker_setActorUpdate2Func(suLastBaddie->marker, actorInfo->update2_func);
ml_vec3f_clear(suLastBaddie->unk1C);
ml_vec3f_clear(suLastBaddie->velocity);
ml_vec3f_clear(suLastBaddie->spawn_position);
suLastBaddie->stored_anctrl_index = 0;
suLastBaddie->unk58_2 = 1;
suLastBaddie->stored_anctrl_playbackType_ = 0;
suLastBaddie->stored_anctrl_forwards = 0;
suLastBaddie->stored_anctrl_smoothTransistion = 0;
suLastBaddie->stored_anctrl_duration = 0.0f;
suLastBaddie->stored_anctrl_timer = 0.0f;
suLastBaddie->unk138_19 = 0;
suLastBaddie->stored_anctrl_subrangeMin = 0.0f;
suLastBaddie->stored_anctrl_subrangeMax = 1.0f;
suLastBaddie->unkF4_22 = 0;
suLastBaddie->unk58_1 = 0;
suLastBaddie->unk138_29 = 0;
suLastBaddie->unk18 = actorInfo->animations;
suLastBaddie->anctrl = NULL;
suLastBaddie->stored_anctrl_timer = 0.0f;
suLastBaddie->unk130 = 0;
suLastBaddie->unk124_5 = 0;
suLastBaddie->unk124_3 = 0;
suLastBaddie->unk138_9 = 0;
suLastBaddie->unk138_8 = 0;
suLastBaddie->unk138_25 = 0;
suLastBaddie->unk16C_3 = 0;
suLastBaddie->unk16C_2 = 0;
suLastBaddie->unk16C_1 = 0;
suLastBaddie->unk16C_0 = 0;
suLastBaddie->unk17C_31 = 0;
suLastBaddie->unk14C[0] = NULL;
suLastBaddie->unk14C[1] = NULL;
suLastBaddie->unk138_27 = 0;
suLastBaddie->has_met_before = FALSE;
suLastBaddie->unk138_23 = 0;
suLastBaddie->unk138_22 = 0;
suLastBaddie->unk138_21 = 0;
suLastBaddie->unk138_20 = 0;
suLastBaddie->unk174 = 0.0f;
suLastBaddie->unk178 = 0.0f;
if( actorInfo->animations){
sp54 = &suLastBaddie->unk18[suLastBaddie->state];
if(sp54->index != 0){
suLastBaddie->anctrl = anctrl_new(0);
anctrl_reset(suLastBaddie->anctrl);
anctrl_setIndex(suLastBaddie->anctrl, sp54->index);
anctrl_setDuration(suLastBaddie->anctrl, sp54->duration);
anctrl_start(suLastBaddie->anctrl, "subaddie.c", 0x4A5);
}
}//L80327BA8
suLastBaddie->unk124_11 = 0;
suLastBaddie->alpha_124_19 = 0xff;
suLastBaddie->depth_mode = MODEL_RENDER_DEPTH_FULL;
suLastBaddie->unk124_0 = suLastBaddie->unk138_31 = 1;
for(i = 0; i < 0x10; i++){
((s32 *)suLastBaddie->unk7C)[i] = 0;
}
for(i = 0; i < 0x0C; i++){
((s32 *)suLastBaddie->unkBC)[i] = 0;
}
if(flags & ACTOR_FLAG_UNKNOWN_0){
suLastBaddie->unk10_25 = func_80306DDC(position) + 1;
if(suLastBaddie->unk10_25 == 0){
suLastBaddie->unk10_25 = 0;
}else{
sp44[0] = (f32)position[0];
sp44[1] = (f32)position[1];
sp44[2] = (f32)position[2];
suLastBaddie->unk10_18 = func_80307258(sp44, suLastBaddie->unk10_25 - 1, 0) + 1;
}
}//L80327D30
if(flags & ACTOR_FLAG_UNKNOWN_2){
suLastBaddie->unk10_1 = 0;
}
if(flags & ACTOR_FLAG_UNKNOWN_3){
suLastBaddie->unkF4_30 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_1){
suLastBaddie->marker->unk44 = (struct5Bs*)1;
}
else if(flags & ACTOR_FLAG_UNKNOWN_6){
suLastBaddie->marker->unk44 = func_8034A2C8();
}
if(flags & ACTOR_FLAG_UNKNOWN_12){
func_8033F738(suLastBaddie->marker);
func_8034BFF8(suLastBaddie->marker);
}
suLastBaddie->unk148 = 0;
if(flags & ACTOR_FLAG_UNKNOWN_11){
suLastBaddie->unk148 = skeletalAnim_new();
}
if(flags & ACTOR_FLAG_UNKNOWN_14){
suLastBaddie->marker->unk50 = (s32)func_803406B0();
}
if(flags & ACTOR_FLAG_UNKNOWN_4){
suLastBaddie->unk124_31 = -1;
}
if(flags & ACTOR_FLAG_UNKNOWN_7){
suLastBaddie->unkF4_22 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_19){
suLastBaddie->unk58_1 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_8){
suLastBaddie->unk130 = func_803255FC;
}
if(flags & ACTOR_FLAG_UNKNOWN_9){
suLastBaddie->marker->unk40_21 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_15){
suLastBaddie->marker->unk40_20 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_17){
suLastBaddie->marker->unk40_22 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_22){
suLastBaddie->marker->unk40_19 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_16){
suLastBaddie->unk138_9 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_18){
suLastBaddie->unk138_8 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_21){
suLastBaddie->unk138_25 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_23){
suLastBaddie->unk16C_3 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_24){
suLastBaddie->unk16C_2 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_25){
suLastBaddie->unk16C_1 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_26){
suLastBaddie->unk17C_31 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_13){
suLastBaddie->unk138_29 = 1;
}
if(flags & ACTOR_FLAG_UNKNOWN_20){
suLastBaddie->unk58_2 = 0;
}
suLastBaddie->unk154 = 0x005e0000;
suLastBaddie->marker->unk54 = (void (*)(struct actorMarker_s *, struct actorMarker_s *, u16 *))func_8032B5C0;
for(i = 0; i < 3; ++i){
suLastBaddie->unk164[i] = 0x63;
}
suLastBaddie->unk170 = -10.0f;
suLastBaddie->unk138_7 = 0;
suLastBaddie->unk3C = flags;
// @recomp Allocate extension data for this actor and place it in padding.
suLastBaddie->pad17C_30 = recomp_create_actor_data(actorInfo->actorId) & 0x7FFFFFFFU;
return suLastBaddie;
}
void func_8032BB88(Actor *this, s32 arg1, s32 arg2);
void func_8033E7CC(ActorMarker *arg0);
void func_8034A2A8(struct5Bs *this);
void func_8034BF54(ActorMarker *marker);
void func_8033F784(ActorMarker *arg0);
void func_80340690(Struct83s *self);
void func_8032ACA8(Actor *arg0);
// @recomp Patched to destroy the extended actor data.
RECOMP_PATCH void func_80325FE8(Actor *this) {
ActorMarker *marker;
u8 temp_v0;
// @recomp Destroy the extended actor data.
recomp_destroy_actor_data(this->pad17C_30);
marker = this->marker;
marker->id = 0;
if (this->anctrl != NULL) {
anctrl_free(this->anctrl);
}
temp_v0 = this->unk44_31;
if (temp_v0 != 0) {
sfxsource_freeSfxsourceByIndex(temp_v0);
}
this->anctrl = NULL;
this->unk44_31 = 0;
if (this->unk138_7 != 0) {
func_8032BB88(this, -1, 8000);
this->unk138_7 = 0;
}
if (marker->actorFreeFunc != NULL) {
marker->actorFreeFunc(this);
marker->actorFreeFunc = NULL;
}
if ((s32)marker->unk44 < 0) {
func_8033E7CC(marker);
func_8034A2A8(marker->unk44);
marker->unk44 = 0;
}
if (marker->unk4C != 0) {
func_8034BF54(this->marker);
marker->unk4C = 0;
}
if (marker->unk48 != 0) {
func_8033F784(marker);
marker->unk48 = 0;
}
if (this->unk148 != NULL) {
skeletalAnim_free(this->unk148);
this->unk148 = NULL;
}
if (marker->unk50 != 0) {
func_80340690((Struct83s *)marker->unk50);
marker->unk50 = 0;
}
func_8032ACA8(this);
}
RECOMP_EXPORT ActorExtensionId bkrecomp_extend_actor(enum actor_e type, u32 size) {
return recomp_register_actor_extension(type, size);
}
RECOMP_EXPORT ActorExtensionId bkrecomp_extend_actor_all(u32 size) {
return recomp_register_actor_extension_generic(size);
}
RECOMP_EXPORT void* bkrecomp_get_extended_actor_data(Actor* actor, ActorExtensionId extension) {
return recomp_get_actor_data(actor->pad17C_30, extension, actor->actor_info->actorId);
}
RECOMP_EXPORT u32 bkrecomp_get_actor_spawn_index(Actor* actor) {
return recomp_get_actor_spawn_index(actor->pad17C_30);
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef __BK_API_H__
#define __BK_API_H__
#include "ultra64.h"
#include "enums.h"
#include "prop.h"
typedef u32 ActorExtensionId;
ActorExtensionId bkrecomp_extend_actor(enum actor_e type, u32 size);
ActorExtensionId bkrecomp_extend_actor_all(u32 size);
void* bkrecomp_get_extended_actor_data(Actor* actor, ActorExtensionId extension);
u32 bkrecomp_get_actor_spawn_index(Actor* actor);
#endif
+21
View File
@@ -0,0 +1,21 @@
#include "patches.h"
#include "bk_api.h"
#include "misc_funcs.h"
RECOMP_DECLARE_EVENT(recomp_on_init());
void core1_init();
void sns_write_payload_over_heap();
void mainLoop();
RECOMP_PATCH void mainThread_entry(void *arg) {
// @recomp Register actor extension data and call the init event.
recomp_on_init();
core1_init();
sns_write_payload_over_heap();
while (1) {
mainLoop();
}
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef __MEM_FUNCS_H__
#define __MEM_FUNCS_H__
#include "patch_helpers.h"
DECLARE_FUNC(u32, recomp_register_actor_extension, u32 actor_type, u32 size);
DECLARE_FUNC(u32, recomp_register_actor_extension_generic, u32 size);
DECLARE_FUNC(void, recomp_clear_all_actor_data);
DECLARE_FUNC(u32, recomp_create_actor_data, u32 actor_type);
DECLARE_FUNC(void, recomp_destroy_actor_data, u32 actor_handle);
DECLARE_FUNC(void*, recomp_get_actor_data, u32 actor_handle, u32 extension_handle, u32 actor_type);
DECLARE_FUNC(u32, recomp_get_actor_spawn_index, u32 actor_handle);
#endif
-38
View File
@@ -1,38 +0,0 @@
#ifndef __N64_TYPES_H__
#define __N64_TYPES_H__
#define va_list __builtin_va_list
#define va_start __builtin_va_start
#define va_arg __builtin_va_arg
#define va_end __builtin_va_end
typedef unsigned int size_t;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
typedef unsigned long long u64;
typedef signed char s8;
typedef short s16;
typedef long s32;
typedef long long s64;
typedef volatile unsigned char vu8;
typedef volatile unsigned short vu16;
typedef volatile unsigned long vu32;
typedef volatile unsigned long long vu64;
typedef volatile signed char vs8;
typedef volatile short vs16;
typedef volatile long vs32;
typedef volatile long long vs64;
typedef float f32;
typedef double f64;
#define TRUE 1
#define FALSE 0
#define NULL 0
#endif
+6
View File
@@ -21,9 +21,15 @@
void osWriteBackDCacheAll(void);
#define bzero bzero_recomp
#define osDpSetStatus osDpSetStatus_recomp
#define malloc malloc_recomp
#define free free_recomp
#define realloc realloc_recomp
#define memcpy memcpy_recomp
#include "ultra64.h"
typedef int bool;
int recomp_printf(const char* fmt, ...);
#endif
+10
View File
@@ -15,3 +15,13 @@ osGetCount_recomp = 0x8F000028;
osCreateMesgQueue_recomp = 0x8F00002C;
osRecvMesg_recomp = 0x8F000030;
osDpSetStatus_recomp = 0x8F000034;
malloc_recomp = 0x8F000038;
free_recomp = 0x8F00003C;
realloc_recomp = 0x8F000040;
recomp_register_actor_extension = 0x8F000044;
recomp_register_actor_extension_generic = 0x8F000048;
recomp_clear_all_actor_data = 0x8F00004C;
recomp_create_actor_data = 0x8F000050;
recomp_destroy_actor_data = 0x8F000054;
recomp_get_actor_data = 0x8F000058;
recomp_get_actor_spawn_index = 0x8F00005C;
+232
View File
@@ -0,0 +1,232 @@
#include <vector>
#include <mutex>
#include "slot_map.h"
#include "librecomp/helpers.hpp"
#include "librecomp/addresses.hpp"
#include "ultramodern/error_handling.hpp"
#include "recomp_ui.h"
#include "recomp_data.h"
#include "../patches/mem_funcs.h"
struct ExtensionInfo {
// Either the actor's type ID, or 0xFFFFFFFF if this is for generic data.
uint32_t actor_type;
// The offset from either the start of the actor's data or the start of the actor's specific extension data depending on the value of actor_type.
uint32_t data_offset;
};
struct ExtensionData {
uint32_t actor_spawn_index;
PTR(void) data_addr;
};
std::mutex actor_data_mutex{};
// The total size of actor-specific extension data for each actor type.
std::vector<uint32_t> actor_data_sizes{};
// The total size of all generic actor extension data.
uint32_t generic_data_size;
// The registered actor extensions.
std::vector<ExtensionInfo> actor_extensions{};
// The extension data for every actor.
using actor_data_map_t = dod::slot_map32<ExtensionData>;
actor_data_map_t actor_data{};
// The number of actors spawned since the last reset.
uint32_t actor_spawn_count = 0;
// Whether or not extensions can be registered at this time.
bool can_register = false;
// Debug counters.
size_t alloc_count = 0;
size_t free_count = 0;
void recomp::init_extended_actor_data() {
std::lock_guard lock{ actor_data_mutex };
actor_data_sizes.clear();
generic_data_size = 0;
actor_extensions.clear();
actor_data.reset();
actor_spawn_count = 0;
can_register = true;
// Create a dummy extension so the first extension handle is nonzero, should help catch bugs.
actor_extensions.push_back({});
}
void recomp::reset_actor_data() {
std::lock_guard lock{ actor_data_mutex };
actor_data.reset();
actor_spawn_count = 0;
assert(alloc_count == free_count);
alloc_count = 0;
free_count = 0;
}
constexpr uint32_t round_up_16(uint32_t value) {
return (value + 15) & (~15);
}
extern "C" void recomp_register_actor_extension(uint8_t* rdram, recomp_context* ctx) {
u32 actor_type = _arg<0, u32>(rdram, ctx);
u32 size = _arg<1, u32>(rdram, ctx);
if (!can_register) {
recompui::message_box("Fatal error in mod - attempted to register actor extension data after actors have been spawned.");
assert(false);
ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__);
}
if (actor_data_sizes.size() <= actor_type) {
actor_data_sizes.resize(2 * actor_type);
}
// Increase the actor type's extension data size by the provided size (rounded up to a multiple of 16).
uint32_t data_offset = actor_data_sizes[actor_type];
actor_data_sizes[actor_type] += round_up_16(size);
// Register the extension.
uint32_t ret = static_cast<uint32_t>(actor_extensions.size());
actor_extensions.emplace_back(ExtensionInfo{.actor_type = actor_type, .data_offset = data_offset});
// printf("Registered actor extension data for type %u (size 0x%08X, offset 0x%08X)\n", actor_type, size, data_offset);
_return<u32>(ctx, ret);
}
extern "C" void recomp_register_actor_extension_generic(uint8_t* rdram, recomp_context* ctx) {
u32 size = _arg<0, u32>(rdram, ctx);
// Increase the generic extension data size by the provided size (rounded up to a multiple of 16).
uint32_t data_offset = generic_data_size;
generic_data_size += round_up_16(size);
// Register the extension.
uint32_t ret = static_cast<uint32_t>(actor_extensions.size());
actor_extensions.emplace_back(ExtensionInfo{.actor_type = 0xFFFFFFFFU, .data_offset = data_offset});
// printf("Registered generic actor extension data (size 0x%08X, offset 0x%08X)\n", size, data_offset);
_return<u32>(ctx, ret);
}
extern "C" void recomp_clear_all_actor_data(uint8_t* rdram, recomp_context* ctx) {
(void)rdram;
(void)ctx;
recomp::reset_actor_data();
}
extern "C" void recomp_create_actor_data(uint8_t* rdram, recomp_context* ctx) {
std::lock_guard lock{ actor_data_mutex };
can_register = false;
// Determine the number of bytes to allocate based on the actor type's extensions and the generic extensions.
u32 actor_type = _arg<0, u32>(rdram, ctx);
u32 alloc_size = generic_data_size;
[[maybe_unused]] u32 type_data_size = 0;
if (actor_type < actor_data_sizes.size()) {
type_data_size = actor_data_sizes[actor_type];
alloc_size += type_data_size;
}
// Allocate the extension data if it's of nonzero size.
PTR(void) data_ptr = NULLPTR;
if (alloc_size != 0) {
void* data = recomp::alloc(rdram, alloc_size);
alloc_count++;
data_ptr = reinterpret_cast<uint8_t*>(data) - rdram + 0xFFFFFFFF80000000U;
}
// Add the actor's fields to the actor data slotmap.
u32 spawn_index = actor_spawn_count++;
dod::slot_map_key32<ExtensionData> key = actor_data.emplace(ExtensionData{.actor_spawn_index = spawn_index, .data_addr = data_ptr});
// printf("Allocated actor data: address 0x%08X with 0x%08X bytes total (0x%08X bytes generic and 0x%08X bytes specific), handle 0x%08X, spawn index %d\n",
// data_ptr, alloc_size, generic_data_size, type_data_size, key.raw, spawn_index);
_return<u32>(ctx, key.raw);
}
extern "C" void recomp_destroy_actor_data(uint8_t* rdram, recomp_context* ctx) {
std::lock_guard lock{ actor_data_mutex };
u32 actor_handle = _arg<0, u32>(rdram, ctx);
actor_data_map_t::key actor_key{actor_handle};
ExtensionData* data = actor_data.get(actor_key);
if (data != nullptr) {
// printf("Freeing actor data: address 0x%08X handle 0x%08X\n", data->data_addr, actor_handle);
if (data->data_addr != NULLPTR) {
recomp::free(rdram, TO_PTR(void, data->data_addr));
free_count++;
}
actor_data.erase(actor_data_map_t::key{actor_handle});
}
else {
// Not an irrecoverable error, but catch it in debug mode with an assert to help find bugs.
assert(false);
}
}
extern "C" void recomp_get_actor_data(uint8_t* rdram, recomp_context* ctx) {
std::lock_guard lock{ actor_data_mutex };
u32 actor_handle = _arg<0, u32>(rdram, ctx);
u32 extension_handle = _arg<1, u32>(rdram, ctx);
u32 actor_type = _arg<2, u32>(rdram, ctx);
// Check if the extension handle is valid.
if (extension_handle == 0 || extension_handle >= actor_extensions.size()) {
_return<PTR(void)>(ctx, NULLPTR);
return;
}
ExtensionInfo& extension = actor_extensions[extension_handle];
bool generic_extension = extension.actor_type == 0xFFFFFFFFU;
// Check if the extension is generic or for the provided actor type.
if (!generic_extension && extension.actor_type != actor_type) {
_return<PTR(void)>(ctx, NULLPTR);
return;
}
actor_data_map_t::key actor_key{actor_handle};
ExtensionData* data = actor_data.get(actor_key);
// Check if actor handle is valid.
if (data == nullptr) {
_return<PTR(void)>(ctx, NULLPTR);
return;
}
// Calculate the address for this specific extension's data.
PTR(void) base_address = data->data_addr;
u32 offset = extension.data_offset;
// Specific actor data is after generic actor data, so increase the offset by the total generic actor data if this isn't generic data.
if (!generic_extension) {
offset += generic_data_size;
}
PTR(void) ret = base_address + offset;
_return<PTR(void)>(ctx, ret);
}
extern "C" void recomp_get_actor_spawn_index(uint8_t* rdram, recomp_context* ctx) {
std::lock_guard lock{ actor_data_mutex };
u32 actor_handle = _arg<0, u32>(rdram, ctx);
actor_data_map_t::key actor_key{actor_handle};
ExtensionData* data = actor_data.get(actor_key);
// Check if actor handle is valid.
if (data == nullptr) {
_return<u32>(ctx, 0xFFFFFFFFU);
return;
}
_return<u32>(ctx, data->actor_spawn_index);
}
+2
View File
@@ -4,6 +4,7 @@
#include "librecomp/game.hpp"
#include "banjo_game.h"
#include "recomp_data.h"
#ifdef _MSC_VER
inline uint32_t byteswap(uint32_t val) {
@@ -120,4 +121,5 @@ std::vector<uint8_t> banjo::decompress_bk(std::span<const uint8_t> compressed_ro
void banjo::bk_on_init(uint8_t* rdram, recomp_context* ctx) {
MEM_W(0, (int32_t)0x80000310) = 6103;
recomp::do_rom_read(rdram, (int32_t)0x80000000, 0x100004C0, 0x2A4);
recomp::init_extended_actor_data();
}