Skip to content

Commit 9195544

Browse files
authored
Merge branch 'grumpycoders:main' into main
2 parents 43846d0 + 1d81a0a commit 9195544

File tree

17 files changed

+441
-63
lines changed

17 files changed

+441
-63
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
url = https://github.com/herumi/xbyak
6161
[submodule "third_party/zep"]
6262
path = third_party/zep
63-
url = https://github.com/nicolasnoble/zep.git
63+
url = https://github.com/grumpycoders/zep.git
6464
[submodule "third_party/miniaudio"]
6565
path = third_party/miniaudio
6666
url = https://github.com/mackron/miniaudio.git

src/core/logger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum class LogClass : unsigned {
4444
KERNEL, // kernel logs
4545
GDB, // GDB logs
4646
SYSTEM, // system logs from the emulator itself
47+
LUA, // logs emitted by the Lua VM
4748
};
4849

4950
template <LogClass logClass, bool enabled>

src/core/pcsxffi.lua

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
--lualoader, R"EOF(--
2+
3+
ffi.cdef [[
4+
typedef union {
5+
struct {
6+
uint32_t r0, at, v0, v1, a0, a1, a2, a3;
7+
uint32_t t0, t1, t2, t3, t4, t5, t6, t7;
8+
uint32_t s0, s1, s2, s3, s4, s5, s6, s7;
9+
uint32_t t8, t9, k0, k1, gp, sp, s8, ra;
10+
uint32_t lo, hi;
11+
} n;
12+
uint32_t r[34];
13+
} psxGPRRegs;
14+
15+
typedef union {
16+
uint32_t r[32];
17+
} psxCP0Regs;
18+
19+
typedef union {
20+
uint32_t r[32];
21+
} psxCP2Data;
22+
23+
typedef union {
24+
uint32_t r[32];
25+
} psxCP2Ctrl;
26+
27+
typedef struct {
28+
psxGPRRegs GPR;
29+
psxCP0Regs CP0;
30+
psxCP2Data CP2D;
31+
psxCP2Ctrl CP2C;
32+
uint32_t pc;
33+
} psxRegisters;
34+
35+
enum BreakpointType { Exec, Read, Write };
36+
37+
uint8_t* getMemPtr();
38+
uint8_t* getRomPtr();
39+
uint8_t* getScratchPtr();
40+
psxRegisters* getRegisters();
41+
void* addBreakpoint(uint32_t address, enum BreakpointType type, unsigned width, const char* cause, bool (*invoker)());
42+
void enableBreakpoint(void*);
43+
void disableBreakpoint(void*);
44+
bool breakpointEnabled(void*);
45+
void removeBreakpoint(void*);
46+
void pauseEmulator();
47+
void resumeEmulator();
48+
void softResetEmulator();
49+
void hardResetEmulator();
50+
void luaMessage(const char* msg, bool error);
51+
void luaLog(const char* msg);
52+
void jumpToPC(uint32_t address);
53+
void jumpToMemory(uint32_t address, unsigned width);
54+
]]
55+
56+
local C = ffi.load 'PCSX'
57+
58+
local function garbageCollect(bp)
59+
C.removeBreakpoint(bp.wrapper)
60+
bp.invokercb:free()
61+
end
62+
63+
local meta = { __gc = garbageCollect }
64+
65+
local function defaultInvoker()
66+
C.pauseEmulator()
67+
return true
68+
end
69+
70+
local validBpTypes = {
71+
Exec = true,
72+
Read = true,
73+
Write = true,
74+
}
75+
76+
local function addBreakpoint(address, bptype, width, cause, invoker)
77+
if type(address) ~= 'number' then error 'PCSX.addBreakpoint needs an address' end
78+
if bptype == nil then bptype = 'Exec' end
79+
if not validBpTypes[bptype] then error 'PCSX.addBreakpoint needs a valid breakpoint type' end
80+
if width == nil then width = 4 end
81+
if type(width) ~= 'number' then error 'PCSX.addBreakpoint needs a width that is a number' end
82+
if cause == nil then cause = '' end
83+
if type(cause) == 'function' and invoker == nil then
84+
invoker = cause
85+
cause = ''
86+
end
87+
if type(cause) ~= 'string' then error 'PCSX.addBreakpoint needs a cause that is a string' end
88+
local invokercb = defaultInvoker
89+
if invoker ~= nil then
90+
if type(invoker) ~= 'function' then
91+
error 'PCSX.addBreakpoint needs an invoker that is a function'
92+
end
93+
invokercb = function()
94+
local ret = invoker()
95+
if ret == false then return false else return true end
96+
end
97+
end
98+
local invokercb = ffi.cast('bool (*)()', invokercb)
99+
local wrapper = C.addBreakpoint(address, bptype, width, cause, invokercb)
100+
local bp = {
101+
wrapper = wrapper,
102+
invokercb = invokercb,
103+
}
104+
setmetatable(bp, meta)
105+
return bp
106+
end
107+
108+
local function printLike(callback, ...)
109+
local s = ''
110+
for i, v in ipairs({...}) do
111+
s = s .. tostring(v) .. ' '
112+
end
113+
callback(s)
114+
end
115+
116+
local function jumpToPC(pc)
117+
if type(pc) ~= 'number' then error 'PCSX.GUI.jumpToPC requires a numeric address' end
118+
C.jumpToPC(pc)
119+
end
120+
121+
local function jumpToMemory(address, width)
122+
if type(address) ~= 'number' then error 'PCSX.GUI.jumpToMemory requires a numeric address' end
123+
if width == nil then width = 1 end
124+
if type(width) ~= 'number' then error 'PCSX.GUI.jumpToMemory requires a numeric width' end
125+
C.jumpToMemory(address, width)
126+
end
127+
128+
PCSX = {
129+
getMemPtr = function() return C.getMemPtr end,
130+
getRomPtr = function() return C.getRomPtr end,
131+
getScratchPtr = function() return C.getScratchPtr end,
132+
getRegisters = C.getRegisters,
133+
addBreakpoint = addBreakpoint,
134+
enableBreakpoint = function(bp) C.enableBreakpoint(bp.wrapper) end,
135+
disableBreakpoint = function(bp) C.disableBreakpoint(bp.wrapper) end,
136+
breakpointEnabled = function(bp) return C.breakpointEnabled(bp.wrapper) end,
137+
pauseEmulator = function() C.pauseEmulator() end,
138+
resumeEmulator = function() C.resumeEmulator() end,
139+
softResetEmulator = function() C.softResetEmulator() end,
140+
hardResetEmulator = function() C.hardResetEmulator() end,
141+
log = function(...) printLike(C.luaLog, ...) end,
142+
GUI = {
143+
jumpToPC = jumpToPC,
144+
jumpToMemory = jumpToMemory,
145+
},
146+
}
147+
148+
print = function(...) printLike(function(s) C.luaMessage(s, false) end, ...) end
149+
printError = function(...) printLike(function(s) C.luaMessage(s, true) end, ...) end
150+
151+
-- )EOF"

src/core/pcsxlua.cc

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/***************************************************************************
2+
* Copyright (C) 2021 PCSX-Redux authors *
3+
* *
4+
* This program is free software; you can redistribute it and/or modify *
5+
* it under the terms of the GNU General Public License as published by *
6+
* the Free Software Foundation; either version 2 of the License, or *
7+
* (at your option) any later version. *
8+
* *
9+
* This program is distributed in the hope that it will be useful, *
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12+
* GNU General Public License for more details. *
13+
* *
14+
* You should have received a copy of the GNU General Public License *
15+
* along with this program; if not, write to the *
16+
* Free Software Foundation, Inc., *
17+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18+
***************************************************************************/
19+
20+
#include "core/pcsxlua.h"
21+
22+
#include "core/debug.h"
23+
#include "core/psxemulator.h"
24+
#include "core/psxmem.h"
25+
#include "core/r3000a.h"
26+
#include "lua/luawrapper.h"
27+
28+
namespace {
29+
30+
struct LuaBreakpoint {
31+
PCSX::Debug::BreakpointUserListType wrapper;
32+
};
33+
34+
void setBreakpoint() {}
35+
void* getMemPtr() { return PCSX::g_emulator->m_psxMem->g_psxM; }
36+
void* getRomPtr() { return PCSX::g_emulator->m_psxMem->g_psxR; }
37+
void* getScratchPtr() { return PCSX::g_emulator->m_psxMem->g_psxH; }
38+
void* getRegisters() { return &PCSX::g_emulator->m_psxCpu->m_psxRegs; }
39+
LuaBreakpoint* addBreakpoint(uint32_t address, PCSX::Debug::BreakpointType type, unsigned width, const char* cause,
40+
bool (*invoker)()) {
41+
LuaBreakpoint* ret = new LuaBreakpoint();
42+
auto* bp =
43+
PCSX::g_emulator->m_debug->addBreakpoint(address, type, width, std::string("Lua Breakpoint ") + cause,
44+
[invoker](const PCSX::Debug::Breakpoint* self) { return invoker(); });
45+
46+
ret->wrapper.push_back(bp);
47+
return ret;
48+
}
49+
void enableBreakpoint(LuaBreakpoint* wrapper) {
50+
if (wrapper->wrapper.size() == 0) return;
51+
wrapper->wrapper.begin()->enable();
52+
}
53+
void disableBreakpoint(LuaBreakpoint* wrapper) {
54+
if (wrapper->wrapper.size() == 0) return;
55+
wrapper->wrapper.begin()->disable();
56+
}
57+
bool breakpointEnabled(LuaBreakpoint* wrapper) {
58+
if (wrapper->wrapper.size() == 0) return false;
59+
return wrapper->wrapper.begin()->enabled();
60+
}
61+
void removeBreakpoint(LuaBreakpoint* wrapper) {
62+
wrapper->wrapper.destroyAll();
63+
delete wrapper;
64+
}
65+
void pauseEmulator() { PCSX::g_system->pause(); }
66+
void resumeEmulator() { PCSX::g_system->resume(); }
67+
void softResetEmulator() { PCSX::g_system->softReset(); }
68+
void hardResetEmulator() { PCSX::g_system->hardReset(); }
69+
void luaMessage(const char* msg, bool error) { PCSX::g_system->luaMessage(msg, error); }
70+
void luaLog(const char* msg) { PCSX::g_system->log(PCSX::LogClass::LUA, msg); }
71+
void jumpToPC(uint32_t pc) { PCSX::g_system->m_eventBus->signal(PCSX::Events::GUI::JumpToPC{pc}); }
72+
void jumpToMemory(uint32_t address, unsigned width) {
73+
PCSX::g_system->m_eventBus->signal(PCSX::Events::GUI::JumpToMemory{address, width});
74+
}
75+
76+
} // namespace
77+
78+
template <typename T, size_t S>
79+
static void registerSymbol(PCSX::Lua* L, const char (&name)[S], const T ptr) {
80+
L->push<S>(name);
81+
L->push((void*)ptr);
82+
L->settable();
83+
}
84+
85+
#define REGISTER(L, s) registerSymbol(L, #s, s)
86+
87+
static void registerAllSymbols(PCSX::Lua* L) {
88+
L->push("_CLIBS");
89+
L->gettable(LUA_REGISTRYINDEX);
90+
if (L->isnil()) {
91+
L->pop();
92+
L->newtable();
93+
L->push("_CLIBS");
94+
L->copy(-2);
95+
L->settable(LUA_REGISTRYINDEX);
96+
}
97+
L->push("PCSX");
98+
L->newtable();
99+
REGISTER(L, getMemPtr);
100+
REGISTER(L, getRomPtr);
101+
REGISTER(L, getScratchPtr);
102+
REGISTER(L, getRegisters);
103+
REGISTER(L, addBreakpoint);
104+
REGISTER(L, enableBreakpoint);
105+
REGISTER(L, disableBreakpoint);
106+
REGISTER(L, breakpointEnabled);
107+
REGISTER(L, removeBreakpoint);
108+
REGISTER(L, pauseEmulator);
109+
REGISTER(L, resumeEmulator);
110+
REGISTER(L, softResetEmulator);
111+
REGISTER(L, hardResetEmulator);
112+
REGISTER(L, luaMessage);
113+
REGISTER(L, luaLog);
114+
REGISTER(L, jumpToPC);
115+
REGISTER(L, jumpToMemory);
116+
L->settable();
117+
L->pop();
118+
}
119+
120+
void PCSX::LuaFFI::open_pcsx(Lua* L) {
121+
static int lualoader = 1;
122+
static const char* pcsxFFI = (
123+
#include "core/pcsxffi.lua"
124+
);
125+
registerAllSymbols(L);
126+
L->load(pcsxFFI, "internal:core/pcsxffi.lua");
127+
}

src/core/pcsxlua.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/***************************************************************************
2+
* Copyright (C) 2021 PCSX-Redux authors *
3+
* *
4+
* This program is free software; you can redistribute it and/or modify *
5+
* it under the terms of the GNU General Public License as published by *
6+
* the Free Software Foundation; either version 2 of the License, or *
7+
* (at your option) any later version. *
8+
* *
9+
* This program is distributed in the hope that it will be useful, *
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12+
* GNU General Public License for more details. *
13+
* *
14+
* You should have received a copy of the GNU General Public License *
15+
* along with this program; if not, write to the *
16+
* Free Software Foundation, Inc., *
17+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18+
***************************************************************************/
19+
20+
#pragma once
21+
22+
namespace PCSX {
23+
24+
class Lua;
25+
26+
namespace LuaFFI {
27+
void open_pcsx(Lua*);
28+
}
29+
30+
} // namespace PCSX

src/core/psxemulator.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "core/gte.h"
2929
#include "core/mdec.h"
3030
#include "core/pad.h"
31+
#include "core/pcsxlua.h"
3132
#include "core/ppf.h"
3233
#include "core/r3000a.h"
3334
#include "core/web-server.h"
@@ -71,6 +72,7 @@ PCSX::Emulator::Emulator()
7172
m_lua->push("luv");
7273
luaopen_luv(m_lua->getState());
7374
m_lua->settable(LUA_GLOBALSINDEX);
75+
LuaFFI::open_pcsx(m_lua.get());
7476
}
7577

7678
PCSX::Emulator::~Emulator() {

src/core/system.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ class System {
114114
message(s);
115115
}
116116
virtual void message(const std::string &) = 0;
117+
// For the Lua output
118+
virtual void luaMessage(const std::string &, bool error) = 0;
117119
// Called periodically; if vsync = true, this while the emulated hardware vsyncs
118120
virtual void update(bool vsync = false) = 0;
119121
// Close mem and plugins

src/gui/gui.cc

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -180,38 +180,6 @@ void PCSX::GUI::init() {
180180
}
181181
}
182182
});
183-
auto printer = [this](Lua L, bool error) -> int {
184-
int n = L.gettop();
185-
std::string s;
186-
187-
for (int i = 1; i <= n; i++) {
188-
if (i > 1) s += " ";
189-
if (L.isstring(i)) {
190-
s += L.tostring(i);
191-
} else {
192-
L.getglobal("tostring");
193-
L.copy(i);
194-
L.pcall(1);
195-
s += L.tostring(-1);
196-
L.pop();
197-
}
198-
}
199-
if (error) {
200-
m_luaConsole.addError(s);
201-
} else {
202-
m_luaConsole.addLog(s);
203-
}
204-
if (m_args.get<bool>("lua_stdout", false)) {
205-
if (error) {
206-
fprintf(stderr, "%s\n", s.c_str());
207-
} else {
208-
fprintf(stdout, "%s\n", s.c_str());
209-
}
210-
}
211-
return 0;
212-
};
213-
g_emulator->m_lua->declareFunc("print", [printer](Lua L) { return printer(L, false); });
214-
g_emulator->m_lua->declareFunc("printError", [printer](Lua L) { return printer(L, true); });
215183
g_emulator->m_lua->load(R"(
216184
print("PCSX-Redux Lua Console")
217185
print(jit.version)

0 commit comments

Comments
 (0)