c0rner/ghidra_wpc_loader

GitHub: c0rner/ghidra_wpc_loader

Ghidra 扩展,用于加载和分析 Williams 弹珠机 WPC 系统 ROM,自动构建体切换内存映射、I/O 寄存器标签和操作系统级符号。

Stars: 2 | Forks: 0

# WPC Loader — 用于 Williams Pinball Controller 的 Ghidra ROM 加载器 这是一个 [Ghidra](https://ghidra-sre.org/) 扩展,用于加载 Williams Pinball Controller (WPC) 游戏 ROM,并构建一个完整、可导航的内存映射——包括体切换 (banked) ROM 覆盖块、 ASIC I/O 寄存器、中断向量和操作系统级别的 RAM 符号。 ## 概述 WPC 弹珠机 (1990–1999) 使用运行频率为 2 MHz 的 **Motorola 68B09E** CPU,具有 64 KB 的地址空间。游戏 ROM 有四种大小:128 KiB、256 KiB、512 KiB 或 1 MiB, 划分为 16 KiB 的页面,并通过 `WPC_ROM_BANK` 硬件寄存器 (`0x3FFC`) 体切换到位于 `0x4000–0x7FFF` 的 CPU 窗口中。 该加载器涵盖了所有六代 WPC 硬件: | 世代 | 年份 | 关键硬件 | |---|---|---| | WPC 字母数字 | 1990–1991 | 14 段显示器,独立的声音板 | | WPC DMD | 1991–1993 | 128×32 点阵显示器 | | WPC Fliptronic | 1993–1994 | 专用拨动板 | | WPC DCS | 1993–1995 | 高保真 DCS 音频板 | | WPC Security | 1994–1996 | 开关矩阵路径中的 Security PIC 芯片 | | WPC-95 | 1995–1999 | FPGA 整合板,额外的 RAM 体切换 | ## 内存映射 加载器会创建以下 Ghidra 内存块: | 内存块 | 地址范围 | 大小 | 权限 | 易失性 | 描述 | |---|---|---|---|---|---| | `RAM` | `0x0000–0x1FFF` | 8 KiB | R/W | 否 | 电池供电的 SRAM | | `RAM_EXT` | `0x2000–0x2FFF` | 4 KiB | R/W | 否 | 额外的 RAM — DCS / WPC-95 *(可选)* | | `DMD` | `0x3000–0x3BFF` | 3 KiB | R/W | **否** | DMD 显示器 SRAM 窗口 — 见说明 | | `IO` | `0x3C00–0x3FFF` | 1 KiB | R/W | **是** | WPC ASIC 硬件寄存器 | | `ROM_PAGE_XX` | `0x4000–0x7FFF` | 16 KiB | R/W/X | 否 | 体切换 ROM 覆盖块 — 见说明 | | `ROM_SYSTEM` | `0x8000–0xFFFF` | 32 KiB | R/W/X | 否 | 固定系统 ROM — 见说明 | ### 内存块说明 **`DMD` — R/W,非易失性** DMD 控制板具有 8 KiB 的 SRAM,最多可容纳 16 个位平面(每个 512 字节)。 CPU 最多将两个页面同时映射到 `0x3000–0x3BFF` 窗口中,并对其进行完全的 R/W 访问。至关重要的是,DMD 控制器**无法自主写入**这些 RAM 页面——它仅从中读取数据以刷新显示。这意味着从 Ghidra 的角度来看,该块*不是* 易失性的:CPU 是唯一的写入者,写入的值在 CPU 再次更改之前, 读取时将保持不变。 **`ROM_PAGE_XX` — R/W/X,非易失性覆盖块** WPC ASIC 在物理上并未对 ROM 窗口进行写保护。CPU 可以(并且确实会) 写入 `0x4000–0x7FFF`,通常用于修补自修改的跳板或就地更新代码向量。 然而,这些写入仅影响 ASIC 总线逻辑中当前映射的页面——它们**不会持久化到 ROM 芯片中**。 当切换到不同的页面并且随后恢复原始页面时,所有写入的数据都会消失。 每个 Ghidra 覆盖块仅模拟单个体切换的快照;跨体的写入效果不会被表示出来。 **`ROM_SYSTEM` — R/W/X** 位于 `0x8000–0xFFFF` 的系统 ROM 反映了硬件的行为:WPC ASIC 未对固定的 ROM 窗口强制执行只读保护,因此 CPU 可以向该区域发出写周期。 实际上,这些写入不会产生任何持久的影响(ROM 芯片会忽略它们),但将该块标记为可写可以防止 Ghidra 将合法的写入指令标记为分析错误。 ### 体切换 ROM 页码编号 WPC 硬件页码从地址空间的**顶部**向下计算。 最后两个页面(`0x3E`、`0x3F`)在系统 ROM 窗口(`0x8000–0xFFFF`) 中永久可见,并且未被覆盖。对于总共有 *N* 个 16 KiB 页面的 ROM,体切换页面索引 *b* 将获得硬件页码 `0x3F − (N − 1 − b)`: | ROM 大小 | 总页数 | 体切换覆盖范围 | |---|---|---| | 128 KiB | 8 | `ROM_PAGE_38` – `ROM_PAGE_3D` (6 个页面) | | 256 KiB | 16 | `ROM_PAGE_30` – `ROM_PAGE_3D` (14 个页面) | | 512 KiB | 32 | `ROM_PAGE_20` – `ROM_PAGE_3D` (30 个页面) | | 1 MiB | 64 | `ROM_PAGE_00` – `ROM_PAGE_3D` (62 个页面) | ## 应用的标签 ### I/O 寄存器 (`0x3FB8–0x3FFF`) 所有已记录的 WPC ASIC 和外设寄存器均已标记,包括: - `WPC_ROM_BANK` — 体切换寄存器 - `WPC_ZEROCROSS_IRQ_CLEAR` — IRQ 源 / 看门狗踢除 (watchdog kick) - `WPC_LEDS` — 诊断 LED - `WPC_SOL_*` — 螺线管驱动输出 - `WPC_LAMP_*` — 灯矩阵行/列 - `WPC_SW_*` / `WPCS_PIC_*` — 开关矩阵输入 (Security 之前 / WPC-S) - `WPC_DMD_*` — DMD 页面选择和扫描线寄存器 - `WPC_SHIFTADDR` / `WPC_SHIFTBIT` — 硬件位移位器 - `WPC_RAM_LOCK` / `WPC_RAM_LOCKSIZE` — RAM 写保护 - `WPC_CLK_*` — 实时时钟 - `WPCS_DATA` / `WPCS_CONTROL_STATUS` — 声音板 - `WPC_FLIPTRONIC_PORT_A` — 拨动线圈/开关 I/O - `WPC95_FLIPPER_*` — WPC-95 拨动器寄存器 - `WPC_ROM_CHECKSUM` / `WPC_ROM_CHECKSUM_DELTA` — 校验和字段 ### 中断向量 (`0xFFF0–0xFFFE`) 每个 6809 向量槽被定义为 `Pointer16` 类型,并进行标记(`VEC_RESET`、`VEC_NMI`、 `VEC_SWI`、`VEC_IRQ`、`VEC_FIRQ`、`VEC_SWI2`、`VEC_SWI3`、`VEC_RESERVED`),同时 在其目标地址处创建一个 Ghidra 函数(`_ISR`)。 复位向量目标也被注册为程序的**入口点**。 ### RAM 符号 (`0x0000–0x03FF`) 包含来自 WPC 逆向工程工作的大约 50 个操作系统级符号,包括线程 变量、灯矩阵缓冲区、螺线管启用影子、IRQ 计数器和 DMD ISR 状态。 ## 加载器选项 Ghidra 的导入对话框中提供两个选项: | 选项 | 默认值 | 描述 | |---|---|---| | **创建体切换 ROM 覆盖块** | ✅ 开启 | 为每个体切换页面创建一个 `ROM_PAGE_XX` 覆盖块 | | **创建扩展 RAM 块 (DCS/WPC-95)** | ✅ 开启 | 在 `0x2000` 处创建 4 KiB 的 `RAM_EXT` 块 | 如果只需快速分析固定的 ROM,请禁用覆盖块。 ## ROM 有效性 加载器接受文件大小恰好为四种有效 WPC ROM 大小之一 (128 KiB、256 KiB、512 KiB、1 MiB)的文件。加载后,消息日志会报告 ROM 版本号(从位于 `0xFFEE` 的校验和字的低字节解码)以及 校验和是否被禁用(`delta = 0x00FF`,开发模式)。 ## 环境要求 | 要求 | 版本 | |---|---| | [Ghidra](https://ghidra-sre.org/) | **12.0.4** | | Java | 21(随 Ghidra 捆绑提供) | ## 构建 使用随 Ghidra 捆绑提供的 gradle **1. 设置您的 Ghidra 安装路径** ``` export GHIDRA_INSTALL_DIR=/path/to/ghidra_12.0.4_PUBLIC ``` **2. 编译:** ``` /path/to/ghidra_12.0.4_PUBLIC/support/gradle/gradlew # → dist/ghidra_12.0.4_PUBLIC__WPCLoader.zip ``` **3. 在 Ghidra 中安装:** 在 Ghidra 的项目管理器中:*文件 → 安装扩展* → 从 `dist/` 中选择该 zip 文件。 出现提示时重启 Ghidra。 ## 用法 1. 打开 Ghidra 并创建或打开一个项目。 2. 将 WPC ROM 文件(`.bin`、`.rom` 或任何扩展名)拖到项目窗口中, 或使用 *文件 → 导入文件*。 3. Ghidra 将通过文件大小检查自动检测 WPC 格式,并建议使用 **WPC ROM Loader** 以及 `6809:BE:16:default`(Motorola 6809,大端序)。 4. 根据需要调整导入选项(覆盖块、扩展 RAM),然后点击 **OK**。 5. 在 CodeBrowser 中打开导入的程序并运行 **自动分析** 以反汇编 系统 ROM。每个体切换的覆盖块都可以单独进行分析。
标签:Ghidra, JS文件枚举, Loader插件, 云资产清单, 后台面板检测, 固件分析, 域名枚举, 嵌入式系统, 游戏模拟器, 逆向工程