作者在这些逆向工程笔记中是什么意思?

逆向工程 文件格式
2021-07-06 04:24:21

我正在尝试为 DOS 游戏中使用的旧视频格式Psygnosis SMV 视频格式编写解码器,但我很难理解图像解码过程,特别是本节:

Macroblocks drawing

Macroblocks are stored in the following format:

 u8 pixels[16 * num_mblocks]
 u4 nibbles[num_mblocks]

Size of pixels[] is equal to ST chunk's nibbles.
For each macroblock draw it by indexing its pixels by nibbles.
First nibble stored in top 4 bits of byte.

以下是我尝试解码的帧的属性:

  • 图像宽度 = 320
  • 图像高度 = 192
  • 宏块宽度 = 16
  • 宏块高度 = 16
  • 小口 = 3840
  • 以字节为单位的帧大小 = 34560

因此,根据这些,我计算了以下值:

num_mblocks = nibbles / 16 = 3840 / 16 = 240 macroblocks

further checking:
(image width / macroblock width) * (image height / macroblock height)
= (320 / 16) * (192 / 16)
= 20 * 12
= 240 macroblocks

第一个问题:

的大小u8 pixels[16 * num_mblocks]确实是 3840 字节,但是u4 nibbles[num_mblocks]应该是什么大小240 字节或一半,因为类型是u4

第二个问题:

当我除以frame size in bytes数量时,macroblocks每个宏块只有 144 个字节(34560 / 240 = 144),但对我来说这与它应该的相去甚远,我想我在某个地方错了。

第三个问题:

作者写道:

对于每个宏块,通过按半字节索引其像素来绘制它。

但这究竟是什么意思?

问题

你能解释/阐明一个人应该如何解码一帧吗?

1个回答

注意:这是一个假设,可能正确,也可能不正确;我还没有针对任何真实文件进行测试。

文件格式的创建者似乎一直在努力节省一些空间。他们想要编码 256 种颜色(“编码 8 位调色视频”),因此他们需要每个像素一个字节。然而,屏幕的某个较小区域很可能重复包含相同颜色的像素。所以,我想说每个宏块只能包含 16 种不同的颜色,可以用 4 位/一个半字节表示。

u8 pixels[16 * num_mblocks]看起来每个宏块都有 16 个像素定义,它们是通用调色板表的索引,每个宏块需要 1 个字节。接下来是每像素一个半字节,它是pixels.

因此,例如,一个宏块的像素将有 16 个字节,它们是调色板的索引;可能看起来像这样:(对不起,有些颜色名称;我用完了适合 5 个字符的名称......)

+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
+  1  +  2  +  3  +  4  +  5  +  6  +  7  +  8  +  9  +  A  +  B  +  C  +  D  +  E  +  F  +
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
| red |green|blue |yellw|magnt|cyan |grey |black|orang|gold |aqua |azure|ivory|plum |wheat|
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----

接下来,您需要每个像素一个半字节,这是该表的索引。所以字节 CA 53 2D 将代表 6 个像素,分别是天蓝色、金色、洋红色、蓝色、绿色和象牙色。

因此,对于 256 个像素的宏块,像素表需要 16 个字节,像素需要 256/2=128 个字节。总计为您计算的 144。u4 nibbles[num_mblocks]可能是错误的,应该是u4 nibbles[num_mblocks*pixels_per_mblock]