A CHIP-8 Emulator For Stock NumWorks!
# NumPy-8! Version 1.0 coded by nonogamer9 (c) 2025 # This is a CHIP-8 Emulator For Stock Numworks! So Performance can be abysmal!! # This Chip 8 Emulator Is A derivative from nono CHIP-8! # Pastebin! https://pastebin.com/AJBpBP1m from kandinsky import fill_rect, color from ion import keydown import time import random class Chip8: def __init__(self): self.memory = [0] * 4096 self.V = [0] * 16 self.I = 0 self.pc = 0x200 self.stack = [] self.delay_timer = 0 self.sound_timer = 0 self.keypad = [False] * 16 self.display = [[False for _ in range(64)] for _ in range(32)] self.opcode = 0 self.draw_flag = False self.load_font_set() def load_font_set(self): font_set = [ 0xF0, 0x90, 0x90, 0x90, 0xF0, # 0 0x20, 0x60, 0x20, 0x20, 0x70, # 1 0xF0, 0x10, 0xF0, 0x80, 0xF0, # 2 0xF0, 0x10, 0xF0, 0x10, 0xF0, # 3 0x90, 0x90, 0xF0, 0x10, 0x10, # 4 0xF0, 0x80, 0xF0, 0x10, 0xF0, # 5 0xF0, 0x80, 0xF0, 0x90, 0xF0, # 6 0xF0, 0x10, 0x20, 0x40, 0x40, # 7 0xF0, 0x90, 0xF0, 0x90, 0xF0, # 8 0xF0, 0x90, 0xF0, 0x10, 0xF0, # 9 0xF0, 0x90, 0xF0, 0x90, 0x90, # A 0xE0, 0x90, 0xE0, 0x90, 0xE0, # B 0xF0, 0x80, 0x80, 0x80, 0xF0, # C 0xE0, 0x90, 0x90, 0x90, 0xE0, # D 0xF0, 0x80, 0xF0, 0x80, 0xF0, # E 0xF0, 0x80, 0xF0, 0x80, 0x80 # F ] for i, byte in enumerate(font_set): self.memory[i] = byte def emulate_cycle(self): self.opcode = (self.memory[self.pc] << 8) | self.memory[self.pc + 1] self.pc += 2 x = (self.opcode & 0x0F00) >> 8 y = (self.opcode & 0x00F0) >> 4 nnn = self.opcode & 0x0FFF nn = self.opcode & 0x00FF n = self.opcode & 0x000F if self.opcode & 0xF000 == 0x0000: if nn == 0xE0: self.display = [[False for _ in range(64)] for _ in range(32)] self.draw_flag = True elif nn == 0xEE: self.pc = self.stack.pop() elif self.opcode & 0xF000 == 0x1000: self.pc = nnn elif self.opcode & 0xF000 == 0x2000: self.stack.append(self.pc) self.pc = nnn elif self.opcode & 0xF000 == 0x3000: if self.V[x] == nn: self.pc += 2 elif self.opcode & 0xF000 == 0x4000: if self.V[x] != nn: self.pc += 2 elif self.opcode & 0xF000 == 0x5000: if self.V[x] == self.V[y]: self.pc += 2 elif self.opcode & 0xF000 == 0x6000: self.V[x] = nn elif self.opcode & 0xF000 == 0x7000: self.V[x] = (self.V[x] + nn) & 0xFF elif self.opcode & 0xF000 == 0x8000: if n == 0x0: self.V[x] = self.V[y] elif n == 0x1: self.V[x] |= self.V[y] elif n == 0x2: self.V[x] &= self.V[y] elif n == 0x3: self.V[x] ^= self.V[y] elif n == 0x4: sum = self.V[x] + self.V[y] self.V[0xF] = 1 if sum > 255 else 0 self.V[x] = sum & 0xFF elif n == 0x5: self.V[0xF] = 1 if self.V[x] > self.V[y] else 0 self.V[x] = (self.V[x] - self.V[y]) & 0xFF elif n == 0x6: self.V[0xF] = self.V[x] & 0x1 self.V[x] >>= 1 elif n == 0x7: self.V[0xF] = 1 if self.V[y] > self.V[x] else 0 self.V[x] = (self.V[y] - self.V[x]) & 0xFF elif n == 0xE: self.V[0xF] = (self.V[x] & 0x80) >> 7 self.V[x] = (self.V[x] << 1) & 0xFF elif self.opcode & 0xF000 == 0x9000: if self.V[x] != self.V[y]: self.pc += 2 elif self.opcode & 0xF000 == 0xA000: self.I = nnn elif self.opcode & 0xF000 == 0xB000: self.pc = nnn + self.V[0] elif self.opcode & 0xF000 == 0xC000: self.V[x] = random.randint(0, 255) & nn elif self.opcode & 0xF000 == 0xD000: self.V[0xF] = 0 for row in range(n): sprite_byte = self.memory[self.I + row] for col in range(8): if sprite_byte & (0x80 >> col) != 0: if self.display[(self.V[y] + row) % 32][(self.V[x] + col) % 64]: self.V[0xF] = 1 self.display[(self.V[y] + row) % 32][(self.V[x] + col) % 64] ^= True self.draw_flag = True elif self.opcode & 0xF000 == 0xE000: if nn == 0x9E: if self.keypad[self.V[x]]: self.pc += 2 elif nn == 0xA1: if not self.keypad[self.V[x]]: self.pc += 2 elif self.opcode & 0xF000 == 0xF000: if nn == 0x07: self.V[x] = self.delay_timer elif nn == 0x0A: key_pressed = False for i in range(16): if self.keypad[i]: self.V[x] = i key_pressed = True break if not key_pressed: self.pc -= 2 elif nn == 0x15: self.delay_timer = self.V[x] elif nn == 0x18: self.sound_timer = self.V[x] elif nn == 0x1E: self.I += self.V[x] elif nn == 0x29: self.I = self.V[x] * 5 elif nn == 0x33: self.memory[self.I] = self.V[x] // 100 self.memory[self.I + 1] = (self.V[x] % 100) // 10 self.memory[self.I + 2] = self.V[x] % 10 elif nn == 0x55: for i in range(x + 1): self.memory[self.I + i] = self.V[i] elif nn == 0x65: for i in range(x + 1): self.V[i] = self.memory[self.I + i] if self.delay_timer > 0: self.delay_timer -= 1 if self.sound_timer > 0: self.sound_timer -= 1 def update_screen(self): for y in range(32): for x in range(64): if self.display[y][x]: fill_rect(x*2, y*2, 2, 2, color(255,255,255)) else: fill_rect(x*2, y*2, 2, 2, color(0,0,0)) def handle_input(self): key_map = { 0: 4, 1: 5, 2: 6, 3: 7, 4: 8, 5: 9, 6: 10, 7: 11, 8: 12, 9: 13, 10: 14, 11: 15, 12: 0, 13: 1, 14: 2, 15: 3 } for nw_key, chip8_key in key_map.items(): self.keypad[chip8_key] = keydown(nw_key) def load_rom(self, rom_data): for i, byte in enumerate(rom_data): self.memory[0x200 + i] = byte def run(self): while True: self.emulate_cycle() self.handle_input() if self.draw_flag: self.update_screen() self.draw_flag = False time.sleep(1/60) # 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 rom_data = [ 0x00, 0xE0, 0xA2, 0x48, 0x60, 0x00, 0x61, 0x1E, 0x62, 0x00, 0xD2, 0x02, 0xD2, 0x12, 0x72, 0x08, 0x32, 0x40, 0x12, 0x0A, 0x60, 0x00, 0x61, 0x3E, 0x62, 0x02, 0xA2, 0x4A, 0xD0, 0x2E, 0xD1, 0x2E, 0x72, 0x0E, 0xD0, 0x2E, 0xD1, 0x2E, 0xA2, 0x58, 0x60, 0x0B, 0x61, 0x08, 0xD0, 0x1F, 0x70, 0x0A, 0xA2, 0x67, 0xD0, 0x1F, 0x70, 0x0A, 0xA2, 0x76, 0xD0, 0x1F, 0x70, 0x03, 0xA2, 0x85, 0xD0, 0x1F, 0x70, 0x0A, 0xA2, 0x94, 0xD0, 0x1F, 0x12, 0x46, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, ] chip8 = Chip8() chip8.load_rom(rom_data) chip8.run()