Python3实现CHIP-8模拟器

0x00 前言

CHIP-8最初是以虚拟机的形式被开发出来的,在早期个人电脑上被用于游戏开发。鉴于CHIP-8只有4Mb的内存,16个8-bits寄存器,一个16-bits地址寄存器,和35条操作码,制作一个CHIP-8模拟器非常适合初学者了解计算机的大致工作方式.

本文章使用python3来实现CHIP-8模拟器.

0x01 内存

CHIP-8有4096(0x1000)个内存空间(就是4兆内存), 每一个位置都能存储一个字节, 也就是8-bits(这就是CHIP-8名字的由来).

  • 前512个字节0x000 ~ 0x1ff原本是用于存储CHIP-8解释器的, 现在通常用于存储字体
  • 0x200开始(包括0x200)往后的空间被用于存储CHIP-8的游戏(ROM)

这里要注意的是CHIP-8的操作码是两个字节的, 所以把ROM写到内存时一个操作码是被存储在连续的两个内存单元上的, 然后在读取时连续读两个字节并拼接成一个操作码.

创建内存

#创建内存
self.Memory = []
for i in range(0, 4096):
    self.Memory.append(0x0)

#创建字体并把它存储于0x000~0x050
fonts = [ 
    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 in range(len(fonts)):
    self.Memory[i] = fonts[i]

#创建一个程序指针用于指向当前操作码
self.ProgramCounter = 0x200

读取ROM并写入内存

#写入(这两个方法名字写错了)
def readProg(self, filename):
    rom = self.convertProg(filename)
        
    offset = int('0x200', 16)
    for i in rom:
        self.Memory[offset] = i
        offset += 1

#读取    
def convertProg(self, filename):
    rom = []

    with open(filename, 'rb') as f:
        wholeProgram = f.read()

        for i in wholeProgram:
            byte = i
            rom.append(byte)

运行

#从内存读取操作码并运行
def execution(self):
    index = self.ProgramCounter
    high = self.hexHandler(self.Memory[index])
    low = self.hexHandler(self.Memory[index + 1])

    opcode = high + low

    self.execOpcode(opcode)

#补全操作码
def hexHandler(self, Num):
    newHex = hex(Num)[2:]
    if len(newHex) == 1:
        newHex = '0' + newHex
        
    return newHex

0x02 寄存器

CHIP-8有16个8-bits寄存器和一个16-bits地址寄存器.

  • 16个寄存器被命名为V0~VF, 其中VF通常被当做是一个状态标志寄存器, 用于表示是否有进位或者用于碰撞检测
  • 地址寄存器通常被用于指向某个图像的位置

当寄存器存储的数字大于它的存储空间时会舍弃掉高位, 记得实现这个机制

寄存器类

class Register:
    def __init__(self, bits):
        self.value = 0
        self.bits = bits

    #检查是否有进位
    def checkCarry(self):
        hexValue = hex(self.value)[2:]

        if len(hexValue) > self.bits / 4:
            self.value = int(hexValue[-int(self.bits / 4):], 16)
            return 1
        
        return 0
    
    #检查是否小于0
    def checkBorrow(self):
        if self.value < 0:
            self.value = abs(self.value)
            return 0
        
        return 1
    
    def readValue(self):
        return hex(self.value)
    
    def setValue(self, value):
        self.value = value

创建寄存器实例

self.Registers = []
for i in range(16):
    self.Registers.append(Register(8))
        
self.IRegister = Register(16)

0x03 栈

这里栈是用于存储函数的返回地址

栈类

class Stack:
    def __init__(self):
        self.stack = []
    
    def push(self, value):
        self.stack.append(value)
    
    def pop(self):
        return self
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值