add memory access highlighting to emulator

This commit is contained in:
Redo 2022-12-07 13:13:17 -06:00
parent 59f7db27f1
commit 4af6f46a51
3 changed files with 64 additions and 43 deletions

View File

@ -36,8 +36,8 @@
#define storeq(x) writememory(cpu->q, x); #define storeq(x) writememory(cpu->q, x);
#define storeqinc(x) writememory(cpu->q++, x); #define storeqinc(x) writememory(cpu->q++, x);
#define storeqp1(x) writememory((cpu->q+1)%65536, x); #define storeqp1(x) writememory((cpu->q+1)%65536, x);
#define pushretaddr1 writememory(cpu->s++, hibyte(cpu->i)); #define pushretaddr1 writememory(cpu->s++, hibyte((cpu->i-1)%65536));
#define pushretaddr2 writememory(cpu->s++, lobyte(cpu->i)); #define pushretaddr2 writememory(cpu->s++, lobyte((cpu->i-1)%65536));
#define lni cpu->instr = readmemory(cpu->i++); cpu->cycle = 0; #define lni cpu->instr = readmemory(cpu->i++); cpu->cycle = 0;
#define ldi cpu->instr = readmemory(cpu->i); cpu->cycle = 0; #define ldi cpu->instr = readmemory(cpu->i); cpu->cycle = 0;
#define addf(x,y) { x=(x+y); cpu->cf=x>=256; x&=0xFF; setzf(x); } #define addf(x,y) { x=(x+y); cpu->cf=x>=256; x&=0xFF; setzf(x); }
@ -83,7 +83,7 @@ struct CPU {
int instr; int instr;
int cycle; int cycle;
int instrpre; int instrpre;
int tick; int frame;
}; };
struct Event { struct Event {
int id; int id;
@ -109,7 +109,7 @@ void postEvent(struct Memory* const mem, int id, int addr) {
} }
int _readmemory(const struct CPU* const cpu, struct Memory* const mem, const int addr) { int _readmemory(const struct CPU* const cpu, struct Memory* const mem, const int addr) {
int addr2 = addr%65536; int addr2 = addr%65536;
mem->reads[addr2] = cpu->tick; mem->reads[addr2] = cpu->frame;
if(mem->onread[addr2]) { if(mem->onread[addr2]) {
postEvent(mem, mem->onread[addr2], addr2); postEvent(mem, mem->onread[addr2], addr2);
} }
@ -118,7 +118,7 @@ int _readmemory(const struct CPU* const cpu, struct Memory* const mem, const int
int _writememory(const struct CPU* const cpu, struct Memory* const mem, const int addr, const int data) { int _writememory(const struct CPU* const cpu, struct Memory* const mem, const int addr, const int data) {
int addr2 = addr%65536; int addr2 = addr%65536;
if(mem->canwrite[addr2]) { if(mem->canwrite[addr2]) {
mem->writes[addr2] = cpu->tick; mem->writes[addr2] = cpu->frame;
mem->data[addr2] = data%256; mem->data[addr2] = data%256;
} }
if(mem->onwrite[addr2]) { if(mem->onwrite[addr2]) {

Binary file not shown.

View File

@ -91,11 +91,11 @@ local function RedrawRegDisplay(rd, cpu, mem)
lg.setColor(0,0,0) lg.setColor(0,0,0)
lg.rectangle("fill", rd.scrX+reg.x+(rd.fontWidth*(4-reg.w)), rd.scrY+reg.y, rd.fontWidth*reg.w, rd.fontHeight) lg.rectangle("fill", rd.scrX+reg.x+(rd.fontWidth*(4-reg.w)), rd.scrY+reg.y, rd.fontWidth*reg.w, rd.fontHeight)
lg.setColor(1,1,1) lg.setColor(1,1,1)
local val = cpu.data[reg.idx]%(math.pow(16, reg.w)) local val = cpu.c[reg.idx]%(math.pow(16, reg.w))
printValue(val, reg.w, rd.scrX+reg.x, rd.scrY+reg.y, rd.fontWidth) printValue(val, reg.w, rd.scrX+reg.x, rd.scrY+reg.y, rd.fontWidth)
end end
for i, flg in pairs(rd.flags) do for i, flg in pairs(rd.flags) do
local val = cpu.data[flg.idx] local val = cpu.c[flg.idx]
if val~=0 then if val~=0 then
lg.setColor(1,1,1) lg.setColor(1,1,1)
else else
@ -122,7 +122,7 @@ local function RedrawStackDisplay(sd, cpu, mem)
lg.rectangle("fill", sd.scrX, sd.scrY, sd.width, sd.height) lg.rectangle("fill", sd.scrX, sd.scrY, sd.width, sd.height)
lg.setColor(1,1,1) lg.setColor(1,1,1)
for i = 1, sd.lines do for i = 1, sd.lines do
local addr = (cpu.data.s-i)%65536 local addr = (cpu.c.s-i)%65536
local val = ReadMemory(mem, addr) local val = ReadMemory(mem, addr)
lg.print(string.format("%04X -%2i %02X", addr, i, val), sd.scrX+8, sd.scrY+8+(12*(i-1))) lg.print(string.format("%04X -%2i %02X", addr, i, val), sd.scrX+8, sd.scrY+8+(12*(i-1)))
end end
@ -134,7 +134,7 @@ local MemoryDisplays = {
columns = 16, columnSpace = 4, rows = 16, columns = 16, columnSpace = 4, rows = 16,
fontHeight = 12, fontHeight = 12,
showAscii = false, showAscii = false,
addr = 0x1000, addr = 0x0000,
highlightTime = 8, highlightTime = 8,
}, },
} }
@ -145,7 +145,6 @@ local function InitMemoryDisplay(md)
md.height = 12+md.fontHeight*md.rows md.height = 12+md.fontHeight*md.rows
lg.print("Memory", md.scrX, md.scrY-16) lg.print("Memory", md.scrX, md.scrY-16)
lg.rectangle("line", md.scrX, md.scrY, md.width+1, md.height+1) lg.rectangle("line", md.scrX, md.scrY, md.width+1, md.height+1)
md.ticksDrawn = {}; for i = 1, md.highlightTime do md.ticksDrawn[i] = 0 end;
end end
local function RedrawMemoryDisplay(md, cpu, mem) local function RedrawMemoryDisplay(md, cpu, mem)
lg.setColor(0,0,0) lg.setColor(0,0,0)
@ -153,15 +152,15 @@ local function RedrawMemoryDisplay(md, cpu, mem)
lg.setColor(1,1,1) lg.setColor(1,1,1)
local highlightAddrs = {} local highlightAddrs = {}
highlightAddrs[cpu.data.p] = "P" highlightAddrs[cpu.c.p] = "P"
highlightAddrs[cpu.data.q] = "Q" highlightAddrs[cpu.c.q] = "Q"
highlightAddrs[cpu.data.s] = "S" highlightAddrs[cpu.c.s] = "S"
highlightAddrs[cpu.data.v] = "V" highlightAddrs[cpu.c.v] = "V"
highlightAddrs[(cpu.data.i-1)%65536] = "I" highlightAddrs[(cpu.c.i-1)%65536] = "I"
local cw = 7 local cw = 7
local tickDraw = md.ticksDrawn[1] local tickDraw = cpu.c.frame-md.highlightTime
for l = 1, md.rows do for l = 1, md.rows do
local addr = md.addr + (l-1)*md.columns local addr = md.addr + (l-1)*md.columns
local lx = md.scrX+8 local lx = md.scrX+8
@ -203,17 +202,16 @@ local function RedrawMemoryDisplay(md, cpu, mem)
end end
end end
end end
table.insert(md.ticksDrawn, cpu.data.tick)
table.remove(md.ticksDrawn, 1)
end end
local ProgramDisplay = { local ProgramDisplay = {
scrX = 8+384+8+128+8, scrY = 32, scrX = 8+384+8+128+8, scrY = 32,
fontHeight = 12, fontHeight = 12,
numLines = 35, numLines = 35,
highlightTime = 8,
} }
local function pdLinesFromDasm(dasm) local function pdLinesFromDasm(dasm)
local lines, addrLines = {}, {} local lines, addrLines, lineAddrs = {}, {}, {}
for line in dasm:gmatch("[^\n]+") do for line in dasm:gmatch("[^\n]+") do
if line~="..." then if line~="..." then
local addrh, datah, rest = line:match("^(.+) | (.+) | +(.+)$") local addrh, datah, rest = line:match("^(.+) | (.+) | +(.+)$")
@ -223,19 +221,22 @@ local function pdLinesFromDasm(dasm)
local addr = tonumber(addrh, 16) local addr = tonumber(addrh, 16)
if label then if label then
table.insert(lines, " | "..label..":") --table.insert(lines, " | "..label..":")
table.insert(lines, " | "..label..":")
lineidx = #lines lineidx = #lines
end end
table.insert(lines, addrh.." | "..text) --table.insert(lines, addrh.." | "..text)
table.insert(lines, addrh.." | "..datah.." | "..text)
local lineidx = #lines local lineidx = #lines
local len = 0; for _ in datah:gfind("[0-9a-fA-F][0-9a-fA-F]") do len = len+1 end; local len = 0; for _ in datah:gfind("[0-9a-fA-F][0-9a-fA-F]") do len = len+1 end;
for i = 1, len do addrLines[addr+i-1] = lineidx end for i = 1, len do addrLines[addr+i-1] = lineidx end
lineAddrs[lineidx] = addr
else else
table.insert(lines, "") table.insert(lines, "")
end end
end end
return lines, addrLines return lines, addrLines, lineAddrs
end end
local function InitProgramDisplay(pd, data, code, arch) local function InitProgramDisplay(pd, data, code, arch)
pd.width = 256 pd.width = 256
@ -246,25 +247,43 @@ local function InitProgramDisplay(pd, data, code, arch)
pd.data = data pd.data = data
pd.code = code pd.code = code
local dasm = asm.disassembleMemory(data, code, arch) local dasm = asm.disassembleMemory(data, code, arch)
pd.lines, pd.addrLines = pdLinesFromDasm(dasm) pd.lines, pd.addrLines, pd.lineAddrs = pdLinesFromDasm(dasm)
pd.midLine = math.floor(pd.numLines/2)
end end
local function RedrawProgramDisplay(pd, cpu) local function RedrawProgramDisplay(pd, cpu, mem)
lg.setColor(0,0,0) lg.setColor(0,0,0)
lg.rectangle("fill", pd.scrX, pd.scrY, pd.width-1, pd.height-1) lg.rectangle("fill", pd.scrX, pd.scrY, pd.width-1, pd.height-1)
lg.setColor(1,1,1) lg.setColor(1,1,1)
local instrAddr = (cpu.data.i-1)%65536 local rectwidth = pd.width-18
for lineidx = pd.firstLine, pd.firstLine+pd.numLines-1 do local rectheight = pd.fontHeight-1
local line = pd.lines[lineidx] local tickDraw = cpu.c.frame-pd.highlightTime
if line then
local x, y = pd.scrX+8, pd.scrY+8+(lineidx-1)*pd.fontHeight local instrAddr = (cpu.c.i-1)%65536
lg.print(line, x, y) local instrLine = pd.addrLines[instrAddr]
if pd.addrLines[instrAddr]==lineidx then if instrLine then
lg.rectangle("line", x, y, pd.width-18, pd.fontHeight-1) if pd.firstLine > instrLine then pd.firstLine = math.max(instrLine-pd.midLine, 1)
end elseif pd.firstLine+pd.numLines-1 < instrLine then pd.firstLine = math.min(instrLine-pd.numLines+pd.midLine, #pd.lines-pd.numLines+1)
end end
end end
--lg.print(pd.dasm or "nil", pd.scrX+8, pd.scrY+8) local screenlineidx = 0
for lineidx = pd.firstLine, pd.firstLine+pd.numLines-1 do
local line = pd.lines[lineidx]
local lineaddr = pd.lineAddrs[lineidx]
if line then
local x, y = pd.scrX+8, pd.scrY+4+screenlineidx*pd.fontHeight
if lineaddr and mem.c.reads[lineaddr] > tickDraw then
lg.rectangle("line", x, y, rectwidth, rectheight)
end
if instrLine==lineidx then
lg.rectangle("fill", x, y, rectwidth, rectheight)
lg.setColor(0,0,0)
end
lg.print(line, x, y)
lg.setColor(1,1,1)
end
screenlineidx = screenlineidx + 1
end
end end
local VideoDisplay = { local VideoDisplay = {
@ -428,26 +447,27 @@ struct CPU {
int rfg; int rfg;
int instr; int instr;
int cycle; int cycle;
int tick; int instrpre;
int frame;
}; };
int TickCPU(struct CPU* const cpu, struct Memory* const mem, const int count, const int countinstrs); int TickCPU(struct CPU* const cpu, struct Memory* const mem, const int count, const int countinstrs);
]] ]]
local CPU = { local CPU = {
data = ffi.new("struct CPU"), c = ffi.new("struct CPU"),
} }
local cpuDll = ffi.load("8608emulator.dll") local cpuDll = ffi.load("8608emulator.dll")
local function TickCPU(cpu, mem, count, countinstrs) local function TickCPU(cpu, mem, count, countinstrs)
local countleft = count local countleft = count
while countleft>0 do while countleft>0 do
countleft = cpuDll.TickCPU(cpu.data, mem.c, countleft, countinstrs and 1 or 0) countleft = cpuDll.TickCPU(cpu.c, mem.c, countleft, countinstrs and 1 or 0)
handleEvents(cpu, mem) handleEvents(cpu, mem)
end end
end end
local function InitCPU(cpu) local function InitCPU(cpu)
cpu.data.rfg = 1; cpu.c.rfg = 1;
end end
CPURequestInterrupt = function(cpu) CPURequestInterrupt = function(cpu)
cpu.data.irq = 1; cpu.c.irq = 1;
end end
---- ----
@ -511,7 +531,7 @@ local function RedrawWindow()
--RedrawVideoDisplay(VideoDisplay, Memory) --RedrawVideoDisplay(VideoDisplay, Memory)
RedrawRegDisplay(RegDisplay, CPU, Memory) RedrawRegDisplay(RegDisplay, CPU, Memory)
RedrawStackDisplay(StackDisplay, CPU, Memory) RedrawStackDisplay(StackDisplay, CPU, Memory)
RedrawProgramDisplay(ProgramDisplay, CPU) RedrawProgramDisplay(ProgramDisplay, CPU, Memory)
for _, md in ipairs(MemoryDisplays) do RedrawMemoryDisplay(md, CPU, Memory) end for _, md in ipairs(MemoryDisplays) do RedrawMemoryDisplay(md, CPU, Memory) end
RedrawFPSCounter(128+32, 4) RedrawFPSCounter(128+32, 4)
@ -531,7 +551,7 @@ function love.load()
InitCharDisplay(CharDisplay) InitCharDisplay(CharDisplay)
InitRegDisplay(RegDisplay) InitRegDisplay(RegDisplay)
InitStackDisplay(StackDisplay) InitStackDisplay(StackDisplay)
local data, code = AssembleToMemory(Memory, "../../8608programs/emutest.asm", Arch) local data, code = AssembleToMemory(Memory, arg[2] or "../../8608programs/emutest.asm", Arch)
InitProgramDisplay(ProgramDisplay, data, code, Arch) InitProgramDisplay(ProgramDisplay, data, code, Arch)
for _, md in ipairs(MemoryDisplays) do InitMemoryDisplay(md) end for _, md in ipairs(MemoryDisplays) do InitMemoryDisplay(md) end
RedrawWindow() RedrawWindow()
@ -541,7 +561,7 @@ end
local RunCPU = false local RunCPU = false
local CPUSpeed = 4999 local CPUSpeed = 4999
function love.draw() function love.draw()
CPU.data.tick = CPU.data.tick+1 CPU.c.frame = CPU.c.frame + 1
if RunCPU then if RunCPU then
TickCPU(CPU, Memory, CPUSpeed, false) TickCPU(CPU, Memory, CPUSpeed, false)
end end
@ -550,13 +570,14 @@ function love.draw()
lg.setColor(1,1,1) lg.setColor(1,1,1)
lg.draw(WindowCanvas, 0, 0, 0, 2, 2) lg.draw(WindowCanvas, 0, 0, 0, 2, 2)
lg.print(CPU.c.frame)
end end
function love.keypressed(k) function love.keypressed(k)
if k=="escape" then le.quit() if k=="escape" then le.quit()
elseif k=="t" then TickCPU(CPU, Memory, 1, true ) elseif k=="t" then TickCPU(CPU, Memory, 1, true )
elseif k=="e" then TickCPU(CPU, Memory, 1, false) elseif k=="e" then TickCPU(CPU, Memory, 1, false)
elseif k=="r" then RunCPU = not RunCPU elseif k=="r" then RunCPU = not RunCPU
elseif k=="i" then CPU.data.irq = 1 elseif k=="i" then CPU.c.irq = 1
else KeyboardOnKey(Keyboard, k, true, CPU, Memory) else KeyboardOnKey(Keyboard, k, true, CPU, Memory)
end end
end end