I came to find out I wasn't quite as thoroughly done labeling all the functions in Legend of the Red Dragon assembly as I thought. As I was going through the code in more detail, I found a call to a function in what looked like another broken stub. I thought no problem, it must just link to one of the functions which I've already labeled, since I'd gone through all of the overlay segments already. I just needed to trace down which function it was and create the JMP manually like before.
Nope!
After a bit of poking around, it turned out that the segment in which this Turbo Pascal stub was wanting to jump into wasn't loaded into IDA at all. This meant somehow I had to manually load this segment in. Luckily you can do that, with the Additional Binary File in the Load File menu. First I had to find the unmangled Turbo Pascal stub in the EXE, since the stubs IDA can't straighten out aren't always the same as the original data in the EXE anymore. Once that was found, I could calculate where the segment was in the LORD.OVR overlay file that I needed. I then used this offset and length to load the section into IDA that I needed.
After loading this, I still had to create the segment again so that I could set the base address, which you apparently can't do when creating the segment in the Additional Binary dialog. But if you make a new segment for the same memory area then it just replaces the other one, basically. Then I had to set the assumed data segment. But even after doing this, the segments in the Program Segmentation tab don't display DS properly. So I dunno how to fix that, although it doesn't seem to matter. I think that's just the default DS.
Then came the next challenge: the relocations. I quickly noticed that there were calls all red and not linking to anywhere else. I knew immediately that it was because there were no relocations applied, but I just wasn't sure how to go about fixing it. My first step was to go back to the Turbo Pascal stub from the EXE and determine the size of the relocation section in the overlay (which is always directly below each segment). I extracted that, and started trying to match up the first relocation to the first CALL in the assembly via IDA's hex editor. Matched up perfectly. Then I realized that I actually only needed to change the segment of each call manually to add 0x1000 to them, since that's IDA's overall base address or whatever. But when you realize just how many calls you're going to have to manually set, you see what a huge pain in the ass that's about to become.
So I did some looking into the IDC script language which IDA uses. Two functions are useful here: Word(), and PatchWord(). I tested it out by manually putting together a script command to patch the first segment address to add 0x1000 to it, and it worked fine. So, I wrote a little C app to convert the relocation table from the overlay into an IDC script, and pasted the lines in several at a time. Worked like a charm!
Then I found ANOTHER broken stub and realized I was going to have to do this all over again. So I opted to make my life a little easier. I wrote another C app to scan the LORD.EXE and locate all of the overlay stubs, then using that information, extract each segment and relocation table into separate binary files, while printing out code and relocation sizes and all that as it goes. I was then able to easily import the code chunk I needed, parse the relocation binary with my other little C app to make the relocation script, patch it, and done. That segment went in much quicker.
I used my stub finder to determine that every stub was now in fact added into IDA. So I proceeded to label those few functions which got added (related to DarkCloak Tavern as it turns out) and can now say I have nearly all of the game's assembly processed/labeled/etc. Again.
This also indirectly resulted in setting me on a path to determine what a couple more of the settings in PLAYEXT.DAT are specifically, so it wasn't all bad!
p.s. The alternative to writing the relocation-to-IDC-script utility would have been one to just patch the segment directly before inserting it. But since I'd already manually inserted the first one straight out of the overlay, I opted to just fix what was already there than try to do it again. This was before I realized I was in fact going to have to do it a second time anyway for the other segment that was missing!
Saturday, May 19, 2012
Thursday, May 10, 2012
Color Quandary
I haven't posted here lately, but for the record, I've labeled and identified basically 99% of the game at this point, so there's not much left to do in terms of disassembly. So I've been working on something related to it. But I did come across some stuff earlier which might warrant a mention. It's in the function to display LORD color codes locally.
But here's the thing: that second iteration will never get called normally. Because of the way the comparison checks work, after the first test for `r, the string position variable is incremented in order to get the background digit. By the time it reaches the other comparison check for `r, the current character won't be `r anymore, it'll be the position of the digit, so the comparison never matches. BUT, it can happen, I suppose, if you use an invalid LORD code. For example, `rr4 would trigger it. This can't be tested in the game itself, though, because all of the editable content (LORDTXT.DAT etc) go through a different color code parsing function.
On a side note, looking through Barak's House is actually fun, because I can see the original (and sometimes much more simple) Pascal code of some of the same functions I spent the time disassembling and figuring out in LORD.
I guess that's it. A lot of rambling about some simple color stuff!
First of all, there is no foreground black, aka color 0. You can use LORD code `^, which sets the foreground color to 16, which will technically be black, but this is not correct. It will be black, sure, but it will also enable blinking text. So if you have a background other than black, you'll see the characters on it, and they will in fact be blinking.
In the Turbo Pascal TextColor function, anything over color 15 will set the blinking bit. 15 or less (aka the standard 16 DOS colors) resets the bit to 0. I'm not exactly sure why Borland chose to do it this way, since the blinking bit is actually at the end of the background color nibble of the text attribute byte in video memory. The bits are broken up as: bBBBFFFF, where b is blink, BBB is background, and FFFF is foreground. The TextBackground function only seems to accept 0..7 according to the help, though, so I'm doubting that blink can be enabled from it. It would make more sense from a technical standpoint to let you set the flashing bit that way, by setting the background color higher than 7 as you would directly into memory. Maybe they thought it would be confusing to people, since the foreground characters are what blink when it's enabled, so they figured all foreground-related stuff should be together? Something I wonder about though is whether Turbo Pascal can actually accept higher than 8 colors for the background, because EGA and up lets you disable blinking in the hardware in order to use the last bit to enable a full 16 colors for the background like the foreground can do. If TextBackground limits the value, you'd have to use a roundabout method of setting the extended background color when in that mode.
Anyway, the second LORD thing is regarding color 12. In this local printing function, for some reason the `@ LORD code translates to color 9, which `9 also does. Maybe since this local print function isn't used for a whole lot of stuff other than during startup, he just never noticed.
Next is something the background colors. For that you use `rX, where X is the background color. This time we do have a 0 for black. But we also have an 8. As mentioned above, though, this might not be possible and simply display black like with 0. Then again, maybe it displays black and enables blinking? No way to find out unless I wrote a test program in Pascal itself.
Next is something the background colors. For that you use `rX, where X is the background color. This time we do have a 0 for black. But we also have an 8. As mentioned above, though, this might not be possible and simply display black like with 0. Then again, maybe it displays black and enables blinking? No way to find out unless I wrote a test program in Pascal itself.
Related to the above is an oddity. Apparently Seth tried to implement setting the background color twice, probably as an oversight. The first time uses a bunch of comparison checks for each ASCII number value. The second one though works differently; it actually makes a short string of the value, and uses the Turbo Pascal "Val" function to convert it into a number, and then sets the background color. This would let you set 0..9, even.
But here's the thing: that second iteration will never get called normally. Because of the way the comparison checks work, after the first test for `r, the string position variable is incremented in order to get the background digit. By the time it reaches the other comparison check for `r, the current character won't be `r anymore, it'll be the position of the digit, so the comparison never matches. BUT, it can happen, I suppose, if you use an invalid LORD code. For example, `rr4 would trigger it. This can't be tested in the game itself, though, because all of the editable content (LORDTXT.DAT etc) go through a different color code parsing function.
You can look at the source code to Barak's House to find its local color-setting function which has this exactly same "bug."
On a side note, looking through Barak's House is actually fun, because I can see the original (and sometimes much more simple) Pascal code of some of the same functions I spent the time disassembling and figuring out in LORD.
I guess that's it. A lot of rambling about some simple color stuff!
Saturday, May 5, 2012
Multi-day Dump
I haven't updated this recently, because individual little things I came across during my disassembly didn't really warrant a post to themselves. But I can take the time to touch on a few things for a single update!
I was starting to run dry on sources to find information on various variables and functions. But then I decided to take a different approach: disassemble LORDCFG.EXE as well. This turned out to be a great idea, because it let me figure out the format of LORD.DAT, as well as figure out how the node files work. I even figured out the registration code algorithm. So I took this information with me back to LORD.EXE and quickly started filling in lots of stuff, and figuring out the bits of LORD.DAT which are impossible to know from LORDCFG. I don't remember ever seeing anyone post what LORD.DAT's structure was before, now that I think about it, so maybe I'll do that here:
regcode1 : long
regcode2 : long
day_last_run : word ; The day of the month in which the game was last run
regcode3 : long
gamewinner : string[146] ; Name of the last winner of the game
multinode_support : byte ; Enable multi-node support
regcode4 : long
allow_bank_transfers : byte ; Allow bank transfers
max_bank_transfer : long ; Maximum amount of money transferable via the bank
human_fights : long ; Number of player vs player fights a day
regcode5 : long
grace_deletion_days : long ; Number of days until players are deleted
ANSI_score_filename : string[60] ; Path + filename to generated ANSI score file
ASCII_score_filename : string[60] ; Path + filename to generated ASCII score file
unknown_string : string[60] ; Nothing uses this that I can find
clean_mode: byte ; Enable clean mode
forest_fights : long ; Forest fights a day
registered_thanks : string ; Who to thank for registering the game
bank_transfers_per_day : byte ; Number of bank transfers allowed a day
I took the time just now to convert that from assembly stuff like "db" and "dw" to a Turbo Pascal-ish syntax, to match the PLAYER.DAT structure Seth gives in LORDSTRC.PAS. Keep in mind that off the top of my head I don't know which of those are actually boolean/char/byte, signed/unsigned, etc. If in question, assume it's signed. If you're only interested in size though (like for loading it in C), long is 4 bytes, word is 2 bytes, byte is 1 byte, and strings are always 1 byte longer than specified (to hold the string length). If no size is specified, the string is 1 size byte + 255 characters. The entire structure is 628 bytes.
Let's see, what else? I've been figuring out formats to all the in-game files like OUT.x, INFO.x, FIGHTx.DAT, etc. I had to make a list of just all of the files the game uses, to keep track! I've also been deducing/documenting the conditions which are required for certain random game events to occur. And I started making a list of all of the special LORD color codes, since they're not all documented.
That reminds me. Something strange I noticed is that LORDTXT.DAT has some ANSI art in it which is damaged. I think Seth used a utility written in Pascal (probably something he wrote himself) to create the file, but unfortunately Pascal's string length limit of 255 characters resulted in some of the really long lines of ANSI getting chopped. So the ANSI graphic of the dragon's lair, and I think the New World one, maybe another but I can't remember, have some damage; ANSI sequences just abruptly end on 2-3 lines. That would imply it was broken like that back in the old days on the BBSes too, but I can't remember either way.
Thanks in part to Barak's House, I found the Turbo Pascal source files of some add-on libraries Seth used, which has made labeling some of the support sections and internal variables a little easier. A lot of it I don't really need to have labeled for disassembling the game itself. But doing so helps me find the stuff Seth himself wrote from the 3rd-party helper stuff he linked in. But to be honest, I think I've identified 99% of the functions Seth made. It's mostly some variables left which are giving me a headache to figure out.
I thought there was something else I wanted to mention too, but I can't think of it. Maybe next time!
I was starting to run dry on sources to find information on various variables and functions. But then I decided to take a different approach: disassemble LORDCFG.EXE as well. This turned out to be a great idea, because it let me figure out the format of LORD.DAT, as well as figure out how the node files work. I even figured out the registration code algorithm. So I took this information with me back to LORD.EXE and quickly started filling in lots of stuff, and figuring out the bits of LORD.DAT which are impossible to know from LORDCFG. I don't remember ever seeing anyone post what LORD.DAT's structure was before, now that I think about it, so maybe I'll do that here:
regcode1 : long
regcode2 : long
day_last_run : word ; The day of the month in which the game was last run
regcode3 : long
gamewinner : string[146] ; Name of the last winner of the game
multinode_support : byte ; Enable multi-node support
regcode4 : long
allow_bank_transfers : byte ; Allow bank transfers
max_bank_transfer : long ; Maximum amount of money transferable via the bank
human_fights : long ; Number of player vs player fights a day
regcode5 : long
grace_deletion_days : long ; Number of days until players are deleted
ANSI_score_filename : string[60] ; Path + filename to generated ANSI score file
ASCII_score_filename : string[60] ; Path + filename to generated ASCII score file
unknown_string : string[60] ; Nothing uses this that I can find
clean_mode: byte ; Enable clean mode
forest_fights : long ; Forest fights a day
registered_thanks : string ; Who to thank for registering the game
bank_transfers_per_day : byte ; Number of bank transfers allowed a day
Let's see, what else? I've been figuring out formats to all the in-game files like OUT.x, INFO.x, FIGHTx.DAT, etc. I had to make a list of just all of the files the game uses, to keep track! I've also been deducing/documenting the conditions which are required for certain random game events to occur. And I started making a list of all of the special LORD color codes, since they're not all documented.
That reminds me. Something strange I noticed is that LORDTXT.DAT has some ANSI art in it which is damaged. I think Seth used a utility written in Pascal (probably something he wrote himself) to create the file, but unfortunately Pascal's string length limit of 255 characters resulted in some of the really long lines of ANSI getting chopped. So the ANSI graphic of the dragon's lair, and I think the New World one, maybe another but I can't remember, have some damage; ANSI sequences just abruptly end on 2-3 lines. That would imply it was broken like that back in the old days on the BBSes too, but I can't remember either way.
Thanks in part to Barak's House, I found the Turbo Pascal source files of some add-on libraries Seth used, which has made labeling some of the support sections and internal variables a little easier. A lot of it I don't really need to have labeled for disassembling the game itself. But doing so helps me find the stuff Seth himself wrote from the 3rd-party helper stuff he linked in. But to be honest, I think I've identified 99% of the functions Seth made. It's mostly some variables left which are giving me a headache to figure out.
I thought there was something else I wanted to mention too, but I can't think of it. Maybe next time!
Subscribe to:
Comments (Atom)