News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: [PSP] Final Fantasy 4 Tile Map File  (Read 1481 times)

travisty

  • Jr. Member
  • **
  • Posts: 12
    • View Profile
[PSP] Final Fantasy 4 Tile Map File
« on: April 22, 2020, 12:20:00 pm »
I'm writing a clone to FF4, and I'm trying to use the existing assets from the PSP version of the game. Progress has been good, and now I'm trying to the tile map config files from the game. Once I have the tile maps loaded correctly, I'll write an exporter that will export these files as .tmx files, so that they can be easily editable with the Tiled map editor. I don't want to bring any event data over right now. Just the data that maps each cell in the map grid to a tile in the texture.



It definitely resembles the map, but there are a bunch of oddly-places tiles, so something's off with how I'm interpreting the `.cn2` file.

Unfortunately, I don't have a full-sized version of what this map is supposed look like for the PSP version of the game. I do have an example of what the entire map looks like for the GBA version. They're "different" maps because the dimensions and tilesets are slightly different, but it's still a pretty accurate reference of what the PSP version of the map should look like:



A major thank you to user Everything for building this badass GBA ROM tile map editor.

When looking through the data in a hex editor, it looks like the the first 2 bytes of the file is the width of the map (in tiles), and the next 2 bytes is the height of the map. If I take the entire size of the file, and subtract 4 from it (the bytes that describe the width and height), then divide the result by 6, the final result is always equal to the width*height in every file. This leads me to believe that each tile in the map is described by 6 bytes.

Another thing I've noticed is that the file seems pretty dense with varying values for all odd bytes in the top 1/3 of the file, a value of 0, 1, or 2 for even bytes. The bottom 1/3 of the file is pretty much 0s for the majority of bytes except for a few things. All of the zeroes make a visual pattern easier to see in that bottom 1/3 of the file.

At the risk of comparing apples to oranges, I've been using the GBA version as reference since the user "Everything" on these forums has a REALLY NICE tile editor for the GBA release of the game. It's helped me make rough comparisons of the game, visually. The GBA version of the game seems to suggest that all tile maps have 3 layers: Layer 1, Layer 2, and a Triggers layer.

The final observation is that all tilesets in the game are 16x16 tiles where all tiles are 32x32 pixels making every tileset in the game 512x512px. This means that all tilesets have exactly 256 tiles in them. If we're looking these tiles up by index, then we'd only need a single, 8-bit value to do so, etc it appears that each tile entry has 2 bytes of data associated with it. I'm pretty sure that these lookup indices aren't 16-bit values because of the byte pattern, and the 16-bit values typically go far beyond the value of 256.

As a recap, here are the observations that I've made so far:
- There appears to always be 3 layers if the PSP version is consistent with the GBA version
- There's a 6:1 ratio between tiles in the map and bytes in the file
- Every even byte being 0, 1, 2 in at least the top 1/3 of the file
- The file's values start off dense and varied at the top, and gets more sparse towards the bottom
- There are exactly 256 tiles in every single tileset, and the first byte of every cell entry appears to be an index to the tileset most of the time

To the result above, I load the first 2 bytes of the file (little-endian), and use that as the map's width in tiles. Then I load the next 2 bytes as the map's height in tiles. I multiply those two values together to get the total cell count per layer. My theory is that there are 2 bytes per cell for Layer 1, so I load "n" bytes into memory where "n" is width*height*2. Then, I use the first byte in of each tile descriptor as an index to look up the tile. It looks like that first byte is a literal lookup index to the tile in the tileset texture "most of the time," but not always.

Here's the first 512 bytes of the map config file (castle1_baron_castle_01.cn2) for reference:

Code: [Select]
24 00 2C 00  09 00 41 01    42 01 09 00  41 01 42 01
09 00 09 00  09 00 09 00    09 00 41 01  42 01 09 00
09 00 09 00  41 01 42 01    09 00 09 00  09 00 09 00
41 01 42 01  09 00 09 00    09 00 09 00  41 01 42 01

09 00 41 01  42 01 09 00    09 00 41 01  42 01 01 00
49 01 02 00  49 01 02 00    02 00 49 01  49 01 02 00
02 00 09 00  02 00 09 00    02 00 49 01  49 01 02 00
02 00 49 01  02 00 02 00    49 01 02 00  49 01 02 00

02 00 02 00  02 00 49 01    02 00 02 00  49 01 02 00
03 00 09 00  52 01 04 00    D4 02 08 02  08 02 08 02
08 02 08 02  08 02 08 02    E4 02 02 00  DC 02 49 01
E8 02 08 02  08 02 08 02    08 02 08 02  08 02 08 02

08 02 08 02  08 02 08 02    08 02 08 02  08 02 08 02
08 02 08 02  08 02 08 02    47 01 09 00  09 00 48 01
F8 02 0C 02  0C 02 0C 02    0C 02 0C 02  0C 02 0C 02
0C 02 08 02  0C 02 08 02    0C 02 0C 02  0C 02 0C 02

0C 02 0C 02  0C 02 0C 02    0C 02 0C 02  0C 02 0C 02
0C 02 0C 02  0C 02 0C 02    0C 02 0C 02  0C 02 0C 02
05 00 09 00  09 00 04 00    F8 02 0C 02  0C 02 0C 02
0C 02 0C 02  0C 02 0C 02    0C 02 0C 02  0C 02 0C 02

0C 02 0C 02  0C 02 0C 02    0C 02 0C 02  0C 02 0C 02
0C 02 0C 02  0C 02 0C 02    0C 02 0C 02  0C 02 0C 02
0C 02 0C 02  0C 02 0C 02    47 01 09 00  42 01 48 01
F8 02 1A 00  1B 00 0C 02    0C 02 0C 02  0C 02 0C 02

0C 02 0C 02  0C 02 0C 02    0C 02 0C 02  0C 02 1A 00
1B 00 0C 02  0C 02 0C 02    0C 02 0C 02  0C 02 0C 02
0C 02 0C 02  0C 02 0C 02    0C 02 1A 00  1B 00 0C 02
47 01 09 00  52 01 04 00    F8 02 3C 01  2D 01 31 00

30 00 80 00  00 00 82 00    7A 00 30 00  00 00 30 00
30 00 30 00  30 00 1C 01    1D 01 31 00  30 00 30 00
30 00 30 00  30 00 30 00    80 00 00 00  82 00 7A 00
30 00 1C 01  3D 01 0C 02    05 00 09 00  09 00 04 00

Here's the tileset (castle1_b_base.tm2) I'm using:



Does anyone have any insight on the tile map format?

EDIT 1:
I think I figured it out. Each alternate byte is either 0, 1, 2. I thought they might have some relation to layers, but they're not. They're related to the tileset. Each map has exactly 3 layers, but it also has exactly 3 tile sets: _base, _var, and _anm.

I was able to figure out the purposes of the _base and _anm tile sets pretty easily, but I couldn't figure out the purpose of the _var tileset. Then it hit me: it's for rotated/flipped tiles.

In conclusion: the first byte is the index in the tileset, and the second byte is the tileset to use. I'll implement this theory, and see what happens.

#gotem

EDIT 2:
Looks like I was mostly correct. I'm not sure what that 3rd layer is for yet, but it looks like maybe it's for triggers, or possibly additional collision data for hidden routes within the tile map?

Anyway, here's the map rendering in all of its glory:

« Last Edit: April 24, 2020, 02:36:40 am by travisty »

Rudy

  • Jr. Member
  • **
  • Posts: 41
    • View Profile
Re: [PSP] Final Fantasy 4 Tile Map File
« Reply #1 on: April 24, 2020, 07:52:42 am »
Oh nice looks great!

Love to see stuff done with the PSP version of FF4

Everything

  • Jr. Member
  • **
  • Posts: 34
    • View Profile
Re: [PSP] Final Fantasy 4 Tile Map File
« Reply #2 on: April 24, 2020, 09:17:41 am »
Excellent work travisty! I'm glad to hear my editor was helpful.

The trigger layer in the GBA version is not actually a layer, it pulls data from an event script to determine where to draw triggers and NPCs. The PSP version looks pretty similar to the GBA version, so I would expect that triggers are stored in the same way.

My guess is that the third layer is for tile properties. In the GBA version, most maps have a third, non-graphics layer with two bytes per tile. One byte is for the lower z-level and the other byte is for the upper z-level (this allows for things like going under bridges and separating high areas from low areas). Unlike most other FF games (including the SNES version of FF4), there are no properties associated with tiles in the tileset.

Here's the format, in case anything is the same on the PSP version. Note that treasures and exits are included in tile properties, rather than as triggers (similar to FF1).

Code: [Select]
0x00 = tile is passable on this z-level
0x01 = tile is not passable on this z-level
0x02 = change from upper to lower z-level
0x03 = change from lower to upper z-level
0x04 = sprite hidden
0x05 = bridge tile (sprite hidden on lower z-level)
0x06 = tile causes damage
0x07 = unknown
0x10 = bottom half of sprite transparent (water tiles)
0x11 = bottom half of sprite hidden (grass tiles)
0x12 = unknown (used right before exits of some maps)
0x13 = unknown (used in some secret passages)
0x20 = treasure (low 5 bits determine treasure index)
0x40 = exit (low 5 bits determine exit index)

travisty

  • Jr. Member
  • **
  • Posts: 12
    • View Profile
Re: [PSP] Final Fantasy 4 Tile Map File
« Reply #3 on: April 24, 2020, 08:32:31 pm »
@Rudy: Thanks! I'd like to eventually build a tool that'll convert all of the tile maps into TMX files, so we can load everything up in the Tiled Map Editor. I could maybe even write a TMX -> cn2 converter one day that'll convert Tiled maps to FF4 maps.

@Everything: Thanks, Everything! Also, thank for sharing that table for the values. I'll have to look when I'm back at my computer, but I'm fairly confident it it'll work on the PSP version. I think the z-level stuff's making sense now. For example, when the player enters a map at an exit point, there's probably a way to determine which z-level to start that player off on. If the player is walking around on say, the lower z-level, and then walks on a tile where its lower z-level's value is 0x03, then the player's tile will move up in depth/draw order to the higher z-level. Then, once the player walks off of that tile, and back onto it, if that same tile's higher z-level byte value is 0x02, then the player will be on the lower z-level again, right?