├── games
├── Brick.ch8
├── Cave.ch8
├── Pong.ch8
├── Airplane.ch8
├── IBMLogo.ch8
├── Tetris.ch8
├── SpaceInvaders.ch8
└── Tic-Tac-Toe.ch8
├── screenshots
├── Bricks.png
├── IBMLogo.png
├── Tetris.png
└── SpaceInvader.png
├── LICENSE
├── README.md
└── chip8.py
/games/Brick.ch8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/games/Brick.ch8
--------------------------------------------------------------------------------
/games/Cave.ch8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/games/Cave.ch8
--------------------------------------------------------------------------------
/games/Pong.ch8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/games/Pong.ch8
--------------------------------------------------------------------------------
/games/Airplane.ch8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/games/Airplane.ch8
--------------------------------------------------------------------------------
/games/IBMLogo.ch8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/games/IBMLogo.ch8
--------------------------------------------------------------------------------
/games/Tetris.ch8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/games/Tetris.ch8
--------------------------------------------------------------------------------
/games/SpaceInvaders.ch8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/games/SpaceInvaders.ch8
--------------------------------------------------------------------------------
/games/Tic-Tac-Toe.ch8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/games/Tic-Tac-Toe.ch8
--------------------------------------------------------------------------------
/screenshots/Bricks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/screenshots/Bricks.png
--------------------------------------------------------------------------------
/screenshots/IBMLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/screenshots/IBMLogo.png
--------------------------------------------------------------------------------
/screenshots/Tetris.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/screenshots/Tetris.png
--------------------------------------------------------------------------------
/screenshots/SpaceInvader.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlpacaMax/Python-CHIP8-Emulator/HEAD/screenshots/SpaceInvader.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2019 AlpacaMax
2 |
3 | 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:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | 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.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CHIP-8 Emulator
2 |
3 | > **CHIP-8** is an interpreted programming language, developed by Joseph Weisbecker. It was initially used on the COSMAC VIP and Telmac 1800 8-bit microcomputers in the mid-1970s. CHIP-8 programs are run on a CHIP-8 virtual machine. It was made to allow video games to be more easily programmed for these computer
4 |
--[Wikipedia](https://en.wikipedia.org/wiki/Chip-8)
5 |
6 | ## Introduction
7 |
8 | This is a python version CHIP-8 Emulator. Although it was originally created as a virtual machine, CHIP-8 could be treated as a simple game console. As a result, implementing this emulator is a good way to get a brief understanding of how computer works.
9 |
10 | ## Usage
11 |
12 | ```
13 | pip3 install pygame
14 | sudo apt install sox
15 | git clone git@github.com:AlpacaMax/Python-CHIP8-Emulator
16 | cd Python-CHIP8-Emulator
17 | python3 chip8.py games/
18 | ```
19 |
20 | ## Screenshots
21 |
22 | 
23 |
24 | 
25 |
26 | 
27 |
28 | 
29 |
30 | **Note:** If you don't like the color, you can go to `line 154` and `line 155` and change `self.zeroColor` and `self.oneColor`.
31 |
32 | ## More CHIP-8 ROMs(Games)
33 |
34 | Visit [The Old Computer](https://www.theoldcomputer.com/roms/index.php?folder=Chip-8/Chip-8/Games) for more CHIP-8 games
--------------------------------------------------------------------------------
/chip8.py:
--------------------------------------------------------------------------------
1 | import pygame
2 | import time
3 | import sys
4 | import random
5 | import os
6 |
7 | class Register:
8 | def __init__(self, bits):
9 | self.value = 0
10 | self.bits = bits
11 |
12 | '''
13 | def checkFlag(self):
14 | hexValue = hex(self.value)[2:]
15 | carryORborrow = False
16 |
17 | if self.value < 0:
18 | self.value = abs(self.value)
19 | carryORborrow = True
20 |
21 | if len(hexValue) > self.bits / 4:
22 | self.value = int(hexValue[-int(self.bits / 4):], 16)
23 | carryORborrow = True
24 |
25 | if carryORborrow:
26 | return 1
27 | return 0
28 | '''
29 |
30 | def checkCarry(self):
31 | hexValue = hex(self.value)[2:]
32 |
33 | if len(hexValue) > self.bits / 4:
34 | self.value = int(hexValue[-int(self.bits / 4):], 16)
35 | return 1
36 |
37 | return 0
38 |
39 | def checkBorrow(self):
40 | if self.value < 0:
41 | self.value = abs(self.value)
42 | return 0
43 |
44 | return 1
45 |
46 | def readValue(self):
47 | return hex(self.value)
48 |
49 | def setValue(self, value):
50 | self.value = value
51 |
52 | class DelayTimer:
53 | def __init__(self):
54 | self.timer = 0
55 |
56 | def countDown(self):
57 | if self.timer > 0:
58 | self.timer -= 1
59 |
60 | def setTimer(self, value):
61 | self.timer = value
62 |
63 | def readTimer(self):
64 | return self.timer
65 |
66 | class SoundTimer(DelayTimer):
67 | def __init__(self):
68 | DelayTimer.__init__(self)
69 |
70 | def beep(self):
71 | if self.timer > 1:
72 | os.system('play --no-show-progress --null --channels 1 synth %s triangle %f' % (self.timer / 60, 440))
73 | self.timer = 0
74 |
75 | class Stack:
76 | def __init__(self):
77 | self.stack = []
78 |
79 | def push(self, value):
80 | self.stack.append(value)
81 |
82 | def pop(self):
83 | return self.stack.pop()
84 |
85 | class Emulator:
86 | def __init__(self):
87 | self.Memory = []
88 | for i in range(0, 4096):
89 | self.Memory.append(0x0)
90 |
91 | fonts = [
92 | 0xF0, 0x90, 0x90, 0x90, 0xF0, # 0
93 | 0x20, 0x60, 0x20, 0x20, 0x70, # 1
94 | 0xF0, 0x10, 0xF0, 0x80, 0xF0, # 2
95 | 0xF0, 0x10, 0xF0, 0x10, 0xF0, # 3
96 | 0x90, 0x90, 0xF0, 0x10, 0x10, # 4
97 | 0xF0, 0x80, 0xF0, 0x10, 0xF0, # 5
98 | 0xF0, 0x80, 0xF0, 0x90, 0xF0, # 6
99 | 0xF0, 0x10, 0x20, 0x40, 0x40, # 7
100 | 0xF0, 0x90, 0xF0, 0x90, 0xF0, # 8
101 | 0xF0, 0x90, 0xF0, 0x10, 0xF0, # 9
102 | 0xF0, 0x90, 0xF0, 0x90, 0x90, # A
103 | 0xE0, 0x90, 0xE0, 0x90, 0xE0, # B
104 | 0xF0, 0x80, 0x80, 0x80, 0xF0, # C
105 | 0xE0, 0x90, 0x90, 0x90, 0xE0, # D
106 | 0xF0, 0x80, 0xF0, 0x80, 0xF0, # E
107 | 0xF0, 0x80, 0xF0, 0x80, 0x80 # F
108 | ]
109 | for i in range(len(fonts)):
110 | self.Memory[i] = fonts[i]
111 |
112 | self.Registers = []
113 | for i in range(16):
114 | self.Registers.append(Register(8))
115 |
116 | self.IRegister = Register(16)
117 | self.ProgramCounter = 0x200
118 |
119 | self.stack = Stack()
120 |
121 | self.delayTimer = DelayTimer()
122 | self.soundTimer = SoundTimer()
123 | pygame.init()
124 | pygame.time.set_timer(pygame.USEREVENT+1, int(1000 / 60))
125 |
126 | self.keys = []
127 | for i in range(0, 16):
128 | self.keys.append(False)
129 | self.keyDict = {
130 | 49 : 1,
131 | 50 : 2,
132 | 51 : 3,
133 | 52 : 0xc,
134 | 113 : 4,
135 | 119 : 5,
136 | 101 : 6,
137 | 114 : 0xd,
138 | 97 : 7,
139 | 115 : 8,
140 | 100 : 9,
141 | 102 : 0xe,
142 | 122 : 0xa,
143 | 120 : 0,
144 | 99 : 0xb,
145 | 118 : 0xf
146 | }
147 |
148 | self.grid = []
149 | for i in range(32):
150 | line = []
151 | for j in range(64):
152 | line.append(0)
153 | self.grid.append(line)
154 | self.emptyGrid = self.grid[:]
155 | self.zeroColor = [0, 0, 50]
156 | self.oneColor = [255, 255, 255]
157 |
158 | self.size = 10
159 | width = 64
160 | height = 32
161 | self.screen = pygame.display.set_mode([width * self.size, height * self.size])
162 | self.screen.fill(self.oneColor)
163 | pygame.display.flip()
164 |
165 | def execOpcode(self, opcode):
166 | #print(opcode)
167 |
168 | if opcode[0] == '0':
169 |
170 | if opcode[1] != '0':
171 | #0NNN
172 |
173 | print("ROM attempts to run RCA 1802 program at <0x" + opcode[1:] + '>')
174 |
175 | else:
176 | if opcode == '00e0':
177 | #00E0
178 | #disp_clear()
179 |
180 | self.clear()
181 |
182 | elif opcode == '00ee':
183 | #00EE
184 | #return;
185 |
186 | self.ProgramCounter = self.stack.pop()
187 |
188 | elif opcode[0] == '1':
189 | #1NNN
190 | #goto NNN;
191 |
192 | self.ProgramCounter = int(opcode[1:], 16) - 2
193 |
194 | elif opcode[0] == '2':
195 | #2NNN
196 | #*(0xNNN)()
197 |
198 | self.stack.push(self.ProgramCounter)
199 | self.ProgramCounter = int(opcode[1:], 16) - 2
200 |
201 | elif opcode[0] == '3':
202 | #3XNN
203 | #if(Vx==NN)
204 |
205 | vNum = int(opcode[1], 16)
206 | targetNum = int(opcode[2:], 16)
207 |
208 | if self.Registers[vNum].value == targetNum:
209 | self.ProgramCounter += 2
210 |
211 | elif opcode[0] == '4':
212 | #4XNN
213 | #if(Vx!=NN)
214 |
215 | vNum = int(opcode[1], 16)
216 | targetNum = int(opcode[2:], 16)
217 |
218 | if self.Registers[vNum].value != targetNum:
219 | self.ProgramCounter += 2
220 |
221 | elif opcode[0] == '5':
222 | #5XY0
223 | #if(Vx==Vy)
224 |
225 | v1 = int(opcode[1], 16)
226 | v2 = int(opcode[2], 16)
227 |
228 | if self.Registers[v1].value == self.Registers[v2].value:
229 | self.ProgramCounter += 2
230 |
231 | elif opcode[0] == '6':
232 | #6XNN
233 | #Vx = NN
234 |
235 | vNum = int(opcode[1], 16)
236 | targetNum = int(opcode[2:], 16)
237 |
238 | self.Registers[vNum].value = targetNum
239 |
240 | elif opcode[0] == '7':
241 | #7XNN
242 | #Vx += NN
243 |
244 | vNum = int(opcode[1], 16)
245 | targetNum = int(opcode[2:], 16)
246 |
247 | self.Registers[vNum].value += targetNum
248 | self.Registers[vNum].checkCarry()
249 |
250 | elif opcode[0] == '8':
251 | if opcode[3] == '0':
252 | #8XY0
253 | #Vx=Vy
254 |
255 | v1 = int(opcode[1], 16)
256 | v2 = int(opcode[2], 16)
257 |
258 | self.Registers[v1].value = self.Registers[v2].value
259 |
260 | elif opcode[3] == '1':
261 | #8XY1
262 | #Vx=Vx|Vy
263 |
264 | v1 = int(opcode[1], 16)
265 | v2 = int(opcode[2], 16)
266 |
267 | self.Registers[v1].value = self.Registers[v1].value | self.Registers[v2].value
268 |
269 | elif opcode[3] == '2':
270 | #8XY2
271 | #Vx=Vx&Vy
272 |
273 | v1 = int(opcode[1], 16)
274 | v2 = int(opcode[2], 16)
275 |
276 | self.Registers[v1].value = self.Registers[v1].value & self.Registers[v2].value
277 |
278 | elif opcode[3] == '3':
279 | #8XY3
280 | #Vx=Vx^Vy
281 |
282 | v1 = int(opcode[1], 16)
283 | v2 = int(opcode[2], 16)
284 |
285 | self.Registers[v1].value = self.Registers[v1].value ^ self.Registers[v2].value
286 |
287 | elif opcode[3] == '4':
288 | #8XY4
289 | #Vx += Vy
290 |
291 | v1 = int(opcode[1], 16)
292 | v2 = int(opcode[2], 16)
293 |
294 | self.Registers[v1].value += self.Registers[v2].value
295 |
296 | self.Registers[0xf].value = self.Registers[v1].checkCarry()
297 |
298 | elif opcode[3] == '5':
299 | #8XY5
300 | #Vx -= Vy
301 |
302 | v1 = int(opcode[1], 16)
303 | v2 = int(opcode[2], 16)
304 |
305 | self.Registers[v1].value -= self.Registers[v2].value
306 |
307 | self.Registers[0xf].value = self.Registers[v1].checkBorrow()
308 |
309 | elif opcode[3] == '6':
310 | #8XY6
311 | #Vx>>1
312 |
313 | v1 = int(opcode[1], 16)
314 | leastBit = int(bin(self.Registers[v1].value)[-1])
315 |
316 | self.Registers[v1].value = self.Registers[v1].value >> 1
317 | self.Registers[0xf].value = leastBit
318 |
319 | elif opcode[3] == '7':
320 | #8XY7
321 | #Vx=Vy-Vx
322 |
323 | v1 = int(opcode[1], 16)
324 | v2 = int(opcode[2], 16)
325 |
326 | self.Registers[v1].value = self.Registers[v2].value - self.Registers[v1].value
327 |
328 | self.Registers[0xf].value = self.Registers[v1].checkBorrow()
329 |
330 | elif opcode[3] == 'e':
331 | #8XYE
332 | #Vx<<=1
333 |
334 | v1 = int(opcode[1], 16)
335 | mostBit = int(bin(self.Registers[v1].value)[2])
336 |
337 | self.Registers[v1].value = self.Registers[v1].value << 1
338 | self.Registers[0xf].value = mostBit
339 |
340 | elif opcode[0] == '9':
341 | #9XY0
342 | #if(Vx!=Vy)
343 |
344 | v1 = int(opcode[1], 16)
345 | v2 = int(opcode[2], 16)
346 |
347 | if self.Registers[v1].value != self.Registers[v2].value:
348 | self.ProgramCounter += 2
349 |
350 | elif opcode[0] == 'a':
351 | #ANNN
352 | #I = NNN
353 |
354 | addr = int(opcode[1:], 16)
355 |
356 | self.IRegister.value = addr
357 |
358 | elif opcode[0] == 'b':
359 | #BNNN
360 | #PC=V0+NNN
361 |
362 | addr = int(opcode[1:], 16)
363 |
364 | self.ProgramCounter = self.Registers[0].value + addr - 2
365 |
366 | elif opcode[0] == 'c':
367 | #CXNN
368 | #Vx=rand()&NN
369 |
370 | vNum = int(opcode[1], 16)
371 | targetNum = int(opcode[2:], 16)
372 |
373 | rand = random.randint(0, 255)
374 |
375 | self.Registers[vNum].value = targetNum & rand
376 |
377 | elif opcode[0] == 'd':
378 | #DXYN
379 | #draw(Vx,Vy,N)
380 |
381 | Vx = int(opcode[1], 16)
382 | Vy = int(opcode[2], 16)
383 | N = int(opcode[3], 16)
384 |
385 | addr = self.IRegister.value
386 | sprite = self.Memory[addr: addr + N]
387 |
388 | for i in range(len(sprite)):
389 | if type(sprite[i]) == str:
390 | sprite[i] = int(sprite[i], 16)
391 |
392 | if self.draw(self.Registers[Vx].value, self.Registers[Vy].value, sprite):
393 | self.Registers[0xf].value = 1
394 | else:
395 | self.Registers[0xf].value = 0
396 |
397 | elif opcode[0] == 'e':
398 | if opcode[2:] == '9e':
399 | #EX9E
400 | #if(key()==Vx)
401 |
402 | Vx = int(opcode[1], 16)
403 | key = self.Registers[Vx].value
404 | if self.keys[key]:
405 | self.ProgramCounter += 2
406 |
407 | elif opcode[2:] == 'a1':
408 | #EXA1
409 | #if(key()!=Vx)
410 |
411 | Vx = int(opcode[1], 16)
412 | key = self.Registers[Vx].value
413 | if not self.keys[key]:
414 | self.ProgramCounter += 2
415 |
416 | elif opcode[0] == 'f':
417 | if opcode[2:] == '07':
418 | #FX07
419 | #delay_timer(Vx)
420 |
421 | Vx = int(opcode[1], 16)
422 | self.Registers[Vx].value = self.delayTimer.readTimer()
423 |
424 | elif opcode[2:] == '0a':
425 | #FX0A
426 | #Vx = get_key()
427 |
428 | Vx = int(opcode[1], 16)
429 | key = None
430 |
431 | while True:
432 | self.keyHandler()
433 | isKeyDown = False
434 |
435 | for i in range(len(self.keys)):
436 | if self.keys[i]:
437 | key = i
438 | isKeyDown = True
439 |
440 | if isKeyDown:
441 | break
442 |
443 | self.Registers[Vx].value = key
444 |
445 | elif opcode[2:] == '15':
446 | #FX15
447 | #delay_timer(Vx)
448 |
449 | Vx = int(opcode[1], 16)
450 | value = self.Registers[Vx].value
451 |
452 | self.delayTimer.setTimer(value)
453 |
454 | elif opcode[2:] == '18':
455 | #FX18
456 | #sound_timer(Vx)
457 |
458 | Vx = int(opcode[1], 16)
459 | value = self.Registers[Vx].value
460 |
461 | self.soundTimer.setTimer(value)
462 |
463 | elif opcode[2:] == '1e':
464 | #FX1E
465 | #I += Vx
466 |
467 | Vx = int(opcode[1], 16)
468 | self.IRegister.value += self.Registers[Vx].value
469 |
470 | elif opcode[2:] == '29':
471 | #FX29
472 | #I = sprite_addr[Vx]
473 |
474 | Vx = int(opcode[1], 16)
475 | value = self.Registers[Vx].value
476 |
477 | self.IRegister.value = value * 5
478 |
479 | elif opcode[2:] == '33':
480 | #FX33
481 | '''
482 | set_BCD(Vx);
483 | *(I+0)=BCD(3);
484 | *(I+1)=BCD(2);
485 | *(I+2)=BCD(1);
486 | '''
487 |
488 | Vx = int(opcode[1], 16)
489 | value = str(self.Registers[Vx].value)
490 |
491 | fillNum = 3 - len(value)
492 | value = '0' * fillNum + value
493 |
494 | for i in range(len(value)):
495 | self.Memory[self.IRegister.value + i] = int(value[i])
496 |
497 | elif opcode[2:] == '55':
498 | #FX55
499 | #reg_dump(Vx, &I)
500 |
501 | Vx = int(opcode[1], 16)
502 | for i in range(0, Vx + 1):
503 | self.Memory[self.IRegister.value + i] = self.Registers[i].value
504 |
505 | elif opcode[2:] == '65':
506 | #FX65
507 | #reg_load(Vx, &I)
508 |
509 | Vx = int(opcode[1], 16)
510 | for i in range(0, Vx + 1):
511 | self.Registers[i].value = self.Memory[self.IRegister.value + i]
512 |
513 | self.ProgramCounter += 2
514 |
515 | def execution(self):
516 | index = self.ProgramCounter
517 | high = self.hexHandler(self.Memory[index])
518 | low = self.hexHandler(self.Memory[index + 1])
519 |
520 | opcode = high + low
521 |
522 | self.execOpcode(opcode)
523 |
524 | def draw(self, Vx, Vy, sprite):
525 | collision = False
526 |
527 | spriteBits = []
528 | for i in sprite:
529 | binary = bin(i)
530 | line = list(binary[2:])
531 | fillNum = 8 - len(line)
532 | line = ['0'] * fillNum + line
533 |
534 | spriteBits.append(line)
535 |
536 | '''
537 | for i in spriteBits:
538 | print(i)
539 | '''
540 |
541 | for i in range(len(spriteBits)):
542 | #line = ''
543 | for j in range(8):
544 | try:
545 | if self.grid[Vy + i][Vx + j] == 1 and int(spriteBits[i][j]) == 1:
546 | collision = True
547 |
548 | self.grid[Vy + i][Vx + j] = self.grid[Vy + i][Vx + j] ^ int(spriteBits[i][j])
549 | #line += str(int(spriteBits[i][j]))
550 | except:
551 | continue
552 |
553 | #print(line)
554 |
555 | return collision
556 |
557 | def clear(self):
558 | for i in range(len(self.grid)):
559 | for j in range(len(self.grid[0])):
560 | self.grid[i][j] = 0
561 |
562 | def readProg(self, filename):
563 | rom = self.convertProg(filename)
564 |
565 | offset = int('0x200', 16)
566 | for i in rom:
567 | self.Memory[offset] = i
568 | offset += 1
569 |
570 | def convertProg(self, filename):
571 | rom = []
572 |
573 | with open(filename, 'rb') as f:
574 | wholeProgram = f.read()
575 |
576 | for i in wholeProgram:
577 | opcode = i
578 | rom.append(opcode)
579 |
580 | return rom
581 |
582 | def hexHandler(self, Num):
583 | newHex = hex(Num)[2:]
584 | if len(newHex) == 1:
585 | newHex = '0' + newHex
586 |
587 | return newHex
588 |
589 | def keyHandler(self):
590 | '''
591 | Chip8 My Keys
592 | --------- ---------
593 | 1 2 3 C 1 2 3 4
594 | 4 5 6 D q w e r
595 | 7 8 9 E a s d f
596 | A 0 B F z x c v
597 | '''
598 |
599 | for event in pygame.event.get():
600 | if event.type == pygame.QUIT:
601 | sys.exit()
602 |
603 | elif event.type == pygame.USEREVENT+1:
604 | self.delayTimer.countDown()
605 |
606 | elif event.type == pygame.KEYDOWN:
607 | try:
608 | targetKey = self.keyDict[event.key]
609 | self.keys[targetKey] = True
610 |
611 | except: pass
612 |
613 | elif event.type == pygame.KEYUP:
614 | try:
615 | targetKey = self.keyDict[event.key]
616 | self.keys[targetKey] = False
617 |
618 | except: pass
619 |
620 | def mainLoop(self):
621 | clock = pygame.time.Clock()
622 |
623 | while True:
624 | clock.tick(300)
625 | self.keyHandler()
626 | self.soundTimer.beep()
627 | self.execution()
628 | self.display()
629 |
630 | def display(self):
631 | for i in range(0, len(self.grid)):
632 | for j in range(0, len(self.grid[0])):
633 | cellColor = self.zeroColor
634 |
635 | if self.grid[i][j] == 1:
636 | cellColor = self.oneColor
637 |
638 | pygame.draw.rect(self.screen, cellColor, [j * self.size, i * self.size, self.size, self.size], 0)
639 |
640 | pygame.display.flip()
641 |
642 | chip8 = Emulator()
643 | chip8.readProg(sys.argv[1])
644 | chip8.mainLoop()
645 |
--------------------------------------------------------------------------------