Broken runtime

This commit is contained in:
Jan Racek
2026-03-27 13:46:42 +01:00
parent eacbf4de46
commit 090402f71a
25 changed files with 1111 additions and 877 deletions

View File

@@ -9,6 +9,8 @@
#include "luaapi.hh"
#include "loadingscreen.hh"
#include <psyqo/primitives/misc.hh>
#include "lua.h"
using namespace psyqo::trig_literals;
@@ -221,6 +223,11 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc
L.OnSceneCreationEnd();
if (loading && loading->isActive()) loading->updateProgress(gpu, 95);
m_liveDataSize = sceneSetup.liveDataSize;
shrinkBuffer();
if (loading && loading->isActive()) loading->updateProgress(gpu, 100);
}
@@ -605,7 +612,7 @@ void psxsplash::SceneManager::processEnableDisableEvents() {
}
// ============================================================================
// SCENE LOADING (PCdrv multi-scene)
// SCENE LOADING
// ============================================================================
void psxsplash::SceneManager::requestSceneLoad(int sceneIndex) {
@@ -620,42 +627,74 @@ void psxsplash::SceneManager::processPendingSceneLoad() {
m_pendingSceneIndex = -1;
auto& gpu = Renderer::GetInstance().getGPU();
loadScene(gpu, targetIndex, /*isFirstScene=*/false);
}
// Build filename: scene_N.splashpack
void psxsplash::SceneManager::loadScene(psyqo::GPU& gpu, int sceneIndex, bool isFirstScene) {
// Build filename using the active backend's naming convention
char filename[32];
snprintf(filename, sizeof(filename), "scene_%d.splashpack", targetIndex);
FileLoader::BuildSceneFilename(sceneIndex, filename, sizeof(filename));
// Blank the screen immediately so the user doesn't see a frozen frame
gpu.clear(psyqo::Color{.r = 0, .g = 0, .b = 0});
// 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);
ff.rect = psyqo::Rect{0, 256, 320, 240};
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, targetIndex)) {
if (loading.load(gpu, *s_font, sceneIndex)) {
loading.renderInitialAndFree(gpu);
}
}
// 1. Tear down EVERYTHING in the current scene first —
// Lua VM, vector backing storage, audio. This returns as much
// heap memory as possible before any new allocation.
clearScene();
if (!isFirstScene) {
// Tear down EVERYTHING in the current scene first —
// Lua VM, vector backing storage, audio. This returns as much
// heap memory as possible before any new allocation.
clearScene();
// 2. Free old splashpack data BEFORE loading the new one.
// This avoids having both scene buffers in the heap simultaneously,
// which is the primary source of fragmentation that prevents
// the Lua compiler from finding large contiguous blocks.
if (m_currentSceneData) {
SceneLoader::FreeFile(m_currentSceneData);
m_currentSceneData = nullptr;
// Free old splashpack data BEFORE loading the new one.
// This avoids having both scene buffers in the heap simultaneously.
if (m_currentSceneData) {
FileLoader::Get().FreeFile(m_currentSceneData);
m_currentSceneData = nullptr;
}
}
if (loading.isActive()) loading.updateProgress(gpu, 20);
// 3. Allocate new scene data (heap is now maximally consolidated)
// Load scene data — use progress-aware variant so the loading bar
// animates during the (potentially slow) CD-ROM read.
int fileSize = 0;
uint8_t* newData = SceneLoader::LoadFile(filename, fileSize);
uint8_t* newData = nullptr;
if (loading.isActive()) {
struct Ctx { LoadingScreen* ls; psyqo::GPU* gpu; };
Ctx ctx{&loading, &gpu};
FileLoader::LoadProgressInfo progress{
[](uint8_t pct, void* ud) {
auto* c = static_cast<Ctx*>(ud);
c->ls->updateProgress(*c->gpu, pct);
},
&ctx, 20, 30
};
newData = FileLoader::Get().LoadFileSyncWithProgress(
filename, fileSize, &progress);
} else {
newData = FileLoader::Get().LoadFileSync(filename, fileSize);
}
if (!newData && isFirstScene) {
// Fallback: try legacy name for backwards compatibility (PCdrv only)
newData = FileLoader::Get().LoadFileSync("output.bin", fileSize);
}
if (!newData) {
return;
}
@@ -663,9 +702,9 @@ void psxsplash::SceneManager::processPendingSceneLoad() {
if (loading.isActive()) loading.updateProgress(gpu, 30);
m_currentSceneData = newData;
m_currentSceneIndex = targetIndex;
m_currentSceneIndex = sceneIndex;
// 4. Initialize with new data (creates fresh Lua VM inside)
// Initialize with new data (creates fresh Lua VM inside)
InitializeScene(newData, loading.isActive() ? &loading : nullptr);
}
@@ -703,6 +742,58 @@ void psxsplash::SceneManager::clearScene() {
m_sceneType = 0;
}
void psxsplash::SceneManager::shrinkBuffer() {
if (m_liveDataSize == 0 || m_currentSceneData == nullptr) return;
uint8_t* oldBase = m_currentSceneData;
uint8_t* newBase = new uint8_t[m_liveDataSize];
if (!newBase) return;
__builtin_memcpy(newBase, oldBase, m_liveDataSize);
intptr_t delta = reinterpret_cast<intptr_t>(newBase) - reinterpret_cast<intptr_t>(oldBase);
auto reloc = [delta](auto* ptr) -> decltype(ptr) {
if (!ptr) return ptr;
return reinterpret_cast<decltype(ptr)>(reinterpret_cast<intptr_t>(ptr) + delta);
};
for (auto& go : m_gameObjects) {
go = reloc(go);
go->polygons = reloc(go->polygons);
}
for (auto& lf : m_luaFiles) {
lf = reloc(lf);
lf->luaCode = reloc(lf->luaCode);
}
for (auto& name : m_objectNames) name = reloc(name);
for (auto& name : m_audioClipNames) name = reloc(name);
for (auto& inter : m_interactables) inter = reloc(inter);
m_bvh.relocate(delta);
m_worldCollision.relocate(delta);
m_navRegions.relocate(delta);
m_rooms = reloc(m_rooms);
m_portals = reloc(m_portals);
m_roomTriRefs = reloc(m_roomTriRefs);
for (int ci = 0; ci < m_cutsceneCount; ci++) {
auto& cs = m_cutscenes[ci];
cs.name = reloc(cs.name);
cs.audioEvents = reloc(cs.audioEvents);
for (uint8_t ti = 0; ti < cs.trackCount; ti++) {
auto& track = cs.tracks[ti];
track.keyframes = reloc(track.keyframes);
if (track.target) track.target = reloc(track.target);
}
}
m_uiSystem.relocate(delta);
FileLoader::Get().FreeFile(oldBase);
m_currentSceneData = newBase;
}
// ============================================================================
// OBJECT NAME LOOKUP
// ============================================================================