【GameBoy模拟器 2】CPU、总线和游戏卡带

先把游戏读进来随便执行一下再说

目标:

  • 了解GameBoy的大致硬件组成和模拟器代码结构
  • 模拟游戏卡带和基本功能与结构,加载gb游戏文件,进行初步的解析校验
  • 了解CPU的工作流程,实现基础的CPU指令、CPU寻址模式
  • 实现CPU的基本工作流程,实现指令的读取、分析与执行:取opcode并解析为指令、按指令对应的寻址方式读取所需数据、运行该指令

涉及到的概念:

  • 卡带:cartridge
  • 总线:bus
  • 内存:memory
  • 内存映射:memory map
  • 中央处理器:CPU (Central Processing Unit)
  • 指令:instruction
  • 寻址模式:addressing mode
  • 操作码: opcode
  • 寄存器:register

知识点

  • 关于CPU状态

    • halted(挂起态)
      • halted ≠ 指游戏暂停,而是通过HALT指令设置的一种状态。相反,游戏暂停的时候,CPU是在一直运行的,没有进入halt状态(经过调试得出结论)
      • 有些操作会需要用到这种指令。比如需要CPU可能需要等待某个外部事件(如硬件中断)发生。在这种情况下,HALT指令可以使CPU进入低功耗状态,直到中断发生。
      • Depending on how much CPU time is required by a game, the HALT instruction can extend battery life anywhere from 5% to 50% or possibly more. - Pan Docs
    • running和paused
      • CPU其实不需要running和paused状态,这两个状态都没有实际用上。LLD的paused状态实际上就是关机
  • 各种寻址模式(从指令集归纳而出的,是否有硬件基础呢?有的,这个基础就是译码器和操作码表)

    • 在CPU设计中,指令译码器是CPU的一部分,能将存储在指令寄存器或微程序指令中的比特转换为能控制CPU其他部分的控制信号 – wikipedia
  • 我们的实现CPU和实际CPU做的事情的区别

    • 我们的实现:一个C程序,三个函数取指、译码、执行
    • 实际硬件层面发生的事情(宏观上都是数字电路的或且非门)
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    以GameBoy的LD A, (HL)指令为例,展示CPU如何处理这条指令:
    
    取指:
    
    PC指向LD A, (HL)指令的内存地址。
    内存接口读取指令,并将其存储在IR中。
    
    译码:
    
    指令译码器解析LD A, (HL)指令。
    操作码确定这是一个加载指令。
    译码器识别出这是间接寻址模式,操作数在HL寄存器指向的内存地址中。
    
    操作码提取:指令译码器从IR中提取操作码。例如,LD A, (HL)的操作码可能是0x7E。
    查找操作码表:指令译码器查找操作码表,确定0x7E对应的指令类型是LD,并且使用间接寻址模式。
    生成控制信号:指令译码器生成控制信号,指示CPU使用HL寄存器的值作为内存地址。
    
    执行:
    
    AGU计算HL寄存器的值,得到内存地址。
    内存接口从该地址读取数据。
    数据通过数据总线传送到寄存器A。
    
  • 关于周期

    • 时钟周期(时钟频率的倒数,系统中最原子的时间单位)
    • 机器周期(由多个时钟周期构成,是CPU完成基础操作花费的时间,一条指令由多个基础操作构成,比如取指、译码、执行)
    • 指令周期(由多个机器周期构成,是某条CPU指令花费的时间)
  • cart write,为什么要对卡带进行写?

    • MBC1类的游戏需要进行特定位置的cart write来切换rom bank(分页机制)
    • gameboy的battery save机制是通过向卡带中的SRAM写入数据,电池给SRAM供电来实现的(掉电后仍然会丢失数据)

测试效果

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
$ gbemu/gbemu ../../roms/dmg-acid2.gb 
Opened: ../../roms/dmg-acid2.gb
Cartridge Loaded:
         Title    : DMG-ACID2
         Type     : 00 (ROM ONLY)
         ROM Size : 32 KB
         RAM Size : 00
         LIC Code : 00 (None)
         ROM Vers : 00
         Checksum : 9F (PASSED)
Cart loaded..
SDL INIT
TTF INIT
Execute Instruction: 00   PC: 0001
Not executing yet
Execute Instruction: 00   PC: 0002
Not executing yet
Execute Instruction: 00   PC: 0003
Not executing yet
Execute Instruction: 00   PC: 0004
Not executing yet
Execute Instruction: 00   PC: 0005
Not executing yet
Execute Instruction: 00   PC: 0006
Not executing yet
Execute Instruction: 00   PC: 0007
Not executing yet
Execute Instruction: 00   PC: 0008
Not executing yet
Execute Instruction: 00   PC: 0009
Not executing yet
Execute Instruction: 00   PC: 000A
Not executing yet
Execute Instruction: 00   PC: 000B
Not executing yet
Execute Instruction: 00   PC: 000C
Not executing yet
Execute Instruction: 00   PC: 000D
Not executing yet
Execute Instruction: 00   PC: 000E
Not executing yet
Execute Instruction: 00   PC: 000F
Not executing yet
Execute Instruction: 00   PC: 0010
Not executing yet
Execute Instruction: 00   PC: 0011
Not executing yet
Execute Instruction: 00   PC: 0012
Not executing yet
Execute Instruction: 00   PC: 0013
Not executing yet
Execute Instruction: 00   PC: 0014
Not executing yet
Execute Instruction: 00   PC: 0015
Not executing yet
Execute Instruction: 00   PC: 0016
Not executing yet
Execute Instruction: 00   PC: 0017
Not executing yet
Execute Instruction: 00   PC: 0018
Not executing yet
Execute Instruction: 00   PC: 0019
Not executing yet
Execute Instruction: 00   PC: 001A
Not executing yet
Execute Instruction: 00   PC: 001B
Not executing yet
Execute Instruction: 00   PC: 001C
Not executing yet
Execute Instruction: 00   PC: 001D
Not executing yet
Execute Instruction: 00   PC: 001E
Not executing yet
Execute Instruction: 00   PC: 001F
Not executing yet
Execute Instruction: 00   PC: 0020
Not executing yet
Execute Instruction: 00   PC: 0021
Not executing yet
Execute Instruction: 00   PC: 0022
Not executing yet
Execute Instruction: 00   PC: 0023
Not executing yet
Execute Instruction: 00   PC: 0024
Not executing yet
Execute Instruction: 00   PC: 0025
Not executing yet
Execute Instruction: 00   PC: 0026
Not executing yet
Execute Instruction: 00   PC: 0027
Not executing yet
Execute Instruction: 00   PC: 0028
Not executing yet
Execute Instruction: 00   PC: 0029
Not executing yet
Execute Instruction: 00   PC: 002A
Not executing yet
Execute Instruction: 00   PC: 002B
Not executing yet
Execute Instruction: 00   PC: 002C
Not executing yet
Execute Instruction: 00   PC: 002D
Not executing yet
Execute Instruction: 00   PC: 002E
Not executing yet
Execute Instruction: 00   PC: 002F
Not executing yet
Execute Instruction: 00   PC: 0030
Not executing yet
Execute Instruction: 00   PC: 0031
Not executing yet
Execute Instruction: 00   PC: 0032
Not executing yet
Execute Instruction: 00   PC: 0033
Not executing yet
Execute Instruction: 00   PC: 0034
Not executing yet
Execute Instruction: 00   PC: 0035
Not executing yet
Execute Instruction: 00   PC: 0036
Not executing yet
Execute Instruction: 00   PC: 0037
Not executing yet
Execute Instruction: 00   PC: 0038
Not executing yet
Execute Instruction: 00   PC: 0039
Not executing yet
Execute Instruction: 00   PC: 003A
Not executing yet
Execute Instruction: 00   PC: 003B
Not executing yet
Execute Instruction: 00   PC: 003C
Not executing yet
Execute Instruction: 00   PC: 003D
Not executing yet
Execute Instruction: 00   PC: 003E
Not executing yet
Execute Instruction: 00   PC: 003F
Not executing yet
Execute Instruction: 00   PC: 0040
Not executing yet
Execute Instruction: 00   PC: 0041
Not executing yet
Execute Instruction: 00   PC: 0042
Not executing yet
Execute Instruction: 00   PC: 0043
Not executing yet
Execute Instruction: 00   PC: 0044
Not executing yet
Execute Instruction: 00   PC: 0045
Not executing yet
Execute Instruction: 00   PC: 0046
Not executing yet
Execute Instruction: 00   PC: 0047
Not executing yet
Execute Instruction: 00   PC: 0048
Not executing yet
Unkown Instruction E9

可以看到:成功加载了游戏的镜像文件,解析出了游戏相关信息,CPU的程序计数器PC在按预期自增。

这证明卡带读取、校验和数据传输功能正常,CPU结构和功能正常。如果手动调整PC从0x100开始,则可以读取到更多的正常指令,比如C3:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
$ gbemu/gbemu ../../roms/dmg-acid2.gb 

Opened: ../../roms/dmg-acid2.gb
Cartridge Loaded:
         Title    : DMG-ACID2
         Type     : 00 (ROM ONLY)
         ROM Size : 32 KB
         RAM Size : 00
         LIC Code : 00 (None)
         ROM Vers : 00
         Checksum : 9F (PASSED)
Cart loaded..
SDL INIT
TTF INIT
Execute Instruction: 00   PC: 0101
Not executing yet
Execute Instruction: C3   PC: 0104
Not executing yet
Unkown Instruction CE
Licensed under CC BY-NC-SA 4.0
最后更新于 Jun 25, 2025 15:02 UTC
Built with Hugo
Jimmy 设计的 Stack 主题