“Dust: A Tale of the Wired West” is a game produced by Cyberflix in 1995. It is a game where the player has lots of conversations with colorful characters, collects inventory items and solves puzzles.
My goals is to better understand the intricacies of how games were made back in the day and diving into the nostalgia of one my favorite games.
In this blog I’d like to explore how these maps work, how the player navigates them, and how this information is stored in the game files.
Dust Game Files
First, here’s a recap of the types of game files Dust contains.
The Windows installation of Dust contains several executable files and game files of interest:
| Type | Description |
|---|---|
| Executables | Dust.exe DF.exe MoviePlay.exe |
| CST | Cast files containing the sprites of the characters and some game logic |
| FLT | Flat files containing puzzle logic |
| MOV | Movie files contain screen animations and still renders |
| PRP | Prop files contain sprites of props that are placed throughout the game |
| PUP | Puppet files contain characters dialogue, game logic and sprites of the characters |
| SET | Set files contain game locations and game logic. |
Today we’re going to focus on the SET files, which are used to store all kinds of information about the game’s locations.
A SET file is built up out of several types of blocks:
| Type | Description |
|---|---|
| HEADER | The header block contains the Color Lookup Table, the map grid, and the locations of the blocks below. It does not contain the locations of the frame blocks. |
| SCRIPT | Each set file contains a boot script-block and a script-block for each place you can stand in this map. |
| WAYPOINTS | The waypoints block contains a list of waypoints that are used to place items and characters in the game. They can also be used to as a destination for a character to walk towards. |
| FRAMELIST | The framelist block contains the locations of the frame blocks and information about which frames are part of which walking animation while traversing the map. |
| FRAME | A frame block contains image-compressed data that can be rendered to the screen. |
Map Layout
The layout of the map is stored at the bottom of the Header block.
All blocks in the Dust game files start with 4 bytes of block information: The block-ID and its size. Since we’re looking at the Windows version of the game files, all the data is stored in Little-Endian byte-order.
Below is an example of the data from APOTH.SET:
0000 0000 0000 0000 0100 0C00 085363656E65204131 00000000000000 22000000 |_____________Scene A1_______”___|
0100 0000 0100 0000 0000 0000 085363656E65204132 00000000000000 23000000 |_____________Scene A2_______#___|
0200 0000 0000 0000 0100 0C00 085363656E65204133 00000000000000 24000000 |_____________Scene A3_______$___|
0000 0100 0000 0000 0100 0C00 085363656E65204231 00000000000000 25000000 |_____________Scene B1_______%___|
0100 0100 0100 0000 0000 0000 085363656E65204232 00000000000000 26000000 |_____________Scene B2_______&___|
0200 0100 0000 0000 0100 0C00 085363656E65204233 00000000000000 27000000 |_____________Scene B3_______’___|
0000 0200 0000 0000 0100 0C00 085363656E65204331 00000000000000 28000000 |_____________Scene C1_______(___|
0100 0200 0100 0000 0000 0100 085363656E65204332 00000000000000 29000000 |_____________Scene C2_______)___|
0200 0200 0000 0000 0100 0C00 085363656E65204333 00000000000000 2A000000 |_____________Scene C3_______*___|
_________ ____ ____ ____ ____ __________________ ______________ ________
A B C D E F G H
| Column | Description |
| A | The X and Y coordinates of the scene (tile in the grid). |
| B | Boolean (1 or 0) which determines whether there is something to interact with in this scene. For example a door you can enter/exit, or something you can click on. |
| C | Unknown Boolean (1 or 0). I haven’t found any correlation between the grid tiles and this value. |
| D | Boolean (1 or 0) which determines whether this block is inaccessible. If the value is one, the player can’t access that tile in the grid. |
| E | Unknown value. This only seems to be filled when the block is inaccessible, but I haven’t found a correlation with anything. |
| F | The name of the scene. The first byte (08) tells us how long the string is. “Scene A1” is 8 characters long. |
| G | This is extra space for the name string to occupy if necessary. |
| H | Script block ID. Each scene in the map can have a script attached to it. These scripts hold game logic which allow players to interact with the map, such as: walking through doors, interacting with objects and moving to other scenes. |
With all this information, we can draw a diagram of the map where:
- Inaccessible blocks are white
- Accessible blocks are green
- Interactable and accessible blocks are blue
Below is the diagram of the the Yunni area underneath the mission, also known in the gamefiles as the Hub.

Plotting the Waypoints
The Waypoints block is quite straight forward. The number of waypoints is stored at offset 24 (offset 32 when including block ID and block size).
It is then followed by chunks of 50 bytes, that can contain 1 or 2 waypoints. They are divided quite strangely, because the first half is 26 bytes and the second half is 24 bytes. The second half only seems to be filled in larger maps.
| Offset | Size | Optional | Description |
|---|---|---|---|
| 2 | UINT16 | No | X coordinate of Waypoint 1 |
| 4 | UINT16 | No | Y coordinate of Waypoint 1 |
| 8 | UINT8 | No | Length of name string of Waypoint 1 |
| 9-25 | – | No | Name of Waypoint 1 |
| 26 | UINT16 | Yes | X coordinate of Waypoint 2 |
| 28 | UINT16 | Yes | Y coordinate of Waypoint 2 |
| 32 | UINT8 | Yes | Length of name string of Waypoint 2 |
| 33-49 | – | Yes | Name of Waypoint 2 |
As it turns out, in order to line up these coordinates with the grid we drew above, each tile needs to be 255×255 in coordinate space.
Anyone who has played Dust will quickly recognize which map they’re looking at below:

green=accessible
Unraveling the Framelist Block
The Framelist Block consists of chunks of 28 bytes. To know how many of these chunks there are, we need to get that information from the file’s Header block at offset 16 (offset 20 if you take the block-id and blocksize into account).
So, what does a chunk look like and what information does it hold? Let’s have a look at the Apothecary set file:
00000000: 0000 0100 0100 0000 0100 0300 0000 0100 0100 0000 0100 0300 2D000000 |_________________________-__|
00000028: 0000 0100 0300 0000 0100 0200 0000 0100 0300 0000 0100 0200 33000000 |_________________________3__|
00000056: 0000 0100 0200 0000 0100 0400 0000 0100 0200 0000 0100 0400 39000000 |_________________________9__|
…
00000112: 0000 0100 0300 0100 0100 0300 0000 0100 0300 0100 0100 0300 45000000 |_________________________E__|
…
_____________________________ _____________________________ ________
A B C
This Framelist block contains a total of 28 chunks of 28 bytes.
Block IDs (C)
In column C we see an incrementing list of block ID’s. In the example above 2D000000 converts to a decimal value of 45 and 33000000 converts to a value of 51. Each of these block ID’s is 6 apart.
In analyzing block 45 and block 51, we can quickly recognize that these are Frame blocks, because they start with 8 bytes of image dimensions that are familiar to us (264 and 512). Also the blocks in between are Frame blocks.
After some checking in different SET files we can assume that each each of these chunks of a Framelist block gives information about 6 frame blocks.
Analyzing the Frame Blocks
0000 0100 0100 0000 0100 0300
If we analyze column A, we see 6 numbers. The third and sixth numbers (marked in red) contain a value between 1 and 4. The other columns (marked in blue) contain values between 0 and another low number.
In order to make sense of what these numbers mean, we have to look at the six frames that correspond to this chunk. The six frames always contain:
- 5 animation frames, followed by
- 1 still frame of higher quality

Unfortunately I can not show you how the image compression of these frames works, because it's still owned by Cyberflix. All I can say about this topic is that it's quite complex and that it was developed in-house using huffman compression.
Location and Orientation (A)
0000 0100 0100 0000 0100 0300
In the case of the chunk above (block 45), the player is standing in the West-most accessible scene with coordinates (0,1).


So it’s clear that the first two numbers (in blue) mark the scene location of the six frames.
The fourth and fifth numbers (also marked in blue) mark the scene location after the animation has finished. In this case, since we’re not moving to another scene (square), both are (0,1).
The third and sixth numbers (marked in red) determine the orientation of the player. These numbers can only hold a value of 1-4:
- North
- South
- East
- West
In case the player doesn’t rotate, but moves from one scene to another, the chunk can look something like this:
00000112: 0000 0100 0300 0100 0100 0300 0000 0100 0300 0100 0100 0300 45000000 |_________________________E__|
Duplicate values (B)
00000112: 0000 0100 0300 0100 0100 0300 0000 0100 0300 0100 0100 0300 45000000 |_________________________E__|
_____________________________ _____________________________ ________
A B C
For some reason, the values in column B (grey) are always an exact copy of the values in column A. The only exception I found was in HUB.SET, which might be reusing animations, or because it teleports the player to the opposite side as part of a maze puzzle.
For now it’s a mystery.
Here is a screenshot of my script which parses all of this data and presents it in a more human readable way:

Interesting Finds
I was hoping to discover some areas in the game that were rendered out but unreachable through the game’s logic. I managed to find some chunks where the camera moves forward into the bookcases of the Chinese Curiosity Shop and seeing an empty Saloon is also quite strange. It’s not much, but hey, it’s something we weren’t able to see before.






Final Thoughts
I managed to draw the map and the waypoints about a year before I figured out how the Framelist blocks worked. I was not able to crack this part of the puzzle until I could decode and render the Frame blocks.
The way that the DreamFactory engine works really becomes a lot more clear once you see that they rendered out all these frames one by one, followed by the characters and props being drawn on top of them.
It was another fun puzzle and I was treated with the gift of being slammed through a book case and some ancient vases. All in all; not a bad day for Reverse Engineering.
Leave a comment