Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local function pad(str, tolen) return string.rep("0", math.max(tolen - str:len(),0)) .. str end
- local function binary(num)
- local bin = {}
- num = math.floor(num)
- repeat
- table.insert(bin, num%2)
- num = math.floor(num/2)
- until num == 0
- return table.concat(bin):reverse()
- end
- local tArgs = { ... }
- if #tArgs < 2 then
- print("Usage: chip8 <rom> <side> [debug]")
- return
- end
- local rFile = shell.resolve(tArgs[1])
- local eSide = tArgs[2]
- local mDebug = not (tArgs[3] == nil)
- if mDebug then print("Checking if rom exists ...") end
- if not fs.exists(rFile) then
- print("Rom file " .. rFile .. " does not exist.")
- return
- end
- if mDebug then print("Checking if rom is a directory ...") end
- if fs.isDir(rFile) then
- print("Rom file " .. rFile .. " is a directory.")
- return
- end
- if mDebug then print("Checking if side is monitor ...") end
- if not peripheral.getType(eSide) == "monitor" then
- print("Peripheral on side " .. eSide .. " is not a monitor.")
- return
- end
- if mDebug then print("Attempting to wrap monitor ...") end
- local mon = peripheral.wrap(eSide)
- if mon == nil then
- print("Failed to wrap monitor on side " .. eSide)
- return
- end
- mon.setTextScale(0.5)
- mon.clear()
- local w,h = mon.getSize()
- if mDebug then print("Checking if monitor is big enough ...") end
- if w < 64 or h < 32 then
- print("The monitor on side " .. eSide .. " is too small.")
- print("Expected 64x32+\nGot " .. tostring(w) .. "x" .. tostring(h))
- return
- end
- if mDebug then print("Protection passed!\n") end
- local chip8_keystate = {}
- local chip8_keytrans = {}
- local chip8_display = {}
- for i = 0,63,1 do
- chip8_display[i] = {}
- for j = 0,31,1 do
- chip8_display[i][j] = 0
- end
- end
- local chip8_memory = {}
- for i = 0, 4095, 1 do chip8_memory[i] = 0 end
- local chip8_register = {}
- for i = 0, 15, 1 do chip8_register[i] = 0 end
- chip8_register["I"] = 512
- chip8_register["PC"] = 512
- chip8_register["DC"] = 0
- chip8_register["SC"] = 0
- local chip8_stack = {}
- chip8_stack[0] = 0
- local chip8_skip = 2
- chip8_fontset = {
- 0xF0, 0x90, 0x90, 0x90, 0xF0,
- 0x20, 0x60, 0x20, 0x20, 0x70,
- 0xF0, 0x10, 0xF0, 0x80, 0xF0,
- 0xF0, 0x10, 0xF0, 0x10, 0xF0,
- 0x90, 0x90, 0xF0, 0x10, 0x10,
- 0xF0, 0x80, 0xF0, 0x10, 0xF0,
- 0xF0, 0x80, 0xF0, 0x90, 0xF0,
- 0xF0, 0x10, 0x20, 0x40, 0x40,
- 0xF0, 0x90, 0xF0, 0x90, 0xF0,
- 0xF0, 0x90, 0xF0, 0x10, 0xF0,
- 0xF0, 0x90, 0xF0, 0x90, 0x90,
- 0xE0, 0x90, 0xE0, 0x90, 0xE0,
- 0xF0, 0x80, 0x80, 0x80, 0xF0,
- 0xE0, 0x90, 0x90, 0x90, 0xE0,
- 0xF0, 0x80, 0xF0, 0x80, 0xF0,
- 0xF0, 0x80, 0xF0, 0x80, 0x80}
- print("Loading fontset ...")
- for i = 1,80,1 do
- chip8_memory[i-1] = chip8_fontset[i]
- end
- chip8_keystate["0"] = 0
- chip8_keystate["1"] = 0
- chip8_keystate["2"] = 0
- chip8_keystate["3"] = 0
- chip8_keystate["4"] = 0
- chip8_keystate["5"] = 0
- chip8_keystate["6"] = 0
- chip8_keystate["7"] = 0
- chip8_keystate["8"] = 0
- chip8_keystate["9"] = 0
- chip8_keystate["A"] = 0
- chip8_keystate["B"] = 0
- chip8_keystate["C"] = 0
- chip8_keystate["D"] = 0
- chip8_keystate["E"] = 0
- chip8_keystate["F"] = 0
- chip8_keystate["END"] = 0
- chip8_keytrans[45] = "0"
- chip8_keytrans[2] = "1"
- chip8_keytrans[3] = "2"
- chip8_keytrans[4] = "3"
- chip8_keytrans[16] = "4"
- chip8_keytrans[17] = "5"
- chip8_keytrans[18] = "6"
- chip8_keytrans[30] = "7"
- chip8_keytrans[31] = "8"
- chip8_keytrans[32] = "9"
- chip8_keytrans[44] = "A"
- chip8_keytrans[46] = "B"
- chip8_keytrans[5] = "C"
- chip8_keytrans[19] = "D"
- chip8_keytrans[33] = "E"
- chip8_keytrans[47] = "F"
- chip8_keytrans[59] = "END"
- function chip8_loadrom()
- local rRom = fs.open(rFile,"rb")
- local index = 512
- local size = 0
- while true do
- byte = rRom.read()
- if byte == nil then break end
- chip8_memory[index] = byte
- index = index + 1
- size = size + 1
- end
- rRom.close()
- return size
- end
- function chip8_updatekeys()
- for i = 48,57,1 do
- chip8_keystate[string.char(i)] = chip8_keystate[string.char(i)] - 1
- if chip8_keystate[string.char(i)] < 0 then chip8_keystate[string.char(i)] = 0 end
- end
- for i = 65,70,1 do
- chip8_keystate[string.char(i)] = chip8_keystate[string.char(i)] - 1
- if chip8_keystate[string.char(i)] < 0 then chip8_keystate[string.char(i)] = 0 end
- end
- os.queueEvent("key","","done")
- while true do
- event,param1,param2 = os.pullEvent("key")
- if param2 == "done" then break end
- if not (chip8_keytrans[param1] == nil) then
- chip8_keystate[chip8_keytrans[param1]] = 4
- if mDebug then print("Pressed " .. chip8_keytrans[param1]) end
- end
- end
- return
- end
- function chip8_keywait()
- while true do
- for i = 48,57,1 do
- chip8_keystate[string.char(i)] = chip8_keystate[string.char(i)] - 1
- if chip8_keystate[string.char(i)] < 0 then chip8_keystate[string.char(i)] = 0 end
- end
- for i = 65,70,1 do
- chip8_keystate[string.char(i)] = chip8_keystate[string.char(i)] - 1
- if chip8_keystate[string.char(i)] < 0 then chip8_keystate[string.char(i)] = 0 end
- end
- os.queueEvent("key","","done")
- while true do
- event,param1,param2 = os.pullEvent("key")
- if param2 == "done" then break end
- if not (chip8_keytrans[param1] == nil) then
- chip8_keystate[chip8_keytrans[param1]] = 4
- if mDebug then print("Pressed " .. chip8_keytrans[param1]) end
- return tonumber(chip8_keytrans[param1],16)
- end
- end
- if pressed then break end
- sleep(0)
- end
- end
- function chip8_getkey(key)
- return chip8_keystate[key] > 0
- end
- function chip8_emulatecode()
- local l
- local opcode = pad(string.format("%X",chip8_memory[chip8_register["PC"]]),2) .. pad(string.format("%X",chip8_memory[chip8_register["PC"]+1]),2)
- local opcfst = string.sub(opcode,1,1)
- if mDebug then
- print("PC:" .. pad(string.format("%X",chip8_register["PC"]),4) .. "|I:" .. pad(string.format("%X",chip8_register["I"]),4) .. " - " .. opcode)
- curX,curY = term.getCursorPos()
- for i = 0,15,1 do
- term.setCursorPos(46,i+2) print("V" .. pad(string.format("%X",i),1) .. ":" .. pad(string.format("%X",chip8_register[i]),2))
- end
- term.setCursorPos(curX,curY)
- end
- for i = 0,15,1 do
- if chip8_register[i] > 255 then error("ERR1") end
- if chip8_register[i] < 0 then error("ERR2") end
- end
- chip8_register["PC"] = chip8_register["PC"] + 2
- if opcfst == "0" then
- if string.sub(opcode,2,4) == "0E0" then
- mon.clear()
- mon.setCursorPos(1,1)
- for i = 0,63,1 do
- for j = 0,31,1 do
- chip8_display[i][j] = 0
- end
- end
- elseif string.sub(opcode,2,4) == "0EE" then
- chip8_register["PC"] = chip8_stack[chip8_stack[0]]
- chip8_stack[0] = chip8_stack[0] - 1
- end
- elseif opcfst == "1" then
- chip8_register["PC"] = tonumber(string.sub(opcode,2,4),16)
- elseif opcfst == "2" then
- chip8_stack[0] = chip8_stack[0] + 1
- chip8_stack[chip8_stack[0]] = chip8_register["PC"]
- chip8_register["PC"] = tonumber(string.sub(opcode,2,4),16)
- elseif opcfst == "3" then
- if chip8_register[tonumber(string.sub(opcode,2,2),16)] == tonumber(string.sub(opcode,3,4),16) then
- chip8_register["PC"] = chip8_register["PC"] + 2
- end
- elseif opcfst == "4" then
- if chip8_register[tonumber(string.sub(opcode,2,2),16)] ~= tonumber(string.sub(opcode,3,4),16) then
- chip8_register["PC"] = chip8_register["PC"] + 2
- end
- elseif opcfst == "5" then
- if chip8_register[tonumber(string.sub(opcode,2,2),16)] == chip8_register[tonumber(string.sub(opcode,3,3),16)] then
- chip8_register["PC"] = chip8_register["PC"] + 2
- end
- elseif opcfst == "6" then
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = tonumber(string.sub(opcode,3,4),16)
- elseif opcfst == "7" then
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = math.fmod(chip8_register[tonumber(string.sub(opcode,2,2),16)] + tonumber(string.sub(opcode,3,4),16),255)
- elseif opcfst == "8" then
- if string.sub(opcode,4,4) == "0" then
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = chip8_register[tonumber(string.sub(opcode,3,3),16)]
- elseif string.sub(opcode,4,4) == "1" then
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = bit.bor(chip8_register[tonumber(string.sub(opcode,2,2),16)],chip8_register[tonumber(string.sub(opcode,3,3),16)])
- elseif string.sub(opcode,4,4) == "2" then
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = bit.band(chip8_register[tonumber(string.sub(opcode,2,2),16)],chip8_register[tonumber(string.sub(opcode,3,3),16)])
- elseif string.sub(opcode,4,4) == "3" then
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = bit.bxor(chip8_register[tonumber(string.sub(opcode,2,2),16)],chip8_register[tonumber(string.sub(opcode,3,3),16)])
- elseif string.sub(opcode,4,4) == "4" then
- chip8_register[15] = 0
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = chip8_register[tonumber(string.sub(opcode,2,2),16)] + chip8_register[tonumber(string.sub(opcode,3,3),16)]
- if chip8_register[tonumber(string.sub(opcode,2,2),16)] > 255 then
- chip8_register[15] = 1
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = math.fmod(chip8_register[tonumber(string.sub(opcode,2,2),16)],256)
- end
- elseif string.sub(opcode,4,4) == "5" then
- chip8_register[15] = 1
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = chip8_register[tonumber(string.sub(opcode,2,2),16)] - chip8_register[tonumber(string.sub(opcode,3,3),16)]
- if chip8_register[tonumber(string.sub(opcode,2,2),16)] < 0 then
- chip8_register[15] = 0
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = chip8_register[tonumber(string.sub(opcode,2,2),16)] + 256
- end
- elseif string.sub(opcode,4,4) == "6" then
- chip8_register[15] = math.fmod(chip8_register[tonumber(string.sub(opcode,3,3),16)],2)
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = bit.brshift(chip8_register[tonumber(string.sub(opcode,3,3),16)],1)
- elseif string.sub(opcode,4,4) == "7" then
- chip8_register[15] = 1
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = chip8_register[tonumber(string.sub(opcode,3,3),16)] - chip8_register[tonumber(string.sub(opcode,2,2),16)]
- if chip8_register[tonumber(string.sub(opcode,2,2),16)] < 0 then
- chip8_register[15] = 0
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = chip8_register[tonumber(string.sub(opcode,2,2),16)] + 256
- end
- elseif string.sub(opcode,4,4) == "E" then
- chip8_register[15] = math.floor(chip8_register[tonumber(string.sub(opcode,3,3),16)] / 128)
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = math.fmod(bit.blshift(chip8_register[tonumber(string.sub(opcode,3,3),16)],1),256)
- end
- elseif opcfst == "9" then
- if not (chip8_register[tonumber(string.sub(opcode,2,2),16)] == chip8_register[tonumber(string.sub(opcode,3,3),16)]) then
- chip8_register["PC"] = chip8_register["PC"] + 2
- end
- elseif opcfst == "A" then
- chip8_register["I"] = tonumber(string.sub(opcode,2,4),16)
- elseif opcfst == "B" then
- chip8_register["PC"] = tonumber(string.sub(opcode,2,4),16) + chip8_register[0]
- elseif opcfst == "C" then
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = bit.band(math.random(0,255),tonumber(string.sub(opcode,3,4),16))
- elseif opcfst == "D" then
- chip8_register[15] = 0
- local x = chip8_register[tonumber(string.sub(opcode,2,2),16)]
- local y = chip8_register[tonumber(string.sub(opcode,3,3),16)]
- local h = tonumber(string.sub(opcode,4,4),16)
- local dLine = ""
- local s = ""
- for i = 0,h-1,1 do
- dLine = ""
- s = pad(binary(chip8_memory[chip8_register["I"]+i]),8)
- for d = 0,7,1 do dLine = dLine .. tostring(chip8_display[math.fmod(x+d,64)][math.min(y+i,31)]) end
- line = pad(binary(bit.bxor(tonumber(s,2),tonumber(dLine,2))),8)
- for p = 1,8,1 do
- if not (x+p-1 > 63 or y+i > 31) then
- mon.setCursorPos(x+p,y+i+1)
- if string.sub(line,p,p) == "1" then
- mon.setBackgroundColor(1)
- mon.write("#")
- mon.setBackgroundColor(32768)
- chip8_display[math.fmod(x+p-1,64)][y+i] = 1
- else
- mon.write(" ")
- if chip8_display[math.fmod(x+p-1,64)][y+i] == 1 then chip8_register[15] = 1 end
- chip8_display[math.fmod(x+p-1,64)][y+i] = 0
- end
- end
- end
- end
- if not mDebug then chip8_updatedisplay() end
- elseif opcfst == "E" then
- if string.sub(opcode,3,4) == "9E" then
- if chip8_getkey(string.format("%X",chip8_register[tonumber(string.sub(opcode,2,2),16)])) then
- chip8_register["PC"] = chip8_register["PC"] + 2
- end
- elseif string.sub(opcode,3,4) == "A1" then
- if not (chip8_getkey(string.format("%X",chip8_register[tonumber(string.sub(opcode,2,2),16)]))) then
- chip8_register["PC"] = chip8_register["PC"] + 2
- end
- end
- elseif opcfst == "F" then
- if string.sub(opcode,3,4) == "07" then
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = chip8_register["DC"]
- elseif string.sub(opcode,3,4) == "0A" then
- chip8_register[tonumber(string.sub(opcode,2,2),16)] = chip8_keywait()
- elseif string.sub(opcode,3,4) == "15" then
- chip8_register["DC"] = chip8_register[tonumber(string.sub(opcode,2,2),16)]
- elseif string.sub(opcode,3,4) == "18" then
- chip8_register["SC"] = chip8_register[tonumber(string.sub(opcode,2,2),16)]
- elseif string.sub(opcode,3,4) == "1E" then
- chip8_register[15] = 0
- chip8_register["I"] = chip8_register["I"] + chip8_register[tonumber(string.sub(opcode,2,2),16)]
- if chip8_register["I"] > 4095 then
- chip8_register[15] = 1
- chip8_register["I"] = math.fmod(chip8_register["I"],256)
- end
- elseif string.sub(opcode,3,4) == "29" then
- chip8_register["I"] = chip8_register[tonumber(string.sub(opcode,2,2),16)] * 5
- elseif string.sub(opcode,3,4) == "33" then
- local bcd = pad(tostring(chip8_register[tonumber(string.sub(opcode,2,2),16)]),3)
- chip8_memory[chip8_register["I"]] = tonumber(string.sub(bcd,1,1))
- chip8_memory[chip8_register["I"]+1] = tonumber(string.sub(bcd,2,2))
- chip8_memory[chip8_register["I"]+2] = tonumber(string.sub(bcd,3,3))
- elseif string.sub(opcode,3,4) == "55" then
- for i = 0,tonumber(string.sub(opcode,2,2),16),1 do
- chip8_memory[chip8_register["I"]+i] = chip8_register[i]
- end
- chip8_register["I"] = chip8_register["I"] + tonumber(string.sub(opcode,2,2),16) + 1
- elseif string.sub(opcode,3,4) == "65" then
- for i = 0,tonumber(string.sub(opcode,2,2),16),1 do
- chip8_register[i] = chip8_memory[chip8_register["I"]+i]
- end
- chip8_register["I"] = chip8_register["I"] + tonumber(string.sub(opcode,2,2),16) + 1
- end
- end
- return
- end
- function chip8_updatedisplay()
- term.clear()
- for y = 0,31,1 do
- for x = 0,63,1 do
- term.setCursorPos(x*(50/64)+1,y*(18/32)+1)
- if chip8_display[x][y] == 1 then
- term.setBackgroundColor(1)
- term.write("#")
- term.setBackgroundColor(32768)
- end
- end
- end
- return
- end
- function chip8_delay()
- if chip8_register["DC"] > 0 then chip8_register["DC"] = chip8_register["DC"] - 1 end
- if chip8_register["SC"] > 0 then chip8_register["SC"] = chip8_register["SC"] - 1 end
- -- chip8_skip = chip8_skip - 1
- -- if chip8_skip == 0 then sleep(0.05) chip8_skip = 3 end
- return
- end
- print("Loading rom into memory ...")
- size = chip8_loadrom()
- print("Loaded " .. tostring(size) .. " bytes!")
- print("Starting emulation, press F1 to end ...")
- if not mDebug then sleep(1.5) term.clear() end
- while true do
- chip8_updatekeys()
- if chip8_getkey("END") then break end
- chip8_emulatecode()
- chip8_delay()
- end
- print("Emulation ended.")
- return
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement