Last update: 12/17/2021

Many thanks to MysticLord, Robert Seddon (Vanished One), Zanerus, and the sagafrontier @ wiki on assisting with this page.

Back to home

Required Software

Required tools:

  • (by MysticLord)
    • Calculates header and free sector bytes of directory with IMF files in it

For manual editing:

For editing sprites and images:

Creating a Patch:

What is an IMF File?

An IMF file is an individual map. Each IMF has a .IMG and a .TEX file. The .IMG file handles dialogue, cutscenes, music playback, sprite placement, and map background display. The .TEX file is the map background. The code for NPC movement, as far as we know, is handled by the IMF. It’s unknown if it’s a simple flag or custom code. The code for enemy movement is handled by another file called MAP.OUT.

IMF*.IMG Structure

There are 10 sub-files in any given IMF*.IMG file. The locations of each sub-file are specified in the header. There are 10 little endian numbers, each 4 bytes long. Here are some examples:

28 00 00 00 //1st sub-file
30 00 00 00 //2nd sub-file
54 00 00 00 //3rd sub-file
58 00 00 00 //4th sub-file
68 00 00 00 //5th sub-file
28 01 00 00 //6th sub-file
F4 1F 00 00 //7th sub-file
F0 26 00 00 //8th sub-file
10 27 00 00 //9th sub-file
EC 46 00 00 //10th sub-file

28 00 00 00 //1st sub-file
F4 00 00 00 //2
18 01 00 00 //3
E4 01 00 00 //4
0C 02 00 00 //5
A8 05 00 00 //6
F0 08 00 00 //7
58 43 00 00 //8
78 43 00 00 //9
54 63 00 00 //10

Sub-File 1 (Section 0)

Appears to give frame attributes for background animations. This sub-file hasn’t been explored all that much.

Sub-File 2 (Section 1)

Appears to define the attributes of NPCs (collision data, interaction data, etc.).

Sub-File 3 (Section 2)

Currently unknown, though it does appear to affect NPC interactions.

Sub-File 4 (Section 3)

Defines attributes for map transitions (which map to go to, animation to play, if it’s associated with a script, etc.).

Sub-File 5 (Section 4)

Define the field script; dialogue, menus, cutscenes, etc. Basically, all the interactive elements of the map.

Sub-File 6 (Section 5)

AKAO MIDI sequences for music and sound effects. This version of AKAO is closely related to the AKAO format used in Final Fantasy VII, but it’s not an exact carry-over. Uses either an INSTR*.ALL file for instruments or default PS1 sounds, it’s currently unknown if the default PS1 sounds are pre-loaded into all INSTR*.ALL files.

Sub-File 7 (Section 6)

NPC sprite data, palettes, and sheets.

Sub-File 8 (Section 7)

Defines the collision map. Not much is currently known about how this functions, but it was created with default tools included with the PS1 SDK.

Sub-File 9 (Section 8)

Currently unknown.

Sub-File 10 (Section 9)

Defines how the associated IMF*.TEX file is to be displayed on the screen.

IMF*.TEX Structure

Begins with a 4-byte header, followed by the map background and its various pieces, including sprite sheets for animated pieces, on-screen text, etc. Header is formatted as follows:

   - XX XX = unknown, tends to be set to 0x08 0x40 
   - SS SS = size of file after header divided by 10 (0x0A)

Modifying IMF Files

IMF*.IMG Files

  • If you decide to expand any of these sub-files, you will have to create an entirely new header. Do note that sometimes, you won’t have to do this as some sectors have free bytes. You can calculate the free bytes of the IMF you’re editing with MysticLord’s script linked at the top of the page.
  • If you don’t know how bit toggles work, it’s simple. You have a list of values that determine when something’s enabled or disabled, each one adding up to give you the final value of the byte. For example, if a bit toggle byte is set to 0x03, then toggles 0x01 and 0x02 are currently active.
  • Generally, 0x808080 seems to indicate an RGB tint applied to a base palette. This appears to be the case across all sub-files that contain some kind of sprite data.

Sub-File 1 (Section 0)

Currently unknown how exactly to edit.

Sub-File 2 (Section 1)

Currently unknown how exactly to edit.

Sub-File 3 (Section 2)

Currently unknown.

Sub-File 4 (Section 3)

I honestly don’t know if these opcodes apply to this sub-file or the next one. Regardless, the opcodes for these events are:

03 0x yy
05 0x yy
- 0x = map jump
- yy = point to script routine in current map? (usually 20)
06 0x 00 = forced event occurrence (only when directly after 05 0x 20)

Towards the bottom of the sub-file, there is region movement code formatted exactly the same as what’s used for the RegionMap. It is formatted as such:

- MMMM = IMF hex value (in little endian)
- XXXX = x-pos (in little endian)
- YYYY = y-pos (in little endian)
- ZZ = z-layer (?)
- SS = bgm hex value
  - values are based on the music stored in the IMF
    - if music can't be found, then nothing's played
  - 04 = default town theme (usually)

It’s unknown how the game assigns these values to hitboxes, so you’ll have to do some testing. It’s possible that they’re assigned from west-most to east-most. Fortunately, most maps don’t have more than 3 or 4 hitboxes that transition to a new map, so it’s not terrible to figure out which opcode goes to which hitbox.

Sub-File 5 (Section 4)

For reference, there is a header in this sub-file with 16-bit pointers to script routines (the first two bytes are the length of the rest of the header).

Text is formatted in SHIFT_JIS (hence why I said wxMEdit is required instead of HxD), while opcodes are defined in ASCII. To view this SHIFT_JIS text, select View > Encoding > East Asian > [Windows 31J] Windows Japanese (SHIFT_JIS):

Here are the opcodes you’ll need for generating dialogue. The order is just what I thought made sense:

48 = initialize new dialogue window
46 = line feed (immediately display next line)
43 = carriage return (wait for player to press O before advancing to next line)
50 = wait for player to press O (no prompt arrow)
44 XX = wait XX units of time
5F XX = text scrolling
- 00 = instant appearance
- 01 = scroll into being
60 XX YY = wait YY units of time before continuing
- XX is unknown (ID of entity?)
00 = conversation end (return)

53 XX (YYYY) = change color
- XX = mode
  - 00 = default white
  - 01 = custom color (enables YYYY)
- YYYY = color
- usually placed preceding text, but can be placed in the middle of text
45 XX = return to start (top left) of current window for subsequent text, overwriting anything already there
47 XX = return to XX char-widths into current line for subsequent text, overwriting anything already there
4B = clear the current dialogue window after a carriage return
4C = initialize large dialogue window (similar to Lute's intro)
54 = close current window (to open a new one)

4A XX YY ZZ = display new dialogue window
- XX = window position (relative to speaker)
- YY = hex ID of speaker
   - varies depending on the map. check which sprite they are in the sprite sub-file for this ID
   - i don't know if the main character's ID is 00 or FF
- ZZ = who the character is speaking to (where to face)
   - FF = speaking to nobody on screen (lets you use a custom facing)
54 (in text) = initialize all windows 
- if you want to change maps during dialogue, use this

7C/7D/7E WW YY ZZ = window y-pos
- WW = unknown
- YY = y-pos
- ZZ = unknown (z-layer?)

51 XX = dialogue window bg/border style
- 01 is used for shop menus
- FF might be no visible bg/border
52 XX = affects dialogue window visibility
- 01 hides main buying menu when party list is displayed
- FF might mean visible at all times

5E yy XX (in text) = call a name of something
- yy = type
  - 00 = item names
  - 02 = character names
  - 03 = technique names (up to DeathSynthesis)
  - 04 = technique names, cont.
  - 05 = more character names (with tabs for shops and probably other menus)
    - probably not stripping out padding whitespace
  - 06 = character names (XX is length variable, max is 09)
    - 06 00 = "", 06 01 = "Bl", 06 02 = "Blue", = 06 09 = "Blue XA"
  - 07 = System Data, your name
  - 08 = System Data, your astrological sign
  - 09 = System Data, your blood type
- XX = ID of name
  - 02 FF = name of current leader

61 cc = shift control to entity cc (for both scripted behavior and user control) 
- cc might include bits of scenery as well 
  - FF = entire party

61 FF = move character during conversation
58 XXXX YYYY ZZ = move/walk to a point
- coordinates are (XXXX, YYYY) in little endian (origin is bottom-left)
- ZZ = mode/speed(?)
  - 56 = walk
  - 57 = run(?)
  - 55 = slide(?)
59 cc ZZ = walk into character cc
- used most often for recruiting characters
- ZZ = same as opcode 58
FE = vanish instantly
- used most often for recruiting characters
5A XXXX YYYY GG = jump to a point
- coordinates are (XXXX, YYYY) in little endian (origin is bottom-left)
- GG = force? (affects speed and range)
  - lower = faster and further
  - may walk to target point to make up for shortfall
54 XXXX YYYY (outside text) = offset sprite relative to entity's actual position
- entity's shadow is attached to entity, so it'll stay in the true position

71 cc = attach camera to (scroll to) entity cc

63 cc YYYY = entity cc performs script routing number YYYY

7F XX = bring up name requester
- 00 doesn't crash, unknown what other args could be

And here are the different kinds of dialogue windows you can use:

4D XX = normal
4E XX = thinking
4F XX = normal, forced to big and 3 lines
- XX = bit toggle, window size
  - 00 = 3 lines (wide)
  - 01 = 2 lines (wide)
  - 02 = 1 line  (wide)
  - 03 = full screen (with window border)
  - 04 = full screen (without window border)
  - 05 = 2 lines (narrow)
  - 06 = 3 lines (narrow)
  - 07 = 4 lines (narrow)
  - 08 = 5 lines (narrow)
  - 0D = 3 lines (medium)
  - 11 = 6 lines (big)

It’s possible for special events to happen during dialogue or after interacting with something. These codes are usually placed directly after a certain line of dialogue. Here are a bunch of them:

00 = event end (return)

1A bb Fb ZZ = rewrite flag 
- bb *b = address of start of data(?)
- F = what kind of data's being referred to
  - 3 = flag data
- ZZ = value written to address

07 0d 80 yy xx = change the sprite sheet of character yy to xx
- xx = FF means your current sprite sheet
07 0d 81 yy xx = (same as above, but for the palette)
20 XX = set character XX to give default name for subsequent name requester 7F
64 0x cc = adjust party
- 00 = remove member
- 01 = add member
- cc = ID of char to add/remove
67 03 cc = change current protagonist to a new character cc
67 05 0x = change T260G's current body
- TYPE1 = 00, TYPE2 = 01, ..., TYPE8 = 07

07 01 XXXXXXXX = give XXXXXXXX credits
07 02 XXXXXXXX = deduct XXXXXXXX credits
- fails if player has less than amount specified, probably an underflow failsafe
07 04 XXXXXXXX = set current credit amount to XXXXXXXX

07 17 uu vv ww mm ss xx yy zz = begin battle
- uu = unknown (usually FF)
  - transition type?
- vv = event ID
  - 00 = no event, load some random enemies
- ww = unknown
- mm = music ID
  - 00 = keep playing the current song
  - FF is required to change to Battle 1 from the previous song
- ss = battle stage
  - click here for a complete list
- xx = unknown (usually 05)
- yy = unknown (usually 00)
- zz = unknown (usually C0)
  - can change what battle you're in

28 40 cc 07 0b 40 ss 23 00 30 NN 07 10 40 ss = increase ss stat of character cc by NN 
- 0E = STR
- 0F = QUI
- 10 = INT
- 11 = WIL
- 12 = PSY
- 13 = VIT
- 14 = CHA

07 20 pp = restore LP
07 1F pp = restore JP? WP?
07 1E pp = restore WP? JP?
- pp = which party members to apply it to. most likely a bit toggle
  - FF = whole party

68 01 ii NN = get NN of item ii

Here are special opcodes specific to shops:

2A XX YYYYYYYY = price of item XX

07 09 00 RR 40 1F 10 = magic shop start
- RR = race bit toggle
  - 01 = human
  - 02 = mystic
  - 04 = mec
  - 08 = monster

It’s also possible to use branching code and jump codes. Unfortunately, it’s not entirely known how to utilize this. Here’s what we have so far:

08 bb cb dd ee xx xx
- bb *b = address of start of data(?)
- c = what kind of data's being referred to
  - 3 = flag data
- if value of referenced data is between dd and ee, data at xx xx is referenced instead

There are specific functions you can call for each protagonist. This is usually text for an item pickup, but there are more things:

49 0M YY ZZ (GOTO? general functions? MESG?)
- 0M = MESGx (0 - 7)
- YY = unknown
- ZZ = unknown
- 02 15 10 = "It's [item]."
- 02 14 10 = "0 Credits"
- 02 11 10 = battle swirl
- 02 21 10 = sends to start of blue's scenario for some reason
- 02 00 10 = activate debug menu

Finally, here are the opcodes that we know most likely exist, but don’t know how they work yet. Feel free to mess around with these and report what you find to the forum:

01 (alternate return?)
02 XX (goto routine XX?)
03 XXXX (jump to offset XX in middle of routine? seems to affect clipping)
04 XXXX (plain goto offset 0xXXXX?)
09 XX XX XX XX XX (maybe same as branch code?)
0A XX XX XX XX XX (same as 09? ends with jump?)
0B XX YY ZZ (involved with field entities somehow)
5B (sit down? freezes everything)
5D XX YY (affects bg tiles somehow; YY higher = more distortion?)
5E XX (out of text) = look (in a direction? at an entity?)
62 (stop? send to back?)
66 XX YY = (seems to involve script routines; 0x63 anims don't work without it)
70 XX (YY?) (unknown)
7B XX YY ZZ (start of shop menu or general sfx?)

Sub-File 6 (Section 5)

Currently, you have to edit this manually as there are no known AKAO sequencer tools. It is very similar to the AKAO version used in FF7, but it’s not exactly 1:1 as SaGa Frontier adds a new sound opcode and has a different format for its headers. To learn about how Early AKAO works, click here (external link, QhimmWiki) or here (external link, sagafrontier @ wiki, in Japanese). You can manually edit AKAO sequences through this method. I am not aware of any tools to edit AKAO sequences.

In terms of listening to these sequences, building vgmtrans from Github can pretty perfectly convert AKAO to MIDI, along with the sample collections and instrument banks to DLS and/or SF2. It can even detect multiple AKAO sequences within one file, so you can drop an IMF*.IMG file or the game’s executable (yes, the executable has music in it) into the application and extract their AKAO sequence(s). In order to properly listen to and export these tracks with a soundfont, you must import the correct sample collection into vgmtrans. For battle music, this is INSTR000.ALL located in the B_SOUND folder. For the purposes of just listening to the songs, that’ll suffice. Note that the harp is stored in bank 1 and the drum kit in bank 127, despite the MIDI only loading sounds from bank 0.

Here are the known differences between FF7’s sound opcodes and SaGa Frontier’s:

  • 0xF3
    • Unknown
  • 0xF5 – 0xF8
    • Unimplemented
    • Code-referenced to 0xA0, shouldn’t be used
  • 0xFC
    • Set extended tone
    • Structure of tone info is described by (addr.) (relative addr.)
    • This is the opcode that breaks all FF7 tools

Here’s how SaGa Frontier’s sample files are formatted:

  • Notes:
    • BYTE = 1 byte
    • WORD = 2 bytes
    • DWORD = 4 bytes
    • These files work perfectly with vgmTrans, so they’re incredibly similar to FF7’s
    • Unlike FF7, the .DAT and .ALL files were combined into a singular .ALL file and given an AKAO signature
"AKAO" string in ASCII
Not used?
Not used?
Not used?
Timestamp (Year, BCD format)
Timestamp (Month, BCD format)
Timestamp (Day, BCD format)
Timestamp (Hour, BCD format)
Timestamp (Minute, BCD format)
Timestamp (Second, BCD format)
SPU dest. addr. for sample data transfer
Size of sample data
Start ID
Not used?
Not used?
Not used?
Not used?
Not used?
Not used?
Not used?
Not used?
Not used?

Number of instruments is calculated as (128 – Start ID).

Articulation and pitch info is next, in a 64-byte repeated structure. The contents of this structure are identical to FF7’s INSTR*.DAT files.

Sample data is placed afterward.

Sub-File 7 (Section 6)

As of now, we only know that palettes for all sprites are defined before the sprite sheet section begins. Each palette is 16 bytes in size. Each sprite is 2-dimensional, formatted as 4bpp linear, reverse-order.

Sub-File 8 (Section 7)

Largely unknown.

- 0xFF = wall
- 0x00 = open space(?)

Sub-File 9 (Section 8)

Currently unknown.

Sub-File 10 (Section 9)

There are three known subsections of this sub-file:

  • Map attributes and tilemap objects, in lists
  • Tile arrangements
  • Palette(s)

Begins with a 12-byte section header, followed by a 16-bit pointer table to subsections, ending with a 32-bit pointer table for the remaining subsections and the end of the sub-file. As per usual, all numbers and pointers are in little endian.

The first subsection’s formatted as follows (the number is the number of bytes used for each attribute):

- 1 Red tint
- 1 Green tint
- 1 Blue tint
- 1 Palette ID
- 2 X-position, offset from default position
- 2 negative Y-position, offset from default position
- 2 positive Y-position, offset from default position
- 2 Unknown
- 1 Unknown
- 1 Distortion in X axis (stretching)
- 1 Unknown
- 1 Flying height: changing this lets the object move vertically above its normal position (not below)
- 1 Ripple (01 gives a weird floating animation (SFX, not a sprite animation routine))
- 1 Unknown (Visibility? Anything other than 00 made the test object vanish)

Here is the formatting in the second subsection’s header:

- ????????XXXXYYYYAAAABBBB, followed by tile IDs as UINT16s, in columns, left to right (length (A/0x10) * (B/0x10) * 2)
   - X = X-position, absolute (origin seems to be top-left for these)
   - Y = Y-position
   - A = Width in pixels
   - B = height in pixels

Here is the formatting of the third subsection’s header:

- 6-bytes long, usually begins 0x00 0x01, followed by one byte defining the number of palettes

Each palette is 512 bytes in length (256 colors).

IMF*.TEX Files

The image is 2-dimensional, formatted as 8bpp linear. The palette for each sprite sheet is stored in the 10th sub-file of its associated .IMG file. Editing these files is as simple as putting it into tilemolester. However, before you can start editing, you first need to manually move the palette(s) that you need to the top of the .TEX file. It’s as simple as copying the palette from the 10th sub-file of the .IMG and pasting that to the top of the .TEX in whichever hex editor you want. As long as the .TEX gets bigger by at least 512 bytes per palette you put in, you’re all set.

Personally, I recommend manually copying/pasting the palette into the .TEX, opening Photopea (free Photoshop alternative, in-browser), and downscaling whichever image you want to display in the .TEX file to around the same size as the source .TEX to make your changes (you’ll have to guess, unfortunately). This way, you can manually transfer your image into the .TEX pixel-by-pixel and modify the .TEX palette to include whatever colors you need. Remember, you only get 256 per palette. It’s kind of like creating pixel art in Minecraft, only more tedious.

How IMF Files are Handled in the Remaster

The remaster does use IMF*.IMG files. For obvious reasons, the remaster does not use .TEX files, so they are not included in resources.assets. Not much is currently known how the remaster handles IMF files. Currently, all we know is that most, but not all, sub-files are used. Some sub-files are used in their entirety, others are only partially used.

  • Sub-file 1
    • Unknown
  • Sub-file 2
    • Unknown, not likely to be used
  • Sub-file 3
    • Unknown
  • Sub-file 4
    • Unknown
      • I have yet to get custom map transitions to work
  • Sub-file 5
    • Used for at least all dialogue
      • Defines a SHIFT_JIS key to point back to BaccaratMessage followed by the usual opcodes
      • Within BaccaratMessage, some of the ASCII opcodes have been replaced by line feeds and carriage returns
    • Unknown what else is used here
  • Sub-file 6
    • Not used(?)
      • It could be used for small things like song ID’s, but it’s currently unknown
  • Sub-file 7
    • Unknown;
      • It’s definitely used in small pieces
  • Sub-file 8
    • Most likely used in its entirety
      • Unknown how the game handles this as the collision maps in the remaster are blocky and inconsistent
  • Sub-file 9
    • Unknown
  • Sub-file 10
    • Unknown; possibly used to define map dimensions and/or sprite layering, but that could be handled by Unity with its Sprite tool