Lua bytecode builder, cdrom fixes
This commit is contained in:
15
Makefile
15
Makefile
@@ -42,5 +42,20 @@ ifeq ($(FPSOVERLAY), 1)
|
|||||||
CPPFLAGS += -DPSXSPLASH_FPSOVERLAY
|
CPPFLAGS += -DPSXSPLASH_FPSOVERLAY
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef OT_SIZE
|
||||||
|
CPPFLAGS += -DOT_SIZE=$(OT_SIZE)
|
||||||
|
endif
|
||||||
|
ifdef BUMP_SIZE
|
||||||
|
CPPFLAGS += -DBUMP_SIZE=$(BUMP_SIZE)
|
||||||
|
endif
|
||||||
|
|
||||||
include third_party/nugget/psyqo-lua/psyqo-lua.mk
|
include third_party/nugget/psyqo-lua/psyqo-lua.mk
|
||||||
include third_party/nugget/psyqo/psyqo.mk
|
include third_party/nugget/psyqo/psyqo.mk
|
||||||
|
|
||||||
|
# Redirect Lua's allocator through our OOM-guarded wrapper
|
||||||
|
LDFLAGS := $(subst psyqo_realloc,lua_oom_realloc,$(LDFLAGS))
|
||||||
|
|
||||||
|
# NOPARSER=1 → Use precompiled bytecode, strip Lua parser from runtime (~25KB savings)
|
||||||
|
ifeq ($(NOPARSER),1)
|
||||||
|
LIBRARIES := $(subst liblua.a,liblua-noparser.a,$(LIBRARIES))
|
||||||
|
endif
|
||||||
|
|||||||
89
src/cdromhelper.hh
Normal file
89
src/cdromhelper.hh
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// CDRomHelper - manages CD-ROM interrupt lifecycle around psyqo's CDRomDevice.
|
||||||
|
//
|
||||||
|
// psyqo's IRQ handler asserts if an interrupt fires with no action
|
||||||
|
// registered (m_action != nullptr check in cdrom-device.cpp:72).
|
||||||
|
// After readSectorsBlocking returns, IMask is re-enabled but no action
|
||||||
|
// is pending. We must mask before any unsolicited interrupt arrives.
|
||||||
|
//
|
||||||
|
// We mask at BOTH levels:
|
||||||
|
// - CPU level (IMask): prevents psyqo's handler from firing
|
||||||
|
// - Controller level (CauseMask=0): prevents the controller from
|
||||||
|
// generating or queueing responses, keeping its state clean
|
||||||
|
//
|
||||||
|
// The motor keeps spinning after Pause (psyqo's read action ends with
|
||||||
|
// CdlPause). This is normal PS1 behavior - PSBW and other homebrew
|
||||||
|
// leave the motor spinning too. We don't send CdlStop because handling
|
||||||
|
// its response correctly while bypassing psyqo's handler is unreliable.
|
||||||
|
|
||||||
|
#if defined(LOADER_CDROM)
|
||||||
|
|
||||||
|
#include <psyqo/hardware/cpu.hh>
|
||||||
|
#include <psyqo/hardware/cdrom.hh>
|
||||||
|
|
||||||
|
namespace psxsplash {
|
||||||
|
|
||||||
|
class CDRomHelper {
|
||||||
|
public:
|
||||||
|
// Call immediately after the last readSectorsBlocking returns.
|
||||||
|
// Masks interrupts at both CPU and controller level.
|
||||||
|
static void SilenceDrive() {
|
||||||
|
// Mask CPU-level IRQ so psyqo's handler can't fire.
|
||||||
|
psyqo::Hardware::CPU::IMask.clear(psyqo::Hardware::CPU::IRQ::CDRom);
|
||||||
|
psyqo::Hardware::CPU::flushWriteQueue();
|
||||||
|
|
||||||
|
// Mask controller-level interrupts. With CauseMask=0 the
|
||||||
|
// controller won't assert the interrupt line or queue
|
||||||
|
// responses. This keeps the controller in a clean state
|
||||||
|
// for the next load, unlike masking only IMask (which
|
||||||
|
// caused unacknowledged responses to pile up and eventually
|
||||||
|
// lock the controller).
|
||||||
|
psyqo::Hardware::CDRom::CauseMask = 0;
|
||||||
|
|
||||||
|
s_silenced = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call before the next file load. Restores the controller to a
|
||||||
|
// clean state ready for psyqo's CDRomDevice to use.
|
||||||
|
// No-op on first scene load (nothing to restore).
|
||||||
|
static void WakeDrive() {
|
||||||
|
if (!s_silenced) return;
|
||||||
|
s_silenced = false;
|
||||||
|
|
||||||
|
// Drain any residual Cause bits while CauseMask is still 0.
|
||||||
|
drainController();
|
||||||
|
|
||||||
|
// Re-enable controller-level interrupts (INT1-5).
|
||||||
|
psyqo::Hardware::CDRom::CauseMask = 0x1f;
|
||||||
|
|
||||||
|
// Drain again: restoring CauseMask may have caused a
|
||||||
|
// pending state to be signaled.
|
||||||
|
drainController();
|
||||||
|
|
||||||
|
// Re-enable CPU-level IRQ for psyqo's handler.
|
||||||
|
psyqo::Hardware::CPU::IMask.set(psyqo::Hardware::CPU::IRQ::CDRom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static inline bool s_silenced = false;
|
||||||
|
|
||||||
|
// Acknowledge and drain any pending interrupt from the CD-ROM
|
||||||
|
// controller. Clears Cause bits, drains the response FIFO, and
|
||||||
|
// clears the CPU IReg flag.
|
||||||
|
static void drainController() {
|
||||||
|
uint8_t cause = psyqo::Hardware::CDRom::Cause;
|
||||||
|
if (cause & 7)
|
||||||
|
psyqo::Hardware::CDRom::Cause = 7;
|
||||||
|
if (cause & 0x18)
|
||||||
|
psyqo::Hardware::CDRom::Cause = 0x18;
|
||||||
|
while (psyqo::Hardware::CDRom::Ctrl.access() & 0x20)
|
||||||
|
psyqo::Hardware::CDRom::Response; // drain FIFO
|
||||||
|
psyqo::Hardware::CPU::IReg.clear(
|
||||||
|
psyqo::Hardware::CPU::IRQ::CDRom);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace psxsplash
|
||||||
|
|
||||||
|
#endif // LOADER_CDROM
|
||||||
140
src/gameobject_bytecode.h
Normal file
140
src/gameobject_bytecode.h
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Pre-compiled PS1 Lua bytecode for GAMEOBJECT_SCRIPT
|
||||||
|
// Generated by luac_psx - do not edit manually
|
||||||
|
// 1581 bytes
|
||||||
|
|
||||||
|
static const unsigned char GAMEOBJECT_BYTECODE[] = {
|
||||||
|
0x1b, 0x4c, 0x75, 0x61, 0x52, 0x00, 0x01, 0x04, 0x04, 0x04, 0x04, 0x01,
|
||||||
|
0x19, 0x93, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00,
|
||||||
|
0x00, 0x1f, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00,
|
||||||
|
0x00, 0x01, 0x00, 0x08, 0x11, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00,
|
||||||
|
0x87, 0x40, 0x40, 0x00, 0xc7, 0x80, 0x40, 0x00, 0x07, 0xc1, 0x40, 0x00,
|
||||||
|
0x47, 0x01, 0x41, 0x00, 0x87, 0x41, 0x41, 0x00, 0x0a, 0x80, 0x41, 0x80,
|
||||||
|
0x0a, 0x80, 0xc1, 0x80, 0x0a, 0x80, 0x41, 0x81, 0x0a, 0x80, 0xc1, 0x81,
|
||||||
|
0x0a, 0x80, 0x41, 0x82, 0x0a, 0x80, 0xc1, 0x82, 0xe5, 0x01, 0x00, 0x00,
|
||||||
|
0x0a, 0xc0, 0x81, 0x83, 0xe5, 0x41, 0x00, 0x00, 0x0a, 0xc0, 0x01, 0x84,
|
||||||
|
0x1f, 0x00, 0x80, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x0d, 0x00, 0x00,
|
||||||
|
0x00, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5f, 0x70,
|
||||||
|
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x04, 0x0b, 0x00, 0x00,
|
||||||
|
0x00, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00,
|
||||||
|
0x04, 0x0b, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x74,
|
||||||
|
0x69, 0x76, 0x65, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74,
|
||||||
|
0x5f, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x59, 0x00, 0x04,
|
||||||
|
0x0e, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x6f, 0x74, 0x61,
|
||||||
|
0x74, 0x69, 0x6f, 0x6e, 0x59, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x00, 0x04, 0x0b, 0x00, 0x00,
|
||||||
|
0x00, 0x5f, 0x5f, 0x6e, 0x65, 0x77, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x05, 0x1e, 0x00, 0x00, 0x00, 0x86, 0x00, 0x40, 0x00, 0xc0,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x9d, 0x80, 0x80, 0x01, 0x58,
|
||||||
|
0x40, 0x40, 0x01, 0x17, 0x00, 0x00, 0x80, 0x9f, 0x00, 0x00, 0x01, 0x18,
|
||||||
|
0x80, 0xc0, 0x00, 0x17, 0x00, 0x01, 0x80, 0xc5, 0x00, 0x80, 0x00, 0x07,
|
||||||
|
0xc1, 0x40, 0x00, 0xde, 0x00, 0x00, 0x01, 0xdf, 0x00, 0x00, 0x00, 0x17,
|
||||||
|
0x00, 0x03, 0x80, 0x18, 0x00, 0xc1, 0x00, 0x17, 0x00, 0x01, 0x80, 0xc5,
|
||||||
|
0x00, 0x00, 0x01, 0x07, 0xc1, 0x40, 0x00, 0xde, 0x00, 0x00, 0x01, 0xdf,
|
||||||
|
0x00, 0x00, 0x00, 0x17, 0x40, 0x01, 0x80, 0x18, 0x40, 0xc1, 0x00, 0x17,
|
||||||
|
0xc0, 0x00, 0x80, 0xc5, 0x00, 0x80, 0x01, 0x07, 0xc1, 0x40, 0x00, 0xde,
|
||||||
|
0x00, 0x00, 0x01, 0xdf, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xdf,
|
||||||
|
0x00, 0x00, 0x01, 0x1f, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04,
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x72, 0x61, 0x77, 0x67, 0x65, 0x74, 0x00, 0x00,
|
||||||
|
0x04, 0x09, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x00, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x63, 0x70, 0x70,
|
||||||
|
0x5f, 0x70, 0x74, 0x72, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x61, 0x63,
|
||||||
|
0x74, 0x69, 0x76, 0x65, 0x00, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x72, 0x6f,
|
||||||
|
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x01, 0x05,
|
||||||
|
0x0f, 0x00, 0x00, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x6f, 0x62, 0x6a, 0x65,
|
||||||
|
0x63, 0x74, 0x2e, 0x6c, 0x75, 0x61, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x11,
|
||||||
|
0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x11,
|
||||||
|
0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12,
|
||||||
|
0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14,
|
||||||
|
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14,
|
||||||
|
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15,
|
||||||
|
0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16,
|
||||||
|
0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17,
|
||||||
|
0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1a,
|
||||||
|
0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x03,
|
||||||
|
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6c, 0x66, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x6b, 0x65, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x72, 0x61, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||||
|
0x5f, 0x45, 0x4e, 0x56, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74,
|
||||||
|
0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x0b, 0x00,
|
||||||
|
0x00, 0x00, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65,
|
||||||
|
0x00, 0x0e, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x6f, 0x74,
|
||||||
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x59, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x29,
|
||||||
|
0x00, 0x00, 0x00, 0x03, 0x00, 0x07, 0x1d, 0x00, 0x00, 0x00, 0x18, 0x00,
|
||||||
|
0xc0, 0x00, 0x17, 0x40, 0x01, 0x80, 0xc5, 0x00, 0x00, 0x00, 0x07, 0x41,
|
||||||
|
0x40, 0x00, 0x40, 0x01, 0x00, 0x01, 0xdd, 0x40, 0x80, 0x01, 0x1f, 0x00,
|
||||||
|
0x80, 0x00, 0x17, 0x80, 0x03, 0x80, 0x18, 0x80, 0xc0, 0x00, 0x17, 0x40,
|
||||||
|
0x01, 0x80, 0xc5, 0x00, 0x80, 0x00, 0x07, 0x41, 0x40, 0x00, 0x40, 0x01,
|
||||||
|
0x00, 0x01, 0xdd, 0x40, 0x80, 0x01, 0x1f, 0x00, 0x80, 0x00, 0x17, 0x80,
|
||||||
|
0x01, 0x80, 0x18, 0xc0, 0xc0, 0x00, 0x17, 0x00, 0x01, 0x80, 0xc5, 0x00,
|
||||||
|
0x00, 0x01, 0x07, 0x41, 0x40, 0x00, 0x40, 0x01, 0x00, 0x01, 0xdd, 0x40,
|
||||||
|
0x80, 0x01, 0x1f, 0x00, 0x80, 0x00, 0xc6, 0x00, 0xc1, 0x01, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x40, 0x01, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0xdd, 0x40,
|
||||||
|
0x00, 0x02, 0x1f, 0x00, 0x80, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x09,
|
||||||
|
0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00,
|
||||||
|
0x04, 0x0a, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x70,
|
||||||
|
0x74, 0x72, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x61, 0x63, 0x74, 0x69,
|
||||||
|
0x76, 0x65, 0x00, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x74, 0x61,
|
||||||
|
0x74, 0x69, 0x6f, 0x6e, 0x59, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x72,
|
||||||
|
0x61, 0x77, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||||
|
0x00, 0x00, 0x01, 0x02, 0x01, 0x04, 0x01, 0x06, 0x00, 0x00, 0x0f, 0x00,
|
||||||
|
0x00, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
|
||||||
|
0x2e, 0x6c, 0x75, 0x61, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
|
||||||
|
0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00,
|
||||||
|
0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
|
||||||
|
0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00,
|
||||||
|
0x00, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
|
||||||
|
0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00,
|
||||||
|
0x00, 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00,
|
||||||
|
0x00, 0x25, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00,
|
||||||
|
0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
|
||||||
|
0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
|
||||||
|
0x00, 0x29, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
|
||||||
|
0x00, 0x73, 0x65, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00,
|
||||||
|
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x79, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x76, 0x61,
|
||||||
|
0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5f,
|
||||||
|
0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x0b, 0x00, 0x00,
|
||||||
|
0x00, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00,
|
||||||
|
0x0e, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x6f, 0x74, 0x61,
|
||||||
|
0x74, 0x69, 0x6f, 0x6e, 0x59, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5f, 0x45,
|
||||||
|
0x4e, 0x56, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
|
||||||
|
0x00, 0x67, 0x61, 0x6d, 0x65, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e,
|
||||||
|
0x6c, 0x75, 0x61, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||||
|
0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
|
||||||
|
0x2a, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||||
|
0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x67, 0x65,
|
||||||
|
0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x73,
|
||||||
|
0x65, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
|
||||||
|
0x67, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x03,
|
||||||
|
0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x73,
|
||||||
|
0x65, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x04, 0x00,
|
||||||
|
0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x67, 0x65,
|
||||||
|
0x74, 0x5f, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x59, 0x00,
|
||||||
|
0x05, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
|
||||||
|
0x73, 0x65, 0x74, 0x5f, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
|
0x59, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||||
|
0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5f, 0x45, 0x4e, 0x56, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x67, 0x61, 0x6d,
|
||||||
|
0x65, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6c, 0x75, 0x61, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
|
||||||
|
0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x00, 0x00, 0x5f, 0x45, 0x4e, 0x56, 0x00,
|
||||||
|
};
|
||||||
59
src/lua.cpp
59
src/lua.cpp
@@ -2,56 +2,27 @@
|
|||||||
|
|
||||||
#include <psyqo-lua/lua.hh>
|
#include <psyqo-lua/lua.hh>
|
||||||
|
|
||||||
|
#include <psyqo/alloc.h>
|
||||||
#include <psyqo/soft-math.hh>
|
#include <psyqo/soft-math.hh>
|
||||||
#include <psyqo/trigonometry.hh>
|
#include <psyqo/trigonometry.hh>
|
||||||
#include <psyqo/xprintf.h>
|
#include <psyqo/xprintf.h>
|
||||||
|
|
||||||
#include "gameobject.hh"
|
#include "gameobject.hh"
|
||||||
|
|
||||||
constexpr const char GAMEOBJECT_SCRIPT[] = R"(
|
// OOM-guarded allocator for Lua. The linker redirects luaI_realloc
|
||||||
return function(metatable)
|
// here instead of straight to psyqo_realloc, so we can log before
|
||||||
local get_position = metatable.get_position
|
// returning NULL.
|
||||||
local set_position = metatable.set_position
|
extern "C" void *lua_oom_realloc(void *ptr, size_t size) {
|
||||||
local get_active = metatable.get_active
|
void *result = psyqo_realloc(ptr, size);
|
||||||
local set_active = metatable.set_active
|
if (!result && size > 0) {
|
||||||
local get_rotationY = metatable.get_rotationY
|
printf("Lua OOM: alloc %u bytes failed\n", (unsigned)size);
|
||||||
local set_rotationY = metatable.set_rotationY
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
metatable.get_position = nil
|
// Pre-compiled PS1 Lua bytecode for the GameObject metatable script.
|
||||||
metatable.set_position = nil
|
// Compiled with luac_psx to avoid needing the Lua parser at runtime.
|
||||||
metatable.get_active = nil
|
#include "gameobject_bytecode.h"
|
||||||
metatable.set_active = nil
|
|
||||||
metatable.get_rotationY = nil
|
|
||||||
metatable.set_rotationY = nil
|
|
||||||
|
|
||||||
function metatable.__index(self, key)
|
|
||||||
local raw = rawget(self, key)
|
|
||||||
if raw ~= nil then return raw end
|
|
||||||
if key == "position" then
|
|
||||||
return get_position(self.__cpp_ptr)
|
|
||||||
elseif key == "active" then
|
|
||||||
return get_active(self.__cpp_ptr)
|
|
||||||
elseif key == "rotationY" then
|
|
||||||
return get_rotationY(self.__cpp_ptr)
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function metatable.__newindex(self, key, value)
|
|
||||||
if key == "position" then
|
|
||||||
set_position(self.__cpp_ptr, value)
|
|
||||||
return
|
|
||||||
elseif key == "active" then
|
|
||||||
set_active(self.__cpp_ptr, value)
|
|
||||||
return
|
|
||||||
elseif key == "rotationY" then
|
|
||||||
set_rotationY(self.__cpp_ptr, value)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
rawset(self, key, value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)";
|
|
||||||
|
|
||||||
// Lua helpers
|
// Lua helpers
|
||||||
|
|
||||||
@@ -149,7 +120,7 @@ static int gameobjectSetRotationY(psyqo::Lua L) {
|
|||||||
void psxsplash::Lua::Init() {
|
void psxsplash::Lua::Init() {
|
||||||
auto L = m_state;
|
auto L = m_state;
|
||||||
// Load and run the game objects script
|
// Load and run the game objects script
|
||||||
if (L.loadBuffer(GAMEOBJECT_SCRIPT, "buffer:gameObjects") == 0) {
|
if (L.loadBuffer(reinterpret_cast<const char*>(GAMEOBJECT_BYTECODE), sizeof(GAMEOBJECT_BYTECODE), "bytecode:gameObjects") == 0) {
|
||||||
if (L.pcall(0, 1) == 0) {
|
if (L.pcall(0, 1) == 0) {
|
||||||
// This will be our metatable
|
// This will be our metatable
|
||||||
L.newTable();
|
L.newTable();
|
||||||
|
|||||||
@@ -37,8 +37,14 @@ class Renderer final {
|
|||||||
Renderer(const Renderer&) = delete;
|
Renderer(const Renderer&) = delete;
|
||||||
Renderer& operator=(const Renderer&) = delete;
|
Renderer& operator=(const Renderer&) = delete;
|
||||||
|
|
||||||
static constexpr size_t ORDERING_TABLE_SIZE = 2048 * 8;
|
#ifndef OT_SIZE
|
||||||
static constexpr size_t BUMP_ALLOCATOR_SIZE = 8096 * 24;
|
#define OT_SIZE (2048 * 8)
|
||||||
|
#endif
|
||||||
|
#ifndef BUMP_SIZE
|
||||||
|
#define BUMP_SIZE (8096 * 24)
|
||||||
|
#endif
|
||||||
|
static constexpr size_t ORDERING_TABLE_SIZE = OT_SIZE;
|
||||||
|
static constexpr size_t BUMP_ALLOCATOR_SIZE = BUMP_SIZE;
|
||||||
static constexpr size_t MAX_VISIBLE_TRIANGLES = 4096;
|
static constexpr size_t MAX_VISIBLE_TRIANGLES = 4096;
|
||||||
|
|
||||||
static constexpr int32_t PROJ_H = 120;
|
static constexpr int32_t PROJ_H = 120;
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
#include <psyqo/primitives/misc.hh>
|
#include <psyqo/primitives/misc.hh>
|
||||||
#include <psyqo/trigonometry.hh>
|
#include <psyqo/trigonometry.hh>
|
||||||
|
|
||||||
|
#if defined(LOADER_CDROM)
|
||||||
|
#include "cdromhelper.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
using namespace psyqo::trig_literals;
|
using namespace psyqo::trig_literals;
|
||||||
@@ -632,6 +636,11 @@ void psxsplash::SceneManager::processPendingSceneLoad() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void psxsplash::SceneManager::loadScene(psyqo::GPU& gpu, int sceneIndex, bool isFirstScene) {
|
void psxsplash::SceneManager::loadScene(psyqo::GPU& gpu, int sceneIndex, bool isFirstScene) {
|
||||||
|
// Restore CD-ROM controller and CPU IRQ state for file loading.
|
||||||
|
#if defined(LOADER_CDROM)
|
||||||
|
CDRomHelper::WakeDrive();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Build filename using the active backend's naming convention
|
// Build filename using the active backend's naming convention
|
||||||
char filename[32];
|
char filename[32];
|
||||||
FileLoader::BuildSceneFilename(sceneIndex, filename, sizeof(filename));
|
FileLoader::BuildSceneFilename(sceneIndex, filename, sizeof(filename));
|
||||||
@@ -698,6 +707,11 @@ void psxsplash::SceneManager::loadScene(psyqo::GPU& gpu, int sceneIndex, bool is
|
|||||||
|
|
||||||
if (loading.isActive()) loading.updateProgress(gpu, 30);
|
if (loading.isActive()) loading.updateProgress(gpu, 30);
|
||||||
|
|
||||||
|
// Stop the CD-ROM motor and mask all interrupts for gameplay.
|
||||||
|
#if defined(LOADER_CDROM)
|
||||||
|
CDRomHelper::SilenceDrive();
|
||||||
|
#endif
|
||||||
|
|
||||||
m_currentSceneData = newData;
|
m_currentSceneData = newData;
|
||||||
m_currentSceneIndex = sceneIndex;
|
m_currentSceneIndex = sceneIndex;
|
||||||
|
|
||||||
|
|||||||
34
tools/luac_psx/Makefile
Normal file
34
tools/luac_psx/Makefile
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# luac_psx - PS1 Lua bytecode compiler
|
||||||
|
#
|
||||||
|
# Minimal PS1 executable that compiles Lua source to bytecode.
|
||||||
|
# Links only psyqo (allocator, xprintf) and psxlua (full parser).
|
||||||
|
# No psxsplash code, no renderer, no GPU.
|
||||||
|
|
||||||
|
TARGET = luac_psx
|
||||||
|
TYPE = ps-exe
|
||||||
|
|
||||||
|
SRCS = main.c
|
||||||
|
|
||||||
|
# Relative path to nugget root
|
||||||
|
NUGGETDIR = ../../third_party/nugget
|
||||||
|
|
||||||
|
# Lua library (full parser variant - NOT noparser)
|
||||||
|
LUADIR = $(NUGGETDIR)/third_party/psxlua/src
|
||||||
|
LIBRARIES += $(LUADIR)/liblua.a
|
||||||
|
|
||||||
|
# Include paths
|
||||||
|
CPPFLAGS += -I$(LUADIR)
|
||||||
|
CPPFLAGS += -I$(NUGGETDIR)
|
||||||
|
CPPFLAGS += -DLUA_TARGET_PSX
|
||||||
|
|
||||||
|
# psyqo build system (provides libpsyqo.a, linker scripts, toolchain config)
|
||||||
|
include $(NUGGETDIR)/psyqo/psyqo.mk
|
||||||
|
|
||||||
|
# Build liblua.a if not already built
|
||||||
|
$(LUADIR)/liblua.a:
|
||||||
|
$(MAKE) -C $(NUGGETDIR)/third_party/psxlua psx
|
||||||
|
|
||||||
|
clean::
|
||||||
|
$(MAKE) -C $(NUGGETDIR)/third_party/psxlua clean
|
||||||
|
|
||||||
|
.PHONY: $(LUADIR)/liblua.a
|
||||||
324
tools/luac_psx/main.c
Normal file
324
tools/luac_psx/main.c
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
/*
|
||||||
|
* luac_psx - PS1 Lua bytecode compiler
|
||||||
|
*
|
||||||
|
* A minimal PS1 executable that reads Lua source files via PCdrv,
|
||||||
|
* compiles them using psxlua's compiler, and writes bytecode back
|
||||||
|
* via PCdrv. Designed to run inside PCSX-Redux headless mode as
|
||||||
|
* a build tool.
|
||||||
|
*
|
||||||
|
* Links only psyqo (allocator) and psxlua (full parser). No game
|
||||||
|
* code, no renderer, no GPU.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "pcdrv.h"
|
||||||
|
|
||||||
|
#include "lua.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
|
||||||
|
/* Internal headers for luaU_dump (supports strip parameter) */
|
||||||
|
#include "lobject.h"
|
||||||
|
#include "lstate.h"
|
||||||
|
#include "lundump.h"
|
||||||
|
|
||||||
|
/* psyqo's xprintf provides sprintf/printf via PS1 syscalls */
|
||||||
|
#include <psyqo/xprintf.h>
|
||||||
|
|
||||||
|
/* psyqo allocator - provides psyqo_realloc and psyqo_free */
|
||||||
|
#include <psyqo/alloc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lua runtime support functions.
|
||||||
|
*
|
||||||
|
* psxlua declares these as extern in llibc.h when LUA_TARGET_PSX
|
||||||
|
* is defined. Normally they're provided via linker --defsym redirects
|
||||||
|
* to psyqo functions, but we define them directly here.
|
||||||
|
*/
|
||||||
|
int luaI_sprintf(char *str, const char *format, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int ret = vsprintf(str, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void luaI_free(void *ptr) {
|
||||||
|
psyqo_free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *luaI_realloc(void *ptr, size_t size) {
|
||||||
|
return psyqo_realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maximum source file size: 256KB should be plenty */
|
||||||
|
#define MAX_SOURCE_SIZE (256 * 1024)
|
||||||
|
|
||||||
|
/* Maximum bytecode output size */
|
||||||
|
#define MAX_OUTPUT_SIZE (256 * 1024)
|
||||||
|
|
||||||
|
/* Maximum manifest line length */
|
||||||
|
#define MAX_LINE_LEN 256
|
||||||
|
|
||||||
|
/* Bytecode writer state */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t *buf;
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
} WriterState;
|
||||||
|
|
||||||
|
/* lua_dump writer callback - accumulates bytecode into a buffer */
|
||||||
|
static int bytecode_writer(lua_State *L, const void *p, size_t sz, void *ud) {
|
||||||
|
WriterState *ws = (WriterState *)ud;
|
||||||
|
if (ws->size + sz > ws->capacity) {
|
||||||
|
printf("ERROR: bytecode output exceeds buffer capacity\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* memcpy via byte loop - no libc on PS1 */
|
||||||
|
const uint8_t *src = (const uint8_t *)p;
|
||||||
|
uint8_t *dst = ws->buf + ws->size;
|
||||||
|
for (size_t i = 0; i < sz; i++) {
|
||||||
|
dst[i] = src[i];
|
||||||
|
}
|
||||||
|
ws->size += sz;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read an entire file via PCdrv into a buffer. Returns bytes read, or -1 on error. */
|
||||||
|
static int read_file(const char *path, char *buf, int max_size) {
|
||||||
|
int fd = PCopen(path, 0, 0); /* O_RDONLY = 0 */
|
||||||
|
if (fd < 0) {
|
||||||
|
printf("ERROR: cannot open '%s'\n", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int total = 0;
|
||||||
|
while (total < max_size) {
|
||||||
|
int chunk = max_size - total;
|
||||||
|
if (chunk > 2048) chunk = 2048; /* read in 2KB chunks */
|
||||||
|
int n = PCread(fd, buf + total, chunk);
|
||||||
|
if (n <= 0) break;
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
PCclose(fd);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a buffer to a file via PCdrv. Returns 0 on success, -1 on error. */
|
||||||
|
static int write_file(const char *path, const void *buf, int size) {
|
||||||
|
int fd = PCcreat(path, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
printf("ERROR: cannot create '%s'\n", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *p = (const uint8_t *)buf;
|
||||||
|
int remaining = size;
|
||||||
|
while (remaining > 0) {
|
||||||
|
int chunk = remaining;
|
||||||
|
if (chunk > 2048) chunk = 2048; /* write in 2KB chunks */
|
||||||
|
int n = PCwrite(fd, p, chunk);
|
||||||
|
if (n < 0) {
|
||||||
|
printf("ERROR: write failed for '%s'\n", path);
|
||||||
|
PCclose(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p += n;
|
||||||
|
remaining -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
PCclose(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simple strlen - no libc on PS1 */
|
||||||
|
static int str_len(const char *s) {
|
||||||
|
int n = 0;
|
||||||
|
while (s[n]) n++;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error log buffer - accumulates error messages for the sentinel file */
|
||||||
|
static char error_log[4096];
|
||||||
|
static int error_log_len = 0;
|
||||||
|
|
||||||
|
static void error_log_append(const char *msg) {
|
||||||
|
int len = str_len(msg);
|
||||||
|
if (error_log_len + len + 1 < (int)sizeof(error_log)) {
|
||||||
|
const char *src = msg;
|
||||||
|
char *dst = error_log + error_log_len;
|
||||||
|
while (*src) *dst++ = *src++;
|
||||||
|
*dst++ = '\n';
|
||||||
|
*dst = '\0';
|
||||||
|
error_log_len += len + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the sentinel file to signal completion */
|
||||||
|
static void write_sentinel(const char *status) {
|
||||||
|
/* For errors, write the error log as sentinel content */
|
||||||
|
if (str_len(status) == 5 && status[0] == 'E') {
|
||||||
|
/* "ERROR" - write error details */
|
||||||
|
if (error_log_len > 0)
|
||||||
|
write_file("__done__", error_log, error_log_len);
|
||||||
|
else
|
||||||
|
write_file("__done__", status, str_len(status));
|
||||||
|
} else {
|
||||||
|
write_file("__done__", status, str_len(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse the next line from the manifest buffer. Returns line length, or -1 at end. */
|
||||||
|
static int next_line(const char *buf, int buf_len, int *pos, char *line, int max_line) {
|
||||||
|
if (*pos >= buf_len) return -1;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (*pos < buf_len && i < max_line - 1) {
|
||||||
|
char c = buf[*pos];
|
||||||
|
(*pos)++;
|
||||||
|
if (c == '\n') break;
|
||||||
|
if (c == '\r') continue; /* skip CR */
|
||||||
|
line[i++] = c;
|
||||||
|
}
|
||||||
|
line[i] = '\0';
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compile a single Lua source file to bytecode */
|
||||||
|
static int compile_file(const char *input_path, const char *output_path,
|
||||||
|
char *source_buf, uint8_t *output_buf) {
|
||||||
|
printf(" %s -> %s\n", input_path, output_path);
|
||||||
|
|
||||||
|
/* Read source */
|
||||||
|
int source_len = read_file(input_path, source_buf, MAX_SOURCE_SIZE);
|
||||||
|
if (source_len < 0) {
|
||||||
|
error_log_append("ERROR: cannot open source file");
|
||||||
|
error_log_append(input_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a fresh Lua state for each file to avoid accumulating memory */
|
||||||
|
lua_State *L = luaL_newstate();
|
||||||
|
if (!L) {
|
||||||
|
printf("ERROR: cannot create Lua state (out of memory)\n");
|
||||||
|
error_log_append("ERROR: cannot create Lua state (out of memory)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compile source to bytecode */
|
||||||
|
int status = luaL_loadbuffer(L, source_buf, source_len, input_path);
|
||||||
|
if (status != LUA_OK) {
|
||||||
|
const char *err = lua_tostring(L, -1);
|
||||||
|
if (err) {
|
||||||
|
printf("ERROR: %s\n", err);
|
||||||
|
error_log_append(err);
|
||||||
|
} else {
|
||||||
|
printf("ERROR: compilation failed for '%s'\n", input_path);
|
||||||
|
error_log_append("ERROR: compilation failed");
|
||||||
|
error_log_append(input_path);
|
||||||
|
}
|
||||||
|
lua_close(L);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dump bytecode (strip debug info to save space) */
|
||||||
|
WriterState ws;
|
||||||
|
ws.buf = output_buf;
|
||||||
|
ws.size = 0;
|
||||||
|
ws.capacity = MAX_OUTPUT_SIZE;
|
||||||
|
|
||||||
|
/* Use luaU_dump directly with strip=1 to remove debug info (line numbers,
|
||||||
|
* local variable names, source filename). Saves significant space. */
|
||||||
|
status = luaU_dump(L, getproto(L->top - 1), bytecode_writer, &ws, 1);
|
||||||
|
lua_close(L);
|
||||||
|
|
||||||
|
if (status != 0) {
|
||||||
|
printf("ERROR: bytecode dump failed for '%s'\n", input_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write bytecode to output file */
|
||||||
|
if (write_file(output_path, ws.buf, ws.size) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" OK (%d bytes source -> %d bytes bytecode)\n", source_len, (int)ws.size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
/* Initialize PCdrv */
|
||||||
|
PCinit();
|
||||||
|
|
||||||
|
printf("luac_psx: PS1 Lua bytecode compiler\n");
|
||||||
|
|
||||||
|
/* Allocate work buffers */
|
||||||
|
char *source_buf = (char *)psyqo_realloc(NULL, MAX_SOURCE_SIZE);
|
||||||
|
uint8_t *output_buf = (uint8_t *)psyqo_realloc(NULL, MAX_OUTPUT_SIZE);
|
||||||
|
char *manifest_buf = (char *)psyqo_realloc(NULL, MAX_SOURCE_SIZE);
|
||||||
|
|
||||||
|
if (!source_buf || !output_buf || !manifest_buf) {
|
||||||
|
printf("ERROR: cannot allocate work buffers\n");
|
||||||
|
write_sentinel("ERROR");
|
||||||
|
while (1) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read manifest file */
|
||||||
|
int manifest_len = read_file("manifest.txt", manifest_buf, MAX_SOURCE_SIZE);
|
||||||
|
if (manifest_len < 0) {
|
||||||
|
printf("ERROR: cannot read manifest.txt\n");
|
||||||
|
write_sentinel("ERROR");
|
||||||
|
while (1) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process manifest: pairs of lines (input, output) */
|
||||||
|
int pos = 0;
|
||||||
|
int file_count = 0;
|
||||||
|
int error_count = 0;
|
||||||
|
char input_path[MAX_LINE_LEN];
|
||||||
|
char output_path[MAX_LINE_LEN];
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
/* Read input path */
|
||||||
|
int len = next_line(manifest_buf, manifest_len, &pos, input_path, MAX_LINE_LEN);
|
||||||
|
if (len < 0) break;
|
||||||
|
if (len == 0) continue; /* skip blank lines */
|
||||||
|
|
||||||
|
/* Read output path */
|
||||||
|
len = next_line(manifest_buf, manifest_len, &pos, output_path, MAX_LINE_LEN);
|
||||||
|
if (len <= 0) {
|
||||||
|
printf("ERROR: manifest has unpaired entry for '%s'\n", input_path);
|
||||||
|
error_count++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compile */
|
||||||
|
if (compile_file(input_path, output_path, source_buf, output_buf) != 0) {
|
||||||
|
error_count++;
|
||||||
|
break; /* stop on first error */
|
||||||
|
}
|
||||||
|
file_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up */
|
||||||
|
psyqo_free(source_buf);
|
||||||
|
psyqo_free(output_buf);
|
||||||
|
psyqo_free(manifest_buf);
|
||||||
|
|
||||||
|
/* Write sentinel */
|
||||||
|
if (error_count > 0) {
|
||||||
|
printf("FAILED: %d file(s) compiled, %d error(s)\n", file_count, error_count);
|
||||||
|
write_sentinel("ERROR");
|
||||||
|
} else {
|
||||||
|
printf("SUCCESS: %d file(s) compiled\n", file_count);
|
||||||
|
write_sentinel("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Halt - PCSX-Redux will kill us */
|
||||||
|
while (1) {}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
99
tools/luac_psx/pcdrv.h
Normal file
99
tools/luac_psx/pcdrv.h
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 PCSX-Redux authors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
static inline int PCinit() {
|
||||||
|
register int r asm("v0");
|
||||||
|
__asm__ volatile("break 0, 0x101\n" : "=r"(r));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int PCcreat(const char *name, int perms) {
|
||||||
|
register const char *a0 asm("a0") = name;
|
||||||
|
register const char *a1 asm("a1") = name;
|
||||||
|
register int a2 asm("a2") = 0;
|
||||||
|
register int v0 asm("v0");
|
||||||
|
register int v1 asm("v1");
|
||||||
|
__asm__ volatile("break 0, 0x102\n" : "=r"(v0), "=r"(v1) : "r"(a0), "r"(a1), "r"(a2));
|
||||||
|
if (v0 == 0) return v1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int PCopen(const char *name, int flags, int perms) {
|
||||||
|
register int a2 asm("a2") = flags;
|
||||||
|
register const char *a0 asm("a0") = name;
|
||||||
|
register const char *a1 asm("a1") = name;
|
||||||
|
register int v0 asm("v0");
|
||||||
|
register int v1 asm("v1");
|
||||||
|
__asm__ volatile("break 0, 0x103\n" : "=r"(v0), "=r"(v1) : "r"(a0), "r"(a1), "r"(a2));
|
||||||
|
if (v0 == 0) return v1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int PCclose(int fd) {
|
||||||
|
register int a0 asm("a0") = fd;
|
||||||
|
register int a1 asm("a1") = fd;
|
||||||
|
register int v0 asm("v0");
|
||||||
|
__asm__ volatile("break 0, 0x104\n" : "=r"(v0) : "r"(a0), "r"(a1) : "v1");
|
||||||
|
return v0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int PCread(int fd, void *buf, int len) {
|
||||||
|
register int a0 asm("a0") = 0;
|
||||||
|
register int a1 asm("a1") = fd;
|
||||||
|
register int a2 asm("a2") = len;
|
||||||
|
register void *a3 asm("a3") = buf;
|
||||||
|
register int v0 asm("v0");
|
||||||
|
register int v1 asm("v1");
|
||||||
|
__asm__ volatile("break 0, 0x105\n" : "=r"(v0), "=r"(v1) : "r"(a0), "r"(a1), "r"(a2), "r"(a3) : "memory");
|
||||||
|
if (v0 == 0) return v1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int PCwrite(int fd, const void *buf, int len) {
|
||||||
|
register int a0 asm("a0") = 0;
|
||||||
|
register int a1 asm("a1") = fd;
|
||||||
|
register int a2 asm("a2") = len;
|
||||||
|
register const void *a3 asm("a3") = buf;
|
||||||
|
register int v0 asm("v0");
|
||||||
|
register int v1 asm("v1");
|
||||||
|
__asm__ volatile("break 0, 0x106\n" : "=r"(v0), "=r"(v1) : "r"(a0), "r"(a1), "r"(a2), "r"(a3));
|
||||||
|
if (v0 == 0) return v1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int PClseek(int fd, int offset, int wheel) {
|
||||||
|
register int a3 asm("a3") = wheel;
|
||||||
|
register int a2 asm("a2") = offset;
|
||||||
|
register int a0 asm("a0") = fd;
|
||||||
|
register int a1 asm("a1") = fd;
|
||||||
|
register int v0 asm("v0");
|
||||||
|
register int v1 asm("v1");
|
||||||
|
__asm__ volatile("break 0, 0x107\n" : "=r"(v0), "=r"(v1) : "r"(a0), "r"(a1), "r"(a2), "r"(a3));
|
||||||
|
if (v0 == 0) return v1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user