GM format

From ENIGMA
Jump to navigation Jump to search

For notes on how to read this format, and other information, please see Format info.

Game Maker 7's GMK files used an encryption/obfuscation which we have documented at GMKrypt.

Base Format

File format identifier (1234321)
Format version (530/600/701/800)
Game ID (0-100,000,000, Random*)
(16 bytes) DPlay Game GUID (Randomize as per the Game ID)

GM version needed for Game Settings (530/542/600/702/800)
<800+> Length of Zlib Game Settings { Zlib Game Settings }

<800+> GM version needed for Triggers (800)
<800+> How many Trigger ID's there are (0)
{
 Length of ZLib Trigger { ZLib Trigger }
}
<800+> (double) Last time Triggers were changed

<800+> GM version needed for Constants (800)
<800+> How many Constants there are (0)
{
 Length of Name { Name }
 Length of Value { Value }
}
<800+> (double) Last time Constants were changed

<Sounds, Sprites, Backrounds, Paths, Scripts,
 Fonts, Timelines, Objects, Rooms>
GM version needed for Resource (800)
How many Resource ID's of this type there are (0)
{
 <800+> Length of Zlib Resource { Zlib Resource }
}

ID of last instance placed (100000)
ID of last tile placed (1000000)

<700+> GM version needed for Included Files (620/800)
<620+> How many Included Files there are (0)
{
 <620 only> See 'Included Files' in 'Resource Formats', no ZLib compression
 <800+> Length of ZLib Included File info { ZLib Included File info }
}

<700+> GM version needed for Extension Packages (700)
<700+> How many Packages there are (0)
{
 Length of Package Name { Package Name }
}

GM version needed for Game Information (430/600/620/800)
<800+> Length of Zlib Game Information { Zlib Game Information }

GM version needed for the following info (500)
How many library dependancies there are (these are stored in the order of the lib's filenames,
 in alphabetical order. Likewise, they are executed in this same order)
{
 Length of Library Creation Code { Library Creation Code }
}

GM version needed for the following info (500/540/700)
How many executable rooms there are (this stores the room indexes in execution order, so you know which
 room to summon next via room_goto_next() etc.)
{
 Room index (in execution order, which is usally the same as the Tree Order)
}

<700+> <12 Root Tree Resources>
<500 and 540> <11 Root Tree Resources>
{
 Status (1=Primary, 2=Group, 3=Secondary)
 Grouping (1-13, See "Resource Tree" Documentation below)
 Index
 Name Length { Name }
 Contents
 {
  <Recurse> (See "Resource Tree" Documentation below)
 }
}

<Additional data may be stored at the end of the file and GM will ignore/discard it>

<End Of File>

Resource Formats

Game Settings

<Game Settings (530/542/600/702/800)> {
 Start in full-screen mode (0)
 <600+> Interpolate colors between pixels (0)
 Don't draw a border in windowed mode (0)
 Display the cursor (1)
 <530 only> Scale percentage in windowed mode (1-999, 100*)
 <530 only> Scale percentage in fullscreen mode (0=max) (0-999, 100*)
 <530 only> Only scale when there is hardware support (1)
 <542+> Scaling (-1 to 999, -1* = Keep Aspect Ratio, 0 = Full Scale, 1-999 = Fixed Scale)
 <542+> Allow the player to resize the game window (0)
 <542+> Let the game window always stay on top (0)
 <542+> Color outside the room region (0 or 0x00000000)
 Set the resolution of the screen (0)
 <530 only> Color Depth (0* = 16-bit, 1 = 32-bit)
 <530 only> Use exclusive graphics mode (0)
<530 only> Resolution (0-6, 0=640x480, 1*=800x600, 2=1024x768, 3=1280x1024, 4=No Change, 5=320x240, 6=1600x1200
 <530 only> Frequency (0-4, 4)
 <530 only> Wait for a vertical blank before drawing (0)
 <530 only> Display the caption in full-screen mode (1)
 <542+> Color Depth (0* = No Change, 1 = 16-bit, 2 = 32-bit)
 <542+> Resolution (0-6, 0* = No change, ...)
 <542+> Frequency (0-5, 0* = No change, 1 = 60, ...)
 Don't show the buttons in the window caption (0)
 <542+> Use synchronization to avoid tearing (0)
 <800+> Disable screensavers and power saving actions (1)
 Let <F4> switch between screen modes (1)
 Let <F1> show the game information (1)
 Let <Esc> end the game (1)
 Let <F5> save the game and <F6> load a game (1)
 <702+> Let <F9> take a screenshot of the game (1)
 <702+> Treat the close button as <Esc> key (1)
 Game Process Priority (0* = Normal, 1 = High, 2 = Highest)
 <530 only> Reserved (1)
 <530 only> Reserved (1)
 Freeze the game when the form looses focus (0)
 Loading Progress Bar (LPB) (0 = No LPB, 1* = Default LPB, 2 = Own LPB)
 <if LPB = 2> {
  <530-702> 10 or -1
  <530-702 and if not -1> Size of Back Image data { Back Image data (Zlib bitmap) }
  <530-702> 10 or -1
  <530-702 and if not -1> Size of Front Image data { Front Image data (Zlib bitmap) }
  <800+> Back Image data exists
  {
   Size of Back Image Data { Back Image data (Zlib bitmap) }
  }
  <800+> Front Image data exists
  {
   Size of Front Image Data { Front Image data (Zlib bitmap) }
  }
 }
 Show your own image while loading (0)
 {
  <530-702> 10 or -1
  <530-702 and if not -1> Size of Image data { Image Data (Zlib bitmap) }
  <800+> Image data exists
  {
   Size of Image data { Image data (Zlib bitmap) }
  }
 }
 Make image partially transparent (0)
 Make translucent with alpha value (0-255, 255)
 Scale progress bar image (1)
 Size of Icon data (2238 in 530-702, 22486 in 800+) { Icon Image Data (raw ICO) }
 Display error messages (1)
 Write error messages to file game_errors.log (0)
 Abort on all error messages (0)
 Treat uninitialized variables as value 0 (evil!) (0)
 Length of Author (0) { Author }
 <530-600> Version (100)
 <702+> Length of Version (3) { Version ("100") }
 (double) Last Changed date and time (generated)
 Length of Information (0) { Information }
 <530-702> How many Constants there are (0)
 {
  Length of Name { Name }
  Length of Value { Value }
 }
 <542 and 600> How many Include files there are (0)
 {
  Length of Filename { Filename }
 }
 <542 and 600> Folder to save Include files to (0* = main, 1 = temp)
 <542 and 600> Overwrite existing Include files (0)
 <542 and 600> Remove Include files at game end (0)
 <702+> Major (1)
 <702+> Minor (0)
 <702+> Release (0)
 <702+> Build (0)
 <702+> Length of Company (0) { Company }
 <702+> Length of Product (0) { Product }
 <702+> Length of Copyright (0) { Copyright }
 <702+> Length of Description (0) { Description }
 <800+> (double) Last time Global Game Settings were changed
}

Triggers

<Triggers> {
 Whether Trigger of this ID exists or not
 {
  GM version needed for the following info (800)
  Length of Name { Name }
  Length of Condition { Condition }
  Moment of Checking (0 = Begin, 1* = Middle, 2 = End)
  Length of Constant Name { Constant Name }
 }
}

Sounds

<Sounds> {
 Whether Sound of this ID exists or not
 {
  Length of Name { Name }
  <800+> (double) Last time this Sound was changed
  GM version needed for the following info (440/600/800)
  <440 only> Kind (-1*=None, 0="Wave", 1="Midi", 2="Mp3", 10="Unknown")
  <600+> Kind (0=Normal, 1=Background, 2=3D, 3=Multimedia)
  Length of Filetype { Filetype (like ".wav") }
  <600+> Length of Filename { Filename (no directory) }
  <600+> Music exists
  {
   <600 only> Size of Music Data { Music Data (original format with Zlib compression) }
   <800+> Size of Music Data { Music Data (original format uncompressed) }
  }
  <440 only and Kind is not -1> Size of Music Data { Music Data (original format with Zlib compression) }
  <440 only> Allow for sound effects (0)
  <440 only> Buffers (1)
  <440 only> Load only on use (0)
  <600+> Effects (Chorus=1, Echo=2, Flanger=4, Gargle=8, Reverb=16)
   Notice, Effects is actually merged into 1 longint
   To get the value, simply add active Effect numbers together
  <600+> (double) Volume (0.0 to 1.0, 1.0*)
  <600+> (double) Pan (-1.0 to 1.0, 0.0* = center)
  <600+> Preload (1)
 }
}

Sprites

<Sprites> {
 Whether Sprite of this ID exists or not
 {
  Length of Name { Name }
  <800+> (double) Last time this Sprite was changed
  GM version needed for the following info (400/542/800)
  <400-542> Width
  <400-542> Height

  <400-542> Left Bounding Box (can be negative)
  <400-542> Right Bounding Box (can be negative)
  <400-542> Bottom Bounding Box (can be negative)
  <400-542> Top Bounding Box (can be negative)
  <400-542> Transparent (1)
  <542 only> Smooth Edges (0)
  <542 only> Preload Texture (1)
  <400-542> Bounding Box (0*=Automatic, 1=Full image, 2=Manual)
  <400-542> Precise collision checking (1)
  <400 only> Use video memory (1)
  <400 only> Load only on use (0)
  X Origin (0)
  Y Origin (0)
  <400-542> How many subimages there are
  {
   10 or -1
   <if not -1> Size of Image Data { Image Data (Zlib Bitmap) }
  }
  <800+> How many subimages there are
  {
   GM version needed for the following info (800)
   Width
   Height
   <if Width and Height are not 0> Size of Image data { Image data (raw BGRA) }
  }
  <800+> Shape (0*=Precise, 1=Rectangle,  2=Disk, 3=Diamond)
  <800+> Alpha Tolerance (0 to 255, 0)
  <800+> Separate Collision Masks (0)
  <800+> Bounding Box (0*=Automatic, 1=Full, 2=Manual)
  <800+> Left (0)
  <800+> Right
  <800+> Bottom
  <800+> Top (0)
 }
}

Backgrounds

<Backgrounds> {
 Whether Background of this ID exists or not
 {
  Length of Name { Name }
  <800+> (double) Last time this Background was changed
  GM version needed for the following info (400/543/710)
  <400-543> Width
  <400-543> Height
  <400-543> Transparent (0)
  <400 only> Use video memory (1)
  <400 only> Load only on use (1)
  <543 only> Smooth Edges (0)
  <543 only> Preload Texture (0)
  <543+> Use as tile set (0)
  <543+> tile width (16)
  <543+> tile height (16)
  <543+> horizontal offset (0)
  <543+> vertical offset (0)
  <543+> horizontal sep (0)
  <543+> vertical sep (0)
  <400-543> Image exists
  {
   10 or -1
   <if not -1> Size of Image data { Image Data (Zlib Bitmap) }
  }
  <710+> GM version needed for the following info (800)
  <800+> Width (0)
  <800+> Height (0)
  <800+ and Width and Height are not 0> Size of Image data { Image data (raw BGRA) }
 }
}

Paths

<Paths> {
 Whether Path of this ID exists or not
 {
  Length of Name { Name }
  <800+> (double) Last time this Path was changed
  GM version needed for the following info (530)
  Connection Kind (0* = Straight lines, 1 = Smooth curve)
  Closed (1)
  Precision (1-8, 4)
  Room Index to show as Background (-1* = none)
  Snap X (16)
  Snap Y (16)
  How many Points there are (0)
  {
   (double) X
   (double) Y
   (double) Speed
  }
 }
}

Scripts

<Scripts> {
 Whether Script of this ID exists or not
 {
  Length of Name { Name }
  <800+> (double) Last time this Script was changed
  GM version needed for the following info (400/800)
  Length of Script { Script }
 }
}

Fonts

<Fonts> {
 Whether Font of this ID exists or not
 {
  Length of Name { Name }
  <800+> (double) Last time this Font was changed
  GM version needed for the following info (540/800)
  Length of Font Name { Font Name }
  Size (12)
  Bold (0)
  Italic (0)
  Character Range Begin (32)
  Character Range End (127)
 }
}

Timelines

Objects

<Objects> {
 Whether Object of this ID exists or not
 {
  Length of Name { Name }
  <800+> (double) Last time this Object was changed
  GM version needed for the following info (430)
  Sprite Index (-1* = none)
  Solid (0)
  Visible (1)
  Depth (0)
  Persistent (0)
  Parent object index (-100* = none)
  Mask sprite index (-1* = none)
  How many Event Types there are minus 1 (10 in v400, 11 in v800, unclear why it's off by one)
Now we have an interesting thing. We have -1's thrown in for each of the event types.
They appear after each event's data (or simply appear where they are if the event type has no data),
but the events may have -1's in them too, so you can't just count down -1's and hope to be at the end
of the object.  No event begins with -1, so if you have a -1 where an event should be, you know that the
event has no data. If there is data, it is documented here. If there are multiple kinds
(event kind = 'numb' in the GM manual) of the same event,
each kind will be added in without a -1 appended on the end until the last. The first kind to appear will
actually be the highest kind number, and then it will count down. Other than that, Events appear in
standard order. The stars ** you will see below relate to Time Lines. See Time Lines for more info.
  {
   Event Numb (see GM Manual)
   **GM version needed for the following info (400)
   How many actions this event has
   {
    GM version needed for the following info (440)
    Library ID
    Action ID
    Action Kind (Normal, Begin Group, Else, etc. See Lib Builder)
    Action may be Relative
    Action is a Question
    Action Applies to something
    Action Type (0=Nothing, 1=Function, 2=Code)
    Length of Function Name { Function Name }
    Length of Code { Code }
    How many Arguments are actually used
    How many arguments there are (always 8)
    {
     Argument Kind (See Lib Builder)
    }
    Applies to Object Index (-1 for Self, -2 for Other)
    Relative
    How many arguments there are (always 8)
    {
     Argument Length { Argument Value }
    }
    NOT
   }**
  }
  (Don't forget the -1 after each Primary event)
 }
}

Rooms

<Rooms> {
 Whether room of this ID exists or not
 {
  Length of Name { Name }
  <800+> (double) Last time this Room was changed
  GM version needed for the following info (520/541)
  Length of Room Caption (0) { Room Caption }
  Width (640)
  Height (480)
  Snap Y (16)
  Snap X (16)
  Turn the grid into an isometric grid (0)
  Speed (30)
  Persistent (0)
  Background Color (12632256 or 0xC0C0C000)
  Draw background color (1)
  Length of Creation Code { Creation Code }
  How many Backgrounds there are (always 8)
  {
   Visible when room starts (0)
   Foreground Image (0)
   Background Image index (-1* = none)
   X (0)
   Y (0)
   Tile Hor. (1)
   Tile Vert. (1)
   Hor. Speed (0)
   Vert. Speed (0)
   Stretch (0)
  }
  Enable the use of Views (0)
  How many Vies there are (always 8)
  {
   Visible when room starts (0)
   <520 only> Left
   <520 only> Top
   <520 only> Width
   <520 only> Height
   <520 only> X
   <520 only> Y
   <541+> View X (min 0, 0)
   <541+> View Y (min 0, 0)
   <541+> View W (min 1, 640)
   <541+> View H (min 1, 480)
   <541+> Port X (min 0, 0)
   <541+> Port Y (min 0, 0)
   <541+> Port W (min 1, 640)
   <541+> Port H (min 1, 480)
   Hbor (min 0, 32)
   Vbor (min 0, 32)
   Hsp (min -1*)
   Vsp (min -1*)
   Object following (-1* = none)
  }
  How many Instances are in the room (0)
  {
   X
   Y
   Object Index
   ID (starts with 100001)
   Length of Creation Code { Creation Code }
   Locked
  }
  How many Tiles are in the room (0)
  {
   X
   Y
   Background Index
   TileX
   TileY
   Width
   Height
   Layer/Depth (1000000)
   ID (starts with 10000001dec)
   Locked
  }
  Remember the Room Editor Info (REI if 0. May be 0 if all settings are defaults)
  Room Editor Width (646, 0 if REI)
  Room Editor Height (488, 0 if REI)
  Toggle the showing of the grid (1, 0 if REI)
  Show Objects (1, 0 if REI)
  Show Tiles (1, 0 if REI)
  Show Backgrounds (1, 0 if REI)
  Show Foregrounds (1, 0 if REI)
  Show Views (0, 0 if REI)
  Delete underlying objects (1, 0 if REI)
  Delete underlying tiles (1, 0 if REI)
  <520 only> Tile Width (16)
  <520 only> Tile Height (16)
  <520 only> Tile Hsep (1)
  <520 only> Tile Vsep (1)
  <520 only> Tile Horizontal Offset (0)
  <520 only> Tile Vertical Offset (0)
  Tab (0-4, 0, 0 if REI)
    0* = objects, 1 settings, 2 tiles, 3 backgrounds, 4 views
  X Position of the horizontal scrollbar of the Room Editor (0, 0 if REI)
  Y Position of the vertical scrollbar of the Room Editor (0, 0 if REI)
 }
}

Included files

<Included Files> {
 <800+> (double) Last time this Include File was changed
 GM version needed for the following info (620/800)
 Length of Filename (0) { Filename }
 Length of Filepath (0) { Filepath }
 Whether an Original File is chosen or not
 Original File Size (0)
 Store in editable gmk file (0)
 {
  Length of File Data (0) { File Data }
 }
 Export (0=Don't, 1=Temp Dir, 2*=Working Dir, 3=Following Folder)
 Length of Folder To Export To (0) { Folder To Export To }
 Overwrite the file if it exists (0)
 Free memory after export (1)
 Remove at game end (1)
}

Game Information

<Game Information> {
 Background Color of Game Information (-16777192 or 0x180000FF)
 <430-620> Mimic the main game window/main form (0)
 <800+> Show help in a separate window (1)
 <600+> Length of Form Caption (16) { Form Caption ("Game Information") }
 <600+> Position Left (-1)
 <600+> Position Top (-1)
 <600+> Position Width (600)
 <600+> Position Height (400)
 <600+> Show the window border and caption (1)
 <600+> Allow the player to resize the window (1)
 <600+> Stay always on top (0)
 <600+> Stop the game while showing help (1)
 <800+> (double) Last time Game Information was changed (not including RTF)
 Length of Game Information RTF (147) { Game Information (Rich Text Format) }
}

Resource Tree

  • <700+> There are 12 Root Tree Resources - 9 primary, 3 secondary
  • <500 and 540> There are 11 Root Tree Resources - 9 primary, 2 secondary

Format

Status, Kind, Index, Length, { Name }, Contents

This is repeated for every node in the tree in a pre-order recursive (depth-first) enumeration. That is, if all branches in the tree were expanded, each node is considered in the order that they appear, starting from the top and going down.

Status

  1. Primary Resource
  2. Group
  3. Secondary Resource

Index

All Secondary Resources are given an Index, or a reference number, which reflects the index of the resource far above, where you set their properties and options. Primary Resources, Groups, and root-level nodes (like Game Information) all use 0 for their Index. Occasionally you may find that they will actually use a number other than zero. It is unclear why they would do this, but just keep it in mind.

If the index does not reflect their resource number above, you may either get invisible resources or <undefined> resources. Also, make sure that no two secondary resources under a single Grouping have the same Index. This results in a link, in which both are dependent on each other and anything you do to one is done to the other.

Name Length { Name }

All have a Name Length. After that, it will count out that many bytes for the name itself.

Contents

All Primary Resources and Groups have Contents count, which is how many child nodes, or groups/secondary resources it has within itself, non-recursive. Secondary Resources always have a content count of 0, since they may never contain anything.

Non-recursive means that if a parent folder contains 5 resources and 2 child folders, and each of those 2 child folders contain several resource, you still only count 7 children for the parent folder (5 resources + 2 folders = 7) and do not count the children inside the child folders - they are responsible for maintaining their own contents.

Example

In an empty file, it would look something like this:

1 2 0 7 Sprites 0 1 3 0 6 Sounds 0 etc.

In the pacman example that comes with most distributions of GM, it would look like this:

1 2 0 7 Sprites 6 2 2 0 7 pacmans 5 3 2 0 8 pac_left 0 3 2 1 9 pac_right 0
3 2 2 6 pac_up 0 3 2 3 8 pac_down 0 3 2 4 9 pac_stand 0 2 2 0 8 monsters 2 etc.

This will cause the tree to look like this:

  • Sprites
    • pacmans
      • pac_left
      • pac_right
      • pac_up
      • pac_down
      • pac_stand
    • monsters (etc...)

Since Primary Resources are included in the save file, you can change their names (and their lengths, as long as you update the longint before their name to reflect the new length) and it will actually display in the resource tree to the left.