2023-07-24 20:17:07 -04:00
|
|
|
#include "LuaDevice.hpp"
|
|
|
|
|
|
|
|
LUA_CLASS_BIND_VARIABLES_IMPLEMENT(LuaDevice);
|
|
|
|
|
2023-07-25 06:46:52 -04:00
|
|
|
bool LuaDevice::Clocked() const {
|
2023-07-27 06:03:28 -04:00
|
|
|
// no real good rationale for checking here,
|
|
|
|
// since function calling does bail out properly
|
2023-07-25 06:46:52 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LuaDevice::Clock() {
|
2023-07-27 07:16:39 -04:00
|
|
|
// clang-format off
|
2023-07-27 06:03:28 -04:00
|
|
|
LuaState->ReferencePush(tableReference);
|
|
|
|
LuaState->GetField(-1,"Clock");
|
|
|
|
if(LuaState->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
|
|
|
LuaState->Push(-2); // 'self' argument
|
|
|
|
LuaState->Call(1, 0);
|
|
|
|
} else {
|
|
|
|
LuaState->Pop(); // pop the Clock function off the stack
|
|
|
|
}
|
|
|
|
LuaState->Pop(); // pop the reference
|
2023-07-27 07:16:39 -04:00
|
|
|
// clang-format off
|
2023-07-25 06:46:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
riscv::Address LuaDevice::Base() const {
|
|
|
|
return base;
|
|
|
|
}
|
|
|
|
|
|
|
|
riscv::Address LuaDevice::Size() const {
|
|
|
|
return base;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 LuaDevice::Peek(riscv::Address address) {
|
2023-07-27 07:16:39 -04:00
|
|
|
// clang-format off
|
2023-07-27 06:03:28 -04:00
|
|
|
LuaState->ReferencePush(tableReference);
|
|
|
|
LuaState->GetField(-1,"Peek");
|
|
|
|
if(LuaState->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
|
|
|
LuaState->Push(-2); // 'self' argument
|
|
|
|
LuaState->PushNumber(static_cast<double>(address));
|
|
|
|
LuaState->Call(2, 1);
|
|
|
|
|
|
|
|
auto result = static_cast<u32>(LuaState->GetNumber(-1));
|
|
|
|
LuaState->Pop(2); // pop result and the table off
|
|
|
|
return result;
|
|
|
|
} else {
|
|
|
|
LuaState->Pop(); // pop whatever Peek is off the stack
|
|
|
|
}
|
|
|
|
LuaState->Pop(); // pop the table reference
|
2023-07-27 07:16:39 -04:00
|
|
|
// clang-format on
|
2023-07-27 06:03:28 -04:00
|
|
|
return 0xffffffff;
|
2023-07-25 06:46:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LuaDevice::Poke(riscv::Address address, u32 value) {
|
2023-07-27 07:16:39 -04:00
|
|
|
// clang-format off
|
2023-07-27 06:03:28 -04:00
|
|
|
LuaState->ReferencePush(tableReference);
|
|
|
|
LuaState->GetField(-1,"Poke");
|
|
|
|
if(LuaState->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
|
|
|
LuaState->Push(-2); // 'self' argument
|
|
|
|
LuaState->PushNumber(static_cast<double>(address));
|
|
|
|
LuaState->PushNumber(static_cast<double>(value));
|
|
|
|
LuaState->Call(3, 0);
|
|
|
|
} else {
|
|
|
|
LuaState->Pop(); // pop whatever Peek is
|
|
|
|
}
|
|
|
|
LuaState->Pop(); // pop the table reference
|
2023-07-27 07:16:39 -04:00
|
|
|
// clang-format on
|
2023-07-25 06:46:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LuaDevice::Reset() {
|
2023-07-27 07:16:39 -04:00
|
|
|
// clang-format off
|
2023-07-27 06:03:28 -04:00
|
|
|
LuaState->ReferencePush(tableReference);
|
|
|
|
LuaState->GetField(-1,"Reset");
|
|
|
|
if(LuaState->GetType(-1) == GarrysMod::Lua::Type::Function) {
|
|
|
|
LuaState->Push(-2); // 'self' argument
|
|
|
|
LuaState->Call(1, 0);
|
|
|
|
} else {
|
|
|
|
LuaState->Pop(); // pop whatever reset is
|
|
|
|
}
|
|
|
|
LuaState->Pop(); // pop the reference
|
2023-07-27 07:16:39 -04:00
|
|
|
// clang-format on
|
2023-07-27 06:03:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
LuaDevice::LuaDevice(riscv::Address base, riscv::Address size) : base(base), size(size) {
|
2023-07-25 06:46:52 -04:00
|
|
|
}
|
|
|
|
|
2023-07-27 06:03:28 -04:00
|
|
|
LuaDevice::~LuaDevice() {
|
|
|
|
// Free all refererences
|
|
|
|
if(tableReference == -1)
|
|
|
|
LuaState->ReferenceFree(tableReference);
|
|
|
|
}
|
|
|
|
|
|
|
|
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaDevice, __index) {
|
|
|
|
auto self = LUA_CLASS_GET(LuaDevice)(1);
|
2023-07-27 07:16:39 -04:00
|
|
|
// lucore::LogInfo("metamethod __index call");
|
|
|
|
|
2023-07-27 06:03:28 -04:00
|
|
|
// TODO: before moving this to a shared lua object class thing
|
|
|
|
// and moving the CPU class to use this way of doing things
|
|
|
|
// I should probably try and like, add stuff to ensure native
|
|
|
|
// methods can be registered as well,,
|
|
|
|
LUA->ReferencePush(self->tableReference);
|
|
|
|
LUA->Push(2);
|
|
|
|
LUA->GetTable(-2);
|
|
|
|
return 1; // the value
|
|
|
|
}
|
|
|
|
|
|
|
|
LUA_MEMBER_FUNCTION_IMPLEMENT(LuaDevice, __newindex) {
|
|
|
|
auto self = LUA_CLASS_GET(LuaDevice)(1);
|
2023-07-27 07:16:39 -04:00
|
|
|
// lucore::LogInfo("metamethod __newindex call");
|
2023-07-27 06:03:28 -04:00
|
|
|
|
2023-07-27 07:16:39 -04:00
|
|
|
// Always push onto the table.
|
2023-07-27 06:03:28 -04:00
|
|
|
// TODO: This function
|
|
|
|
// should error on attempt to __newindex any native methods
|
|
|
|
// (when moved to a shared place)
|
|
|
|
LUA->ReferencePush(self->tableReference);
|
|
|
|
LUA->Push(2);
|
|
|
|
LUA->Push(3);
|
|
|
|
LUA->SetTable(-3);
|
|
|
|
LUA->Pop();
|
|
|
|
return 0;
|
|
|
|
}
|
2023-07-25 06:46:52 -04:00
|
|
|
|
2023-07-24 20:17:07 -04:00
|
|
|
void LuaDevice::Bind(GarrysMod::Lua::ILuaBase* LUA) {
|
|
|
|
// clang-format off
|
2023-07-27 06:03:28 -04:00
|
|
|
//LUA_CLASS_BIND_BEGIN(LuaDevice)
|
|
|
|
__lua_typeid = LUA->CreateMetaTable("LuaDevice");
|
|
|
|
LUA->PushSpecial(GarrysMod::Lua::SPECIAL_REG);
|
|
|
|
LUA->PushNumber(__lua_typeid);
|
|
|
|
LUA->SetField(-2, "LuaDevice__typeid");
|
|
|
|
LUA->Pop(); /* pop registry */
|
|
|
|
|
|
|
|
LUA_SET_C_FUNCTION(__gc)
|
|
|
|
LUA_SET_C_FUNCTION(__index)
|
|
|
|
LUA_SET_C_FUNCTION(__newindex)
|
2023-07-24 20:17:07 -04:00
|
|
|
LUA_CLASS_BIND_END();
|
|
|
|
// clang-format on
|
|
|
|
}
|
|
|
|
|
2023-07-27 06:03:28 -04:00
|
|
|
void LuaDevice::Create(GarrysMod::Lua::ILuaBase* LUA, riscv::Address base, riscv::Address size) {
|
|
|
|
auto device = new LuaDevice(base, size);
|
2023-07-25 06:46:52 -04:00
|
|
|
device->LuaState = LUA;
|
2023-07-27 06:03:28 -04:00
|
|
|
|
|
|
|
LUA->CreateTable();
|
2023-07-27 07:16:39 -04:00
|
|
|
device->tableReference = LUA->ReferenceCreate();
|
2023-07-27 06:03:28 -04:00
|
|
|
LUA->Pop();
|
|
|
|
|
|
|
|
// push base/size properties for lua to have a looksee at !
|
|
|
|
// ideally these should be handled as metamethods in __index,
|
|
|
|
// but i don't quite feel like making gmod sol2 yet /shrug
|
|
|
|
LUA->ReferencePush(device->tableReference);
|
2023-07-27 07:16:39 -04:00
|
|
|
LUA->PushNumber(static_cast<double>(base));
|
|
|
|
LUA->SetField(-2, "Base");
|
|
|
|
LUA->PushNumber(static_cast<double>(base));
|
|
|
|
LUA->SetField(-2, "Size");
|
2023-07-27 06:03:28 -04:00
|
|
|
LUA->Pop();
|
|
|
|
|
2023-07-25 06:46:52 -04:00
|
|
|
LUA->PushUserType(device, __lua_typeid);
|
2023-07-24 20:17:07 -04:00
|
|
|
}
|