1
Fork 0

Remove fixed-sized pools for most things except audio

This commit is contained in:
n64 2020-09-26 17:27:48 +02:00
parent 6117ab9e4c
commit 45dbaa7468
24 changed files with 7079 additions and 55 deletions

View file

@ -454,7 +454,7 @@ ifeq ($(TARGET_WEB),1)
PLATFORM_LDFLAGS := -lm -no-pie -s TOTAL_MEMORY=20MB -g4 --source-map-base http://localhost:8080/ -s "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain']"
endif
PLATFORM_CFLAGS += -DNO_SEGMENTED_MEMORY
PLATFORM_CFLAGS += -DNO_SEGMENTED_MEMORY -DUSE_SYSTEM_MALLOC
# Compiler and linker flags for graphics backend
ifeq ($(ENABLE_OPENGL),1)

View file

@ -4424,7 +4424,8 @@ typedef union {
_g0->words.w0 = _SHIFTL(G_FILLRECT, 24, 8) | \
_SHIFTL((lrx), 2, 22); \
_g0->words.w1 = _SHIFTL((lry), 2, 22); \
_g1->words.w0 = _SHIFTL((ulx), 2, 22); \
_g1->words.w0 = _SHIFTL(G_RDPHALF_1, 24, 8) | \
_SHIFTL((ulx), 2, 22); \
_g1->words.w1 = _SHIFTL((uly), 2, 22); \
}
#define gsDPFillRectangle(ulx, uly, lrx, lry) \
@ -4433,7 +4434,7 @@ typedef union {
_SHIFTL((lry), 2, 22), \
}}, \
{{ \
_SHIFTL((ulx), 2, 22), \
(_SHIFTL(G_RDPHALF_1, 24, 8) | _SHIFTL((ulx), 2, 22)), \
_SHIFTL((uly), 2, 22), \
}}
#else
@ -4670,24 +4671,26 @@ typedef union {
\
_g0->words.w0 = _SHIFTL(G_TEXRECT, 24, 8) | \
_SHIFTL((xh), 0, 24); \
_g0->words.w1 = _SHIFTL((yh), 0, 24); \
_g1->words.w0 = (_SHIFTL(tile, 24, 3) | _SHIFTL((xl), 0, 24)); \
_g1->words.w1 = _SHIFTL((yl), 0, 24); \
_g2->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \
_g0->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL((yh), 0, 24)); \
_g1->words.w0 = (_SHIFTL(G_RDPHALF_1, 24, 8) | \
_SHIFTL((xl), 0, 24)); \
_g1->words.w1 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \
_g2->words.w0 = _SHIFTL(G_RDPHALF_2, 24, 8) | \
_SHIFTL((yl), 0, 24); \
_g2->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \
}
# define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \
{{ \
(_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL((xh), 0, 24)), \
_SHIFTL((yh), 0, 24), \
}}, \
{{ \
(_SHIFTL((tile), 24, 3) | _SHIFTL((xl), 0, 24)), \
_SHIFTL((yl), 0, 24), \
(_SHIFTL((tile), 24, 3) | _SHIFTL((yh), 0, 24)), \
}}, \
{{ \
(_SHIFTL((G_RDPHALF_1), 24, 8) | _SHIFTL((xl), 0, 24)), \
_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16), \
}}, \
{{ \
(_SHIFTL((G_RDPHALF_2), 24, 8) | _SHIFTL((yl), 0, 24)), \
_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16) \
}}
@ -4697,10 +4700,12 @@ typedef union {
\
_g0->words.w0 = _SHIFTL(G_TEXRECTFLIP, 24, 8) | \
_SHIFTL((xh), 0, 24); \
_g0->words.w1 = _SHIFTL((yh), 0, 24); \
_g1->words.w0 = (_SHIFTL(tile, 24, 3) | _SHIFTL((xl), 0, 24)); \
_g1->words.w1 = _SHIFTL((yl), 0, 24); \
_g2->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \
_g0->words.w1 = (_SHIFTL(tile, 24, 3) | _SHIFTL((yh), 0, 24)); \
_g1->words.w0 = (_SHIFTL(G_RDPHALF_1, 24, 8) | \
_SHIFTL((xl), 0, 24)); \
_g1->words.w1 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \
_g2->words.w0 = _SHIFTL(G_RDPHALF_2, 24, 8) | \
_SHIFTL((yl), 0, 24); \
_g2->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \
}
#else

View file

@ -312,6 +312,10 @@ struct GraphNodeObject *init_graph_node_object(struct AllocOnlyPool *pool,
vec3f_copy(graphNode->pos, pos);
vec3f_copy(graphNode->scale, scale);
vec3s_copy(graphNode->angle, angle);
#ifdef USE_SYSTEM_MALLOC
// To avoid uninitialised memory usage in audio code
vec3f_copy(graphNode->cameraToObject, gVec3fZero);
#endif
graphNode->sharedChild = sharedChild;
graphNode->throwMatrix = NULL;
graphNode->animInfo.animID = 0;

View file

@ -55,6 +55,10 @@ static s16 sScriptStatus;
static s32 sRegister;
static struct LevelCommand *sCurrentCmd;
#ifdef USE_SYSTEM_MALLOC
static struct MemoryPool *sMemPoolForGoddard;
#endif
static s32 eval_script_op(s8 op, s32 arg) {
s32 result = 0;
@ -280,7 +284,23 @@ static void level_cmd_load_mio0(void) {
sCurrentCmd = CMD_NEXT;
}
#ifdef USE_SYSTEM_MALLOC
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);
}
#endif
static void level_cmd_load_mario_head(void) {
#ifdef USE_SYSTEM_MALLOC
sMemPoolForGoddard = mem_pool_init(0, 0);
gdm_init(alloc_for_goddard, free_for_goddard);
gdm_setup();
gdm_maketestdl(CMD_GET(s16, 2));
#else
// TODO: Fix these hardcoded sizes
void *addr = main_pool_alloc(DOUBLE_SIZE_ON_64_BIT(0xE1000), MEMORY_POOL_LEFT);
if (addr != NULL) {
@ -291,6 +311,7 @@ static void level_cmd_load_mario_head(void) {
gdm_maketestdl(CMD_GET(s16, 2));
} else {
}
#endif
sCurrentCmd = CMD_NEXT;
}
@ -320,8 +341,12 @@ static void level_cmd_clear_level(void) {
static void level_cmd_alloc_level_pool(void) {
if (sLevelPool == NULL) {
#ifdef USE_SYSTEM_MALLOC
sLevelPool = alloc_only_pool_init();
#else
sLevelPool = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool),
MEMORY_POOL_LEFT);
#endif
}
sCurrentCmd = CMD_NEXT;
@ -330,7 +355,9 @@ static void level_cmd_alloc_level_pool(void) {
static void level_cmd_free_level_pool(void) {
s32 i;
#ifndef USE_SYSTEM_MALLOC
alloc_only_pool_resize(sLevelPool, sLevelPool->usedSpace);
#endif
sLevelPool = NULL;
for (i = 0; i < 8; i++) {

View file

@ -27,6 +27,13 @@ SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS];
/**
* Pools of data to contain either surface nodes or surfaces.
*/
#ifdef USE_SYSTEM_MALLOC
static struct AllocOnlyPool *sStaticSurfaceNodePool;
static struct AllocOnlyPool *sStaticSurfacePool;
static struct AllocOnlyPool *sDynamicSurfaceNodePool;
static struct AllocOnlyPool *sDynamicSurfacePool;
static u8 sStaticSurfaceLoadComplete;
#else
struct SurfaceNode *sSurfaceNodePool;
struct Surface *sSurfacePool;
@ -34,6 +41,8 @@ struct Surface *sSurfacePool;
* The size of the surface pool (2300).
*/
s16 sSurfacePoolSize;
#endif
u8 unused8038EEA8[0x30];
@ -41,16 +50,24 @@ u8 unused8038EEA8[0x30];
* Allocate the part of the surface node pool to contain a surface node.
*/
static struct SurfaceNode *alloc_surface_node(void) {
#ifdef USE_SYSTEM_MALLOC
struct AllocOnlyPool *pool = !sStaticSurfaceLoadComplete ?
sStaticSurfaceNodePool : sDynamicSurfaceNodePool;
struct SurfaceNode *node = alloc_only_pool_alloc(pool, sizeof(struct SurfaceNode));
#else
struct SurfaceNode *node = &sSurfaceNodePool[gSurfaceNodesAllocated];
#endif
gSurfaceNodesAllocated++;
node->next = NULL;
#ifndef USE_SYSTEM_MALLOC
//! A bounds check! If there's more surface nodes than 7000 allowed,
// we, um...
// Perhaps originally just debug feedback?
if (gSurfaceNodesAllocated >= 7000) {
}
#endif
return node;
}
@ -60,15 +77,22 @@ static struct SurfaceNode *alloc_surface_node(void) {
* initialize the surface.
*/
static struct Surface *alloc_surface(void) {
#ifdef USE_SYSTEM_MALLOC
struct AllocOnlyPool *pool = !sStaticSurfaceLoadComplete ?
sStaticSurfacePool : sDynamicSurfacePool;
struct Surface *surface = alloc_only_pool_alloc(pool, sizeof(struct Surface));
#else
struct Surface *surface = &sSurfacePool[gSurfacesAllocated];
#endif
gSurfacesAllocated++;
#ifndef USE_SYSTEM_MALLOC
//! A bounds check! If there's more surfaces than the 2300 allowed,
// we, um...
// Perhaps originally just debug feedback?
if (gSurfacesAllocated >= sSurfacePoolSize) {
}
#endif
surface->type = 0;
surface->force = 0;
@ -524,9 +548,16 @@ 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) {
#ifdef USE_SYSTEM_MALLOC
sStaticSurfaceNodePool = alloc_only_pool_init();
sStaticSurfacePool = alloc_only_pool_init();
sDynamicSurfaceNodePool = alloc_only_pool_init();
sDynamicSurfacePool = alloc_only_pool_init();
#else
sSurfacePoolSize = 2300;
sSurfaceNodePool = main_pool_alloc(7000 * sizeof(struct SurfaceNode), MEMORY_POOL_LEFT);
sSurfacePool = main_pool_alloc(sSurfacePoolSize * sizeof(struct Surface), MEMORY_POOL_LEFT);
#endif
gCCMEnteredSlide = 0;
reset_red_coins_collected();
@ -597,6 +628,13 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
unused8038BE90 = 0;
gSurfaceNodesAllocated = 0;
gSurfacesAllocated = 0;
#ifdef USE_SYSTEM_MALLOC
alloc_only_pool_clear(sStaticSurfaceNodePool);
alloc_only_pool_clear(sStaticSurfacePool);
alloc_only_pool_clear(sDynamicSurfaceNodePool);
alloc_only_pool_clear(sDynamicSurfacePool);
sStaticSurfaceLoadComplete = FALSE;
#endif
clear_static_surfaces();
@ -639,6 +677,10 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
gNumStaticSurfaceNodes = gSurfaceNodesAllocated;
gNumStaticSurfaces = gSurfacesAllocated;
#ifdef USE_SYSTEM_MALLOC
sStaticSurfaceLoadComplete = TRUE;
#endif
}
/**
@ -646,6 +688,15 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
*/
void clear_dynamic_surfaces(void) {
if (!(gTimeStopState & TIME_STOP_ACTIVE)) {
#ifdef USE_SYSTEM_MALLOC
if (gSurfacesAllocated > gNumStaticSurfaces) {
alloc_only_pool_clear(sDynamicSurfacePool);
}
if (gSurfaceNodesAllocated > gNumStaticSurfaceNodes) {
alloc_only_pool_clear(sDynamicSurfaceNodePool);
}
#endif
gSurfacesAllocated = gNumStaticSurfaces;
gSurfaceNodesAllocated = gNumStaticSurfaceNodes;

View file

@ -159,6 +159,11 @@ void load_obj_warp_nodes(void) {
struct ObjectWarpNode *sp24;
struct Object *sp20 = (struct Object *) gObjParentGraphNode.children;
#ifdef USE_SYSTEM_MALLOC
if (sp20 == NULL) {
return;
}
#endif
do {
struct Object *sp1C = sp20;

View file

@ -12,7 +12,13 @@ void bhv_object_bubble_loop(void) {
f32 bubbleY = o->oPosY;
if (bubbleY > waterY) {
if (gFreeObjectList.next) {
if (
#ifdef USE_SYSTEM_MALLOC
TRUE
#else
gFreeObjectList.next != NULL
#endif
) {
bubbleSplash = spawn_object_at_origin(o, 0, MODEL_SMALL_WATER_SPLASH, bhvBubbleSplash);
bubbleSplash->oPosX = o->oPosX;
bubbleSplash->oPosY = bubbleY + 5.0f;

View file

@ -63,9 +63,16 @@ void bhv_small_water_wave_loop(void) {
if (o->oPosY > sp1C) {
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
o->oPosY += 5.0f;
if (gFreeObjectList.next != NULL)
if (
#ifdef USE_SYSTEM_MALLOC
TRUE
#else
gFreeObjectList.next != NULL
#endif
) {
spawn_object(o, MODEL_SMALL_WATER_SPLASH, bhvObjectWaterSplash);
}
}
if (o->oInteractStatus & INT_STATUS_INTERACTED)
obj_mark_for_deletion(o);
}

View file

@ -25,8 +25,14 @@
// know of a good way to split them
struct Controller gControllers[3];
struct SPTask *gGfxSPTask;
#ifdef USE_SYSTEM_MALLOC
struct AllocOnlyPool *gGfxAllocOnlyPool;
Gfx *gDisplayListHeadInChunk;
Gfx *gDisplayListEndInChunk;
#else
Gfx *gDisplayListHead;
u8 *gGfxPoolEnd;
#endif
struct GfxPool *gGfxPool;
OSContStatus gControllerStatuses[4];
OSContPad gControllerPads[4];
@ -221,7 +227,7 @@ void create_task_structure(void) {
gGfxSPTask->msgqueue = &D_80339CB8;
gGfxSPTask->msg = (OSMesg) 2;
gGfxSPTask->task.t.type = M_GFXTASK;
#if TARGET_N64
#ifdef TARGET_N64
gGfxSPTask->task.t.ucode_boot = rspF3DBootStart;
gGfxSPTask->task.t.ucode_boot_size = ((u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart);
gGfxSPTask->task.t.flags = 0;
@ -291,6 +297,7 @@ void draw_reset_bars(void) {
osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK);
}
#ifdef TARGET_N64
void rendering_init(void) {
gGfxPool = &gGfxPools[0];
set_segment_base_addr(1, gGfxPool->buffer);
@ -305,13 +312,31 @@ void rendering_init(void) {
frameBufferIndex++;
gGlobalTimer++;
}
#endif
#ifdef USE_SYSTEM_MALLOC
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;
}
#endif
void config_gfx_pool(void) {
gGfxPool = &gGfxPools[gGlobalTimer % GFX_NUM_POOLS];
set_segment_base_addr(1, gGfxPool->buffer);
gGfxSPTask = &gGfxPool->spTask;
#ifdef USE_SYSTEM_MALLOC
gDisplayListHeadInChunk = gGfxPool->buffer;
gDisplayListEndInChunk = gDisplayListHeadInChunk + 1;
alloc_only_pool_clear(gGfxAllocOnlyPool);
#else
gDisplayListHead = gGfxPool->buffer;
gGfxPoolEnd = (u8 *) (gGfxPool->buffer + GFX_POOL_SIZE);
#endif
}
/** Handles vsync. */
@ -648,9 +673,11 @@ void game_loop_one_iteration(void) {
// when debug info is enabled, print the "BUF %d" information.
if (gShowDebugText) {
#ifndef USE_SYSTEM_MALLOC
// 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);
#endif
}
#ifdef TARGET_N64
}

View file

@ -9,7 +9,11 @@
#include "types.h"
#include "memory.h"
#ifdef USE_SYSTEM_MALLOC
#define GFX_POOL_SIZE 1
#else
#define GFX_POOL_SIZE 6400
#endif
struct GfxPool {
Gfx buffer[GFX_POOL_SIZE];
@ -37,8 +41,14 @@ extern uintptr_t gPhysicalZBuffer;
extern void *D_80339CF0;
extern void *D_80339CF4;
extern struct SPTask *gGfxSPTask;
#ifdef USE_SYSTEM_MALLOC
extern struct AllocOnlyPool *gGfxAllocOnlyPool;
extern Gfx *gDisplayListHeadInChunk;
extern Gfx *gDisplayListEndInChunk;
#else
extern Gfx *gDisplayListHead;
extern u8 *gGfxPoolEnd;
#endif
extern struct GfxPool *gGfxPool;
extern u8 gControllerBits;
extern s8 gEepromProbe;
@ -73,4 +83,9 @@ void rendering_init(void);
void config_gfx_pool(void);
void display_and_vsync(void);
#ifdef USE_SYSTEM_MALLOC
Gfx **alloc_next_dl(void);
#define gDisplayListHead (*(gDisplayListEndInChunk - gDisplayListHeadInChunk >= 2 ? &gDisplayListHeadInChunk : alloc_next_dl()))
#endif
#endif // GAME_INIT_H

View file

@ -2,6 +2,9 @@
#ifndef TARGET_N64
#include <string.h>
#endif
#ifdef USE_SYSTEM_MALLOC
#include <stdlib.h>
#endif
#include "sm64.h"
@ -14,6 +17,7 @@
#include "memory.h"
#include "segment_symbols.h"
#include "segments.h"
#include "platform_info.h"
// round up to the next multiple
#define ALIGN4(val) (((val) + 0x3) & ~0x3)
@ -21,26 +25,60 @@
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
struct MainPoolState {
#ifndef USE_SYSTEM_MALLOC
u32 freeSpace;
struct MainPoolBlock *listHeadL;
struct MainPoolBlock *listHeadR;
#endif
struct MainPoolState *prev;
};
struct MainPoolBlock {
struct MainPoolBlock *prev;
struct MainPoolBlock *next;
#ifdef USE_SYSTEM_MALLOC
void (*releaseHandler)(void *addr);
#endif
};
#ifdef USE_SYSTEM_MALLOC
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;
};
#else
struct MemoryBlock {
struct MemoryBlock *next;
u32 size;
};
#endif
struct MemoryPool {
#ifdef USE_SYSTEM_MALLOC
struct AllocOnlyPool *allocOnlyPool;
struct FreeListNode *bins[27];
#else
u32 totalSpace;
struct MemoryBlock *firstBlock;
struct MemoryBlock freeList;
#endif
};
extern uintptr_t sSegmentTable[32];
@ -110,6 +148,18 @@ void move_segment_table_to_dmem(void) {
}
#endif
#ifdef USE_SYSTEM_MALLOC
static void main_pool_free_all(void) {
while (sPoolListHeadL != NULL) {
main_pool_free(sPoolListHeadL + 1);
}
}
void main_pool_init(void) {
atexit(main_pool_free_all);
}
#else
/**
* 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
@ -127,7 +177,61 @@ void main_pool_init(void *start, void *end) {
sPoolListHeadR->prev = NULL;
sPoolListHeadR->next = NULL;
}
#endif
#ifdef USE_SYSTEM_MALLOC
void *main_pool_alloc(u32 size, void (*releaseHandler)(void *addr)) {
struct MainPoolBlock *newListHead = (struct MainPoolBlock *) malloc(sizeof(struct MainPoolBlock) + size);
if (newListHead == NULL) {
abort();
}
if (sPoolListHeadL != NULL) {
sPoolListHeadL->next = newListHead;
}
newListHead->prev = sPoolListHeadL;
newListHead->next = NULL;
newListHead->releaseHandler = releaseHandler;
sPoolListHeadL = newListHead;
return newListHead + 1;
}
u32 main_pool_free(void *addr) {
struct MainPoolBlock *block = ((struct MainPoolBlock *) addr) - 1;
void *toFree;
do {
if (sPoolListHeadL == NULL) {
abort();
}
if (sPoolListHeadL->releaseHandler != NULL) {
sPoolListHeadL->releaseHandler(sPoolListHeadL + 1);
}
toFree = sPoolListHeadL;
sPoolListHeadL = sPoolListHeadL->prev;
if (sPoolListHeadL != NULL) {
sPoolListHeadL->next = NULL;
}
free(toFree);
} while (toFree != block);
return 0;
}
u32 main_pool_push_state(void) {
struct MainPoolState *prevState = gMainPoolState;
gMainPoolState = main_pool_alloc(sizeof(*gMainPoolState), NULL);
gMainPoolState->prev = prevState;
return 0;
}
/**
* Restore pool state from a previous call to main_pool_push_state. Return the
* amount of free space left in the pool.
*/
u32 main_pool_pop_state(void) {
struct MainPoolState *prevState = gMainPoolState->prev;
main_pool_free(gMainPoolState);
gMainPoolState = prevState;
}
#else
/**
* Allocate a block of memory from the pool of given size, and from the
* specified side of the pool (MEMORY_POOL_LEFT or MEMORY_POOL_RIGHT).
@ -241,6 +345,7 @@ u32 main_pool_pop_state(void) {
gMainPoolState = gMainPoolState->prev;
return sPoolFreeSpace;
}
#endif
/**
* Perform a DMA read from ROM. The transfer is split into 4KB blocks, and this
@ -270,11 +375,15 @@ static void dma_read(u8 *dest, u8 *srcStart, u8 *srcEnd) {
* Perform a DMA read from ROM, allocating space in the memory pool to write to.
* Return the destination address.
*/
static void *dynamic_dma_read(u8 *srcStart, u8 *srcEnd, u32 side) {
static void *dynamic_dma_read(u8 *srcStart, u8 *srcEnd, UNUSED u32 side) {
void *dest;
u32 size = ALIGN16(srcEnd - srcStart);
#ifdef USE_SYSTEM_MALLOC
dest = main_pool_alloc(size, NULL);
#else
dest = main_pool_alloc(size, side);
#endif
if (dest != NULL) {
dma_read(dest, srcStart, srcEnd);
}
@ -377,6 +486,118 @@ void load_engine_code_segment(void) {
}
#endif
#ifdef USE_SYSTEM_MALLOC
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;
}
}
struct AllocOnlyPool *alloc_only_pool_init(void) {
struct AllocOnlyPool *pool;
void *addr = main_pool_alloc(sizeof(struct AllocOnlyPool), alloc_only_pool_release_handler);
pool = (struct AllocOnlyPool *) addr;
pool->lastBlock = NULL;
pool->lastBlockSize = 0;
pool->lastBlockNextPos = 0;
return pool;
}
void alloc_only_pool_clear(struct AllocOnlyPool *pool) {
alloc_only_pool_release_handler(pool);
pool->lastBlock = NULL;
pool->lastBlockSize = 0;
pool->lastBlockNextPos = 0;
}
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;
}
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;
}
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;
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) {
size = ALIGN8(size);
return alloc_only_pool_alloc(gGfxAllocOnlyPool, size);
}
#else
/**
* Allocate an allocation-only pool from the main pool. This pool doesn't
* support freeing allocated memory.
@ -537,6 +758,7 @@ void *alloc_display_list(u32 size) {
}
return ptr;
}
#endif
static struct MarioAnimDmaRelatedThing *func_802789F0(u8 *srcAddr) {
struct MarioAnimDmaRelatedThing *sp1C = dynamic_dma_read(srcAddr, srcAddr + sizeof(u32),

View file

@ -8,7 +8,9 @@
#define MEMORY_POOL_LEFT 0
#define MEMORY_POOL_RIGHT 1
#ifdef USE_SYSTEM_MALLOC
struct AllocOnlyPool;
#else
struct AllocOnlyPool
{
s32 totalSpace;
@ -16,6 +18,7 @@ struct AllocOnlyPool
u8 *startPtr;
u8 *freePtr;
};
#endif
struct MemoryPool;
@ -32,8 +35,13 @@ void *segmented_to_virtual(const void *addr);
void *virtual_to_segmented(u32 segment, const void *addr);
void move_segment_table_to_dmem(void);
#ifdef USE_SYSTEM_MALLOC
void main_pool_init(void);
void *main_pool_alloc(u32 size, void (*releaseHandler)(void *addr));
#else
void main_pool_init(void *start, void *end);
void *main_pool_alloc(u32 size, u32 side);
#endif
u32 main_pool_free(void *addr);
void *main_pool_realloc(void *addr, u32 size);
u32 main_pool_available(void);
@ -54,9 +62,15 @@ void load_engine_code_segment(void);
#define load_engine_code_segment(...)
#endif
#ifdef USE_SYSTEM_MALLOC
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);
#else
struct AllocOnlyPool *alloc_only_pool_init(u32 size, u32 side);
void *alloc_only_pool_alloc(struct AllocOnlyPool *pool, s32 size);
struct AllocOnlyPool *alloc_only_pool_resize(struct AllocOnlyPool *pool, u32 size);
#endif
struct MemoryPool *mem_pool_init(u32 size, u32 side);
void *mem_pool_alloc(struct MemoryPool *pool, u32 size);

View file

@ -551,7 +551,13 @@ struct Object *try_to_spawn_object(s16 offsetY, f32 scale, struct Object *parent
const BehaviorScript *behavior) {
struct Object *obj;
if (gFreeObjectList.next != NULL) {
if (
#ifdef USE_SYSTEM_MALLOC
TRUE
#else
gFreeObjectList.next != NULL
#endif
) {
obj = spawn_object(parent, model, behavior);
obj->oPosY += offsetY;
obj_scale(obj, scale);

View file

@ -63,10 +63,12 @@ s16 gDebugInfoOverwrite[16][8];
*/
u32 gTimeStopState;
#ifndef USE_SYSTEM_MALLOC
/**
* The pool that objects are allocated from.
*/
struct Object gObjectPool[OBJECT_POOL_CAPACITY];
#endif
/**
* A special object whose purpose is to act as a parent for macro objects.
@ -540,16 +542,20 @@ void clear_objects(void) {
debug_unknown_level_select_check();
#ifndef USE_SYSTEM_MALLOC
init_free_object_list();
#endif
clear_object_lists(gObjectListArray);
stub_behavior_script_2();
stub_obj_list_processor_1();
#ifndef USE_SYSTEM_MALLOC
for (i = 0; i < OBJECT_POOL_CAPACITY; i++) {
gObjectPool[i].activeFlags = ACTIVE_FLAG_DEACTIVATED;
geo_reset_object_node(&gObjectPool[i].header.gfx);
}
#endif
gObjectMemoryPool = mem_pool_init(0x800, MEMORY_POOL_LEFT);
gObjectLists = gObjectListArray;

View file

@ -1051,8 +1051,12 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
Mtx *initialMatrix;
Vp *viewport = alloc_display_list(sizeof(*viewport));
#ifdef USE_SYSTEM_MALLOC
gDisplayListHeap = alloc_only_pool_init();
#else
gDisplayListHeap = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool),
MEMORY_POOL_LEFT);
#endif
initialMatrix = alloc_display_list(sizeof(*initialMatrix));
gMatStackIndex = 0;
gCurAnimType = 0;
@ -1081,8 +1085,10 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
}
gCurGraphNodeRoot = NULL;
if (gShowDebugText) {
#ifndef USE_SYSTEM_MALLOC
print_text_fmt_int(180, 36, "MEM %d",
gDisplayListHeap->totalSpace - gDisplayListHeap->usedSpace);
#endif
}
main_pool_free(gDisplayListHeap);
}

View file

@ -1,3 +1,6 @@
#ifdef USE_SYSTEM_MALLOC
#include <stdlib.h>
#endif
#include <PR/ultratypes.h>
#include "audio/external.h"
@ -89,10 +92,26 @@ struct Object *try_allocate_object(struct ObjectNode *destList, struct ObjectNod
destList->prev->next = nextObj;
destList->prev = nextObj;
} else {
#ifdef USE_SYSTEM_MALLOC
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;
#else
return NULL;
#endif
}
#ifdef USE_SYSTEM_MALLOC
init_graph_node_object(NULL, &nextObj->gfx, 0, gVec3fZero, gVec3sZero, gVec3fOne);
#else
geo_remove_child(&nextObj->gfx.node);
#endif
geo_add_child(&gObjParentGraphNode, &nextObj->gfx.node);
return (struct Object *) nextObj;
@ -112,6 +131,7 @@ void unused_deallocate(struct LinkedList *freeList, struct LinkedList *node) {
node->next = freeList->next;
freeList->next = node;
}
/**
* Remove the given object from the object list that it's currently in, and
* insert it at the beginning of the free list (singly linked).
@ -126,6 +146,7 @@ static void deallocate_object(struct ObjectNode *freeList, struct ObjectNode *ob
freeList->next = obj;
}
#ifndef USE_SYSTEM_MALLOC
/**
* Add every object in the pool to the free object list.
*/
@ -146,6 +167,7 @@ void init_free_object_list(void) {
// End the list
obj->header.next = NULL;
}
#endif
/**
* Clear each object list, without adding the objects back to the free list.
@ -154,6 +176,17 @@ void clear_object_lists(struct ObjectNode *objLists) {
s32 i;
for (i = 0; i < NUM_OBJ_LISTS; i++) {
#ifdef USE_SYSTEM_MALLOC
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);
}
#endif
objLists[i].next = &objLists[i];
objLists[i].prev = &objLists[i];
}
@ -192,7 +225,9 @@ void unload_object(struct Object *obj) {
obj->header.gfx.throwMatrix = NULL;
func_803206F8(obj->header.gfx.cameraToObject);
geo_remove_child(&obj->header.gfx.node);
#ifndef USE_SYSTEM_MALLOC
geo_add_child(&gObjParentGraphNode, &obj->header.gfx.node);
#endif
obj->header.gfx.node.flags &= ~GRAPH_RENDER_BILLBOARD;
obj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
@ -209,6 +244,7 @@ struct Object *allocate_object(struct ObjectNode *objList) {
s32 i;
struct Object *obj = try_allocate_object(objList, &gFreeObjectList);
#ifndef USE_SYSTEM_MALLOC
// 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.
@ -233,6 +269,7 @@ struct Object *allocate_object(struct ObjectNode *objList) {
}
}
}
#endif
// Initialize object fields

View file

@ -1,3 +1,4 @@
#ifndef USE_SYSTEM_MALLOC
#include <PR/ultratypes.h>
#include "debug_utils.h"
@ -312,6 +313,10 @@ void mem_stats(void) {
list = sEmptyBlockListHead;
print_list_stats(list, FALSE, PERM_G_MEM_BLOCK | TEMP_G_MEM_BLOCK);
}
#else
void mem_stats(void) {
}
#endif
/*
::::::

View file

@ -114,8 +114,10 @@ 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];
#ifndef USE_SYSTEM_MALLOC
static u8 *sMemBlockPoolBase; // @ 801BB00C
static u32 sAllocMemory; // @ 801BB010; malloc-ed bytes
#endif
static u32 unref_801bb014;
static s32 D_801BB018;
static s32 D_801BB01C;
@ -182,6 +184,11 @@ static OSIoMesg D_801BE980;
static struct ObjView *D_801BE994; // store if View flag 0x40 set
#endif
#ifdef USE_SYSTEM_MALLOC
static void *(*sAllocFn)(u32 size);
static void (*sFreeFn)(void *ptr);
#endif
// data
static u32 unref_801a8670 = 0;
static s32 D_801A8674 = 0;
@ -193,8 +200,10 @@ 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
#ifndef USE_SYSTEM_MALLOC
static u32 sMemBlockPoolSize = 1; // @ 801A8698
static s32 sMemBlockPoolUsed = 0; // @ 801A869C
#endif
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
@ -763,7 +772,11 @@ void reset_cur_dl_indices(void);
// TODO: make a gddl_num_t?
u32 get_alloc_mem_amt(void) {
#ifdef USE_SYSTEM_MALLOC
return 0;
#else
return sAllocMemory;
#endif
}
s32 gd_get_ostime(void) {
@ -959,9 +972,14 @@ void gd_exit(UNUSED s32 code) {
/* 24A1D4 -> 24A220; orig name: func_8019BA04 */
void gd_free(void *ptr) {
#ifdef USE_SYSTEM_MALLOC
sFreeFn(ptr);
#else
sAllocMemory -= gd_free_mem(ptr);
#endif
}
#ifndef USE_SYSTEM_MALLOC
/* 24A220 -> 24A318 */
void *gd_allocblock(u32 size) {
void *block; // 1c
@ -980,9 +998,13 @@ void *gd_allocblock(u32 size) {
sMemBlockPoolUsed += size;
return block;
}
#endif
/* 24A318 -> 24A3E8 */
void *gd_malloc(u32 size, u8 perm) {
void *gd_malloc(u32 size, UNUSED u8 perm) {
#ifdef USE_SYSTEM_MALLOC
return sAllocFn(size);
#else
void *ptr; // 1c
size = ALIGN(size, 8);
ptr = gd_request_mem(size, perm);
@ -998,6 +1020,7 @@ void *gd_malloc(u32 size, u8 perm) {
sAllocMemory += size;
return ptr;
#endif
}
/* 24A3E8 -> 24A420; orig name: func_8019BC18 */
@ -1122,12 +1145,23 @@ void Unknown8019C288(s32 stickX, s32 stickY) {
ctrl->stickYf = (f32)(stickY / 2);
}
#ifndef USE_SYSTEM_MALLOC
/* 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);
}
#endif
#ifdef USE_SYSTEM_MALLOC
void gdm_init(void *(*allocFn)(u32 size), void (*freeFn)(void *addr)) {
add_to_stacktrace("gdm_init");
sAllocFn = allocFn;
sFreeFn = freeFn;
gd_reset_sfx();
imout();
}
#else
/* 24AAE0 -> 24AB7C */
void gdm_init(void *blockpool, u32 size) {
UNUSED u32 pad;
@ -1145,6 +1179,7 @@ void gdm_init(void *blockpool, u32 size) {
gd_reset_sfx();
imout();
}
#endif
/* 24AB7C -> 24AC18 */
void gdm_setup(void) {
@ -3118,9 +3153,11 @@ void gd_init(void) {
s8 *data; // 2c
add_to_stacktrace("gd_init");
#ifndef USE_SYSTEM_MALLOC
i = (u32)(sMemBlockPoolSize - DOUBLE_SIZE_ON_64_BIT(0x3E800));
data = gd_allocblock(i);
gd_add_mem_to_heap(i, data, 0x10);
#endif
D_801BB184 = (u16) 0xff;
D_801A867C = 0;
D_801A8680 = 0;

View file

@ -42,8 +42,12 @@ 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);
#ifdef USE_SYSTEM_MALLOC
void gdm_init(void *(*allocFn)(u32 size), void (*freeFn)(void *ptr));
#else
void gd_add_to_heap(void *addr, u32 size);
void gdm_init(void *blockpool, u32 size);
#endif
void gdm_setup(void);
void gdm_maketestdl(s32 id);
void gd_vblank(void);

6289
src/pc/dlmalloc.c Normal file

File diff suppressed because it is too large Load diff

192
src/pc/gfx/gfx_dummy.c Normal file
View file

@ -0,0 +1,192 @@
#ifdef ENABLE_GFX_DUMMY
#include <time.h>
#include <errno.h>
#include "gfx_window_manager_api.h"
#include "gfx_rendering_api.h"
static void gfx_dummy_wm_init(const char *game_name, bool start_in_fullscreen) {
}
static void gfx_dummy_wm_set_keyboard_callbacks(bool (*on_key_down)(int scancode), bool (*on_key_up)(int scancode), void (*on_all_keys_up)(void)) {
}
static void gfx_dummy_wm_set_fullscreen_changed_callback(void (*on_fullscreen_changed)(bool is_now_fullscreen)) {
}
static void gfx_dummy_wm_set_fullscreen(bool enable) {
}
static void gfx_dummy_wm_main_loop(void (*run_one_game_iter)(void)) {
while (1) {
run_one_game_iter();
}
}
static void gfx_dummy_wm_get_dimensions(uint32_t *width, uint32_t *height) {
*width = 320;
*height = 240;
}
static void gfx_dummy_wm_handle_events(void) {
}
static bool gfx_dummy_wm_start_frame(void) {
return true;
}
static void gfx_dummy_wm_swap_buffers_begin(void) {
}
static struct timespec gfx_dummy_wm_timediff(struct timespec t1, struct timespec t2) {
t1.tv_sec -= t2.tv_sec;
t1.tv_nsec -= t2.tv_nsec;
if (t1.tv_nsec < 0) {
t1.tv_nsec += 1000000000;
t1.tv_sec -= 1;
}
return t1;
}
static struct timespec gfx_dummy_wm_timeadd(struct timespec t1, struct timespec t2) {
t1.tv_sec += t2.tv_sec;
t1.tv_nsec += t2.tv_nsec;
if (t1.tv_nsec > 1000000000) {
t1.tv_nsec -= 1000000000;
t1.tv_sec += 1;
}
return t1;
}
static void gfx_dummy_wm_swap_buffers_end(void) {
static struct timespec prev;
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
struct timespec diff = gfx_dummy_wm_timediff(t, prev);
if (diff.tv_sec == 0 && diff.tv_nsec < 1000000000 / 30) {
struct timespec add = {0, 1000000000 / 30};
struct timespec next = gfx_dummy_wm_timeadd(prev, add);
while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL) == EINTR) {
}
prev = next;
} else {
prev = t;
}
}
static double gfx_dummy_wm_get_time(void) {
return 0.0;
}
static bool gfx_dummy_renderer_z_is_from_0_to_1(void) {
return false;
}
static void gfx_dummy_renderer_unload_shader(struct ShaderProgram *old_prg) {
}
static void gfx_dummy_renderer_load_shader(struct ShaderProgram *new_prg) {
}
static struct ShaderProgram *gfx_dummy_renderer_create_and_load_new_shader(uint32_t shader_id) {
return NULL;
}
static struct ShaderProgram *gfx_dummy_renderer_lookup_shader(uint32_t shader_id) {
return NULL;
}
static void gfx_dummy_renderer_shader_get_info(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) {
*num_inputs = 0;
used_textures[0] = false;
used_textures[1] = false;
}
static uint32_t gfx_dummy_renderer_new_texture(void) {
return 0;
}
static void gfx_dummy_renderer_select_texture(int tile, uint32_t texture_id) {
}
static void gfx_dummy_renderer_upload_texture(const uint8_t *rgba32_buf, int width, int height) {
}
static void gfx_dummy_renderer_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) {
}
static void gfx_dummy_renderer_set_depth_test(bool depth_test) {
}
static void gfx_dummy_renderer_set_depth_mask(bool z_upd) {
}
static void gfx_dummy_renderer_set_zmode_decal(bool zmode_decal) {
}
static void gfx_dummy_renderer_set_viewport(int x, int y, int width, int height) {
}
static void gfx_dummy_renderer_set_scissor(int x, int y, int width, int height) {
}
static void gfx_dummy_renderer_set_use_alpha(bool use_alpha) {
}
static void gfx_dummy_renderer_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t buf_vbo_num_tris) {
}
static void gfx_dummy_renderer_init(void) {
}
static void gfx_dummy_renderer_on_resize(void) {
}
static void gfx_dummy_renderer_start_frame(void) {
}
static void gfx_dummy_renderer_end_frame(void) {
}
static void gfx_dummy_renderer_finish_render(void) {
}
struct GfxWindowManagerAPI gfx_dummy_wm_api = {
gfx_dummy_wm_init,
gfx_dummy_wm_set_keyboard_callbacks,
gfx_dummy_wm_set_fullscreen_changed_callback,
gfx_dummy_wm_set_fullscreen,
gfx_dummy_wm_main_loop,
gfx_dummy_wm_get_dimensions,
gfx_dummy_wm_handle_events,
gfx_dummy_wm_start_frame,
gfx_dummy_wm_swap_buffers_begin,
gfx_dummy_wm_swap_buffers_end,
gfx_dummy_wm_get_time
};
struct GfxRenderingAPI gfx_dummy_renderer_api = {
gfx_dummy_renderer_z_is_from_0_to_1,
gfx_dummy_renderer_unload_shader,
gfx_dummy_renderer_load_shader,
gfx_dummy_renderer_create_and_load_new_shader,
gfx_dummy_renderer_lookup_shader,
gfx_dummy_renderer_shader_get_info,
gfx_dummy_renderer_new_texture,
gfx_dummy_renderer_select_texture,
gfx_dummy_renderer_upload_texture,
gfx_dummy_renderer_set_sampler_parameters,
gfx_dummy_renderer_set_depth_test,
gfx_dummy_renderer_set_depth_mask,
gfx_dummy_renderer_set_zmode_decal,
gfx_dummy_renderer_set_viewport,
gfx_dummy_renderer_set_scissor,
gfx_dummy_renderer_set_use_alpha,
gfx_dummy_renderer_draw_triangles,
gfx_dummy_renderer_init,
gfx_dummy_renderer_on_resize,
gfx_dummy_renderer_start_frame,
gfx_dummy_renderer_end_frame,
gfx_dummy_renderer_finish_render
};
#endif

14
src/pc/gfx/gfx_dummy.h Normal file
View file

@ -0,0 +1,14 @@
#ifdef ENABLE_GFX_DUMMY
#ifndef GFX_DUMMY_H
#define GFX_DUMMY_H
#include "gfx_rendering_api.h"
#include "gfx_window_manager_api.h"
extern struct GfxRenderingAPI gfx_dummy_renderer_api;
extern struct GfxWindowManagerAPI gfx_dummy_wm_api;
#endif
#endif

View file

@ -100,6 +100,11 @@ static struct RSP {
} texture_scaling_factor;
struct LoadedVertex loaded_vertices[MAX_VERTICES + 4];
uint8_t saved_opcode;
uint8_t saved_tile;
uint16_t saved_uls, saved_ult;
int32_t saved_lrx, saved_lry, saved_ulx, saved_uly;
} rsp;
static struct RDP {
@ -1459,6 +1464,56 @@ static void gfx_run_dl(Gfx* cmd) {
gfx_sp_set_other_mode(C0(8, 8) + 32, C0(0, 8), (uint64_t) cmd->words.w1 << 32);
#endif
break;
#ifdef F3D_OLD
case (uint8_t)G_RDPHALF_2:
#else
case (uint8_t)G_RDPHALF_1:
#endif
switch (rsp.saved_opcode) {
case G_TEXRECT:
case G_TEXRECTFLIP:
#ifdef F3DEX_GBI_2E
rsp.saved_ulx = (int32_t)(C0(0, 24) << 8) >> 8;
#endif
rsp.saved_uls = (uint16_t)C1(16, 16);
rsp.saved_ult = (uint16_t)C1(0, 16);
break;
#ifdef F3DEX_GBI_2E
case G_FILLRECT:
{
int32_t ulx = (int32_t)(C0(0, 24) << 8) >> 8;
int32_t uly = (int32_t)(C1(0, 24) << 8) >> 8;
gfx_dp_fill_rectangle(ulx, uly, rsp.saved_lrx, rsp.saved_lry);
rsp.saved_opcode = G_NOOP;
break;
}
#endif
}
break;
#ifdef F3D_OLD
case (uint8_t)G_RDPHALF_CONT:
#else
case (uint8_t)G_RDPHALF_2:
#endif
switch (rsp.saved_opcode) {
case G_TEXRECT:
case G_TEXRECTFLIP:
{
uint8_t tile = rsp.saved_tile;
int32_t ulx = rsp.saved_ulx, lrx = rsp.saved_lrx, lry = rsp.saved_lry;
uint16_t uls = rsp.saved_uls, ult = rsp.saved_ult;
#ifdef F3DEX_GBI_2E
int32_t uly = (int32_t)(C0(0, 24) << 8) >> 8;
#else
int32_t uly = rsp.saved_uly;
#endif
uint16_t dsdx = (uint16_t)C1(16, 16);
uint16_t dtdy = (uint16_t)C1(0, 16);
gfx_dp_texture_rectangle(ulx, uly, lrx, lry, tile, uls, ult, dsdx, dtdy, rsp.saved_opcode == G_TEXRECTFLIP);
rsp.saved_opcode = G_NOOP;
break;
}
}
// RDP Commands:
case G_SETTIMG:
@ -1503,45 +1558,26 @@ static void gfx_run_dl(Gfx* cmd) {
case G_TEXRECT:
case G_TEXRECTFLIP:
{
int32_t lrx, lry, tile, ulx, uly;
uint32_t uls, ult, dsdx, dtdy;
rsp.saved_opcode = opcode;
#ifdef F3DEX_GBI_2E
lrx = (int32_t)(C0(0, 24) << 8) >> 8;
lry = (int32_t)(C1(0, 24) << 8) >> 8;
++cmd;
ulx = (int32_t)(C0(0, 24) << 8) >> 8;
uly = (int32_t)(C1(0, 24) << 8) >> 8;
++cmd;
uls = C0(16, 16);
ult = C0(0, 16);
dsdx = C1(16, 16);
dtdy = C1(0, 16);
rsp.saved_lrx = (int32_t)(C0(0, 24) << 8) >> 8;
rsp.saved_lry = (int32_t)(C1(0, 24) << 8) >> 8;
rsp.saved_tile = (int32_t)C1(24, 3);
#else
lrx = C0(12, 12);
lry = C0(0, 12);
tile = C1(24, 3);
ulx = C1(12, 12);
uly = C1(0, 12);
++cmd;
uls = C1(16, 16);
ult = C1(0, 16);
++cmd;
dsdx = C1(16, 16);
dtdy = C1(0, 16);
rsp.saved_lrx = C0(12, 12);
rsp.saved_lry = C0(0, 12);
rsp.saved_tile = C1(24, 3);
rsp.saved_ulx = C1(12, 12);
rsp.saved_uly = C1(0, 12);
#endif
gfx_dp_texture_rectangle(ulx, uly, lrx, lry, tile, uls, ult, dsdx, dtdy, opcode == G_TEXRECTFLIP);
break;
}
case G_FILLRECT:
#ifdef F3DEX_GBI_2E
{
int32_t lrx, lry, ulx, uly;
lrx = (int32_t)(C0(0, 24) << 8) >> 8;
lry = (int32_t)(C1(0, 24) << 8) >> 8;
++cmd;
ulx = (int32_t)(C0(0, 24) << 8) >> 8;
uly = (int32_t)(C1(0, 24) << 8) >> 8;
gfx_dp_fill_rectangle(ulx, uly, lrx, lry);
rsp.saved_opcode = G_FILLRECT;
rsp.saved_lrx = (int32_t)(C0(0, 24) << 8) >> 8;
rsp.saved_lry = (int32_t)(C1(0, 24) << 8) >> 8;
break;
}
#else

View file

@ -17,6 +17,7 @@
#include "gfx/gfx_dxgi.h"
#include "gfx/gfx_glx.h"
#include "gfx/gfx_sdl.h"
#include "gfx/gfx_dummy.h"
#include "audio/audio_api.h"
#include "audio/audio_wasapi.h"
@ -140,8 +141,13 @@ static void on_fullscreen_changed(bool is_now_fullscreen) {
}
void main_func(void) {
#ifdef USE_SYSTEM_MALLOC
main_pool_init();
gGfxAllocOnlyPool = alloc_only_pool_init();
#else
static u64 pool[0x165000/8 / 4 * sizeof(void *)];
main_pool_init(pool, pool + sizeof(pool) / sizeof(pool[0]));
#endif
gEffectsMemoryPool = mem_pool_init(0x4000, MEMORY_POOL_LEFT);
configfile_load(CONFIG_FILE);
@ -165,6 +171,9 @@ void main_func(void) {
#else
wm_api = &gfx_sdl;
#endif
#elif defined(ENABLE_GFX_DUMMY)
rendering_api = &gfx_dummy_renderer_api;
wm_api = &gfx_dummy_wm_api;
#endif
gfx_init(wm_api, rendering_api, "Super Mario 64 PC-Port", configFullscreen);