We just moved to a different server. Please be patient until all files and pages are restored and the MediaWiki software has been updated. Thank you
The Fourth Generation
The Fourth Generation (4gen) is a small side scroller for DOS from 1996. The only common file types used in this game are FLIC and AMF. Everything else is proprietary.
These are uncompressed archive files. The game uses basically just one DCF in which all the game data is stored. It contains no file names, so the game usually references to the "files" via indexes. DCF stands for "D'India software Chunk File" as seen in the file itself. This string is not part of the file format but is an actual chunk of 27 bytes length, found at the very first offset. There are no lengths saved with each chunk. Instead, the length of a chunk is calculated from the offset differences. DCF has the following structure:
word num_files dword offsets byte data
Offsets are absolute, meaning the first offset is 2 + num_files * 4 instead of 0. Because num_files is 16 bits, there's a maximum of 65536 chunks possible to store inside a DCF. Internally, the games uses different offset bases for different "groupings". For example, sprite offset # 0 is actually DCF offset # 175.
Bitmaps are stored in a proprietary format, the header is 8 bytes. It can contain an optional palette as well as an optional collision shape used for enemies, weapons, obstacles etc. It has the following structure:
byte zero byte pal_len word width word height byte blend_mode byte coll_data_incl byte coll_data //optional byte palette //optional byte data
The first byte is always zero. pal_length is the number of color triples used for the local palette. Width and height are the bitmap dimensions in pixels. The blend_mode is used to combine the bitmap with the background in different ways (see below). When coll_data_incl is set to 1 the collision shape follows directly after the header. Its vertical dimension is equal to height but the horizontal dimension is width / 8, always rounded UP to ensure that objects smaller than 8 pixels still have one pixel of collision data. Then follows the local palette, which is 3 * pal_length bytes long. NOTE: The first index of this palette is 1 and not 0. Index 0 is used as background (or transparent) color and is not affected by this palette.
blend_mode can be one of the following:
- 1 = completely opaque
- 2 = pal index 0 is transparent
- 4 = semi transparent, colors are blended additively instead of linear
- 5 = refraction (no coloring takes place)
- 6 = heightmap
At the moment, I have no idea how the local palette is mapped to the global palette. The game runs in 8 bit graphics mode of course (256 colors), so the bitmaps can't use their local palette without some kind of index remapping!
The definitions for the different background scenes are arranged in one chunk. Each scene has a length of 4262 bytes, containing layer properties and object placement:
byte name_len char name byte ? byte ? byte water_fx word color_correction SC_LAYER layers
name_len is the length of the scene's name, but the actual name field has a fixed size of 19 bytes. When water_fx is set to 1, the whole screen is distorted with a sine-wave animation – only used in the underwater scene. All colors of the global palette are multiplied by the color_correction vector. The last field consists of 6 layers which contain information about the images used and how to display them. The SC_LAYER struct contains the following:
byte enabled word ? // always 0 smallint y_pos // or FOV in 3D mode word scroll_speed word type word eye_height // 3D only word y_clipping // 3D only word ? // always 0 word images word num_img SC_OBJ objects
Only when enabled is set o 1, the layer becomes visible. y_pos has two different meanings: for normal (flat) images it means the vertical position of the image in screen pixels. But when 3D mode is used, this parameter is the field of view of the texture. scroll_speed defines how fast the layer scrolls to the left:
- 1 = 4 px/frame
- 2 = 2 px/frame
- 3 = 1 px/frame
- 4 = 2 frames/px
The type field defines the appearance of the layer:
- 0 = flat
- 1 = ground (3D)
- 2 = clouds (3D)
- 4 = heightmap (3D)
The eye_height parameter defines how far away the texture is from the "camera" in Y direction. y_clipping is the vertical screen position (in pixels) at which the texture plane is clipped. It is automatically measured from top (clouds, type = 2) or bottom (ground, type = 1). The images array contains the indexes for the images that make up the layer. The image sequence of every layer is looped infinitely. The number of images used in a layer is defined by the num_img parameter. Every background image has the same fixed horizontal dimension of 320 px. If an invalid index is given, there's still a 320 px wide gap to the next image. The last field is an array of 18 optional backdrop objects, which support animations and can be placed at arbitrary positions (This feature is actually only used for the space scene, with the rotating space station at the beginning). The SC_OBJ struct contains the following:
word offset word x word y word image_idx word frames word ? word ? word frame_rate
offset specifies the "slot" at which the object is placed. A "slot" has a fixed width of 320 px, meaning the value of this parameter is actually multiplied by 320. The position of the image relative to the slot is given by the x and y parameters. The image_idx is the first frame of the animation, or the only frame, depending on the frames parameter. If this is >0 then the subsequent indexes after the image_idx is used for the animation frames. That means that the images must be arranged accordingly inside the .DCF file! And finally, the frame_rate defines the speed of the animation.
All objects are defined in one chunk. One object definition is 68 bytes long:
byte name_len char name word logic smallint velocity word img_down word img_up word img_level word frames word frame_rate word wpn1 word wpn2 word health word collision_dmg word ? // always 2 word explosion word turn_dist word ? word ? word ? word ? byte ? byte powerup word muzzle_x word muzzle_y word nozzle_x word nozzle_y word ?
The logic is the behavior of the object. velocity is the movement speed, which can also be negative, if an enemy comes from behind (left screen side). img_down, img_up and img_level are the images used for the 3 states of vertical movement (up, down, or not at all). This does not apply to every logic. The frames parameter is the number of subsequent frames used for the animation (if > 0). The first frame is img_level in most cases. The enemy's primary and secondary weapon number is defined in the wpn1 and wpn2 fields respectively. health – no comment. collision_dmg is the amount of damage inflicted to the player when he collides with the object. The exploson parameter specifies the type of explosion after an object is destroyed. It affects the size and the number of explosion sprites as well as the number of debris pieces and the appearance of the white shockwave-like circle for bigger explosions. If an object can change its direction on the x-axis, the turn_dist parameter is the position in screen pixels at which the object starts to change its course. Does only apply to a handful of logics. If the powerup byte is set to 20, an energy cell is left behind after the object is destroyed. The player can pick up the cell to slightly increase the shield's strength. The two muzzle parameters are the x and y positions (in pixels) from the top left corner of the object's image at which the projectiles are fired. The same goes for the nozzle parameter, which specifies the x and y position of the jet engine.
Every definition block has a length of 55 bytes:
byte name_len char name smallint velocity word rot_speed word image_idx word frames word frame_rate word logic word damage word impact_type word interval1 word interval2 word energy word ? // always 2 word ? word ? smallint vel_vertical word ? byte ? // always 0 word ? // always 65535
velocity is the forward speed of the projectile. rot_speed defines how fast the projectile changes the direction to follow the target (only used for missiles and the "stalker" weapon). As always, image_idx is the .DCF index of the image to use and frames is the number of animation frames, which are played back at the rate defined in frame_rate. NOTE: some weapons use the frame parameter actually not as animation but as different images for different moving directions! logic is the actual weapon type. The number of projectiles per shot, the movement pattern and the ability to seek a target are influenced by this value. The value of damage is inflicted to the target and impact_type is the explosion animation of the projectile. interval1 is the number of frames between each shot, interval2 is the number of frames between a burst of shots. The value of the energy parameter reflects the energy consumption per shot. Some weapons fire 3 projectiles at once that are traveling not just straight ahead but also up and down as specified with the vel_vertical parameter.
Every level file (chunk) is 20597 bytes long:
word remapping byte availability word scene word music word gravity byte upgrade word flic word ? word ? word ? word events
It consists of 4 sections. The first one is an array of words where each one is an index which refers to a bitmap that is either processed or ignored during loading. If the value of an index is 65535 the bitmap is ignored. If the value is between 0 and 3, the bitmap's palette is mapped to the global palette in different ways. NOTE: I have not yet discovered how the actual processing works. In my tests, the visual differences are minimal but to me it seems as if the value specifies different quantization algorithms to drop a few colors of a bitmap's palette in favor for other bitmaps to gain a bit of quality. But until I know more, this has to be considered wild speculation! The fixed length of that array becomes a problem if someone would want to mod the game and add more content to it (instead of overwriting existing chunks) because even if the DCF archive can hold up to 65536 files, the above mentioned array can only manage 2000 images without manipulating the game executable directly.
Then follows an array of 200 bytes to make certain items available for the player to upgrade the ship with. Only weapons are affected by this, all other items are always available. The following list shows which byte # makes which item available by setting its value to 1.
- 117 = Twin Cannons (unused)
- 118 = Pulse Cannons
- 119 = Velden arrow
- 120 = Blue Daggers
- 121 = Tempest
- 122 = Sonic Wave
- 123 = Helix
- 124 = Laser
- 125 = Stalker
- 126 = Photon Pulse
- 127 = Scorpion Missile
- 128 = Rage Missile
- 129 = X-29 Missile
- 130 = Flux Beam
- 131 = Disintegrator (unused)
The next 15 bytes contain some information about the level: scene is the index of the background scene and music is the index of the AMF file to play. The gravity parameter has only an effect on debris pieces. If it's 0 there's no gravity and the pieces drift away with their initial speed. If this value is 1 then gravity is applied to them. Before each level, the player has the ability to upgrade the ship, but only if this parameter is set to 1. The flic parameter is the number of the FLIC file to be used as background animation for the upgrade screen. 6 being the hangar animation and 7 the space flight animation. The game crashes when an invalid number is given.
The last section holds the list of events. An event consists of an identifier and up to 4 parameters. All parameters, including the identifier, are two bytes long. Events are executed one after another as specified in an event's delta parameter. This is the time to wait before the next event is executed. There are at least 18 event types. NOTE: I haven't tested everything in-depth yet so the following list is based pretty much on what I could make out on first sight! That means the list is far from perfect.
00 01 object x y delta
The most common event, used to spawn an object. The object parameter refers to an index inside the object definition chunk. x and y are the coordinates where the object is created and the delta parameter is the time to wait before the next event is executed. A value of 0 executes the next event immediately. Most events seem to have a delta parameter but there are too many unknowns to be really sure about it.
00 02 unknown1 unknown2 unknown3
00 03 unknown1 unknown2
00 05 delta
Suspends the processing of events for the given time.
00 07 speed delta unknown1 unknown2
Sets the scrolling speed. When speed is 0, the scrolling stops. The initial value is 4. This is always the first event in the list but it's not a requirement to be the first.
00 08 unknown
Can be found at the end of the list, just before [00 17]. The unknown parameter is always 0.
00 09 unknown
Attachment. This event attaches the object, that is spawned by the following [00 01], to the object, which was previously spawned after a [00 0A]. In this case, the coordinates of the following [00 01] are relative to the "parent" object. Objects spawned this way don't move on their own. They're attached to the parent object and move together with it.
00 0A unknown
Parenting. This event marks the following [00 01] as "parent" for further objects, which are in turn marked as "children" by a preceding [00 09].
00 0B unknown delta
00 0C object delta
00 0D unknown delta
The only event without parameter. It can only be found after a [00 0C] event.
00 13 offset delta
Jumps to the event specified by the offset parameter. The offset is in bytes and NOT in words and is relative to the start of the event list. 0 is the first entry. This is used to loop a section of the list while a boss fight takes place.
00 14 unknown1 unknown2 unknown3 unknown4
00 15 unknown1 unknown2 unknown3
00 16 unknown1 unknown2
00 17 unknown
This marks the end of the event list and thus, the end of the level. The unknown parameter is 0 most of the time. This event goes "hand in hand" with [00 08], that COULD mean that these two blocks are actually just one, where the "00 17" is just a parameter inside event type [00 08].
0A 00 unknown1 unknown2
The space after the list is padded with zeros until the chunk is 20597 bytes long. The gameplay takes place in screen space and NOT in world space. The player as well as every other object does actually not move through the level. Instead, the illusion of movement is only realized through the background scene. Objects are just spawned left and right of the screen, like in a shooting gallery.
Headerless, uncompressed RAW files in 8 bit unsigned PCM format with a sample rate of 11 kHz.
The music is in Scream Tracker 3 format, converted to AMF as required to work with DPMI, an interface which is also used by other DOS applications back in the day…
All the short pre-rendered cut scenes are Autodesk Animator files…
Beta / Cut / Unused content
- Originally, it was planned to have mission introduction messages before each level. There are text files for each mission but only the first 5 are finished. The remaining 6 are just copied over from the 5th.
- Furthermore, there was a boss planned for level 5, "a high powered super tank and its escort convoy" according to the unused text.
- There is an unused picture of a person (very likely one of the developers) which was intended to be shown on the credits screen.
- A handful of sprites, some of them even animated, can be found but are never used in the game.
- And a few weapons, although fully functional, were cut from the final game.