gpt4 book ai didi

c - 硬件仿真的正确实现是什么?

转载 作者:行者123 更新时间:2023-12-03 17:05:15 28 4
gpt4 key购买 nike

我要编程 Game Boy模拟器(Z80 是 CPU,以防有人不熟悉它),在我进行研究时,我发现了一些我不太确定的事情。

第一个是 C 是这里选择的编程语言。这不是什么大问题,但我想从今天的角度听听你的意见。甚至不推荐使用 C++。

我发现的第二件事是每个人都在每个操作码中使用一个函数。这似乎是合乎逻辑的,因为它只是一个函数调用,并且可能比为“ADD”指令使用一个函数更好地优化,然后您必须找出此处使用的寄存器。但今天这有多大必要?如果我注意到另一种可能更方便的方法并没有削减它(现在或多或少现代游戏机出现在我的脑海中),我应该坚持还是应该重写我的模拟器?

此外,一遍又一遍地编写“将该寄存器添加到该寄存器”的函数有点令人沮丧。有没有办法从操作码映射或类似的东西中自动化?

最佳答案

我主要同意 WingsOfIcarus。我已经写了一些模拟器,所以这是我的见解:

  • 使用函数指针是个好主意 (为了代码的速度和清晰度)
  • OOP 不是问题

    是的,成员调用会慢一点,但是如果您小心一点,它不会对性能产生太大影响。另一方面,OOP 仿真代码更易于管理/阅读/理解。
  • 使用指令数据库代替固定指令解码。

    我正在使用一个文本文件,其中包含所有指令的所有必要信息。模拟器在初始化期间解析它(提供函数指针和操作数的数组......)。在这种架构中,无需任何代码更改即可轻松纠正指令集中的错误。

    复杂的指令集文档在某些方面几乎总是有问题的。最坏的情况是 Z80 (我从未见过 100% 无错误的指令集)。所以使用更多的指令集,比较它们并创建一个无错误的集(如果可以的话)。
  • 将声音、视频、键盘和鼠标添加到您的仿真中

    这通常不是问题。上 视窗 使用 WaveOut 而不是 DirectSound .它更稳定、更快(DSound 的可用延迟有时甚至 > 400 毫秒)。使用 WaveOut,我能够将延迟降低到 20-80 毫秒,这很好。
  • 以每秒模拟 CPU 的 T 个周期应用限制速度

    我正在使用机器周期正确计时,这要慢得多,但允许我正确实现任何硬件外围仿真(FDC、DMAC、声音芯片,...没有任何黑客)
  • 为模拟平台应用加载/保存文件

  • 例如,这是我的指令集的一部分(直接提供给 CPU 仿真:
    opc      T0 T1 MC1   MC2   MC3   MC4   MC5   MC6   MC7   mnemonic

    B8 04 00 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 ... 0 CP A,B
    B9 04 00 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 ... 0 CP A,C
    BA 04 00 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 ... 0 CP A,D
    BB 04 00 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 ... 0 CP A,E
    BC 04 00 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 ... 0 CP A,H
    BD 04 00 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 ... 0 CP A,L
    BE 07 00 M1R 4 MRD 3 ... 0 ... 0 ... 0 ... 0 ... 0 CP A,(HL)
    BF 04 00 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 ... 0 CP A,A
    C0 11 05 M1R 5 MRD 3 MRD 3 ... 0 ... 0 ... 0 ... 0 RET NZ
    C1 10 00 M1R 4 MRD 3 MRD 3 ... 0 ... 0 ... 0 ... 0 POP BC
    C2L2H2 10 10 M1R 4 MRD 3 MRD 3 ... 0 ... 0 ... 0 ... 0 JP NZ,U16
    C3L1H1 10 00 M1R 4 MRD 3 MRD 3 ... 0 ... 0 ... 0 ... 0 JP U16
    C4L2H2 17 10 M1R 4 MRD 3 MRD 4 MWR 3 MWR 3 ... 0 ... 0 CALL NZ,U16
    C5 11 00 M1R 5 MWR 3 MWR 3 ... 0 ... 0 ... 0 ... 0 PUSH BC
    C6U2 07 00 M1R 4 MRD 3 ... 0 ... 0 ... 0 ... 0 ... 0 ADD A,U8
    C7 11 00 M1R 5 MWR 3 MWR 3 ... 0 ... 0 ... 0 ... 0 RST 00H
    C8 11 05 M1R 5 MRD 3 MRD 3 ... 0 ... 0 ... 0 ... 0 RET Z
    C9 10 00 M1R 4 MRD 3 MRD 3 ... 0 ... 0 ... 0 ... 0 RET
    CAL2H2 10 10 M1R 4 MRD 3 MRD 3 ... 0 ... 0 ... 0 ... 0 JP Z,U16

    opc: operation code [hex]
    L1,H1,U1,S1 means first operand direct number or address
    L2,H2,U2,S2 means second operand direct number or address
    L3,H3,U3,S3 means third operand direct number or address
    H,L ... U16 high and low byte
    U ... U8 unsigned byte
    S ... S8 signed byte

    T0 normal instruction duration [T] always 2 decimal digits
    T1 instruction duration if condition not met [T] always 2 decimal digits

    MC1++ Machine cycle first is type,second is duration [T] always 1 decimal digit
    ... unused
    M1R M1 cycle
    MRD memory read
    MWR memory write
    IOR IO read
    IOW IO write
    NON no external operation (internal computation)
    INT interrupt cycle

    mnem instruction text (mnemonic)
  • opc用于指针数组中的地址
  • mnemonic用于选择合适的函数指针,操作数类型
  • T0T1用于指令计时(这对于粗略的仿真来说已经足够了)
  • MC1++用于正确的 MC 计时(以实现正确的硬件仿真和争用计时)

  • 这是 my Zilog Z80A complete instruction set with machine cycle timing下载链接。随意使用(只需在某处提及我的昵称)。在移植到这个之后,我终于能够 100% 通过 ZEXALL 测试。欲了解更多信息,请参阅 Writing a graphical Z80 emulator in C or C++ .

    关于c - 硬件仿真的正确实现是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15692091/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com