Ideally, while the project files holds the game information in the form that is the most convenient by the Editor used by the game developer, the game data represents this information in the most convenient form for the Engine.
Building a game is to transform information that describes the game to the form convenient for the Engine. This document describes how a platform agnostic AGS game is built.
At the time of writing, some relevant information is in different source code files, mainly:
Editor/AGS.Editor/BuildTargets/BuildTargetDataFile.csEditor/AGS.Editor/DataFileWriter.csEngine/main/game_file.cppCommon/game/main_game_file.cppCommon/ac/gamesetupstruct.cpp
Many people know an AGS game as simply the following:
game.exe
audio.vox #optional
This game executable is roughly (but not exactly!) the same as:
acwin.exe
game.ags
audio.vox #optional
Where acwin.exe is the engine and game.ags is the game, and audio.vox is
the speech assets that may or may not be there.
To make it easier in this document, we are going to ignore platform specifics
in the engine and consider only the data file game.ags and external assets like
audio.vox. So in this document, when we talk about an AGS game, this is what is
on mind.
A stream is a sequence of bytes with a beginning and an end, where the beginning and end may or may not match the beginning and end of a file. We can define an order in which bytes are stored, an assign meaning to ordered groups of ordered bytes to serialize or deserialize information.
[[0 1 [2 3] 4] 5 6 7]
if we consider 0-7 above as each a byte, we can consider any opening and closing bracket as a stream
A stream can then be defined in this way as holding:
- Offset, the position where the stream starts in a group of sequential bytes
- Length, which tells us the end of the stream
- Byte array, the actual bytes in the stream
MultiFileLib is a library that is replicated in both DataFileWriter on the Editor, and on the Common library in the Engine, that enables assigning meaning to a group of bytes in a file as a stream with the following information:
- Filename, used to identify the group of bytes;
- Offset, the location of this stream in the biggest possible stream of the file.
- Length, the byte size of this stream;
- Datafile, the bytes of this stream;
We can use MultiFileLib to abstract the contents of the game.ags file in a streamed
filesystem (note: if there's a proper name here, please some fix this).
We can assume a file in the regular filesystem with name "name.extension" holds
the same "name.extension" and same bytes in it's resulting stream in the streamed
filesystem. Because of this, I am not going to make a distinction from the filesystem
and streamed filesystem, unless required to reinforce a point.
In the streamed filesystem that the AGS Engine reads to run a game, it can find files that define logic to run or logic states and also asset files, which do not define logic by itself, mostly image and sound files.
- Initial state of game objects
- Initial state of game rooms
- Bytecode to run in the script engine
- Metadata for the script engine
- Game sprites
- Game audio
- ...
Logic files and asset files have no difference between themselves that are not specifics on how their bytes should be interpreted, so they can all be considered files in the streamed filesystem.
I am going to arbitrarily assign a category as Asset or Logic to group files read by the engine here. We can assume that there are no audio, image (including font files) mixed in the logic files, and that there are only references there, unless otherwise noted.
The Game DTA file, named currently as game28.dta, has most of the logic information
required for an AGS game. The following is included in order, with examples or comments:
- Game Metadata
- Game file signature,
"Adventure Creator Game File v2" - Game data version, integer identifier of this data format
- AGS Editor version,
"3.5.0.24"
- Game file signature,
- Game options and initial setup data
- AGS Game options (mostly configured in Global Settings)
- AGS
gamevariable
- Initialize GUI IDs
- Additional game settings
- Save game extension
- Seve game directory
- AGS Font configuration (not the actual font)
- Sprite alpha channel setting (for each sprite)
- Inventory Item information
- Number of items
- Data: Description, ID of Image, ID of CursorImage, Hotspot, ...
- Cursors information
- Number of Cursors
- Data: ID of Image, Hotspot, ...
- Compiled scripts (bytecode and metadata)
- Global script
- Dialog scripts
- Other scripts
- View information
- Number of views
- Loop information per loop, frame information per frame
- Characters information
- Number of Characters
- All information required for a character (it's a lot!)
- GUI information
- Number of GUIs
- All information related to each GUI control per GUI and required to initialize each GUI
- Plugin related information
- Custom properties information
- Custom properties for Characters
- Custom properties for Inventory Items
- Dialog names
- AudioClip Type information
- Number of AudioClip Types
- Data: AudioClip Type max channel, cross fade configuration, ...
- AudioClip information
- Number of AudioClips
- AudioClip metadata
Room .crm files are stored as room*.crm files directly, and they include the compiled rooms
script objects.
All sprites are stored contiguously in a file and it's index is stored in separate file.
sprindex.dat, the sprite index file- it holds the sprite IDs and the byte offset of each sprite in the the sprite data file and their length in bytes.
acsprset.spr, the actual sprite data- sprites are stored contiguously as bitmaps.
Audio files are stored with the same names used in the AudioCache directory, and
they can also optionally be stored outside the game.ags in a audio.vox file.
Fonts are stored as agsfnt*.ttf or agsfnt*.wfn depending of the original format
of the font, with the names including a number index that will be corresponded
to the index of the font metadata stored in the Game DTA file.
Additionally, an AGS game data holds video files in flic.fl? and *.ogv, and
a loading image for the game boot as preload.pcx.
The project files can be changed with less regard to form, as long as the tool used to build the game (the AGS Editor) accommodates this change and still outputs the files compatible with the Engine. This is why the project file and Editor versions are different than the game dta versions, allowing easier management of changes.
This step simply copies the audio files from their original sources to a flat
directory named AudioCache/ at the root of the project.
List of audio files with any name and supported extensions and ID to use per file, and the audio files.
The audio files in a flat directory with names as au0X.Y, where X is the original
audio ID as hexadecimal with fixed 6 digits in size and Y being the original file
extension.
All game dialogs.
Script files
*.asc
*.ash
scipt files generated from dialogs
Compiles preprocessed Script files to script objects
All script objects and data to initialize and describe all game objects and options
game28.dta
This step receives a list of files and packs the files listed in the game DataFile, using the MultiFileLib.
game28.dta # game DTA file
room*.crm # at least one room is required
sprindex.dat
acsprset.spr
au0*.* # optionally, for audio files, may be stored outside in a .vox file
agsfnt*.(ttf|wfn) # font files, may or may not exist, at least one font file is required.
preload.pcx # optionally
flic.fl? # optionally, for videos
*.ogv # optionally, for videos
game.ags