Final Fantasy II
15 June 2002 - Reflection by koitsu
Spinner needed some material, so here’s the skinny. But first, an intro of it’s own:
For those of you who don’t know, I consider myself a ronin of sorts. By that I mean that I rarely become part of a romhacking “group” when working on a title – I prefer to remain as an individual. I’m also very peculiar as to who I work for. My word is binding, so for me to agree to do some work for someone takes a lot of pre-cursor thought. “Do I really want to do this?“, “Do I have the time for this?“, “Can I actually accomplish this goal?“, et cetera. I mainly prefer to just sit from the sidelines and let romhackers do their thing, since the way they go about it is completely different than how I do. Such was not the case with FF2j.
In early 1998, Demi approached me about doing some work for Neo Demiforce on the FF2j title – in particular, replacing the original intro with something more to NDs liking. I agreed. But, sadly, I’m a very lazy person, and so it took some ass-kicking to get the ball rolling. After some hounding, I sat down over a period of about a week and disassembled FF2j, following the code from it’s reset vector and all throughout the initial intro. It was fairly simple, but relied heavily on pre-written subroutines that the actual game used – in English, it meant that I couldn’t start yanking out subroutines to make space for the new intro. I had to go with what free space there was in the ROM, which was very very little (under 1400 bytes, if I remember correctly).
During this time, BigWierd had been working on a replacement title screen (which is what you see today). BigWierd and I had long known one another from SNES-oriented chat sessions over IRC, so it was cool working with him. I believe he originally drew the logo using NESticle; I was given a GIF so that I could know what to expect, then later was given the actual CHR data. The filesize was 1264 bytes; this was literally the logo, including all the black space you see around it (each being it’s own unique tile). This didn’t include the nametable data (used for laying out graphics on the screen).
This posed a serious problem: it only left me with a few hundred bytes for actual code, which wasn’t going to be enough. I hadn’t even dealt with the issue of a new palette yet. So, I decided to take the risk of overwriting some data in the ROM which I assumed was unused, since I needed the room. I threw up the title logo as raw data, tossed up the new palette, and and within a few days, v1.00 of the Neo Demiforce FF2j translation was released.
During the next week, I spent most of my time going over my code to figure out how I could make it better. I felt absolutely horrible having to overwrite a bunch of data in the ROM; I knew this was going to cause trouble sooner or later, and I felt completely obligated to do things the Right Way(tm) the second time around. The last thing I needed was Demi smacking me around due to shaving a few hundred bytes off the original ROM.
I proceeded to re-write the code from scratch, using as many pre-written subroutines from the actual game that I could (simply by going through the code and analyzing). This brought my code down in size, but it didn’t help the issue of the title screen taking up so much room in the ROM. So, I did something that I really didn’t want to do:
I shaved off some of the blank tiles in the CHR data, and proceeded to compress the results using an RLE (run-length-encoding) algorythm. Most of the CHR data consisted of repetitive data, eg. 0×0F0F0F0F0F, and so on. In that example, RLE would convert those 5 bytes into 2 bytes; 0×050F (value 0×0F, 5 times). This can actually increase the number of bytes used in the case of something like 0×081A (which RLE compresses to 0×0108011A), but as I said, most of the data was repetitive. I wrote the compressor in perl5, since I didn’t know how to code for Windows, and I despised DJGPP. Naturally, I wrote the decompressor in 6502 assembly. The end result compressed the 1264 title screen image down to about 976 bytes.
This still wasn’t acceptable. So, I did the inevitable: I went through the CHR data manually and removed all re-occurring tiles. There’s no sense in having 50 tiles all with the same data when you can just have 1 tile and refer to it with nametable data. The end result was 610 bytes; a near-60% compression ratio. Pretty good!
So, I implemented everything during the next 48 hours, and found that I was left with a LOT of room for other fun stuff. I decided to make some text fade in/out (which I think is what the replacement introduction is known best for (see below for more on this)). But, the fade wasn’t working right on all emulators. In 1998, none of us had a decent grasp of how the NES PPU worked, so everyone was still fiddling around with ideas on how to get things to emulate right. My code resulted in gibberish being shown on the screen during the fade, and so I asked Sardu (Icer Addis, author of NESticle) for some advice as to what was going on. He provided some tips, and in the end, I found that my problem had to do with me not resetting the internal VRAM address before the next VBlank (which Square is quite well-known for doing). One JSR call took care of everything.
I pushed this release out to Demi, who immediately updated the official patch to v1.02.
I was content with my work, and went back into hibernation until I was needed again (which never happened). Instead, a few years later (when eBay fuckheads who started selling pre-burned copies of the FF2j translation on cart), I read horror stories of how the FF2j intro would show garbage when fading, or in some cases wouldn’t work right at all (this can be seen when using LoopyNES even today).
I began working on v1.03 and v1.04 of the FF2j intro, but never finished them. My goal with v1.04 was to re-write everything AGAIN, and do things right from the start – I wanted to add an easter egg to the intro as well, where at the “PUSH START” screen, you could hit a combination of buttons to have the text fade out and display a special message. The message I wanted to display was “NESticle - R.I.P.”, since the last NESticle release (version x.xx) had just come out.
I still have all the sourcecode & data from version 1.02 to 1.04; version 1.02’s INTRO.ASM is 8638 bytes (not including the CHR data), and 1.04’s is 10820 bytes. Yes it’s commented, and no I won’t give it out.
So ends my story of the FF2j intro. I hope you enjoyed reading it as much as I enjoyed coding it for ND.