EXPANDED PC SPRITE COLORS FOR FF6 PATCH BY EGGERS This readme file contains a lot of information, some of which is unnecessary for most users. Read it if you are curious or want to do something advanced. Make sure that you definitely read and understand the section "IMPORTANT USAGE INFORMATION". TABLE OF CONTENTS 1. What is this patch? 2. Permission 3. ROM versions / patch versions 4. Important usage information 4.1 PC sprites are still limited to 12 colors... 4.1.1 Certain palette colors are special... 4.2 Graphics glitches may occur when you load an older save... 4.3 Battle palettes can be different from out-of-battle... 4.3.1 There are other cases, not related to this patch... 5. If you're curious 5.1 Why can I only use 12 colors? 5.2 What is the cache, and why do I have to clear it...? 6. For advanced users 6.1 What bytes are altered? 6.2 Reassembling the code 1. WHAT IS THIS PATCH? =================== A fact known probably only to ROM hackers: the FF6 / FF3us game only allows playable character sprites to use the first 12 colors of a 16 color palette. If the last four palette indices are used by a PC sprite, the sprite will look correct on the world / town map, but will have mixed-up colors in battle. This patch allows a PC sprite to use the last four, previously unusable colors of its palette. If you are working on a hack which is to include custom PC sprites, you now have a access to a greater selection of colors. (NOTE HOWEVER the important restrictions and specification, discussed in the "usage information" section.) This hack is for people who are themselves creating hacks. In itself, has no visible effect on the game. It will, however, allow the game to correctly display your own custom sprites which use the formerly unusable palette colors. In order to help test or see this patch's effects, I have included a few custom sprite sheets, as .png images. If you'd like to use these, you must import them into the ROM yourself. I assume most people who have downloaded this patch will already know how to do this using a tool like FF3usME. If not, a good resource for tools and information is: http://www.ff6hacking.com/ 2. PERMISSION =================== ROM hackers are encouraged to use this patch freely in creating their own hacks. You may distribute a patch that effectively includes this patch as a part of it, in addition to your own alterations like custom sprites. This permission applies as long as you are not making money off your project. In the appropriate credit section, please provide credit to Eggers. I have also included my .asm code, which you may use and modify as you like. Please provide credit to Eggers if you distribute this patch or code, with or without modifications or additions. 3. ROM VERSIONS / PATCH VERSIONS =================== I've included two versions of the .ips patch: one for a headered ROM, and one for an unheadered. The unheadered ROM should be exactly 24 Mb in size, and the headered one should have an extra 512 bytes ($200 in hexadecimal), containing information that identifies the game to an emulator. Make sure you apply the correct patch depending on whether your file has a header or not. In addition, there are two versions of the FF3us game: a 1.0, and a 1.1. Both ROM versions can be found online, and the version number isn't always specified. This patch was designed for the 1.0 ROM. If neither the headered nor the unheadered patch works with your ROM, you may be using a 1.1 ROM. Find a 1.0 version, and try again. One effect of this patch will be to expand your ROM's size to 32 Mb. It is designed to be applied to an unaltered, non-expanded ROM. There is no need to expand the ROM yourself before applying the patch. In fact, if you apply this patch to a ROM that you have already expanded, and you have written your own code or data to the expanded region, this patch will overwrite that data. So, apply this patch first, before applying your own additional modifications. 4. IMPORTANT USAGE INFORMATION =================== This modification is easy to use, more or less. Just apply the .ips patch to an unaltered ROM, and then import your own sprites with a compatible editor (FF3usME is fully compatible). HOWEVER, there are important caveats. If you don't understand these issues, your custom sprites may appear glitched, and you will not know why. So please, read carefully. This could also be seen as a troubleshooting section. If your sprites are not displaying their correct colors, read / re-read this section. ~~~ 4.1 ~~~ PC sprites are still limited to 12 colors for a given character. These colors can now be any 12 of your choosing from the 16-color palette assigned to the character. The chosen subset of colors can be different for each PC. ~~~~~~~~~~~ Elaboration: To be as clear as possible, the original game only allows playable characters to use the FIRST 12 entries of a palette. The entire set is usable on the world map. NPCs who share palettes with PCs sometimes use the last 4 colors. However, if a PC sprite uses those colors, it will not display correctly in battle. With this patch, a PC sprite is still limited to a set of 12 colors. The 12 colors can be any subset of the 16-color palette assigned to that PC. (Sorry, you cannot mix-and-match across palettes.) The chosen colors no longer have to be the first 12 colors of the palette. They can include the last four which were previously unusable. If two sprites use the same 16-color palette, they do not necessarily have to use the same 12 colors from their common palette. Each PC sprite can use its own subset. You do not have to explicitly specify which 12 colors you want to use. Just edit your sprite as if it were a 16-color sprite, but make sure you do not actually use more than 12 colors. ~~ 4.1.1 ~~ In addition, certain palette colors are special, and must always be considered "used", even if they are not actually used by any pixel ~~~~~~~~~~~ The special colors are those in palette indices 1, 2, 7, and 8. Index 1 is transparent. 2 is the black / outline color. 7 and 8 are skin tones. 2, 7 and 8 are special because they change when the PC is subject to a status effect. The outline (#2) is used for effects like vanish, protect and haste. The skin tones (7 & 8) are used for effects like poison and zombie. It's because of their special status that they cannot be toyed with or omitted from the palette. Even if a sprite does not use these colors (Like Shadow's sprite, which does not have any visible skin) these palette indices will always be considered "used" and will count toward the 12 color maximum. Another way of thinking of this is: your palette subset must include indices 1, 2, 7 and 8, and can include up to 8 additional colors (out of 12 additional colors in the 16-color palette). You should also keep these special indices in mind when creating your own custom sprites or palettes. Make sure you use them for their intended purpose if you want your character to look right when, e.g., poisoned. ~~~ 4.2 ~~~ Graphics glitches may occur when you load an older save game after making changes to your custom sprites. A simple in-game fix is provided. ~~~~~~~~~~~ When you are actively changing your custom sprites, you may encounter a problem. If you save a game (or save a state), and then edit your ROM, changing your character sprites, and then subsequently load the game which you saved while using the old sprite data, your new sprites may not show up with correct colors. This won't occur once you've stopped modifying your sprites. It will only happen if you alter the ROM and continue to use the existing save file. So, it won't be an issue for players of your finished hack. But, it might be an annoyance to you while you are developing and testing. A fix is available in-game. If you're experiencing this problem, open the main menu (the one that shows character portraits and has options for items, skills, equip, and so on). Hold down the L and R buttons, and press SELECT. This will clear a cache of data, which is responsible for the issue. If cached data is found and cleared, you will hear a tone (the "healing" sound-effect). The next time you enter battle, your new sprites will display correctly. You may notice a short pause as the data is recalculated. That will only happen the first time a sprite is used in battle after the cache is cleared, once for each sprite. If you want to get rid of the cache-clear feature when you distribute your finished hack, so users can't clear the cache, you can use a hex editor to disable/remove the code. See the "advanced users" section for information. However, it is probably not necessary to do so. Even if your players do trigger this by accident (or on purpose) nothing bad will happen. The only side-effect will be a slight pause next time a sprite is loaded. ~~~ 4.3 ~~~ Battle palettes can be different from out-of-battle palettes, and you must watch out for this, or your sprites may display in an unexpected way. ~~~~~~~~~~~ Battle palettes and out-of-battle palettes are stored in different locations in the ROM, even though they mostly duplicate each other. In a few cases, the last four colors for a particular battle palette are not the same as the corresponding colors for the non-battle palette. The last four battle palette colors are normally not ever used anyway, so the developers presumably just didn't bother to keep them synchronized. However, with this patch, they ARE used for the first time (if you make a custom sprite that uses them). I've taken the liberty of altering the battle palettes to match the out-of- battle palettes. This tweak is a part of the IPS patch. Even so, you may encounter this issue if you edit the palettes yourself, or if you patch the game manually rather than applying the ips, or something else. So, if your sprites look different in and out of battle, make sure this is not the issue. ~~ 4.3.1 ~~ There are other cases, not related to this patch, in which sprites may use the "wrong" palette. ~~~~~~~~~~~ If you switch the palette number assigned to a PC, the switch may not correctly happen under all circumstances. This is NOT caused by this patch. It is a quirk present in the original game. For instance, the wrong palette may be used on the world map, in shop menus, on the save game screen, or in certain scenes in which the character is considered an NPC. These issues are fixable, although they can be awkward to fix. You should check out the documents and message boards available at ff6hacking.com, and other pages found in that site's link section. Again, these issues have nothing to do with my patch. I'm mentioning them in case someone THINKS they are caused by this patch. 5. IF YOU'RE CURIOUS =================== Some additional information explaining the reasons for certain quirks and restrictions, and some detail about exactly what this patch does / how it works. ~~~ 5.1 ~~~ Why can I only use 12 colors? ~~~~~~~~~~~ The graphic engine works in a certain way: SNES sprites normally have a 16-color palette per sprite. They can choose a palette from a selection stored in palette memory. Palette memory holds up to 8 sprite palettes, each having its own 16 colors. In FF6, on the world map, sprites use an entire 16-color palette, as per normal. A sprite can contain any or all of the colors in its palette without any problem. In battle, however, character sprites "give away" a partition of their palette to other, miscellaneous sprites, such as the hand cursor, damage digits, and so on. PC sprites only use the first 12 colors, while the other sprites only use the last 4. So, if you create a PC sprite that uses the last 4 colors, those colors will show up as colors from the hand cursor or something else, instead of how they're supposed to. The developers did this to work around the SNES's limited palette memory. The battle engine wants to display many different sprites, and each sprite needs to be able to load its own independent palette. The only way to achieve this is to allow some sprites to share a palette, with each using its own partition of the 16 colors. It is necessary and actually kind of clever. But it has the side-effect of reducing the colors available to PCs. That is why you can only use the first 12 colors in the unpatched game. This patch changes things. In order to use the formerly inaccessible colors, graphic and palette data are now altered dynamically in memory whenever a PC sprite is loaded for battle. If the sprite uses a color from the last 4 entries of the palette, that color is switched into one of the first 12 palette slots: the ones belonging to the PC sprite. That is of course only possible if there is an unused slot within the first 12. You must omit a color to add one. So, even with this patch, you are still limited to 12 colors, but they can be any 12 of your choosing. ~~~ 5.2 ~~~ What is the cache, and why do I have to clear it when I edit my sprites? ~~~~~~~~~~~ In order to achieve its result, this patch dynamically alters sprite data in memory. That takes a certain amount of time. In testing, there was an associated "load time" / graphics processing time at the beginning of each battle, which was annoying. In order to reduce processing time, the algorithm was made to permanently save some intermediary data, after calculating it just once for a given sprite. The first time a particular character sprite is loaded for battle, there will be a small pause as it is analyzed and modified to use its correct colors. The next time the same sprite is loaded, the saved data will be re-loaded from the cache. That will bypass a lot of calculation, and reduce the length of the pause to something less noticeable. The pre-calculated data is stored in SRAM. That is the same place your save games reside. The data is in an unused part of the SRAM -- one which does not belong to any of the three save games. A positive effect of storing this data in SRAM is that it will persist across saves/reloads. A negative side-effect is that the character sprite data will effectively depend on both the ROM and SRAM. So it may not display correctly if the ROM is edited but the SRAM is not. The workaround is to clear the cache, meaning the data will simply be recalculated next time the sprite is loaded. 6. FOR ADVANCED USERS =================== If you are creating a sophisticated hack, you may want to know some specific information about how this patch alters the ROM. You might be applying other patches at the same time. Or you might have your own code or data. You might want to know which bytes are altered by this patch, and you might want to relocate this patch's code to prevent a conflict with another patch, or with your own code or data. If you aren't comfortable with hex editors and so on, this section will be too advanced for you. If you don't know but would like to learn about these things, google for terms like hex editor or assembler. If there's a question google can't help you with, try a message board. ~~~ 6.1 ~~~ What bytes are altered? ~~~~~~~~~~~ The most substantial section of new code is inserted at $F0/0000 by default. (In case you don't know, that is the CPU memory map address. The corresponding byte in the actual ROM file, as seen in a hex editor, would be $300000, or $300200 if your ROM has a header.) The function there duplicates a function originally found at $C1/3D43. In addition to doing the same work as the original function, it also does the dynamic sprite editing, switching in the "extra" palette colors. In order for the new code to be called, the original function in C1 must also have its first few bytes overwritten, so it calls the new function in the new bank and then returns. The bytes beginning at ROM address $013D43 (CPU address C1/3D43) are overwritten with: 22 00 00 F0 60. This is a long jump and assumes the default location of F0/0000. The middle three bytes are the address of the new code, beginning with the least significant byte. If you moved the new function to $F38000 (for instance), you would change those bytes to: 22 00 80 F3 60. HOWEVER: an important thing to know is that this new code in F0 cannot simply be relocated by copy/paste. That is because it includes jumps and pointers within itself that reference absolute memory addresses. If you move the function from its original ROM location, it will load or jump to nonsense data stored at the original location in F0. If you want to relocate the code, you will have to reassemble it from the .asm file I have provided. I have tried to make this as easy as possible. You only have to change a couple of constants found near the top of the file. See below for instructions on where to get the assembler, and how to assemble the code. As an aside, if you want some free space in bank C1, you can overwrite the original function in C1, which is replaced by the new function in F0. The function begins at C1/3D43, which is where we inserted the long jump to the new code. Following the five bytes which do the long jump and return, you may overwrite the rest of the function with FF or other junk data, and add your own new code or data there. The function ends at C1/3E4C. Continuing on, there is also another, smaller code addition in bank C3. A short piece of extra code is added at C3/F0A0 (ROM address 03F0A0). That is the code that clears the SRAM data cache when you press the appropriate combination of buttons while on the main menu. We also change an existing function to jump to that new code. The three bytes beginning at C3/1DA4 (ROM location 031DA4) are overwritten with: 20 A0 F0. This, again, assumes the default location for the new function. A0 F0 are, of course, the pointer to the function, with the least significant byte first. If you want to disable the clear-cache feature, you can overwrite the bytes at C3/1DA4 their original values, which are 20 48 35. Then the ROM will no longer jump to the clear cache code. You can also get rid of the clear cache code after you've done that. Unlike the other new function in F0, this function in C3 can be freely relocated within C3. Just copy/paste its bytes to another address, and change the jump pointer. Do not move it outside of C3, however, or you will have to make a long jump instead of a jump. ~~~ 6.2 ~~~ Reassembling the code ~~~~~~~~~~~ First: you can open the file expandedpalettes.asm in a text editor like notepad. If you just want to relocate the code, I've made this as easy as possible to do. At the start of the file, there will be a bunch of explanatory comments, and a couple of constants you can change, in order to specify the memory location to which you want to relocate this function. By default these read: MY_DATA_BANK .EQU $F0 And: MY_CODE_OFFSET .EQU $0000 If you would like to relocate the function to from F0/0000 to F1/1234, you would change these to: MY_DATA_BANK .EQU $F1 MY_CODE_OFFSET .EQU $1234 This is also all you need to do. Feel free to read and modify the rest of the code if you wish. That would be for a very advanced and very intereseted user, however. So now, you'll want to use this .asm file to produce binary data. You can do that with the assembler found at: http://www.obelisk.demon.co.uk/dev65/index.html This is the assembler I used. Other assemblers for the SNES architecture may also work, but they may not, because they do not all use the same syntax. So, you should use that one. The assembler is java-based, so it should work on nearly any computer or OS, although you may have to work harder if your computer is not Windows, because the .bat files will not work. Download and extract the file. Then move the file expandedpalettes.asm into the same directory as the assembler, which should include the files 65xx.jar, As65.bat and Lk65.bat. Open a command prompt, and browse to that directory. You want to type the following: call As65 expandedpalettes.asm That will make a file called expandedpalettes.obj, which is an intermediary file between the asm text, and the binary data. Then, type the following: call Lk65 -code $00000-$1ffff -output expandedpalettes.bin -bin expandedpalettes.obj Alternately, instead of using the command line, you can paste those two lines into a text file, save it with the extension .bat, and run it from the assembler directory. Anyway, this will produce a binary data file called expandedpalettes.bin. You can open that file with a hex editor in order to get the data, and paste it into your ROM. The output .bin file may (or may not) start with a bunch of filler data, in the form of EA over and over. The EA filler will be present if the code offset you specified was not equal to $0000 (that is: if you asked to relocate the code to somewhere other than the very start of a bank). Ignore those EA bytes. They are a side-effect of a somewhat lazy and inelegant method I used to get the pointers to point to the right locations. Find the first value that is not EA. That will be the start of the code for the function located by default at $F00000. If you changed the constants in the asm file, the code found here will work when pasted to your chosen location, instead of the default location of F0/0000 / 300000. The function is about $500 long in hexadecimal-numbered bytes. It does not take up the entire bin file. Following its end, there will be a few lines of EA. Those EAs serve as a visual separator between this function and the next function in the bin file. They are filler and don't need to be copied. When you copy/paste this function into your ROM, DO NOT copy the EAs -- either the ones before or after the function. Especially do not copy the ones before the function. That will mess up your pointers. Begin with the first non-EA value. The first three bytes of the function should be: C9 FF D0. The function ends a little less than $500 later. The last three bytes should be: 40 00 80. The ending is followed by 64 repetitions of EA. Overwrite the appropriate part of your ROM with the data from expandedpalettes.bin. Overwrite the ROM beginning at the location you specified when you modified the .asm file. Don't forget to also change the long jump located at C1/3D43, so it points to your new/relocated function. Now, in expandedpalettes.bin, following the main function, and following the 64 EAs which serve as a separator, we have the binary data for the other added function -- the one meant to be located in C3. It can be located in any free space in C3. (The free space is located at the end of the bank, starting with 03F091, and is filled with the value FF.) You may, if you want, manually copy/paste those bytes from the bin into the ROM. If you applied the IPS patch, the function will already be in the ROM. Don't forget to update the jump statement located at C3/1DA4 so it points to the correct location of the new code. The last few bytes of the C3 function should be B9 0E 60. These are followed by a bunch of 00s. You do not need to copy the 00s. That should do it. You've now manually patched the ROM with the new code at a location of your choosing. Run it and give it a try. If it does not work, troubleshooting suggestions: Does your ROM have a header? If so, remember to add 200 when determining the ROM file address to paste into. Also, remember that the SNES CPU does NOT "know" about the header. That means you should NOT add 200 when determining the SNES memory address. Also, in case you forgot, the SNES memory address is equal to the ROM file address +C0 (hexadecimal number). So, for instance, ROM address 315432 would be SNES memory address F1/5432. That is assuming the ROM has no header. When you pasted the bytes, make sure you overwrote the old data, rather than inserting it, which would cause the ROM to grow in size. If the ROM is a few bytes too big because you inserted extra data, or if existing code is shifted, that will cause many problems. Make sure you copied all the appropriate code, and only the appropriate code. Make sure you did not copy the EAs. Make sure you also inserted / updated the jump statements in C1 and C3 to point to the addresses where you copied the new code. That should do it.