Skip to content

Commit 4c9e5a3

Browse files
committed
Messing around, seems broken
1 parent 34f56c5 commit 4c9e5a3

File tree

4 files changed

+227
-0
lines changed

4 files changed

+227
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#chip-8 roms
2+
roms/
3+
14
# Byte-compiled / optimized / DLL files
25
__pycache__/
36
*.py[cod]

chip8.py

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
import os
2+
import time
3+
from font import font
4+
import random
5+
import math
6+
import sys
7+
from msvcrt import getch
8+
import keymap
9+
10+
memory = [0] * 4096
11+
registers = [0] * 16
12+
IDX, PC, opcode = 0, 0x200, 0
13+
screen = [[0] * 64 for i in range(32)]
14+
delay_timer, sound_timer = 0, 0
15+
stack, SP = [], 0
16+
keys = [False] * 16
17+
draw, last_draw = True, 0
18+
19+
20+
def getKeys():
21+
keys = [False] * 16
22+
#keys[getKeyPress()] = True
23+
24+
25+
def getKeyPress():
26+
key = None
27+
while key is None:
28+
char = getch().decode('utf-8')
29+
if char == 'c':
30+
raise Exception('C for exit')
31+
key = keymap.keymap.get(char, None)
32+
print(char, key, file= sys.stderr)
33+
return key
34+
35+
36+
def cycle():
37+
global PC, IDX, opcode, registers, memory, screen, draw, delay_timer, sound_timer
38+
opcode = (memory[PC] << 8) + memory[PC + 1]
39+
first, second, third, fourth = (opcode & 0xF000) >> 12, (
40+
opcode & 0x0F00) >> 8, (opcode & 0x00F0) >> 4, opcode & 0x000F
41+
if opcode & 0xFFFF != opcode:
42+
raise Exception("BAD OPCODE" + hex(opcode))
43+
PC += 2
44+
if first == 0:
45+
if opcode == 0x00E0:
46+
screen = [[0] * 64 for i in range(32)]
47+
elif opcode == 0x00EE:
48+
PC = stack.pop()
49+
elif first == 1:
50+
PC = opcode & 0x0FFF
51+
elif first == 2:
52+
stack.append(PC)
53+
PC = opcode & 0x0FFF
54+
if len(stack) > 16:
55+
raise Exception('STACK OVERFLOW!')
56+
elif first == 3:
57+
if registers[second] == opcode & 0x00FF:
58+
PC += 2
59+
elif first == 4:
60+
if registers[second] != opcode & 0x00FF:
61+
PC += 2
62+
elif first == 5:
63+
if registers[second] == registers[third]:
64+
PC += 2
65+
elif first == 6:
66+
registers[second] = opcode & 0x00FF
67+
elif first == 7:
68+
registers[second] = (
69+
registers[second] + (opcode & 0x00FF)) % 0xFF
70+
elif first == 8:
71+
if fourth == 0:
72+
registers[second] = registers[
73+
third]
74+
elif fourth == 1:
75+
registers[second] |= registers[
76+
third]
77+
elif fourth == 2:
78+
registers[second] &= registers[
79+
third]
80+
elif fourth == 3:
81+
registers[second] ^= registers[
82+
third]
83+
elif fourth == 4:
84+
registers[0xF] = 0
85+
registers[second] += registers[
86+
third]
87+
if registers[second] > 0xFF:
88+
registers[0xF] = 1
89+
registers[second] %= 0xFF
90+
elif fourth == 5:
91+
registers[0xF] = 1
92+
registers[second] -= registers[
93+
third]
94+
if registers[second] < 0:
95+
registers[0xF] = 0
96+
registers[second] %= 0xFF
97+
elif fourth == 6:
98+
registers[0xF] = registers[second] & 0x01
99+
registers[second] >>= 1
100+
elif fourth == 7:
101+
registers[0xF] = 1
102+
registers[second] = registers[
103+
third] - registers[second]
104+
if registers[second] < 0:
105+
registers[0xF] = 0
106+
registers[second] %= 0xFF
107+
elif fourth == 0xE:
108+
registers[0xF] = registers[second] & 0x80 >> 7
109+
registers[second] = (registers[second] << 1) % 0xFF
110+
else:
111+
raise Exception('Unknown opcode: ' + hex(opcode))
112+
elif first == 9:
113+
if registers[second] != registers[third]:
114+
PC += 2
115+
elif first == 0xA:
116+
IDX = opcode & 0x0FFF
117+
elif first == 0xB:
118+
PC = ((opcode & 0x0FFF) + registers[0]) % 0xFFFF
119+
elif first == 0xC:
120+
registers[second] = random.randrange(
121+
0xFF) & opcode
122+
elif first == 0xD:
123+
vx, vy, n = registers[second], registers[
124+
third], fourth
125+
if not n:
126+
raise Exception('16 BIT Sprite')
127+
registers[0xF] = 0
128+
for line in range(n):
129+
pixels = memory[IDX + line]
130+
for bit in range(8):
131+
if vx + bit >= 64 or vy + line >= 32:
132+
break
133+
if screen[vy + line][vx + bit] & (pixels & (1 << (7 - bit))):
134+
registers[0xF] = 1
135+
screen[vy + line][vx + bit] ^= pixels & (1 << (7 - bit))
136+
draw = True
137+
elif first == 0xE:
138+
if opcode & 0x00FF == 0x9E:
139+
getKeys()
140+
if keys[registers[second]]:
141+
PC += 2
142+
elif opcode & 0x00FF == 0xA1:
143+
getKeys()
144+
if not keys[registers[second]]:
145+
PC += 2
146+
else:
147+
raise Exception('Unknown opcode: ' + hex(opcode))
148+
elif first == 0xF:
149+
if opcode & 0x00FF == 0x07:
150+
registers[second] = math.ceil((delay_timer - time.time()) / 60.0) % 0xFF
151+
elif opcode & 0x00FF == 0x0A:
152+
registers[second] = getKeyPress()
153+
elif opcode & 0x00FF == 0x15:
154+
delay_timer = time.time() + registers[second] / 60.0
155+
elif opcode & 0x00FF == 0x18:
156+
sound_timer = time.time() + registers[second] / 60.0
157+
elif opcode & 0x00FF == 0x1E:
158+
IDX = (IDX + registers[second]) % 0xFFFF
159+
elif opcode & 0x00FF == 0x29:
160+
IDX = registers[second] * 5
161+
elif opcode & 0x00FF == 0x33:
162+
memory[IDX] = registers[second] // 100
163+
memory[IDX + 1] = (registers[second] % 100) // 10
164+
memory[IDX + 2] = registers[second] % 10
165+
elif opcode & 0x00FF == 0x55:
166+
memory[IDX:IDX + second] = registers[:second]
167+
elif opcode & 0x00FF == 0x65:
168+
registers[:second] = memory[IDX:IDX + second]
169+
else:
170+
raise Exception('Unknown opcode: ' + hex(opcode))
171+
else:
172+
raise Exception('Unknown opcode: ' + hex(opcode))
173+
174+
175+
def draw_screen():
176+
global draw, last_draw
177+
os.system('cls')
178+
for line in screen:
179+
print(''.join('#' if v else ' ' for v in line))
180+
draw = False
181+
last_draw = time.time()
182+
183+
184+
print('V: ', [hex(v) for v in registers],
185+
'IDX: ', hex(IDX), 'OP: ', hex(opcode), 'STK: ', [hex(v) for v in stack], len(memory), file=sys.stderr)
186+
187+
memory[0:len(font)] = font
188+
189+
190+
if len(sys.argv) < 2:
191+
raise Exception('Provide ROM path')
192+
193+
with open(sys.argv[1], 'rb') as file:
194+
program = file.read()
195+
196+
memory[0x200:0x200 + len(program)] = program
197+
198+
while True:
199+
print('V: ', [hex(v) for v in registers],
200+
'IDX: ', hex(IDX), 'OP: ', hex(opcode), 'STK: ', [hex(v) for v in stack], len(memory), file=sys.stderr)
201+
cycle()
202+
time.sleep(0.01)
203+
if draw and time.time() - last_draw > 0.05:
204+
draw_screen()

font.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
font = [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,
2+
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]

keymap.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
keymap = {
2+
'0': 0,
3+
'1': 1,
4+
'2': 2,
5+
'3' :3,
6+
'4' :4,
7+
'5' :5,
8+
'6' :6,
9+
'7' :7,
10+
'8' :8,
11+
'9' :9,
12+
'w' :10,
13+
'a' :11,
14+
's' :12,
15+
'd' :13,
16+
'z' :14,
17+
'x' :15
18+
}

0 commit comments

Comments
 (0)