cleanup
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include "profiler.hh"
|
||||
#include "renderer.hh"
|
||||
#include "splashpack.hh"
|
||||
#include "streq.hh"
|
||||
#include "luaapi.hh"
|
||||
#include "loadingscreen.hh"
|
||||
|
||||
@@ -163,24 +164,21 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc
|
||||
|
||||
m_playerHeight = sceneSetup.playerHeight;
|
||||
|
||||
// Load movement parameters from splashpack (v8+)
|
||||
m_controls.setMoveSpeed(sceneSetup.moveSpeed);
|
||||
m_controls.setSprintSpeed(sceneSetup.sprintSpeed);
|
||||
m_playerRadius = (int32_t)sceneSetup.playerRadius.value;
|
||||
if (m_playerRadius == 0) m_playerRadius = PLAYER_RADIUS; // fallback to default
|
||||
if (m_playerRadius == 0) m_playerRadius = PLAYER_RADIUS;
|
||||
m_jumpVelocityRaw = (int32_t)sceneSetup.jumpVelocity.value;
|
||||
int32_t gravityRaw = (int32_t)sceneSetup.gravity.value;
|
||||
m_gravityPerFrame = gravityRaw / 30; // Convert per-second² to per-frame velocity change
|
||||
if (m_gravityPerFrame == 0 && gravityRaw > 0) m_gravityPerFrame = 1; // Ensure nonzero
|
||||
m_gravityPerFrame = gravityRaw / 30;
|
||||
if (m_gravityPerFrame == 0 && gravityRaw > 0) m_gravityPerFrame = 1;
|
||||
m_velocityY = 0;
|
||||
m_isGrounded = true;
|
||||
m_lastFrameTime = 0;
|
||||
m_deltaFrames = 1;
|
||||
|
||||
// Initialize collision system
|
||||
m_collisionSystem.init();
|
||||
|
||||
// Register colliders from splashpack data
|
||||
for (size_t i = 0; i < sceneSetup.colliders.size(); i++) {
|
||||
SPLASHPACKCollider* collider = sceneSetup.colliders[i];
|
||||
if (collider == nullptr) continue;
|
||||
@@ -203,7 +201,6 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc
|
||||
);
|
||||
}
|
||||
|
||||
// Register trigger boxes from splashpack data
|
||||
for (size_t i = 0; i < sceneSetup.triggerBoxes.size(); i++) {
|
||||
SPLASHPACKTriggerBox* tb = sceneSetup.triggerBoxes[i];
|
||||
if (tb == nullptr) continue;
|
||||
@@ -219,9 +216,7 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc
|
||||
m_collisionSystem.registerTriggerBox(bounds, tb->luaFileIndex);
|
||||
}
|
||||
|
||||
// Load Lua files - order is important here. We need
|
||||
// to load the Lua files before we register the game objects,
|
||||
// as the game objects may reference Lua files by index.
|
||||
|
||||
for (int i = 0; i < m_luaFiles.size(); i++) {
|
||||
auto luaFile = m_luaFiles[i];
|
||||
L.LoadLuaFile(luaFile->luaCode, luaFile->length, i);
|
||||
@@ -233,7 +228,6 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc
|
||||
|
||||
L.OnSceneCreationStart();
|
||||
|
||||
// Register game objects
|
||||
for (auto object : m_gameObjects) {
|
||||
L.RegisterGameObject(object);
|
||||
}
|
||||
@@ -255,34 +249,25 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc
|
||||
void psxsplash::SceneManager::GameTick(psyqo::GPU &gpu) {
|
||||
LuaAPI::IncrementFrameCount();
|
||||
|
||||
// Tick cutscene player (advance frame and apply tracks before rendering)
|
||||
m_cutscenePlayer.tick();
|
||||
|
||||
// Delta-time measurement: count elapsed frames based on gpu timer
|
||||
// PS1 NTSC frame = ~33333 microseconds (30fps vsync)
|
||||
{
|
||||
uint32_t now = gpu.now();
|
||||
if (m_lastFrameTime != 0) {
|
||||
uint32_t elapsed = now - m_lastFrameTime;
|
||||
// 33333us per frame at 30fps. If >50000us, we dropped a frame.
|
||||
m_deltaFrames = (elapsed > 50000) ? 2 : 1;
|
||||
if (elapsed > 83000) m_deltaFrames = 3; // Two frames dropped
|
||||
if (elapsed > 83000) m_deltaFrames = 3;
|
||||
}
|
||||
m_lastFrameTime = now;
|
||||
}
|
||||
|
||||
uint32_t renderingStart = gpu.now();
|
||||
auto& renderer = psxsplash::Renderer::GetInstance();
|
||||
// Dispatch render path based on scene type.
|
||||
// Interior scenes (type 1) use room/portal occlusion; exterior scenes use BVH culling.
|
||||
if (m_sceneType == 1 && m_roomCount > 0 && m_rooms != nullptr) {
|
||||
// Determine which room the camera is in for portal culling.
|
||||
// During cutscene playback the camera may be elsewhere from the player,
|
||||
// so use the actual camera position to find the room.
|
||||
|
||||
int camRoom = -1;
|
||||
if (m_navRegions.isLoaded()) {
|
||||
if (m_cutscenePlayer.isPlaying()) {
|
||||
// Camera-driven: look up nav region from camera world position
|
||||
auto& camPos = m_currentCamera.GetPosition();
|
||||
uint16_t camRegion = m_navRegions.findRegion(camPos.x.value, camPos.z.value);
|
||||
if (camRegion != NAV_NO_REGION) {
|
||||
@@ -290,7 +275,6 @@ void psxsplash::SceneManager::GameTick(psyqo::GPU &gpu) {
|
||||
if (ri != 0xFF) camRoom = (int)ri;
|
||||
}
|
||||
} else if (m_playerNavRegion != NAV_NO_REGION) {
|
||||
// Normal gameplay: use cached player nav region
|
||||
uint8_t ri = m_navRegions.getRoomIndex(m_playerNavRegion);
|
||||
if (ri != 0xFF) camRoom = (int)ri;
|
||||
}
|
||||
@@ -308,10 +292,8 @@ void psxsplash::SceneManager::GameTick(psyqo::GPU &gpu) {
|
||||
psxsplash::debug::Profiler::getInstance().setSectionTime(psxsplash::debug::PROFILER_RENDERING, renderingTime);
|
||||
#endif
|
||||
|
||||
// Collision detection
|
||||
uint32_t collisionStart = gpu.now();
|
||||
|
||||
// Build player AABB from position + radius/height
|
||||
AABB playerAABB;
|
||||
{
|
||||
psyqo::FixedPoint<12> r;
|
||||
@@ -327,7 +309,6 @@ void psxsplash::SceneManager::GameTick(psyqo::GPU &gpu) {
|
||||
psyqo::Vec3 pushBack;
|
||||
int collisionCount = m_collisionSystem.detectCollisions(playerAABB, pushBack);
|
||||
|
||||
// Apply push-back to player position
|
||||
{
|
||||
psyqo::FixedPoint<12> zero;
|
||||
if (pushBack.x != zero || pushBack.z != zero) {
|
||||
@@ -426,9 +407,7 @@ void psxsplash::SceneManager::GameTick(psyqo::GPU &gpu) {
|
||||
|
||||
uint32_t navmeshStart = gpu.now();
|
||||
if (!freecam) {
|
||||
// Priority: WorldCollision + NavRegions (v7) > NavGrid (v5) > Legacy Navmesh
|
||||
if (m_worldCollision.isLoaded()) {
|
||||
// Move-and-slide against world geometry (XZ walls only)
|
||||
psyqo::Vec3 slid = m_worldCollision.moveAndSlide(
|
||||
oldPlayerPosition, m_playerPosition, m_playerRadius, 0xFF);
|
||||
|
||||
@@ -664,9 +643,6 @@ void psxsplash::SceneManager::loadScene(psyqo::GPU& gpu, int sceneIndex, bool is
|
||||
char filename[32];
|
||||
FileLoader::BuildSceneFilename(sceneIndex, filename, sizeof(filename));
|
||||
|
||||
// Blank BOTH framebuffers so the user doesn't see the BIOS screen
|
||||
// or a frozen frame. FastFill ignores the scissor/DrawingArea so we
|
||||
// can target any VRAM region directly.
|
||||
psyqo::Prim::FastFill ff(psyqo::Color{.r = 0, .g = 0, .b = 0});
|
||||
ff.rect = psyqo::Rect{0, 0, 320, 240};
|
||||
gpu.sendPrimitive(ff);
|
||||
@@ -674,7 +650,6 @@ void psxsplash::SceneManager::loadScene(psyqo::GPU& gpu, int sceneIndex, bool is
|
||||
gpu.sendPrimitive(ff);
|
||||
gpu.pumpCallbacks();
|
||||
|
||||
// Try to load a loading screen for the target scene
|
||||
LoadingScreen loading;
|
||||
if (s_font) {
|
||||
if (loading.load(gpu, *s_font, sceneIndex)) {
|
||||
@@ -742,9 +717,7 @@ void psxsplash::SceneManager::clearScene() {
|
||||
// (bytecode, strings, tables, registry) in one shot via lua_close.
|
||||
L.Shutdown();
|
||||
|
||||
// 2. Free vector BACKING STORAGE (not just contents).
|
||||
// clear() only sets size=0 but keeps the allocated capacity.
|
||||
// swap-with-empty releases the heap blocks so they can be coalesced.
|
||||
// 2. Clear all vectors to free their heap storage (game objects, Lua files, names, etc)
|
||||
{ eastl::vector<GameObject*> tmp; tmp.swap(m_gameObjects); }
|
||||
{ eastl::vector<LuaFile*> tmp; tmp.swap(m_luaFiles); }
|
||||
{ eastl::vector<const char*> tmp; tmp.swap(m_objectNames); }
|
||||
@@ -775,12 +748,10 @@ void psxsplash::SceneManager::shrinkBuffer() {
|
||||
if (m_liveDataSize == 0 || m_currentSceneData == nullptr) return;
|
||||
|
||||
uint8_t* oldBase = m_currentSceneData;
|
||||
// Allocate the shrunk buffer. The volatile cast prevents the compiler
|
||||
// from assuming operator new never returns NULL (it does with
|
||||
// -fno-exceptions), which would let it optimize away the null check.
|
||||
|
||||
uint8_t* volatile newBaseV = new uint8_t[m_liveDataSize];
|
||||
uint8_t* newBase = newBaseV;
|
||||
if (!newBase) return; // Heap exhausted — keep the full buffer
|
||||
if (!newBase) return;
|
||||
__builtin_memcpy(newBase, oldBase, m_liveDataSize);
|
||||
|
||||
intptr_t delta = reinterpret_cast<intptr_t>(newBase) - reinterpret_cast<intptr_t>(oldBase);
|
||||
@@ -823,11 +794,6 @@ void psxsplash::SceneManager::shrinkBuffer() {
|
||||
|
||||
m_uiSystem.relocate(delta);
|
||||
|
||||
// Re-key Lua registry entries for game objects. RegisterGameObject stored
|
||||
// lightuserdata keys using the OLD buffer addresses. After relocation, the
|
||||
// game object pointers changed but the registry keys are stale. Without
|
||||
// this, Entity.Find/FindByIndex return nil (wrong key), and in release
|
||||
// builds (-Os) the optimizer can turn this into a hard crash.
|
||||
if (!m_gameObjects.empty()) {
|
||||
L.RelocateGameObjects(
|
||||
reinterpret_cast<GameObject**>(m_gameObjects.data()),
|
||||
@@ -842,16 +808,11 @@ void psxsplash::SceneManager::shrinkBuffer() {
|
||||
// OBJECT NAME LOOKUP
|
||||
// ============================================================================
|
||||
|
||||
// Inline streq (no libc on bare-metal PS1)
|
||||
static bool name_eq(const char* a, const char* b) {
|
||||
while (*a && *b) { if (*a++ != *b++) return false; }
|
||||
return *a == *b;
|
||||
}
|
||||
|
||||
psxsplash::GameObject* psxsplash::SceneManager::findObjectByName(const char* name) const {
|
||||
if (!name || m_objectNames.empty()) return nullptr;
|
||||
for (size_t i = 0; i < m_objectNames.size() && i < m_gameObjects.size(); i++) {
|
||||
if (m_objectNames[i] && name_eq(m_objectNames[i], name)) {
|
||||
if (m_objectNames[i] && streq(m_objectNames[i], name)) {
|
||||
return m_gameObjects[i];
|
||||
}
|
||||
}
|
||||
@@ -861,7 +822,7 @@ psxsplash::GameObject* psxsplash::SceneManager::findObjectByName(const char* nam
|
||||
int psxsplash::SceneManager::findAudioClipByName(const char* name) const {
|
||||
if (!name || m_audioClipNames.empty()) return -1;
|
||||
for (size_t i = 0; i < m_audioClipNames.size(); i++) {
|
||||
if (m_audioClipNames[i] && name_eq(m_audioClipNames[i], name)) {
|
||||
if (m_audioClipNames[i] && streq(m_audioClipNames[i], name)) {
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user