Fix pointers after loading level from cart

This commit is contained in:
James Lambert 2022-07-24 16:03:29 -06:00
parent 0a8db5cc0e
commit 20f84f1fd4
9 changed files with 125 additions and 7 deletions

View file

@ -192,7 +192,7 @@ build/src/scene/portal.o: $(MODEL_HEADERS)
## Test Chambers
####################
TEST_CHAMBERS = assets/test_chambers/test_chamber_00/test_chamber_00.blend
TEST_CHAMBERS = assets/test_chambers/test_chamber_00.blend
TEST_CHAMBER_HEADERS = $(TEST_CHAMBERS:%.blend=build/%.h)
TEST_CHAMBER_OBJECTS = $(TEST_CHAMBERS:%.blend=build/%_geo.o)

View file

@ -16,6 +16,8 @@
#define SCHEDULER_PRIORITY 13
#define NUM_FIELDS 1
#define LEVEL_SEGMENT 2
#define DMA_QUEUE_SIZE 200
#define SCENE_SCALE 256

View file

@ -9,6 +9,8 @@ struct GraphicsTask gGraphicsTasks[2];
extern OSMesgQueue gfxFrameMsgQ;
extern OSMesgQueue *schedulerCommandQueue;
void* gLevelSegment;
#if WITH_GFX_VALIDATOR
#include "../../gfxvalidator/validator.h"
#endif
@ -53,6 +55,7 @@ void graphicsCreateTask(struct GraphicsTask* targetTask, GraphicsCallback callba
renderStateInit(renderState, targetTask->framebuffer, zbuffer);
gSPSegment(renderState->dl++, 0, 0);
gSPSegment(renderState->dl++, LEVEL_SEGMENT, gLevelSegment);
gSPDisplayList(renderState->dl++, setup_rspstate);
if (firsttime) {

View file

@ -25,6 +25,8 @@ struct GraphicsTask {
extern struct GraphicsTask gGraphicsTasks[2];
extern Vp fullscreenViewport;
extern void* gLevelSegment;
#define GET_GFX_TYPE(gfx) (_SHIFTR((gfx)->words.w0, 24, 8))
typedef void (*GraphicsCallback)(void* data, struct RenderState* renderState, struct GraphicsTask* task);

View file

@ -0,0 +1,13 @@
#ifndef __LEVEL_METADATA_H__
#define __LEVEL_METADATA_H__
#include "level_definition.h"
struct LevelMetadata {
struct LevelDefinition* levelDefinition;
char* segmentRomStart;
char* segmentRomEnd;
char* segmentStart;
};
#endif

View file

@ -6,6 +6,10 @@
#include "physics/collision_scene.h"
#include "static_render.h"
#include "cutscene_runner.h"
#include "../graphics/graphics.h"
#include "../util/rom.h"
#include "../util/memory.h"
struct LevelDefinition* gCurrentLevel;
u64 gTriggeredCutscenes;
@ -14,12 +18,73 @@ int levelCount() {
return LEVEL_COUNT;
}
#define ADJUST_POINTER_POS(ptr, offset) (void*)((ptr) ? (char*)(ptr) + (offset) : 0)
struct LevelDefinition* levelFixPointers(struct LevelDefinition* from, int pointerOffset) {
struct LevelDefinition* result = ADJUST_POINTER_POS(from, pointerOffset);
result->collisionQuads = ADJUST_POINTER_POS(result->collisionQuads, pointerOffset);
for (int i = 0; i < result->collisionQuadCount; ++i) {
result->collisionQuads[i].collider = ADJUST_POINTER_POS(result->collisionQuads[i].collider, pointerOffset);
result->collisionQuads[i].collider->data = ADJUST_POINTER_POS(result->collisionQuads[i].collider->data, pointerOffset);
result->collisionQuads[i].body = ADJUST_POINTER_POS(result->collisionQuads[i].body, pointerOffset);
result->collisionQuads[i].data = ADJUST_POINTER_POS(result->collisionQuads[i].data, pointerOffset);
}
result->staticContent = ADJUST_POINTER_POS(result->staticContent, pointerOffset);
result->roomStaticMapping = ADJUST_POINTER_POS(result->roomStaticMapping, pointerOffset);
result->staticBoundingBoxes = ADJUST_POINTER_POS(result->staticBoundingBoxes, pointerOffset);
result->portalSurfaces = ADJUST_POINTER_POS(result->portalSurfaces, pointerOffset);
for (int i = 0; i < result->portalSurfaceCount; ++i) {
result->portalSurfaces[i].vertices = ADJUST_POINTER_POS(result->portalSurfaces[i].vertices, pointerOffset);
result->portalSurfaces[i].edges = ADJUST_POINTER_POS(result->portalSurfaces[i].edges, pointerOffset);
result->portalSurfaces[i].gfxVertices = ADJUST_POINTER_POS(result->portalSurfaces[i].gfxVertices, pointerOffset);
}
result->portalSurfaceMappingRange = ADJUST_POINTER_POS(result->portalSurfaceMappingRange, pointerOffset);
result->portalSurfaceMappingIndices = ADJUST_POINTER_POS(result->portalSurfaceMappingIndices, pointerOffset);
result->triggers = ADJUST_POINTER_POS(result->triggers, pointerOffset);
result->cutscenes = ADJUST_POINTER_POS(result->cutscenes, pointerOffset);
for (int i = 0; i < result->cutsceneCount; ++i) {
result->cutscenes[i].steps = ADJUST_POINTER_POS(result->cutscenes[i].steps, pointerOffset);
}
result->locations = ADJUST_POINTER_POS(result->locations, pointerOffset);
result->world.rooms = ADJUST_POINTER_POS(result->world.rooms, pointerOffset);
result->world.doorways = ADJUST_POINTER_POS(result->world.doorways, pointerOffset);
for (int i = 0; i < result->world.roomCount; ++i) {
result->world.rooms[i].quadIndices = ADJUST_POINTER_POS(result->world.rooms[i].quadIndices, pointerOffset);
result->world.rooms[i].cellContents = ADJUST_POINTER_POS(result->world.rooms[i].cellContents, pointerOffset);
result->world.rooms[i].doorwayIndices = ADJUST_POINTER_POS(result->world.rooms[i].doorwayIndices, pointerOffset);
}
result->doors = ADJUST_POINTER_POS(result->doors, pointerOffset);
result->buttons = ADJUST_POINTER_POS(result->buttons, pointerOffset);
result->signalOperators = ADJUST_POINTER_POS(result->signalOperators, pointerOffset);
result->decor = ADJUST_POINTER_POS(result->decor, pointerOffset);
result->fizzlers = ADJUST_POINTER_POS(result->fizzlers, pointerOffset);
result->elevators = ADJUST_POINTER_POS(result->elevators, pointerOffset);
return result;
}
void levelLoad(int index) {
if (index < 0 || index >= LEVEL_COUNT) {
return;
}
gCurrentLevel = gLevelList[index];
struct LevelMetadata* metadata = &gLevelList[index];
void* memory = malloc(metadata->segmentRomEnd - metadata->segmentRomStart);
romCopy(metadata->segmentRomStart, memory, metadata->segmentRomEnd - metadata->segmentRomStart);
gLevelSegment = memory;
gCurrentLevel = levelFixPointers(metadata->levelDefinition, (char*)memory - metadata->segmentStart);
gTriggeredCutscenes = 0;
collisionSceneInit(&gCollisionScene, gCurrentLevel->collisionQuads, gCurrentLevel->collisionQuadCount, &gCurrentLevel->world);

View file

@ -3,11 +3,15 @@ const path = require('path');
const InvalidTokenCharacter = /[^A-Za-z0-9_]/gim;
function generateLD(objectLocation) {
function getSegmentName(objectLocation) {
const levelName = path.basename(objectLocation);
const noExtension = levelName.slice(0, levelName.length - path.extname(levelName).length);
const segmentName = noExtension.replace(InvalidTokenCharacter, '_');
return noExtension.replace(InvalidTokenCharacter, '_');
}
function generateLD(objectLocation) {
const segmentName = getSegmentName(objectLocation);
return `
BEGIN_SEG(${segmentName}, 0x02000000)

View file

@ -7,14 +7,41 @@ function generateInclude(outputLocation, headerLocation) {
const InvalidTokenCharacter = /[^A-Za-z0-9_]/gim;
function getSegmentName(headerLocation) {
const levelName = path.basename(headerLocation);
const noExtension = levelName.slice(0, levelName.length - path.extname(levelName).length);
return noExtension.replace(InvalidTokenCharacter, '_');
}
function generateLevelName(outputLocation, headerLocation) {
const relative = path.relative(path.dirname(outputLocation), headerLocation).slice(0, -2);
return relative.replace(InvalidTokenCharacter, '_') + '_level';
}
function generateMetadata(outputLocation, headerLocation) {
const segmentName = getSegmentName(headerLocation);
return ` {
&${generateLevelName(outputLocation, headerLocation)},
_${segmentName}_geoSegmentRomStart,
_${segmentName}_geoSegmentRomEnd,
_${segmentName}_geoSegmentStart,
},`;
}
function generateExterns(headerLocation) {
const segmentName = getSegmentName(headerLocation);
return `
extern char _${segmentName}_geoSegmentRomStart[];
extern char _${segmentName}_geoSegmentRomEnd[];
extern char _${segmentName}_geoSegmentStart[];
`;
}
function generateLevelList(outputLocation, headerLocations) {
return `struct LevelDefinition* gLevelList[] = {
${headerLocations.map(headerLocation => ` &${generateLevelName(outputLocation, headerLocation)},`).join('\n')}
return `struct LevelMetadata gLevelList[] = {
${headerLocations.map(headerLocation => generateMetadata(outputLocation, headerLocation)).join('\n')}
};
`;
}
@ -23,12 +50,14 @@ function generateData(outputLocation, headerLocations) {
return `#ifndef __BUILD_LEVEL_LIST_H__
#define __BUILD_LEVEL_LIST_H__
#include "levels/level_definition.h"
#include "levels/level_metadata.h"
${headerLocations.map(headerLocation => generateInclude(outputLocation, headerLocation)).join('\n')}
#define LEVEL_COUNT ${headerLocations.length}
${headerLocations.map(generateExterns).join('\n')}
${generateLevelList(outputLocation, headerLocations)}
#endif