mirror of https://github.com/sm64pc/sm64pc.git
Moved to system malloc removed model id limit
This commit is contained in:
parent
fc3890c688
commit
f02de40a1d
3
Makefile
3
Makefile
|
@ -293,6 +293,9 @@ SRC_DIRS += src/moon/mod-engine/hooks
|
|||
# Moon64 SRC [Mod-Engine - Shaders Module]
|
||||
SRC_DIRS += src/moon/mod-engine/shaders
|
||||
|
||||
# Moon64 SRC [Mod-Engine - Models Module]
|
||||
SRC_DIRS += src/moon/mod-engine/models
|
||||
|
||||
# Moon64 SRC [Achievements]
|
||||
SRC_DIRS += src/moon/achievements
|
||||
|
||||
|
|
|
@ -161,8 +161,9 @@
|
|||
CMD_BBH(0x20, 0x04, 0x0000)
|
||||
|
||||
#define LOAD_MODEL_FROM_DL(model, dl, layer) \
|
||||
CMD_BBH(0x21, 0x08, ((layer << 12) | model)), \
|
||||
CMD_PTR(dl)
|
||||
CMD_BBH(0x21, 0x0C, 0), \
|
||||
CMD_PTR(dl), \
|
||||
CMD_HH(layer, model)
|
||||
|
||||
#define LOAD_MODEL_FROM_GEO(model, geo) \
|
||||
CMD_BBH(0x22, 0x08, model), \
|
||||
|
@ -175,18 +176,20 @@
|
|||
CMD_W(unk8)
|
||||
|
||||
#define OBJECT_WITH_ACTS(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) \
|
||||
CMD_BBBB(0x24, 0x18, acts, model), \
|
||||
CMD_BBBB(0x24, 0x1C, acts, 0x00), \
|
||||
CMD_HHHHHH(posX, posY, posZ, angleX, angleY, angleZ), \
|
||||
CMD_W(behParam), \
|
||||
CMD_PTR(beh)
|
||||
CMD_PTR(beh), \
|
||||
CMD_HH(0, model)
|
||||
|
||||
#define OBJECT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh) \
|
||||
OBJECT_WITH_ACTS(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, 0x1F)
|
||||
|
||||
#define MARIO(unk3, behArg, beh) \
|
||||
CMD_BBBB(0x25, 0x0C, 0x00, unk3), \
|
||||
#define MARIO(model, behArg, beh) \
|
||||
CMD_BBH(0x25, 0x10, 0), \
|
||||
CMD_W(behArg), \
|
||||
CMD_PTR(beh)
|
||||
CMD_PTR(beh), \
|
||||
CMD_HH(0, model)
|
||||
|
||||
#define WARP_NODE(id, destLevel, destArea, destNode, flags) \
|
||||
CMD_BBBB(0x26, 0x08, id, destLevel), \
|
||||
|
@ -277,7 +280,7 @@
|
|||
|
||||
#define ADV_DEMO() \
|
||||
CMD_BBH(0x3D, 0x04, 0x0000)
|
||||
|
||||
|
||||
#define CLEAR_DEMO_PTR() \
|
||||
CMD_BBH(0x3E, 0x04, 0x0000)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "game/object_list_processor.h"
|
||||
#include "graph_node.h"
|
||||
#include "surface_collision.h"
|
||||
#include "moon/mod-engine/models/mod-model.h"
|
||||
|
||||
// Macros for retrieving arguments from behavior scripts.
|
||||
#define BHV_CMD_GET_1ST_U8(index) (u8)((gCurBhvCommand[index] >> 24) & 0xFF) // unused
|
||||
|
@ -151,9 +152,9 @@ static s32 bhv_cmd_cylboard(void) {
|
|||
// Command 0x1B: Sets the current model ID of the object.
|
||||
// Usage: SET_MODEL(modelID)
|
||||
static s32 bhv_cmd_set_model(void) {
|
||||
s32 modelID = BHV_CMD_GET_2ND_S16(0);
|
||||
|
||||
gCurrentObject->header.gfx.sharedChild = gLoadedGraphNodes[modelID];
|
||||
u32 modelID = BHV_CMD_GET_U32(0);
|
||||
gCurrentObject->header.gfx.sharedChild = get_graph_node(modelID);
|
||||
printf("bhv_cmd_set_model %d\n", modelID);
|
||||
|
||||
gCurBhvCommand++;
|
||||
return BHV_PROC_CONTINUE;
|
||||
|
|
|
@ -312,6 +312,8 @@ struct GraphNodeObject *init_graph_node_object(struct AllocOnlyPool *pool,
|
|||
vec3f_copy(graphNode->pos, pos);
|
||||
vec3f_copy(graphNode->scale, scale);
|
||||
vec3s_copy(graphNode->angle, angle);
|
||||
// To avoid uninitialised memory usage in audio code
|
||||
vec3f_copy(graphNode->cameraToObject, gVec3fZero);
|
||||
graphNode->sharedChild = sharedChild;
|
||||
graphNode->throwMatrix = NULL;
|
||||
graphNode->unk38.animID = 0;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "surface_collision.h"
|
||||
#include "surface_load.h"
|
||||
#include "level_table.h"
|
||||
#include "moon/mod-engine/models/mod-model.h"
|
||||
|
||||
#define CMD_GET(type, offset) (*(type *) (CMD_PROCESS_OFFSET(offset) + (u8 *) sCurrentCmd))
|
||||
|
||||
|
@ -54,6 +55,8 @@ static s16 sScriptStatus;
|
|||
static s32 sRegister;
|
||||
static struct LevelCommand *sCurrentCmd;
|
||||
|
||||
static struct MemoryPool *sMemPoolForGoddard;
|
||||
|
||||
static s32 eval_script_op(s8 op, s32 arg) {
|
||||
s32 result = 0;
|
||||
|
||||
|
@ -279,17 +282,19 @@ static void level_cmd_load_mio0(void) {
|
|||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
||||
static void *alloc_for_goddard(u32 size) {
|
||||
return mem_pool_alloc(sMemPoolForGoddard, size);
|
||||
}
|
||||
|
||||
static void free_for_goddard(void *ptr) {
|
||||
mem_pool_free(sMemPoolForGoddard, ptr);
|
||||
}
|
||||
|
||||
static void level_cmd_load_mario_head(void) {
|
||||
// TODO: Fix these hardcoded sizes
|
||||
void *addr = main_pool_alloc(DOUBLE_SIZE_ON_64_BIT(0xE1000), MEMORY_POOL_LEFT);
|
||||
if (addr != NULL) {
|
||||
gdm_init(addr, DOUBLE_SIZE_ON_64_BIT(0xE1000));
|
||||
gd_add_to_heap(gZBuffer, sizeof(gZBuffer)); // 0x25800
|
||||
gd_add_to_heap(gFrameBuffer0, 3 * sizeof(gFrameBuffer0)); // 0x70800
|
||||
gdm_setup();
|
||||
gdm_maketestdl(CMD_GET(s16, 2));
|
||||
} else {
|
||||
}
|
||||
sMemPoolForGoddard = mem_pool_init(0, 0);
|
||||
gdm_init(alloc_for_goddard, free_for_goddard);
|
||||
gdm_setup();
|
||||
gdm_maketestdl(CMD_GET(s16, 2));
|
||||
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
@ -319,17 +324,17 @@ static void level_cmd_clear_level(void) {
|
|||
|
||||
static void level_cmd_alloc_level_pool(void) {
|
||||
if (sLevelPool == NULL) {
|
||||
sLevelPool = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool),
|
||||
MEMORY_POOL_LEFT);
|
||||
sLevelPool = alloc_only_pool_init();
|
||||
}
|
||||
|
||||
printf("Called alloc level pool\n");
|
||||
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
||||
static void level_cmd_free_level_pool(void) {
|
||||
s32 i;
|
||||
|
||||
alloc_only_pool_resize(sLevelPool, sLevelPool->usedSpace);
|
||||
sLevelPool = NULL;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
|
@ -371,29 +376,19 @@ static void level_cmd_end_area(void) {
|
|||
}
|
||||
|
||||
static void level_cmd_load_model_from_dl(void) {
|
||||
s16 val1 = CMD_GET(s16, 2) & 0x0FFF;
|
||||
#ifdef VERSION_EU
|
||||
s16 val2 = (CMD_GET(s16, 2) & 0xFFFF) >> 12;
|
||||
#else
|
||||
s16 val2 = CMD_GET(u16, 2) >> 12;
|
||||
#endif
|
||||
void *val3 = CMD_GET(void *, 4);
|
||||
|
||||
if (val1 < 256) {
|
||||
gLoadedGraphNodes[val1] =
|
||||
(struct GraphNode *) init_graph_node_display_list(sLevelPool, 0, val2, val3);
|
||||
}
|
||||
u32 model = CMD_GET(u32, 0xA);
|
||||
s64 layer = CMD_GET(u16, 0x8);
|
||||
void *dl_ptr = CMD_GET(void *, 4);
|
||||
bind_graph_node(model, (struct GraphNode *) init_graph_node_display_list(sLevelPool, 0, layer, dl_ptr));
|
||||
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
||||
static void level_cmd_load_model_from_geo(void) {
|
||||
s16 arg0 = CMD_GET(s16, 2);
|
||||
u32 arg0 = CMD_GET(u32, 2);
|
||||
void *arg1 = CMD_GET(void *, 4);
|
||||
|
||||
if (arg0 < 256) {
|
||||
gLoadedGraphNodes[arg0] = process_geo_layout(sLevelPool, arg1);
|
||||
}
|
||||
bind_graph_node(arg0, process_geo_layout(sLevelPool, arg1));
|
||||
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
@ -404,27 +399,20 @@ static void level_cmd_23(void) {
|
|||
f32 f;
|
||||
} arg2;
|
||||
|
||||
s16 model = CMD_GET(s16, 2) & 0x0FFF;
|
||||
#ifdef VERSION_EU
|
||||
s16 arg0H = (CMD_GET(s16, 2) & 0xFFFF) >> 12;
|
||||
#else
|
||||
u32 model = CMD_GET(u32, 2) & 0x0FFF;
|
||||
s16 arg0H = CMD_GET(u16, 2) >> 12;
|
||||
#endif
|
||||
void *arg1 = CMD_GET(void *, 4);
|
||||
// load an f32, but using an integer load instruction for some reason (hence the union)
|
||||
arg2.i = CMD_GET(s32, 8);
|
||||
|
||||
if (model < 256) {
|
||||
// GraphNodeScale has a GraphNode at the top. This
|
||||
// is being stored to the array, so cast the pointer.
|
||||
gLoadedGraphNodes[model] =
|
||||
(struct GraphNode *) init_graph_node_scale(sLevelPool, 0, arg0H, arg1, arg2.f);
|
||||
}
|
||||
|
||||
bind_graph_node(model, (struct GraphNode *) init_graph_node_scale(sLevelPool, 0, arg0H, arg1, arg2.f));
|
||||
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
||||
static void level_cmd_init_mario(void) {
|
||||
u32 model = CMD_GET(u32, 0xE);
|
||||
vec3s_set(gMarioSpawnInfo->startPos, 0, 0, 0);
|
||||
vec3s_set(gMarioSpawnInfo->startAngle, 0, 0, 0);
|
||||
|
||||
|
@ -432,7 +420,8 @@ static void level_cmd_init_mario(void) {
|
|||
gMarioSpawnInfo->areaIndex = 0;
|
||||
gMarioSpawnInfo->behaviorArg = CMD_GET(u32, 4);
|
||||
gMarioSpawnInfo->behaviorScript = CMD_GET(void *, 8);
|
||||
gMarioSpawnInfo->unk18 = gLoadedGraphNodes[CMD_GET(u8, 3)];
|
||||
gMarioSpawnInfo->unk18 = get_graph_node(model);
|
||||
printf("level_cmd_init_mario %d\n", model);
|
||||
gMarioSpawnInfo->next = NULL;
|
||||
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
|
@ -440,11 +429,10 @@ static void level_cmd_init_mario(void) {
|
|||
|
||||
static void level_cmd_place_object(void) {
|
||||
u8 val7 = 1 << (gCurrActNum - 1);
|
||||
u16 model;
|
||||
u32 model = CMD_GET(u32, 0x1A);
|
||||
struct SpawnInfo *spawnInfo;
|
||||
|
||||
printf("level_cmd_place_object %d\n", model);
|
||||
if (sCurrAreaIndex != -1 && ((CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) {
|
||||
model = CMD_GET(u8, 3);
|
||||
spawnInfo = alloc_only_pool_alloc(sLevelPool, sizeof(struct SpawnInfo));
|
||||
|
||||
spawnInfo->startPos[0] = CMD_GET(s16, 4);
|
||||
|
@ -460,7 +448,7 @@ static void level_cmd_place_object(void) {
|
|||
|
||||
spawnInfo->behaviorArg = CMD_GET(u32, 16);
|
||||
spawnInfo->behaviorScript = CMD_GET(void *, 20);
|
||||
spawnInfo->unk18 = gLoadedGraphNodes[model];
|
||||
spawnInfo->unk18 = get_graph_node(model);
|
||||
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
|
||||
|
||||
gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo;
|
||||
|
|
|
@ -27,8 +27,11 @@ SpatialPartitionCell gDynamicSurfacePartition[16][16];
|
|||
/**
|
||||
* Pools of data to contain either surface nodes or surfaces.
|
||||
*/
|
||||
struct SurfaceNode *sSurfaceNodePool;
|
||||
struct Surface *sSurfacePool;
|
||||
static struct AllocOnlyPool *sStaticSurfaceNodePool;
|
||||
static struct AllocOnlyPool *sStaticSurfacePool;
|
||||
static struct AllocOnlyPool *sDynamicSurfaceNodePool;
|
||||
static struct AllocOnlyPool *sDynamicSurfacePool;
|
||||
static u8 sStaticSurfaceLoadComplete;
|
||||
|
||||
/**
|
||||
* The size of the surface pool (2300).
|
||||
|
@ -41,17 +44,14 @@ u8 unused8038EEA8[0x30];
|
|||
* Allocate the part of the surface node pool to contain a surface node.
|
||||
*/
|
||||
static struct SurfaceNode *alloc_surface_node(void) {
|
||||
struct SurfaceNode *node = &sSurfaceNodePool[gSurfaceNodesAllocated];
|
||||
struct AllocOnlyPool *pool = !sStaticSurfaceLoadComplete ?
|
||||
sStaticSurfaceNodePool : sDynamicSurfaceNodePool;
|
||||
struct SurfaceNode *node = alloc_only_pool_alloc(pool, sizeof(struct SurfaceNode));
|
||||
|
||||
gSurfaceNodesAllocated++;
|
||||
|
||||
node->next = NULL;
|
||||
|
||||
//! A bounds check! If there's more surface nodes than 7000 allowed,
|
||||
// we, um...
|
||||
// Perhaps originally just debug feedback?
|
||||
if (gSurfaceNodesAllocated >= 7000) {
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -61,15 +61,10 @@ static struct SurfaceNode *alloc_surface_node(void) {
|
|||
*/
|
||||
static struct Surface *alloc_surface(void) {
|
||||
|
||||
struct Surface *surface = &sSurfacePool[gSurfacesAllocated];
|
||||
struct AllocOnlyPool *pool = !sStaticSurfaceLoadComplete ? sStaticSurfacePool : sDynamicSurfacePool;
|
||||
struct Surface *surface = alloc_only_pool_alloc(pool, sizeof(struct Surface));
|
||||
gSurfacesAllocated++;
|
||||
|
||||
//! A bounds check! If there's more surfaces than the 2300 allowed,
|
||||
// we, um...
|
||||
// Perhaps originally just debug feedback?
|
||||
if (gSurfacesAllocated >= sSurfacePoolSize) {
|
||||
}
|
||||
|
||||
surface->type = 0;
|
||||
surface->force = 0;
|
||||
surface->flags = 0;
|
||||
|
@ -524,9 +519,10 @@ static void load_environmental_regions(s16 **data) {
|
|||
* Allocate some of the main pool for surfaces (2300 surf) and for surface nodes (7000 nodes).
|
||||
*/
|
||||
void alloc_surface_pools(void) {
|
||||
sSurfacePoolSize = 2300;
|
||||
sSurfaceNodePool = main_pool_alloc(7000 * sizeof(struct SurfaceNode), MEMORY_POOL_LEFT);
|
||||
sSurfacePool = main_pool_alloc(sSurfacePoolSize * sizeof(struct Surface), MEMORY_POOL_LEFT);
|
||||
sStaticSurfaceNodePool = alloc_only_pool_init();
|
||||
sStaticSurfacePool = alloc_only_pool_init();
|
||||
sDynamicSurfaceNodePool = alloc_only_pool_init();
|
||||
sDynamicSurfacePool = alloc_only_pool_init();
|
||||
|
||||
gCCMEnteredSlide = 0;
|
||||
reset_red_coins_collected();
|
||||
|
@ -580,7 +576,6 @@ u32 get_area_terrain_size(s16 *data) {
|
|||
return data - startPos;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process the level file, loading in vertices, surfaces, some objects, and environmental
|
||||
* boxes (water, gas, JRB fog).
|
||||
|
@ -596,6 +591,15 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
|
|||
gSurfaceNodesAllocated = 0;
|
||||
gSurfacesAllocated = 0;
|
||||
|
||||
alloc_only_pool_clear(sStaticSurfaceNodePool);
|
||||
alloc_only_pool_clear(sStaticSurfacePool);
|
||||
alloc_only_pool_clear(sDynamicSurfaceNodePool);
|
||||
alloc_only_pool_clear(sDynamicSurfacePool);
|
||||
sStaticSurfaceLoadComplete = FALSE;
|
||||
|
||||
// Originally they forgot to clear this matrix,
|
||||
// results in segfaults if this is not done.
|
||||
clear_dynamic_surfaces();
|
||||
clear_static_surfaces();
|
||||
|
||||
// A while loop iterating through each section of the level data. Sections of data
|
||||
|
@ -637,6 +641,7 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
|
|||
|
||||
gNumStaticSurfaceNodes = gSurfaceNodesAllocated;
|
||||
gNumStaticSurfaces = gSurfacesAllocated;
|
||||
sStaticSurfaceLoadComplete = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -644,6 +649,12 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
|
|||
*/
|
||||
void clear_dynamic_surfaces(void) {
|
||||
if (!(gTimeStopState & TIME_STOP_ACTIVE)) {
|
||||
if (gSurfacesAllocated > gNumStaticSurfaces) {
|
||||
alloc_only_pool_clear(sDynamicSurfacePool);
|
||||
}
|
||||
if (gSurfaceNodesAllocated > gNumStaticSurfaceNodes) {
|
||||
alloc_only_pool_clear(sDynamicSurfaceNodePool);
|
||||
}
|
||||
gSurfacesAllocated = gNumStaticSurfaces;
|
||||
gSurfaceNodesAllocated = gNumStaticSurfaceNodes;
|
||||
|
||||
|
@ -651,9 +662,6 @@ void clear_dynamic_surfaces(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void unused_80383604(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies an object's transformation to the object's vertices.
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "gfx_dimensions.h"
|
||||
|
||||
struct SpawnInfo gPlayerSpawnInfos[1];
|
||||
struct GraphNode *D_8033A160[0x100];
|
||||
struct Area gAreaData[8];
|
||||
|
||||
struct WarpTransition gWarpTransition;
|
||||
|
@ -38,7 +37,6 @@ s16 gPauseScreenMode;
|
|||
s16 gSaveOptSelectIndex;
|
||||
|
||||
struct SpawnInfo *gMarioSpawnInfo = &gPlayerSpawnInfos[0];
|
||||
struct GraphNode **gLoadedGraphNodes = D_8033A160;
|
||||
struct Area *gAreas = gAreaData;
|
||||
struct Area *gCurrentArea = NULL;
|
||||
struct CreditsEntry *gCurrCreditsEntry = NULL;
|
||||
|
@ -168,6 +166,10 @@ void load_obj_warp_nodes(void) {
|
|||
struct ObjectWarpNode *sp24;
|
||||
struct Object *sp20 = (struct Object *) gObjParentGraphNode.children;
|
||||
|
||||
if (sp20 == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
struct Object *sp1C = sp20;
|
||||
|
||||
|
|
|
@ -118,9 +118,8 @@ struct WarpTransition
|
|||
/*0x04*/ struct WarpTransitionData data;
|
||||
};
|
||||
|
||||
extern struct GraphNode **gLoadedGraphNodes;
|
||||
extern struct SpawnInfo gPlayerSpawnInfos[];
|
||||
extern struct GraphNode *D_8033A160[];
|
||||
extern struct GraphNode *gLoadedModelsPool[];
|
||||
extern struct Area gAreaData[];
|
||||
extern struct WarpTransition gWarpTransition;
|
||||
extern s16 gCurrCourseNum;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "spawn_object.h"
|
||||
#include "spawn_sound.h"
|
||||
#include "thread6.h"
|
||||
#include "moon/mod-engine/models/mod-model.h"
|
||||
|
||||
#define o gCurrentObject
|
||||
|
||||
|
@ -76,7 +77,7 @@ struct Struct802C0DF0 {
|
|||
u8 unk0;
|
||||
u8 unk1;
|
||||
u8 unk2;
|
||||
u8 model;
|
||||
u32 model;
|
||||
const BehaviorScript *behavior;
|
||||
};
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ static s8 sPieceActions14[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1 };
|
||||
|
||||
struct BowserPuzzlePiece {
|
||||
u8 model;
|
||||
u32 model;
|
||||
s8 xOffset;
|
||||
s8 zOffset;
|
||||
s8 initialAction;
|
||||
|
|
|
@ -12,12 +12,10 @@ void bhv_object_bubble_loop(void) {
|
|||
f32 bubbleY = o->oPosY;
|
||||
|
||||
if (bubbleY > waterY) {
|
||||
if (gFreeObjectList.next) {
|
||||
bubbleSplash = spawn_object_at_origin(o, 0, MODEL_SMALL_WATER_SPLASH, bhvBubbleSplash);
|
||||
bubbleSplash->oPosX = o->oPosX;
|
||||
bubbleSplash->oPosY = bubbleY + 5.0f;
|
||||
bubbleSplash->oPosZ = o->oPosZ;
|
||||
}
|
||||
bubbleSplash = spawn_object_at_origin(o, 0, MODEL_SMALL_WATER_SPLASH, bhvBubbleSplash);
|
||||
bubbleSplash->oPosX = o->oPosX;
|
||||
bubbleSplash->oPosY = bubbleY + 5.0f;
|
||||
bubbleSplash->oPosZ = o->oPosZ;
|
||||
|
||||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
}
|
||||
|
|
|
@ -8,20 +8,20 @@ void bhv_celebration_star_init(void) {
|
|||
o->oCelebStarDiameterOfRotation = 100;
|
||||
#if BUGFIX_STAR_BOWSER_KEY
|
||||
if (gCurrLevelNum == LEVEL_BOWSER_1 || gCurrLevelNum == LEVEL_BOWSER_2) {
|
||||
o->header.gfx.sharedChild = gLoadedGraphNodes[MODEL_BOWSER_KEY];
|
||||
o->header.gfx.sharedChild = get_graph_node(MODEL_BOWSER_KEY);
|
||||
o->oFaceAnglePitch = 0;
|
||||
o->oFaceAngleRoll = 49152;
|
||||
cur_obj_scale(0.1f);
|
||||
o->oCelebStarUnkF4 = 1;
|
||||
} else {
|
||||
o->header.gfx.sharedChild = gLoadedGraphNodes[MODEL_STAR];
|
||||
o->header.gfx.sharedChild = get_graph_node(MODEL_STAR);
|
||||
o->oFaceAnglePitch = 0;
|
||||
o->oFaceAngleRoll = 0;
|
||||
cur_obj_scale(0.4f);
|
||||
o->oCelebStarUnkF4 = 0;
|
||||
}
|
||||
#else
|
||||
o->header.gfx.sharedChild = gLoadedGraphNodes[MODEL_STAR];
|
||||
o->header.gfx.sharedChild = get_graph_node(MODEL_STAR);
|
||||
cur_obj_scale(0.4f);
|
||||
o->oFaceAnglePitch = 0;
|
||||
o->oFaceAngleRoll = 0;
|
||||
|
|
|
@ -19,9 +19,9 @@ void bhv_collect_star_init(void) {
|
|||
starId = (o->oBehParams >> 24) & 0xFF;
|
||||
currentLevelStarFlags = save_file_get_star_flags(gCurrSaveFileNum - 1, gCurrCourseNum - 1);
|
||||
if (currentLevelStarFlags & (1 << starId)) {
|
||||
o->header.gfx.sharedChild = gLoadedGraphNodes[MODEL_TRANSPARENT_STAR];
|
||||
o->header.gfx.sharedChild = get_graph_node(MODEL_TRANSPARENT_STAR);
|
||||
} else {
|
||||
o->header.gfx.sharedChild = gLoadedGraphNodes[MODEL_STAR];
|
||||
o->header.gfx.sharedChild = get_graph_node(MODEL_STAR);
|
||||
}
|
||||
|
||||
obj_set_hitbox(o, &sCollectStarHitbox);
|
||||
|
|
|
@ -63,8 +63,7 @@ void bhv_small_water_wave_loop(void) {
|
|||
if (o->oPosY > sp1C) {
|
||||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
o->oPosY += 5.0f;
|
||||
if (gFreeObjectList.next != NULL)
|
||||
spawn_object(o, MODEL_SMALL_WATER_SPLASH, bhvObjectWaterSplash);
|
||||
spawn_object(o, MODEL_SMALL_WATER_SPLASH, bhvObjectWaterSplash);
|
||||
}
|
||||
if (o->oInteractStatus & INT_STATUS_INTERACTED)
|
||||
obj_mark_for_deletion(o);
|
||||
|
|
|
@ -29,8 +29,11 @@
|
|||
// know of a good way to split them
|
||||
struct Controller gControllers[3];
|
||||
struct SPTask *gGfxSPTask;
|
||||
Gfx *gDisplayListHead;
|
||||
u8 *gGfxPoolEnd;
|
||||
|
||||
struct AllocOnlyPool *gGfxAllocOnlyPool;
|
||||
Gfx *gDisplayListHeadInChunk;
|
||||
Gfx *gDisplayListEndInChunk;
|
||||
|
||||
struct GfxPool *gGfxPool;
|
||||
OSContStatus gControllerStatuses[4];
|
||||
OSContPad gControllerPads[4];
|
||||
|
@ -259,31 +262,22 @@ void end_master_display_list(void) {
|
|||
create_task_structure();
|
||||
}
|
||||
|
||||
//void draw_reset_bars(void) { // TARGET_64 only
|
||||
// Stubbed. Only N64 target uses this
|
||||
// }
|
||||
|
||||
void rendering_init(void) {
|
||||
gGfxPool = &gGfxPools[0];
|
||||
set_segment_base_addr(1, gGfxPool->buffer);
|
||||
gGfxSPTask = &gGfxPool->spTask;
|
||||
gDisplayListHead = gGfxPool->buffer;
|
||||
gGfxPoolEnd = (u8 *) (gGfxPool->buffer + GFX_POOL_SIZE);
|
||||
init_render_image();
|
||||
clear_frame_buffer(0);
|
||||
end_master_display_list();
|
||||
send_display_list(&gGfxPool->spTask);
|
||||
|
||||
frameBufferIndex++;
|
||||
gGlobalTimer++;
|
||||
Gfx **alloc_next_dl(void) {
|
||||
u32 size = 1000;
|
||||
Gfx *new_chunk = alloc_only_pool_alloc(gGfxAllocOnlyPool, size * sizeof(Gfx));
|
||||
gSPBranchList(gDisplayListHeadInChunk++, new_chunk);
|
||||
gDisplayListHeadInChunk = new_chunk;
|
||||
gDisplayListEndInChunk = new_chunk + size;
|
||||
return &gDisplayListHeadInChunk;
|
||||
}
|
||||
|
||||
void config_gfx_pool(void) {
|
||||
gGfxPool = &gGfxPools[gGlobalTimer % GFX_NUM_POOLS];
|
||||
set_segment_base_addr(1, gGfxPool->buffer);
|
||||
gGfxSPTask = &gGfxPool->spTask;
|
||||
gDisplayListHead = gGfxPool->buffer;
|
||||
gGfxPoolEnd = (u8 *) (gGfxPool->buffer + GFX_POOL_SIZE);
|
||||
gDisplayListHeadInChunk = gGfxPool->buffer;
|
||||
gDisplayListEndInChunk = gDisplayListHeadInChunk + 1;
|
||||
alloc_only_pool_clear(gGfxAllocOnlyPool);
|
||||
}
|
||||
|
||||
/** Handles vsync. */
|
||||
|
@ -596,11 +590,4 @@ void game_loop_one_iteration(void) {
|
|||
read_controller_inputs();
|
||||
levelCommandAddr = level_script_execute(levelCommandAddr);
|
||||
display_and_vsync();
|
||||
|
||||
// when debug info is enabled, print the "BUF %d" information.
|
||||
if (gShowDebugText) {
|
||||
// subtract the end of the gfx pool with the display list to obtain the
|
||||
// amount of free space remaining.
|
||||
print_text_fmt_int(180, 20, "BUF %d", gGfxPoolEnd - (u8 *) gDisplayListHead);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "types.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define GFX_POOL_SIZE 6400
|
||||
|
||||
struct GfxPool {
|
||||
Gfx buffer[GFX_POOL_SIZE];
|
||||
struct SPTask spTask;
|
||||
|
@ -35,8 +37,9 @@ extern uintptr_t gPhysicalZBuffer;
|
|||
extern void *D_80339CF0;
|
||||
extern void *D_80339CF4;
|
||||
extern struct SPTask *gGfxSPTask;
|
||||
extern Gfx *gDisplayListHead;
|
||||
extern u8 *gGfxPoolEnd;
|
||||
extern struct AllocOnlyPool *gGfxAllocOnlyPool;
|
||||
extern Gfx *gDisplayListHeadInChunk;
|
||||
extern Gfx *gDisplayListEndInChunk;
|
||||
extern struct GfxPool *gGfxPool;
|
||||
extern u8 gControllerBits;
|
||||
extern s8 gEepromProbe;
|
||||
|
@ -71,4 +74,7 @@ void rendering_init(void);
|
|||
void config_gfx_pool(void);
|
||||
void display_and_vsync(void);
|
||||
|
||||
Gfx **alloc_next_dl(void);
|
||||
#define gDisplayListHead (*(gDisplayListEndInChunk - gDisplayListHeadInChunk >= 2 ? &gDisplayListHeadInChunk : alloc_next_dl()))
|
||||
|
||||
#endif // GAME_INIT_H
|
||||
|
|
|
@ -245,11 +245,7 @@ void spawn_special_objects(s16 areaIndex, s16 **specialObjList) {
|
|||
s16 y;
|
||||
s16 z;
|
||||
s16 extraParams[4];
|
||||
#ifdef VERSION_EU
|
||||
s16 model;
|
||||
#else
|
||||
u8 model;
|
||||
#endif
|
||||
u32 model;
|
||||
u8 type;
|
||||
u8 presetID;
|
||||
u8 defaultParam;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <PR/ultratypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sm64.h"
|
||||
|
||||
#define INCLUDED_FROM_MEMORY_C
|
||||
|
@ -19,26 +21,40 @@
|
|||
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
|
||||
|
||||
struct MainPoolState {
|
||||
u32 freeSpace;
|
||||
struct MainPoolBlock *listHeadL;
|
||||
struct MainPoolBlock *listHeadR;
|
||||
void *prev;
|
||||
};
|
||||
|
||||
struct MainPoolBlock {
|
||||
struct MainPoolBlock *prev;
|
||||
struct MainPoolBlock *next;
|
||||
void (*releaseHandler)(void *addr);
|
||||
};
|
||||
|
||||
struct AllocOnlyPoolBlock {
|
||||
struct AllocOnlyPoolBlock *prev;
|
||||
#if !IS_64_BIT
|
||||
void *pad; // require 8 bytes alignment
|
||||
#endif
|
||||
};
|
||||
|
||||
struct AllocOnlyPool {
|
||||
struct AllocOnlyPoolBlock *lastBlock;
|
||||
u32 lastBlockSize;
|
||||
u32 lastBlockNextPos;
|
||||
};
|
||||
|
||||
struct FreeListNode {
|
||||
struct FreeListNode *next;
|
||||
};
|
||||
|
||||
struct AllocatedNode {
|
||||
s32 bin;
|
||||
s32 pad;
|
||||
};
|
||||
|
||||
struct MemoryPool {
|
||||
u32 totalSpace;
|
||||
struct MemoryBlock *firstBlock;
|
||||
struct MemoryBlock *freeList;
|
||||
};
|
||||
|
||||
struct MemoryBlock {
|
||||
struct MemoryBlock *next;
|
||||
u32 size;
|
||||
struct AllocOnlyPool *allocOnlyPool;
|
||||
struct FreeListNode *bins[27];
|
||||
};
|
||||
|
||||
extern uintptr_t sSegmentTable[32];
|
||||
|
@ -85,23 +101,14 @@ void *virtual_to_segmented(UNUSED u32 segment, const void *addr) {
|
|||
void move_segment_table_to_dmem(void) {
|
||||
}
|
||||
|
||||
static void main_pool_free_all(void) {
|
||||
while (sPoolListHeadL != NULL) {
|
||||
main_pool_free(sPoolListHeadL + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the main memory pool. This pool is conceptually a pair of stacks
|
||||
* that grow inward from the left and right. It therefore only supports
|
||||
* freeing the object that was most recently allocated from a side.
|
||||
*/
|
||||
void main_pool_init(void *start, void *end) {
|
||||
sPoolStart = (u8 *) ALIGN16((uintptr_t) start) + 16;
|
||||
sPoolEnd = (u8 *) ALIGN16((uintptr_t) end - 15) - 16;
|
||||
sPoolFreeSpace = sPoolEnd - sPoolStart;
|
||||
|
||||
sPoolListHeadL = (struct MainPoolBlock *) (sPoolStart - 16);
|
||||
sPoolListHeadR = (struct MainPoolBlock *) sPoolEnd;
|
||||
sPoolListHeadL->prev = NULL;
|
||||
sPoolListHeadL->next = NULL;
|
||||
sPoolListHeadR->prev = NULL;
|
||||
sPoolListHeadR->next = NULL;
|
||||
void main_pool_init(void) {
|
||||
atexit(main_pool_free_all);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,100 +116,46 @@ void main_pool_init(void *start, void *end) {
|
|||
* specified side of the pool (MEMORY_POOL_LEFT or MEMORY_POOL_RIGHT).
|
||||
* If there is not enough space, return NULL.
|
||||
*/
|
||||
void *main_pool_alloc(u32 size, u32 side) {
|
||||
struct MainPoolBlock *newListHead;
|
||||
void *addr = NULL;
|
||||
|
||||
size = ALIGN16(size) + 16;
|
||||
if (size != 0 && sPoolFreeSpace >= size) {
|
||||
sPoolFreeSpace -= size;
|
||||
if (side == MEMORY_POOL_LEFT) {
|
||||
newListHead = (struct MainPoolBlock *) ((u8 *) sPoolListHeadL + size);
|
||||
sPoolListHeadL->next = newListHead;
|
||||
newListHead->prev = sPoolListHeadL;
|
||||
newListHead->next = NULL;
|
||||
addr = (u8 *) sPoolListHeadL + 16;
|
||||
sPoolListHeadL = newListHead;
|
||||
} else {
|
||||
newListHead = (struct MainPoolBlock *) ((u8 *) sPoolListHeadR - size);
|
||||
sPoolListHeadR->prev = newListHead;
|
||||
newListHead->next = sPoolListHeadR;
|
||||
newListHead->prev = NULL;
|
||||
sPoolListHeadR = newListHead;
|
||||
addr = (u8 *) sPoolListHeadR + 16;
|
||||
}
|
||||
void *main_pool_alloc(u32 size, void (*releaseHandler)(void *addr)) {
|
||||
struct MainPoolBlock *newListHead = (struct MainPoolBlock *) malloc(sizeof(struct MainPoolBlock) + size);
|
||||
if (newListHead == NULL) {
|
||||
abort();
|
||||
}
|
||||
return addr;
|
||||
if (sPoolListHeadL != NULL) {
|
||||
sPoolListHeadL->next = newListHead;
|
||||
}
|
||||
newListHead->prev = sPoolListHeadL;
|
||||
newListHead->next = NULL;
|
||||
newListHead->releaseHandler = releaseHandler;
|
||||
sPoolListHeadL = newListHead;
|
||||
return newListHead + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a block of memory that was allocated from the pool. The block must be
|
||||
* the most recently allocated block from its end of the pool.
|
||||
* Return the amount of free space left in the pool.
|
||||
*/
|
||||
u32 main_pool_free(void *addr) {
|
||||
struct MainPoolBlock *block = (struct MainPoolBlock *) ((u8 *) addr - 16);
|
||||
struct MainPoolBlock *oldListHead = (struct MainPoolBlock *) ((u8 *) addr - 16);
|
||||
|
||||
if (oldListHead < sPoolListHeadL) {
|
||||
while (oldListHead->next != NULL) {
|
||||
oldListHead = oldListHead->next;
|
||||
struct MainPoolBlock *block = ((struct MainPoolBlock *) addr) - 1;
|
||||
void *toFree;
|
||||
do {
|
||||
if (sPoolListHeadL == NULL) {
|
||||
abort();
|
||||
}
|
||||
sPoolListHeadL = block;
|
||||
sPoolListHeadL->next = NULL;
|
||||
sPoolFreeSpace += (uintptr_t) oldListHead - (uintptr_t) sPoolListHeadL;
|
||||
} else {
|
||||
while (oldListHead->prev != NULL) {
|
||||
oldListHead = oldListHead->prev;
|
||||
if (sPoolListHeadL->releaseHandler != NULL) {
|
||||
sPoolListHeadL->releaseHandler(sPoolListHeadL + 1);
|
||||
}
|
||||
sPoolListHeadR = block->next;
|
||||
sPoolListHeadR->prev = NULL;
|
||||
sPoolFreeSpace += (uintptr_t) sPoolListHeadR - (uintptr_t) oldListHead;
|
||||
}
|
||||
return sPoolFreeSpace;
|
||||
toFree = sPoolListHeadL;
|
||||
sPoolListHeadL = sPoolListHeadL->prev;
|
||||
if (sPoolListHeadL != NULL) {
|
||||
sPoolListHeadL->next = NULL;
|
||||
}
|
||||
free(toFree);
|
||||
} while (toFree != block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize a block of memory that was allocated from the left side of the pool.
|
||||
* If the block is increasing in size, it must be the most recently allocated
|
||||
* block from the left side.
|
||||
* The block does not move.
|
||||
*/
|
||||
void *main_pool_realloc(void *addr, u32 size) {
|
||||
void *newAddr = NULL;
|
||||
struct MainPoolBlock *block = (struct MainPoolBlock *) ((u8 *) addr - 16);
|
||||
|
||||
if (block->next == sPoolListHeadL) {
|
||||
main_pool_free(addr);
|
||||
newAddr = main_pool_alloc(size, MEMORY_POOL_LEFT);
|
||||
}
|
||||
return newAddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of the largest block that can currently be allocated from the
|
||||
* pool.
|
||||
*/
|
||||
u32 main_pool_available(void) {
|
||||
return sPoolFreeSpace - 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push pool state, to be restored later. Return the amount of free space left
|
||||
* in the pool.
|
||||
*/
|
||||
u32 main_pool_push_state(void) {
|
||||
void *prevState = gMainPoolState;
|
||||
u32 freeSpace = sPoolFreeSpace;
|
||||
struct MainPoolBlock *lhead = sPoolListHeadL;
|
||||
struct MainPoolBlock *rhead = sPoolListHeadR;
|
||||
|
||||
gMainPoolState = main_pool_alloc(sizeof(*gMainPoolState), MEMORY_POOL_LEFT);
|
||||
gMainPoolState->freeSpace = freeSpace;
|
||||
gMainPoolState->listHeadL = lhead;
|
||||
gMainPoolState->listHeadR = rhead;
|
||||
struct MainPoolState *prevState = gMainPoolState;
|
||||
gMainPoolState = main_pool_alloc(sizeof(*gMainPoolState), NULL);
|
||||
gMainPoolState->prev = prevState;
|
||||
return sPoolFreeSpace;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -210,11 +163,9 @@ u32 main_pool_push_state(void) {
|
|||
* amount of free space left in the pool.
|
||||
*/
|
||||
u32 main_pool_pop_state(void) {
|
||||
sPoolFreeSpace = gMainPoolState->freeSpace;
|
||||
sPoolListHeadL = gMainPoolState->listHeadL;
|
||||
sPoolListHeadR = gMainPoolState->listHeadR;
|
||||
gMainPoolState = gMainPoolState->prev;
|
||||
return sPoolFreeSpace;
|
||||
struct MainPoolState *prevState = gMainPoolState->prev;
|
||||
main_pool_free(gMainPoolState);
|
||||
gMainPoolState = prevState;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -235,7 +186,7 @@ static void *dynamic_dma_read(u8 *srcStart, u8 *srcEnd, u32 side) {
|
|||
void *dest;
|
||||
u32 size = ALIGN16(srcEnd - srcStart);
|
||||
|
||||
dest = main_pool_alloc(size, side);
|
||||
dest = main_pool_alloc(size, NULL);
|
||||
if (dest != NULL) {
|
||||
dma_read(dest, srcStart, srcEnd);
|
||||
}
|
||||
|
@ -247,160 +198,115 @@ static void *dynamic_dma_read(u8 *srcStart, u8 *srcEnd, u32 side) {
|
|||
* support freeing allocated memory.
|
||||
* Return NULL if there is not enough space in the main pool.
|
||||
*/
|
||||
struct AllocOnlyPool *alloc_only_pool_init(u32 size, u32 side) {
|
||||
void *addr;
|
||||
struct AllocOnlyPool *subPool = NULL;
|
||||
|
||||
size = ALIGN4(size);
|
||||
addr = main_pool_alloc(size + sizeof(struct AllocOnlyPool), side);
|
||||
if (addr != NULL) {
|
||||
subPool = (struct AllocOnlyPool *) addr;
|
||||
subPool->totalSpace = size;
|
||||
subPool->usedSpace = 0;
|
||||
subPool->startPtr = (u8 *) addr + sizeof(struct AllocOnlyPool);
|
||||
subPool->freePtr = (u8 *) addr + sizeof(struct AllocOnlyPool);
|
||||
static void alloc_only_pool_release_handler(void *addr) {
|
||||
struct AllocOnlyPool *pool = (struct AllocOnlyPool *) addr;
|
||||
struct AllocOnlyPoolBlock *block = pool->lastBlock;
|
||||
while (block != NULL) {
|
||||
struct AllocOnlyPoolBlock *prev = block->prev;
|
||||
free(block);
|
||||
block = prev;
|
||||
}
|
||||
return subPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate from an allocation-only pool.
|
||||
* Return NULL if there is not enough space.
|
||||
*/
|
||||
void *alloc_only_pool_alloc(struct AllocOnlyPool *pool, s32 size) {
|
||||
void *addr = NULL;
|
||||
struct AllocOnlyPool *alloc_only_pool_init(void) {
|
||||
struct AllocOnlyPool *pool;
|
||||
void *addr = main_pool_alloc(sizeof(struct AllocOnlyPool), alloc_only_pool_release_handler);
|
||||
|
||||
size = ALIGN4(size);
|
||||
if (size > 0 && pool->usedSpace + size <= pool->totalSpace) {
|
||||
addr = pool->freePtr;
|
||||
pool->freePtr += size;
|
||||
pool->usedSpace += size;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
pool = (struct AllocOnlyPool *) addr;
|
||||
pool->lastBlock = NULL;
|
||||
pool->lastBlockSize = 0;
|
||||
pool->lastBlockNextPos = 0;
|
||||
|
||||
/**
|
||||
* Resize an allocation-only pool.
|
||||
* If the pool is increasing in size, the pool must be the last thing allocated
|
||||
* from the left end of the main pool.
|
||||
* The pool does not move.
|
||||
*/
|
||||
struct AllocOnlyPool *alloc_only_pool_resize(struct AllocOnlyPool *pool, u32 size) {
|
||||
struct AllocOnlyPool *newPool;
|
||||
|
||||
size = ALIGN4(size);
|
||||
newPool = main_pool_realloc(pool, size + sizeof(struct AllocOnlyPool));
|
||||
if (newPool != NULL) {
|
||||
pool->totalSpace = size;
|
||||
}
|
||||
return newPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a memory pool from the main pool. This pool supports arbitrary
|
||||
* order for allocation/freeing.
|
||||
* Return NULL if there is not enough space in the main pool.
|
||||
*/
|
||||
struct MemoryPool *mem_pool_init(u32 size, u32 side) {
|
||||
void *addr;
|
||||
struct MemoryBlock *block;
|
||||
struct MemoryPool *pool = NULL;
|
||||
|
||||
size = ALIGN4(size);
|
||||
addr = main_pool_alloc(size + ALIGN16(sizeof(struct MemoryPool)), side);
|
||||
if (addr != NULL) {
|
||||
pool = (struct MemoryPool *) addr;
|
||||
|
||||
pool->totalSpace = size;
|
||||
pool->firstBlock = (struct MemoryBlock *) ((u8 *) addr + ALIGN16(sizeof(struct MemoryPool)));
|
||||
pool->freeList = (struct MemoryBlock *) ((u8 *) addr + ALIGN16(sizeof(struct MemoryPool)));
|
||||
|
||||
block = pool->firstBlock;
|
||||
block->next = NULL;
|
||||
block->size = pool->totalSpace;
|
||||
}
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate from a memory pool. Return NULL if there is not enough space.
|
||||
*/
|
||||
void *mem_pool_alloc(struct MemoryPool *pool, u32 size) {
|
||||
struct MemoryBlock *freeBlock = (struct MemoryBlock *) &pool->freeList;
|
||||
void *addr = NULL;
|
||||
void alloc_only_pool_clear(struct AllocOnlyPool *pool) {
|
||||
alloc_only_pool_release_handler(pool);
|
||||
pool->lastBlock = NULL;
|
||||
pool->lastBlockSize = 0;
|
||||
pool->lastBlockNextPos = 0;
|
||||
}
|
||||
|
||||
size = ALIGN4(size) + sizeof(struct MemoryBlock);
|
||||
while (freeBlock->next != NULL) {
|
||||
if (freeBlock->next->size >= size) {
|
||||
addr = (u8 *) freeBlock->next + sizeof(struct MemoryBlock);
|
||||
if (freeBlock->next->size - size <= sizeof(struct MemoryBlock)) {
|
||||
freeBlock->next = freeBlock->next->next;
|
||||
} else {
|
||||
struct MemoryBlock *newBlock = (struct MemoryBlock *) ((u8 *) freeBlock->next + size);
|
||||
newBlock->size = freeBlock->next->size - size;
|
||||
newBlock->next = freeBlock->next->next;
|
||||
freeBlock->next->size = size;
|
||||
freeBlock->next = newBlock;
|
||||
}
|
||||
break;
|
||||
void *alloc_only_pool_alloc(struct AllocOnlyPool *pool, s32 size) {
|
||||
u8 *addr;
|
||||
u32 s = size;
|
||||
if (pool->lastBlockSize - pool->lastBlockNextPos < s) {
|
||||
struct AllocOnlyPoolBlock *block;
|
||||
u32 nextSize = pool->lastBlockSize * 2;
|
||||
if (nextSize < 100) {
|
||||
nextSize = 100;
|
||||
}
|
||||
freeBlock = freeBlock->next;
|
||||
if (nextSize < s) {
|
||||
nextSize = s;
|
||||
}
|
||||
block = (struct AllocOnlyPoolBlock *) malloc(sizeof(struct AllocOnlyPoolBlock) + nextSize);
|
||||
if (block == NULL) {
|
||||
abort();
|
||||
}
|
||||
block->prev = pool->lastBlock;
|
||||
pool->lastBlock = block;
|
||||
pool->lastBlockSize = nextSize;
|
||||
pool->lastBlockNextPos = 0;
|
||||
}
|
||||
addr = (u8 *) (pool->lastBlock + 1) + pool->lastBlockNextPos;
|
||||
pool->lastBlockNextPos += s;
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a block that was allocated using mem_pool_alloc.
|
||||
*/
|
||||
void mem_pool_free(struct MemoryPool *pool, void *addr) {
|
||||
struct MemoryBlock *block = (struct MemoryBlock *) ((u8 *) addr - sizeof(struct MemoryBlock));
|
||||
struct MemoryBlock *freeList = pool->freeList;
|
||||
struct MemoryPool *mem_pool_init(UNUSED u32 size, UNUSED u32 side) {
|
||||
struct MemoryPool *pool;
|
||||
void *addr = main_pool_alloc(sizeof(struct MemoryPool), NULL);
|
||||
u32 i;
|
||||
|
||||
if (pool->freeList == NULL) {
|
||||
pool->freeList = block;
|
||||
block->next = NULL;
|
||||
} else {
|
||||
if (block < pool->freeList) {
|
||||
if ((u8 *) pool->freeList == (u8 *) block + block->size) {
|
||||
block->size += freeList->size;
|
||||
block->next = freeList->next;
|
||||
pool->freeList = block;
|
||||
} else {
|
||||
block->next = pool->freeList;
|
||||
pool->freeList = block;
|
||||
}
|
||||
} else {
|
||||
while (freeList->next != NULL) {
|
||||
if (freeList < block && block < freeList->next) {
|
||||
break;
|
||||
}
|
||||
freeList = freeList->next;
|
||||
}
|
||||
if ((u8 *) freeList + freeList->size == (u8 *) block) {
|
||||
freeList->size += block->size;
|
||||
block = freeList;
|
||||
} else {
|
||||
block->next = freeList->next;
|
||||
freeList->next = block;
|
||||
}
|
||||
if (block->next != NULL && (u8 *) block->next == (u8 *) block + block->size) {
|
||||
block->size = block->size + block->next->size;
|
||||
block->next = block->next->next;
|
||||
}
|
||||
pool = (struct MemoryPool *) addr;
|
||||
pool->allocOnlyPool = alloc_only_pool_init();
|
||||
for (i = 0; i < ARRAY_COUNT(pool->bins); i++) {
|
||||
pool->bins[i] = NULL;
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
void *mem_pool_alloc(struct MemoryPool *pool, u32 size) {
|
||||
struct FreeListNode *node;
|
||||
struct AllocatedNode *an;
|
||||
s32 bin = -1;
|
||||
u32 itemSize;
|
||||
u32 i;
|
||||
|
||||
for (i = 3; i < 30; i++) {
|
||||
if (size <= (1U << i)) {
|
||||
bin = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bin == -1) {
|
||||
abort();
|
||||
}
|
||||
itemSize = 1 << bin;
|
||||
node = pool->bins[bin - 3];
|
||||
if (node == NULL) {
|
||||
node = alloc_only_pool_alloc(pool->allocOnlyPool, sizeof(struct AllocatedNode) + itemSize);
|
||||
node->next = NULL;
|
||||
pool->bins[bin - 3] = node;
|
||||
}
|
||||
an = (struct AllocatedNode *) node;
|
||||
pool->bins[bin - 3] = node->next;
|
||||
an->bin = bin;
|
||||
return an + 1;
|
||||
}
|
||||
|
||||
void mem_pool_free(struct MemoryPool *pool, void *addr) {
|
||||
struct AllocatedNode *an = ((struct AllocatedNode *) addr) - 1;
|
||||
struct FreeListNode *node = (struct FreeListNode *) an;
|
||||
s32 bin = an->bin;
|
||||
node->next = pool->bins[bin - 3];
|
||||
pool->bins[bin - 3] = node;
|
||||
}
|
||||
|
||||
void *alloc_display_list(u32 size) {
|
||||
void *ptr = NULL;
|
||||
|
||||
size = ALIGN8(size);
|
||||
if (gGfxPoolEnd - size >= (u8 *) gDisplayListHead) {
|
||||
gGfxPoolEnd -= size;
|
||||
ptr = gGfxPoolEnd;
|
||||
} else {
|
||||
}
|
||||
return ptr;
|
||||
return alloc_only_pool_alloc(gGfxAllocOnlyPool, size);
|
||||
}
|
||||
|
||||
static struct MarioAnimDmaRelatedThing *func_802789F0(u8 *srcAddr) {
|
||||
|
|
|
@ -8,16 +8,7 @@
|
|||
#define MEMORY_POOL_LEFT 0
|
||||
#define MEMORY_POOL_RIGHT 1
|
||||
|
||||
#define GFX_POOL_SIZE (512 * 1024)
|
||||
|
||||
struct AllocOnlyPool
|
||||
{
|
||||
s32 totalSpace;
|
||||
s32 usedSpace;
|
||||
u8 *startPtr;
|
||||
u8 *freePtr;
|
||||
};
|
||||
|
||||
struct AllocOnlyPool;
|
||||
struct MemoryPool;
|
||||
struct MarioAnimation;
|
||||
struct Animation;
|
||||
|
@ -35,8 +26,8 @@ void *segmented_to_virtual(const void *addr);
|
|||
void *virtual_to_segmented(u32 segment, const void *addr);
|
||||
void move_segment_table_to_dmem(void);
|
||||
|
||||
void main_pool_init(void *start, void *end);
|
||||
void *main_pool_alloc(u32 size, u32 side);
|
||||
void main_pool_init(void);
|
||||
void *main_pool_alloc(u32 size, void (*releaseHandler)(void *addr));
|
||||
u32 main_pool_free(void *addr);
|
||||
void *main_pool_realloc(void *addr, u32 size);
|
||||
u32 main_pool_available(void);
|
||||
|
@ -49,9 +40,9 @@ u32 main_pool_pop_state(void);
|
|||
#define load_segment_decompress_heap(...)
|
||||
#define load_engine_code_segment(...)
|
||||
|
||||
struct AllocOnlyPool *alloc_only_pool_init(u32 size, u32 side);
|
||||
struct AllocOnlyPool *alloc_only_pool_init(void);
|
||||
void alloc_only_pool_clear(struct AllocOnlyPool *pool);
|
||||
void *alloc_only_pool_alloc(struct AllocOnlyPool *pool, s32 size);
|
||||
struct AllocOnlyPool *alloc_only_pool_resize(struct AllocOnlyPool *pool, u32 size);
|
||||
|
||||
struct MemoryPool *mem_pool_init(u32 size, u32 side);
|
||||
void *mem_pool_alloc(struct MemoryPool *pool, u32 size);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "save_file.h"
|
||||
#include "spawn_object.h"
|
||||
#include "spawn_sound.h"
|
||||
#include "moon/mod-engine/models/mod-model.h"
|
||||
|
||||
/**
|
||||
* @file obj_behaviors.c
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "save_file.h"
|
||||
#include "seq_ids.h"
|
||||
#include "spawn_sound.h"
|
||||
#include "moon/mod-engine/models/mod-model.h"
|
||||
|
||||
#define POS_OP_SAVE_POSITION 0
|
||||
#define POS_OP_COMPUTE_VELOCITY 1
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "rendering_graph_node.h"
|
||||
#include "spawn_object.h"
|
||||
#include "spawn_sound.h"
|
||||
#include "moon/mod-engine/models/mod-model.h"
|
||||
|
||||
s8 D_8032F0A0[] = { 0xF8, 0x08, 0xFC, 0x04 };
|
||||
s16 D_8032F0A4[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
|
||||
|
@ -478,7 +479,7 @@ struct Object *spawn_object_rel_with_rot(struct Object *parent, u32 model, const
|
|||
return newObj;
|
||||
}
|
||||
|
||||
struct Object *spawn_obj_with_transform_flags(struct Object *sp20, s32 model, const BehaviorScript *sp28) {
|
||||
struct Object *spawn_obj_with_transform_flags(struct Object *sp20, u32 model, const BehaviorScript *sp28) {
|
||||
struct Object *sp1C = spawn_object(sp20, model, sp28);
|
||||
sp1C->oFlags |= OBJ_FLAG_0020 | OBJ_FLAG_SET_THROW_MATRIX_FROM_TRANSFORM;
|
||||
return sp1C;
|
||||
|
@ -534,14 +535,14 @@ struct Object *spawn_object_at_origin(struct Object *parent, UNUSED s32 unusedAr
|
|||
obj->parentObj = parent;
|
||||
obj->header.gfx.unk18 = parent->header.gfx.unk18;
|
||||
obj->header.gfx.unk19 = parent->header.gfx.unk18;
|
||||
|
||||
geo_obj_init((struct GraphNodeObject *) &obj->header.gfx, gLoadedGraphNodes[model], gVec3fZero,
|
||||
printf("spawn_object_at_origin %d\n", model);
|
||||
geo_obj_init((struct GraphNodeObject *) &obj->header.gfx, get_graph_node(model), gVec3fZero,
|
||||
gVec3sZero);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
struct Object *spawn_object(struct Object *parent, s32 model, const BehaviorScript *behavior) {
|
||||
struct Object *spawn_object(struct Object *parent, u32 model, const BehaviorScript *behavior) {
|
||||
struct Object *obj;
|
||||
|
||||
obj = spawn_object_at_origin(parent, 0, model, behavior);
|
||||
|
@ -550,21 +551,17 @@ struct Object *spawn_object(struct Object *parent, s32 model, const BehaviorScri
|
|||
return obj;
|
||||
}
|
||||
|
||||
struct Object *try_to_spawn_object(s16 offsetY, f32 scale, struct Object *parent, s32 model,
|
||||
struct Object *try_to_spawn_object(s16 offsetY, f32 scale, struct Object *parent, u32 model,
|
||||
const BehaviorScript *behavior) {
|
||||
struct Object *obj;
|
||||
|
||||
if (gFreeObjectList.next != NULL) {
|
||||
obj = spawn_object(parent, model, behavior);
|
||||
obj->oPosY += offsetY;
|
||||
obj_scale(obj, scale);
|
||||
return obj;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
obj = spawn_object(parent, model, behavior);
|
||||
obj->oPosY += offsetY;
|
||||
obj_scale(obj, scale);
|
||||
return obj;
|
||||
}
|
||||
|
||||
struct Object *spawn_object_with_scale(struct Object *parent, s32 model, const BehaviorScript *behavior, f32 scale) {
|
||||
struct Object *spawn_object_with_scale(struct Object *parent, u32 model, const BehaviorScript *behavior, f32 scale) {
|
||||
struct Object *obj;
|
||||
|
||||
obj = spawn_object_at_origin(parent, 0, model, behavior);
|
||||
|
@ -580,7 +577,7 @@ static void obj_build_relative_transform(struct Object *obj) {
|
|||
}
|
||||
|
||||
struct Object *spawn_object_relative(s16 behaviorParam, s16 relativePosX, s16 relativePosY, s16 relativePosZ,
|
||||
struct Object *parent, s32 model, const BehaviorScript *behavior) {
|
||||
struct Object *parent, u32 model, const BehaviorScript *behavior) {
|
||||
struct Object *obj = spawn_object_at_origin(parent, 0, model, behavior);
|
||||
|
||||
obj_copy_pos_and_angle(obj, parent);
|
||||
|
@ -595,7 +592,7 @@ struct Object *spawn_object_relative(s16 behaviorParam, s16 relativePosX, s16 re
|
|||
|
||||
struct Object *spawn_object_relative_with_scale(s16 behaviorParam, s16 relativePosX, s16 relativePosY,
|
||||
s16 relativePosZ, f32 scale, struct Object *parent,
|
||||
s32 model, const BehaviorScript *behavior) {
|
||||
u32 model, const BehaviorScript *behavior) {
|
||||
struct Object *obj;
|
||||
|
||||
obj = spawn_object_relative(behaviorParam, relativePosX, relativePosY, relativePosZ, parent, model,
|
||||
|
@ -1124,8 +1121,9 @@ void cur_obj_get_dropped(void) {
|
|||
cur_obj_move_after_thrown_or_dropped(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void cur_obj_set_model(s32 modelID) {
|
||||
o->header.gfx.sharedChild = gLoadedGraphNodes[modelID];
|
||||
void cur_obj_set_model(u32 modelID) {
|
||||
printf("cur_obj_set_model %d\n", modelID);
|
||||
o->header.gfx.sharedChild = get_graph_node(modelID);
|
||||
}
|
||||
|
||||
void mario_set_flag(s32 flag) {
|
||||
|
@ -2740,12 +2738,9 @@ s32 cur_obj_update_dialog_with_cutscene(s32 actionArg, s32 dialogFlags, s32 cuts
|
|||
return dialogResponse;
|
||||
}
|
||||
|
||||
s32 cur_obj_has_model(u16 modelID) {
|
||||
if (o->header.gfx.sharedChild == gLoadedGraphNodes[modelID]) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
s32 cur_obj_has_model(u32 modelID) {
|
||||
printf("cur_obj_has_model %d\n", modelID);
|
||||
return o->header.gfx.sharedChild == get_graph_node(modelID);
|
||||
}
|
||||
|
||||
void cur_obj_align_gfx_with_floor(void) {
|
||||
|
|
|
@ -55,7 +55,7 @@ struct SpawnParticlesInfo
|
|||
{
|
||||
/*0x00*/ s8 behParam;
|
||||
/*0x01*/ s8 count;
|
||||
/*0x02*/ u8 model;
|
||||
/*0x02*/ u32 model;
|
||||
/*0x03*/ s8 offsetY;
|
||||
/*0x04*/ s8 forwardVelBase;
|
||||
/*0x05*/ s8 forwardVelRange;
|
||||
|
@ -97,18 +97,18 @@ struct Object *spawn_object_abs_with_rot(struct Object *parent, s16 uselessArg,
|
|||
s16 x, s16 y, s16 z, s16 rx, s16 ry, s16 rz);
|
||||
struct Object *spawn_object_rel_with_rot(struct Object *parent, u32 model, const BehaviorScript *behavior,
|
||||
s16 xOff, s16 yOff, s16 zOff, s16 rx, s16 ry, UNUSED s16 rz);
|
||||
struct Object *spawn_obj_with_transform_flags(struct Object *sp20, s32 model, const BehaviorScript *sp28);
|
||||
struct Object *spawn_obj_with_transform_flags(struct Object *sp20, u32 model, const BehaviorScript *sp28);
|
||||
struct Object *spawn_water_droplet(struct Object *parent, struct WaterDropletParams *params);
|
||||
struct Object *spawn_object_at_origin(struct Object *, s32, u32, const BehaviorScript *);
|
||||
struct Object *spawn_object_at_origin(struct Object *parent, UNUSED s32 unusedArg, u32 model, const BehaviorScript *behavior);
|
||||
struct Object *spawn_object(struct Object *parent, s32 model, const BehaviorScript *behavior);
|
||||
struct Object *try_to_spawn_object(s16 offsetY, f32 scale, struct Object *parent, s32 model, const BehaviorScript *behavior);
|
||||
struct Object *spawn_object_with_scale(struct Object *parent, s32 model, const BehaviorScript *behavior, f32 scale);
|
||||
struct Object *spawn_object(struct Object *parent, u32 model, const BehaviorScript *behavior);
|
||||
struct Object *try_to_spawn_object(s16 offsetY, f32 scale, struct Object *parent, u32 model, const BehaviorScript *behavior);
|
||||
struct Object *spawn_object_with_scale(struct Object *parent, u32 model, const BehaviorScript *behavior, f32 scale);
|
||||
struct Object *spawn_object_relative(s16 behaviorParam, s16 relativePosX, s16 relativePosY, s16 relativePosZ,
|
||||
struct Object *parent, s32 model, const BehaviorScript *behavior);
|
||||
struct Object *parent, u32 model, const BehaviorScript *behavior);
|
||||
struct Object *spawn_object_relative_with_scale(s16 behaviorParam, s16 relativePosX, s16 relativePosY,
|
||||
s16 relativePosZ, f32 scale, struct Object *parent,
|
||||
s32 model, const BehaviorScript *behavior);
|
||||
u32 model, const BehaviorScript *behavior);
|
||||
void cur_obj_move_using_vel(void);
|
||||
void obj_copy_graph_y_offset(struct Object *dst, struct Object *src);
|
||||
void obj_copy_pos_and_angle(struct Object *dst, struct Object *src);
|
||||
|
@ -157,7 +157,7 @@ void cur_obj_set_y_vel_and_animation(f32 sp18, s32 sp1C);
|
|||
void cur_obj_unrender_and_reset_state(s32 sp18, s32 sp1C);
|
||||
void cur_obj_get_thrown_or_placed(f32 forwardVel, f32 velY, s32 thrownAction);
|
||||
void cur_obj_get_dropped(void);
|
||||
void cur_obj_set_model(s32 modelID);
|
||||
void cur_obj_set_model(u32 modelID);
|
||||
void mario_set_flag(s32 flag);
|
||||
s32 cur_obj_clear_interact_status_flag(s32 flag);
|
||||
void obj_mark_for_deletion(struct Object *obj);
|
||||
|
@ -276,7 +276,7 @@ s32 cur_obj_can_mario_activate_textbox(f32 radius, f32 height, UNUSED s32 unused
|
|||
s32 cur_obj_can_mario_activate_textbox_2(f32 radius, f32 height);
|
||||
s32 cur_obj_update_dialog(s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused);
|
||||
s32 cur_obj_update_dialog_with_cutscene(s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID);
|
||||
s32 cur_obj_has_model(u16 modelID);
|
||||
s32 cur_obj_has_model(u32 modelID);
|
||||
void cur_obj_align_gfx_with_floor(void);
|
||||
s32 mario_is_within_rectangle(s16 minX, s16 maxX, s16 minZ, s16 maxZ);
|
||||
void cur_obj_shake_screen(s32 shake);
|
||||
|
|
|
@ -63,11 +63,6 @@ s16 gDebugInfoOverwrite[16][8];
|
|||
*/
|
||||
u32 gTimeStopState;
|
||||
|
||||
/**
|
||||
* The pool that objects are allocated from.
|
||||
*/
|
||||
struct Object gObjectPool[OBJECT_POOL_CAPACITY];
|
||||
|
||||
/**
|
||||
* A special object whose purpose is to act as a parent for macro objects.
|
||||
*/
|
||||
|
@ -188,7 +183,7 @@ s8 sObjectListUpdateOrder[] = { OBJ_LIST_SPAWNER,
|
|||
struct ParticleProperties {
|
||||
u32 particleFlag;
|
||||
u32 activeParticleFlag;
|
||||
u8 model;
|
||||
u32 model;
|
||||
const BehaviorScript *behavior;
|
||||
};
|
||||
|
||||
|
@ -540,17 +535,11 @@ void clear_objects(void) {
|
|||
|
||||
debug_unknown_level_select_check();
|
||||
|
||||
init_free_object_list();
|
||||
clear_object_lists(gObjectListArray);
|
||||
|
||||
stub_behavior_script_2();
|
||||
stub_obj_list_processor_1();
|
||||
|
||||
for (i = 0; i < OBJECT_POOL_CAPACITY; i++) {
|
||||
gObjectPool[i].activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
geo_reset_object_node(&gObjectPool[i].header.gfx);
|
||||
}
|
||||
|
||||
gObjectMemoryPool = mem_pool_init(0x800, MEMORY_POOL_LEFT);
|
||||
gObjectLists = gObjectListArray;
|
||||
|
||||
|
|
|
@ -1048,8 +1048,7 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
|
|||
Mtx *initialMatrix;
|
||||
Vp *viewport = alloc_display_list(sizeof(*viewport));
|
||||
|
||||
gDisplayListHeap = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool),
|
||||
MEMORY_POOL_LEFT);
|
||||
gDisplayListHeap = alloc_only_pool_init();
|
||||
initialMatrix = alloc_display_list(sizeof(*initialMatrix));
|
||||
gMatStackIndex = 0;
|
||||
gCurAnimType = 0;
|
||||
|
@ -1077,10 +1076,6 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
|
|||
geo_process_node_and_siblings(node->node.children);
|
||||
}
|
||||
gCurGraphNodeRoot = NULL;
|
||||
if (gShowDebugText) {
|
||||
print_text_fmt_int(180, 36, "MEM %d",
|
||||
gDisplayListHeap->totalSpace - gDisplayListHeap->usedSpace);
|
||||
}
|
||||
main_pool_free(gDisplayListHeap);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,7 +230,6 @@ void *create_skybox_ortho_matrix(s8 player) {
|
|||
f32 bottom = sSkyBoxInfo[player].scaledY - SCREEN_HEIGHT;
|
||||
f32 top = sSkyBoxInfo[player].scaledY;
|
||||
Mtx *mtx = alloc_display_list(sizeof(*mtx));
|
||||
|
||||
f32 half_width = (4.0f / 3.0f) / GFX_DIMENSIONS_ASPECT_RATIO * SCREEN_WIDTH / 2;
|
||||
f32 center = (sSkyBoxInfo[player].scaledX + SCREEN_WIDTH / 2);
|
||||
if (half_width < SCREEN_WIDTH / 2) {
|
||||
|
@ -241,7 +240,6 @@ void *create_skybox_ortho_matrix(s8 player) {
|
|||
|
||||
if (mtx != NULL) {
|
||||
guOrtho(mtx, left, right, bottom, top, 0.0f, 3.0f, 1.0f);
|
||||
} else {
|
||||
}
|
||||
|
||||
return mtx;
|
||||
|
@ -251,7 +249,7 @@ void *create_skybox_ortho_matrix(s8 player) {
|
|||
* Creates the skybox's display list, then draws the 3x3 grid of tiles.
|
||||
*/
|
||||
Gfx *init_skybox_display_list(s8 player, s8 background, s8 colorIndex) {
|
||||
s32 dlCommandCount = 7 + (3 * 3) * 7; // 5 for the start and end, plus 9 skybox tiles
|
||||
s32 dlCommandCount = 124;
|
||||
void *skybox = alloc_display_list(dlCommandCount * sizeof(Gfx));
|
||||
Gfx *dlist = skybox;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <stdlib.h>
|
||||
#include <PR/ultratypes.h>
|
||||
|
||||
#include "audio/external.h"
|
||||
#include "engine/geo_layout.h"
|
||||
#include "engine/graph_node.h"
|
||||
|
@ -89,10 +89,18 @@ struct Object *try_allocate_object(struct ObjectNode *destList, struct ObjectNod
|
|||
destList->prev->next = nextObj;
|
||||
destList->prev = nextObj;
|
||||
} else {
|
||||
return NULL;
|
||||
nextObj = (struct ObjectNode *) malloc(sizeof(struct Object));
|
||||
if (nextObj == NULL) {
|
||||
abort();
|
||||
}
|
||||
// Insert at end of destination list
|
||||
nextObj->prev = destList->prev;
|
||||
nextObj->next = destList;
|
||||
destList->prev->next = nextObj;
|
||||
destList->prev = nextObj;
|
||||
}
|
||||
|
||||
geo_remove_child(&nextObj->gfx.node);
|
||||
init_graph_node_object(NULL, &nextObj->gfx, 0, gVec3fZero, gVec3sZero, gVec3fOne);
|
||||
geo_add_child(&gObjParentGraphNode, &nextObj->gfx.node);
|
||||
|
||||
return (struct Object *) nextObj;
|
||||
|
@ -126,27 +134,6 @@ static void deallocate_object(struct ObjectNode *freeList, struct ObjectNode *ob
|
|||
freeList->next = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add every object in the pool to the free object list.
|
||||
*/
|
||||
void init_free_object_list(void) {
|
||||
s32 i;
|
||||
s32 poolLength = OBJECT_POOL_CAPACITY;
|
||||
|
||||
// Add the first object in the pool to the free list
|
||||
struct Object *obj = &gObjectPool[0];
|
||||
gFreeObjectList.next = (struct ObjectNode *) obj;
|
||||
|
||||
// Link each object in the pool to the following object
|
||||
for (i = 0; i < poolLength - 1; i++) {
|
||||
obj->header.next = &(obj + 1)->header;
|
||||
obj++;
|
||||
}
|
||||
|
||||
// End the list
|
||||
obj->header.next = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear each object list, without adding the objects back to the free list.
|
||||
*/
|
||||
|
@ -154,6 +141,15 @@ void clear_object_lists(struct ObjectNode *objLists) {
|
|||
s32 i;
|
||||
|
||||
for (i = 0; i < NUM_OBJ_LISTS; i++) {
|
||||
struct ObjectNode *list = objLists + i;
|
||||
struct ObjectNode *node = list->next;
|
||||
|
||||
while (node != NULL && node != list) {
|
||||
struct Object *obj = (struct Object *) node;
|
||||
node = node->next;
|
||||
|
||||
unload_object(obj);
|
||||
}
|
||||
objLists[i].next = &objLists[i];
|
||||
objLists[i].prev = &objLists[i];
|
||||
}
|
||||
|
@ -190,7 +186,6 @@ void unload_object(struct Object *obj) {
|
|||
obj->header.gfx.throwMatrix = NULL;
|
||||
stop_sounds_from_source(obj->header.gfx.cameraToObject);
|
||||
geo_remove_child(&obj->header.gfx.node);
|
||||
geo_add_child(&gObjParentGraphNode, &obj->header.gfx.node);
|
||||
|
||||
obj->header.gfx.node.flags &= ~GRAPH_RENDER_BILLBOARD;
|
||||
obj->header.gfx.node.flags &= ~GRAPH_RENDER_CYLBOARD;
|
||||
|
@ -208,31 +203,6 @@ struct Object *allocate_object(struct ObjectNode *objList) {
|
|||
s32 i;
|
||||
struct Object *obj = try_allocate_object(objList, &gFreeObjectList);
|
||||
|
||||
// The object list is full if the newly created pointer is NULL.
|
||||
// If this happens, we first attempt to unload unimportant objects
|
||||
// in order to finish allocating the object.
|
||||
if (obj == NULL) {
|
||||
// Look for an unimportant object to kick out.
|
||||
struct Object *unimportantObj = find_unimportant_object();
|
||||
|
||||
// If no unimportant object exists, then the object pool is exhausted.
|
||||
if (unimportantObj == NULL) {
|
||||
// We've met with a terrible fate.
|
||||
while (TRUE) {
|
||||
}
|
||||
} else {
|
||||
// If an unimportant object does exist, unload it and take its slot.
|
||||
unload_object(unimportantObj);
|
||||
obj = try_allocate_object(objList, &gFreeObjectList);
|
||||
if (gCurrentObject == obj) {
|
||||
//! Uh oh, the unimportant object was in the middle of
|
||||
// updating! This could cause some interesting logic errors,
|
||||
// but I don't know of any unimportant objects that spawn
|
||||
// other objects.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize object fields
|
||||
|
||||
obj->activeFlags = ACTIVE_FLAG_ACTIVE | ACTIVE_FLAG_UNK8;
|
||||
|
|
|
@ -1,316 +1,4 @@
|
|||
#include <PR/ultratypes.h>
|
||||
|
||||
#include "debug_utils.h"
|
||||
#include "gd_memory.h"
|
||||
#include "renderer.h"
|
||||
|
||||
/**
|
||||
* @file gd_memory.c
|
||||
*
|
||||
* This file contains the functions need to manage allocation in
|
||||
* goddard's heap. However, the actual, useable allocation functions
|
||||
* are `gd_malloc()`, `gd_malloc_perm()`, and `gd_malloc_temp()`, as
|
||||
* well as `gd_free()`. This file is for managing the underlying memory
|
||||
* block lists.
|
||||
*/
|
||||
|
||||
/* bss */
|
||||
static struct GMemBlock *sFreeBlockListHead;
|
||||
static struct GMemBlock *sUsedBlockListHead;
|
||||
static struct GMemBlock *sEmptyBlockListHead;
|
||||
|
||||
/* Forward Declarations */
|
||||
void empty_mem_block(struct GMemBlock *);
|
||||
struct GMemBlock *into_free_memblock(struct GMemBlock *);
|
||||
struct GMemBlock *make_mem_block(u32, u8);
|
||||
u32 print_list_stats(struct GMemBlock *, s32, s32);
|
||||
|
||||
/**
|
||||
* Empty a `GMemBlock` into a default state. This empty block
|
||||
* doesn't point to any data, nor does it have any size. The
|
||||
* block is removed from whatever list is was in, and is added
|
||||
* to the empty block list.
|
||||
*/
|
||||
void empty_mem_block(struct GMemBlock *block) {
|
||||
if (block->next != NULL) {
|
||||
block->next->prev = block->prev;
|
||||
}
|
||||
|
||||
if (block->prev != NULL) {
|
||||
block->prev->next = block->next;
|
||||
}
|
||||
|
||||
switch (block->blockType) {
|
||||
case G_MEM_BLOCK_FREE:
|
||||
if (block->prev == NULL) {
|
||||
sFreeBlockListHead = block->next;
|
||||
}
|
||||
break;
|
||||
case G_MEM_BLOCK_USED:
|
||||
if (block->prev == NULL) {
|
||||
sUsedBlockListHead = block->next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
block->next = sEmptyBlockListHead;
|
||||
if (block->next != NULL) {
|
||||
sEmptyBlockListHead->prev = block;
|
||||
}
|
||||
|
||||
sEmptyBlockListHead = block;
|
||||
block->prev = NULL;
|
||||
block->ptr = NULL;
|
||||
block->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a `GMemBlock` into a free block that points to memory available
|
||||
* for allocation.
|
||||
*
|
||||
* @returns pointer to the free `GMemBlock` */
|
||||
struct GMemBlock *into_free_memblock(struct GMemBlock *block) {
|
||||
struct GMemBlock *freeBlock;
|
||||
void *ptr;
|
||||
u8 permanence;
|
||||
u32 space;
|
||||
|
||||
ptr = block->ptr;
|
||||
space = block->size;
|
||||
permanence = block->permFlag;
|
||||
|
||||
empty_mem_block(block);
|
||||
freeBlock = make_mem_block(G_MEM_BLOCK_FREE, permanence);
|
||||
freeBlock->ptr = ptr;
|
||||
freeBlock->size = space;
|
||||
freeBlock->permFlag = permanence;
|
||||
|
||||
return freeBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new `GMemBlock` structure of the given type and permanence.
|
||||
* It does not assign any heap space to the new block.
|
||||
*
|
||||
* @param blockType either `G_MEM_BLOCK_FREE` or `G_MEM_BLOCK_USED`
|
||||
* @param permFlag some sort of permanence value, where setting one the upper
|
||||
* four bits imply a permanent block, while setting one the lower
|
||||
* four bits imply a temporary block
|
||||
* @returns a pointer to the new `GMemBlock`
|
||||
*/
|
||||
struct GMemBlock *make_mem_block(u32 blockType, u8 permFlag) {
|
||||
struct GMemBlock *newMemBlock;
|
||||
|
||||
if (sEmptyBlockListHead == NULL) {
|
||||
sEmptyBlockListHead = (struct GMemBlock *) gd_allocblock(sizeof(struct GMemBlock));
|
||||
|
||||
if (sEmptyBlockListHead == NULL) {
|
||||
fatal_printf("MakeMemBlock() unable to allocate");
|
||||
}
|
||||
|
||||
sEmptyBlockListHead->next = NULL;
|
||||
sEmptyBlockListHead->prev = NULL;
|
||||
}
|
||||
|
||||
newMemBlock = sEmptyBlockListHead;
|
||||
if ((sEmptyBlockListHead = newMemBlock->next) != NULL) {
|
||||
newMemBlock->next->prev = NULL;
|
||||
}
|
||||
|
||||
switch (blockType) {
|
||||
case G_MEM_BLOCK_FREE:
|
||||
newMemBlock->next = sFreeBlockListHead;
|
||||
if (newMemBlock->next != NULL) {
|
||||
sFreeBlockListHead->prev = newMemBlock;
|
||||
}
|
||||
sFreeBlockListHead = newMemBlock;
|
||||
break;
|
||||
case G_MEM_BLOCK_USED:
|
||||
newMemBlock->next = sUsedBlockListHead;
|
||||
if (newMemBlock->next != NULL) {
|
||||
sUsedBlockListHead->prev = newMemBlock;
|
||||
}
|
||||
sUsedBlockListHead = newMemBlock;
|
||||
break;
|
||||
default:
|
||||
fatal_printf("unkown memblock type");
|
||||
}
|
||||
newMemBlock->prev = NULL;
|
||||
newMemBlock->blockType = (u8) blockType;
|
||||
newMemBlock->permFlag = permFlag;
|
||||
|
||||
return newMemBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free memory allocated on the goddard heap.
|
||||
*
|
||||
* @param ptr pointer to heap allocated memory
|
||||
* @returns size of memory freed
|
||||
* @retval 0 `ptr` did not point to a valid memory block
|
||||
*/
|
||||
u32 gd_free_mem(void *ptr) {
|
||||
register struct GMemBlock *curBlock;
|
||||
u32 bytesFreed;
|
||||
register u8 *targetBlock = ptr;
|
||||
|
||||
for (curBlock = sUsedBlockListHead; curBlock != NULL; curBlock = curBlock->next) {
|
||||
if (targetBlock == curBlock->ptr) {
|
||||
bytesFreed = curBlock->size;
|
||||
into_free_memblock(curBlock);
|
||||
return bytesFreed;
|
||||
}
|
||||
}
|
||||
|
||||
fatal_printf("Free() Not a valid memory block");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a pointer to goddard heap memory of at least `size` and
|
||||
* of the same `permanence`.
|
||||
*
|
||||
* @return pointer to heap
|
||||
* @retval NULL could not fulfill the request
|
||||
*/
|
||||
void *gd_request_mem(u32 size, u8 permanence) {
|
||||
struct GMemBlock *foundBlock = NULL;
|
||||
struct GMemBlock *curBlock;
|
||||
struct GMemBlock *newBlock;
|
||||
|
||||
newBlock = make_mem_block(G_MEM_BLOCK_USED, permanence);
|
||||
curBlock = sFreeBlockListHead;
|
||||
|
||||
while (curBlock != NULL) {
|
||||
if (curBlock->permFlag & permanence) {
|
||||
if (curBlock->size == size) {
|
||||
foundBlock = curBlock;
|
||||
break;
|
||||
} else {
|
||||
if (curBlock->size > size) {
|
||||
if (foundBlock != NULL) { /* find closest sized block */
|
||||
if (curBlock->size < foundBlock->size) {
|
||||
foundBlock = curBlock;
|
||||
}
|
||||
} else {
|
||||
foundBlock = curBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
curBlock = curBlock->next;
|
||||
}
|
||||
|
||||
if (foundBlock == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (foundBlock->size > size) { /* split free block */
|
||||
newBlock->ptr = foundBlock->ptr;
|
||||
newBlock->size = size;
|
||||
|
||||
foundBlock->size -= size;
|
||||
foundBlock->ptr += size;
|
||||
} else if (foundBlock->size == size) { /* recycle whole free block */
|
||||
newBlock->ptr = foundBlock->ptr;
|
||||
newBlock->size = size;
|
||||
empty_mem_block(foundBlock);
|
||||
}
|
||||
|
||||
return newBlock->ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add memory of `size` at `addr` to the goddard heap for later allocation.
|
||||
*
|
||||
* @returns `GMemBlock` that contains info about the new heap memory
|
||||
*/
|
||||
struct GMemBlock *gd_add_mem_to_heap(u32 size, void *addr, u8 permanence) {
|
||||
struct GMemBlock *newBlock;
|
||||
/* eight-byte align the new block's data stats */
|
||||
size = (size - 8) & ~7;
|
||||
addr = (void *)(((uintptr_t) addr + 8) & ~7);
|
||||
|
||||
newBlock = make_mem_block(G_MEM_BLOCK_FREE, permanence);
|
||||
newBlock->ptr = addr;
|
||||
newBlock->size = size;
|
||||
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* NULL the various `GMemBlock` list heads
|
||||
*/
|
||||
void init_mem_block_lists(void) {
|
||||
sFreeBlockListHead = NULL;
|
||||
sUsedBlockListHead = NULL;
|
||||
sEmptyBlockListHead = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print information (size, entries) about the `GMemBlock` list. It can print
|
||||
* information for individual blocks as well as summary info for the entry list.
|
||||
*
|
||||
* @param block `GMemBlock` to start reading the list
|
||||
* @param printBlockInfo If `TRUE`, print information about every block
|
||||
* in the list
|
||||
* @param permanence Limit info printed to blocks with this permanence
|
||||
* @returns number of entries
|
||||
*/
|
||||
u32 print_list_stats(struct GMemBlock *block, s32 printBlockInfo, s32 permanence) {
|
||||
u32 entries = 0;
|
||||
u32 totalSize = 0;
|
||||
|
||||
while (block != NULL) {
|
||||
if (block->permFlag & permanence) {
|
||||
entries++;
|
||||
if (printBlockInfo) {
|
||||
gd_printf(" %6.2fk (%d bytes)\n",
|
||||
(f32) block->size / 1024.0, //? 1024.0f
|
||||
block->size);
|
||||
}
|
||||
totalSize += block->size;
|
||||
}
|
||||
block = block->next;
|
||||
}
|
||||
|
||||
gd_printf("Total %6.2fk (%d bytes) in %d entries\n",
|
||||
(f32) totalSize / 1024.0, //? 1024.0f
|
||||
totalSize, entries);
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print summary information about all used, free, and empty
|
||||
* `GMemBlock`s.
|
||||
*/
|
||||
void mem_stats(void) {
|
||||
struct GMemBlock *list;
|
||||
|
||||
gd_printf("Perm Used blocks:\n");
|
||||
list = sUsedBlockListHead;
|
||||
print_list_stats(list, FALSE, PERM_G_MEM_BLOCK);
|
||||
gd_printf("\n");
|
||||
|
||||
gd_printf("Perm Free blocks:\n");
|
||||
list = sFreeBlockListHead;
|
||||
print_list_stats(list, FALSE, PERM_G_MEM_BLOCK);
|
||||
gd_printf("\n");
|
||||
|
||||
gd_printf("Temp Used blocks:\n");
|
||||
list = sUsedBlockListHead;
|
||||
print_list_stats(list, FALSE, TEMP_G_MEM_BLOCK);
|
||||
gd_printf("\n");
|
||||
|
||||
gd_printf("Temp Free blocks:\n");
|
||||
list = sFreeBlockListHead;
|
||||
print_list_stats(list, FALSE, TEMP_G_MEM_BLOCK);
|
||||
gd_printf("\n");
|
||||
|
||||
gd_printf("Empty blocks:\n");
|
||||
list = sEmptyBlockListHead;
|
||||
print_list_stats(list, FALSE, PERM_G_MEM_BLOCK | TEMP_G_MEM_BLOCK);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -111,8 +111,6 @@ static struct ObjGadget *sTimerGadgets[GD_NUM_TIMERS]; // @ 801BAEA8
|
|||
static u32 D_801BAF28; // RAM addr offset?
|
||||
static s16 D_801BAF30[13][8]; // [[s16; 8]; 13]? vert indices?
|
||||
static u32 unref_801bb000[3];
|
||||
static u8 *sMemBlockPoolBase; // @ 801BB00C
|
||||
static u32 sAllocMemory; // @ 801BB010; malloc-ed bytes
|
||||
static u32 unref_801bb014;
|
||||
static s32 D_801BB018;
|
||||
static s32 D_801BB01C;
|
||||
|
@ -179,6 +177,9 @@ static OSIoMesg D_801BE980;
|
|||
static struct ObjView *D_801BE994; // store if View flag 0x40 set
|
||||
#endif
|
||||
|
||||
static void *(*sAllocFn)(u32 size);
|
||||
static void (*sFreeFn)(void *ptr);
|
||||
|
||||
// data
|
||||
static u32 unref_801a8670 = 0;
|
||||
static s32 D_801A8674 = 0;
|
||||
|
@ -190,8 +191,6 @@ static f32 sDynamicsTime = 0.0f; // @ 801A8688
|
|||
static f32 sDLGenTime = 0.0f; // @ 801A868C
|
||||
static f32 sRCPTime = 0.0f; // @ 801A8690
|
||||
static f32 sTimeScaleFactor = 1.0f; // @ D_801A8694
|
||||
static u32 sMemBlockPoolSize = 1; // @ 801A8698
|
||||
static s32 sMemBlockPoolUsed = 0; // @ 801A869C
|
||||
static s32 D_801A86A0 = 0;
|
||||
static struct GdTimer *D_801A86A4 = NULL; // timer for dlgen, dynamics, or rcp
|
||||
static struct GdTimer *D_801A86A8 = NULL; // timer for dlgen, dynamics, or rcp
|
||||
|
@ -461,11 +460,11 @@ static Gfx gd_dl_sparkle[] = {
|
|||
gsSPClearGeometryMode(G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR),
|
||||
gsDPSetRenderMode(G_RM_AA_ZB_TEX_EDGE, G_RM_NOOP2),
|
||||
gsSPTexture(0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON),
|
||||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD,
|
||||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD,
|
||||
G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD),
|
||||
gsDPLoadSync(),
|
||||
gsDPLoadBlock(G_TX_LOADTILE, 0, 0, 32 * 32 - 1, CALC_DXT(32, G_IM_SIZ_16b_BYTES)),
|
||||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 0, G_TX_RENDERTILE, 0, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD,
|
||||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 0, G_TX_RENDERTILE, 0, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD,
|
||||
G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOLOD),
|
||||
gsDPSetTileSize(0, 0, 0, (32 - 1) << G_TEXTURE_IMAGE_FRAC, (32 - 1) << G_TEXTURE_IMAGE_FRAC),
|
||||
gsSPVertex(gd_vertex_sparkle, 4, 0),
|
||||
|
@ -642,7 +641,7 @@ static Gfx gd_dl_mario_face_shine[] = {
|
|||
gsDPSetTexturePersp(G_TP_PERSP),
|
||||
gsDPSetTextureFilter(G_TF_BILERP),
|
||||
gsDPSetCombineMode(G_CC_HILITERGBA, G_CC_HILITERGBA),
|
||||
gsDPLoadTextureBlock(gd_texture_mario_face_shine, G_IM_FMT_IA, G_IM_SIZ_8b, 32, 32, 0,
|
||||
gsDPLoadTextureBlock(gd_texture_mario_face_shine, G_IM_FMT_IA, G_IM_SIZ_8b, 32, 32, 0,
|
||||
G_TX_WRAP | G_TX_NOMIRROR, G_TX_WRAP | G_TX_NOMIRROR, 5, 5, G_TX_NOLOD, G_TX_NOLOD),
|
||||
gsDPPipeSync(),
|
||||
gsSPEndDisplayList(),
|
||||
|
@ -741,7 +740,7 @@ void reset_cur_dl_indices(void);
|
|||
// TODO: make a gddl_num_t?
|
||||
|
||||
u32 get_alloc_mem_amt(void) {
|
||||
return sAllocMemory;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 gd_get_ostime(void) {
|
||||
|
@ -937,45 +936,12 @@ void gd_exit(UNUSED s32 code) {
|
|||
|
||||
/* 24A1D4 -> 24A220; orig name: func_8019BA04 */
|
||||
void gd_free(void *ptr) {
|
||||
sAllocMemory -= gd_free_mem(ptr);
|
||||
}
|
||||
|
||||
/* 24A220 -> 24A318 */
|
||||
void *gd_allocblock(u32 size) {
|
||||
void *block; // 1c
|
||||
|
||||
size = ALIGN(size, 8);
|
||||
if ((sMemBlockPoolUsed + size) > sMemBlockPoolSize) {
|
||||
gd_printf("gd_allocblock(): Failed request: %dk (%d bytes)\n", size / 1024, size);
|
||||
gd_printf("gd_allocblock(): Heap usage: %dk (%d bytes) \n", sMemBlockPoolUsed / 1024,
|
||||
sMemBlockPoolUsed);
|
||||
print_all_memtrackers();
|
||||
mem_stats();
|
||||
fatal_printf("exit");
|
||||
}
|
||||
|
||||
block = sMemBlockPoolBase + sMemBlockPoolUsed;
|
||||
sMemBlockPoolUsed += size;
|
||||
return block;
|
||||
sFreeFn(ptr);
|
||||
}
|
||||
|
||||
/* 24A318 -> 24A3E8 */
|
||||
void *gd_malloc(u32 size, u8 perm) {
|
||||
void *ptr; // 1c
|
||||
size = ALIGN(size, 8);
|
||||
ptr = gd_request_mem(size, perm);
|
||||
|
||||
if (ptr == NULL) {
|
||||
gd_printf("gd_malloc(): Failed request: %dk (%d bytes)\n", size / 1024, size);
|
||||
gd_printf("gd_malloc(): Heap usage: %dk (%d bytes) \n", sAllocMemory / 1024, sAllocMemory);
|
||||
print_all_memtrackers();
|
||||
mem_stats();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sAllocMemory += size;
|
||||
|
||||
return ptr;
|
||||
return sAllocFn(size);
|
||||
}
|
||||
|
||||
/* 24A3E8 -> 24A420; orig name: func_8019BC18 */
|
||||
|
@ -1100,26 +1066,10 @@ void Unknown8019C288(s32 stickX, s32 stickY) {
|
|||
ctrl->stickYf = (f32)(stickY / 2);
|
||||
}
|
||||
|
||||
/* 24AAA8 -> 24AAE0; orig name: func_8019C2D8 */
|
||||
void gd_add_to_heap(void *addr, u32 size) {
|
||||
// TODO: is this `1` for permanence special?
|
||||
gd_add_mem_to_heap(size, addr, 1);
|
||||
}
|
||||
|
||||
/* 24AAE0 -> 24AB7C */
|
||||
void gdm_init(void *blockpool, u32 size) {
|
||||
UNUSED u32 pad;
|
||||
|
||||
void gdm_init(void *(*allocFn)(u32 size), void (*freeFn)(void *addr)) {
|
||||
add_to_stacktrace("gdm_init");
|
||||
// Align downwards?
|
||||
size = (size - 8) & ~7;
|
||||
// Align to next double word boundry?
|
||||
blockpool = (void *) (((uintptr_t) blockpool + 8) & ~7);
|
||||
sMemBlockPoolBase = blockpool;
|
||||
sMemBlockPoolSize = size;
|
||||
sMemBlockPoolUsed = 0;
|
||||
sAllocMemory = 0;
|
||||
init_mem_block_lists();
|
||||
sAllocFn = allocFn;
|
||||
sFreeFn = freeFn;
|
||||
gd_reset_sfx();
|
||||
imout();
|
||||
}
|
||||
|
@ -2301,7 +2251,7 @@ void parse_p1_controller(void) {
|
|||
u8 *prevGdCtrlBytes; // 28
|
||||
f32 aspect = GFX_DIMENSIONS_ASPECT_RATIO;
|
||||
aspect *= 0.75;
|
||||
|
||||
|
||||
gdctrl = &gGdCtrl;
|
||||
gdCtrlBytes = (u8 *) gdctrl;
|
||||
prevGdCtrlBytes = (u8 *) gdctrl->prevFrame;
|
||||
|
@ -3076,9 +3026,6 @@ void gd_init(void) {
|
|||
s8 *data; // 2c
|
||||
|
||||
add_to_stacktrace("gd_init");
|
||||
i = (u32)(sMemBlockPoolSize - DOUBLE_SIZE_ON_64_BIT(0x3E800));
|
||||
data = gd_allocblock(i);
|
||||
gd_add_mem_to_heap(i, data, 0x10);
|
||||
D_801BB184 = (u16) 0xff;
|
||||
D_801A867C = 0;
|
||||
D_801A8680 = 0;
|
||||
|
@ -3400,7 +3347,7 @@ void gd_put_sprite(u16 *sprite, s32 x, s32 y, s32 wx, s32 wy) {
|
|||
// Must be game screen aspect ratio, not GFX window aspect ratio
|
||||
f32 aspect = ((float) SCREEN_WIDTH) / ((float) SCREEN_HEIGHT ) * 0.75;
|
||||
x *= aspect;
|
||||
|
||||
|
||||
gSPDisplayList(next_gfx(), osVirtualToPhysical(gd_dl_sprite_start_tex_block));
|
||||
for (r = 0; r < wy; r += 32) {
|
||||
for (c = 0; c < wx; c += 32) {
|
||||
|
|
|
@ -42,8 +42,7 @@ void *gd_malloc(u32 size, u8 perm);
|
|||
void *gd_malloc_perm(u32 size);
|
||||
void *gd_malloc_temp(u32 size);
|
||||
void func_8019BD0C(s32 dlNum, s32 gfxIdx);
|
||||
void gd_add_to_heap(void *addr, u32 size);
|
||||
void gdm_init(void *blockpool, u32 size);
|
||||
void gdm_init(void *(*allocFn)(u32 size), void (*freeFn)(void *ptr));
|
||||
void gdm_setup(void);
|
||||
void gdm_maketestdl(s32 id);
|
||||
void gd_vblank(void);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <string.h>
|
||||
#include "moon/utils/moon-gfx.h"
|
||||
#include "gfx_dimensions.h"
|
||||
#include "moon/mod-engine/models/mod-model.h"
|
||||
|
||||
/**
|
||||
* @file file_select.c
|
||||
|
@ -601,10 +602,9 @@ void copy_action_file_button(struct Object *copyButton, s32 copyFileButtonID) {
|
|||
sFadeOutText = TRUE;
|
||||
sMainMenuTimer = 0;
|
||||
save_file_copy(sSelectedFileIndex, copyFileButtonID - MENU_BUTTON_COPY_MIN);
|
||||
sMainMenuButtons[copyFileButtonID]->header.gfx.sharedChild =
|
||||
gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE];
|
||||
sMainMenuButtons[copyFileButtonID - MENU_BUTTON_COPY_MIN]->header.gfx.sharedChild =
|
||||
gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE];
|
||||
|
||||
sMainMenuButtons[copyFileButtonID]->header.gfx.sharedChild = get_graph_node(MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE);
|
||||
sMainMenuButtons[copyFileButtonID - MENU_BUTTON_COPY_MIN]->header.gfx.sharedChild = get_graph_node(MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE);
|
||||
} else {
|
||||
// If clicked in a existing save file, play buzz sound
|
||||
if (MENU_BUTTON_COPY_FILE_A + sSelectedFileIndex == copyFileButtonID) {
|
||||
|
@ -1830,10 +1830,10 @@ void print_erase_menu_prompt(s16 x, s16 y) {
|
|||
sFadeOutText = TRUE;
|
||||
sMainMenuTimer = 0;
|
||||
save_file_erase(sSelectedFileIndex);
|
||||
sMainMenuButtons[MENU_BUTTON_ERASE_MIN + sSelectedFileIndex]->header.gfx.sharedChild =
|
||||
gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE];
|
||||
sMainMenuButtons[sSelectedFileIndex]->header.gfx.sharedChild =
|
||||
gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE];
|
||||
|
||||
sMainMenuButtons[MENU_BUTTON_ERASE_MIN + sSelectedFileIndex]->header.gfx.sharedChild = get_graph_node(MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE);
|
||||
sMainMenuButtons[sSelectedFileIndex]->header.gfx.sharedChild = get_graph_node(MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE);
|
||||
|
||||
sEraseYesNoHoverState = MENU_ERASE_HOVER_NONE;
|
||||
// ..and is hovering "NO", return back to main phase
|
||||
} else if (sEraseYesNoHoverState == MENU_ERASE_HOVER_NO) {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
#include "mod-model.h"
|
||||
|
||||
#include "moon/mod-engine/interfaces/file-entry.h"
|
||||
#include "moon/mod-engine/interfaces/bit-module.h"
|
||||
#include "types.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
map<int, GraphNode*> loadedGraphNodes;
|
||||
|
||||
extern "C"{
|
||||
void bind_graph_node(int modelId, struct GraphNode *graphNode){
|
||||
loadedGraphNodes[modelId] = graphNode;
|
||||
// cout << "Binding model with id " << modelId << endl;
|
||||
}
|
||||
struct GraphNode * get_graph_node(int modelId){
|
||||
if(loadedGraphNodes.find(modelId) == loadedGraphNodes.end()) return NULL;
|
||||
// cout << "Loading model with id " << modelId << endl;
|
||||
return loadedGraphNodes[modelId];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef ModEngineModelModule
|
||||
#define ModEngineModelModule
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
|
||||
namespace Moon {
|
||||
|
||||
}
|
||||
|
||||
namespace MoonInternal {
|
||||
void setupModuleEngine( std::string state );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void bind_graph_node(int modelId, struct GraphNode *graphNode);
|
||||
struct GraphNode * get_graph_node(int modelId);
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -188,8 +188,8 @@ static void on_anim_frame(double time) {
|
|||
|
||||
void main_func(char *argv[]) {
|
||||
|
||||
static u64 pool[0x165000/8 / 4 * sizeof(void *)];
|
||||
main_pool_init(pool, pool + sizeof(pool) / sizeof(pool[0]));
|
||||
main_pool_init();
|
||||
gGfxAllocOnlyPool = alloc_only_pool_init();
|
||||
gEffectsMemoryPool = mem_pool_init(0x4000, MEMORY_POOL_LEFT);
|
||||
|
||||
const char *gamedir = gCLIOpts.GameDir[0] ? gCLIOpts.GameDir : FS_BASEDIR;
|
||||
|
|
Loading…
Reference in New Issue