Advertisement
nonogamer9

NumPY-8! A CHIP-8 Emulator For Stock NumWorks!

Feb 6th, 2025 (edited)
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.49 KB | Software | 0 0
  1. # NumPy-8! Version 1.0 coded by nonogamer9 (c) 2025
  2. # https://my.numworks.com/python/nonogamer9/numpyeight
  3. # This is a CHIP-8 Emulator For Stock Numworks! So Performance can be abysmal!!
  4. from kandinsky import fill_rect, color
  5. from ion import keydown
  6. import time
  7. import random
  8.  
  9. class Chip8:
  10.     def __init__(self):
  11.         self.memory = [0] * 4096
  12.         self.V = [0] * 16
  13.         self.I = 0
  14.         self.pc = 0x200
  15.         self.stack = []
  16.         self.delay_timer = 0
  17.         self.sound_timer = 0
  18.         self.keypad = [False] * 16
  19.         self.display = [[False for _ in range(64)] for _ in range(32)]
  20.         self.opcode = 0
  21.         self.draw_flag = False
  22.  
  23.         self.load_font_set()
  24.  
  25.     def load_font_set(self):
  26.         font_set = [
  27.             0xF0, 0x90, 0x90, 0x90, 0xF0,  # 0
  28.             0x20, 0x60, 0x20, 0x20, 0x70,  # 1
  29.             0xF0, 0x10, 0xF0, 0x80, 0xF0,  # 2
  30.             0xF0, 0x10, 0xF0, 0x10, 0xF0,  # 3
  31.             0x90, 0x90, 0xF0, 0x10, 0x10,  # 4
  32.             0xF0, 0x80, 0xF0, 0x10, 0xF0,  # 5
  33.             0xF0, 0x80, 0xF0, 0x90, 0xF0,  # 6
  34.             0xF0, 0x10, 0x20, 0x40, 0x40,  # 7
  35.             0xF0, 0x90, 0xF0, 0x90, 0xF0,  # 8
  36.             0xF0, 0x90, 0xF0, 0x10, 0xF0,  # 9
  37.             0xF0, 0x90, 0xF0, 0x90, 0x90,  # A
  38.             0xE0, 0x90, 0xE0, 0x90, 0xE0,  # B
  39.             0xF0, 0x80, 0x80, 0x80, 0xF0,  # C
  40.             0xE0, 0x90, 0x90, 0x90, 0xE0,  # D
  41.             0xF0, 0x80, 0xF0, 0x80, 0xF0,  # E
  42.             0xF0, 0x80, 0xF0, 0x80, 0x80   # F
  43.         ]
  44.         for i, byte in enumerate(font_set):
  45.             self.memory[i] = byte
  46.  
  47.     def emulate_cycle(self):
  48.         self.opcode = (self.memory[self.pc] << 8) | self.memory[self.pc + 1]
  49.         self.pc += 2
  50.  
  51.         x = (self.opcode & 0x0F00) >> 8
  52.         y = (self.opcode & 0x00F0) >> 4
  53.         nnn = self.opcode & 0x0FFF
  54.         nn = self.opcode & 0x00FF
  55.         n = self.opcode & 0x000F
  56.  
  57.         if self.opcode & 0xF000 == 0x0000:
  58.             if nn == 0xE0:
  59.                 self.display = [[False for _ in range(64)] for _ in range(32)]
  60.                 self.draw_flag = True
  61.             elif nn == 0xEE:
  62.                 self.pc = self.stack.pop()
  63.         elif self.opcode & 0xF000 == 0x1000:
  64.             self.pc = nnn
  65.         elif self.opcode & 0xF000 == 0x2000:
  66.             self.stack.append(self.pc)
  67.             self.pc = nnn
  68.         elif self.opcode & 0xF000 == 0x3000:
  69.             if self.V[x] == nn:
  70.                 self.pc += 2
  71.         elif self.opcode & 0xF000 == 0x4000:
  72.             if self.V[x] != nn:
  73.                 self.pc += 2
  74.         elif self.opcode & 0xF000 == 0x5000:
  75.             if self.V[x] == self.V[y]:
  76.                 self.pc += 2
  77.         elif self.opcode & 0xF000 == 0x6000:
  78.             self.V[x] = nn
  79.         elif self.opcode & 0xF000 == 0x7000:
  80.             self.V[x] = (self.V[x] + nn) & 0xFF
  81.         elif self.opcode & 0xF000 == 0x8000:
  82.             if n == 0x0:
  83.                 self.V[x] = self.V[y]
  84.             elif n == 0x1:
  85.                 self.V[x] |= self.V[y]
  86.             elif n == 0x2:
  87.                 self.V[x] &= self.V[y]
  88.             elif n == 0x3:
  89.                 self.V[x] ^= self.V[y]
  90.             elif n == 0x4:
  91.                 sum = self.V[x] + self.V[y]
  92.                 self.V[0xF] = 1 if sum > 255 else 0
  93.                 self.V[x] = sum & 0xFF
  94.             elif n == 0x5:
  95.                 self.V[0xF] = 1 if self.V[x] > self.V[y] else 0
  96.                 self.V[x] = (self.V[x] - self.V[y]) & 0xFF
  97.             elif n == 0x6:
  98.                 self.V[0xF] = self.V[x] & 0x1
  99.                 self.V[x] >>= 1
  100.             elif n == 0x7:
  101.                 self.V[0xF] = 1 if self.V[y] > self.V[x] else 0
  102.                 self.V[x] = (self.V[y] - self.V[x]) & 0xFF
  103.             elif n == 0xE:
  104.                 self.V[0xF] = (self.V[x] & 0x80) >> 7
  105.                 self.V[x] = (self.V[x] << 1) & 0xFF
  106.         elif self.opcode & 0xF000 == 0x9000:
  107.             if self.V[x] != self.V[y]:
  108.                 self.pc += 2
  109.         elif self.opcode & 0xF000 == 0xA000:
  110.             self.I = nnn
  111.         elif self.opcode & 0xF000 == 0xB000:
  112.             self.pc = nnn + self.V[0]
  113.         elif self.opcode & 0xF000 == 0xC000:
  114.             self.V[x] = random.randint(0, 255) & nn
  115.         elif self.opcode & 0xF000 == 0xD000:
  116.             self.V[0xF] = 0
  117.             for row in range(n):
  118.                 sprite_byte = self.memory[self.I + row]
  119.                 for col in range(8):
  120.                     if sprite_byte & (0x80 >> col) != 0:
  121.                         if self.display[(self.V[y] + row) % 32][(self.V[x] + col) % 64]:
  122.                             self.V[0xF] = 1
  123.                         self.display[(self.V[y] + row) % 32][(self.V[x] + col) % 64] ^= True
  124.             self.draw_flag = True
  125.         elif self.opcode & 0xF000 == 0xE000:
  126.             if nn == 0x9E:
  127.                 if self.keypad[self.V[x]]:
  128.                     self.pc += 2
  129.             elif nn == 0xA1:
  130.                 if not self.keypad[self.V[x]]:
  131.                     self.pc += 2
  132.         elif self.opcode & 0xF000 == 0xF000:
  133.             if nn == 0x07:
  134.                 self.V[x] = self.delay_timer
  135.             elif nn == 0x0A:
  136.                 key_pressed = False
  137.                 for i in range(16):
  138.                     if self.keypad[i]:
  139.                         self.V[x] = i
  140.                         key_pressed = True
  141.                         break
  142.                 if not key_pressed:
  143.                     self.pc -= 2
  144.             elif nn == 0x15:
  145.                 self.delay_timer = self.V[x]
  146.             elif nn == 0x18:
  147.                 self.sound_timer = self.V[x]
  148.             elif nn == 0x1E:
  149.                 self.I += self.V[x]
  150.             elif nn == 0x29:
  151.                 self.I = self.V[x] * 5
  152.             elif nn == 0x33:
  153.                 self.memory[self.I] = self.V[x] // 100
  154.                 self.memory[self.I + 1] = (self.V[x] % 100) // 10
  155.                 self.memory[self.I + 2] = self.V[x] % 10
  156.             elif nn == 0x55:
  157.                 for i in range(x + 1):
  158.                     self.memory[self.I + i] = self.V[i]
  159.             elif nn == 0x65:
  160.                 for i in range(x + 1):
  161.                     self.V[i] = self.memory[self.I + i]
  162.  
  163.         if self.delay_timer > 0:
  164.             self.delay_timer -= 1
  165.         if self.sound_timer > 0:
  166.             self.sound_timer -= 1
  167.  
  168.     def update_screen(self):
  169.         for y in range(32):
  170.             for x in range(64):
  171.                 if self.display[y][x]:
  172.                     fill_rect(x*2, y*2, 2, 2, color(255,255,255))
  173.                 else:
  174.                     fill_rect(x*2, y*2, 2, 2, color(0,0,0))
  175.  
  176.     def handle_input(self):
  177.         key_map = {
  178.             0: 4, 1: 5, 2: 6, 3: 7,
  179.             4: 8, 5: 9, 6: 10, 7: 11,
  180.             8: 12, 9: 13, 10: 14, 11: 15,
  181.             12: 0, 13: 1, 14: 2, 15: 3
  182.         }
  183.         for nw_key, chip8_key in key_map.items():
  184.             self.keypad[chip8_key] = keydown(nw_key)
  185.  
  186.     def load_rom(self, rom_data):
  187.         for i, byte in enumerate(rom_data):
  188.             self.memory[0x200 + i] = byte
  189.  
  190.     def run(self):
  191.         while True:
  192.             self.emulate_cycle()
  193.             self.handle_input()
  194.             if self.draw_flag:
  195.                 self.update_screen()
  196.                 self.draw_flag = False
  197.             time.sleep(1/60)
  198.  
  199. # this is where you put your converted roms to! Just use this pastebin script and your chip8 roms and they will work! : https://pastebin.com/UR6xg0jc
  200. rom_data = [
  201.     0x00, 0xE0, 0xA2, 0x48, 0x60, 0x00, 0x61, 0x1E, 0x62, 0x00, 0xD2, 0x02, 0xD2, 0x12, 0x72, 0x08,
  202.     0x32, 0x40, 0x12, 0x0A, 0x60, 0x00, 0x61, 0x3E, 0x62, 0x02, 0xA2, 0x4A, 0xD0, 0x2E, 0xD1, 0x2E,
  203.     0x72, 0x0E, 0xD0, 0x2E, 0xD1, 0x2E, 0xA2, 0x58, 0x60, 0x0B, 0x61, 0x08, 0xD0, 0x1F, 0x70, 0x0A,
  204.     0xA2, 0x67, 0xD0, 0x1F, 0x70, 0x0A, 0xA2, 0x76, 0xD0, 0x1F, 0x70, 0x03, 0xA2, 0x85, 0xD0, 0x1F,
  205.     0x70, 0x0A, 0xA2, 0x94, 0xD0, 0x1F, 0x12, 0x46, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
  206.     0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  207.     0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x81,
  208.     0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  209.     0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x80, 0x80, 0x80,
  210.     0x80, 0x80, 0x80, 0x80, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x81, 0x81, 0x81, 0x81,
  211.     0x81, 0x81, 0xFF, 0xFF,
  212. ]
  213.  
  214. chip8 = Chip8()
  215. chip8.load_rom(rom_data)
  216. chip8.run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement