ObjDesc format
ObjDesc is a proprietary graphics format used in Pokémon Ranger. The game supports a lot of ObjDesc types, however, all of them share the same base format as the types only differ in usage context. The graphics consist of sequenced animation frames, sprite frames and their respective cells, raw tile data and color palettes.
Structure
- Compressed? Inconsistent
- Wrapped in flatbuffer? Yes
- Uses pointer fix list? Yes
A flatbuffer may contain more than one ObjDesc block that are loaded depending on use. Usually, all blocks refer to the same raw tile and palette data.
Header
Each ObjDesc entry starts with this 16 bytes structure:
| Offset | Type | Name | Description |
|---|---|---|---|
0x00 |
int |
offAnimInfo |
Offset to AnimationInfo |
0x04 |
int |
offFrameInfo |
Offset to FrameInfo |
0x08 |
int |
offTileInfo |
Offset to TileInfo |
0x0C |
int |
offPaletteInfo |
Offset to PaletteInfo |
AnimationInfo
The AnimationInfo block is 8 bytes. It contains the offset to the very first Animation offset and the number of Animation entries.
| Offset | Type | Name | Description |
|---|---|---|---|
0x00 |
int |
offAnims |
Offset to list of Animation entries |
0x04 |
int |
numAnims |
Number of Animation entries |
It is worth noting that the game interprets a number of 0 Animation entries as 1.
Animation
An Animation is a sequence of animation frames. It is a linked list of offsets to individual AnimationFrame entries. A null offset denotes the end of an animation. Therefore, each animation has a variable size, but the minimum size is 4 bytes.
AnimationFrame
An AnimationFrame is a sequence of "micro instructions" that control how to display a frame on the screen. Usually, a micro instruction is 4 bytes and has the same structure. Thus, an individual AnimationFrame has a variable size, though the minimum is 2 to 4 bytes. The structure of these entries looks like this:
| Offset | Type | Name | Description |
|---|---|---|---|
0x00 |
byte |
type |
Instruction identifier |
0x01 |
bool |
useParam |
Uses parameter? |
0x02 |
short |
param |
Parameter (read if useParam is true) |
The following instruction types can be found in the game.
| ID | Description | Parameter | Notes |
|---|---|---|---|
0x01 |
Frame duration[*] | Duration in time frames | After duration is over, the game goes to the next AnimationFrame in line. If the end of the list is reached, it loops back to the first AnimationFrame. |
0x02 |
Load frame | Frame index | Draws the Frame specified by its index onto the screen. |
0x03 |
Horizontal shaking | Unknown | |
0x04 |
Vertical Shaking | Unknown | |
0x05 |
Unknown | Unknown | |
0x06 |
Unknown | Unknown | |
0x10 |
Unknown | Unknown | |
0x20 |
Unknown[*] | n/a | |
0x50 |
Cancel animation[*] | n/a | Cancels the Animation without looping to the beginning. |
[*] Marks the end of a micro instruction list.
FrameInfo
The FrameInfo block is 0x8 bytes. It contains the offset to the very first Frame and an unknown value that still needs to be figured out.
| Offset | Type | Name | Description |
|---|---|---|---|
0x00 |
int |
offFirstFrame |
Offset to first Frame entry |
0x04 |
int |
unkFrameInfo |
Unknown |
Frame
A frame is a fully-composed sprite consisting of one or more smaller frame cells. Each Frame is 8 bytes.
| Offset | Type | Name | Description |
|---|---|---|---|
0x00 |
int |
offFrameCells |
Offset to first FrameCell entry |
0x04 |
int |
numFrameCells |
Number of FrameCell entries |
FrameCell
A frame cell contains information how to load a tile from the tile block, which colors/palette to use and how to draw it onto the screen. Each FrameCell is 12 bytes.
| Offset | Type | Name | Description |
|---|---|---|---|
0x00 |
short |
tileIndex |
Tile index |
0x02 |
byte |
dimWidth |
Tile width[*] |
0x03 |
byte |
dimHeight |
Tile height[*] |
0x04 |
short |
offPalette |
Palette offset |
0x06 |
byte |
flip |
Flip bits (bit 0 = horizontally, bit 1 = vertically) |
0x07 |
byte |
unk7 |
Unknown (always 0?) |
0x08 |
short |
offX |
X offset on screen |
0x0A |
short |
offY |
Y offset on screen |
[*] Allowed values are 0 to 3. The values are interpreted as:
- 0 = 8 pixels
- 1 = 16 pixels
- 2 = 32 pixels
- 3 = 64 pixels
TileInfo
The TileInfo block is 0x8 bytes. It contains the offset to the very first Tile and the size of the raw tile block.
| Offset | Type | Name | Description |
|---|---|---|---|
0x00 |
int |
offTiles |
Offset to first Tile entry |
0x04 |
int |
rawTilesSize |
Size of raw tile data |
Tile
A tile holds information on where raw tile data is found in the tiles block. The information includes the offset to the raw tile data and the bitmap size in bytes. The actual dimensions of the tile are not specified here. Each entry is 8 bytes.
| Offset | Type | Name | Description |
|---|---|---|---|
0x00 |
int |
offTile |
Offset to raw tile data |
0x04 |
short |
bitmapSize |
Bitmap size in bytes |
0x06 |
short |
offTileCopy |
Copy of raw tile offset |
PaletteInfo
The PaletteInfo block is 8 bytes. It contains the offset to palette data and an unknown value that still needs to be figured out.
| Offset | Type | Name | Description |
|---|---|---|---|
0x00 |
int |
offPalette |
Offset to palette data |
0x04 |
int |
unkPaletteInfo |
Unknown (always 0x200?) |
The palette data contains at least one palette and each palette contains 16 colors. The first color is always interpreted transparent. Colors are represented in BGR555 format (16-bit). The following pseudocode shows how to retrieve the red, green and blue components of a BGR555 color:
b = (bgr555 & 0x7C00) >>> 7;
g = (bgr555 & 0x03E0) >>> 2;
r = (bgr555 & 0x001F) << 3;
Note: >>> is unsigned right shift in Java.
Contents of pointer fix list
The list should contain offsets to the following fields:
- one for each
Tileentry'soffTile - one for each
Frameentry'soffFrameCells - one for each
Animationentry's sub offsets excluding null offsets (= 0) - one for each entry in the
Animationlist offAnimsoffFirstFrameoffTilesoffPaletteoffAnimInfooffFrameInfooffTileInfooffPaletteInfo
ObjDesc types
The following types can be found in the game:
| Name | Description |
|---|---|
abilityObjDesc |
|
ability_bodyObjDesc |
|
ability_neckObjDesc |
|
ability_sebireObjDesc |
|
ability_standObjDesc |
|
ability_stand_bodyObjDesc |
|
ability_stand_neckObjDesc |
|
ability_stand_sebireObjDesc |
|
ability_stand_tailObjDesc |
|
ability_tailObjDesc |
|
action2ObjDesc |
|
action3ObjDesc |
|
actionObjDesc |
|
attack1ObjDesc |
|
attack1_standObjDesc |
|
attack2ObjDesc |
|
boroObjDesc |
|
breakObjDesc |
|
catchObjDesc |
|
cut1ObjDesc |
|
cut2ObjDesc |
|
damageObjDesc |
|
dislikeObjDesc |
Annoyed Steelix |
dododamageObjDesc |
|
dodoriostandObjDesc |
|
dodoriowalkObjDesc |
|
dodostandObjDesc |
|
dodowalkObjDesc |
|
fallObjDesc |
|
flyObjDesc |
Flying |
fly_standObjDesc |
|
hoverObjDesc |
|
ladderObjDesc |
|
ladder_downObjDesc |
|
ladder_upObjDesc |
|
landingObjDesc |
|
laplacestandObjDesc |
|
laplacewalkObjDesc |
|
pose2ObjDesc |
|
poseObjDesc |
|
pose_koObjDesc |
|
pukaObjDesc |
|
rideObjDesc |
|
runObjDesc |
|
shakeObjDesc |
|
sleepObjDesc |
Sleeping Steelix |
stand2ObjDesc |
|
standObjDesc |
Idle |
stand_abilityObjDesc |
|
stand_attack1ObjDesc |
|
stand_bodyObjDesc |
|
stand_flyObjDesc |
|
stand_neckObjDesc |
|
stand_sebireObjDesc |
|
stand_tailObjDesc |
|
stand_walkObjDesc |
|
walkObjDesc |
Walking |
walk_standObjDesc |
