Advertisement
CrazedProgrammer

Blit-8 Version 1.0

Aug 25th, 2016
626
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.21 KB | None | 0 0
  1. --[[
  2. Blit-8 version 1.0
  3. Copyright (c) 2016 CrazedProgrammer
  4.  
  5. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  6.  
  7. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  8.  
  9. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  10. ]]--
  11.  
  12. if not _HOST then
  13.     print("This program requires ComputerCraft 1.76 or higher to work.")
  14.     error()
  15. end
  16. local filename = ({...})[1]
  17. if not filename then
  18.     print("Usage: blit8 <filename>")
  19.     error()
  20. end
  21. filename = shell.resolve(filename)
  22.  
  23. local help = {
  24. "Blit-8 by CrazedProgrammer",
  25. "Chip-8 key mapping:",
  26. "123C   1234  7890",
  27. "456D   QWER  UIOP",
  28. "789E   ASDF  JKL;",
  29. "A0BF   ZXCV  M,./",
  30. "Enter: Restart",
  31. "Space: Pause/Continue",
  32. "Left/Right: Change clock speed",
  33. "Up: Change background color",
  34. "Down: Change foreground color",
  35. "Press any button to return."}
  36.  
  37. local speed = 10 -- Instructions per frame (60Hz)
  38. local display, keys, keypress, RAM, stack, DT, ST, PC, SP, V, I
  39.  
  40. -- Load ROM into RAM
  41.  
  42.  
  43. local function load()
  44.     display = { }
  45.     keys = { }
  46.     RAM = {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}
  47.     stack = { } -- #stack = stack pointer
  48.     DT, ST = 0, 0 -- Timers
  49.     PC = 0x200 -- Program counter
  50.     V, I = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0 -- General purpose registers: V0 - VF, 12-bit memory register
  51.  
  52.     if not fs.exists(filename) then
  53.         print("ROM file does not exist.")
  54.         error()
  55.     end
  56.     local address = 0x200
  57.     local handle = fs.open(filename, "rb")
  58.     local byte = handle.read()
  59.     while byte do
  60.         RAM[address + 1] = byte
  61.         byte = handle.read()
  62.         address = address + 1
  63.     end
  64.     handle.close()
  65.     for i = 1, 4096 do
  66.         if not RAM[i] then
  67.             RAM[i] = 0
  68.         end
  69.     end
  70. end
  71.  
  72. local function doCycle()
  73.     local opcode = RAM[PC + 1] * 256 + RAM[PC + 2]
  74.     local opcode1 = math.floor(opcode / 4096)
  75.     local opcode2 = math.floor((opcode % 4096) / 256)
  76.     local opcode3 = math.floor((opcode % 256) / 16)
  77.     local opcode4 = opcode % 16
  78.     local nnn = opcode2 * 256 + opcode3 * 16 + opcode4
  79.     local kk = opcode3 * 16 + opcode4
  80.     local x = opcode2 + 1
  81.     local y = opcode3 + 1
  82.    
  83.     if opcode1 + opcode2 + opcode4 == 0 and opcode3 == 0xE then
  84.         for i = 1, 64 * 32 do
  85.             display[i] = nil
  86.         end
  87.     elseif opcode1 + opcode2 == 0 and opcode3 == 0xE and opcode4 == 0xE then
  88.         if #stack > 0 then
  89.             PC = stack[#stack] - 2
  90.             stack[#stack] = nil
  91.         end
  92.     elseif opcode1 == 1 then
  93.         PC = nnn - 2
  94.     elseif opcode1 == 2 then
  95.         stack[#stack + 1] = PC + 2
  96.         PC = nnn - 2
  97.     elseif opcode1 == 3 then
  98.         if V[x] == kk then
  99.             PC = PC + 2
  100.         end
  101.     elseif opcode1 == 4 then
  102.         if V[x] ~= kk then
  103.             PC = PC + 2
  104.         end
  105.     elseif opcode1 == 5 and opcode4 == 0 then
  106.         if V[x] == V[y] then
  107.             PC = PC + 2
  108.         end
  109.     elseif opcode1 == 6 then
  110.         V[x] = kk
  111.     elseif opcode1 == 7 then
  112.         V[x] = (V[x] + kk) % 256
  113.     elseif opcode1 == 8 then
  114.         if opcode4 == 0 then
  115.             V[x] = V[y]
  116.         elseif opcode4 == 1 then
  117.             V[x] = bit.bor(V[x], V[y])
  118.         elseif opcode4 == 2 then
  119.             V[x] = bit.band(V[x], V[y])
  120.         elseif opcode4 == 3 then
  121.             V[x] = bit.bxor(V[x], V[y])
  122.         elseif opcode4 == 4 then
  123.             V[x] = V[x] + V[y]
  124.             if V[x] > 255 then
  125.                 V[x] = V[x] % 256
  126.                 V[16] = 1
  127.             else
  128.                 V[16] = 0
  129.             end
  130.         elseif opcode4 == 5 then
  131.             V[x] = V[x] - V[y]
  132.             if V[x] < 0 then
  133.                 V[16] = 0
  134.                 V[x] = V[x] % 256
  135.             else
  136.                 V[16] = 1
  137.             end
  138.         elseif opcode4 == 6 then
  139.             V[16] = V[x] % 2
  140.             V[x] = math.floor(V[x] / 2)
  141.         elseif opcode4 == 7 then
  142.             V[x] = V[y] - V[x]
  143.             if V[x] < 0 then
  144.                 V[16] = 0
  145.                 V[x] = V[x] % 256
  146.             else
  147.                 V[16] = 1
  148.             end
  149.         elseif opcode4 == 0xE then
  150.             V[16] = math.floor(V[x] / 128)
  151.             V[x] = (V[x] * 2) % 256
  152.         end
  153.     elseif opcode1 == 9 and opcode4 == 0 then
  154.         if V[x] ~= V[y] then
  155.             PC = PC + 2
  156.         end
  157.     elseif opcode1 == 0xA then
  158.         I = nnn
  159.     elseif opcode1 == 0xB then
  160.         PC = nnn + V[1] - 2
  161.     elseif opcode1 == 0xC then
  162.         V[x] = bit.band(math.floor(math.random() * 256), kk)
  163.     elseif opcode1 == 0xD then
  164.         local px, py = V[x] % 64, V[y] % 32
  165.         V[16] = 0
  166.         for j = 0, opcode4 - 1 do
  167.             if py + j > 31 then
  168.                 break
  169.             end
  170.             local byte = RAM[I + j + 1]
  171.             for i = 0, 7 do
  172.                 if px + i > 63 then
  173.                     break
  174.                 end
  175.                 if bit.band(byte, 2 ^ (7 - i)) > 0 then
  176.                     local index = (py + j) * 64 + px + i + 1
  177.                     display[index] = not display[index]
  178.                     if not display[index] then
  179.                         V[16] = 1
  180.                     end
  181.                 end
  182.             end
  183.         end
  184.     elseif opcode1 == 0xE and opcode3 == 9 and opcode4 == 0xE then
  185.         if keys[V[x] + 1] then
  186.             PC = PC + 2
  187.         end
  188.     elseif opcode1 == 0xE and opcode3 == 0xA and opcode4 == 1 then
  189.         if not keys[V[x] + 1] then
  190.             PC = PC + 2
  191.         end
  192.     elseif opcode1 == 0xF then
  193.         if opcode3 == 0 and opcode4 == 7 then
  194.             V[x] = DT
  195.         elseif opcode3 == 0 and opcode4 == 0xA then
  196.             if not keypress then
  197.                 PC = PC - 2
  198.             else
  199.                 V[x] = keypress
  200.             end
  201.         elseif opcode3 == 1 and opcode4 == 5 then
  202.             DT = V[x]
  203.         elseif opcode3 == 1 and opcode4 == 8 then
  204.             ST = V[x]
  205.             if ST > 0 and commands then
  206.                 commands.execAsync("/playsound note.pling @a ~ ~ ~")
  207.             end
  208.         elseif opcode3 == 1 and opcode4 == 0xE then
  209.             I = I + V[x]
  210.         elseif opcode3 == 2 and opcode4 == 9 then
  211.             I = V[x] * 5
  212.         elseif opcode3 == 3 and opcode4 == 3 then
  213.             RAM[I + 1] = math.floor(V[x] / 100)
  214.             RAM[I + 2] = math.floor((V[x] % 100) / 10)
  215.             RAM[I + 3] = V[x] % 10
  216.         elseif opcode3 == 5 and opcode4 == 5 then
  217.             for i = 1, x do
  218.                 RAM[I + i] = V[i]
  219.             end
  220.         elseif opcode3 == 6 and opcode4 == 5 then
  221.             for i = 1, x do
  222.                 V[i] = RAM[I + i]
  223.             end
  224.         end
  225.     end
  226.     PC = (PC + 2) % 4096
  227. end
  228.  
  229. local function doFrame()
  230.     for i = 1, speed do
  231.         doCycle()
  232.     end
  233.     if DT > 0 then
  234.         DT = DT - 1
  235.     end
  236.     if ST > 0 then
  237.         ST = ST - 1
  238.     end
  239. end
  240.  
  241.  
  242. load()
  243.    
  244. local running = true
  245. local screenTimer = os.startTimer(0)
  246. local keyMapping = {45, 51, 2, 8, 3, 9, 4, 10, 16, 22, 17, 23, 18, 24, 30, 36, 31, 37, 32, 38, 44, 50, 46, 52, 5, 11, 19, 25, 33, 39, 47, 53}
  247. local screenColor1 = colors.white
  248. local screenColor2 = colors.black
  249. local screenWidth, screenHeight = term.getSize()
  250. local screenX, screenY = math.floor((screenWidth - 32) / 2) + 1, math.floor((screenHeight - 12) / 2) + 1
  251. term.setTextColor(screenColor1)
  252. term.setBackgroundColor(screenColor2)
  253. term.clear()
  254.  
  255. while true do
  256.     local event = {os.pullEventRaw()}
  257.     if event[1] == "terminate" then
  258.         break
  259.     elseif event[1] == "term_resize" then
  260.         screenWidth, screenHeight = term.getSize()
  261.         screenX, screenY = math.floor((screenWidth - 32) / 2), math.floor((screenHeight - 12) / 2)
  262.         term.setTextColor(screenColor1)
  263.         term.setBackgroundColor(screenColor2)
  264.         term.clear()
  265.     elseif event[1] == "key" then
  266.         if event[2] == 14 then
  267.             break
  268.         elseif event[2] == 29 then
  269.             term.clear()
  270.             for i = 1, #help do
  271.                 term.setCursorPos(1, i)
  272.                 term.write(help[i])
  273.             end
  274.             os.pullEvent("key")
  275.             screenWidth, screenHeight = term.getSize()
  276.             screenX, screenY = math.floor((screenWidth - 32) / 2), math.floor((screenHeight - 12) / 2)
  277.             term.setTextColor(screenColor1)
  278.             term.setBackgroundColor(screenColor2)
  279.             term.clear()
  280.             screenTimer = os.startTimer(0)
  281.         elseif event[2] == 28 then
  282.             load()
  283.         elseif event[2] == 57 then
  284.             running = not running
  285.         elseif event[2] == 203 then
  286.             if speed > 3 then
  287.                 speed = speed - 3
  288.             end
  289.         elseif event[2] == 205 then
  290.             speed = speed + 3
  291.         elseif event[2] == 200 then
  292.             screenColor2 = 2 ^ ((math.log(screenColor2) / math.log(2) + 1) % 16)
  293.         elseif event[2] == 208 then
  294.             screenColor1 = 2 ^ ((math.log(screenColor1) / math.log(2) + 1) % 16)
  295.         else
  296.             for i = 1, 32 do
  297.                 if event[2] == keyMapping[i] then
  298.                     keys[math.floor((i - 1) / 2) + 1] = true
  299.                     keypress = math.floor((i - 1) / 2)
  300.                 end
  301.             end
  302.         end
  303.     elseif event[1] == "key_up" then
  304.         for i = 1, 32 do
  305.             if event[2] == keyMapping[i] then
  306.                 keys[math.floor((i - 1) / 2) + 1] = false
  307.             end
  308.         end
  309.     elseif event[1] == "timer" and event[2] == screenTimer then
  310.         screenTimer = os.startTimer(0)
  311.         if running then
  312.             for i = 1, 3 do
  313.                 doFrame()
  314.                 keypress = nil
  315.             end
  316.         end
  317.        
  318.         term.setCursorPos(1, screenHeight)
  319.         term.write((running and "Running" or "Paused").." "..tostring(speed * 60).."Hz  Ctrl = Help  Bsp = Quit    ")
  320.         for j = 1, 11 do
  321.             term.setCursorPos(screenX, screenY + j - 1)
  322.             for i = 1, 32 do
  323.                 local p1 = display[(j * 3 - 3) * 64 + i * 2 - 1] and 1 or 0
  324.                 local p2 = display[(j * 3 - 3) * 64 + i * 2] and 1 or 0
  325.                 local p3 = display[(j * 3 - 2) * 64 + i * 2 - 1] and 1 or 0
  326.                 local p4 = display[(j * 3 - 2) * 64 + i * 2] and 1 or 0
  327.                 local p5 = display[(j * 3 - 1) * 64 + i * 2 - 1] and 1 or 0
  328.                 local p6 = display[(j * 3 - 1) * 64 + i * 2]
  329.                 if p6 then
  330.                     p1, p2, p3, p4, p5 = 1 - p1, 1 - p2, 1 - p3, 1 - p4, 1 - p5
  331.                     term.setTextColor(screenColor2)
  332.                     term.setBackgroundColor(screenColor1)
  333.                 end
  334.                 term.write(string.char(128 + p1 + p2 * 2 + p3 * 4 + p4 * 8 + p5 * 16))
  335.                 if p6 then
  336.                     term.setTextColor(screenColor1)
  337.                     term.setBackgroundColor(screenColor2)
  338.                 end
  339.             end
  340.         end
  341.     end
  342. end
  343. term.setTextColor(colors.white)
  344. term.setBackgroundColor(colors.black)
  345. term.clear()
  346. term.setCursorPos(1, 1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement