fixup luadevice binding a bit
This commit is contained in:
parent
edc5def251
commit
1d0830160b
|
@ -26,7 +26,7 @@ if SERVER then
|
|||
print("size property is " .. device.Size)
|
||||
|
||||
function device:Clock()
|
||||
print("a")
|
||||
print(self.Base)
|
||||
end
|
||||
|
||||
function device:Peek(address)
|
||||
|
@ -59,7 +59,7 @@ end
|
|||
cpu:Cycle();cpu:Cycle();cpu:Cycle();cpu:Cycle();
|
||||
cpu:Cycle();cpu:Cycle();cpu:Cycle();cpu:Cycle();
|
||||
cpu:Cycle();cpu:Cycle();cpu:Cycle();cpu:Cycle();
|
||||
]]
|
||||
--]]
|
||||
|
||||
AddCSLuaFile("entities/gmod_lcpu_cpu.lua")
|
||||
end
|
||||
|
|
|
@ -4,40 +4,43 @@
|
|||
#include "LuaCpu.hpp"
|
||||
#include "LuaDevice.hpp"
|
||||
|
||||
LUA_FUNCTION(LCPUNative_CreateCPU) {
|
||||
LUA->CheckType(1, GarrysMod::Lua::Type::Number);
|
||||
auto memorySize = static_cast<u32>(LUA->GetNumber(1));
|
||||
namespace lcpu {
|
||||
LUA_FUNCTION(LCPUNative_CreateCPU) {
|
||||
LUA->CheckType(1, GarrysMod::Lua::Type::Number);
|
||||
auto memorySize = static_cast<u32>(LUA->GetNumber(1));
|
||||
|
||||
// TODO: There's probably a way to like, ensure a per-player max.
|
||||
if(memorySize > (64 * 1024 * 1024))
|
||||
LUA->ThrowError("Over RAM size limit.");
|
||||
// TODO: There's probably a way to like, ensure a per-player max.
|
||||
if(memorySize > (64 * 1024 * 1024))
|
||||
LUA->ThrowError("Over RAM size limit.");
|
||||
|
||||
LuaCpu::Create(LUA, memorySize);
|
||||
return 1;
|
||||
}
|
||||
LuaCpu::Create(LUA, memorySize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LUA_FUNCTION(LCPUNative_CreateDevice) {
|
||||
auto base = LUA->CheckNumber(1);
|
||||
auto size = LUA->CheckNumber(2);
|
||||
lucore::LogInfo("Creating Lua device object mapped @ 0x{:08x} with size 0x{:08x}", static_cast<riscv::Address>(base),
|
||||
static_cast<riscv::Address>(size));
|
||||
LuaDevice::Create(LUA, static_cast<riscv::Address>(base), static_cast<riscv::Address>(size));
|
||||
return 1;
|
||||
}
|
||||
LUA_FUNCTION(LCPUNative_CreateDevice) {
|
||||
auto base = LUA->CheckNumber(1);
|
||||
auto size = LUA->CheckNumber(2);
|
||||
lucore::LogInfo("Creating Lua device object mapped @ 0x{:08x} with size 0x{:08x}", static_cast<riscv::Address>(base),
|
||||
static_cast<riscv::Address>(size));
|
||||
LuaDevice::Create(LUA, static_cast<riscv::Address>(base), static_cast<riscv::Address>(size));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GlobalsBind(GarrysMod::Lua::ILuaBase* LUA) {
|
||||
LuaCpu::RegisterClass(LUA);
|
||||
LuaDevice::RegisterClass(LUA);
|
||||
void GlobalsBind(GarrysMod::Lua::ILuaBase* LUA) {
|
||||
LuaCpu::RegisterClass(LUA);
|
||||
LuaDevice::RegisterClass(LUA);
|
||||
|
||||
// clang-format off
|
||||
LUA->PushSpecial(GarrysMod::Lua::SPECIAL_GLOB);
|
||||
LUA->CreateTable();
|
||||
LUA->PushNumber(LCPU_MODULE_VERSION);
|
||||
LUA->SetField(-2, "ModuleVersion");
|
||||
// clang-format off
|
||||
LUA->PushSpecial(GarrysMod::Lua::SPECIAL_GLOB);
|
||||
LUA->CreateTable();
|
||||
LUA->PushNumber(LCPU_MODULE_VERSION);
|
||||
LUA->SetField(-2, "ModuleVersion");
|
||||
|
||||
LUA_SET_C_FUNCTION_NAME(LCPUNative_CreateCPU, "CreateCPU");
|
||||
LUA_SET_C_FUNCTION_NAME(LCPUNative_CreateDevice, "CreateDevice");
|
||||
LUA->SetField(-2, "LCPUNative");
|
||||
LUA->Pop();
|
||||
// clang-format on
|
||||
}
|
||||
LUA_SET_C_FUNCTION_NAME(LCPUNative_CreateCPU, "CreateCPU");
|
||||
LUA_SET_C_FUNCTION_NAME(LCPUNative_CreateDevice, "CreateDevice");
|
||||
LUA->SetField(-2, "LCPUNative");
|
||||
LUA->Pop();
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
} // namespace lcpu
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#include "LuaHelpers.hpp"
|
||||
|
||||
namespace lcpu {
|
||||
/// This should be bumped on any incompatible change to the native bindings
|
||||
/// that would break older Lua code, or requires newer Lua code to run.
|
||||
#define LCPU_MODULE_VERSION 1
|
||||
|
||||
void GlobalsBind(GarrysMod::Lua::ILuaBase* LUA);
|
||||
void GlobalsBind(GarrysMod::Lua::ILuaBase* LUA);
|
||||
|
||||
} // namespace lcpu
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#include "LuaDevice.hpp"
|
||||
|
||||
// this is temporary from the thing
|
||||
|
||||
// this is temporary from the test harness, and will be replaced
|
||||
// at some point.
|
||||
/// simple 16550 UART implementation
|
||||
struct SimpleUartDevice : public riscv::Bus::MmioDevice {
|
||||
constexpr static riscv::Address BASE_ADDRESS = 0x10000000;
|
||||
|
@ -30,87 +30,90 @@ struct SimpleUartDevice : public riscv::Bus::MmioDevice {
|
|||
}
|
||||
};
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, PoweredOn) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
LUA->PushBool(self->poweredOn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, Cycle) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
if(!self->poweredOn)
|
||||
return 0;
|
||||
self->system->Step();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, PowerOff) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
if(!self->poweredOn)
|
||||
return 0;
|
||||
|
||||
self->poweredOn = false;
|
||||
self->system->bus->Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, PowerOn) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
if(self->poweredOn)
|
||||
return 0;
|
||||
|
||||
self->poweredOn = true;
|
||||
self->system->bus->Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, Reset) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
self->system->bus->Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, AttachDevice) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
auto device = LuaDevice::FromLua(LUA, 2);
|
||||
|
||||
// Attach it
|
||||
LUA->PushBool(self->system->bus->AttachDevice(static_cast<riscv::Bus::Device*>(device)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LuaCpu::RegisterClass(GarrysMod::Lua::ILuaBase* LUA) {
|
||||
RegisterClassStart(LUA);
|
||||
|
||||
RegisterMethod("PoweredOn", PoweredOn);
|
||||
RegisterMethod("Cycle", Cycle);
|
||||
RegisterMethod("PowerOff", PowerOff);
|
||||
RegisterMethod("PowerOn", PowerOn);
|
||||
RegisterMethod("Reset", Reset);
|
||||
RegisterMethod("AttachDevice", AttachDevice);
|
||||
}
|
||||
|
||||
LuaCpu::LuaCpu(u32 memorySize) {
|
||||
poweredOn = true;
|
||||
system = riscv::System::Create(memorySize);
|
||||
system->OnPowerOff = [&]() {
|
||||
poweredOn = false;
|
||||
system->bus->Reset();
|
||||
};
|
||||
|
||||
// lame test code. this WILL be removed, I just want this for a quick test
|
||||
system->bus->AttachDevice(new SimpleUartDevice);
|
||||
auto fp = std::fopen("/home/lily/test-gmod.bin", "rb");
|
||||
if(fp) {
|
||||
std::fseek(fp, 0, SEEK_END);
|
||||
auto len = std::ftell(fp);
|
||||
std::fseek(fp, 0, SEEK_SET);
|
||||
|
||||
std::fread(system->ram->Raw(), 1, len, fp);
|
||||
std::fclose(fp);
|
||||
namespace lcpu {
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, PoweredOn) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
LUA->PushBool(self->poweredOn);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
LuaCpu::~LuaCpu() {
|
||||
delete system;
|
||||
}
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, Cycle) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
if(!self->poweredOn)
|
||||
return 0;
|
||||
self->system->Step();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, PowerOff) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
if(!self->poweredOn)
|
||||
return 0;
|
||||
|
||||
self->poweredOn = false;
|
||||
self->system->bus->Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, PowerOn) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
if(self->poweredOn)
|
||||
return 0;
|
||||
|
||||
self->poweredOn = true;
|
||||
self->system->bus->Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, Reset) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
self->system->bus->Reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaCpu, AttachDevice) {
|
||||
auto self = LuaCpu::FromLua(LUA, 1);
|
||||
auto device = LuaDevice::FromLua(LUA, 2);
|
||||
|
||||
// Attach it
|
||||
LUA->PushBool(self->system->bus->AttachDevice(static_cast<riscv::Bus::Device*>(device)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LuaCpu::RegisterClass(GarrysMod::Lua::ILuaBase* LUA) {
|
||||
RegisterClassStart(LUA);
|
||||
|
||||
RegisterMethod("PoweredOn", PoweredOn);
|
||||
RegisterMethod("Cycle", Cycle);
|
||||
RegisterMethod("PowerOff", PowerOff);
|
||||
RegisterMethod("PowerOn", PowerOn);
|
||||
RegisterMethod("Reset", Reset);
|
||||
RegisterMethod("AttachDevice", AttachDevice);
|
||||
}
|
||||
|
||||
LuaCpu::LuaCpu(u32 memorySize) {
|
||||
poweredOn = true;
|
||||
system = riscv::System::Create(memorySize);
|
||||
system->OnPowerOff = [&]() {
|
||||
poweredOn = false;
|
||||
system->bus->Reset();
|
||||
};
|
||||
|
||||
// lame test code. this WILL be removed, I just want this for a quick test
|
||||
system->bus->AttachDevice(new SimpleUartDevice);
|
||||
auto fp = std::fopen("/home/lily/test-gmod.bin", "rb");
|
||||
if(fp) {
|
||||
std::fseek(fp, 0, SEEK_END);
|
||||
auto len = std::ftell(fp);
|
||||
std::fseek(fp, 0, SEEK_SET);
|
||||
|
||||
std::fread(system->ram->Raw(), 1, len, fp);
|
||||
std::fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
LuaCpu::~LuaCpu() {
|
||||
delete system;
|
||||
}
|
||||
|
||||
} // namespace lcpu
|
||||
|
|
|
@ -4,25 +4,29 @@
|
|||
|
||||
#include "LuaObject.hpp"
|
||||
|
||||
/// Bindings of [riscv::System] to Lua.
|
||||
struct LuaCpu : public lcpu::lua::LuaObject<LuaCpu> {
|
||||
/// Lua binding stuff
|
||||
constexpr static const char* Name() { return "LuaCpu"; }
|
||||
static void RegisterClass(GarrysMod::Lua::ILuaBase* LUA);
|
||||
namespace lcpu {
|
||||
/// Bindings of [riscv::System] to Lua.
|
||||
struct LuaCpu : public lua::LuaObject<LuaCpu> {
|
||||
/// Lua binding stuff
|
||||
constexpr static const char* Name() { return "LuaCpu"; }
|
||||
static void RegisterClass(GarrysMod::Lua::ILuaBase* LUA);
|
||||
|
||||
protected:
|
||||
friend struct lcpu::lua::LuaObject<LuaCpu>;
|
||||
LuaCpu(u32 memorySize);
|
||||
~LuaCpu();
|
||||
private:
|
||||
LUA_MEMBER_FUNCTION(PoweredOn); // Check if the CPU is powered on
|
||||
LUA_MEMBER_FUNCTION(Cycle); // do a single cycle (called internally by LCPU entity)
|
||||
LUA_MEMBER_FUNCTION(PowerOff); // power off and reset the LCPU
|
||||
LUA_MEMBER_FUNCTION(PowerOn); // power on the LCPU
|
||||
LUA_MEMBER_FUNCTION(Reset); // reset the LCPU
|
||||
LUA_MEMBER_FUNCTION(AttachDevice); // attach a LuaDevice to this cpu
|
||||
protected:
|
||||
friend struct lua::LuaObject<LuaCpu>;
|
||||
LuaCpu(u32 memorySize);
|
||||
~LuaCpu();
|
||||
|
||||
// member variables
|
||||
riscv::System* system;
|
||||
bool poweredOn;
|
||||
};
|
||||
private:
|
||||
LUA_MEMBER_FUNCTION(PoweredOn); // Check if the CPU is powered on
|
||||
LUA_MEMBER_FUNCTION(Cycle); // do a single cycle (called internally by LCPU entity)
|
||||
LUA_MEMBER_FUNCTION(PowerOff); // power off and reset the LCPU
|
||||
LUA_MEMBER_FUNCTION(PowerOn); // power on the LCPU
|
||||
LUA_MEMBER_FUNCTION(Reset); // reset the LCPU
|
||||
LUA_MEMBER_FUNCTION(AttachDevice); // attach a LuaDevice to this cpu
|
||||
|
||||
// member variables
|
||||
riscv::System* system;
|
||||
bool poweredOn;
|
||||
};
|
||||
|
||||
} // namespace lcpu
|
||||
|
|
|
@ -1,96 +1,112 @@
|
|||
#include "LuaDevice.hpp"
|
||||
|
||||
void LuaDevice::RegisterClass(GarrysMod::Lua::ILuaBase* LUA) {
|
||||
RegisterClassStart(LUA);
|
||||
namespace lcpu {
|
||||
void LuaDevice::RegisterClass(GarrysMod::Lua::ILuaBase* LUA) {
|
||||
RegisterClassStart(LUA);
|
||||
|
||||
RegisterGetter("Base", [](GarrysMod::Lua::ILuaBase* LUA) {
|
||||
auto self = LuaDevice::FromLua(LUA, 1);
|
||||
LUA->PushNumber(static_cast<double>(self->base));
|
||||
});
|
||||
RegisterGetter("Base", [](GarrysMod::Lua::ILuaBase* LUA) {
|
||||
auto self = LuaDevice::FromLua(LUA, 1);
|
||||
LUA->PushNumber(static_cast<double>(self->base));
|
||||
});
|
||||
|
||||
RegisterGetter("Size", [](GarrysMod::Lua::ILuaBase* LUA) {
|
||||
auto self = LuaDevice::FromLua(LUA, 1);
|
||||
LUA->PushNumber(static_cast<double>(self->size));
|
||||
});
|
||||
}
|
||||
RegisterGetter("Size", [](GarrysMod::Lua::ILuaBase* LUA) {
|
||||
auto self = LuaDevice::FromLua(LUA, 1);
|
||||
LUA->PushNumber(static_cast<double>(self->size));
|
||||
});
|
||||
}
|
||||
|
||||
bool LuaDevice::Clocked() const {
|
||||
// no real good rationale for checking here,
|
||||
// since function calling does bail out properly
|
||||
return true;
|
||||
}
|
||||
bool LuaDevice::Clocked() const {
|
||||
// no real good rationale for checking here,
|
||||
// since function calling does bail out properly
|
||||
return true;
|
||||
}
|
||||
|
||||
void LuaDevice::Clock() {
|
||||
// clang-format off
|
||||
lua->ReferencePush(GetTableReference());
|
||||
lua->GetField(-1,"Clock");
|
||||
void LuaDevice::Clock() {
|
||||
// clang-format off
|
||||
lua->ReferencePush(GetTableReference());
|
||||
lua->GetField(-1,"Clock");
|
||||
if(lua->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
lua->Push(-2); // 'self' argument
|
||||
lua->Call(1, 0);
|
||||
} else {
|
||||
lua->Pop(); // pop the Clock function off the stack
|
||||
}
|
||||
lua->Pop(); // pop the reference
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
riscv::Address LuaDevice::Base() const {
|
||||
return base;
|
||||
}
|
||||
|
||||
riscv::Address LuaDevice::Size() const {
|
||||
return base;
|
||||
}
|
||||
|
||||
u32 LuaDevice::Peek(riscv::Address address) {
|
||||
// clang-format off
|
||||
lua->ReferencePush(GetTableReference());
|
||||
lua->GetField(-1,"Peek");
|
||||
if(lua->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
lua->Push(-2); // 'self' argument
|
||||
lua->PushNumber(static_cast<double>(address));
|
||||
lua->Call(2, 1);
|
||||
|
||||
auto result = static_cast<u32>(lua->GetNumber(-1));
|
||||
lua->Pop(2); // pop result and the table off
|
||||
return result;
|
||||
} else {
|
||||
lua->Pop(); // pop whatever Peek is off the stack
|
||||
}
|
||||
lua->Pop(); // pop the table reference
|
||||
// clang-format on
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
void LuaDevice::Poke(riscv::Address address, u32 value) {
|
||||
// clang-format off
|
||||
lua->ReferencePush(GetTableReference());
|
||||
lua->GetField(-1,"Poke");
|
||||
if(lua->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
lua->Push(-2); // 'self' argument
|
||||
lua->PushNumber(static_cast<double>(address));
|
||||
lua->PushNumber(static_cast<double>(value));
|
||||
lua->Call(3, 0);
|
||||
} else {
|
||||
lua->Pop(); // pop whatever Peek is
|
||||
}
|
||||
lua->Pop(); // pop the table reference
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void LuaDevice::Reset() {
|
||||
// clang-format off
|
||||
lua->ReferencePush(GetTableReference());
|
||||
lua->GetField(-1,"Reset");
|
||||
if(lua->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
lua->Push(-2); // 'self' argument
|
||||
lua->Call(1, 0);
|
||||
} else {
|
||||
lua->Pop(); // pop the Clock function off the stack
|
||||
lua->Pop(); // pop whatever reset is
|
||||
}
|
||||
lua->Pop(); // pop the reference
|
||||
// clang-format off
|
||||
}
|
||||
lua->Pop(); // pop the reference
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
riscv::Address LuaDevice::Base() const {
|
||||
return base;
|
||||
}
|
||||
LuaDevice::LuaDevice(riscv::Address base, riscv::Address size) : base(base), size(size) {
|
||||
}
|
||||
|
||||
riscv::Address LuaDevice::Size() const {
|
||||
return base;
|
||||
}
|
||||
void LuaDevice::AfterLuaInit() {
|
||||
// Our Lua callbacks only get the table, not the actual userdata,
|
||||
// ao we have to mirror things :( kinda sucks, but meh
|
||||
|
||||
u32 LuaDevice::Peek(riscv::Address address) {
|
||||
// clang-format off
|
||||
lua->ReferencePush(GetTableReference());
|
||||
lua->GetField(-1,"Peek");
|
||||
if(lua->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
lua->Push(-2); // 'self' argument
|
||||
lua->PushNumber(static_cast<double>(address));
|
||||
lua->Call(2, 1);
|
||||
|
||||
auto result = static_cast<u32>(lua->GetNumber(-1));
|
||||
lua->Pop(2); // pop result and the table off
|
||||
return result;
|
||||
} else {
|
||||
lua->Pop(); // pop whatever Peek is off the stack
|
||||
}
|
||||
lua->Pop(); // pop the table reference
|
||||
// clang-format on
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
void LuaDevice::Poke(riscv::Address address, u32 value) {
|
||||
// clang-format off
|
||||
lua->ReferencePush(GetTableReference());
|
||||
lua->GetField(-1,"Poke");
|
||||
if(lua->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
lua->Push(-2); // 'self' argument
|
||||
lua->PushNumber(static_cast<double>(address));
|
||||
lua->PushNumber(static_cast<double>(value));
|
||||
lua->Call(3, 0);
|
||||
} else {
|
||||
lua->Pop(); // pop whatever Peek is
|
||||
}
|
||||
lua->Pop(); // pop the table reference
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void LuaDevice::Reset() {
|
||||
// clang-format off
|
||||
lua->ReferencePush(GetTableReference());
|
||||
lua->GetField(-1,"Reset");
|
||||
if(lua->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
||||
lua->Push(-2); // 'self' argument
|
||||
lua->Call(1, 0);
|
||||
} else {
|
||||
lua->Pop(); // pop whatever reset is
|
||||
}
|
||||
lua->Pop(); // pop the reference
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
LuaDevice::LuaDevice(riscv::Address base, riscv::Address size) : base(base), size(size) {
|
||||
}
|
||||
// clang-format off
|
||||
lua->ReferencePush(GetTableReference());
|
||||
lua->PushNumber(static_cast<double>(base));
|
||||
lua->SetField(-2, "Base");
|
||||
lua->PushNumber(static_cast<double>(base));
|
||||
lua->SetField(-2, "Size");
|
||||
lua->Pop();
|
||||
// clang-format on
|
||||
}
|
||||
} // namespace lcpu
|
||||
|
|
|
@ -5,29 +5,33 @@
|
|||
#include "LuaHelpers.hpp"
|
||||
#include "LuaObject.hpp"
|
||||
|
||||
/// A work-in-progress binding of [riscv::Bus::MmioDevice] to lua
|
||||
struct LuaDevice : public riscv::Bus::MmioDevice, lcpu::lua::LuaObject<LuaDevice> {
|
||||
/// Lua binding stuff
|
||||
constexpr static const char* Name() { return "LuaDevice"; }
|
||||
static void RegisterClass(GarrysMod::Lua::ILuaBase* LUA);
|
||||
namespace lcpu {
|
||||
/// A work-in-progress binding of [riscv::Bus::MmioDevice] to lua
|
||||
struct LuaDevice : public riscv::Bus::MmioDevice, lcpu::lua::LuaObject<LuaDevice> {
|
||||
/// Lua binding stuff
|
||||
constexpr static const char* Name() { return "LuaDevice"; }
|
||||
static void RegisterClass(GarrysMod::Lua::ILuaBase* LUA);
|
||||
|
||||
// [riscv::Bus::MmioDevice] implementation
|
||||
bool Clocked() const override;
|
||||
void Clock() override;
|
||||
void Reset() override;
|
||||
// [riscv::Bus::MmioDevice] implementation
|
||||
bool Clocked() const override;
|
||||
void Clock() override;
|
||||
void Reset() override;
|
||||
|
||||
riscv::Address Base() const override;
|
||||
riscv::Address Size() const override;
|
||||
riscv::Address Base() const override;
|
||||
riscv::Address Size() const override;
|
||||
|
||||
u32 Peek(riscv::Address address) override;
|
||||
void Poke(riscv::Address address, u32 value) override;
|
||||
u32 Peek(riscv::Address address) override;
|
||||
void Poke(riscv::Address address, u32 value) override;
|
||||
|
||||
protected:
|
||||
friend lcpu::lua::LuaObject<LuaDevice>;
|
||||
LuaDevice(riscv::Address base, riscv::Address size);
|
||||
~LuaDevice() = default;
|
||||
protected:
|
||||
friend lcpu::lua::LuaObject<LuaDevice>;
|
||||
LuaDevice(riscv::Address base, riscv::Address size);
|
||||
~LuaDevice() = default;
|
||||
|
||||
private:
|
||||
riscv::Address base {};
|
||||
riscv::Address size {};
|
||||
};
|
||||
void AfterLuaInit() override;
|
||||
|
||||
private:
|
||||
riscv::Address base {};
|
||||
riscv::Address size {};
|
||||
};
|
||||
} // namespace lcpu
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
//! Helpers for lua binding
|
||||
//! Helpers for binding Lua and C++.
|
||||
//! If you want to bind a C++ class to Lua, see the
|
||||
//! [lcpu::lua::LuaObject<TImpl>] type in LuaObject.hpp
|
||||
#pragma once
|
||||
|
||||
#include <GarrysMod/Lua/Interface.h>
|
||||
|
@ -20,14 +22,6 @@
|
|||
|
||||
#define LUA_MEMBER_FUNCTION_IMPLEMENT(CLASS, FUNC) int CLASS::FUNC##__ImpStatic(GarrysMod::Lua::ILuaBase* LUA)
|
||||
|
||||
// this synthesizes a lambda which takes the stack argument to get. this can actually also be
|
||||
// stored as a variable for later usage (... if you so desire?)
|
||||
#define LUA_CLASS_GET(T) \
|
||||
[LUA](int stackPos) { \
|
||||
LUA->CheckType(stackPos, T::__lua_typeid); \
|
||||
return LUA->GetUserType<T>(stackPos, T::__lua_typeid); \
|
||||
}
|
||||
|
||||
// Set a C function as a field.
|
||||
#define LUA_SET_C_FUNCTION(name) \
|
||||
LUA->PushCFunction(name); \
|
||||
|
|
|
@ -10,6 +10,9 @@ namespace lcpu::lua {
|
|||
|
||||
/// A CRTP-based class which allows binding C++ to Lua, in a
|
||||
/// fairly sensible manner.
|
||||
///
|
||||
/// Classes backed by this class can have arbitrary properties
|
||||
/// created by Lua (using a backing table created by this object).
|
||||
template <class TImpl>
|
||||
struct LuaObject {
|
||||
using CFunc = GarrysMod::Lua::CFunc;
|
||||
|
@ -26,12 +29,15 @@ namespace lcpu::lua {
|
|||
/// C++ registered value read-write.
|
||||
static void RegisterSetter(const std::string& name, ILuaVoidFunc func) { setters()[name] = func; }
|
||||
|
||||
virtual void AfterLuaInit() {};
|
||||
|
||||
/// Create an instance of this type to give to Lua.
|
||||
/// addl. arguments are forwarded to the C++ constructor
|
||||
template <class... Args>
|
||||
static void Create(GarrysMod::Lua::ILuaBase* LUA, Args&&... args) {
|
||||
auto ptr = new TImpl(static_cast<Args&&>(args)...);
|
||||
ptr->InitLuaStuff(LUA);
|
||||
ptr->AfterLuaInit();
|
||||
LUA->PushUserType(ptr, __lua_typeid);
|
||||
}
|
||||
|
||||
|
@ -85,14 +91,14 @@ namespace lcpu::lua {
|
|||
LUA->CreateTable();
|
||||
tableReference = LUA->ReferenceCreate();
|
||||
|
||||
// register some convinence things
|
||||
// register some convinence getters
|
||||
RegisterGetter("Name", [](GarrysMod::Lua::ILuaBase* LUA) { LUA->PushString(TImpl::Name()); });
|
||||
}
|
||||
|
||||
int GetTableReference() { return tableReference; }
|
||||
|
||||
LuaObject() = default;
|
||||
~LuaObject() {
|
||||
virtual ~LuaObject() {
|
||||
// free the table reference
|
||||
if(tableReference != -1)
|
||||
lua->ReferenceFree(tableReference);
|
||||
|
|
|
@ -11,7 +11,7 @@ GMOD_MODULE_OPEN() {
|
|||
lucore::Logger::The().AttachSink(lcpu::SourceSink::The());
|
||||
lucore::LogInfo("LCPU Native Module! (ModuleVersion {})", LCPU_MODULE_VERSION);
|
||||
|
||||
GlobalsBind(LUA);
|
||||
lcpu::GlobalsBind(LUA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue