基于尼康官方软件AC-PW,提取其核心 Pcf9032.dll逆向。
由 DeepSeek 4.0 Pro 辅助完成。
第一章 概述
1.1 适用范围
本报告完整描述 F90X/N90s F90/N90 胶片单反相机通过串行接口与计算机通信的底层协议、命令集、寄存器映射、功能编号及所有操作序列。所有内容均来自对官方控制库 Pcf9032.dll 及配套软件 PhotoSecretary的逆向分析,并通过资源提取进行验证。
1.2 通信架构
- 物理层:RS-232C 串行通信,5V 电平
- 波特率:初始 1200 bps,握手后切换至 9600 bps
- 数据格式:8 数据位,无校验,1 停止位 (8N1)
- 端口选择:COM1~COM4,由功能 ID 0 设定
- DLL 文件:Pcf9032.dll(Nikon 相机通信库),由主程序动态加载
1.3 相机型号识别
| 型号标识 | 相机返回字符串 | 地址字节 | 对应型号 |
|---|---|---|---|
| 1 | F90N90 | 0x10 | F90系列/N90(北美发售型号)系列 |
| 2 | F90xN90s | 0x20 | F90X系列/N90S(北美发售型号)系列 |
第二章 通信初始化
2.1 唤醒与型号识别
- 打开串口
COM%d,配置为 1200,8N1。 - 发送唤醒字节:
00(1 字节),等待 200ms,清空接收缓冲区。 - 发送型号查询:
53 31 30 30 30 05(S1000+ ENQ,共 6 字节)。 - 接收相机返回的标识字符串(例如
31 30 32 30 46 39 30 58 2F 4E 39 30 53 00 03 06表示1020F90X/N90S)。 - 根据字符串确定型号:
- 若包含
F90N90→ 型号 1,地址字节 0x10。 - 若包含
F90xN90s→ 型号 2,地址字节 0x20。
- 若包含
2.2 波特率升级至 9600
- 发送 9 字节命令(型号 1 用 0x10,型号 2 用 0x20):
01 10 87 05 00 00 00 00 03或01 20 87 05 00 00 00 00 03 - 等待相机应答
06 00(ACK)。 - 将本地串口切换为 9600 bps,等待 200ms 稳定。
2.3 结束 9600 会话(返回 1200)
- 发送
04 04(EOT 两次),相机返回04 04确认,然后串口恢复到 1200。 - 若相机自动休眠,波特率也会自动降回 1200。
第三章 通信帧格式
校验和仅计算纯数据部分,即从 STX (0x02) 之后的第一个字节开始,到 ETX (0x03) 之前的所有字节,不包括帧头(SOH)、地址、命令码、长度字段等任何头部字节。
波特率切换等特殊握手指令会使用 0x87 作为操作码,此类特殊指令属于硬编码控制帧,不完全遵循常规寄存器读写帧的载荷结构。
3.1 标准命令帧(命令码 ≤ 100)
读请求(无数据)
偏移 大小 值 说明
0 1 0x01 帧头 (SOH)
1 1 ADDR 设备地址 (0x10 或 0x20)
2 1 0x80 读操作
3 1 0x00 保留
4 1 v6 寄存器地址高字节
5 1 v7 寄存器地址低字节
6 1 0x00 保留
7 1 len 期望接收的数据长度
8 1 0x03 帧尾 (ETX)
总长 9 字节,无校验。
写请求(有数据)
偏移 大小 值 说明 0 1 0x01 帧头 1 1 ADDR 设备地址 2 1 0x81 写操作 3 1 0x00 保留 4 1 v6 寄存器地址高字节 5 1 v7 寄存器地址低字节 6 1 0x00 保留 7 1 len 数据长度(实际发送字节数) 8 1 0x02 数据起始标识 (STX) 9~ len DATA 数据体 9+len 1 CHK 校验和(所有 DATA 字节累加和的低 8 位) 10+len 1 0x03 帧尾 (ETX) 11+len 1 0x00 填充
总长 12 + len 字节。
3.2 扩展命令帧(命令码 > 100)
读请求
偏移 大小 值 说明 0 1 0x01 帧头 1 1 ADDR 设备地址 2 1 0x1B 命令组标识 3 1 0x90 命令组标识 4 1 0x82 读操作 5 1 v6 参数(由命令码决定) 6 1 len 期望接收长度 7 1 0x00 保留 8 1 0x03 帧尾
总长 9 字节。
写请求
偏移 大小 值 说明 0 1 0x01 帧头 1 1 ADDR 设备地址 2 1 0x1B 命令组标识 3 1 0x90 命令组标识 4 1 0x81 写操作 5 1 v6 参数 6 1 len 数据长度 7~ len DATA 数据体 7+len 1 CHK 校验和 8+len 1 0x03 帧尾 9+len 1 0x00 填充
总长 10 + len 字节。
3.3 应答帧
- 短应答(ACK):
06 00表示成功。 - 特殊同步应答:
04 04用于同步。 - 长应答(数据包):
- 字节 0:状态码(通常忽略,或为 0x01)
- 字节 1~(n-2):数据
- 字节 (n-1):校验和(字节 1 到字节 n-2 的累加和低 8 位)
- 字节 n:0x03 (ETX)
3.4 重试机制
发送命令后,最多重试 4 次(外层循环)× 4 次(内层发送尝试)。每次发送失败等待 200ms,若连续 4 次内层失败则退出内层;内层结束后等待 150ms 再进入下一次外循环。
第四章 命令码与寄存器地址映射表
4.1 标准命令码表(≤100)
从 DLL 函数 sub_1000DB73 的 switch 分支提取。v6、v7 以十六进制补码表示(负值转换为无符号字节,例 -3 = 0xFD)。
| 命令码 | v6 (hex) | v7 (hex) | 寄存器地址 | 常用数据长度 | 方向 | 关联功能ID |
|---|---|---|---|---|---|---|
| 0 | FD | 19 | FD19 | 1 | 读/写 | – |
| 1 | FD | 17 | FD17 | 2(读)/6(写) | 读/写 | – |
| 2 | FD | 1A | FD1A | 1 | 读/写 | – |
| 3 | FD | 1C | FD1C | 1 | 读/写 | – |
| 4 | FD | 1B | FD1B | 1 | 读/写 | – |
| 5 | FD | 16 | FD16 | 1 | 读/写 | – |
| 6 | FD | 28 | FD28 | 1 | 写 | 13 |
| 7 | FD | 26 | FD26 | 1 | 写 | 14,15,16 |
| 8 | FD | 27 | FD27 | 1 | 写 | 14,15,16 |
| 9 | FD | 29 | FD29 | 1 | 写 | 18 |
| 10 | FD | 2B | FD2B | 1 | 写 | 20 |
| 11 | FD | 2A | FD2A | 1 | 写 | 19 |
| 12 | FD | 2D | FD2D | 1 | 写 | 21 |
| 13 | FD | 2E | FD2E | 1 | 写 | 26 |
| 14 | FD | 21 | FD21 | 1 | 读 | – |
| 15 | FD | 2C | FD2C | 1 | 写 | 22,23 |
| 16 | FE | 44 | FE44 | 2 | 读/写 | – |
| 17 | FE | C9/C1 | FE? | 1 | 写 | 型号相关 |
| 18 | FD | 20 | FD20 | 1 | 读/写 | 0x64,0x66 |
| 19 | FD | 39 | FD39 | 1 | 读/写 | – |
| 20 | FD | 3A | FD3A | 1 | 读/写 | 0x64,0x66 |
| 21 | FD | 3B | FD3B | 1 | 读/写 | 0x64 |
| 22 | FD | 3C | FD3C | 2 | 读/写 | 0x64 |
| 23 | FE | D0 | FED0 | 1 | 写 | 用户设置 |
| 24 | FD | F2 | FDF2 | 2 | 写 | 用户设置 |
| 25 | FD | F3 | FDF3 | 1 | 读/写 | – |
| 26 | FE | 94 | FE94 | 2 | 写 | 用户设置 |
| 27 | FE | 95 | FE95 | 1 | 读/写 | – |
| 28 | FE | 9E | FE9E | 1 | 写 | 用户设置 |
| 29 | FD | 25 | FD25 | 1 | 写 | 17 |
| 30 | FD | 36 | FD36 | 3 | 读/写 | 90-95 |
| 31 | FE | C8 | FEC8 | 1 | 写 | 用户设置 |
| 32 | FD | 33 | FD33 | 3(型号1) | 读/写 | 0x46-0x52 |
| 33 | FD | 34 | FD34 | 1 | 读 | 状态检测 |
| 34 | FD | 40 | FD40 | 1 | 读/写 | 131 |
| 35 | FD | 30 | FD30 | 6(型号2) | 读/写 | 0x46-0x52 |
| 36 | FD | 41 | FD41 | 3 | 读/写 | – |
| 37 | FD | 24 | FD24 | 1 | 读 | 状态查询 |
| 38 | FE | 50 | FE50 | 1 | 读 | 状态检测 |
| 39 | FE | 20 | FE20 | 1 | 读/写 | – |
| 40 | FE | DB/D4 | FE? | 1 | 写 | 型号相关 |
| 41 | FD | 93/8E | FD? | 1 | 写 | 型号相关 |
| 42 | FD | 9D/90 | FD? | 1 | 写 | 型号相关 |
| 43 | FE | 06 | FE06 | 1 | 写 | – |
| 44 | FD | 1F | FD1F | 1 | 写 | 0x64 |
4.2 扩展命令码表(>100)
从 sub_1000DED3 的 switch 提取,命令码对应 ASCII 字符,v6 为帧内参数。
| 命令码 | ASCII | v6 (hex) | 常用数据长度 | 方向 |
|---|---|---|---|---|
| 101 | ‘e’ | 00 | 3 | 写 |
| 102 | ‘f’ | 06 | 5 | 写 |
| 103 | ‘g’ | 10 | 1 | 写 |
| 118 | ‘v’ | 70 | 1 | 读/写 |
| 119 | ‘w’ | 72 | 2 | 读/写 |
| 122 | ‘z’ | 80 | 1 | 写 |
第五章 功能 ID 完整映射
5.1 设定/读取函数导出索引
| 导出序号 | 函数名 | 用途 |
|---|---|---|
| 1 | FeatureExists | 检查功能ID是否有效 |
| 2 | GetIndexString | 获取功能选项文本 |
| 3 | GetMaxIndex | 获取选项最大索引 |
| 8 | GetValueBool | 读取布尔型参数 |
| 9 | GetValueFloat | 未实现 |
| 10 | GetValueIndex | 读取索引型参数 |
| 11 | GetValueInteger | 读取整型参数 |
| 12 | GetValueString | 读取字符串参数 |
| 13 | GetValueStruct | 读取结构体参数 |
| 14 | InvalidateReads | 清除读取缓存 |
| 15 | SetValueBool | 设置布尔型参数 |
| 16 | SetValueFloat | 未实现 |
| 17 | SetValueIndex | 设置索引型参数 |
| 18 | SetValueInteger | 设置整型参数 |
| 19 | SetValueString | 设置字符串参数 |
| 20 | SetValueStruct | 设置结构体参数 |
| 21 | StartProcess | 执行动作(拍摄、对焦、删除等) |
| 23 | WriteDataToCamera | 将修改的参数写入相机 |
5.2 功能 ID → 命令/寄存器映射
以下列出全部功能 ID(0~147)的精确技术映射,包括类型、设置/读取函数、所属 WriteDataToCamera 的 case、具体的命令码、寄存器地址(v6, v7)或扩展命令标识,以及在配置块中的位操作说明。
| 功能 ID | 类型 | 设置函数 | 读取函数 | Case | 命令码 / 寄存器 | 操作描述 |
|---|---|---|---|---|---|---|
| 0 | Integer | SetValueInteger | – | – | 直接设置全局变量 word_10015218 | 通信端口号 (1~4) |
| 1 | – | – | – | – | – | 未使用 |
| 2 | String | – | GetValueString | – | 直接返回相机型号字符串指针 | 相机型号字符串 (“F90N90” 或 “F90xN90s”) |
| 3 | Bool | SetValueBool | – | – | 直接设置 word_100122D4 | 相机型号选择 (0=型号1, 1=型号2) |
| 4 | Index | – | GetValueIndex | – | 特殊:读取 word_10012170 数组 | 电子手帐数据读取状态/进度 |
| 5 | Integer | – | GetValueInteger | – | 直接读取 dword_10012000 | 内部状态值(只读) |
| 6 | Bool | – | GetValueBool | 5 | 通过 sub_10008905 读取 word_100122BC | 未知布尔状态(只读) |
| 7~12 | – | – | – | – | – | 未使用 |
| 13 | Index | SetValueIndex | GetValueIndex | 1 | 命令 6 → FD28 | 测光方式 (0=矩阵, 1=中央重点, 2=点) |
| 14 | Index | SetValueIndex | GetValueIndex | 1 | 命令 7/8 → FD26, FD27;位操作 | 曝光模式 (0=P,1=S,2=A,3=M,4=CP,5-11=变程序) |
| 15 | Index | SetValueIndex | GetValueIndex | 1 | 命令 7/8 → FD26, FD27;位操作 | 曝光模式(与14共用寄存器,不同位) |
| 16 | Bool | SetValueBool | GetValueBool | 1 | 命令 7/8 → FD26, FD27;位操作 | 曝光模式扩展布尔 |
| 17 | Index | SetValueIndex | GetValueIndex | 1 | 命令 29 → FD25 | 快门速度 (B门/定时相关) |
| 18 | Index | SetValueIndex | GetValueIndex | 1 | 命令 9 → FD29 | 卷片模式 (0=单张, 1=低速连拍, 2=高速连拍) |
| 19 | Index | SetValueIndex | GetValueIndex | 1 | 命令 11 → FD2A | 闪光同步模式 (0=前帘,1=慢速,2=后帘,3=防红眼) |
| 20 | Index | SetValueIndex | GetValueIndex | 1 | 命令 10 → FD2B | 对焦区域 (0=宽区, 1=点) |
| 21 | Index | SetValueIndex | GetValueIndex | 1 | 命令 12 → FD2D | 曝光补偿范围 (-5.0~+5.0 EV) |
| 22 | Bool | SetValueBool | GetValueBool | 1 | 命令 15 → FD2C;位操作 | DX/手动 ISO 选择 |
| 23 | Index | SetValueIndex | GetValueIndex | 1 | 命令 15 → FD2C | ISO 感光度 (0=ISO 6, 1=ISO 8 … 30=ISO 6400) |
| 24 | Index | – | GetValueIndex | 1 | 命令 15 读回 FD2C | ISO 扩展读取 |
| 26 | Index | SetValueIndex | GetValueIndex | 1 | 命令 13 → FD2E | 闪光补偿/特殊设定 |
| 27~28 | – | – | – | – | – | 未使用 |
| 29 | Bool | – | GetValueBool | 3 | word_100123F2(通过 sub_100058C7 读取) | MF-26 状态(只读) |
| 30 | Bool | – | GetValueBool | 3 | word_100123F4(通过 sub_100058C7 读取) | MF-26 状态(只读) |
| 31 | Index | SetValueIndex | GetValueIndex | 3 | 命令 18,20 等,位操作 FD20, FD3A 等 | MF-26 曝光模式 |
| 32 | Index | SetValueIndex | GetValueIndex | 3 | 同上 | MF-26 曝光模式 |
| 33 | Index | SetValueIndex | GetValueIndex | 3 | 命令 6 → FD28 | 测光方式 (MF-26) |
| 34 | Index | SetValueIndex | GetValueIndex | 3 | 命令 9 → FD29 | 卷片模式 (MF-26) |
| 35 | Index | SetValueIndex | GetValueIndex | 3 | 命令 11 → FD2A | 闪光同步模式 (MF-26) |
| 36 | Index | SetValueIndex | GetValueIndex | 3 | 命令 10 → FD2B | 对焦区域 (MF-26) |
| 37~39 | – | – | – | – | – | 未使用 |
| 40 | Index | SetValueIndex | GetValueIndex | 1/8 | 命令 1 → FD17 | 用户设置库名称 |
| 41 | Index | – | GetValueIndex | 1/8 | 命令 1/7 读取 | 用户设置库当前选择 |
| 42 | Index | – | GetValueIndex | 8 | 命令 43 → FE06 等 | 镜头光圈值 (F1~F90) |
| 43 | Index | SetValueIndex | GetValueIndex | 8 | 命令 43 → FE06 等 | 镜头光圈值(设定) |
| 44 | Index | SetValueIndex | GetValueIndex | 1 | 命令 9 → FD29 | 卷片模式(另一入口) |
| 45 | Index | SetValueIndex | GetValueIndex | 8 | 命令 45 | 闪光同步(另一设定) |
| 46 | Bool | SetValueBool | GetValueBool | 8 | 命令 15 → FD2C;位操作 | 对焦模式 (0=手动, 1=AF 等) |
| 47 | Index | – | GetValueIndex | 8 | 命令 47 | ISO 显示(备用) |
| 48 | Index | SetValueIndex | GetValueIndex | 8 | 命令 10 → FD2B | 对焦区域(另一入口) |
| 49 | Index | SetValueIndex | GetValueIndex | 8 | 命令 49 | AF 方式 (0=释放优先, 1=对焦优先, 2=手动) |
| 50 | Index | – | GetValueIndex | 8 | 命令 50 | 对焦状态选项 |
| 51 | Index | SetValueIndex | GetValueIndex | 8 | 命令 51 | 对焦状态 (0=前焦,1=后焦,2=合焦,3=无法合焦) |
| 52 | Index | SetValueIndex | GetValueIndex | 8 | 命令 52 | ON/OFF 开关 |
| 53 | Index | SetValueIndex | GetValueIndex | 8 | 命令 53 | 曝光补偿值 (-20.0~+20.0) |
| 54 | Index | SetValueIndex | GetValueIndex | 8 | 命令 54 | 曝光补偿值(另一组) |
| 55 | Index | SetValueIndex | GetValueIndex | 8 | 命令 55 | 胶片计数器 (E, 0~99) |
| 56 | Index | SetValueIndex | GetValueIndex | 8 | 命令 56 | 电池状态 (0=满电, 1=低电量) |
| 57 | Index | – | GetValueIndex | 8 | 命令 57 | 特定索引 |
| 58 | Index | – | GetValueIndex | 8 | 命令 58 | 曝光补偿范围 (-5.0~+5.0 EV) |
| 59 | Index | SetValueIndex | GetValueIndex | 8 | 命令 59 | 镜头焦距 (5mm~7600mm) |
| 60 | Index | SetValueIndex | GetValueIndex | 8 | 命令 60 | 镜头焦距(另一组) |
| 61 | Index | SetValueIndex | GetValueIndex | 8 | 命令 61 | 镜头焦距(另一组) |
| 62 | Index | – | GetValueIndex | 8 | 命令 62 | 光圈值(另一组) |
| 63 | Index | – | GetValueIndex | 8 | 命令 63 | 特定索引 |
| 64 | Index | – | GetValueIndex | 8 | 命令 64 | 光圈值(另一组) |
| 65 | Index | – | GetValueIndex | 1/8 | 命令 1 读取 | 用户库读取 |
| 66 | Index | SetValueIndex | GetValueIndex | 1/8 | 命令 6 → FD28 | 测光方式(另一入口) |
| 67 | Index | SetValueIndex | GetValueIndex | 8 | 命令 67 | 闪光同步(另一组) |
| 68 | Index | SetValueIndex | GetValueIndex | 8 | 命令 68 | 镜头焦距(另一组) |
| 69 | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | 蜂鸣音开关(恢复默认用) |
| 70 (0x46) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | 合焦音开关 |
| 71 (0x47) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | DX 优先设定 |
| 72 (0x48) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | AE/AF 同时锁定 |
| 73 (0x49) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | AF-C 对焦优先 |
| 74 (0x4A) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | AF-S 释放优先 |
| 75 (0x4B) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | AF-S 帧间 AF 驱动 |
| 76 (0x4C) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | 0 帧数据印记 |
| 77 (0x4D) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | 测光偏差显示 |
| 78 (0x4E) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | A 模式简易曝光补偿 |
| 79 (0x4F) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | (保留) |
| 80 (0x50) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | 闪光灯相关设定 |
| 81 (0x51) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | 闪光灯相关设定 |
| 82 (0x52) | Bool | SetValueBool | GetValueBool | 4 | 配置块位操作 (命令32/35) | 闪光灯相关设定 |
| 83 | Index | SetValueIndex | GetValueIndex | 4 | 配置块 (命令32/35) | 闪光灯模式 |
| 84 | Index | SetValueIndex | GetValueIndex | 4 | 配置块 (命令32/35) | 长时间曝光时间 (4秒~60秒/B门) |
| 85 | Index | SetValueIndex | GetValueIndex | 4 | 配置块 (命令32/35) | 同步释放模式 |
| 86 | Index | SetValueIndex | GetValueIndex | 4 | 配置块 (命令32/35) | (预留) |
| 87 | Index | SetValueIndex | GetValueIndex | 4 | 配置块 (命令32/35) | 自拍/间隔时间 |
| 88 | – | – | – | – | StartProcess(0x58) 调用 | 恢复默认设置(操作码) |
| 89 | – | – | – | – | StartProcess(0x89) 调用 | 触发拍摄(操作码) |
| 90 | Index | SetValueIndex | GetValueIndex | 7 | 命令 30 → FD36 | 闪光灯/自定义程序点 (快门) |
| 91 | Index | SetValueIndex | GetValueIndex | 7 | 命令 30 → FD36 | 闪光灯/自定义程序点 (光圈) |
| 92 | Index | SetValueIndex | GetValueIndex | 7 | 命令 30 → FD36 | 同上 |
| 93 | Index | SetValueIndex | GetValueIndex | 7 | 命令 30 → FD36 | 同上 |
| 94 | Index | SetValueIndex | GetValueIndex | 7 | 命令 30 → FD36 | 同上 |
| 95 | Index | SetValueIndex | GetValueIndex | 7 | 命令 30 → FD36 | 同上 |
| 96 | – | – | – | – | StartProcess(0x60) 调用 | 闪光灯操作(操作码) |
| 97 | Index | – | GetValueIndex | 8 | 命令 97 | 微调值 |
| 98 | Index | SetValueIndex | GetValueIndex | 8/11 | 命令 98 | 微调值 (0.3~2.0) |
| 99 | Index | SetValueIndex | GetValueIndex | 8/11 | 命令 99 | 曝光补偿步长 (-3.0~+1.0) |
| 100 | Bool | – | – | 8 | – | (保留) |
| 101 | Integer | – | GetValueInteger | 8 | 读取多个配置寄存器 | 配置块值(只读) |
| 102~105 | – | – | – | – | – | 未使用 |
| 106 | Index | SetValueIndex | GetValueIndex | 9 | 扩展命令 103, 122 等 | 时区城市 (1~24) |
| 107 | – | – | – | – | – | 未使用 |
| 108 | Index | – | – | 9 | 扩展命令 | 时区城市(备用) |
| 109 | Index | SetValueIndex | GetValueIndex | 10 | 扩展命令 | 时差数值 (-10~+12, -11) |
| 110 | Index | SetValueIndex | GetValueIndex | 10 | 扩展命令 | 时差数值 (-11) |
| 111~114 | – | – | – | – | – | 未使用 |
| 115 | Index | – | GetValueIndex | 11 | 扩展命令 | 模式选择 |
| 116 | Index | SetValueIndex | GetValueIndex | 11 | 扩展命令 | 微调值 (另一入口) |
| 117 | – | – | – | – | – | 未使用 |
| 118 | Index | SetValueIndex | GetValueIndex | 11 | 扩展命令 | 曝光补偿步长 (同 99) |
| 119 | Index | SetValueIndex | GetValueIndex | 11 | 扩展命令 | 特殊设定(自拍/闪光相关) |
| 120~123 | – | – | – | – | – | 未使用 |
| 124 | Struct | – | GetValueStruct | 11 | 扩展命令 | 读取结构体 (2 字段) |
| 125 | Struct | – | GetValueStruct | 11 | 扩展命令 | 读取结构体 (3 字段) |
| 126 | – | – | – | – | – | 未使用 |
| 127~129 | – | – | – | 12 | 扩展命令 | 保留 |
| 130 | Struct | – | GetValueStruct | 11 | 扩展命令 | 读取结构体 (3 字段) |
| 131 | Index | SetValueIndex | GetValueIndex | 5 | 命令 34 → FD40 | 数据存储模式 (0/69/78/95) |
| 132 | Index | SetValueIndex | GetValueIndex | 5 | 命令 5 → FD34 bit7 | 数据印记 / 特殊设定位 |
| 133 | – | – | – | – | 命令 133(内部全消去) | 内部使用 |
| 134 | Integer | – | GetMinMaxInteger | – | 只读,范围 0-9999 | 胶片编号 |
| 135 | – | – | – | – | – | 未使用 |
| 136 | – | – | – | – | StartProcess(0x88) 调用 | 指针复位/状态初始化 |
| 137 | – | – | – | – | StartProcess(0x89) 调用 | 触发拍摄(同 89) |
| 138 | – | – | – | – | – | 未使用 |
| 139 | Index | – | GetIndexString | 6 | 字符串资源 | 自定义功能名称/选项 |
| 140~145 | – | – | – | – | – | 未使用 |
| 146 | Struct | – | GetValueStruct | 6 | 扩展命令 | 相机信息(型号、序列号等) |
| 147 | Struct | – | GetValueStruct | 6/5 | 扩展命令 | 对焦数据读取 |
注释:
- 配置块位操作:功能 ID 69~82 的具体位定义已在第七章详细列出。每个布尔值对应配置块(命令32/35)的某一位,通过读-修改-写流程改变。
- 扩展命令:功能 ID 106~130 使用命令码 >100 的扩展命令(格式
1B 90 cmd v6 len),具体 v6 和 len 见第四章扩展命令表。 - 操作码:88, 89, 96, 136, 137 等不直接对应设置/读取函数,而是由
StartProcess分发执行,内部命令序列已在前文各章详述。 - 表中粗体为软件中直接面向用户的主要功能。
- 未使用的功能 ID 在 DLL 中返回错误 2(不支持)。
- 对于131:
- 这些值直接写入
FD40寄存器,对应相机的“数据存储模式”0(0x00) → 不存储数据(Disabled) 69(0x45) → 存储最小数据量(Minimum)78(0x4E) → 存储中间数据量(Intermediate)95(0x5F) → 存储最大数据量(Maximum)
该映射与我们之前整理的FD40寄存器功能一致,且与 DLL 资源中对应的字符串(“記憶しない”、“最小情報量記憶”等)吻合。
第六章 特殊操作流程
6.1 拍摄(快门释放)
- 操作码:
StartProcess(0x89) - DLL 函数:
sub_10007BB0→ 型号1调用sub_10007C4B,型号2调用sub_10007CE0 - 命令序列(以型号1为例):
- 读
FD20、FD24、FD40获取状态。 - 构造写命令
01 10 81 00 FD 41 00 01 02 <data> <cs> 03 00,数据为0x42(’B’)及校验。 - 等待 ACK,再读
FD20和FD24完成清理。
- 读
6.2 自动对焦
- DLL 中未作为独立导出命令,但 EXE 的“AFの実行”菜单调用
StartProcess,其内部可触发对焦操作,对应的相机命令为01 20 86 00 00 00 00 00 03(也可被直接发送)。
6.3 用户设置库(保存/调用)
- 保存到库:
StartProcess(0x25)→sub_10005B79 - 从库读取:
StartProcess(0x26)→sub_10005A2E,StartProcess(0x27)→sub_10005D47 - 这些函数内部发送命令 18、20、31、119 以及
sub_1000E07D/sub_1000E183等位操作,并读写 FD17、FD26、FD27 等寄存器。
6.4 恢复默认设置
StartProcess(0x58)- 先将内部变量设为一组出厂默认值(详见代码中的连续赋值),然后调用
sub_100065A7,发送命令 119 或 18,最后写入配置块(命令 32 或 35)和公共配置(命令 20)。
6.5 胶卷数据读取
- 入口:
sub_10006F09→ 型号1调用sub_10007042,型号2调用sub_1000749C - 步骤:
- 读
FD20、FD24、FD40验证状态和存储模式。 - 读
FD41获取帧数v19和相关信息。 - 根据
v19计算动态地址:addr = 2 * v19(可能进行回绕修正)。 - 调用
sub_10007A14发送动态读命令,接收数据包。 - 数据以
0xFF作为卷结束标记,ISO 索引在最后。 - 解析帧数据(每帧 3/4/6 字节,取决于存储模式),字段包括快门速度、光圈、曝光模式、测光方式、焦距、曝光补偿等。
- 发送确认命令
0x42(’B’)完成本次读取。
- 读
6.6 删除胶卷数据
- 全消去:
StartProcess(0x1C)→sub_1000A9CD- 检查相机内是否有数据,若无则发送命令 133,相机清空整个环形缓冲区。
- 部分删除(移动读取指针):
StartProcess(0x1B)→sub_1000A7E1- 发送命令 134,并操作命令 19(FD39)的位 3,使相机内部的待读指针前移,等效于删除已读取的卷。
- 指针/状态复位:
StartProcess(0x88)→sub_10008403- 型号1:写 FD41 特定值,清除 FED6 的 bit0,清零 FD40。
- 型号2:读 FD00,写命令 ‘B’,清除 FECE 的 bit0,清零 FD40。
第七章 配置块位定义
从 sub_1000694E 提取(以型号1配置块命令32为例):
v34低字节 =a3[10]v34高字节:- bit0:
a3[13]控制 - bit1:
a3[2]控制 - bit2:
a3[11]控制 - bit3:
a3[3]控制 - bit5:
a3[9]控制 - bit6:
a3[8]控制
- bit0:
v35低字节:- bit2:
a3[12](1或3置1) - bit3:
a3[12](2或3置1) - bit4:
a3[5]控制 - bit5:
a3[7]控制 - bit7:
a3[6]控制
- bit2:
型号2配置块(命令35)有类似的位定义,详见原始反编译代码。
第八章 错误码表
| 错误码 (hex) | 含义 |
|---|---|
| 0x19 (25) | 参数无效 |
| 0x1D (29) | 数据块读取校验失败 |
| 0x25 (37) | 对焦扫描初始化失败 |
| 0x28 (40) | 功能不可用/状态错误 |
| 0x29 (41) | 功能不支持 |
| 0x32 (50) | 通用“不支持此操作” |
| 0x33 (51) | 参数冲突 |
| 0x34 (52) | 参数范围错误 |
| 0x35 (53) | 参数范围错误 |
| 0x37 (55) | 模式不匹配 |
| 0x45 (69) | 初始化失败 |
| -18 | 校验和不匹配 |
| -27 | 未收到 ACK (0x06) |
| -30 | 接收超时 |
| -35 | 相机状态错误 |
所有错误均通过全局变量 dword_10015220 返回。
第九章 数值编码与资源字符串
相机参数值到显示文本的映射完全来自 DLL/EXE 资源,无需第三方数据。例如:
- 快门速度:EXE 资源 17408 开始
"30"",连续列出 Bulb、30″、25″、… 1/8000。 - 光圈:资源 17664 起 F1、F1.1、… F90。
- ISO:资源 19968 起 ISO 6、ISO 8、… ISO 6400。
- 曝光补偿:资源 19712 起 0.0、-0.2、… +20.0。
- 测光方式:资源 22190 起 “多分区测光”、”中央重点测光”、”点测光”。
- 曝光模式:资源 17920 起 “P:多程序自动”、”S:快门优先” 等。
所有字符串均已在 EXE 和 DLL 的资源提取中完整列出,并翻译为中文。
第十章 与第三方文档的主要差异说明(主要指f90x-serial-documentation/f90x-serial-documentation.md at trunk · antarktikali/f90x-serial-documentation · GitHub及gIcon source 项目等)
- 地址字节:第三方固定使用
0x20,我们根据 DLL 逻辑动态使用0x10或0x20。 - 扩展命令格式:第三方可能省略
0x90,我们严格采用 DLL 的1B 90 cmd格式。 - 环形缓冲区指针:第三方直接操作 FD44/FD46,DLL 通过动态地址计算和 FED6/FECE 等寄存器间接实现,功能等效。
- 部分只读状态寄存器(如 FE20、FE22)在 DLL 中未出现立即数,但其信息已通过功能 ID 提供,不影响使用。
- 所有命令码和寄存器映射完全基于 DLL 的
sub_1000DB73、sub_1000DED3,比第三方仅列举的片段更为完整和准确。
附录 A 数据块格式(胶卷记录)
卷头:2 字节 0x5A58(“ZX”)
2 字节 元数据
2 字节 0x0000
2 字节 卷号(BCD)
帧数据:N × (3/4/6 字节) 取决于存储模式
1 字节 0xFF(结束标记)
1 字节 ISO 索引
每帧数据字段(6 字节最大模式):快门速度、光圈、曝光模式、测光模式、闪光同步、焦距、曝光补偿、闪光补偿。具体编码与命令寄存器返回的原始值一致,可参照资源字符串表解析。
补充:
- 在
sub_10007042中,读取胶卷数据时使用的动态地址v28 = 2 * v19,并且有如下回绕处理:
v15 = 总字节数 + v28;
if ( v15 >= 0x200u )
v15 -= 444; // 回绕修正,444 = 0x1BC
- 这说明环形缓冲区的大小为 512 (0x200) 字节,当读取指针超过
0x1FF时,会回绕到0x200 - 444 = 0x44(实际基址由相机固定)。DLL 内部自动处理了回绕,开发者只需按此逻辑实现即可。

发表回复