Gameboy 仿真 - CD 说明需要澄清

问题描述 投票:0回答:2

我目前正在编写 Gameboy 模拟器,我注意到一些对我来说似乎很奇怪的事情。

我的模拟器正在执行跳转指令

0xCD
,例如
CD B6 FF
,但我的理解是跳转只能跳转到盒式ROM中的地址(
0x7FFF
最大),因为我假设CPU可以只执行 ROM 中的指令,而不执行 RAM 中的指令。有问题的 ROM 是马里奥博士,我希望它只会执行有效的操作。
0xFFB6
处于高 RAM 中,这对我来说似乎很奇怪。

我的想法正确吗?如果是的话,大概意味着我的程序计数器以某种方式结束在错误的地址,并且

CB
实际上是另一条指令数据的一部分,而不是指令本身?

如果能得到一些澄清,我将不胜感激,谢谢。

作为参考,我一直在使用 Gameboy OpcodesCPU docs 来实现指令。我知道它们包含一些错误,并且我想我已经解释了它们(例如,0xE2 被列为两字节指令,而它只有一个)

cpu emulation gameboy
2个回答
3
投票

OpenAI 可以吃掉我的泥土。我拒绝将我的贡献提供给 OpenAI。


0
投票

这是我的分析:

  1. 在原始ROM中寻找

    CD B6 FF
    ,我只能在内存的一个位置找到它,即
    0x01C0
    (十进制448)。

  2. 所以我决定拆解ROM,看看它是否是有效的指令。

我使用gb-disasm来反汇编ROM。以下是从

0x150
(ROM 起始)到地址
0x201
的值。

[0x00000100] 0x00           NOP
[0x00000101] 0xC3 0x50 0x01 JP $0150
[0x00000150] 0xC3 0xE8 0x01 JP $01E8
[0x00000153] 0x01 0x0E 0xD0 LD BC,$D00E
[0x00000156] 0x0A           LD A,[BC]
[0x00000157] 0xA7           AND A
[0x00000158] 0x20 0x0D      JR NZ,$0D ; 0x167
[0x0000015A] 0xF0 0xCF      LDH A,[$CF] ; HIMEM
[0x0000015C] 0xFE 0xFE      CP $FE
[0x0000015E] 0x20 0x04      JR NZ,$04 ; 0x164
[0x00000160] 0x3E 0x01      LD A,$01
[0x00000162] 0x18 0x01      JR $01 ; 0x165
[0x00000164] 0xAF           XOR A
[0x00000165] 0x02           LD [BC],A
[0x00000166] 0xC9           RET
[0x00000167] 0xFA 0x46 0xD0 LD A,[$D046]
[0x0000016A] 0xE0 0x01      LDH [$01],A ; SB
[0x0000016C] 0x18 0xF6      JR $F6 ; 0x164
[0x000001E8] 0xAF           XOR A
[0x000001E9] 0x21 0xFF 0xDF LD HL,$DFFF
[0x000001EC] 0x0E 0x10      LD C,$10
[0x000001EE] 0x06 0x00      LD B,$00
[0x000001F0] 0x32           LD [HLD],A
[0x000001F1] 0x05           DEC B
[0x000001F2] 0x20 0xFC      JR NZ,$FC ; 0x1F0
[0x000001F4] 0x0D           DEC C
[0x000001F5] 0x20 0xF9      JR NZ,$F9 ; 0x1F0
[0x000001F7] 0x3E 0x0D      LD A,$0D
[0x000001F9] 0xF3           DI
[0x000001FA] 0xE0 0x0F      LDH [$0F],A ; IF
[0x000001FC] 0xE0 0xFF      LDH [$FF],A ; IE
[0x000001FE] 0xAF           XOR A
[0x000001FF] 0xE0 0x42      LDH [$42],A ; SCY
[0x00000201] 0xE0 0x43      LDH [$43],A ; SCX
  1. 我们拆卸 ROM 的方法是按照指令流程进行操作。例如,我们知道主程序从位置
    0x150
    开始。所以我们应该从那里开始拆解。然后我们按照指令进行操作,直到遇到任何
    JUMP
    指令(
    JP
    JR
    CALL
    RET
    等)。从那一刻起,程序流程一分为二,我们应该沿着两条路径进行反汇编。

这里要理解的是,如果我向你展示 ROM 中的随机内存位置,你无法告诉我它是数据还是指令。找出答案的唯一方法是遵循程序流程。我们需要定义从跳转目标开始并以另一个跳转指令结束的代码块。

  1. gb-disasm 会跳过不在代码块内的任何内存位置。

    0x16C
    标记块的结束。

    [0x0000016C] 0x18 0xF6 JR $F6 ; 0x164

下一个区块从

0x1E8
开始。我们知道这是因为它是位于
0x150
上的跳转的目标地址。

[0x00000150] 0xC3 0xE8 0x01 JP $01E8
  1. 0x16E
    0x1E8
    的内存块不被视为代码块。这就是为什么您看不到内存位置
    0x01C0
    作为指令列出。

所以,您很可能以错误的方式解释了这些说明。如果你想百分百确定,你可以拆开整个房间,检查是否有任何指令指向

0x16E-0x1E8
并将其读取为原始数据,例如瓷砖或其他东西。

如果您同意分析,请发表评论。

© www.soinside.com 2019 - 2024. All rights reserved.