010editor 模板编写
参考文档:
https://www.sweetscape.com/010editor/manual/IntroTemplates.htm
https://bbs.pediy.com/thread-257797.htm
https://lyana-nullptr.github.io/2024/07/27/try-the-template-of-010editor/
变量
模板文件的开头会有如下信息:
1 | // File: |
程序会优先用File Mask匹配文件扩展名,再用ID Bytes匹配魔术数,匹配成功的话就会自动加载模板文件。
默认情况下,所有变量都会显示在模板窗口中。比如:
1 | struct test{ |
可以通过local关键字定义变量,这样的变量默认不会显示在模板窗口中,不过用户任然可以在窗口中点击右键菜单中的Show Local Variables来显示局部变量。
1 | // 该模板中定义了变量 a, b, c, d, e, f, g |
重复定义同名的变量将被视作定义一个数组变量,也可以通过循环语句和定义变量语句组合实现。如:
1 | // 方法 1,显示为: |
变量属性
1 | < format=hex|decimal|octal|binary, |
format: 以某种进制格式显示,默认为十进制,显示在 Vlaue 栏
fgcolor: 设置字体色
bgcolor: 设置背景色
comment: 添加注释,显示在 Comment 栏
name: 替换显示的字符,默认为结构体中的变量名,显示在 Name 栏
open: 设置树形图是否展开,默认不展开
hidden: 设置是否隐藏,默认为不隐藏
read: 读回调,返回字符串并显示在 Vlaue 栏
write: 写回调,将读回调返回的字符写入结构体某个字段中
size: 按需执行,可节约系统内存
一些颜色值 :
1 | cBlack - 0x000000 |
帮助大伙更好的理解以上这几个特殊的属性,图 1 中的 1 处是 name 属性显示的字符,如果不指定 name 属性默认就是结构体中的变量名。2 处是 format 属性,默认是十进制,这里指定为 16 进制。3 处是背景颜色和字体颜色缩影,这里没设置颜色所以显示为空。4 处就是 comment 属性显示的位置。
数据类型
8字节 char byte CHAR BYTE uchar ubyte UCHAR UBYTE
16字节 short int16 SHORT INT16 ushort uint16 USHORT UINT16 WORD
32字节 int int32 long INT INT32 LONG uint uint32 ulong UINT UINT32 ULONG DWORD
64字节 int64 quad QUAD INT64 __int64 uint64 uquad UQUAD UINT64 __uint64 QWORD
浮点 float FLOAT double DOUBLE hfloat HFLOAT
其他 DOSDATE DOSTIME FILETIME OLETIME time_t
使用:
1 | enum MYENUM { COMP_1, COMP_2 = 5, COMP_3 } var1; |
控制语句和函数
支持 for,if,while,switch
函数参数可以通过值或引用传递,010editor脚本不支持指针,但是可以用[]表示数组
程序中不需要main函数,代码从第一行开始执行
关键字
sizeof
startof 用于计算变量起始地址
1 | SetCursorPos( startof( lines[0] ) ); |
exists 检查某变量是否声明
1 | int i; |
function_exists 检查函数是否定义
1 | if( function_exists(CopyStringToClipboard) ) |
this 引用当前结构体
1 | void PrintHeader( struct HEADER &h ) |
parentof 访问包含变量的结构和union
1 | void PrintHeader( struct HEADER &h ) |
大小端以及其他设置
默认随系统,比如在 Windows 下是按照小端模式,通过BigEndian和LittleEndian来调整读取方式。
1 | BigEndian(); // 转换为大端模式 |
- color设置
1 | int id <fgcolor=cBlack, bgcolor=0x0000FF>; |
脚本终止
如果在执行过程中发现脚本结构不对时可以提前结束,使用return语句即可,我们把整个脚本文件看作是一个C函数,用return就可以提前退出函数。
1 | local string magic = ReadString(0, 5); |
结构体扩展
结构体构造函数
1 | typedef struct (uint offset) { |
使用方法:
1 | FILE f(123); |
结构体表达式
有时候结构体不是固定长度,而是根据字段的值来决定的
1 | typedef struct { |
甚至可以直接按照下面写法:
1 | typedef struct { |
当前地址
当前地址是下一个被定义变量的起始地址,初始为 0h,每定义一个变量,当前地址将会后移该变量的大小(通常用十六进制表示)
FTell() 函数用于获取当前地址,FSeek() 函数用于修改当前地址,FSkip() 函数用于移动当前地址,使用这些函数的组合
可以实现不按序读取数据。
使用 ReadInt()、ReadByte() 等读取函数配合 FTell() 等函数可以从当前地址开始读取一段符合类型的值,这几个函数不会影响当前地址,常在条件语句中
用作判断,例如:
1 | // 从当前地址开始读取一段 int 值,且这个值为 1 时,将会定义结构体变量 opt1,类型为 OPTION1 |
常用api
1 | void BigEndian() |
io函数
1 | void BigEndian()//设置大小头端 |
其他函数
1 | //书签 |
字符串函数
1 | //类型转换 |
工具函数
1 | //计算校验和 |
特别需要注意的是以下几个函数,对于解析偏移后的动态数据它们是不可或缺的:
FEof 判断当前读取位置是否在文件末尾
FTell 返回文件的当前读取位置
FSeek 将当前读取位置设置为指定地址
FSkip 将当前读取位置向前移动多个字节