问题标签 [gameboy]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
cpu - Gameboy 仿真 - CD 说明需要说明
我目前正在编写 Gameboy 模拟器,我注意到一些对我来说似乎很奇怪的东西。
0xCD
例如,我的模拟器正在执行跳转指令,CD B6 FF
但我的理解是跳转应该只跳转到盒式 ROM 内的地址(0x7FFF
最大值),因为我假设 CPU 只能执行来自 ROM 的指令,而不是 RAM。有问题的 ROM 是 Mario 博士,我希望它只会执行有效的操作。0xFFB6
在高 RAM 中,这对我来说似乎很奇怪。
我的想法正确吗?如果我是,大概这意味着我的程序计数器以某种方式以错误的地址结束,并且CB
实际上是另一条指令数据的一部分,而不是指令本身?
我将不胜感激,谢谢。
作为参考,我一直在使用Gameboy Opcodes和CPU 文档来实现指令。我知道它们包含一些错误,我想我已经解释了它们(例如,0xE2 被列为两字节指令,而它只有一个)
emulation - GBZ80 - ADC 指令未通过测试
我一直在通过我的 Gameboy 模拟器运行Blarggs CPU 测试,并且op r,r测试显示我的 ADC 指令无法正常工作,但 ADD 是。我的理解是,两者之间的唯一区别是在添加之前将现有的进位标志添加到第二个操作数。因此,我的 ADC 代码如下:
我在测试ROM中输入了以下内容:
当设置进位标志时, A 的值为0 (Flags = B0),否则为FF (Flags = 00)。就我的理解而言,这就是它应该如何工作的方式。但是,它仍然无法通过测试。
根据我的研究,我相信标志的影响方式与 ADD 相同。从字面上看,我的代码与工作 ADD 指令的唯一变化是在前两行中添加了标志检查/潜在增量,我的测试代码似乎证明了这一点。
我错过了什么吗?也许 ADD/ADC 之间的标志状态有一个特殊性?附带说明一下,SUB 指令也通过了,但 SBC 以同样的方式失败。
谢谢
if-statement - gbz80 - IF 语句
我正在 VisualboyAdvance 上的 Z80 中进行一些编码,但我不知道如何执行任何类型的 IF 语句。
我编写了一个脚本来增加屏幕上从 0xC3A0 开始的每个图块的值。屏幕数据在 0xC507 结束。
我的代码如下:
如您所见,它不断循环并最终通过增加核心功能使游戏崩溃。我想要一种方法来让它在 HL 达到 0xC507 时使用 0xC9(Ret)。
任何帮助将非常感激。
如果你能向我解释你提供的陈述是如何工作的,那就太好了。机器代码对我来说是陌生的。
machine-code - GBZ80——代码缺点
我有一个循环 0x167 次的代码,写入屏幕。我想要发生的是脚本循环三次。
我的脚本:
现在,它没有停止它应该停止的地方,而是继续破坏内存,直到它达到 d325 并导致脚本崩溃。正如您可能知道的那样,我尝试使用 DE 作为循环计数器。
请解释您的答案,我对此仍然很无聊。
python - Python在VisualBoyAdvance中读取口袋妖怪的内存地址
首先,我对使用 Python 的更多“低级”事物不熟悉,所以如果这是一个菜鸟问题,请原谅。
我有一个类似于 Xbox 和 Playstation 的“成就”系统的想法,您可以使用 Python 通过读取内存地址来跟踪 Gameboy 模拟器中的某些内容。
我决定我应该用口袋妖怪试试这个。(叶绿开始)
我的第一个想法是像这样取得一些成就:
所以在谷歌搜索了一些内存地址之后,我最终来到了这里。
它在文章中说,在叶绿中,训练师的派对数据从 0x02024284 开始,每个口袋妖怪的个人数据是 100 字节。正确的。
所以我进入 VisualBoyAdvance(我的模拟器)并点击
现在我在搜索框中输入 02024284,它会将我带到数据。
文章说,从那行开始,偏移量超过 8 位,接下来的 10 个字节是口袋妖怪的昵称。
如果我从我的模拟器中读取这个(在 8 位模式下),我会读取接下来的 10 组 8 位,我得到:
应该是 Ivysaur(我假设这是十六进制的,所以我用谷歌搜索了一个十六进制到字符串转换器并输入了这个,但它带回了一堆乱码(下))
现在,我的两个问题。
我将如何将这些内存地址从 VBA 拉到 Python?(我在 Windows 7 上使用 Python 2.7)
我将如何解码/解密返回为“人类可读格式”的字符串?- 感谢@blubberdiblub 清除这部分
关于 VBA 和 Python 一起工作,我找不到太多信息来指导我,并希望有人可以帮助我了解这一点。我想进入内存地址(出于这样的原因),我认为这将是一个很酷的小项目。
assembly - 优化 GameBoy Z80 中的位操作算法
这不是作业问题,而是针对我正在开发的游戏。
我有两个 16 位 RGB 颜色,并且想根据其他六个四位数量来改变它们的六个通道。算法简单但繁琐;我正在寻找一种通过一次做更多有用的工作来优化它的方法。
高级概述:
hl
指向四个颜色字节。[hl] = %gggrrrrr
,[hl+1] = %0bbbbbgg
,[hl+2] = %GGGRRRRR
和[hl+3] = %0BBBBBGG
. (这是两种颜色,rgb
和RGB
。)bc
指向三个增量字节。[bc] = %hhhhaaaa
,[bc+1] = %ddddssss
, 和[bc+2] = %ppppqqqq
. (这是六个 delta 值,h
、a
、d
、s
、p
、 和q
。)- 所以有六个 5 位颜色通道值和六个 4 位增量值。我想将每个颜色通道C与增量值D配对,并像这样改变C : C' = C + ( D & %11) - (( D & %1100) >> 2),但将C保持在其 5 内位界限 [0, 31]。我实际上并不关心它们是如何配对的:任何方便的一对一配对都可以。如果C + (( D & %1100) >> 2) - ( D & %11) 以某种方式允许更优雅的算法,我会同意的。
如果我在 register 中隔离一个颜色通道C和在register 中d
的一个增量值De
,那么这个例程将为该对执行变化:
到目前为止,我有一个通用例程,可以将任何 DV 应用于任何颜色通道;然后是三个隔离红色、绿色或蓝色通道并将给定 DV 应用于它们的例程;最后是一个主程序,它挑选出六个 DV 并与它们一起调用适当的通道修改程序。这“足够好”,但我敢肯定还有改进的余地。执行速度似乎不是问题,但我想减少代码大小(当然删除冗余指令也会提高一点速度)。是否有任何帮助的 asm 位操作技巧?
这是完整的代码:
c - 确定 Gameboy GB 仿真的中断例程何时结束
因此,对于上下文,我想让您知道我到目前为止所了解的内容:
指令执行后调用中断处理并设置中断主机使能标志。
中断处理由多个“中断例程”组成(对于gameboy,它有Vblank、LCD stat、计时器、手柄和串行)。
CPU 需要根据 IE 标志和 IF 标志上设置的值来处理每个中断。
中断例程具有优先级(与我的问题并不真正相关)。
中断例程必须有开始和结束
因此,查看中断例程,它首先将在例程结束后应该保留的寄存器值推入堆栈指针。现在它总是有 reti 指令,我认为它总是一个中断例程的结束,它应该在处理中断之前弹出下一条指令的地址。
我想知道是否:
reti 指令在每个中断例程中只出现一次并且只出现在最后,这是一个“标准”吗?因为这是我可以确定是否会结束阅读进一步说明的唯一方法,
它使用 reti 而不是 ret 因为我们想要断言 ime 标志仍然处于启用状态,因此可以继续检查是否需要提供任何其他中断,
在中断处理开始之前,我需要将下一条指令的地址显式推送到堆栈指针中,因为没有汇编指令指示在中断处理开始之前将其推送。这是为了在中断结束时进行 reti 指令。
编辑:
因此,为了提供有关我的问题的更多背景信息,我决定发布我的指令周期代码。
在 CPU.c 中
在 InteruptHandler.c 中
java - 如何改变执行速度?
我正在用 Java 编写 Nintendo Gameboy 模拟器,但在模拟处理器时遇到了问题。原始时钟频率约为。4.19MHz。这个怎么做?我考虑过放入Thread.sleep(long, int)
,但它不起作用,因为使用它你可以模拟高达 1MHz,但不能模拟 4MHz。有没有类似但更精确的东西?还有其他方法可以降低执行速度吗?
visualization - 从 Gameboy Printer Spoof 重建串行图像数据
任天堂创造了一种与 Gameboy 兼容的打印机。Gameboy 可以通过串行 SPI 链接对其进行打印。我使用 STM32 通过捕获来自 Gameboy 的数据包并欺骗打印机响应来模拟打印机。
来自 Gameboy 的数据自然是字节流。每两位对应一个像素(为每个像素提供 4 种灰度级)。Gameboy 通常打印分辨率为 160 x 144 的图像。这些图像被分成 9 段,每段 16 像素高 (9*16=144)。
然后在每个段中,从上到下,从左到右处理串行像素数据。
现在,我的问题是,当我使用 Java 应用程序处理数据时,它并没有按应有的方式显示。
我不确定问题是什么,我已经研究了很长时间。您可以看到第一张照片看起来几乎就像实际照片的两个并排版本。有谁知道像素数据的格式是否与我所知道的不同,或者它只是我的代码中的一个错误?
这是我用来转换数据的代码:
这是我用来创建图像的数据(在项目文件夹中保存为“gbinput.txt”):
assembly - 将寄存器加载到自身的指令的目的是什么?
在浏览 Gameboy 的指令集时,我遇到了如下指令:
这些指令中的每一个在此表中都有自己的操作码,这使我认为由于可能的操作码数量的限制,它们具有一定的重要性。
我首先认为它可能会取消引用该寄存器中的指针并将值存储在该指针处(就像在这个问题中一样),但在模拟器中,LD A, A
实现为:
它们似乎对处理器的状态没有影响(只需将寄存器设置为它们自己的值),并且NOP
执行的周期数与 a 相同。
为什么这些操作码包含在指令集中,它们的用途是什么?