The current URL is datacrystal.tcrf.net.
Final Fantasy/ROM map: Difference between revisions
m (Starting Stats (incomplete)) |
m (Xkeeper moved page Final Fantasy:ROM map to Final Fantasy/ROM map: normalize subpages and titles) |
||
(42 intermediate revisions by 10 users not shown) | |||
Line 1: | Line 1: | ||
{{rommap|game= | {{rommap|game=Final Fantasy}} | ||
== Disassembly == | |||
For a detailed byte-for-byte treatment of the ROM, consult Anomie's disassembly.<br> | |||
It's available in the RHDN documents section:<br> | |||
[https://www.romhacking.net/documents/663/ Anomie's FF1 Disassembly with Bugfix & Enhancement Patches] | |||
The disassembly has a separate text file for each of the game's 16 banks. | |||
Each file contains all bytes in the file, with each line being a row of 16 bytes.<br> | |||
Each line has the bank address at the start of the line, it looks like this:<br> | |||
<tt>ac70: 36 30 41 3f b8 36 3f c1 05 3a 41 3e b8 38 3e 3f</tt> | |||
Line 52: | Line 65: | ||
== Starting Stats == | == Starting Stats == | ||
There are 11 bytes for each character. | There are 11 bytes for each character. 5 bytes with the value of "00" are used to seperate each character. Bytes are ordered as follows: Fighter, Thief, Black Belt, Red Mage, White Mage, Black Mage. | ||
* <tt>0x3050 to 0x----- (0001)</tt> = Fighter's Listing Byte (normally 00) | * <tt>0x3050 to 0x----- (0001)</tt> = Fighter's Listing Byte (normally 00) | ||
* <tt>0x3051 to 0x----- (0001)</tt> = Fighter's Starting HP (normally 23) | * <tt>0x3051 to 0x----- (0001)</tt> = Fighter's Starting HP (normally 23) | ||
Line 62: | Line 75: | ||
* <tt>0x3057 to 0x----- (0001)</tt> = Fighter's Starting Damage (normally 0A) | * <tt>0x3057 to 0x----- (0001)</tt> = Fighter's Starting Damage (normally 0A) | ||
* <tt>0x3058 to 0x----- (0001)</tt> = Fighter's Starting Hit% (normally 0A) | * <tt>0x3058 to 0x----- (0001)</tt> = Fighter's Starting Hit% (normally 0A) | ||
* <tt>0x3059 to 0x----- (0001)</tt> = Fighter's Starting Evade% (normally 35)<br><br> | * <tt>0x3059 to 0x----- (0001)</tt> = Fighter's Starting Evade% (normally 35) | ||
* <tt> | * <tt>0x305A to 0x----- (0001)</tt> = Fighter's Starting MagDef% (normally 15)<br><br> | ||
* <tt> | * <tt>0x3060 to 0x----- (0001)</tt> = Thief's Listing Byte (normally 01) | ||
* <tt>0x3061 to 0x----- (0001)</tt> = Thief's Starting HP (normally 1E) | |||
== Main Menu Hand Cursor Data == | == Main Menu Hand Cursor Data == | ||
Line 100: | Line 114: | ||
== Random Window Stuff == | == Random Window Stuff == | ||
* <tt>0x3D630</tt> = window open speed | |||
* <tt>0x3D6A9</tt> = window close speed | |||
* <tt>0x3E0AA to 0x----- (0001)</tt> = horizontal spacing between text and left boundary of window | * <tt>0x3E0AA to 0x----- (0001)</tt> = horizontal spacing between text and left boundary of window | ||
* <tt>0x3E0B1 to 0x----- (0001)</tt> = vertical spacing between text and top boundary of window | * <tt>0x3E0B1 to 0x----- (0001)</tt> = vertical spacing between text and top boundary of window | ||
Line 124: | Line 140: | ||
* <tt>0x3F308 to 0x----- (0001)</tt> = character battle border Width | * <tt>0x3F308 to 0x----- (0001)</tt> = character battle border Width | ||
* <tt>0x3F30A to 0x----- (0001)</tt> = character battle border Height | * <tt>0x3F30A to 0x----- (0001)</tt> = character battle border Height | ||
* <tt>0x3f3a3 to 0x------(0001)</tt> = background width | |||
* <tt>0x3f384 to 0x3f386 (0001)</tt> = menu fill | |||
* <tt>0x3F3E0 to 0x----- (0001)</tt> = stat battle width for all 4 stat windows | * <tt>0x3F3E0 to 0x----- (0001)</tt> = stat battle width for all 4 stat windows | ||
* <tt>0x3F30F to 0x----- (0001)</tt> = stat battle x position for all 4 stat windows | * <tt>0x3F30F to 0x----- (0001)</tt> = stat battle x position for all 4 stat windows | ||
Line 130: | Line 148: | ||
* <tt>0x3F31B to 0x----- (0001)</tt> = stat battle window 2 y position | * <tt>0x3F31B to 0x----- (0001)</tt> = stat battle window 2 y position | ||
* <tt>0x3F320 to 0x----- (0001)</tt> = stat battle window 1 y position | * <tt>0x3F320 to 0x----- (0001)</tt> = stat battle window 1 y position | ||
* <tt>0x3F355 to 0x----- (0001)</tt> = row 1 BG × position and type | |||
* <tt>0x3F39D to 0x----- (0001)</tt> = how many tiles the first section of the BG should draw | * <tt>0x3F39D to 0x----- (0001)</tt> = how many tiles the first section of the BG should draw | ||
* <tt>0x3F3AA to 0x----- (0001)</tt> = how many tiles the second section of the BG should draw | * <tt>0x3F3AA to 0x----- (0001)</tt> = how many tiles the second section of the BG should draw | ||
Line 136: | Line 155: | ||
* <tt>0x3F36B to 0x----- (0001)</tt> = row 3 BG environment tile set (00,04,08,0C) | * <tt>0x3F36B to 0x----- (0001)</tt> = row 3 BG environment tile set (00,04,08,0C) | ||
* <tt>0x3F372 to 0x----- (0001)</tt> = row 4 BG environment tile set (00,04,08,0C) | * <tt>0x3F372 to 0x----- (0001)</tt> = row 4 BG environment tile set (00,04,08,0C) | ||
* <tt>0x3f64c to 0x3f653 (0001)</tt> = bottom of enemy border | |||
* <tt>0x3F410 to 0x3F44F (0040)</tt> = Battle Screen [[Attribute Data]] | * <tt>0x3F410 to 0x3F44F (0040)</tt> = Battle Screen [[Attribute Data]] | ||
* <tt>0x3F9F5 to 0x----- (0001)</tt> = Enemy window X coordinate | * <tt>0x3F9F5 to 0x----- (0001)</tt> = Enemy window X coordinate | ||
Line 213: | Line 233: | ||
* <tt>0x3FA67 to 0x----- (0001)</tt> = value for which string to display in Enemy name slot 4 | * <tt>0x3FA67 to 0x----- (0001)</tt> = value for which string to display in Enemy name slot 4 | ||
[[ | == World map data == | ||
World map data is stored in ROM Bank 0x01, which is accessed by the CPU at address 0x8000, and located at 0x4000 in the ROM image. (0x4010 for iNES files). | |||
The data begins with a 256 entry table of 2-byte memory addresses (CPU addresses), pointing to the first (left-most) tile of each row of the world map. Since the map tile data is compressed, this index table allows quick access to the map data. | |||
The actual world map tile data starts at CPU address 0x8200. Each entry in this data area is either 1 byte or 2 bytes long. The most significant bit of the first byte is set if there is a second byte for this entry. The first byte (excluding the MSB flag) specifies the tile number (0-127). The second byte, if present, specifies the number of tiles that should be displayed. If the second byte is 2, then two tiles should be rendered. If the second byte is 0, then the tile should be rendered 256 times. A single byte entry with the value of 0xFF represents the end of the row. | |||
* See [[Final Fantasy:World map data]]. | |||
== Town and dungeon map data == | |||
Town and dungeon map data is similar to the world map data. It is compressed with the same 1/2 byte method, but it does not contain a single byte 0xFF value at the end of each row. Instead, each row is 64 tiles wide, and any 2-byte tiles that extend beyond the last tile will wrap around and continue on the next row. There is a single byte 0xFF value at the end of the map. | |||
There is a table of 2-byte CPU address pointers located at the beginning of Bank 4 which contains the start of each map. The 2 most significant bits of each entry specifies the bank number (starting from Bank 4), and the remaining 14 bits specifies the CPU address of the map, starting at 0x8000. | |||
Each map also has 16 entries in a table located on bank 0 at CPU address 0xB400 which define any objects located on that map. This includes Bosses, NPCs, bats, magic brooms, etc. Each entry is 3 bytes long. Byte 1 is the object type. Byte 2 is the X position, and byte 3 is the Y position. Byte 2 also contains behavior flags. If bit 7 (0x80) is set, this object is inside of a room. If bit 6 is set (0x40), this object does not move. | |||
After the map tiles have been "decompressed" into RAM in a 64x64 grid, the map effectively wraps in both the horizontal and vertical directions. Walking to the left of the map will seamlessly continue on the right of the map, and standing near the left side of the map will draw tiles from the right side of the map. | |||
== Free bytes in the original FF1 ROM == | |||
This is a list of known free bytes available in the original FF1 ROM.<br> | |||
These bytes were gleaned from examining the ROM, Disch's 1.0 Disassembly, and Anomie's Disassembly.<br> | |||
Each Bank section below denotes the following: | |||
* Offset Adjustment as a +/- hex value e.g. <tt><b><i>-28010</i></b> (37 total bytes)</tt><br> | |||
* Total free bytes in the whole bank as a decimal value in parens e.g. <tt>-28010 <b><i>(37 total bytes)</i></b></tt><br> | |||
* a list of entries having the form in the form <tt>851C : 0x3052C (4 bytes)</tt> | |||
** The N bytes next to each offset in parens is the count (in decimal) of free bytes starting at <i>that</i> offset.<br> | |||
** For each entry listed, the ROM offset = the Bank offset + the Offset Adjustment value (which can be negative or positive).<br> | |||
===BANK 01=== | |||
+3FF0 (30 total bytes) | |||
* <tt>BFE2 : 0x07FF2 (30 bytes)</tt> | |||
===BANK 06=== | |||
- 10010 (? total bytes) | |||
* <tt>ACAA : 0x (4,950 bytes <u><b>with a <i>HUGE</i> caveat</b></u>)</tt> | |||
<b>Be very careful if putting any routines or data in this area.</b><br> | |||
Explanation:<br> | |||
There are 61 standard maps in the original game, the last being Titan's Tunnel.<br> | |||
Standard maps use variable length storage with a Run-Length Encoding (RLE) style compression scheme, | |||
so instead of a fixed size, they end with a byte having the value FF (the end of map marker value).<br> | |||
Standard map data is stored in an area of ROM stretching from Bank 04 to the end of Bank 06.<br> | |||
All of the bytes in bank 06 after that last map's FF byte are zeroed out.<br> | |||
Coincidentally (or not?) the last 3 pointers in the standard map pointer table (maps 62-64) are also zeroed out.<br> | |||
The issue is that when the standard maps are saved, they're rewritten in RLE-compressed form, which means the | |||
data can grow or shrink.<br> | |||
As a result, <b>all data after the last map's FF byte can slide forward or backward as a result.</b><br> | |||
So pay attention if using this area in your ROM hack; assembly labels will automatically handle relocated routines, | |||
but hackers using hex editors will have to update variable references, branches, and jumps whenever map edits cause the code to move. | |||
{{note|Some FF1 editing tools might truncate any bytes that slide forward past the end of bank 06 (i.e. no bytes are allowed to move past 0x1C00F). Consult your tool's documentation or experiment on a test ROM to determine how the tool handles this scenario and plan accordingly.}} | |||
===BANK 09=== | |||
-1c010 (475 <b>?</b> total bytes) | |||
* <tt>B980 : 0x27990 (384 bytes)</tt> | |||
{{note|These 384 bytes apparently define an unused graphic and a series of alternating black and white tiles that don't appear in the game.}} | |||
* <tt>BBDA : 0x27BEA (38 bytes)</tt> | |||
* <tt>BEEB : 0x27EFB (21 bytes)</tt> | |||
* <tt>BF30 : 0x27F40 (4 bytes)</tt> | |||
* <tt>BF67 : 0x27F77 (25 bytes)</tt> | |||
===BANK 0B=== | |||
-24010 (5 total bytes) | |||
<br> | |||
{{note|In the disassembly, {{0x|2C010}} : {{$|8000}} is identified as 1024 bytes of unknown space, but this is actually the overworld battle domain data. It's stored in the <tt>bin/0B_8000_unknown.bin</tt> file and incbin'd into the assembly source file for Bank 0B.}} | |||
{{note|In the disassembly, {{0x|2CFFC}} : {{$|8FEC}} is identified as 20 bytes of unused space, but this is actually the battle message "Nothing happens". It is the only battle message stored after the battle message pointer table. In the <tt>bank_0B.asm</tt> source file, this is stored as a series of inline bytes (not an incbin'd file).}} | |||
* <tt>9093 : 0x2DA03 (1 bytes)</tt> | |||
* <tt>A7FC : 0x2E80C (4 bytes)</tt> | |||
===BANK 0C=== | |||
-28010 (37 total bytes) | |||
* <tt>851C : 0x3052C (4 bytes)</tt> (padding) | |||
* <tt>92F4 : 0x31304 (12 bytes)</tt> | |||
* <tt>BC95 : 0x33CA5 (16 bytes)</tt> (maybe) | |||
* <tt>BFFB : 0x3400B (5 bytes)</tt> | |||
===BANK 0D=== | |||
-2C010 (70 total bytes) | |||
* <tt>9DF9 : 0x35E09 (7 bytes)</tt> | |||
* <tt>A779 : 0x36789 (7 bytes)</tt> | |||
* <tt>A7E5 : 0x367F5 (27 bytes)</tt> (almost looks like it might be attributes) | |||
* <tt>AE02 : 0x36E12 (14 bytes)</tt> ?unused -- fragmented code? | |||
* <tt>AFFE : 0x3700E (2 bytes)</tt> (that $60 might be an unused RTS -- but who cares) | |||
* <tt>BA9F : 0x37AAF (1 bytes)</tt> | |||
* <tt>BAF9 : 0x37B09 (7 bytes)</tt> (unknown / unused) | |||
* <tt>BEFB : 0x37F0B (5 bytes)</tt> | |||
===BANK 0E=== | |||
-30010 (114 total bytes) | |||
* <tt>84E2 : 0x384F2 (30 bytes)</tt> | |||
* <tt>9088 : 0x39098 (9 bytes)</tt> (ClearGameEventFlag unused by the original game) | |||
* <tt>94EF : 0x394FF (1 bytes)</tt> (truly unused -- no entry in the jump table) | |||
* <tt>9586 : 0x39596 (14 bytes)</tt> Talk_CubeBotBad | |||
* <tt>9B3E : 0x39B4E (22 bytes)</tt> UnusedRoutine_9B3E, Faux/Unused routine | |||
* <tt>BF3A : 0x3BF4A (22 bytes)</tt> Unused Phantom Code | |||
* <tt>BFF0 : 0x3C000 (16 bytes)</tt> | |||
===BANK 0F=== | |||
-30010 (126 total bytes) | |||
* <tt>C464 : 0x3C474 (5 bytes)</tt> | |||
* <tt>D7BF : 0x3D7CF (3 bytes)</tt> (unused/unreachable call) | |||
* <tt>DB09 : 0x3DB19 (2 bytes)</tt> (unused NOPs) | |||
* <tt>E4BF : 0x3E4CF (8 bytes)</tt> | |||
* <tt>ECB9 : 0x3ECC9 (1 bytes)</tt> | |||
* <tt>FCBB : 0x3FCCB (7 bytes)</tt> (UNUSED_DrawBattle_IncSrcPtr) | |||
* <tt>FDF1 : 0x3FE01 (15 bytes)</tt> (Unused space) | |||
* <tt>FEEB : 0x3FEFB (23 bytes)</tt> | |||
* <tt>FF3C : 0x3FF4C (4 bytes)</tt> | |||
* <tt>FF81 : 0x3FF91 (15 bytes)</tt> | |||
* <tt>FFA4 : 0x3FFB4 (4 bytes)</tt> | |||
* <tt>FFB9 : 0x3FFC9 (7 bytes)</tt> | |||
* <tt>FFCD : 0x3FFDD (22 bytes)</tt> space before "FINAL FANTASY" | |||
* <tt>FFF0 : 0x40000 (10 bytes)</tt> space after "FINAL FANTASY" | |||
== Unused routines in the original US FF1 ROM == | |||
The following routines are either completely or partially unused | |||
in the original US FF1 ROM and can be recycled as free space. | |||
===Bank C=== | |||
* [$B674 :: 0x33684] lut_IBCharStatsPtrTable_alt (8 bytes) | |||
* [$B67C :: 0x3368C] lut_CharStatsPtrTable_alt (8 bytes) | |||
These are duplicates of the lut_IBCharStatsPtrTable and | |||
lut_CharStatsPtrTable tables. References to the duplicates | |||
can be updated to point to the originals, and the 16 contiguous | |||
bytes here can be used for other LUTs or a short routine. | |||
* [$B684 :: 0x33694] PreparePlayerMagAttack (41 bytes) | |||
41 of the last 42 bytes in this routine perform tasks that have no effect. | |||
Those bytes can be moved out of the routine and used for other tasks. | |||
* [$B730 :: 0x33740] PrepareEnemyMagAttack (39 bytes) | |||
The entire routine loads stats that simply aren't used by the routine | |||
or its caller. | |||
===Bank E=== | |||
* [$BEF7 :: 0x3BF07] UpdateEquipMenuModeAttrib (55 bytes) | |||
Likely a holdover from the Japanese version, it has no visible effect | |||
in the US version (since the palettes involved are identical) and | |||
would need to be refactored to work as intended anyway. | |||
===Bank F=== | |||
* [$FAA6 :: 0x3FAB6] DrawBattleString_ExpandChar (55 bytes) | |||
Another holdover from the Japanese version, part of this function | |||
attempts to assign the top half of characters when drawing a string. | |||
The default is a blank (space) character. | |||
Since this is always a space character in the US ROM, the code | |||
to choose that top tile could be removed, since a space will always | |||
be used. | |||
{{Internal Data|game=Final Fantasy}} |
Latest revision as of 02:41, 24 January 2024
The following article is a ROM map for Final Fantasy.
Disassembly
For a detailed byte-for-byte treatment of the ROM, consult Anomie's disassembly.
It's available in the RHDN documents section:
Anomie's FF1 Disassembly with Bugfix & Enhancement Patches
The disassembly has a separate text file for each of the game's 16 banks.
Each file contains all bytes in the file, with each line being a row of 16 bytes.
Each line has the bank address at the start of the line, it looks like this:
ac70: 36 30 41 3f b8 36 3f c1 05 3a 41 3e b8 38 3e 3f
Intro Values
- 0x37F30 to 0x38000 (00D0) = Intro text, #$00 ends text
- 0x3A12C to 0x----- (0001) = Intro text background color, original value = #$01
- 0x3A2E3 to 0x----- (0001) = Text 'default' color after flicker, returns to this color
- 0x3A2B8 to 0x----- (0001) = Text color that the above flicker math routine is applied to
- 0x3A2C8 to 0x----- (0001) = Intro fade-in speed. Lower = fast & higher = slower, original value = #$0F
- 0x3EB40 to 0x----- (0001) = Text color after flicker effect has been applied on text line
- 0x3EB48 to 0x----- (0001) = Text 'color number 02' after flicker effect
Game Selecting Values
- 0x3A263 - 0x3A281 (001F) = New Game/Continue/Respond Rate text
- 0x384B8 - 0x384C7 (0010) = Copyright (for Square and Nintendo) text
- 0x36843 - 0x36843 (0010) = Copyright (for Square and Nintendo) text
Starting Items
For Tents/Cabins/Houses and the Potions, the number given is the amount of them with which you start (eg., to start with 10 heal potions, set the byte at $3049 to $0A). For the rest, supply any non-zero value to start with that item.
- 0x3026 to 0x----- (0001) = Sets off bridge scene prematurarly when game starts
- 0x3031 to 0x----- (0001) = Lute
- 0x3032 to 0x----- (0001) = Crown
- 0x3033 to 0x----- (0001) = Crystal
- 0x3034 to 0x----- (0001) = Herb
- 0x3035 to 0x----- (0001) = Mystic Key
- 0x3036 to 0x----- (0001) = TNT
- 0x3037 to 0x----- (0001) = Adamant
- 0x3038 to 0x----- (0001) = Slab
- 0x3039 to 0x----- (0001) = Ruby
- 0x303A to 0x----- (0001) = Rod
- 0x303B to 0x----- (0001) = Floater
- 0x303C to 0x----- (0001) = Chime
- 0x303D to 0x----- (0001) = Tail
- 0x303E to 0x----- (0001) = Cube
- 0x303F to 0x----- (0001) = Bottle
- 0x3040 to 0x----- (0001) = Oxyale
- 0x3041 to 0x----- (0001) = Canoe appears on items screen (not working Canoe)
- 0x3042 to 0x----- (0001) = Orb 1
- 0x3043 to 0x----- (0001) = Orb 2
- 0x3044 to 0x----- (0001) = Orb 3
- 0x3045 to 0x----- (0001) = Orb 4
- 0x3046 to 0x----- (0001) = Tents
- 0x3047 to 0x----- (0001) = Cabins
- 0x3048 to 0x----- (0001) = Houses
- 0x3049 to 0x----- (0001) = Heal Potions
- 0x304A to 0x----- (0001) = Pure Potions
- 0x304B to 0x----- (0001) = Soft Potions
Starting Stats
There are 11 bytes for each character. 5 bytes with the value of "00" are used to seperate each character. Bytes are ordered as follows: Fighter, Thief, Black Belt, Red Mage, White Mage, Black Mage.
- 0x3050 to 0x----- (0001) = Fighter's Listing Byte (normally 00)
- 0x3051 to 0x----- (0001) = Fighter's Starting HP (normally 23)
- 0x3052 to 0x----- (0001) = Fighter's Starting Strength (normally 14)
- 0x3053 to 0x----- (0001) = Fighter's Starting Agility (normally 05)
- 0x3054 to 0x----- (0001) = Fighter's Starting Intellect (normally 01)
- 0x3055 to 0x----- (0001) = Fighter's Starting Vitality (normally 0A)
- 0x3056 to 0x----- (0001) = Fighter's Starting Luck (normally 05)
- 0x3057 to 0x----- (0001) = Fighter's Starting Damage (normally 0A)
- 0x3058 to 0x----- (0001) = Fighter's Starting Hit% (normally 0A)
- 0x3059 to 0x----- (0001) = Fighter's Starting Evade% (normally 35)
- 0x305A to 0x----- (0001) = Fighter's Starting MagDef% (normally 15)
- 0x3060 to 0x----- (0001) = Thief's Listing Byte (normally 01)
- 0x3061 to 0x----- (0001) = Thief's Starting HP (normally 1E)
Main Menu Hand Cursor Data
- 0x3B636 to 0x----- (0001) = X position of Character4 Sprite
- 0x3B64A to 0x----- (0001) = Y position of Character4 Sprite
- 0x3B8AC to 0x----- (0001) = X position of ORB 1
- 0x3B8AE to 0x----- (0001) = Y position of ORB 1
- 0x3B7E9 to 0x----- (0001) = X position of Character1 Hand Cursor
- 0x3B7EA to 0x----- (0001) = Y position of Character1 Hand Cursor
- 0x3B7EB to 0x----- (0001) = X position of Character2 Hand Cursor
- 0x3B7EC to 0x----- (0001) = Y position of Character2 Hand Cursor
- 0x3B7ED to 0x----- (0001) = X position of Character3 Hand Cursor
- 0x3B7EE to 0x----- (0001) = Y position of Character3 Hand Cursor
- 0x3B7EF to 0x----- (0001) = X position of Character4 Hand Cursor
- 0x3B7F0 to 0x----- (0001) = Y position of Character4 Hand Cursor
- 0x3B7F1 to 0x----- (0001) = Y position of ITEM Hand Cursor
- 0x3B7F2 to 0x----- (0001) = Y position of MAGIC Hand Cursor
- 0x3B7F3 to 0x----- (0001) = Y position of WEAPON Hand Cursor
- 0x3B7F4 to 0x----- (0001) = Y position of STATUS Hand Cursor
Default Character Screen Data
- 0x3A0C4 to 0x----- (0001) = X position of 4 letter name
- 0x3A0C5 to 0x----- (0001) = Y position of 4 letter name
- 0x3A0C6 to 0x----- (0001) = X position of Class Title
- 0x3A0C7 to 0x----- (0001) = Y position of Class Title
- 0x3A0C8 to 0x----- (0001) = X position of Character Sprite
- 0x3A0C9 to 0x----- (0001) = Y position of Character Sprite
- 0x3A0CA to 0x----- (0001) = X position of Background Window
- 0x3A0CB to 0x----- (0001) = Y position of Background Window
- 0x3A0CC to 0x----- (0001) = X position of Hand Cursor
- 0x3A0CD to 0x----- (0001) = Y position of Hand Cursor
Random Window Stuff
- 0x3D630 = window open speed
- 0x3D6A9 = window close speed
- 0x3E0AA to 0x----- (0001) = horizontal spacing between text and left boundary of window
- 0x3E0B1 to 0x----- (0001) = vertical spacing between text and top boundary of window
- 0x3E082 to 0x----- (0001) = horizontal window border subtraction
- 0x3E089 to 0x----- (0001) = vertical window border subtraction
Battle Values
- 0x31751 to 0x----- (0001) = all characters default sprite staring X coordinates
- 0x3175F to 0x----- (0001) = character 1 default sprite Y coordinate
- 0x31764 to 0x----- (0001) = character 2 default sprite Y coordinate
- 0x31769 to 0x----- (0001) = character 3 default sprite Y coordinate
- 0x3176E to 0x----- (0001) = character 4 default sprite Y coordinate
- 0x3E0C8 to 0x----- (0001) = where (on name table) to load left window tile, original vaue $FA
- 0x3E0CD to 0x----- (0001) = where (on name table) to load background tile, original vaue $FF
- 0x3E0D5 to 0x----- (0001) = where (on name table) to load right tile, original vaue $FB
- 0x3E11F to 0x----- (0001) = where (on name table) to load upper-left tile, original vaue $F7
- 0x3E124 to 0x----- (0001) = where (on name table) to load top tile, original vaue $F8
- 0x3E12C to 0x----- (0001) = where (on name table) to load upper-right tile, original vaue $F9
- 0x3F2F5 to 0x----- (0001) = main battle border X & Y position
- 0x3F2FA to 0x----- (0001) = main battle border Width (should not be below 3)
- 0x3F2FC to 0x----- (0001) = main battle border Height (should not be below 3)
- 0x3F301 to 0x----- (0001) = character battle border X position
- 0x3F306 to 0x----- (0001) = character battle border Y position
- 0x3F308 to 0x----- (0001) = character battle border Width
- 0x3F30A to 0x----- (0001) = character battle border Height
- 0x3f3a3 to 0x------(0001) = background width
- 0x3f384 to 0x3f386 (0001) = menu fill
- 0x3F3E0 to 0x----- (0001) = stat battle width for all 4 stat windows
- 0x3F30F to 0x----- (0001) = stat battle x position for all 4 stat windows
- 0x3F311 to 0x----- (0001) = stat battle window 4 y position
- 0x3F316 to 0x----- (0001) = stat battle window 3 y position
- 0x3F31B to 0x----- (0001) = stat battle window 2 y position
- 0x3F320 to 0x----- (0001) = stat battle window 1 y position
- 0x3F355 to 0x----- (0001) = row 1 BG × position and type
- 0x3F39D to 0x----- (0001) = how many tiles the first section of the BG should draw
- 0x3F3AA to 0x----- (0001) = how many tiles the second section of the BG should draw
- 0x3F35D to 0x----- (0001) = row 1 BG environment tile set (00,04,08,0C)
- 0x3F364 to 0x----- (0001) = row 2 BG environment tile set (00,04,08,0C)
- 0x3F36B to 0x----- (0001) = row 3 BG environment tile set (00,04,08,0C)
- 0x3F372 to 0x----- (0001) = row 4 BG environment tile set (00,04,08,0C)
- 0x3f64c to 0x3f653 (0001) = bottom of enemy border
- 0x3F410 to 0x3F44F (0040) = Battle Screen Attribute Data
- 0x3F9F5 to 0x----- (0001) = Enemy window X coordinate
- 0x3F9F6 to 0x----- (0001) = Enemy window Y coordinate
- 0x3F9F7 to 0x----- (0001) = Enemy window Width
- 0x3F9F8 to 0x----- (0001) = Enemy window Height
- 0x3F9FA to 0x----- (0001) = current Attacker window X coordinate
- 0x3F9FB to 0x----- (0001) = current Attacker window Y coordinate
- 0x3F9FC to 0x----- (0001) = current Attacker window Width
- 0x3F9FD to 0x----- (0001) = current Attacker window Height
- 0x3F9FF to 0x----- (0001) = current Attacker text X coordinate
- 0x3FA00 to 0x----- (0001) = current Attacker text Y coordinate
- 0x3FA02 to 0x----- (0001) = hit number window X coordinate
- 0x3FA03 to 0x----- (0001) = hit number window Y coordinate
- 0x3FA04 to 0x----- (0001) = hit number window Width
- 0x3FA05 to 0x----- (0001) = hit number window Height
- 0x3FA07 to 0x----- (0001) = hit number text X coordinate
- 0x3FA08 to 0x----- (0001) = hit number text Y coordinate
- 0x3FA0A to 0x----- (0001) = current Attackee window X coordinate
- 0x3FA0B to 0x----- (0001) = current Attackee window Y coordinate
- 0x3FA0C to 0x----- (0001) = current Attackee window Width
- 0x3FA0D to 0x----- (0001) = current Attackee window Height
- 0x3FA0F to 0x----- (0001) = current Attackee text X coordinate
- 0x3FA10 to 0x----- (0001) = current Attackee text Y coordinate
- 0x3FA12 to 0x----- (0001) = Attack Status window X coordinate
- 0x3FA13 to 0x----- (0001) = Attack Status window Y coordinate
- 0x3FA14 to 0x----- (0001) = Attack Status window Width
- 0x3FA15 to 0x----- (0001) = Attack Status window Height
- 0x3FA17 to 0x----- (0001) = Attack Status text X coordinate
- 0x3FA18 to 0x----- (0001) = Attack Status text Y coordinate
- 0x3FA1A to 0x----- (0001) = Battle Info window X coordinate
- 0x3FA1B to 0x----- (0001) = Battle Info window Y coordinate
- 0x3FA1C to 0x----- (0001) = Battle Info window Width
- 0x3FA1D to 0x----- (0001) = Battle Info window Height
- 0x3FA1F to 0x----- (0001) = Battle Info text X coordinate
- 0x3FA20 to 0x----- (0001) = Battle Info text Y coordinate
- 0x3FA22 to 0x----- (0001) = Magic window X coordinate
- 0x3FA23 to 0x----- (0001) = Magic window Y coordinate
- 0x3FA24 to 0x----- (0001) = Magic window Width
- 0x3FA25 to 0x----- (0001) = Magic window Height
- 0x3FA27 to 0x----- (0001) = Drink window X coordinate
- 0x3FA28 to 0x----- (0001) = Drink window Y coordinate
- 0x3FA29 to 0x----- (0001) = Drink window Width
- 0x3FA2A to 0x----- (0001) = Drink window Height
- 0x3FA2C to 0x----- (0001) = Battle options window X coordinate
- 0x3FA2D to 0x----- (0001) = Battle options window Y coordinate
- 0x3FA2E to 0x----- (0001) = Battle options window Width
- 0x3FA2F to 0x----- (0001) = Battle options window Height
- 0x3FA31 to 0x----- (0001) = "FIGHT" battle X coordinate
- 0x3FA32 to 0x----- (0001) = "FIGHT" battle Y coordinate
- 0x3FA33 to 0x----- (0001) = Text pointer byte (Low)
- 0x3FA34 to 0x----- (0001) = Text pointer byte (High)
- 0x3FA36 to 0x----- (0001) = "MAGIC" battle X coordinate
- 0x3FA37 to 0x----- (0001) = "MAGIC" battle Y coordinate
- 0x3FA38 to 0x----- (0001) = Text pointer byte (Low)
- 0x3FA39 to 0x----- (0001) = Text pointer byte (High)
- 0x3FA3B to 0x----- (0001) = "DRINK" battle X coordinate
- 0x3FA3C to 0x----- (0001) = "DRINK" battle Y coordinate
- 0x3FA3D to 0x----- (0001) = Text pointer byte (Low)
- 0x3FA3E to 0x----- (0001) = Text pointer byte (High)
- 0x3FA40 to 0x----- (0001) = "ITEM" battle X coordinate
- 0x3FA41 to 0x----- (0001) = "ITEM" battle Y coordinate
- 0x3FA42 to 0x----- (0001) = Text pointer byte (Low)
- 0x3FA43 to 0x----- (0001) = Text pointer byte (High)
- 0x3FA45 to 0x----- (0001) = "RUN" battle X coordinate
- 0x3FA46 to 0x----- (0001) = "RUN" battle Y coordinate
- 0x3FA47 to 0x----- (0001) = Text pointer byte (Low)
- 0x3FA48 to 0x----- (0001) = Text pointer byte (High)
- 0x3FA49 to 0x----- (0001) = Pattern table location for "FIGHT" tiles (through 3FA4C)
- 0x3FA4E to 0x----- (0001) = Pattern table location for "MAGIC" tiles (through 3FA51)
- 0x3FA53 to 0x----- (0001) = Pattern table location for "DRINK" tiles (through 3FA56)
- 0x3FA58 to 0x----- (0001) = Pattern table location for "ITEM" tiles (through 3FA5B)
- 0x3FA5D to 0x----- (0001) = Pattern table location for "RUN" tiles (through 3FA5F)
- 0x3FA61 to 0x----- (0001) = value for which string to display in Enemy name slot 1
- 0x3FA63 to 0x----- (0001) = value for which string to display in Enemy name slot 2
- 0x3FA65 to 0x----- (0001) = value for which string to display in Enemy name slot 3
- 0x3FA67 to 0x----- (0001) = value for which string to display in Enemy name slot 4
World map data
World map data is stored in ROM Bank 0x01, which is accessed by the CPU at address 0x8000, and located at 0x4000 in the ROM image. (0x4010 for iNES files).
The data begins with a 256 entry table of 2-byte memory addresses (CPU addresses), pointing to the first (left-most) tile of each row of the world map. Since the map tile data is compressed, this index table allows quick access to the map data.
The actual world map tile data starts at CPU address 0x8200. Each entry in this data area is either 1 byte or 2 bytes long. The most significant bit of the first byte is set if there is a second byte for this entry. The first byte (excluding the MSB flag) specifies the tile number (0-127). The second byte, if present, specifies the number of tiles that should be displayed. If the second byte is 2, then two tiles should be rendered. If the second byte is 0, then the tile should be rendered 256 times. A single byte entry with the value of 0xFF represents the end of the row.
Town and dungeon map data
Town and dungeon map data is similar to the world map data. It is compressed with the same 1/2 byte method, but it does not contain a single byte 0xFF value at the end of each row. Instead, each row is 64 tiles wide, and any 2-byte tiles that extend beyond the last tile will wrap around and continue on the next row. There is a single byte 0xFF value at the end of the map.
There is a table of 2-byte CPU address pointers located at the beginning of Bank 4 which contains the start of each map. The 2 most significant bits of each entry specifies the bank number (starting from Bank 4), and the remaining 14 bits specifies the CPU address of the map, starting at 0x8000.
Each map also has 16 entries in a table located on bank 0 at CPU address 0xB400 which define any objects located on that map. This includes Bosses, NPCs, bats, magic brooms, etc. Each entry is 3 bytes long. Byte 1 is the object type. Byte 2 is the X position, and byte 3 is the Y position. Byte 2 also contains behavior flags. If bit 7 (0x80) is set, this object is inside of a room. If bit 6 is set (0x40), this object does not move.
After the map tiles have been "decompressed" into RAM in a 64x64 grid, the map effectively wraps in both the horizontal and vertical directions. Walking to the left of the map will seamlessly continue on the right of the map, and standing near the left side of the map will draw tiles from the right side of the map.
Free bytes in the original FF1 ROM
This is a list of known free bytes available in the original FF1 ROM.
These bytes were gleaned from examining the ROM, Disch's 1.0 Disassembly, and Anomie's Disassembly.
Each Bank section below denotes the following:
- Offset Adjustment as a +/- hex value e.g. -28010 (37 total bytes)
- Total free bytes in the whole bank as a decimal value in parens e.g. -28010 (37 total bytes)
- a list of entries having the form in the form 851C : 0x3052C (4 bytes)
- The N bytes next to each offset in parens is the count (in decimal) of free bytes starting at that offset.
- For each entry listed, the ROM offset = the Bank offset + the Offset Adjustment value (which can be negative or positive).
- The N bytes next to each offset in parens is the count (in decimal) of free bytes starting at that offset.
BANK 01
+3FF0 (30 total bytes)
- BFE2 : 0x07FF2 (30 bytes)
BANK 06
- 10010 (? total bytes)
- ACAA : 0x (4,950 bytes with a HUGE caveat)
Be very careful if putting any routines or data in this area.
Explanation:
There are 61 standard maps in the original game, the last being Titan's Tunnel.
Standard maps use variable length storage with a Run-Length Encoding (RLE) style compression scheme,
so instead of a fixed size, they end with a byte having the value FF (the end of map marker value).
Standard map data is stored in an area of ROM stretching from Bank 04 to the end of Bank 06.
All of the bytes in bank 06 after that last map's FF byte are zeroed out.
Coincidentally (or not?) the last 3 pointers in the standard map pointer table (maps 62-64) are also zeroed out.
The issue is that when the standard maps are saved, they're rewritten in RLE-compressed form, which means the
data can grow or shrink.
As a result, all data after the last map's FF byte can slide forward or backward as a result.
So pay attention if using this area in your ROM hack; assembly labels will automatically handle relocated routines, but hackers using hex editors will have to update variable references, branches, and jumps whenever map edits cause the code to move.
Note: Some FF1 editing tools might truncate any bytes that slide forward past the end of bank 06 (i.e. no bytes are allowed to move past 0x1C00F). Consult your tool's documentation or experiment on a test ROM to determine how the tool handles this scenario and plan accordingly. |
BANK 09
-1c010 (475 ? total bytes)
- B980 : 0x27990 (384 bytes)
Note: These 384 bytes apparently define an unused graphic and a series of alternating black and white tiles that don't appear in the game. |
- BBDA : 0x27BEA (38 bytes)
- BEEB : 0x27EFB (21 bytes)
- BF30 : 0x27F40 (4 bytes)
- BF67 : 0x27F77 (25 bytes)
BANK 0B
-24010 (5 total bytes)
Note: In the disassembly, 0x2C010 : $8000
is identified as 1024 bytes of unknown space, but this is actually the overworld battle domain data. It's stored in the bin/0B_8000_unknown.bin file and incbin'd into the assembly source file for Bank 0B. |
Note: In the disassembly, 0x2CFFC : $8FEC
is identified as 20 bytes of unused space, but this is actually the battle message "Nothing happens". It is the only battle message stored after the battle message pointer table. In the bank_0B.asm source file, this is stored as a series of inline bytes (not an incbin'd file). |
- 9093 : 0x2DA03 (1 bytes)
- A7FC : 0x2E80C (4 bytes)
BANK 0C
-28010 (37 total bytes)
- 851C : 0x3052C (4 bytes) (padding)
- 92F4 : 0x31304 (12 bytes)
- BC95 : 0x33CA5 (16 bytes) (maybe)
- BFFB : 0x3400B (5 bytes)
BANK 0D
-2C010 (70 total bytes)
- 9DF9 : 0x35E09 (7 bytes)
- A779 : 0x36789 (7 bytes)
- A7E5 : 0x367F5 (27 bytes) (almost looks like it might be attributes)
- AE02 : 0x36E12 (14 bytes) ?unused -- fragmented code?
- AFFE : 0x3700E (2 bytes) (that $60 might be an unused RTS -- but who cares)
- BA9F : 0x37AAF (1 bytes)
- BAF9 : 0x37B09 (7 bytes) (unknown / unused)
- BEFB : 0x37F0B (5 bytes)
BANK 0E
-30010 (114 total bytes)
- 84E2 : 0x384F2 (30 bytes)
- 9088 : 0x39098 (9 bytes) (ClearGameEventFlag unused by the original game)
- 94EF : 0x394FF (1 bytes) (truly unused -- no entry in the jump table)
- 9586 : 0x39596 (14 bytes) Talk_CubeBotBad
- 9B3E : 0x39B4E (22 bytes) UnusedRoutine_9B3E, Faux/Unused routine
- BF3A : 0x3BF4A (22 bytes) Unused Phantom Code
- BFF0 : 0x3C000 (16 bytes)
BANK 0F
-30010 (126 total bytes)
- C464 : 0x3C474 (5 bytes)
- D7BF : 0x3D7CF (3 bytes) (unused/unreachable call)
- DB09 : 0x3DB19 (2 bytes) (unused NOPs)
- E4BF : 0x3E4CF (8 bytes)
- ECB9 : 0x3ECC9 (1 bytes)
- FCBB : 0x3FCCB (7 bytes) (UNUSED_DrawBattle_IncSrcPtr)
- FDF1 : 0x3FE01 (15 bytes) (Unused space)
- FEEB : 0x3FEFB (23 bytes)
- FF3C : 0x3FF4C (4 bytes)
- FF81 : 0x3FF91 (15 bytes)
- FFA4 : 0x3FFB4 (4 bytes)
- FFB9 : 0x3FFC9 (7 bytes)
- FFCD : 0x3FFDD (22 bytes) space before "FINAL FANTASY"
- FFF0 : 0x40000 (10 bytes) space after "FINAL FANTASY"
Unused routines in the original US FF1 ROM
The following routines are either completely or partially unused in the original US FF1 ROM and can be recycled as free space.
Bank C
- [$B674 :: 0x33684] lut_IBCharStatsPtrTable_alt (8 bytes)
- [$B67C :: 0x3368C] lut_CharStatsPtrTable_alt (8 bytes)
These are duplicates of the lut_IBCharStatsPtrTable and lut_CharStatsPtrTable tables. References to the duplicates can be updated to point to the originals, and the 16 contiguous bytes here can be used for other LUTs or a short routine.
- [$B684 :: 0x33694] PreparePlayerMagAttack (41 bytes)
41 of the last 42 bytes in this routine perform tasks that have no effect. Those bytes can be moved out of the routine and used for other tasks.
- [$B730 :: 0x33740] PrepareEnemyMagAttack (39 bytes)
The entire routine loads stats that simply aren't used by the routine or its caller.
Bank E
- [$BEF7 :: 0x3BF07] UpdateEquipMenuModeAttrib (55 bytes)
Likely a holdover from the Japanese version, it has no visible effect in the US version (since the palettes involved are identical) and would need to be refactored to work as intended anyway.
Bank F
- [$FAA6 :: 0x3FAB6] DrawBattleString_ExpandChar (55 bytes)
Another holdover from the Japanese version, part of this function attempts to assign the top half of characters when drawing a string. The default is a blank (space) character. Since this is always a space character in the US ROM, the code to choose that top tile could be removed, since a space will always be used.
Internal Data for Final Fantasy
| |
---|---|