• If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • Stop wasting time looking for files and revisions. Connect your Gmail, DriveDropbox, and Slack accounts and in less than 2 minutes, Dokkio will automatically organize all your file attachments. Learn more and claim your free account.



Page history last edited by PBworks 13 years, 11 months ago


Hello, I'm rewriting Syndicate for modern PCs. I'm re-using all the original data from the DOS version so that I just distribute an .exe file and gamers use their own paid-for version of the game data files. Here's the progress I've made so far in decoding the game data formats.


General notes


Any data file that begins with the 3 characters "RNC" is compressed using the RNC-1 algorithm. Decompressing it and putting it back into the DATA folder has no effect on the game, Syndicate doesn't care whether its data files are compressed or not. This make messing about with them much easier.


In-game data formats (H*.*) can be modified when you're in the frontend menu and you will see the changes the next time you enter a mission. This really speeds-up turnaround time when messing with the data.


In-game data files tend to be called H*.*, and frontend menu data files M*.*, I guess this stands for "high" and "medium" resolutions, respectively.


Animations, how they work


Animations are built-up from three different files, HSTA-0.ani, HFRA-0.ani, and HELE-0.ani.


The first file HSTA-0.ani is an index, for each anim it contains the location of the first frame of that animation. I'm guessing that "sta" means "start".


The second file HFRA-0.ani contains information about a given animation frame. It points to the frame elements in HELE-0.ani, and it also points to the next frame in the animation.


The third file HELE-0.ani defines a single piece (i.e. one sprite) from an animation frame.






This file defines the map tiles. There are 256 64x48 tiles, and each tile is built up from 6 32x16 sub-tiles. Sub-tiles are arranged into tiles as follows:




File header

The first 6144 (256x6x4) bytes of HBLK01.DAT is the file header, this is an array of 4-byte integers. Each value gives the file offset to the data for a subtile.


So for example to draw map tile number 50, you go to index 300 (50 x 6, at 1200 bytes into the file), and this gives you the data offset for subtile 0, idx 301, for subtile 1, and so on.


Subtile data

Each subtile is organised as 16 groups of 20 bytes each. One 20 byte block represents a row of 32 pixels.


The first 4 bytes contain the transparency values for the 32 pixels, one bit (on/off) of transparency per pixel. 1 = transparent, 0 = solid. So for example, FF FF 00 00 is 16 transparent pixels followed by 16 solid pixels.


The remaining 16 bytes contain the colour information. Each pixel is 4 bits, which is a colour palette index. With 4 bits, only a maximum of 16 colours are possible.


The colour data is organised into bit-planes, least significant first. The first four bytes are all the "1" bits for the 32 pixels, the next four bytes are all the "2" bits, followed by the "4" bits and finally the "8" bits.


So imagine for example that the 16 bytes of colour data looks like this:

bitplane 1 bitplane 2 bitplane 4 bitplane 8
20 FC 03 FF 11 03 0C 00 20 00 00 00 2E C0 90 3C


To get the third pixel for example you need the 3rd bit from each bitplane:


plane 1 = 20 FC 03 FF = 00100000 11111100 00000011 11111111

plane 2 = 11 03 0C 00 = 00010001 00000011 00001100 00000000

plane 4 = 20 00 00 00 = 00100000 00000000 00000000 00000000

plane 8 = 2E C0 90 3C = 00101110 11000000 10010000 00111100


The resulting value for the 3rd pixel is 1101, or 13.




This file is an array of animation frame elements. Each element is a single sprite (see HSPR-*.dat and HSPR-*.tab). Since most things in the game are constructed from multiple sprites (e.g. heads, torsos, and legs are all separate things), several elements are needed for an animation frame.


There is no header to this file, it just gets straight into the data. Each element has the following structure:

struct HELE_entry


u16 sprite_location; // = sprite idx * 6

s16 x_offset, y_offset;

u16 mirror; // 1 = mirror the sprite, 0 = don't

u16 next_element_idx;


The X and Y offsets say how many pixels to move the sprite relative to the origin of the animation frame. Since most anim frames are rooted at the feet of a character, many of these offsets are negative values.


When next_element_idx is zero, then this is the last element in the anim frame.




This is the in-game font data. First 640 bytes are the header. 128x5 bytes. Header struct is:

struct Font_header


u16 dataOffset;

u8 width;

u8 height;

u8 ?? vertical offset maybe ??



The header index of a character is the same as its ascii value, which is why the first 32 entries are null.


When the data offset is zero, that means the character is not supported. When the data offset is -1, that means the char is supported but there's no data needed for

it (i.e. just jump "width" pixels to the right).


Data is read in little-endian (PC order) words, 1 bit per pixel. Word size is determined by character width, 1 byte for chars less than 9px wide, 2 bytes for wider chars (no char exceeds 16px wide). Data is null-terminated with a zero-word.


Two examples:

Char 0x22, double-quote.

data: 0x028C
width: 05
height: 04
voffset: 00

data: 48 D8 D8 90 00

48 = 00011000     **
D8 = 11011000  ** **
D8 = 11011000  ** **
90 = 10010000  *  *

Char 0x23, pound (hash) mark.

data: 0x0291
width: 09
height: 09
voffset: 00

data: 00 09 00 1B 80 3F 00 7F 00 36 00 7F 00 FE 00 6C 00 48 00 00

0900 = 00001001 00000000      *  *
1B00 = 00011011 00000000     ** **
3F80 = 00111111 10000000    ******* 
7F00 = 01111111 00000000   *******
3600 = 00110110 00000000    ** **
7F00 = 01111111 00000000   *******
FE00 = 11111110 00000000  *******
6C00 = 01101100 00000000   ** **
4800 = 01001000 00000000   *  * 




This file contains an array of animation frames.


There is no header to this file, it just gets straight into the data. Each element has the following structure:

struct HFRA_file_entry


u16 first_element_index;

u8 width, height;

u16 is_first_frame;

u16 next_frame_idx;


The "first_element_index" is an index into the HELE-0.ani file.


The "next_frame_idx" points to the next frame in the animation. If this "animation" is just a single static frame, then this index will actually point straight back to this frame. For animations with several frames in a loop the last frame will point back to the first. No idea yet what happens if the animation isn't looping.


The "is_first_frame" is just my guess. It might not actually be this, it just seems that way. It may be used for something else, and just happens to only be set on the first anim frame. For example it might be a flag to say whether or not the anim loops.




These are the in-game palettes. Each palette contains 256 entries, but in the game only the first 16 are used.


Each entry consists of 3 bytes, one each for red, green, and blue intensity values.


Each intensity value is only six bits, not the full eight, so the maximum value is 63 (0x3f). To scale an intensity value up to a full eight-bit byte, multiply by 255 then divide by 63. Simply multiplying by 4 is not good enough, the values will be slightly too dark.




These files contain the data for the in-game sprites (apart from the map tiles, which are in HBLK01.dat). There is no header, the corresponding .TAB file serves that purpose.


Data is organised into chunks of 5 bytes. Each 5-byte chunk represents 8 pixels in a row. These chunks work in the same way as the 20-byte chunks in the HBLK01.dat file, i.e.:


byte 1 = transparency bits for the 8 pixels, 1 = transparent, 0 = solid.

bytes 2-5 = colour values, arranged into 4 bitplanes; least significant first.


All sprites are 16, 32, or 64 bytes wide (apart from the zero-width .TAB entries which can be safely ignored). So that means 2, 4, or 8 of these 5-byte chunks per row.


Sprites specify data for the full width and height, even when there are 8 or more transparent bytes at the end of a line, or when there are transparent lines at the bottom of the sprite.




This file acts as an index into the corresponding .DAT file. It is an array of entries with the following structure:

struct HsprTabFileEntry


u32 dataOffset;

u8 width;

u8 height;


The "dataOffset" is an offset into the corresponding .DAT file, to say where the data for this sprite starts.




This file is a simple array of 2-byte indices into the HFRA-0.dat file. Each one of these entries can be thought of as a complete animation, because the HFRA entry it points to is the first frame, which then points onward to the next frame, and so on.


A brief note on experimentation:

The first value (after the initial 0000) is 0x0179. This value is the "syndicate agent standing still facing down/left) animation. This is useful to know because it's really easy to mess around with it and see the results, just load up a new game on mission 1, and then get an agent to face down and left.


A few entries later on is one with the value 0x185. This is the same thing (agent facing down/left) but is the walk cycle, so you can use it to experiment with multi-frame animations.




These files specify how to lay-out the in-game maps. Using this in conjunction with the HBLK01.dat file, you've got enough information to be able to create a level viewer.


The game maps are 128 tiles wide, by 96 tiles deep, by 12 tiles tall.


The header is an array of 12,288 (128x96) 4-byte integers. Each entry is an offset into the file. The 12 bytes beginning at that offset are the indices for the 12 tiles (stacked vertically, from bottom to top) making up that map square.




Simple one this, 8 bits per pixel, 32 x 1024, comprising of 40 32x32 images.


Images are used for the corporate logos in the menus.


Not yet decoded


  • COL01.DAT
  • MFNT-0.DAT
  • MFNT-0.TAB
  • MSPR-0.DAT
  • MSPR-0.TAB

Comments (0)

You don't have permission to comment on this page.