more emulator features, sub # instr

This commit is contained in:
Redo 2024-08-12 22:52:33 -06:00
parent 4ae98df548
commit 6de62423e8
11 changed files with 563 additions and 122 deletions

View File

@ -65,7 +65,9 @@ local instructions = {
{ mnem="ADD #" , opcode=0x6B, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAdd" ,"instrNext"}, desc="Add %imm8 to %A, %flags" , ccode={"loadimmedt","addf(cpu.a,cpu.t); lni;"} }, { mnem="ADD #" , opcode=0x6B, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAdd" ,"instrNext"}, desc="Add %imm8 to %A, %flags" , ccode={"loadimmedt","addf(cpu.a,cpu.t); lni;"} },
-- { mnem="ADB #" , opcode=0x , {"loadImmedT","instrSub1"}, {"aluB", "alurT","aluOpAdd" ,"instrNext"}, desc="" , ccode={"loadimmedt","addf(cpu.b,cpu.t); lni;"} }, -- { mnem="ADB #" , opcode=0x , {"loadImmedT","instrSub1"}, {"aluB", "alurT","aluOpAdd" ,"instrNext"}, desc="" , ccode={"loadimmedt","addf(cpu.b,cpu.t); lni;"} },
-- { mnem="ADC #" , opcode=0x , {"loadImmedT","instrSub1"}, {"aluC", "alurT","aluOpAdd" ,"instrNext"}, desc="" , ccode={"loadimmedt","addf(cpu.c,cpu.t); lni;"} }, -- { mnem="ADC #" , opcode=0x , {"loadImmedT","instrSub1"}, {"aluC", "alurT","aluOpAdd" ,"instrNext"}, desc="" , ccode={"loadimmedt","addf(cpu.c,cpu.t); lni;"} },
{ mnem="SUB #" , opcode=0xEB, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpSub" ,"instrNext"}, desc="Subtract %imm8 from %A, %flags" , ccode={"loadimmedt","subf(cpu.a,cpu.t); lni;"} },
{ mnem="ADC #" , opcode=0x69, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAddC","instrNext"}, desc="Add %imm8 plus the Carry Flag to %A, %flags" , ccode={"loadimmedt","addf(cpu.a,cpu.t+cpu.cf); lni;"} }, { mnem="ADC #" , opcode=0x69, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAddC","instrNext"}, desc="Add %imm8 plus the Carry Flag to %A, %flags" , ccode={"loadimmedt","addf(cpu.a,cpu.t+cpu.cf); lni;"} },
{ mnem="SBC #" , opcode=0xE9, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpSubC","instrNext"}, desc="Subtract %imm8 from %A including the Carry Flag, %flags" , ccode={"loadimmedt","addf(cpu.a,~cpu.t+cpu.cf); lni;"} },
{ mnem="CMP #" , opcode=0xC9, {"loadImmedT","instrSub1"}, {"alulA","alurT","aluOpSub" ,"instrNext"}, desc="%cmp %imm8 from %A" , ccode={"loadimmedt","cmpf(cpu.a,cpu.t); lni;"} }, { mnem="CMP #" , opcode=0xC9, {"loadImmedT","instrSub1"}, {"alulA","alurT","aluOpSub" ,"instrNext"}, desc="%cmp %imm8 from %A" , ccode={"loadimmedt","cmpf(cpu.a,cpu.t); lni;"} },
{ mnem="AND #" , opcode=0x29, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAnd" ,"instrNext"}, desc="Bitwise AND %A with %imm8, %zflag" , ccode={"loadimmedt","cpu.a&=cpu.t; setzf(cpu.a); lni;"} }, { mnem="AND #" , opcode=0x29, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAnd" ,"instrNext"}, desc="Bitwise AND %A with %imm8, %zflag" , ccode={"loadimmedt","cpu.a&=cpu.t; setzf(cpu.a); lni;"} },
{ mnem="ORA #" , opcode=0x09, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpIor" ,"instrNext"}, desc="Bitwise OR %A with %imm8, %zflag" , ccode={"loadimmedt","cpu.a|=cpu.t; setzf(cpu.a); lni;"} }, { mnem="ORA #" , opcode=0x09, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpIor" ,"instrNext"}, desc="Bitwise OR %A with %imm8, %zflag" , ccode={"loadimmedt","cpu.a|=cpu.t; setzf(cpu.a); lni;"} },
@ -82,7 +84,7 @@ local instructions = {
-- { mnem="sbb zpg" , opcode=0x , {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluB", "alurT","aluOpSub" ,"instrNext"}, desc="B-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.b,cpu.u); lni;"} }, -- { mnem="sbb zpg" , opcode=0x , {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluB", "alurT","aluOpSub" ,"instrNext"}, desc="B-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.b,cpu.u); lni;"} },
-- { mnem="sbc zpg" , opcode=0x , {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluC", "alurT","aluOpSub" ,"instrNext"}, desc="C-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.c,cpu.u); lni;"} }, -- { mnem="sbc zpg" , opcode=0x , {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluC", "alurT","aluOpSub" ,"instrNext"}, desc="C-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.c,cpu.u); lni;"} },
{ mnem="ADC zpg" , opcode=0x65, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAddC","instrNext"}, desc="Add %zpgIn plus the Carry Flag to %A, %flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.a,cpu.u+cpu.cf); lni;"} }, { mnem="ADC zpg" , opcode=0x65, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAddC","instrNext"}, desc="Add %zpgIn plus the Carry Flag to %A, %flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.a,cpu.u+cpu.cf); lni;"} },
{ mnem="SBC zpg" , opcode=0xE5, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpSubC","instrNext"}, desc="Subtract %zpgIn from %A including the Carry Flag, %flags", ccode={"loadimmedt","loadstackrelu","addf(cpu.a,-cpu.u+cpu.cf); lni;"} }, { mnem="SBC zpg" , opcode=0xE5, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpSubC","instrNext"}, desc="Subtract %zpgIn from %A including the Carry Flag, %flags", ccode={"loadimmedt","loadstackrelu","addf(cpu.a,~cpu.u+cpu.cf); lni;"} },
{ mnem="CMP zpg" , opcode=0xC5, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"alulA","alurT","aluOpSub" ,"instrNext"}, desc="%cmp %zpgIn from %A" , ccode={"loadimmedt","loadstackrelu","cmpf(cpu.a,cpu.u); lni;"} }, { mnem="CMP zpg" , opcode=0xC5, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"alulA","alurT","aluOpSub" ,"instrNext"}, desc="%cmp %zpgIn from %A" , ccode={"loadimmedt","loadstackrelu","cmpf(cpu.a,cpu.u); lni;"} },
{ mnem="AND zpg" , opcode=0x25, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAnd" ,"instrNext"}, desc="Bitwise AND %A with %zpgIn, %flags" , ccode={"loadimmedt","loadstackrelu","cpu.a&=cpu.u; setzf(cpu.a); lni;"} }, { mnem="AND zpg" , opcode=0x25, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAnd" ,"instrNext"}, desc="Bitwise AND %A with %zpgIn, %flags" , ccode={"loadimmedt","loadstackrelu","cpu.a&=cpu.u; setzf(cpu.a); lni;"} },
{ mnem="ORA zpg" , opcode=0x05, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpIor" ,"instrNext"}, desc="Bitwise OR %A with %zpgIn, %flags" , ccode={"loadimmedt","loadstackrelu","cpu.a|=cpu.u; setzf(cpu.a); lni;"} }, { mnem="ORA zpg" , opcode=0x05, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpIor" ,"instrNext"}, desc="Bitwise OR %A with %zpgIn, %flags" , ccode={"loadimmedt","loadstackrelu","cpu.a|=cpu.u; setzf(cpu.a); lni;"} },
@ -112,7 +114,7 @@ local instructions = {
{ mnem="SUB C" , opcode=0xFB, {"aluA", "alurC","aluOpSub" ,"instrNext"}, desc="Subtract %C from %A, %flags" , ccode={"subf(cpu.a,cpu.c); lni;"} }, { mnem="SUB C" , opcode=0xFB, {"aluA", "alurC","aluOpSub" ,"instrNext"}, desc="Subtract %C from %A, %flags" , ccode={"subf(cpu.a,cpu.c); lni;"} },
-- { mnem="sbb C" , opcode=0x , {"aluB", "alurC","aluOpSub" ,"instrNext"}, desc="B-=C, set flags" , ccode={"subf(cpu.b,cpu.c); lni;"} }, -- { mnem="sbb C" , opcode=0x , {"aluB", "alurC","aluOpSub" ,"instrNext"}, desc="B-=C, set flags" , ccode={"subf(cpu.b,cpu.c); lni;"} },
{ mnem="ADC C" , opcode=0x79, {"aluA", "alurC","aluOpAddC","instrNext"}, desc="Add %C plus the Carry Flag to %A, %flags" , ccode={"addf(cpu.a,cpu.c+cpu.cf); lni;"} }, { mnem="ADC C" , opcode=0x79, {"aluA", "alurC","aluOpAddC","instrNext"}, desc="Add %C plus the Carry Flag to %A, %flags" , ccode={"addf(cpu.a,cpu.c+cpu.cf); lni;"} },
{ mnem="SBC C" , opcode=0xF9, {"aluA", "alurC","aluOpSubC","instrNext"}, desc="Subtract %C form %A including the Carry Flag, %flags" , ccode={"addf(cpu.a,-cpu.c+cpu.cf); lni;"} }, { mnem="SBC C" , opcode=0xF9, {"aluA", "alurC","aluOpSubC","instrNext"}, desc="Subtract %C form %A including the Carry Flag, %flags" , ccode={"addf(cpu.a,~cpu.c+cpu.cf); lni;"} },
{ mnem="CMP C" , opcode=0xD9, {"alulA","alurC","aluOpSub" ,"instrNext"}, desc="%cmp %C from %A" , ccode={"cmpf(cpu.a,cpu.c); lni;"} }, { mnem="CMP C" , opcode=0xD9, {"alulA","alurC","aluOpSub" ,"instrNext"}, desc="%cmp %C from %A" , ccode={"cmpf(cpu.a,cpu.c); lni;"} },
{ mnem="AND C" , opcode=0x39, {"aluA", "alurC","aluOpAnd" ,"instrNext"}, desc="Bitwise AND %A with %C, %flags" , ccode={"cpu.a&=cpu.c; setzf(cpu.a); lni;"} }, { mnem="AND C" , opcode=0x39, {"aluA", "alurC","aluOpAnd" ,"instrNext"}, desc="Bitwise AND %A with %C, %flags" , ccode={"cpu.a&=cpu.c; setzf(cpu.a); lni;"} },
{ mnem="ORA C" , opcode=0x19, {"aluA", "alurC","aluOpIor" ,"instrNext"}, desc="Bitwise OR %A with %C, %flags" , ccode={"cpu.a|=cpu.c; setzf(cpu.a); lni;"} }, { mnem="ORA C" , opcode=0x19, {"aluA", "alurC","aluOpIor" ,"instrNext"}, desc="Bitwise OR %A with %C, %flags" , ccode={"cpu.a|=cpu.c; setzf(cpu.a); lni;"} },

View File

@ -41,7 +41,9 @@
DEC {value: u8} => $C6 @ value DEC {value: u8} => $C6 @ value
ICC {value: u8} => $47 @ value ICC {value: u8} => $47 @ value
ADD #{value: i8} => $6B @ value ADD #{value: i8} => $6B @ value
SUB #{value: i8} => $EB @ value
ADC #{value: i8} => $69 @ value ADC #{value: i8} => $69 @ value
SBC #{value: i8} => $E9 @ value
CMP #{value: i8} => $C9 @ value CMP #{value: i8} => $C9 @ value
AND #{value: i8} => $29 @ value AND #{value: i8} => $29 @ value
ORA #{value: i8} => $09 @ value ORA #{value: i8} => $09 @ value

Binary file not shown.

View File

@ -4,7 +4,12 @@
-- This file deals mostly with the user interface, controls, and high-level functions. -- This file deals mostly with the user interface, controls, and high-level functions.
-- Emulation of the CPU internals is done by the 8608emulator.dll library. See 8608emulator.c for details. -- Emulation of the CPU internals is done by the 8608emulator.dll library. See 8608emulator.c for details.
-- Number of frames to highlight memory and instructions when they're accessed
local MainHighlightTime = 8 local MainHighlightTime = 8
-- If true, char display renders in default print fallback mode; otherwise, terminal print mode is used
local PrintMode = true
-- Maximum number of CPU cycles per frame
local MaxTicksPerFrame = 555
require("colorset") require("colorset")
local ffi = require("ffi") local ffi = require("ffi")
@ -17,6 +22,11 @@ local lk = love.keyboard
local la = love.audio local la = love.audio
local PlaySound local PlaySound
local CPURequestInterrupt
local TimerSchedule
local TickCPU
local jsrInstrs = {0x20, 0x2C, 0x0C}
---- ----
local function InitColorset() local function InitColorset()
@ -220,15 +230,17 @@ local ProgramDisplay = {
fontHeight = 12, fontHeight = 12,
numLines = 34, numLines = 34,
highlightTime = MainHighlightTime, highlightTime = MainHighlightTime,
maxChars = 30,
} }
local function toPrintableChar(v) local function toPrintableChar(v)
if v>=0x20 and v<=0x7E then return string.char(v) if v>=0x20 and v<=0x7E then return string.char(v)
else return "\\x"..string.format("%02X", v) end else return "\\x"..string.format("%02X", v) end
end end
local function pdLinesFromDasm(dasm) local function pdLinesFromDasm(dasm, maxChars)
local div = " | " local div = "|"
local lines, addrLines, lineAddrs = {}, {}, {} local lines, addrLines, lineAddrs = {}, {}, {}
local function addDasmLine(addr, data, text) local function addDasmLine(addr, data, text)
text = text:sub(1, maxChars - #div*2 - 8)
local dataStr = "" local dataStr = ""
if data then if data then
local dt = {} local dt = {}
@ -274,7 +286,7 @@ local function pdLinesFromDasm(dasm)
local datastr = {} local datastr = {}
for v in datah:gfind("[0-9a-fA-F][0-9a-fA-F]") do for v in datah:gfind("[0-9a-fA-F][0-9a-fA-F]") do
if #data>=maxlen then if #data>=maxlen then
addDasmLine(addr+len-#data, data, "\""..table.concat(datastr.."\"")) addDasmLine(addr+len-#data, data, "\""..table.concat(datastr).."\"")
data = {} data = {}
datastr = {} datastr = {}
end end
@ -285,7 +297,7 @@ local function pdLinesFromDasm(dasm)
if len<=maxlen then if len<=maxlen then
addDasmLine(addr, data, text) addDasmLine(addr, data, text)
elseif #data>0 then elseif #data>0 then
addDasmLine(addr+len-#data, data, "\""..table.concat(datastr.."\"")) addDasmLine(addr+len-#data, data, "\""..table.concat(datastr).."\"")
end end
end end
end end
@ -298,7 +310,7 @@ local function InitProgramDisplay(pd, dasmText)
lg.print("Program", pd.scrX, pd.scrY-12) lg.print("Program", pd.scrX, pd.scrY-12)
lg.rectangle("line", pd.scrX, pd.scrY, pd.width, pd.height) lg.rectangle("line", pd.scrX, pd.scrY, pd.width, pd.height)
pd.firstLine = 1 pd.firstLine = 1
pd.lines, pd.addrLines, pd.lineAddrs = pdLinesFromDasm(dasmText) pd.lines, pd.addrLines, pd.lineAddrs = pdLinesFromDasm(dasmText, pd.maxChars)
pd.midLine = math.floor(pd.numLines/2) pd.midLine = math.floor(pd.numLines/2)
pd.init = true pd.init = true
end end
@ -368,7 +380,7 @@ local function InitCharDisplay(cd)
end end
local Keyboard = { local Keyboard = {
addrRange = {0x0500, 0x05FF}, addrRange = {0xF100, 0xF1FF},
queueSize = 16, queueSize = 16,
queue = {}, queue = {},
interrupts = false, interrupts = false,
@ -392,7 +404,6 @@ local function KeyboardOnWrite(addr, cpu, mem, kb)
mem.c.data[addr] = kb.queue[1] or 0 mem.c.data[addr] = kb.queue[1] or 0
end end
local keycodes = require("keycodes") local keycodes = require("keycodes")
local CPURequestInterrupt
local function KeyboardOnKey(kb, key, press, cpu, mem) local function KeyboardOnKey(kb, key, press, cpu, mem)
local code = keycodes[key] or keycodes["invalid"] local code = keycodes[key] or keycodes["invalid"]
if code==0x7F then print("invalid key: "..key) end if code==0x7F then print("invalid key: "..key) end
@ -431,10 +442,11 @@ local function RedrawKeyInfo(x, y, uk, run)
printHighlight("[R] "..(run and "Stop" or "Run "), 23, lk.isDown("r"), x, y) printHighlight("[R] "..(run and "Stop" or "Run "), 23, lk.isDown("r"), x, y)
if not run then if not run then
printHighlight("[S] Step" , 33, lk.isDown("s"), x, y) printHighlight("[S] Step" , 33, lk.isDown("s"), x, y)
end
-- printHighlight("[T] Tick once" , 48, lk.isDown("t"), x, y) -- printHighlight("[T] Tick once" , 48, lk.isDown("t"), x, y)
printHighlight("[I] Interrupt" , 43, lk.isDown("i"), x, y) printHighlight("[X] Step Over" , 43, lk.isDown("x"), x, y)
printHighlight("[Q] Quit" , 70, lk.isDown("q"), x, y) end
printHighlight("[I] Interrupt" , 58, lk.isDown("i"), x, y)
printHighlight("[Q] Quit" , 73, lk.isDown("q"), x, y)
end end
end end
@ -471,12 +483,15 @@ local function gpioDiv(addr, cpu, mem, gpio)
WriteMemory(mem, base+0x02, math.floor(gpio.divLeft/gpio.divRight)) WriteMemory(mem, base+0x02, math.floor(gpio.divLeft/gpio.divRight))
WriteMemory(mem, base+0x03, gpio.divLeft%gpio.divRight) WriteMemory(mem, base+0x03, gpio.divLeft%gpio.divRight)
end end
local function gpioPopcount(v)
return 0 -- todo
end
local gpioFunctions = { local gpioFunctions = {
[0x00] = gpioSetValue("mulLeft" , gpioMul), [0x00] = gpioSetValue("mulLeft" , gpioMul),
[0x01] = gpioSetValue("mulRight", gpioMul), [0x01] = gpioSetValue("mulRight", gpioMul),
[0x02] = gpioSetValue("divLeft" , gpioDiv), [0x02] = gpioSetValue("divLeft" , gpioDiv),
[0x03] = gpioSetValue("divRight", gpioDiv), [0x03] = gpioSetValue("divRight", gpioDiv),
[0x04] = function(addr, cpu, mem, gpio) WriteMemory(mem, addr, gpioPopcount(readMemory(mem, addr))) end, [0x04] = function(addr, cpu, mem, gpio) WriteMemory(mem, addr, gpioPopcount(ReadMemory(mem, addr))) end,
[0x05] = function(addr, cpu, mem, gpio) gpio.timerCount = 60/10; WriteMemory(mem, addr, 0); end [0x05] = function(addr, cpu, mem, gpio) gpio.timerCount = 60/10; WriteMemory(mem, addr, 0); end
} }
local function GPIOOnWrite(addr, cpu, mem, gpio) local function GPIOOnWrite(addr, cpu, mem, gpio)
@ -516,31 +531,124 @@ local function InitConsole(con)
con.prevInputIdx = 0 con.prevInputIdx = 0
con.tempError = nil con.tempError = nil
end end
local function RedrawConsole(con) local function RedrawConsole(con, kb)
lg.setColor(0,0,0) lg.setColor(0,0,0)
lg.rectangle("fill", con.scrX, con.scrY, con.width, con.height) lg.rectangle("fill", con.scrX, con.scrY, con.width, con.height)
lg.setColor(1,1,1) lg.setColor(1,1,1)
lg.rectangle("line", con.scrX, con.scrY, con.width, con.height) lg.rectangle("line", con.scrX, con.scrY, con.width, con.height)
if con.blinkFrame < con.blinkFrames/2 then if not kb then
local curx, cury = con.scrX + #con.input*7 + 2, con.scrY+3 if con.blinkFrame < con.blinkFrames/2 then
lg.rectangle("fill", curx, cury, 8, 12) local curx, cury = con.scrX + #con.input*7 + 2, con.scrY+3
end lg.rectangle("fill", curx, cury, 8, 12)
con.blinkFrame = con.blinkFrame + 1 end
if con.blinkFrame >= con.blinkFrames then con.blinkFrame = 0 end con.blinkFrame = con.blinkFrame + 1
if #con.input==0 then if con.blinkFrame >= con.blinkFrames then con.blinkFrame = 0 end
lg.setColor(0.5,0.5,0.5) if #con.input==0 then
lg.print(con.tempError or "Type a Command (@addr | addr=byte | addr=byte1 byte2 ...)", con.scrX+2+8, con.scrY+4) lg.setColor(0.5,0.5,0.5)
else lg.print(con.tempError or "Enter Command (>ticks | !addr | @addr | addr=byte | addr=byte1 byte2...)", con.scrX+2+8, con.scrY+4)
lg.print(con.input, con.scrX+2, con.scrY+4) else
lg.print(con.input, con.scrX+2, con.scrY+4)
end
end end
end end
local function ConsoleError(con, err) local function ConsoleError(con, err)
con.tempError = err con.tempError = err
end end
local function ConsoleExec(con, mem) local function conWriteDataBlock(con, mem, addr, data)
local writeTime = 2
ConsoleError(con, "Writing")
for i, byte in ipairs(data) do
TimerSchedule((i-1)*writeTime, function()
if con.tempError ~= nil then
con.tempError = con.tempError .. "."
end
mem.c.data[(addr+i-1)%65536] = byte
PlaySound("write")
end)
end
TimerSchedule((#data-1)*writeTime, function()
PlaySound("writeDone")
PlaySound("success")
ConsoleError(con, "Wrote " .. #data .. " byte" .. (#data>1 and "s" or "") .. " to address $" .. string.format("%04X", addr))
end)
end
local function tickCpuOnce(cpu, mem, byInstr)
TickCPU(cpu, mem, 1, byInstr, nil)
end
local function tickCpuUntil(con, cpu, mem, contfunc, strfunc, donestr, step)
con.tempError = ""
local tickTime = 1
local tickStep, byInstr
if step then
tickStep = step
byInstr = true
else
tickStep = MaxTicksPerFrame
byInstr = false
end
local i = 1
local recFunc
recFunc = function()
for j = 1, tickStep do
if contfunc(i) then
tickCpuOnce(cpu, mem, byInstr)
else
PlaySound("writeDone")
PlaySound("success")
ConsoleError(con, donestr)
return
end
i = i+1
end
if con.tempError ~= nil then
con.tempError = strfunc(i)
end
PlaySound("write")
TimerSchedule(tickTime, recFunc)
end
recFunc()
end
local function tickCpuStepOver(con, cpu, mem, pd)
local stepOver = false
for _, v in ipairs(jsrInstrs) do
if cpu.c.instr == v then
stepOver = true
end
end
if not stepOver then
tickCpuOnce(cpu, mem, true)
return
end
local line = pd.addrLines and pd.addrLines[(cpu.c.i-1)%65536]
if not line then
tickCpuOnce(cpu, mem, true)
return
end
local addr
while not addr do
line = line+1
local addrs = pd.lineAddrs[line]
if not addrs then
tickCpuOnce(cpu, mem, true)
return
end
addr = addrs[1]
end
--print(string.format("%04X", addr))
tickCpuUntil(con, cpu, mem,
--function() return (cpu.c.i ~= (addr+1)%65536) and (cpu.c.rfg==1) end,
function() return (cpu.c.i ~= (addr+1)%65536) end,
function() return "Running to address $" .. string.format("%04X", addr) end,
nil,
nil
)
end
local function ConsoleExec(con, cpu, mem)
PlaySound("enter") PlaySound("enter")
if con.input=="" then if con.input=="" then
PlaySound("error") PlaySound("error")
con.tempError = nil
return return
end end
@ -564,6 +672,69 @@ local function ConsoleExec(con, mem)
MemoryDisplays[1].addr = addr MemoryDisplays[1].addr = addr
ConsoleError(con, "Memory display set to address $" .. string.format("%04X", addr)) ConsoleError(con, "Memory display set to address $" .. string.format("%04X", addr))
PlaySound("success") PlaySound("success")
elseif ip:sub(1, 1)=="!" then
if RunCPU then
ConsoleError(con, "CPU must be paused to change execution")
PlaySound("error")
return
end
local rest = ip:sub(2, #ip)
local addr = tonumber(rest, 16)
if not addr then
ConsoleError(con, "Error: Expected a hex number")
PlaySound("error")
return
end
if addr<0 then addr = 0 end
if addr>65535 then addr = 65535 end
cpu.c.i = (addr+1)%65536
cpu.c.cycle = 0
cpu.c.instr = ReadMemory(mem, addr)
ConsoleError(con, "CPU instruction pointer set to $" .. string.format("%04X", addr))
PlaySound("success")
elseif ip:sub(1, 2)==">>" then
if RunCPU then
ConsoleError(con, "CPU must be paused to step")
PlaySound("error")
return
end
local rest = ip:sub(3, #ip)
local addr = tonumber(rest, 16)
if not addr then
ConsoleError(con, "Error: Expected a hex number")
PlaySound("error")
return
end
if addr<0 then addr = 0 end
if addr>65535 then addr = 65535 end
tickCpuUntil(con, cpu, mem,
function() return cpu.c.i ~= (addr+1)%65536 end,
function() return "Running to address $" .. string.format("%04X", addr) end,
"Ran to address " .. string.format("%04X", addr),
nil
)
elseif ip:sub(1, 1)==">" then
if RunCPU then
ConsoleError(con, "CPU must be paused to single-step")
PlaySound("error")
return
end
local rest = ip:sub(2, #ip)
local steps = tonumber(rest, 16)
if rest=="" then steps = 1 end
if not steps then
ConsoleError(con, "Error: Expected a hex number")
PlaySound("error")
return
end
if steps<1 then steps = 1 end
if steps>65535 then steps = 65535 end
tickCpuUntil(con, cpu, mem,
function(i) return i<=steps; end,
function(i) return "Step $"..string.format("%X", i).."/$"..string.format("%X", steps) end,
"Ran $" .. string.format("%02X", steps) .. " steps",
steps<(MaxTicksPerFrame/4) and steps or nil
)
elseif ip:find("=") then elseif ip:find("=") then
local addrS, rest = ip:match("^ *([0-9a-fA-F]+) *= *([0-9a-fA-F ]+)$") local addrS, rest = ip:match("^ *([0-9a-fA-F]+) *= *([0-9a-fA-F ]+)$")
local addr = tonumber(addrS or "", 16) local addr = tonumber(addrS or "", 16)
@ -582,27 +753,27 @@ local function ConsoleExec(con, mem)
end end
table.insert(data, byte) table.insert(data, byte)
end end
for i, byte in ipairs(data) do
mem.c.data[(addr+i-1)%65536] = byte conWriteDataBlock(con, mem, addr, data)
PlaySound("write", i) else
end ConsoleError(con, "Error: Unknown command")
PlaySound("writeDone", #data) PlaySound("error")
PlaySound("success", #data)
ConsoleError(con, "Wrote " .. #data .. " byte" .. (#data>1 and "s" or "") .. " to address $" .. string.format("%04X", addr))
end end
end end
local function shiftDown() local function shiftDown()
return lk.isDown("lshift") or lk.isDown("rshift") return lk.isDown("lshift") or lk.isDown("rshift")
end end
local function ConsoleKey(con, k, mem) local function ConsoleKey(con, k, cpu, mem)
local add local add
if k=="backspace" then con.input = con.input:sub(1, #con.input-1) if k=="backspace" then con.input = con.input:sub(1, #con.input-1)
elseif shiftDown() and k=="1" then add = "!"
elseif shiftDown() and k=="2" then add = "@" elseif shiftDown() and k=="2" then add = "@"
elseif shiftDown() and k=="." then add = ">"
elseif k>="0" and k<="9" then add = k elseif k>="0" and k<="9" then add = k
elseif #k==1 and k>="a" and k<="f" then add = k:upper() elseif #k==1 and k>="a" and k<="f" then add = k:upper()
elseif k=="=" then add = "=" elseif k=="=" then add = "="
elseif k=="space" then add = " " elseif k=="space" then add = " "
elseif k=="return" then ConsoleExec(con, mem) elseif k=="return" then ConsoleExec(con, cpu, mem)
elseif k=="up" and con.prevInputs[con.prevInputIdx+1] then elseif k=="up" and con.prevInputs[con.prevInputIdx+1] then
if con.prevInputIdx==0 then con.prevInputs[0] = con.input end if con.prevInputIdx==0 then con.prevInputs[0] = con.input end
con.prevInputIdx = con.prevInputIdx + 1 con.prevInputIdx = con.prevInputIdx + 1
@ -637,6 +808,10 @@ local soundNames = {
"success", "success",
"write","writeDone", "write","writeDone",
} }
local soundCounts = {
--["step"] = 100,
["write"] = 100,
}
local function InitSound() local function InitSound()
for _, name in ipairs(soundNames) do for _, name in ipairs(soundNames) do
local sound = { local sound = {
@ -645,33 +820,36 @@ local function InitSound()
lastPlayed = 0, lastPlayed = 0,
} }
local fn = "content/" .. name .. ".wav" local fn = "content/" .. name .. ".wav"
for i = 1, 4 do for i = 1, soundCounts[name] or 4 do
table.insert(sound.sources, la.newSource(fn, "static")) table.insert(sound.sources, la.newSource(fn, "static"))
end end
Sounds[name] = sound Sounds[name] = sound
end end
end end
local SoundFrame = 0 PlaySound = function(name)
local QueuedSounds = {} local sound = Sounds[name] or error("no sound with name: " .. name)
PlaySound = function(name, delay) sound.lastPlayed = (sound.lastPlayed % #sound.sources) + 1
if (not delay) or delay==0 then sound.sources[sound.lastPlayed]:play()
local sound = Sounds[name] or error("no sound with name: " .. name)
sound.lastPlayed = (sound.lastPlayed % #sound.sources) + 1
sound.sources[sound.lastPlayed]:play()
else
local time = SoundFrame + delay
QueuedSounds[time] = QueuedSounds[time] or {}
table.insert(QueuedSounds[time], name)
end
end end
local function UpdateSound()
if QueuedSounds[SoundFrame] then ----
for _, name in ipairs(QueuedSounds[SoundFrame]) do -- Timer
PlaySound(name)
local TimerFrame = 0
local TimerSchedules = {}
TimerSchedule = function(time, func)
local frame = TimerFrame + time
TimerSchedules[frame] = TimerSchedules[frame] or {}
table.insert(TimerSchedules[frame], func)
end
local function UpdateTimer()
if TimerSchedules[TimerFrame] then
for _, func in ipairs(TimerSchedules[TimerFrame]) do
func()
end end
QueuedSounds[SoundFrame] = nil TimerSchedules[TimerFrame] = nil
end end
SoundFrame = SoundFrame + 1 TimerFrame = TimerFrame + 1
end end
@ -777,7 +955,7 @@ local CPU = {
c = 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, breakaddr) TickCPU = function(cpu, mem, count, countinstrs, breakaddr)
local countleft = count local countleft = count
while countleft>0 do while countleft>0 do
countleft = cpuDll.TickCPU(cpu.c, mem.c, countleft, countinstrs and 1 or 0, breakaddr or 0xFFFFFFFF) countleft = cpuDll.TickCPU(cpu.c, mem.c, countleft, countinstrs and 1 or 0, breakaddr or 0xFFFFFFFF)
@ -792,10 +970,6 @@ CPURequestInterrupt = function(cpu)
cpu.c.irq = 1; cpu.c.irq = 1;
end end
function RunToNextInstr(cpu)
end
---- ----
--local function RedrawVideoDisplay(vd, mem) --local function RedrawVideoDisplay(vd, mem)
@ -825,20 +999,32 @@ local function RedrawCharDisplay(cd, mem)
local acolor = cd.addrColor + abase local acolor = cd.addrColor + abase
local colormem = ReadMemory(mem, acolor) local colormem = ReadMemory(mem, acolor)
local colorid = colormem%64 local colorid = colormem%64
local highlight = colormem>=128 local highlight = PrintMode or colormem>=128
lg.setColor(ColorSet[colorid]) lg.setColor(ColorSet[colorid])
local scrx = cd.scrX + cx*cd.fontWidth
local scry = cd.scrY + cy*cd.fontHeight
local scrw = cd.fontWidth
local scrh = cd.fontHeight
if highlight then if highlight then
lg.rectangle("fill", cd.scrX + cx*cd.fontWidth, cd.scrY + cy*cd.fontHeight, cd.fontWidth, cd.fontHeight) lg.rectangle("fill", scrx, scry, scrw, scrh)
lg.setColor(0, 0, 0) if PrintMode then lg.setColor(1,1,1) else lg.setColor(0,0,0) end
end end
local val = ReadMemory(mem, achar)%128 local val = ReadMemory(mem, achar)%128
if val>=32 then if val>=0x20 and val<=0x7F then -- printable ascii
local char = string.char(val) local char = string.char(val)
lg.print(char, cd.scrX + cx*cd.fontWidth, cd.scrY + cy*cd.fontHeight) lg.print(char, scrx, scry)
elseif val>=16 and val<=31 then elseif val>=0x10 and val<=0x17 then -- solid color
local r, g, b = math.floor(val/4)%2, math.floor(val/2)%2, val%2 local r, g, b = math.floor(val/4)%2, math.floor(val/2)%2, val%2
lg.setColor(r, g, b) lg.setColor(r, g, b)
lg.rectangle("fill", cd.scrX + cx*cd.fontWidth, cd.scrY + cy*cd.fontHeight, cd.fontWidth, cd.fontHeight) lg.rectangle("fill", scrx, scry, scrw, scrh)
elseif val>=0x80 and val<=0x8F then -- 2x2 pixels
lg.setColor(0,0,0)
if val %2==1 then lg.rectangle("fill", scrx+scrw/2, scry+scrh/2, scrw/2, scrh/2) end -- bottom right
if math.floor(val/2)%2==1 then lg.rectangle("fill", scrx , scry+scrh/2, scrw/2, scrh/2) end -- bottom left
if math.floor(val/4)%2==1 then lg.rectangle("fill", scrx+scrw/2, scry , scrw/2, scrh/2) end -- top right
if math.floor(val/4)%2==1 then lg.rectangle("fill", scrx , scry , scrw/2, scrh/2) end -- top left
elseif val>=0xA0 and val<=0xDF then -- kana
-- todo
end end
end end
end end
@ -861,9 +1047,9 @@ local function RedrawWindow(usekeyboard, runcpu)
RedrawStackDisplay(StackDisplay, CPU, Memory) RedrawStackDisplay(StackDisplay, CPU, Memory)
RedrawProgramDisplay(ProgramDisplay, CPU, Memory) 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, 4)
RedrawKeyInfo(128+32+64+16, 4, usekeyboard, runcpu) RedrawKeyInfo(128+64+16, 4, usekeyboard, runcpu)
RedrawConsole(Console) RedrawConsole(Console, usekeyboard)
lg.setCanvas() lg.setCanvas()
end end
@ -955,13 +1141,14 @@ local function endFrame()
end end
local RunCPU = false local RunCPU = false
local CPUSpeed = 555 local CPUSpeed = MaxTicksPerFrame
local UseKeyboard = false local UseKeyboard = false
function love.draw() function love.draw()
startFrame() startFrame()
UpdateTimer()
UpdateGPIO(GPIO, CPU, Memory) UpdateGPIO(GPIO, CPU, Memory)
UpdateSound()
CPU.c.frame = CPU.c.frame + 1 CPU.c.frame = CPU.c.frame + 1
if RunCPU then if RunCPU then
@ -984,14 +1171,14 @@ function love.keypressed(k)
KeyboardOnKey(Keyboard, k, true, CPU, Memory) KeyboardOnKey(Keyboard, k, true, CPU, Memory)
else else
if k=="q" then le.quit() if k=="q" then le.quit()
elseif k=="s" and not RunCPU then TickCPU(CPU, Memory, 1, true , nil); PlaySound("step"); elseif k=="s" and (not RunCPU) then tickCpuOnce(CPU, Memory, true); PlaySound("step");
elseif k=="x" and (not RunCPU) then tickCpuStepOver(Console, CPU, Memory, ProgramDisplay); PlaySound("step");
--elseif k=="t" then TickCPU(CPU, Memory, 1, false, nil) --elseif k=="t" then TickCPU(CPU, Memory, 1, false, nil)
--elseif k=="o" then RunToNextInstr(cpu)
elseif k=="r" then RunCPU = not RunCPU; PlaySound(RunCPU and "runOn" or "runOff"); elseif k=="r" then RunCPU = not RunCPU; PlaySound(RunCPU and "runOn" or "runOff");
elseif k=="i" then CPU.c.irq = 1; PlaySound("interrupt"); elseif k=="i" then CPU.c.irq = 1; PlaySound("interrupt");
--elseif k=="u" then CPU.c.rfg = 1 --elseif k=="u" then CPU.c.rfg = 1
else else
ConsoleKey(Console, k, Memory) ConsoleKey(Console, k, CPU, Memory)
end end
end end
end end

View File

@ -414,7 +414,7 @@ void cpu_instr_227_0(struct CPU* const cpu, struct Memory* const mem) { cpu->b=l
void cpu_instr_227_1(struct CPU* const cpu, struct Memory* const mem) { lni; } void cpu_instr_227_1(struct CPU* const cpu, struct Memory* const mem) { lni; }
void cpu_instr_229_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; } void cpu_instr_229_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; }
void cpu_instr_229_1(struct CPU* const cpu, struct Memory* const mem) { loadstackrelu cpu->cycle++; } void cpu_instr_229_1(struct CPU* const cpu, struct Memory* const mem) { loadstackrelu cpu->cycle++; }
void cpu_instr_229_2(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a,-cpu->u+cpu->cf); lni; } void cpu_instr_229_2(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a,~cpu->u+cpu->cf); lni; }
void cpu_instr_230_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; } void cpu_instr_230_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; }
void cpu_instr_230_1(struct CPU* const cpu, struct Memory* const mem) { loadstackrelu cpu->cycle++; } void cpu_instr_230_1(struct CPU* const cpu, struct Memory* const mem) { loadstackrelu cpu->cycle++; }
void cpu_instr_230_2(struct CPU* const cpu, struct Memory* const mem) { instrpreload; addf(cpu->u, 1 ); cpu->cycle++; } void cpu_instr_230_2(struct CPU* const cpu, struct Memory* const mem) { instrpreload; addf(cpu->u, 1 ); cpu->cycle++; }
@ -424,7 +424,11 @@ void cpu_instr_231_1(struct CPU* const cpu, struct Memory* const mem) { loadstac
void cpu_instr_231_2(struct CPU* const cpu, struct Memory* const mem) { subf(cpu->a,cpu->u); lni; } void cpu_instr_231_2(struct CPU* const cpu, struct Memory* const mem) { subf(cpu->a,cpu->u); lni; }
void cpu_instr_232_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; } void cpu_instr_232_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; }
void cpu_instr_232_1(struct CPU* const cpu, struct Memory* const mem) { cpu->p=(cpu->p+signed8(cpu->t))%65536; lni; } void cpu_instr_232_1(struct CPU* const cpu, struct Memory* const mem) { cpu->p=(cpu->p+signed8(cpu->t))%65536; lni; }
void cpu_instr_233_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; }
void cpu_instr_233_1(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a,~cpu->t+cpu->cf); lni; }
void cpu_instr_234_0(struct CPU* const cpu, struct Memory* const mem) { lni; } void cpu_instr_234_0(struct CPU* const cpu, struct Memory* const mem) { lni; }
void cpu_instr_235_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; }
void cpu_instr_235_1(struct CPU* const cpu, struct Memory* const mem) { subf(cpu->a,cpu->t); lni; }
void cpu_instr_237_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } void cpu_instr_237_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; }
void cpu_instr_237_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } void cpu_instr_237_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; }
void cpu_instr_237_2(struct CPU* const cpu, struct Memory* const mem) { cpu->a=loadut; setzf(cpu->a); cpu->cycle++; } void cpu_instr_237_2(struct CPU* const cpu, struct Memory* const mem) { cpu->a=loadut; setzf(cpu->a); cpu->cycle++; }
@ -444,7 +448,7 @@ void cpu_instr_243_0(struct CPU* const cpu, struct Memory* const mem) { cpu->b=l
void cpu_instr_243_1(struct CPU* const cpu, struct Memory* const mem) { lni; } void cpu_instr_243_1(struct CPU* const cpu, struct Memory* const mem) { lni; }
void cpu_instr_246_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a, 1 ); lni; } void cpu_instr_246_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a, 1 ); lni; }
void cpu_instr_247_0(struct CPU* const cpu, struct Memory* const mem) { cpu->c=cpu->b; lni; } void cpu_instr_247_0(struct CPU* const cpu, struct Memory* const mem) { cpu->c=cpu->b; lni; }
void cpu_instr_249_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a,-cpu->c+cpu->cf); lni; } void cpu_instr_249_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a,~cpu->c+cpu->cf); lni; }
void cpu_instr_250_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->c, 1 ); lni; } void cpu_instr_250_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->c, 1 ); lni; }
void cpu_instr_251_0(struct CPU* const cpu, struct Memory* const mem) { subf(cpu->a,cpu->c); lni; } void cpu_instr_251_0(struct CPU* const cpu, struct Memory* const mem) { subf(cpu->a,cpu->c); lni; }
void cpu_instr_252_0(struct CPU* const cpu, struct Memory* const mem) { cpu->p=(cpu->p+signed8(cpu->a))%65536; lni; } void cpu_instr_252_0(struct CPU* const cpu, struct Memory* const mem) { cpu->p=(cpu->p+signed8(cpu->a))%65536; lni; }
@ -686,9 +690,9 @@ CPUInstruction CPUInstructions[256][8] = {
{cpu_instr_230_0,cpu_instr_230_1,cpu_instr_230_2,cpu_instr_230_3,0,0,0,0}, {cpu_instr_230_0,cpu_instr_230_1,cpu_instr_230_2,cpu_instr_230_3,0,0,0,0},
{cpu_instr_231_0,cpu_instr_231_1,cpu_instr_231_2,0,0,0,0,0}, {cpu_instr_231_0,cpu_instr_231_1,cpu_instr_231_2,0,0,0,0,0},
{cpu_instr_232_0,cpu_instr_232_1,0,0,0,0,0,0}, {cpu_instr_232_0,cpu_instr_232_1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0}, {cpu_instr_233_0,cpu_instr_233_1,0,0,0,0,0,0},
{cpu_instr_234_0,0,0,0,0,0,0,0}, {cpu_instr_234_0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0}, {cpu_instr_235_0,cpu_instr_235_1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0},
{cpu_instr_237_0,cpu_instr_237_1,cpu_instr_237_2,cpu_instr_237_3,0,0,0,0}, {cpu_instr_237_0,cpu_instr_237_1,cpu_instr_237_2,cpu_instr_237_3,0,0,0,0},
{0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0},

View File

@ -1,18 +1,19 @@
-- These are the keycodes provided by the keyboard peripheral to the CPU within the emulator.
-- copied from Brick_LuaLogic/bricks/input/keyboard-global.lua -- copied from Brick_LuaLogic/bricks/input/keyboard-global.lua
-- with some key names changed from Torque format to LOVE format.
return { return {
["backspace"] = 8, ["backspace"] = 8,
["tab"] = 9, ["tab"] = 9,
["return"] = 13, ["return"] = 13,
["lshift"] = 16, ["lshift"] = 16, -- 0x10
["lcontrol"] = 17, ["lctrl"] = 17, --["lcontrol"] = 17,
["lalt"] = 18, ["lalt"] = 18,
-- this block does not match vkey codes -- this block does not match vkey codes
["rshift"] = 20, ["rshift"] = 20, -- 0x14
["rcontrol"] = 21, ["rctrl"] = 21, --["rcontrol"] = 21,
["ralt"] = 22, ["ralt"] = 22,
-- this block does not match vkey codes -- this block does not match vkey codes
@ -20,6 +21,7 @@ return {
["="] = 25, ["="] = 25,
[","] = 26, [","] = 26,
["."] = 27, ["."] = 27,
["-"] = 28, -- not in bl
["/"] = 29, ["/"] = 29,
["`"] = 30, ["`"] = 30,
@ -50,7 +52,7 @@ return {
["["] = 60, ["["] = 60,
["\\"] = 61, ["\\"] = 61,
["]"] = 62, ["]"] = 62,
["apostrophe"] = 63, ["\'"] = 63, --["apostrophe"] = 63,
["a"] = 65, ["a"] = 65,
["b"] = 66, ["b"] = 66,
@ -79,22 +81,22 @@ return {
["y"] = 89, ["y"] = 89,
["z"] = 90, ["z"] = 90,
["numpad0"] = 96, ["kp0"] = 96, --["numpad0"] = 96,
["numpad1"] = 97, ["kp1"] = 97, --["numpad1"] = 97,
["numpad2"] = 98, ["kp2"] = 98, --["numpad2"] = 98,
["numpad3"] = 99, ["kp3"] = 99, --["numpad3"] = 99,
["numpad4"] = 100, ["kp4"] = 100, --["numpad4"] = 100,
["numpad5"] = 101, ["kp5"] = 101, --["numpad5"] = 101,
["numpad6"] = 102, ["kp6"] = 102, --["numpad6"] = 102,
["numpad7"] = 103, ["kp7"] = 103, --["numpad7"] = 103,
["numpad8"] = 104, ["kp8"] = 104, --["numpad8"] = 104,
["numpad9"] = 105, ["kp9"] = 105, --["numpad9"] = 105,
["*"] = 106, ["kp*"] = 106, --["*"] = 106,
["+"] = 107, ["kp+"] = 107, --["+"] = 107,
["numpadenter"] = 108, ["kpenter"] = 108, --["numpadenter"] = 108,
["minus"] = 109, ["kp-"] = 109, --["minus"] = 109,
["numpaddecimal"] = 110, ["kp."] = 110, --["numpaddecimal"] = 110,
--["/"] = 111, -- already 29 ["kp/"] = 111, --["/"] = 111,
["f1"] = 112, ["f1"] = 112,
["f2"] = 113, ["f2"] = 113,
@ -109,5 +111,5 @@ return {
["f11"] = 122, ["f11"] = 122,
["f12"] = 123, ["f12"] = 123,
["invalid"] = 127, --["invalid"] = 127,
} }

Binary file not shown.

View File

@ -1,18 +1,260 @@
outp | addr | data (base 16) outp | addr | data (base 16)
0:0 | 0 | ; FAIL: 0:0 | 0 | ; CURSORPOS:
0:0 | 0 | fa ; INC C 2:0 | 2 | ; SHIFTDOWN:
1:0 | 1 | 98 fd ; BRA FAIL 3:0 | 3 | ; TESTCHAR:
3:0 | 3 | ; RESET: fc00:0 | fc00 | fc 20 ; PRINTCHAR
3:0 | 3 | 58 ; CLI fc02:0 | fc02 | fd 1b ; GETCHAR
4:0 | 4 | fe ; INC B fc04:0 | fc04 | fc 92 ; PRINTSTRING
5:0 | 5 | cd f0 05 ; STA TIMER fc06:0 | fc06 | fd 59 ; GETSTRING
8:0 | 8 | 18 ; HLT fc08:0 | fc08 | fc 9f ; PRINTHEX
9:0 | 9 | 98 f8 ; BRA RESET fc0a:0 | fc0a | fd 8e ; SLEEP
b:0 | b | 41 ; RST fc20:0 | fc20 | ; PRINTCHAR:
c:0 | c | ; INTERRUPT: fc20:0 | fc20 | 48 ; PHA
c:0 | c | f6 ; INC A fc21:0 | fc21 | 54 ; PHX
d:0 | d | 38 ; RUN fc22:0 | fc22 | c9 0a ; CMP #$0A
e:0 | e | 40 ; RTI fc24:0 | fc24 | f0 1a ; BEQ PRINTCHAR_NL
fffc:0 | fffc | 00 03 ; RESET fc26:0 | fc26 | c9 0c ; CMP #$0C
fffe:0 | fffe | 00 0c ; INTERRUPT fc28:0 | fc28 | f0 3d ; BEQ PRINT_CLS
fc2a:0 | fc2a | c9 08 ; CMP #$08
fc2c:0 | fc2c | f0 28 ; BEQ BACKSPACE
fc2e:0 | fc2e | a6 00 ; LDX CURSORPOS
fc30:0 | fc30 | c1 ; STA X+
fc31:0 | fc31 | 86 00 ; STX CURSORPOS
fc33:0 | fc33 | a5 01 ; LDA CURSORPOS+1
fc35:0 | fc35 | d0 06 ; BNE PRINTCHAR_RETURN
fc37:0 | fc37 | a5 00 ; LDA CURSORPOS
fc39:0 | fc39 | c9 c4 ; CMP #SCREEN_CHAR_OVFPG
fc3b:0 | fc3b | f0 2f ; BEQ SCROLLUP
fc3d:0 | fc3d | ; PRINTCHAR_RETURN:
fc3d:0 | fc3d | 74 ; PLX
fc3e:0 | fc3e | 68 ; PLA
fc3f:0 | fc3f | 60 ; RTS
fc40:0 | fc40 | ; PRINTCHAR_NL:
fc40:0 | fc40 | a5 01 ; LDA CURSORPOS+1
fc42:0 | fc42 | 29 c0 ; AND #$100-SCREEN_WIDTH
fc44:0 | fc44 | c9 c0 ; CMP #$100-SCREEN_WIDTH
fc46:0 | fc46 | d0 06 ; BNE NOSCROLLUP
fc48:0 | fc48 | a5 00 ; LDA CURSORPOS
fc4a:0 | fc4a | c9 c3 ; CMP #SCREEN_CHAR_MAXPG
fc4c:0 | fc4c | f0 1e ; BEQ SCROLLUP
fc4e:0 | fc4e | ; NOSCROLLUP:
fc4e:0 | fc4e | 6b 40 ; ADD #$40
fc50:0 | fc50 | 47 00 ; ICC CURSORPOS
fc52:0 | fc52 | 85 01 ; STA CURSORPOS+1
fc54:0 | fc54 | 98 e7 ; BRA PRINTCHAR_RETURN
fc56:0 | fc56 | ; BACKSPACE:
fc56:0 | fc56 | a5 01 ; LDA CURSORPOS+1
fc58:0 | fc58 | 29 3f ; AND #SCREEN_WIDTH-1
fc5a:0 | fc5a | f0 e1 ; BEQ PRINTCHAR_RETURN
fc5c:0 | fc5c | a6 00 ; LDX CURSORPOS
fc5e:0 | fc5e | e8 ff ; ADX #-1
fc60:0 | fc60 | 86 00 ; STX CURSORPOS
fc62:0 | fc62 | a9 00 ; LDA #$00
fc64:0 | fc64 | 81 ; STA X
fc65:0 | fc65 | 98 d6 ; BRA PRINTCHAR_RETURN
fc67:0 | fc67 | ; PRINT_CLS:
fc67:0 | fc67 | 20 fc a0 ; JSR CLEARSCREEN
fc6a:0 | fc6a | 98 d1 ; BRA PRINTCHAR_RETURN
fc6c:0 | fc6c | ; SCROLLUP:
fc6c:0 | fc6c | 14 ; PHY
fc6d:0 | fc6d | 48 ; PHA
fc6e:0 | fc6e | 5c ; PHB
fc6f:0 | fc6f | 1c ; PHC
fc70:0 | fc70 | aa c0 00 ; LDX #SCREEN_CHAR
fc73:0 | fc73 | a8 c0 40 ; LDY #SCREEN_CHAR+SCREEN_WIDTH
fc76:0 | fc76 | 2b 0f ; LDC #SCREEN_HEIGHT-1
fc78:0 | fc78 | ; SCROLLUP_LPOUT:
fc78:0 | fc78 | ab 40 ; LDB #SCREEN_WIDTH
fc7a:0 | fc7a | ; SCROLLUP_LPIN:
fc7a:0 | fc7a | f1 ; LDA Y+
fc7b:0 | fc7b | c1 ; STA X+
fc7c:0 | fc7c | de ; DEC B
fc7d:0 | fc7d | d0 fb ; BNE SCROLLUP_LPIN
fc7f:0 | fc7f | da ; DEC C
fc80:0 | fc80 | d0 f6 ; BNE SCROLLUP_LPOUT
fc82:0 | fc82 | 86 00 ; STX CURSORPOS
fc84:0 | fc84 | a9 00 ; LDA #$00
fc86:0 | fc86 | ab 40 ; LDB #SCREEN_WIDTH
fc88:0 | fc88 | ; SCROLLUP_LPC:
fc88:0 | fc88 | c1 ; STA X+
fc89:0 | fc89 | de ; DEC B
fc8a:0 | fc8a | d0 fc ; BNE SCROLLUP_LPC
fc8c:0 | fc8c | 3c ; PLC
fc8d:0 | fc8d | 7c ; PLB
fc8e:0 | fc8e | 68 ; PLA
fc8f:0 | fc8f | 34 ; PLY
fc90:0 | fc90 | 98 ab ; BRA PRINTCHAR_RETURN
fc92:0 | fc92 | ; PRINTSTRING:
fc92:0 | fc92 | 48 ; PHA
fc93:0 | fc93 | 54 ; PHX
fc94:0 | fc94 | ; PRINTSTRING_LOOP:
fc94:0 | fc94 | e1 ; LDA X+
fc95:0 | fc95 | f0 05 ; BEQ PRINTSTRING_DONE
fc97:0 | fc97 | 20 fc 20 ; JSR PRINTCHAR
fc9a:0 | fc9a | 98 f8 ; BRA PRINTSTRING_LOOP
fc9c:0 | fc9c | ; PRINTSTRING_DONE:
fc9c:0 | fc9c | 74 ; PLX
fc9d:0 | fc9d | 68 ; PLA
fc9e:0 | fc9e | 60 ; RTS
fc9f:0 | fc9f | ; PRINTHEX:
fc9f:0 | fc9f | 60 ; RTS
fca0:0 | fca0 | ; CLEARSCREEN:
fca0:0 | fca0 | 54 ; PHX
fca1:0 | fca1 | 14 ; PHY
fca2:0 | fca2 | 48 ; PHA
fca3:0 | fca3 | 5c ; PHB
fca4:0 | fca4 | 1c ; PHC
fca5:0 | fca5 | aa c0 00 ; LDX #SCREEN_CHAR
fca8:0 | fca8 | a8 c8 00 ; LDY #SCREEN_COLOR
fcab:0 | fcab | a9 10 ; LDA #SCREEN_HEIGHT
fcad:0 | fcad | 85 00 ; STA CURSORPOS
fcaf:0 | fcaf | a9 00 ; LDA #0
fcb1:0 | fcb1 | ab 26 ; LDB #SCREEN_BLACK
fcb3:0 | fcb3 | ; CLSLPOUT:
fcb3:0 | fcb3 | 2b 40 ; LDC #SCREEN_WIDTH
fcb5:0 | fcb5 | ; CLSLPIN:
fcb5:0 | fcb5 | c1 ; STA X+
fcb6:0 | fcb6 | d3 ; STB Y+
fcb7:0 | fcb7 | da ; DEC C
fcb8:0 | fcb8 | d0 fb ; BNE CLSLPIN
fcba:0 | fcba | c6 00 ; DEC CURSORPOS
fcbc:0 | fcbc | d0 f5 ; BNE CLSLPOUT
fcbe:0 | fcbe | aa c0 00 ; LDX #SCREEN_CHAR
fcc1:0 | fcc1 | 86 00 ; STX CURSORPOS
fcc3:0 | fcc3 | 3c ; PLC
fcc4:0 | fcc4 | 7c ; PLB
fcc5:0 | fcc5 | 68 ; PLA
fcc6:0 | fcc6 | 34 ; PLY
fcc7:0 | fcc7 | 74 ; PLX
fcc8:0 | fcc8 | 60 ; RTS
fcc9:0 | fcc9 | ; WAITKEY:
fcc9:0 | fcc9 | 20 fd 8e ; JSR SLEEP
fccc:0 | fccc | ; GETKEY:
fccc:0 | fccc | ed f1 00 ; LDA KEYBOARD
fccf:0 | fccf | f0 f8 ; BEQ WAITKEY
fcd1:0 | fcd1 | 60 ; RTS
fcd2:0 | fcd2 | ; KEY_SYMBOLS:
fcd2:0 | fcd2 | 30 30 29 31 31 21 32 32 40 33 33 23 34 34 24 35 35 25 36 36 5e 37 37 26 38 38 2a 39 39 28 ; "00)11!22@33#44$55%66^77&88*99("
fcf0:0 | fcf0 | 18 3b 3a 19 3d 2b 1a 2c 3c 1b 2e 3e 1c 2d 5f 1d 2f 3f 1e 60 7e ; "\x18;:\x19=+\x1A,<\x1B.>\x1C-_\x1D/?\x1E`~"
fd05:0 | fd05 | 3c 5b 7b 3d 5c 7c 3e 5d 7d 3f 27 22 ; "\x3C[{\x3D\\|\x3E]}\x3F'\x22"
fd11:0 | fd11 | 0d 0a 0a ; "\x0d\x0A\x0A"
fd14:0 | fd14 | 20 20 20 08 08 08 ; " \x08\x08\x08"
fd1a:0 | fd1a | 00 ; "\0"
fd1b:0 | fd1b | ; GETCHAR:
fd1b:0 | fd1b | 5c ; PHB
fd1c:0 | fd1c | ; GETCHAR_RESTART:
fd1c:0 | fd1c | 20 fc cc ; JSR GETKEY
fd1f:0 | fd1f | b7 ; TAB
fd20:0 | fd20 | 29 7b ; AND #$7B
fd22:0 | fd22 | c9 10 ; CMP #$10
fd24:0 | fd24 | f0 2c ; BEQ SHIFTKEY
fd26:0 | fd26 | 97 ; TBA
fd27:0 | fd27 | c9 80 ; CMP #$80
fd29:0 | fd29 | 90 f1 ; BLT GETCHAR_RESTART
fd2b:0 | fd2b | 29 7f ; AND #$7F
fd2d:0 | fd2d | c9 41 ; CMP #$41
fd2f:0 | fd2f | 90 04 ; BLT NOT_LETTER
fd31:0 | fd31 | c9 5a ; CMP #$5A
fd33:0 | fd33 | 10 1b ; BLE GETCHAR_RETURN
fd35:0 | fd35 | ; NOT_LETTER:
fd35:0 | fd35 | 54 ; PHX
fd36:0 | fd36 | aa fc d2 ; LDX #KEY_SYMBOLS
fd39:0 | fd39 | ; KEY_SYM_LP:
fd39:0 | fd39 | e3 ; LDB X+
fd3a:0 | fd3a | f0 11 ; BEQ KEY_SYM_DONE
fd3c:0 | fd3c | ; KEY_SYM_CONTINUE:
fd3c:0 | fd3c | dd ; CMP B
fd3d:0 | fd3d | f0 04 ; BEQ KEY_SYM_MATCH
fd3f:0 | fd3f | e8 02 ; ADX #2
fd41:0 | fd41 | 98 f6 ; BRA KEY_SYM_LP
fd43:0 | fd43 | ; KEY_SYM_MATCH:
fd43:0 | fd43 | a7 02 ; LDB SHIFTDOWN
fd45:0 | fd45 | f0 02 ; BEQ KEY_SYM_NOSHIFT
fd47:0 | fd47 | e8 01 ; ADX #1
fd49:0 | fd49 | ; KEY_SYM_NOSHIFT:
fd49:0 | fd49 | a1 ; LDA X
fd4a:0 | fd4a | 74 ; PLX
fd4b:0 | fd4b | 98 03 ; BRA GETCHAR_RETURN
fd4d:0 | fd4d | ; KEY_SYM_DONE:
fd4d:0 | fd4d | 74 ; PLX
fd4e:0 | fd4e | 98 cc ; BRA GETCHAR_RESTART
fd50:0 | fd50 | ; GETCHAR_RETURN:
fd50:0 | fd50 | 7c ; PLB
fd51:0 | fd51 | 60 ; RTS
fd52:0 | fd52 | ; SHIFTKEY:
fd52:0 | fd52 | 97 ; TBA
fd53:0 | fd53 | 29 80 ; AND #$80
fd55:0 | fd55 | 85 02 ; STA SHIFTDOWN
fd57:0 | fd57 | 98 c3 ; BRA GETCHAR_RESTART
fd59:0 | fd59 | ; GETSTRING:
fd59:0 | fd59 | 48 ; PHA
fd5a:0 | fd5a | 54 ; PHX
fd5b:0 | fd5b | ; GETSTRING_LOOP:
fd5b:0 | fd5b | 20 fd 1b ; JSR GETCHAR
fd5e:0 | fd5e | 20 fc 20 ; JSR PRINTCHAR
fd61:0 | fd61 | c1 ; STA X+
fd62:0 | fd62 | c9 08 ; CMP #$08
fd64:0 | fd64 | d0 02 ; BNE GETSTRING_NOBK
fd66:0 | fd66 | e8 fe ; ADX #-2
fd68:0 | fd68 | ; GETSTRING_NOBK:
fd68:0 | fd68 | c9 0a ; CMP #$0A
fd6a:0 | fd6a | d0 ef ; BNE GETSTRING_LOOP
fd6c:0 | fd6c | e8 ff ; ADX #-1
fd6e:0 | fd6e | a9 00 ; LDA #$00
fd70:0 | fd70 | 81 ; STA X
fd71:0 | fd71 | 74 ; PLX
fd72:0 | fd72 | 68 ; PLA
fd73:0 | fd73 | 60 ; RTS
fd74:0 | fd74 | ; STRCMP:
fd74:0 | fd74 | 54 ; PHX
fd75:0 | fd75 | 14 ; PHY
fd76:0 | fd76 | 48 ; PHA
fd77:0 | fd77 | 5c ; PHB
fd78:0 | fd78 | ; STRCMP_NEXTCHAR:
fd78:0 | fd78 | e1 ; LDA X+
fd79:0 | fd79 | f0 08 ; BEQ STRCMP_XOVER
fd7b:0 | fd7b | f3 ; LDB Y+
fd7c:0 | fd7c | f0 08 ; BEQ STRCMP_YOVER
fd7e:0 | fd7e | dd ; CMP B
fd7f:0 | fd7f | f0 f7 ; BEQ STRCMP_NEXTCHAR
fd81:0 | fd81 | 98 06 ; BRA STRCMP_RETURN
fd83:0 | fd83 | ; STRCMP_XOVER:
fd83:0 | fd83 | b1 ; LDA Y
fd84:0 | fd84 | 98 03 ; BRA STRCMP_RETURN
fd86:0 | fd86 | ; STRCMP_YOVER:
fd86:0 | fd86 | e8 ff ; ADX #-1
fd88:0 | fd88 | a1 ; LDA X
fd89:0 | fd89 | ; STRCMP_RETURN:
fd89:0 | fd89 | 7c ; PLB
fd8a:0 | fd8a | 68 ; PLA
fd8b:0 | fd8b | 34 ; PLY
fd8c:0 | fd8c | 74 ; PLX
fd8d:0 | fd8d | 60 ; RTS
fd8e:0 | fd8e | ; SLEEP:
fd8e:0 | fd8e | cd f0 05 ; STA TIMER
fd91:0 | fd91 | 18 ; HLT
fd92:0 | fd92 | 60 ; RTS
fd93:0 | fd93 | ; STR_HI:
fd93:0 | fd93 | 48 49 00 ; "HI\0"
fd96:0 | fd96 | ; STR_HIRES:
fd96:0 | fd96 | 48 45 4c 4c 4f 21 0a 00 ; "HELLO!\n\0"
fd9e:0 | fd9e | ; RESET:
fd9e:0 | fd9e | 20 fc a0 ; JSR CLEARSCREEN
fda1:0 | fda1 | 58 ; CLI
fda2:0 | fda2 | ; INPUTLP:
fda2:0 | fda2 | aa 02 00 ; LDX #$0200
fda5:0 | fda5 | 20 fd 59 ; JSR GETSTRING
fda8:0 | fda8 | a8 fd 93 ; LDY #STR_HI
fdab:0 | fdab | 20 fd 74 ; JSR STRCMP
fdae:0 | fdae | d0 f2 ; BNE INPUTLP
fdb0:0 | fdb0 | aa fd 96 ; LDX #STR_HIRES
fdb3:0 | fdb3 | 20 fc 92 ; JSR PRINTSTRING
fdb6:0 | fdb6 | 98 ea ; BRA INPUTLP
fdb8:0 | fdb8 | 18 ; HLT
fdb9:0 | fdb9 | 41 ; RST
fdba:0 | fdba | ; INTERRUPT:
fdba:0 | fdba | 38 ; RUN
fdbb:0 | fdbb | 40 ; RTI
fffc:0 | fffc | fd 9e ; RESET
fffe:0 | fffe | fd ba ; INTERRUPT

Binary file not shown.

View File

@ -32,7 +32,9 @@ ICC zpg 47 4 Add the Carrry Flag to the value at an given 8-bit address,
8-bit Arithmetic and Logic (A): 8-bit Arithmetic and Logic (A):
ADD # 6B 2 Add a given 8-bit value to the value in the A register, and set the Carry Flag and Zero Flag according to the result ADD # 6B 2 Add a given 8-bit value to the value in the A register, and set the Carry Flag and Zero Flag according to the result
SUB # EB 2 Subtract a given 8-bit value from the value in the A register, and set the Carry Flag and Zero Flag according to the result
ADC # 69 2 Add a given 8-bit value plus the Carry Flag to the value in the A register, and set the Carry Flag and Zero Flag according to the result ADC # 69 2 Add a given 8-bit value plus the Carry Flag to the value in the A register, and set the Carry Flag and Zero Flag according to the result
SBC # E9 2 Subtract a given 8-bit value from the value in the A register including the Carry Flag, and set the Carry Flag and Zero Flag according to the result
CMP # C9 2 Set the Carry Flag and Zero Flag according to the result of subtracting a given 8-bit value from the value in the A register CMP # C9 2 Set the Carry Flag and Zero Flag according to the result of subtracting a given 8-bit value from the value in the A register
AND # 29 2 Bitwise AND the value in the A register with a given 8-bit value, and set the Zero Flag according to the result AND # 29 2 Bitwise AND the value in the A register with a given 8-bit value, and set the Zero Flag according to the result
ORA # 09 2 Bitwise OR the value in the A register with a given 8-bit value, and set the Zero Flag according to the result ORA # 09 2 Bitwise OR the value in the A register with a given 8-bit value, and set the Zero Flag according to the result
@ -205,7 +207,7 @@ TXV 96 1 Copy the 16-bit value in the X register into the 16-bit Inte
TAS 95 1 Copy the value in the A register into the 8-bit Stack Pointer register TAS 95 1 Copy the value in the A register into the 8-bit Stack Pointer register
TSA B5 1 Copy the 8-bit Stack Pointer into the A register TSA B5 1 Copy the 8-bit Stack Pointer into the A register
Opcodes used: 189/256 Opcodes used: 191/256
0123456789ABCDEF 0123456789ABCDEF
00 | CC-BJA-BSA--JJ-- 00 | CC-BJA-BSA--JJ--
10 | B--BSA-MCA-BSA-B 10 | B--BSA-MCA-BSA-B
@ -221,5 +223,5 @@ A0 | WBWBWBWBWBWBWWWW
B0 | BBWBMMMMWBWBWBWB B0 | BBWBMMMMWBWBWBWB
C0 | WB-B-AU-XA--JB-B C0 | WB-B-AU-XA--JB-B
D0 | BBWB--UM-AU-XAU- D0 | BBWB--UM-AU-XAU-
E0 | WBWB-AUAX-C--B-B E0 | WBWB-AUAXACA-B-B
F0 | BBWB--UM-AUAXAUA F0 | BBWB--UM-AUAXAUA

View File

@ -3,12 +3,12 @@
For a quick guide on how to use this project, see [getting-started.md](getting-started.md)<br> For a quick guide on how to use this project, see [getting-started.md](getting-started.md)<br>
For a detailed description of the architecture, see [architecture.md](architecture.md)<br> For a detailed description of the architecture, see [architecture.md](architecture.md)<br>
For a list of instructions, see [instructionList.txt](instructionList.txt) For a list of instructions, see [instructionList.txt](instructionList.txt)<br>
For a memory map of the 8608-based computer, see [memoryMap.md](memoryMap.md) For a memory map of the 8608-based computer, see [memoryMap.md](memoryMap.md)
To use the emulator, simply drag-and-drop an assembly code file onto [emulator/8608-emulator.bat](emulator/8608-emulator.bat) To use the emulator, simply drag-and-drop an assembly code file onto [emulator/8608-emulator.bat](emulator/8608-emulator.bat)<br>
You must include the 8608 architecture file into your assembly code: [8608.asm](8608.asm)<br> You must include the 8608 architecture file into your assembly code: [8608.asm](8608.asm)<br>
`#include "8608/8608.asm"`<br> `#include "8608/8608.asm"`
Note: This project depends on several pieces of free and open-source software,<br> Note: This project depends on several pieces of free and open-source software,<br>
whose binaries are included in the repository:<br> whose binaries are included in the repository:<br>