RaccoonFacts/Mini-Cam-Custom-Frame-Tool-GPZP
GitHub: RaccoonFacts/Mini-Cam-Custom-Frame-Tool-GPZP
该工具包用于逆向解码并替换基于 Generalplus GPDV 平台的玩具数码相机 SPI NOR flash 中存储的装饰性相框资源,支持从设计到刷写的完整自定义流程。
Stars: 5 | Forks: 0
# 📷 Mini-Cam-Custom-Frame-Tool-GPZP
适用于 **Photo Creator Mini Cam** 玩具数码相机(以及其他基于 Generalplus GPDV 的相机)的自定义相框工具包。
⚠️ **工作正在进行中** — 工具可以使用,但尚未完全完善。使用风险自负,请妥善保管您的固件备份。07/05/2026
## 功能说明
这款相机将 6 个装饰性相框(胶卷、滑板、霓虹星、花朵、笑脸、涂鸦)以压缩图像分块的形式存储在 2MB 的 SPI NOR flash 芯片内。该工具包可以让您:
- **解码**原厂相框为 PNG 格式以便查看
- **编码**任意 640x480 RGBA PNG 图像为相机原生格式
- **修补**您的自定义相框到固件二进制文件中
- 使用 XGPro 编程器将修补后的固件**重新刷写**回相机
## 所需硬件
| 项目 | 备注 |
|------|-------|
| XGPro T48 或 T56 编程器 | 任意型号均可 |
| SOIC8 芯片夹 | 用于免拆机读写 |
| Photo Creator Mini Cam | 目标相机 |
该 flash 芯片为 **Puya PY25D16 (SOP8)** — 请在 XGPro 中精确选择此型号。
## 提取固件
1. 拆开相机(背面有 4 颗螺丝)
2. 在 PCB 上找到 SOP8 flash 芯片
3. **在取出相机电池的情况下**,将 SOIC8 芯片夹夹在芯片上
4. 在 XGPro 中:选择 `PY25D16 SOP8` → **读取** → 另存为 `py25d16hb@sop8.bin`
5. 将此文件作为您的主备份妥善保管
## 安装
```
git clone https://github.com/RaccoonFacts/Mini-Cam-Custom-Frame-Tool-GPZP.git
cd Mini-Cam-Custom-Frame-Tool-GPZP
```
## 使用说明
### 将原厂相框解码为 PNG
```
python3 decode_frame.py
# 输出所有 6 帧 到 ./frames/
```
### 创建自定义相框
- 在任何图像编辑器(Photoshop、GIMP、Krita)中打开 `examples/template.png`
- 以 **640x480 像素**、**RGBA** 模式设计您的相框
- 透明像素 = 照片显示的区域
- 保存为 PNG 格式
### 将您的 PNG 编码并压缩为 GPZP 分块
```
# Step 1: 将 PNG 编码为 strips
python3 frame_encoder.py myframe.png ./my_strips/
# Step 2: 压缩 strips 以适配固件 tile 大小
python3 strip_compressor.py py25d16hb@sop8.bin smiley myframe.png ./my_strips/
```
### 修补到固件
```
python3 patcher.py py25d16hb@sop8.bin smiley ./my_strips/
# 输出 py25d16hb@sop8_patched.bin
```
### 重新刷写
1. 打开 XGPro,加载 `py25d16hb@sop8_patched.bin`
2. 选择 `PY25D16 SOP8`
3. **擦除** → **编程** → **校验**
4. 重新安装芯片,组装好相机
## 技术细节
适合想要深入了解的用户:
- **容器格式:** GPNV(Generalplus 专有格式)
- **压缩格式:** 带有**固定霍夫曼编码 (BTYPE=1)** 的原始 deflate — 相机的解压器会拒绝动态霍夫曼 (BTYPE=2),而这正是 Python 的 zlib 默认选项。必须通过 libz ctypes 使用 `Z_FIXED` 策略。
- **颜色格式:** UYVY(YUV422 打包格式),在解码时 U 和 V 进行了互换
- **透明度键:** `U=128, V=128, Y=140`
- **分块尺寸:** 640×120 像素
- **相框布局:** 4 个分块垂直堆叠 → 640×480 最终图像
- **Flash 芯片:** PY25D16,2MB SPI NOR,SOP8 封装
- **资源基地址:** `0x07EC00`
- **资源索引表:** `0x83400`
- **平台:** Generalplus GPDV,ARM Cortex-M
### 更新相框选择预览缩略图
```
python3 preview_changer.py py25d16hb@sop8.bin smiley myframe.png
```
这会更新相机的相框选择菜单中显示的小缩略图。请与主修补程序一起运行,以保持预览与您的自定义相框同步。
## 预览缩略图技术细节
相框选择菜单为每个相框槽位显示一个 160×160 像素的缩略图。它们与主相框分块分开存储,位于固件中的不同区域。
与相框分块的主要区别:
- **格式:** RGB565(每个像素 2 字节,小端序) — 不同于相框分块的 UYVY
- **尺寸:** 160×160 像素 = 未压缩时为 51200 字节
- **可见区域:** 菜单中仅显示顶部 160×80 像素的部分 — 底部一半始终为黑色/透明填充
- **透明度键:** `0x8C71` (RGB565) — 不同于 UYVY 相框分块的 `U=128, V=128, Y=140` 透明度键
- **压缩格式:** 与相框分块相同的固定霍夫曼 deflate (BTYPE=1)
固件中的预览偏移量:
| 相框 | 偏移量 |
|-------|--------|
| film (胶卷) | 0x143A04 |
| skateboard (滑板) | 0x144004 |
| neon_star (霓虹星) | 0x144C04 |
| flower (花朵) | 0x145804 |
| smiley (笑脸) | 0x147404 |
| graffiti (涂鸦) | 0x148E04 |
偏移量通过资源索引表 `0x83400` 并使用基地址 `0x07EC00` 进行定位。
每个分块名称映射到表中格式为 `GPZP` 的命名条目 — 该工具会自动解析这些条目。涂鸦的第 4 个分块没有命名条目,为硬编码。
| 相框 | 分块 | 条带 | Y 位置 |
|-------|------|-------|------------|
| film | CP0001 | 0 | 0 |
| film | CP0002 | 1 | 120 |
| film | CP0003 | 2 | 240 |
| film | CP0100 | 3 | 360 |
| skateboard | CP0101 | 0 | 0 |
| skateboard | CP0102 | 1 | 120 |
| skateboard | CP0103 | 2 | 240 |
| skateboard | CP0200 | 3 | 360 |
| neon_star | CP0201 | 0 | 0 |
| neon_star | CP0202 | 1 | 120 |
| neon_star | CP0203 | 2 | 240 |
| neon_star | CP0300 | 3 | 360 |
| flower | CP0301 | 0 | 0 |
| flower | CP0302 | 1 | 120 |
| flower | CP0303 | 2 | 240 |
| flower | CP0400 | 3 | 360 |
| smiley | CP0401 | 0 | 0 |
| smiley | CP0402 | 1 | 120 |
| smiley | CP0403 | 2 | 240 |
| smiley | CP0500 | 3 | 360 |
| graffiti | CP0501 | 0 | 0 |
| graffiti | CP0502 | 1 | 120 |
| graffiti | CP0503 | 2 | 240 |
| graffiti | hardcoded | 3 | 360 — `0x0DFA00` |
## 免责声明
本工具仅供个人在自有的硬件上进行教育用途。请务必备份您的原始固件。如果刷写出错,请重新刷写原始的 `.bin` 备份文件。
## 贡献
如果您有这款相机的其他变体,并发现了不同的偏移量或颜色格式,请提交 issue 或 PR 并附上您的发现。请提供您的固件 MD5 和芯片标识。
*由 [RaccoonFacts](https://github.com/RaccoonFacts) 逆向并开发*
标签:SPI Flash, 固件修改, 图像处理, 嵌入式开发, 硬件工具, 逆向工具