繁体   English   中英

ZX Spectrum 中的 POKE

[英]POKE in ZX Spectrum

我正在使用旧的 ZX Spectrum 48k,我想知道如何输入POKE 代码

您用磁带加载游戏 - 然后以某种方式打破 POKE 语句中的程序类型并再次开始运行程序?

我已经对此进行了大量搜索,但无法准确找到这是如何完成的,因此我们将不胜感激。

先说一下PEEK和POKE的含义:

10 let x = PEEK 40000: REM returns (reads) the value (0-255) in position 40000
20 POKE 40000, 201: REM writes the 201 value in position 40000

大多数程序加载了一个名为 loader 的小型 BASIC 程序。 它是这样的:

10 cls
20 print "Loading AWESOME GAME!!!"
20 load "" screen$
30 load "" code 40000
40 randomize usr 40000

意思应该很简单:加载一个屏幕演示(第 20 行)以让用户在汇编程序(游戏本身)加载(第 30 行)时保持娱乐,最后启动游戏(第 40 行)。

关于第 40 行, usr 40000是执行此操作的表达式,在位置 40000 处调用程序集。指令Randomize只是初始化rnd使用的随机种子,认为它实际上永远不会返回。

因此,第一次尝试将是:

  1. 按“break”(或多或少相当于 Ctrl+C),输入list ,然后将 pokes 放在第 35 行,即一旦程序已加载但尚未执行。

  2. 不要输入load ""来启动游戏,而是输入merge "" (这用于将内存中的基本程序与磁带中的程序结合起来)。 该过程将在执行加载程序之前停止。 当加载程序包含禁用 BREAK 的poke指令时,这很有用。

这些方法的问题在于,起初隐藏加载器内部的尝试是幼稚的(例如在第 10 行包含 PAPER 0: INK 0 指令或类似的东西,使所有内容暂时不可见),但很快他们就会得到一个复杂得多,直到真正成为REM指令中包含的汇编程序为止。

下一步是分析在基本加载器之后加载的汇编代码的头文件,得出转储地址和代码长度,并创建您自己的加载器,您可以在其中包含您想要的poke指令。 许多杂志分发了这种装载机,旨在在原始装载机之前装载(装载机寻找特定的块,绕过原始基本装载机)。

因此,开发人员决定将组装块包含在没有标题的磁带中,并保护加载程序。 或者包括一个加载器,它只加载一个汇编程序来替代 ROM 中的加载器,使用不同的速度,没有头信息等。或者包括一个加载器,它加载一个无头块,包括演示屏幕和游戏代码。

然后出现了像Multiface-1这样的特殊硬件。 阅读Multiface-1 手册,您可以看到如何通过按下红色按钮(引发 NMI(非屏蔽中断))调用 multiface 的软件(包含在外围硬件的 ROM 中),此时会显示一个菜单,允许您保存内存(并且保存的代码将不受任何保护,从而打开路径以创建您自己的 pokes 加载程序),或者甚至检查( PEEK )内存中特定地址的当前值并直接输入POKE的(通过它您可以找到例如,这些惯例的开始,会减少你的生活)。

POKE 的指令通常是这样的(这是一个简化): POKE addr, 0POKE addr, 201 数字地址是减少可用生命数量或检测与敌人冲突的例行程序的开始。

代码 0 是汇编 NOP(无操作)指令。 在 NOP 期间,CPU 什么也不做。

代码201或C9是汇编RET (返回)指令,表示为子程序返回。 在 BASIC 中,您可以使用GOSUB调用子程序并使用RETURN从它的末尾RETURN 在汇编中,同一对是 CALL/RET。

如果你有一个 201,那么它实际上意味着一个子程序(比如在你的生活中减去一个),例如:

9950 let lives = lives - 1
9960 return

被转化为:

9950 return
9960 return

如果您有一个 0 值,则相同的例程将转换为:

9950
9960 return

ZX Spectrum 杂志中印刷的 POKE 代码通常希望您拥有一个插入式硬件设备(例如 Multiface)。 游戏加载后,您可以按 Multiface 按钮停止游戏,输入 POKE,然后返回游戏。

没有特殊设备,您需要使用加载程序,如其他答案所述。 您需要加载初始的小加载程序,然后 BREAK 进入代码。 如果幸运的话,代码会在游戏的其余部分加载一些简单的东西,然后使用 RANDOMIZE USR 调用执行实际的机器代码游戏。 在这种情况下,您可以修改加载程序 BASIC 程序以在游戏加载之后但游戏开始之前执行 POKES。

然而,许多游戏让这变得困难,因为它们包含自定义加载器代码。 这通常是用机器代码编写的,嵌入到 REM 语句中的小型 BASIC 程序中。 机器代码将加载游戏并执行它,因为它们永远不会将控制权返回给 BASIC 代码,所以没有机会进入 POKE。 如果您足够专注,您可以尝试修改机器代码以将控制权返回给 BASIC,以便您可以 POKE,或者通过机器代码调用执行 POKE。 这很难,因为如果我没记错的话,编辑器曾经在 REM 语句中打乱包含不可打印字符的行。 有像 RoyBot 这样的软件工具可以帮助你修改内存中的代码。

一些游戏开发者做了非常疯狂的事情来防止游戏黑客攻击,例如实现加载器代码,在执行时实际上覆盖了自己的代码

大多数 Spectrum 程序使用两步过程来开始游戏:

  1. 加载并运行一个小的 BASIC 程序
  2. 然后那个小的 BASIC 程序加载更长的机器代码,然后跳转到机器代码的入口点(例如RANDOMIZE USR 28455 )。

如果你能管理这些步骤之间停下来,你可以POKE左右(以提高人的生命,......数),然后启动机器代码RANDOMIZE USR 28455 ,假设你以某种方式找到了正确的地址。

一旦机器程序正在运行,通常无法停止它并返回到 BASIC 解释器。 除非机器程序提供了一些明确的(或无意的)方式来这样做。

我记得很久以前......当一个 Spectrum 游戏加载时,它最初加载一个小的加载程序,然后运行它,磁带继续并加载程序的大部分。加载器中的最后一个命令然后程序发出一个 poke 命令,该命令调用加载的所有内容并开始游戏。 所以,正如我所记得的,一旦加载程序加载完毕,您必须暂停磁带,并停止代码行自动发出最后的 poke,然后继续。 然后,一旦批量加载完毕,您就可以从命令行发出 poke,然后使用原始 poke 开始游戏。 加载程序将在第一组红线和蓝线之后加载,然后是屏幕上非常短的黄线和蓝线(我记得它打印了此时找到的程序的名称)。 停止磁带,按 Break,然后按 List 查看代码。 祝你好运,好问题!

作为找到正确 poke 的解决方法,在加载和 BREAK 程序后,您可以搜索如下命令:

LD A,3

在开始时有 3 条生命的游戏中。 此命令的十六进制代码是:

3E 03 -> in hex
62 3  -> in decimal

例如,搜索此数据并将 03 更改为 255(255 是最大允许值)。 然后测试一下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM