CHIP8模拟器的python3实现-3-指令实现
class Chip8CPU(object):
def __init__(self, screen):
self.registers = {
'v': [],
'index': 0,
'pc': 0,
'sp': 0,
'rpl': []
}
self.timers = {
'delay': 0,
'sound': 0,
} self.operation_lookup = {
0x0: self.screen_return,
0x1: self.jump_to_address,
0x2: self.jump_to_subroutine,
0x3: self.skip_if_reg_equal_val,
0x4: self.skip_if_reg_not_equal_val,
0x5: self.skip_if_reg_equal_reg,
0x6: self.move_value_to_reg,
0x7: self.add_value_to_reg,
0x8: self.execute_logical_instruction,
0x9: self.skip_if_reg_not_equal_reg,
0xA: self.load_index_reg_with_value,
0xB: self.jump_to_index_plus_value,
0xC: self.generate_random_number_to_reg,
0xD: self.draw_sprite,
0xE: self.keyboard_routines,
0xF: self.misc_routines, } self.logical_operation_lookup = {
0x0: self.move_reg_into_reg,
0x1: self.logical_or,
0x2: self.logical_and,
0x3: self.exclusive_or,
0x4: self.add_reg_to_reg,
0x5: self.subtract_reg_from_reg,
0x6: self.right_shift_reg,
0x7: self.substract_reg_from_reg1,
0xE: self.left_shift_reg,
} self.misc_routine_lookup = {
0x07: self.move_delay_timer_into_reg,
0x0A: self.wait_for_keypress,
0x15: self.move_reg_into_delay_timer,
0x18: self.move_reg_into_sound_timer,
0x1E: self.add_reg_into_index,
0x29: self.load_index_with_reg_sprite,
0x30: self.load_index_with_extended_reg_sprite,
0x33: self.store_bcd_in_memory,
0x55: self.store_regs_in_memory,
0x65: self.read_regs_from_memory,
0x75: self.store_regs_in_rpl,
0x85: self.read_regs_from_rpl
} self.operand = 0
self.mode = MODE_NORMAL
self.screen = screen self.memory = bytearray(MAX_MEMORY)
self.reset()
self.running = True def execute_instruction(self, operand=None):
if operand:
self.operand = operand
else:
self.operand = int(self.memory[self.registers['pc']])
self.operand = self.operand << 8
self.operand += int(self.memory[self.registers['pc'] + 1])
self.registers['pc'] += 2
operation = (self.operand & 0xF000) >> 12
self.operation_lookup[operation]()
return self.operand def screen_return(self):
operation = self.operand & 0x00FF
sub_operation = operation & 0x00F0
if sub_operation == 0x00C0:
num_lines = self.operand & 0x000F
self.screen.scroll_down(num_lines)
elif operation == 0x00E0:
self.screen.clear_screen()
elif operation == 0x00EE:
self.return_from_subroutine()
elif operation == 0x00FB:
self.screen.scroll_right()
elif operation == 0x00FC:
self.screen.scroll_left()
elif operation == 0x00FD:
self.running = False
elif operation == 0x00FE:
self.disable_extended_mode()
elif operation == 0x00FF:
self.enable_extended_mode() def return_from_subroutine(self):
self.registers['sp'] -= 1
self.registers['pc'] = self.memory[self.registers['sp']] << 8
self.registers['sp'] -= 1
self.registers['pc'] += self.memory[self.registers['sp']] def enable_extended_mode(self):
self.screen.set_extended()
self.mode = MODE_EXTENDED def disable_extended_mode(self):
self.screen.set_normal()
self.mode = MODE_NORMAL def jump_to_address(self):
self.registers['pc'] = self.operand & 0x0FFF def jump_to_subroutine(self):
self.memory[self.registers['sp']] = self.registers['pc'] & 0x00FF
self.registers['sp'] += 1
self.memory[self.registers['sp']] = (self.registers['pc'] & 0xFF00) >> 8
self.registers['sp'] += 1
self.registers['pc'] = self.operand & 0x0FFF def skip_if_reg_equal_val(self):
source = (self.operand & 0x0F00) >> 8
if self.registers['v'][source] == (self.operand & 0x00FF):
self.registers['pc'] += 2 def skip_if_reg_not_equal_val(self):
source = (self.operand & 0x0F00) >> 8
if self.registers['v'][source] != (self.operand & 0x00FF):
self.registers['pc'] += 2 def skip_if_reg_equal_reg(self):
source = (self.operand & 0x0F00) >> 8
target = (self.operand & 0x00F0) >> 4
if self.registers['v'][source] == self.registers['v'][target]:
self.registers['pc'] += 2 def move_value_to_reg(self):
target = (self.operand & 0x0F00) >> 8
self.registers['v'][target] = self.operand & 0x00FF def add_value_to_reg(self):
target = (self.operand & 0x0F00) >> 8
temp = self.registers['v'][target] + (self.operand & 0x00FF)
self.registers['v'][target] = temp if temp < 256 else temp - 256 def skip_if_reg_not_equal_reg(self):
source = (self.operand & 0x0F00) >> 8
target = (self.operand & 0x00F0) >> 4
if self.registers['v'][source] != self.registers['v'][target]:
self.registers['pc'] += 2 def load_index_reg_with_value(self):
self.registers['index'] = self.operand & 0x0FFF def jump_to_index_plus_value(self):
self.registers['pc'] = self.registers['index'] + (self.operand & 0x0FFF) def generate_random_number_to_reg(self):
value = self.operand & 0x00FF
target = (self.operand & 0x0F00) >> 8
self.registers['v'][target] = value & randint(0, 255) def draw_sprite(self):
x_source = (self.operand & 0x0F00) >> 8
y_source = (self.operand & 0x00F0) >> 4
x_pos = self.registers['v'][x_source]
y_pos = self.registers['v'][y_source]
num_bytes = self.operand & 0x000F
self.registers['v'][0xF] = 0 if self.mode == MODE_EXTENDED and num_bytes == 0:
self.draw_extended(x_pos, y_pos, 16)
else:
self.draw_normal(x_pos, y_pos, num_bytes) def draw_normal(self, x_pos, y_pos, num_bytes):
for y_index in range(num_bytes):
color_byte = bin(self.memory[self.registers['index'] + y_index])
color_byte = color_byte[2:].zfill(8)
y_coord = y_pos + y_index
y_coord = y_coord % self.screen.get_height() for x_index in range(8):
x_coord = x_pos + x_index
x_coord = x_coord % self.screen.get_width() color = int(color_byte[x_index])
current_color = self.screen.get_pixel(x_coord, y_coord) if color == 1 and current_color == 1:
self.registers['v'][0xF] = 1
color = 0
elif color == 0 and current_color == 1:
color = 1 self.screen.draw_pixel(x_coord, y_coord, color) self.screen.update() def draw_extended(self, x_pos, y_pos, num_bytes):
for y_index in range(num_bytes):
for x_byte in range(2):
color_byte = bin(self.memory[self.registers['index'] + (y_index * 2) + x_byte])
color_byte = color_byte[2:].zfill(8)
y_coord = y_pos + y_index
y_coord = y_coord % self.screen.height for x_index in range(8):
x_coord = x_pos + x_index + (x_byte * 8)
x_coord = x_coord % self.screen.width
color = int(color_byte[x_index])
current_color = self.screen.get_pixel(x_coord, y_coord) if color == 1 and current_color == 1:
self.registers['v'][0xF] = 1
color = 0 elif color == 0 and current_color == 1:
color = 1 self.screen.draw_pixel(x_coord, y_coord, color) self.screen.update() def keyboard_routines(self):
operation = self.operand & 0x00FF
source = (self.operand & 0x0F00) >> 8 key_to_check = self.registers['v'][source]
keys_pressed = key.get_pressed()
if operation == 0x9E:
if keys_pressed[KEY_MAPPINGS[key_to_check]]:
self.registers['pc'] += 2
elif operation == 0xA1:
if not keys_pressed[KEY_MAPPINGS[key_to_check]]:
self.registers['pc'] += 2 def execute_logical_instruction(self):
operation = self.operand & 0x000F
self.logical_operation_lookup[operation]() def move_reg_into_reg(self):
target = (self.operand & 0x0F00) >> 8
source = (self.operand & 0x00F0) >> 4
self.registers['v'][target] = self.registers['v'][source] def logical_or(self):
target = (self.operand & 0x0F00) >> 8
source = (self.operand & 0x00F0) >> 4
self.registers['v'][target] |= self.registers['v'][source] def logical_and(self):
target = (self.operand & 0x0F00) >> 8
source = (self.operand & 0x00F0) >> 4
self.registers['v'][target] &= self.registers['v'][source] def exclusive_or(self):
target = (self.operand & 0x0F00) >> 8
source = (self.operand & 0x00F0) >> 4
self.registers['v'][target] ^= self.registers['v'][source] def add_reg_to_reg(self):
target = (self.operand & 0x0F00) >> 8
source = (self.operand & 0x00F0) >> 4
temp = self.registers['v'][target] + self.registers['v'][source]
if temp > 255:
self.registers['v'][target] = temp - 256
self.registers['v'][0xF] = 1
else:
self.registers['v'][target] = temp
self.registers['v'][0xF] = 0 def subtract_reg_from_reg(self):
target = (self.operand & 0x0F00) >> 8
source = (self.operand & 0x00F0) >> 4
source_reg = self.registers['v'][source]
target_reg = self.registers['v'][target]
if target_reg > source_reg:
target_reg -= source_reg
self.registers['v'][0xF] = 1
else:
target_reg = 256 + target_reg - source_reg
self.registers['v'][0xF] = 0
self.registers['v'][target] = target_reg def right_shift_reg(self):
source = (self.operand & 0x0F00) >> 8
target = (self.operand & 0x00F0) >> 4
bit_zero = self.registers['v'][source] & 0x1
self.registers['v'][target] = self.registers['v'][source] >> 1
self.registers['v'][0xF] = bit_zero def substract_reg_from_reg1(self):
target = (self.operand & 0x0F00) >> 8
source = (self.operand & 0x00F0) >> 4
source_reg = self.registers['v'][source]
target_reg = self.registers['v'][target]
if source_reg > target_reg:
target_reg = source_reg - target_reg
self.registers['v'][0xF] = 1
else:
target_reg = 256 + source_reg - target_reg
self.registers['v'][0xF] = 0
self.registers['v'][target] = target_reg def left_shift_reg(self):
source = (self.operand & 0x0F00) >> 8
target = (self.operand & 0x00F0) >> 4
bit_seven = (self.registers['v'][source] & 0x80) >> 8
self.registers['v'][target] = self.registers['v'][source] << 1
self.registers['v'][0xF] = bit_seven def misc_routines(self):
operation = self.operand & 0x00FF
self.misc_routine_lookup[operation]() def move_delay_timer_into_reg(self):
target = (self.operand & 0x0F00) >> 8
self.registers['v'][target] = self.timers['delay'] def wait_for_keypress(self):
target = (self.operand & 0x0F00) >> 8
key_pressed = False
while not key_pressed:
event = pygame.event.wait()
if event.type == pygame.KEYDOWN:
keys_pressed = key.get_pressed()
for keyval, lookup_key in KEY_MAPPINGS.items():
if keys_pressed[lookup_key]:
self.registers['v'][target] = keyval
key_pressed = True
break def move_reg_into_delay_timer(self):
source = (self.operand & 0x0F00) >> 8
self.timers['delay'] = self.registers['v'][source] def move_reg_into_sound_timer(self):
source = (self.operand & 0x0F00) >> 8
self.timers['sound'] = self.registers['v'][source] def load_index_with_reg_sprite(self):
source = (self.operand & 0x0F00) >> 8
self.registers['index'] = self.registers['v'][source] * 5 def load_index_with_extended_reg_sprite(self):
source = (self.operand & 0x0F00) >> 8
self.registers['index'] = self.registers['v'][source] * 10 def add_reg_into_index(self):
source = (self.operand & 0x0F00) >> 8
self.registers['index'] += self.registers['v'][source] def store_bcd_in_memory(self):
source = (self.operand & 0x0F00) >> 8
bcd_value = '{:03d}'.format(self.registers['v'][source])
self.memory[self.registers['index']] = int(bcd_value[0])
self.memory[self.registers['index'] + 1] = int(bcd_value[1])
self.memory[self.registers['index'] + 2] = int(bcd_value[2]) def store_regs_in_memory(self):
source = (self.operand & 0x0F00) >> 8
for counter in range(source + 1):
self.memory[self.registers['index'] + counter] = \
self.registers['v'][counter] def read_regs_from_memory(self):
source = (self.operand & 0x0F00) >> 8
for counter in range(source + 1):
self.registers['v'][counter] = \
self.memory[self.registers['index'] + counter] def store_regs_in_rpl(self):
source = (self.operand & 0x0F00) >> 8
for counter in range(source + 1):
self.registers['rpl'][counter] = self.registers['v'][counter] def read_regs_from_rpl(self):
source = (self.operand & 0x0F00) >> 8
for counter in range(source + 1):
self.registers['v'][counter] = self.registers['rpl'][counter] def reset(self):
self.registers['v'] = [0] * NUM_REGISTERS
self.registers['pc'] = PROGRAM_COUNTER_START
self.registers['sp'] = STACK_POINTER_START
self.registers['index'] = 0
self.registers['rpl'] = [0] * NUM_REGISTERS
self.timers['delay'] = 0
self.timers['sound'] = 0 def load_rom(self, filename, offset=PROGRAM_COUNTER_START):
rom_data = open(filename, 'rb').read()
for index, val in enumerate(rom_data):
self.memory[offset + index] = val def decrement_timers(self):
if self.timers['delay'] != 0:
self.timers['delay'] -= 1 if self.timers['sound'] != 0:
self.timers['delay'] -= 1
CHIP8模拟器的python3实现-3-指令实现的更多相关文章
- chip8模拟器的python3实现-1-CHIP8简介
打算编写一个NES模拟器,先从简单的chip8模拟器入手 1.CHIP-8简介 CHIP-8是一个解释型语言,由Joseph Weisbecker开发.最初CHIP-8在上个世纪70年代被使用在COS ...
- chip8模拟器的python3实现-2-指令介绍
CHIP指令表 CHIP-8有35个指令,都为两字节长,以大端方式存储.指令表的指令格式规定如下: NNN:地址 NN:8位常量 N:4位常量 V:寄存器 X和Y:4位,标识寄存器 PC:程序计数器 ...
- QEMU模拟器Windows版本模拟ARMX86CPU指令
http://qemu.weilnetz.de/ QEMU Binaries for Windows
- Python3执行top指令
import subprocess top_info = subprocess.Popen(["], stdout=subprocess.PIPE) out, err = top_info. ...
- C++版 Chip8游戏模拟器
很早就想写个FC模拟器,但真是一件艰难的事情.. 所以先写个Chip8模拟器,日后再继续研究FC模拟器. Chip8只有35条指令,属于RISC指令集,4k内存,2k显存,16个寄存器(其中15个通用 ...
- 如何实现模拟器(CHIP-8 interpreter) 绝佳杰作.
转自 http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/ How to write an ...
- CS:APP2e Y86处理器模拟器∗指南
CS:APP2e Y86处理器模拟器∗指南 Randal E.Bryant David R. O'Hallaron 2013年7月29日 本文档描述了处理器模拟器,伴随的表示在第4章Y86处理器架构的 ...
- Appium+python自动化19-iOS模拟器(iOS Simulator)安装自家APP
前言 做过iOS上app测试的小伙伴应该都知道,普通用户安装app都是从appstore下载安装,安装测试版本的app,一般就是开发给的二维码扫码安装, 或者开发给个.ipa的安装包文件,通过itoo ...
- Appium+python自动化19-iOS模拟器(iOS Simulator)安装自家APP【转载】
前言 做过iOS上app测试的小伙伴应该都知道,普通用户安装app都是从appstore下载安装,安装测试版本的app,一般就是开发给的二维码扫码安装, 或者开发给个.ipa的安装包文件,通过itoo ...
随机推荐
- 74HC245引脚定义 使用方法
典型的CMOS型三态缓冲门电路,八路信号收发器. 由于单片机或CPU的数据/地址/控制总线端口都有一定的负载能力,如果负载超过其负载能力,一般应加驱动器. 主要应用于大屏显示 引脚定义 DIR:方向控 ...
- 仓库管理移动应用解决方案——C#开发的移动应用开源解决方案
产品简介 SmoWMS是一款仓库管理移动解决方案,通过Smobiler平台开发,包含了仓库管理中基础的入库.出库.订单管理.调拨.盘点.报表等功能.支持扫码条码扫描.RFID扫描等仓库中常见的场景. ...
- django内容回顾:
Django 下载安装 命令行 pip install django==1.11.26 -i 源 pycharm 创建项目 命令行 django-admin startproject 项目名 pych ...
- boostrap --- 弹窗modal的使用
<input id="btntext" type="button" value="添加文本组件" data-toggle=" ...
- linux字体,bashrc的问题的解决
0.查看文件 :set ff #查看文件类型 这里是fileformat=unix :set ff=dos 设置为dos模式, 也可以用 sed -i 's/$/\r/' :set ff=unix 设 ...
- Mondb
1. MongoDB简介 • MongoDB是为快速开发互联网Web应用而设计的数据库系统.• MongoDB的设计目标是极简.灵活.作为Web应用栈的一部分.• MongoDB的数据模型是面向文档的 ...
- Manthan, Codefest 18 (rated, Div. 1 + Div. 2) F 单调栈 + 贡献 + 计数
https://codeforces.com/contest/1037/problem/F 题意 function z(array a, integer k): if length(a) < k ...
- H5视频、音频不能自动播放,Uncaught (in promise) DOMException: play() failed because the user didn't
错误原因:Chrome的autoplay政策在2018年4月做了更改. 解决办法: 第一步,在chrome浏览器中输入:chrome://flags/#autoplay-policy 第二步,在Aut ...
- AGC037C Numbers on a Circle(神奇思路)
Atcoder 全是神仙题-- 先变成能不能从 \(b\) 到 \(a\).操作变成一个数减掉旁边两个数. 考虑里面最大的且不和 \(a\) 中相等的那个数.它两边的数此时都不能操作,否则就减到非正数 ...
- 【目录】洛谷|CODEVS题解汇总
[动规]爱与愁的心痛 [动规]编辑距离 [动规]采药 [动规]创意吃鱼法 [动规]过河卒 [动规]开心的金明 [动规]旅行 [动规]骑士游历 [动规]数字三角形 [动规]最长连号 [动规]装箱问题 [ ...