我正在使用一台旧的ZX Spectrum 48k玩耍,想知道如何输入POKE codes。您需要通过磁带加载游戏,然后在某种程度上打破程序,键入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行),以在汇编程序(游戏本身)加载时保持用户的娱乐,最后启动游戏(第40行)。
关于第40行,“usr 40000”是调用地址为40000处的汇编表达式。指令“Randomize”只是初始化随机种子,供“rnd”使用,但它实际上永远不会返回。
因此,首先尝试的方法是:
按下“break”键(相当于Ctrl+C),输入“list”,并将poke放在第35行,即在程序加载后但尚未执行时。
不要键入“load \\"\\"”以启动游戏,而要键入“merge \\"\\"”(这也可以用来将存储器中的基本程序与磁带中的程序合并)。该过程将在执行加载器之前停止。当加载器包含禁用BREAK的poke指令时,这非常有用。
这些方法的问题在于,一开始隐藏加载器内部的尝试是幼稚的(例如,在第10行包括“PAPER 0: INK 0”指令或类似于此的内容,使所有东西暂时消失),但很快就会变得复杂得多,一直到实际上成为包含在REM指令中的汇编程序。
下一步是分析基本加载器之后加载的汇编代码的头文件,确定转储地址和代码长度,并创建自己的加载器,其中可以包含所需的poke指令。许多杂志分发这些类型的加载器,旨在在原始加载器之前加载(加载器查找特定块,绕过原始基本加载器)。
因此,开发人员决定在磁带中不包括汇编块的头信息,以及保护加载器。或包括一个只加载替换ROM中加载器的汇编程序的加载器,使用不同的速度,无头信息等。或包括一个加载头部块的加载器,其中包括演示屏幕和游戏代码。
然后出现了一些特殊的硬件,比如Multiface-1。通过阅读Multiface-1手册,您可以看到如何通过按下红色按钮(触发非屏蔽中断)调用multiface的软件(包含在外围硬件的ROM中),会显示一个菜单,允许您保存此时的内存(并且保存的代码将不受任何保护,因此打开了创建自己的loader并使用poke的路径),甚至检查(PEEK
)指定地址的当前值并直接输入POKE
(通过这种方式,您可以找到那些减少生命的例程的开头,例如,在游戏中失去一条命的程序)。
POKE
指令通常是这样的(这是一种简化形式):POKE addr,0
或POKE addr,201
。数字addr是减少可用生命数量或检测与敌人冲突的例行程序的开始。0
是汇编NOP
(无操作)指令。在NOP
期间,CPU不执行任何操作。201
或C9
是汇编RET
(返回)指令,表示从子程序返回。在BASIC中,您可以使用GOSUB
调用子程序,并使用RETURN
从其末尾返回。在汇编语言中,相同的程序对是CALL
/RET
。201
,那么它实际上意味着一个子程序(例如减去一个生命),如下所示:9950 let lives = lives - 1
9960 return
被转换成了:
9950 return
9960 return
如果您的值为0,则会将相同的例程转换为:
9950
9960 return
RANDOMIZE USR 28455
)。POKE
来进行操作(增加生命值等),然后使用 RANDOMIZE USR 28455
启动机器码,假设你已经找到了正确的地址。LD A,3
3E 03 -> in hex
62 3 -> in decimal