Thanks to DTaeKim on gamefaqs.com, I got interested awhile back at looking into the info within Lufia I. Though he was looking into monster data at the time, I was wanting a text dump of the game. Turns out that all of the text in Lufia I is stored in some sort of compressed format (not compressed as much as it just contains pointers to other words to insert, actually) where you will get a statement like this:
(memory location 0x257e5 through 0x25831)
cc 2c 20 0c 7a 20 0c 26 20 0c ee 6f 6e 65 05 0c 7f 20 61 20 66 61 6b 65 20 0c 19 3f 04 a0 0b 08 20 a0 20 72 69 63 68 20 87 20 67 65 6d 73 74 6f 6e 65 05 6d 69 6e 65 73 2e 20 cc 20 0c 6f 20 72 61 6e 20 0c 8b 05 0c 60 20 61 67 6f 2e
Which, shows up as this in the text dump:
Ì, .z .& .îone.. a fake ..?. .. rich ‡ gemstone.mines. Ì .o ran .‹..` ago.
Can't read some of those characters? Well, that's because the stuff that doesn't make sense has to do with punctuation and pointers to other words that get put in place.
The statement that should be making is this:
But, why would anyone
make a fake ruby?
Medan was rich in gemstone
mines. But they ran out
years ago.
A few words are there that you can make out (between some townsperson and the Princess in Medan). Such as ",", "one", "a fake", "?", "rich", "gemstone mines.", "ran", "ago.". But what about the questionable things you can't see. Let's take the first part, the "But, why would anyone make a fake ruby, which looks like this, and compare it against the dictionary file of the game (0x54a50):
cc 2c 20 0c 7a 20 0c 26 20 0c ee 6f 6e 65 05 0c 7f 20 61 20 66 61 6b 65 20 0c 19 3f
Ì, .z .& .îone.. a fake ..?.
cc -> refers to an upper case "But"
2c -> comma (",")
20 -> blank space
0c 7a -> refers to a lower case (0c is "lower case"/0d is "upper case") "why"
20 -> blank space
0c 26 -> refers to a lower case "would"
20 -> blank space
0c ee -> refers to a lower case "any"
6f -> letter "o"
6e -> letter "n"
65 -> letter "e"
05 -> line/carriage return
0c 7f -> refers to a lower case "make"
20 -> blank space
61 -> letter "a"
20 -> blank space
66 -> "f"
61 -> "a"
6b -> "k"
65 -> "e"
20 -> blank space
0c 19 -> refers to a lower case "ruby"
3f -> "?"
But, why would anyone
make a fake ruby?
After that, there is a "04 a0" code which I can only assume is some sort of "close textbox" and "open new text box" (and possibly a character sprite/on screen location to hook it to). But then we get to the second phrase:
0b 08 20 a0 20 72 69 63 68 20 87 20 67 65 6d 73 74 6f 6e 65 05 6d 69 6e 65 73 2e 20 cc 20 0c 6f 20 72 61 6e 20 0c 8b 05 0c 60 20 61 67 6f 2e
.. rich ‡ gemstone.mines. Ì .o ran .‹..` ago.
0b 08 -> dictionary for the town name "Medan"
20 -> blank space
a0 -> lower case "was" (notice it is not referenced by any 0c/0d type calls)
20 -> blank space
72 -> "r"
69 -> "i"
63 -> "c"
68 -> "h"
20 -> blank space
87 -> lower case "in"
20 -> blank space
67 65 6d 73 74 6f 6e 65 -> letters for "gemstone"
05 -> carriage/line return
6d 69 6e 65 73 -> letters for "mines"
2e -> "."
20 -> blank space
cc -> upper case "But" (as 8c refers to lower case)
20 -> blank space
0c 6f -> lower case "they"
20 -> blank space
72 61 6e -> letters for "ran"
20 -> blank space
0c 8b -> lower case "out"
05 -> carriage/line return
0c 60 -> lower case "years"
20 -> blank space
61 67 6f -> letters for "ago"
2e -> "."
Medan was rich in gemstone
mines. But they ran out
years ago.
Then there's more words after that, because she's long winded, but you get the idea... It took me almost 8 hours of trial and error to figure out how the dictionary words were stored, as well as what numbers called them (which I figured out by comparing the dictionary against known phrases). The upper case/lower case was a bit harder to figure out as well. There's still some extra data that doesn't make sense yet. Also, there's a lot of words that are in the dictionary but they don't both to make a call to use them (like "one" in the above example"). There must be a reason for this, but I have yet to figure it out.
Some things are a little more hidden, such as a character is referenced by "07 0X"
with Hero being "07 00" up to Gades as "07 0b". Also, while to get lowercase/uppercase for the one set of dictionary words it seems to be dependent on the "0c" vs. "0d" call, the other section of dictionary words has two memory addresses that are separate for lower case or upper case (though the dictionary only exists once, it just loops back on itself I guess). For example, in the non-0c/0d dictionary, the word "there" is referenced by "8e", while "There" is referenced by "ce". Meaning they're exactly 40 H difference.
Now, for the dictionaries themselves, the character names start around "0xe800", the town names around "0xe850", there's one of 16 words (such as ('s) and ("Welcome")). These start at "0x54a50". Then the next dictionary (the one that has double calls to it, for being lower case/upper case) starts at "0x54ac0" (it contains 80 items, which makes for 160 words between upper/lower case). Then the main dictionary (called by 0c/0d for lower/upper case) starts near "0x54c10". Now, there's two types of dictionary calls here.
Early on names:
0xe850: 8f e8 95 e8 9b e8
8f e8 refers to memory location "0xe88f", which contains the name "Alekia"
95 e8 refers to memory location "0xe895", which contains the name "Chatam"
9b e8 refers to memory location "0xe89b", which contains the name "Sheran"
These places are called by text boxes by "0b xx", where "0b 01" is Alekia, "0b 02" is Chatam, "0b 03" is Sheran and so on (there's an extra space '.' in this list which makes the names start at 1 instead of 0).
Later on words:
0x54ac0: 42 cb 45 cb 48 cb
Here we have a bit of a problem, as memory location "0xcb42" is way back in the program and nowhere near what we want. So all of these later dictionary entries need to have the hex value "0x48000" added to them so that they point to the proper place. The unique item grabber program I made for Diablo I uses a pointer offset like this too, so it is not all that uncommon for larger programs, especially later on in the data when dealing with 16 bit little endian pointers.
42 cb + 48000H = "0x54b42" which contains the word "the"
45 cb + 48000H = "0x54b45" which contains the word "you"
48 cb + 48000H = "0x54b48" which contains the word "to"
In case you didn't notice, the pointer to the next word tells you where to stop. At least, that's my guess...
I've uploaded the dictionary for anyone to view right here:
Lufia I Master Dictionary Reference Key (current update: v.1.1 on Feb 16, 2010)
Current script text dump of the game based off of the current dictionary:
Lufia I Script Text Dump (current update: v.1.1 on Feb 16, 2010)
If you think I've missed something, screwed up something, or have an idea of how it all ties together or how the game makes it all work as one, let me know. Also, I believe Lufia II: Rise of the Sinistrals works in a similar fashion to this game, if I am not mistaken (but, I like Lufia I better, so here we are... >_>).
And just for kicks, here's my 10 hours worth of note taking for making this dictionary file/figuring all of this stuff out:
Above: The only way to figure out numbers... Is to use lots and lots of pencil and paper notes...
***** The "aside" Section (aka. wandering off point) *****
The only thing I have yet to figure out is exactly how the dictionary algorithm works. But, I believe this is a good start. Also, on the subject of things in the game that the character should not get access to is a town named "Makao" (which is similar to the name of a casino town in Lufia II, which means it probably just got dummied out in this one), as well as 5 dummied out items, and a handful of spells which you cannot fairly get.
Defake - drops enemy agility
Figual - confuses enemy
Paraiz - paralyzes enemy
Elegion - casts "Thunder" on all enemies on screen
Elegi - casts "Flash" on all enemies on screen
Elegio - casts "Bolt" on all enemies on screen
Absob1 - absorbs enemy MP
The best part? If you "hack" the spells into your list, they only cost 0 or 1 MP per cast! You can roll the game with ease, consider you can give these spells to Hero, Jerin, or Lufia.
Above: Wrecking things with Elegion... So good. So good.
Have a suggestion? Comment? Question? Just drop me a line at: vegetaman@gmail.com