I'm making an emulator for the chip-8 using the Godot 4.3 game engine, It's almost complete and you can play pong on it perfectly fine, But it can't display numbers from the built in font.
Each character is 4 pixels wide and 5 pixels high. The character 0 has the encoding 0xF0, 0x90, 0x90, 0x90, 0xF0 which is interpreted as follows:
| hex | bin | pixels |
|---|---|---|
| 0xF0 | 1111 | ████ |
| 0x90 | 1001 | █ █ |
| 0x90 | 1001 | █ █ |
| 0x90 | 1001 | █ █ |
| 0xF0 | 1111 | ████ |
Here's my font as packed byte array:
# RAM var RAM: PackedByteArray = [] # Built in font: var font: PackedByteArray = [ 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 ] func _ready() -> void: # Other code... # Load font into RAM: var offset: int = 0x50 for i: int in font: RAM[offset] = i offset += 1 var rom: PackedByteArray = open_read_and_get_ROM("rom_path_here") load_rom_into_ram(rom) func load_rom_into_ram(ROM: PackedByteArray) -> void: var offset: int = 0x200 for i: int in ROM: RAM[offset] = i offset += 1 chip-8 roms are supposed to use the font that's already built in to your emulator, But the roms I try display nonsense instead of displaying actual hex numbers.
I really don't think there's anything wrong with the draw instruction because It can draw anything else perfectly but here it is anyway:
0xD000: # 1st nibble is 'D': # DXYN: Draws a sprite at coordinate (VX, VY)... registers[0xF] = 0 # VF register must be cleared first. var x_pos: int = registers[opcode >> 8 & 0xF] % 64 var y_pos: int = registers[opcode >> 4 & 0xF] % 32 for N: int in range(opcode & 0x000F): var Nth_byte: int = RAM[index_register + N] for i: int in range(8): if x_pos >= 64: x_pos = x_pos % 64 # wrap coordinates when reaching end of screen. screen[x_pos][y_pos] = screen[x_pos][y_pos] ^ (Nth_byte << i & 0b10000000) if screen[x_pos][y_pos] ^ (Nth_byte << i & 0b10000000) != 0: # Check if pixel collision. registers[0xF] = 1 # add 1 to the flag register VF. x_pos += 1 y_pos += 1 x_pos -= 8 if y_pos >= 32: y_pos = y_pos % 32 # wrap coordinates when reaching end of screen. queue_redraw() 


