• Welcome to Final Fantasy Hacktics. Please login or sign up.
 

My progress in FFTA hacking [Map, Events and Text editing] [Engine Hacks]

Started by Leonarth, July 16, 2018, 12:14:58 am

Dual-Wielding Ninja

So with the latest engine hack, is it possible, for example, for the Alchemist job to use "Conjure Potion" to use a Potion for free at the cost of MP? Or where they always able to do something like that before?
  • Modding version: Other/Unknown
  • Discord username: Dual-Wielding Ninja

Leonarth

Quote from: undefinedSo with the latest engine hack, is it possible, for example, for the Alchemist job to use "Conjure Potion" to use a Potion for free at the cost of MP? Or where they always able to do something like that before?

That's actually a good thing to bring up.
Although you could always have done that, doing so would have also costed a Potion, if the player had any. That's no longer the case, the item ability effects now only consume items when used through the Item ability.
  • Modding version: Other/Unknown

Dual-Wielding Ninja

Quote from: Leonarth on August 18, 2020, 06:25:44 pmThat's actually a good thing to bring up.
Although you could always have done that, doing so would have also costed a Potion, if the player had any. That's no longer the case, the item ability effects now only consume items when used through the Item ability.
That's great to hear! That means that one can effectively turn the Alchemist job into its X-2 incarnation in terms of function, and move most of its Abilities over to Sage.

Edit: In fact, is it also possible to make a function that basically works like the Mix Ability from X-2, via engine hack or through the Nightmare Module (or similar)?
  • Modding version: Other/Unknown
  • Discord username: Dual-Wielding Ninja

Leonarth

Quote from: undefinedIn fact, is it also possible to make a function that basically works like the Mix Ability from X-2, via engine hack or through the Nightmare Module (or similar)?
Through the existing engine hacks: no, nothing related to that has been done.
Through engine hacks in general?
Learn ASM, write the code, the GBA runs it. The specs are the limit.

What you are suggesting isn't really that far out there compared to what already exists in the game: you have Throw/Hurl (select an item, power is based on the item) and Double Cast (select two abilities) already, so the game even has built-in support for menus like that. It still wouldn't be an easy job, of course. It's also not something I'm interested in making, I had to look this up to even know what you were talking about.
  • Modding version: Other/Unknown

FlamingZelda

Three years later did the map editor ever find its way to a releasable form? I ask because Custom maps would be a huge boon to the FFT community and as another user mentioned, would add a level of strategy currently not present in the game.

Additionally, any chance on a Text editing tool for non Buildfile/EA users? I started my hack with AiO 2-3 years ago and I can't afford to restart in order to fix move descriptions.
  • Modding version: Other/Unknown

Leonarth

I've been very busy and I haven't really been able to work much on this or any of my other projects.
Most of my free time I use for relaxation, which I honestly think I need.

Quote from: undefineddid the map editor ever find its way to a releasable form
I never even started on a map editor, I used Tiled (as seen on my screenshot).
All I made was a python script that takes a tiled map and turns it into an event file.
It only really handles the visual part of the map.

The height of each map position, their terrain type (water, lava, column) and the allowed deployment positions have to be made by hand.
It does not handle insertion of the map, either, you have to write an installer for your map yourself.

I found there was no good way of using Tiled to make even the height map, which is an absolute basic feature of a ffta map, so I gave up on improving that further.

Quote from: undefinedtool for non Buildfile
If I ever make any tool it will only work for buildfiles.

Either way, what is wrong with your move descriptions? "broken" is very undescriptive.
  • Modding version: Other/Unknown

nitwit

Where is the map, event, and text data located, and how is it formatted?

Leonarth

That's a big question. Not an easy one to answer, there's a lot of ways data can be compressed, there's a ton of parts to a map entry (24 different atributes for a map), there's a ton of event instructions, there's a bunch of text tables...

It would take me days to write anything proper about maps or events, which is why I haven't really bothered doing it, two years ago or so I did write a python script that dumps all maps and their tilesets and palettes.
I could touch that up and send it your way if you are interested.

I also have WIP event assembler raws, which are descriptions of the event commands and their arguments that can be used with EA, as well as notes on how events are structured.

For text you can just go to Data Crystal, that should have most of the information you'd need.

Honestly, it's been simply too long since I was active on hacking this game, I don't remember all of the details so writing good doc is very hard, even when I made the custom map I just worried about understanding the parts I was changing and ignored the rest, so doc wouldn't be that comprehensive.

If you are really interested in one of the topics in particular (I assume you want to try your hand at making a tool?) let me know which one so I can focus on writing about that for you.
  • Modding version: Other/Unknown

nitwit

I just want whatever info you have out there in case anyone else wants to work on it. It's okay if you don't have perfect/complete explanations, so long as the location and structure of the data is correct. And if you just want to be done with it, upload what you have after verifying those things with whatever warnings and bugs you can remember.

Every time I've uploaded something after quitting it in disgust someone pops up a few days later that they were working on the same thing in parallel to me, so I just do everything openly now.

Leonarth

Quote from: undefinedafter quitting it in disgust
I did not quit, though, I simply saw that there was no way to properly make FFTA maps with Tiled.
A map editing tool specific to FFTA would need to be made, at least from what I have seen in generic tile editors.

Anyway, I put together some notes on maps, I'd like to know if there's any part of it that people feel needs further explanation.
Map table starts at: $569104
Number of entries: 0xA3
Size of an entry: 0x58

When accessing this table map ID is decreased by 1, so map ID 1 is the first entry, map ID 0 has no entry and instead produces a completely black map.

Map table:
0x00 Word Tileset graphics, relative offset (these are loaded to 0x06000000)
0x04 Word Tile arrangement for both layers, relative offset
0x08 Word Top layer behavior, relative offset
0x0C Short Relative offset to map palette for LCD A
0x0E Short pad?
0x10 Word Terrain map, relative offset
0x14 Word Main tile animations, relative offset
0x18 Word Main tile animation graphics, relative offset
0x1C Word Target VRAM offset for Main tile animations
0x20 Word Extra tile animations 1, relative offset
0x24 Word Extra tile animations 2, relative offset
0x28 Word Extra tile animations 3, relative offset
0x2C Word Extra tile animations 4, relative offset
0x30 Word Extra tile animation 1 graphics, relative offset
0x34 Word Extra tile animation 2 graphics, relative offset
0x38 Word Extra tile animation 3 graphics, relative offset
0x3C Word Extra tile animation 4 graphics, relative offset
0x40 Word Target VRAM offset for Extra tile animations 1
0x44 Word Target VRAM offset for Extra tile animations 2
0x48 Word Target VRAM offset for Extra tile animations 3
0x4C Word Target VRAM offset for Extra tile animations 4
0x50 Word pad?
0x54 Byte Sky palette id for LCD A
0x55 Byte Sky palette id for LCD B and TV
0x56 Byte Map palette id for LCD B and TV
0x57 Byte pad?

Relative offsets in Tile animations are added to their corresponding Tile animation graphics.

A map palette table entry is a short, relative offset to the start of that color mode's table.
Map palette tables start at:
LCD B: $42CC80
TV: $427A04
There is no LCD A table, as the LCD A map palettes are referenced through relative offsets.

All other relative offsets are always relative to the start of the table, $569104

Sky palettes do not work in the same way, I haven't really looked much into them, though.

Data accessed through relative offsets has a compression header.
Not all data can use every mode, for example, Tile arrangement only checks for modes 0x01, 0x10 and 0x11.

Palettes accessed through palette ID are always lzss compressed, with no compression header.

The compression header looks like this:
0x00 Byte Mode

if Mode is 0x00 or 0x02 (raw):
0x01 3Bytes Uncompressed data length
The rest of bytes are raw, uncompressed data

if Mode is 0x01 (raw, fixed size):
0x01 3Bytes Unused
The rest of bytes are raw, uncompressed data, Uncompressed data length is 0x4000 bytes

if Mode is 0x10 (lz77):
0x01 3Bytes Uncompressed data length
The rest of bytes are lz77 compressed data

if Mode is 0x11:
0x01 3Bytes Offset

if Offset is 0xFFFFFF:
Call the decompress routine again, passing the offset + 4 as the argument. For some reason.
I have only ever seen the mode on the new decompress call be 0x10, not sure what the point is.
else:
Get the word at Offset, and divide it by 256 (or >> 8), call this NewID.
Call decompress for Tile arrangement of map NewID (without substracting 1 from NewID).

if Mode is 0x12 (lz77):
0x01 Word Unused
0x05 3Bytes Uncompressed data length
The rest of bytes are lz77 compressed data

if Mode is 0x20 (lzss):
0x01 3Bytes Unused
0x04 Word Uncompressed data length
The rest of bytes are lzss compressed data

if Mode is 0x21:
??? Seems to never be used.
If modes 0x01 and 0x11 are anything to go by, this could be a map specific lzss mode.
That would simply mean the Uncompressed data length is fixed.
As it is never used, I never really bothered checking.

if Mode is 0x22 (lzss):
0x01 7Bytes Unused
0x08 Word Uncompressed data length
The rest of bytes are lzss compressed data

Data is decompressed before it can be accessed, the structures explained here are for the decompressed data.

Tile arrangement:
2 layers of:
64 rows of:
64 columns of:
0x00 Short Tile

The Bottom layer is first, the Top layer is second.
These tiles are stored in WRAM and then copied to VRAM as needed, so their format is just that of a regular GBA tile.
Layers are simply what the map looks like, they technically have no impact on gameplay.

The Bottom layer goes below the units, it contains most of what the map looks like.
Stuff on the Top layer goes above the Bototm layer. It goes below the units as well, unless specified otherwise by the Top layer behavior data.
The Top layer can easily be used as a way to add more detail to maps, which is something vanilla doesn't take advantage of.

Terrain map structure:
16 rows of:
16 columns of:
0x00 Byte Height of the terrain
0x01 Byte Type of the terrain
Positions start with the top left one, going right and down, as if reading.

Type of the terrain is actually a bitfield (not heavily tested):
0b0000 0000: No bits set, regular terrain
0b0000 0001: Can look at but can't walk on, however, can fly over
0b0000 0010: Water (can jump over, can stand on)
0b0000 0100: Can look at but can't even fly over
0b0000 1000: Can't look at and can't walk on
0b0001 0000: Nothing special?
0b0010 0000: Nothing special?
0b0100 0000: Nothing special?
0b1000 0000: Nothing special?

Top layer behavior:
64 rows of:
32 columns of:
0x00 Short Behavior
As you may have guessed, each column in the Top layer behaviour data affects two tiles of the Top layer in the Tile arrangement data.
Behavior is a packed struct that looks like this:
0b--YY YYHH HHH- XXXX
- denotes unused bits.

For example, if we had an X of 8, a Y of 12 and a H of 5:
X: 0b---- ---- ---- 1000
H: 0b---- --00 101- ----
Y: 0b--11 00-- ---- ----
Putting it all together:
0b0011 0000 1010 1000
Or, as a Short:
0x30A8

The purpose of this data is to determine when something in the Top layer goes in front of units, and when it goes behind them.
The X and Y components should correspond with the Terrain map tile this Top layer "object" would be "standing" on.
H should correspond with the height of that same Terrain Map tile.
I have not actually looked into how the game handles this data and what the actual checks look like, but going by these rules works fine enough.

Tile animations:
0x00 Short Length of graphics for each frame
0x02 Short Number of entries in the list
Then, for each entry:
0x00 Short Duration
0x02 Short Graphics relative offset (this gets multiplied by 0x20 after being read, which is the size of a tile)
  • Modding version: Other/Unknown

FlamingZelda

Quote from: Leonarth on November 14, 2021, 01:46:33 pmAnyway, I put together some notes on maps, I'd like to know if there's any part of it that people feel needs further explanation.
Map table starts at: $569104
Number of entries: 0xA3
Size of an entry: 0x58

When accessing this table map ID is decreased by 1, so map ID 1 is the first entry, map ID 0 has no entry and instead produces a completely black map.

Map table:
0x00 Word Tileset graphics, relative offset (these are loaded to 0x06000000)
0x04 Word Tile arrangement for both layers, relative offset
0x08 Word Top layer behavior, relative offset
0x0C Short Relative offset to map palette for LCD A
0x0E Short pad?
0x10 Word Terrain map, relative offset
0x14 Word Main tile animations, relative offset
0x18 Word Main tile animation graphics, relative offset
0x1C Word Target VRAM offset for Main tile animations
0x20 Word Extra tile animations 1, relative offset
0x24 Word Extra tile animations 2, relative offset
0x28 Word Extra tile animations 3, relative offset
0x2C Word Extra tile animations 4, relative offset
0x30 Word Extra tile animation 1 graphics, relative offset
0x34 Word Extra tile animation 2 graphics, relative offset
0x38 Word Extra tile animation 3 graphics, relative offset
0x3C Word Extra tile animation 4 graphics, relative offset
0x40 Word Target VRAM offset for Extra tile animations 1
0x44 Word Target VRAM offset for Extra tile animations 2
0x48 Word Target VRAM offset for Extra tile animations 3
0x4C Word Target VRAM offset for Extra tile animations 4
0x50 Word pad?
0x54 Byte Sky palette id for LCD A
0x55 Byte Sky palette id for LCD B and TV
0x56 Byte Map palette id for LCD B and TV
0x57 Byte pad?

Relative offsets in Tile animations are added to their corresponding Tile animation graphics.

A map palette table entry is a short, relative offset to the start of that color mode's table.
Map palette tables start at:
LCD B: $42CC80
TV: $427A04
There is no LCD A table, as the LCD A map palettes are referenced through relative offsets.

All other relative offsets are always relative to the start of the table, $569104

Sky palettes do not work in the same way, I haven't really looked much into them, though.

Data accessed through relative offsets has a compression header.
Not all data can use every mode, for example, Tile arrangement only checks for modes 0x01, 0x10 and 0x11.

Palettes accessed through palette ID are always lzss compressed, with no compression header.

The compression header looks like this:
0x00 Byte Mode

if Mode is 0x00 or 0x02 (raw):
0x01 3Bytes Uncompressed data length
The rest of bytes are raw, uncompressed data

if Mode is 0x01 (raw, fixed size):
0x01 3Bytes Unused
The rest of bytes are raw, uncompressed data, Uncompressed data length is 0x4000 bytes

if Mode is 0x10 (lz77):
0x01 3Bytes Uncompressed data length
The rest of bytes are lz77 compressed data

if Mode is 0x11:
0x01 3Bytes Offset

if Offset is 0xFFFFFF:
Call the decompress routine again, passing the offset + 4 as the argument. For some reason.
I have only ever seen the mode on the new decompress call be 0x10, not sure what the point is.
else:
Get the word at Offset, and divide it by 256 (or >> 8), call this NewID.
Call decompress for Tile arrangement of map NewID (without substracting 1 from NewID).

if Mode is 0x12 (lz77):
0x01 Word Unused
0x05 3Bytes Uncompressed data length
The rest of bytes are lz77 compressed data

if Mode is 0x20 (lzss):
0x01 3Bytes Unused
0x04 Word Uncompressed data length
The rest of bytes are lzss compressed data

if Mode is 0x21:
??? Seems to never be used.
If modes 0x01 and 0x11 are anything to go by, this could be a map specific lzss mode.
That would simply mean the Uncompressed data length is fixed.
As it is never used, I never really bothered checking.

if Mode is 0x22 (lzss):
0x01 7Bytes Unused
0x08 Word Uncompressed data length
The rest of bytes are lzss compressed data

Data is decompressed before it can be accessed, the structures explained here are for the decompressed data.

Tile arrangement:
2 layers of:
64 rows of:
64 columns of:
0x00 Short Tile

The Bottom layer is first, the Top layer is second.
These tiles are stored in WRAM and then copied to VRAM as needed, so their format is just that of a regular GBA tile.
Layers are simply what the map looks like, they technically have no impact on gameplay.

The Bottom layer goes below the units, it contains most of what the map looks like.
Stuff on the Top layer goes above the Bototm layer. It goes below the units as well, unless specified otherwise by the Top layer behavior data.
The Top layer can easily be used as a way to add more detail to maps, which is something vanilla doesn't take advantage of.

Terrain map structure:
16 rows of:
16 columns of:
0x00 Byte Height of the terrain
0x01 Byte Type of the terrain
Positions start with the top left one, going right and down, as if reading.

Type of the terrain is actually a bitfield (not heavily tested):
0b0000 0000: No bits set, regular terrain
0b0000 0001: Can look at but can't walk on, however, can fly over
0b0000 0010: Water (can jump over, can stand on)
0b0000 0100: Can look at but can't even fly over
0b0000 1000: Can't look at and can't walk on
0b0001 0000: Nothing special?
0b0010 0000: Nothing special?
0b0100 0000: Nothing special?
0b1000 0000: Nothing special?

Top layer behavior:
64 rows of:
32 columns of:
0x00 Short Behavior
As you may have guessed, each column in the Top layer behaviour data affects two tiles of the Top layer in the Tile arrangement data.
Behavior is a packed struct that looks like this:
0b--YY YYHH HHH- XXXX
- denotes unused bits.

For example, if we had an X of 8, a Y of 12 and a H of 5:
X: 0b---- ---- ---- 1000
H: 0b---- --00 101- ----
Y: 0b--11 00-- ---- ----
Putting it all together:
0b0011 0000 1010 1000
Or, as a Short:
0x30A8

The purpose of this data is to determine when something in the Top layer goes in front of units, and when it goes behind them.
The X and Y components should correspond with the Terrain map tile this Top layer "object" would be "standing" on.
H should correspond with the height of that same Terrain Map tile.
I have not actually looked into how the game handles this data and what the actual checks look like, but going by these rules works fine enough.

Tile animations:
0x00 Short Length of graphics for each frame
0x02 Short Number of entries in the list
Then, for each entry:
0x00 Short Duration
0x02 Short Graphics relative offset (this gets multiplied by 0x20 after being read, which is the size of a tile)

Thank you this is very helpful

Quote from: Leonarth on November 13, 2021, 01:11:50 pmEither way, what is wrong with your move descriptions? "broken" is very undescriptive.

They're not broken, they're just totally inaccurate. Subdue for example used to deal 1-12 dmg, now it does a weak strike and stuns an enemy for a turn. I'm just gonna have to release a txt file alongside my hack which gives all the jobs' abilities and growth rates alongside an updated job tree.
  • Modding version: Other/Unknown

nitwit

Thanks for posting your data, I don't have much else to add but you may want to add links to the first post in the thread of all the important posts.

dck

Quote from: FlamingZelda on November 14, 2021, 04:39:43 pmThey're not broken, they're just totally inaccurate. Subdue for example used to deal 1-12 dmg, now it does a weak strike and stuns an enemy for a turn. I'm just gonna have to release a txt file alongside my hack which gives all the jobs' abilities and growth rates alongside an updated job tree.
Basically, if you want to use the buildfile for Leo's engine hacks you'll need to also install its text modification features as well- this will make it so you have to also use these text modification features to handle any further text changes your hack needs as well; there might be a few very small changes that don't depend on the text installer, but for most stuff it's a requirement.

Afaik there's no released text editor that just writes to the rom directly (though iirc one exists), but the way I did all the custom text in mine was just writing over existing entries directly in a hex editor. It's surprisingly lenient (you can make follow-up textboxes and stuff) so long as you have some stuff to cannibalize like removed laws, cards or whatever.

Still, I would never recommend doing this- it's simply incompatible with Leo's engine hacks and they are by far the biggest leap in hacking development since AiO came around.

This is, incidentally, the one largest change left in my own hack stalling progress for lack of putting time to learn using it.
  • Modding version: Other/Unknown
  • Discord username: adri#1824

Dual-Wielding Ninja

Quote from: Leonarth on August 18, 2020, 11:52:48 pmThrough the existing engine hacks: no, nothing related to that has been done.
Through engine hacks in general?
Learn ASM, write the code, the GBA runs it. The specs are the limit.

What you are suggesting isn't really that far out there compared to what already exists in the game: you have Throw/Hurl (select an item, power is based on the item) and Double Cast (select two abilities) already, so the game even has built-in support for menus like that. It still wouldn't be an easy job, of course. It's also not something I'm interested in making, I had to look this up to even know what you were talking about.
Almost a year and a half late, but fair point. Was just curious for the most part.
  • Modding version: Other/Unknown
  • Discord username: Dual-Wielding Ninja