mrcook/jetpac-disassembly
GitHub: mrcook/jetpac-disassembly
一个基于 SkoolKit 的 JETPAC 经典游戏 ROM 反汇编项目,还原并注释原始二进制代码。
Stars: 66 | Forks: 11
# JETPAC 卡带 ROM 反汇编
一个非官方的 JETPAC 反汇编版本,经典 8 位电脑游戏,
于 1983 年为 16K ZX Spectrum 家用电脑发布。
[这个反汇编](https://github.com/mrcook/jetpac-disassembly) 是
基于原始 ZX Spectrum JETPAC 卡带 ROM 的二进制数据,
使用 [SkoolKit](http://skoolkit.ca) 反汇编工具包创建。
## 游戏介绍
一款面向 8 位家用电脑系统的快节奏射击游戏。
Jetpac 是 Jetman 系列的第一部作品,后续还有
_1983 年的 Lunar Jetman_ 和 _1990 年的 Solar Jetman: Hunt for the Golden Warpship_。
**“Acme Interstellar Transport Company”正在向太阳系中的各个行星
运送 SPACESHIP KITS;而作为首席试飞员,你
所要做的就是组装火箭,并推动它前往下一个目的地。**
**但!由于你并不总能获得免费穿越银河的机会,而太空旅行
又是如此昂贵,现在是你致富的好机会!你可以在旅途中顺道访问几颗
行星,收集奇怪的宝石、元素或黄金,并将它们带回。**
**听起来很简单,不是吗!**
但!在让自己成为宇宙中最富有的人之前,你必须记得每次
降落星球时用 6 个燃料舱为飞船加油。其他你收集到的
物品都可以归你所有。降落之后,你会发现自身装备了最新的 Hydrovac **JET PAC**,
它可以自动空投几乎任何火箭阶段、燃料舱或贵重物品到你选定的位置,
并在飞船基地释放它们,同时配备强大的四光子激光相位器,
用于击落任何可能对你访问提出异议的讨厌小外星人。
而你懂的!当你收集完它们的所有财物并悄悄离开,
连一句告别都没有时,这些外星人会变得多么愤怒。
_JETPAC 由 Chris Stamper 和 Tim Stamper 于 1983 年为
16K 和 48K 的 Sinclair ZX Spectrum 设计开发。_
## 项目状态
此反汇编可能已经完成。
- 所有代码块都已标记并注释。
- 所有变量都已标记并注释。
- 所有数据都已分离并注释。
- 所有文本数据都已注释。
- 所有图形都已注释(瓦片、精灵)。
- 所有游戏缓冲区(敌机/可收集物)都已注释。
不过,仍有一些代码和变量部分
值得进一步深入分析。
欢迎反馈与提交!
## Skoolkit 使用说明
当 ZX Spectrum 从卡带启动时,
位于地址 `$0000` 的 _loader_ 例程会被执行。该例程将加载屏幕复制到 Spectrum 显示文件,
并等待玩家按键。随后,游戏代码和数据会被复制到电脑 RAM 的地址 `$6000`
(十进制为 `24499`)。
因此为了让反汇编位于正确地址,Skoolkit 需要指定一个起始写入地址。
以下命令可以从 `.rom` 镜像中提取游戏(镜像未包含在本仓库中),
应用反汇编注释,并将生成的源代码写入 `.skool` 文件:
```
$ sna2skool.py -c jetpac.ctl -Hl -o 24499 jetpac.rom > jetpac.skool
```
## 汇编代码
Skoolkit 可以生成有效的 Z80 汇编代码,命令如下:
```
$ skool2asm.py -H -crs jetpac.skool > jetpac.asm
```
生成的 `asm` 文件在没有 loader 例程的情况下无法启动游戏。
一个基础示例可在文件中找到:
[`loader.asm`](https://github.com/mrcook/jetpac-disassembly/blob/master/loader.asm)。
[Pasmo Assembler](http://pasmo.speccy.org/) 可用于将源代码汇编为可用的 ZX Spectrum 磁带镜像。
```
$ pasmo --tzxbas loader.asm jetpac.tzx
```
## 磁带版本反汇编说明
本节包含关于卡带版与磁带版 Jetpac 差异的注释。
两者的代码基本相同,区别仅在于:
- 内存加载位置略有不同;
- 磁带版支持 Kempston 摇杆而非 Interface 2;
- 还包含一个用于磁带加载的 _代码移动例程_。
BASIC 磁带加载器是一条长指令序列,已在此重新排版以适配显示。
```
1 CLEAR 24575:
BEEP .1,1: BEEP .1,2: BEEP .1,3: BEEP .1,4: BEEP .1,5:
PAPER 0: INK 7: BRIGHT 1: CLS : PRINT BRIGHT 1;INK 7;
AT 9,7;"JETPAC IS LOADING";
AT 12,10;"PLEASE WAIT":
PRINT AT 0,0: LOAD ""SCREEN$ :
INK 0: PAPER 0:
PRINT AT 5,0: LOAD ""CODE :
PRINT AT 5,0: LOAD ""CODE :
PRINT AT 5,0: LOAD ""CODE :
PRINT AT 5,0: LOAD ""CODE :
PRINT USR 24576
```
以下是用于反汇编 TZX 镜像文件的 skoolkit `t2s` 配置文件:
```
; tap2sna.py file for Jetpac cassette version. Run
;
; $ tap2sna.py @jetpac.t2s
;
; to create a Z80 snapshot.
jetpac.tzx
jetpac.z80
; Skoolkit handles these automatically,
; but listing here for reference.
; ram load: 4,16384 # load screen (JPSP)
; ram load: 6,24576 # load game code/data
; ram load: 8,23424 # load `mover` routine
; ram load: 10,23728 # load `JP (HL)` opcode
; ram load: 12,23672 # load game start check variables
; After the game loads the PC starts at $6000:
;
; c$6000 DI
; $6001 JP $5B80
;
; The `mover` routine at $5B80 moves bytes 24580-32772 down to 24576-32768.
; This routine is loaded from tape block #8 (see above).
--ram move=$6004,$2000,$6000
; Initialize all game variables and data so the source code is clean.
--ram poke=$5CCB-$5FFF,$00
--reg sp=$5CF0
--reg pc=$61E5
```
如你所见,`--ram move=$6004,$2000,$6000` 模拟了磁带上
找到的代码移动例程。
对此感兴趣的朋友,该例程如下:
```
; Skoolkit code mover disassembly for Jetpac
; Disassembly of the code mover routine, which copies 8192 bytes from address
; $6004 down to $6000, before then jumping to the game start routine.
c$5b80 ld hl,$6004 ;
$5b83 ld de,$6000 ;
$5b86 ld bc,$2000 ;
$5b89 ldir ;
$5b8b jp $61e5 ;
; Tape block #6 ("The Game") is loaded at this address, starts running, then
; calls the above routine, which then overwrites these instructions.
c$6000 di ;
$6001 jp $5b80 ;
```
Kempston 摇杆菜单项:
```
$62dc defm "4 KEMPSTON JOYSTIC"
$62f0 defb $cb ; ASCII "K" ($4B) + EOL control bit
```
摇杆读取例程及其在代码中的使用方式存在一些细微差异。
以下是主要的读取例程本身:
```
; Joystick Input (Kempston)
;
; Output:A Joystick direction/button state.
@label=ReadKempstonJoystick
c$733a in a,($1f) ; Joystick port
$733c cpl ; Invert all bits in #REGa
$733d ret ;
```
### 128K Spectrum 修复
在键盘读取代码中存在一条 `out ($fd),a` 指令,
在 128K Spectrum 上似乎会导致问题,因此需要将其改为 `NOP` 指令。
```
; jetpac.skool
- $7326 out ($fd),a ; Set port for reading keyboard
+ $7326 nop
+ $7327 nop
```
## 版权信息
本反汇编、注释和支持文件版权归 Michael R. Cook © 2020 所有。
JETPAC 版权、ULTIMATE PLAY THE GAME。版权与商业名称,1983 年 Ashby Computers & Graphics Ltd。保留所有权利。
标签:1983, 8位游戏, Jetman系列, Jetpac, ROM分析, SkoolKit, Wayback Machine, ZX Spectrum, 像素射击, 反汇编, 复古游戏, 太空射击, 安全报告生成, 开源反汇编, 快速连接, 汇编语言, 游戏ROM, 游戏开发历史, 游戏源码, 游戏逆向工程, 电子游戏考古, 系统运维工具, 经典游戏, 街机射击, 逆向工具