The dangers of flags

Jul 19, 2006 at 4:50 AM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
After a bit of screwing around with offsets, I noticed the flags fall very close to relatively harmless stuff in memory. I tried something out.

Turns out there's no check made to see if you go beyond the reserved space for flags. You can go mess around with other data if you know what you're doing. This is potentially dangerous since you might end up setting a flag in Sue's thinking it's safe, but actually be modifying memory elsewhere.

There are 1000 flags, meaning the safe range is between 0000 and 8000. Beyond that you're bumping into other reserved RAM.

0049DDA0 <- The starting offset of the flags.

Each flag is a bit, meaning it takes 8 flags to move by 1 byte. So flag 8 is 0x0049DDA1.

0049E1DC <- This is a "soft" quake effect. You can set a value to it by doing the following.

0049E1DC - 0049DDA0 = 43C (1084 in decimal)
1084 x 8 = 8672.

Flags 8672 to 8679 control the "soft" quake offset. You can give it ANY value by screwing around with the contents in binary using flags (ie, 8672 is 1, 8673 is 2, 8674 is 4...)

Flag 9088 to 9095 controls which key is being held, for instance. I don't have all of the offsets for what is covered by this, but there are a few important system-related things to watch out for (the keyboard handler being one of them, like in this case.)

Enjoy - this is about all that I have in the range flags cover in RAM at the moment. Anyone who can find interesting junk should feel free to use it as desired in their hack. Note that flags past 8000 are unsafe and prone to change often.

Oh yeah, you can also use the game's time as a semi-random number generator (0049E1EC; flags 8800-8831.) The miliseconds are sure to change frequently enough to serve as a reliable random branch device.
 
Jul 19, 2006 at 5:36 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
I figured this wasn't thread-worthy, so I thought I'd post it here. Maybe this thread could be more of a "odds and ends" thing. Anyhow.

The max amount of maps a hack can have is 128 (0x80). The reason for this is that the code reserves 0x80 bytes for a structure contained at 0049E5B8 in RAM. This structure is indexed by the map ID, meaning that maps over 0x80 would end up messing around in memory reserved for other uses, which could screw the game up.

The function at 0x00014B20 is the main culprit. The CALL it makes to 00480D30 is basically a call to a function which zeroes out memory, and 0x80 is PUSHed onto the stack at some point (the function uses this to calculate how many bytes to affect by the function.) I suspect, for you C/C++ programmer out there, that this is a call to ZeroMemory() (which itself is an alias of sorts for memset(x, 0, y).) If this doesn't make sense to you, don't sweat it - basically, there are 0x80 entries reserved for maps in the code and in memory.
 
Jul 19, 2006 at 10:32 PM
Hoxtilicious
"Life begins and ends with Nu."
Join Date: Dec 30, 2005
Location: Germany
Posts: 3218
Age: 33
Pronouns: No homie
The dangers of flags? ^^ are flags dangerous? lol well I have a question, were i can set that flags, in the EXE or on a specific map? what can I do with that flags? ^^
 
Jul 19, 2006 at 10:41 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
Those are event flags. Ie, <FL+. I'm talking about stuff you can do with Sue's Workshop, not assembly. ;) Mind you, you could mess around with those offsets in the code to acheive effects (ie, a well-placed MOV byte ptr [0049E1DC], 0xFF would trigger some quake effect for 255 units of time), but this isn't accessible to everyone so using flags and this little bug makes these things easier to acheive.

I'll post more offsets if I find any.

By "the danger of flags" I'm talking about the lack of bounds checking, which allows you to do the above. You can use flag-related commands in a script to access non-flag data, which is very dangerous if you don't know what you're doing, and most likely unreliable. ;)
 
Jul 20, 2006 at 9:45 AM
Hoxtilicious
"Life begins and ends with Nu."
Join Date: Dec 30, 2005
Location: Germany
Posts: 3218
Age: 33
Pronouns: No homie
So if i set flag 8002 or a another flag for example, the programm would be quit, cause of a error? :p
 
Jul 20, 2006 at 3:56 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
It could, but chances are you'll just end up setting, for example, the time you've been playing to 4 minutes. Then next time you try to read from that, you'd end up getting an unset flag because a few minutes have elapsed and the time has changed.

<FL+8600

This, for instance, will crash the game.

<FL+8674

This won't. It'll trigger a brief shaking of the screen, but definately won't act as a flag.
 
Jul 20, 2006 at 4:57 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
Found four new very interesting offsets.

0049E190 <- When set to a non-zero value, flashes occasionally (like lightning)
0049E1C4 <- Flash B color
0049E1C8 <- Flash G color
0049E1CC <- Flash R color

The really interesting stuff are the three RGB flash colors. You can make the screen flash other colors like that. Here's an example script.

<FL-8480
<FL-8481
<FL-8482
<FL-8483
<FLA

Wham. Yellow flash.
 
Jul 20, 2006 at 4:59 PM
Hoxtilicious
"Life begins and ends with Nu."
Join Date: Dec 30, 2005
Location: Germany
Posts: 3218
Age: 33
Pronouns: No homie
Cool ^^ These Flags Are For Awesome Effects !! Xd

Edit: maybe we need a overview? ;)

I will make a simple FAQ for this! Things like this are not to hard (you just need a little bit of endurance :p), so It's my Job todo this ^^
 
Jul 21, 2006 at 1:17 AM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
What do you mean by overview?

Some of these are not very obvious. For instance, one of the values covered, I suspect, is a handle to a device context. A device context is basically some immaterial concept used to represent anything graphical that Windows can alter, like a bitmap image or the contents of a window. A handle is the address which points to this device context (think of it like grabbing the handle on a door before being able to use its "open" method) A crafty hacker may be able to redirect the rendering to some other device context of his own creation to pull out images and such, but this isn't for the faint of heart, and most certainly isn't observable through experimentation.

Other things are easy to find, like the flash and shaking effects. But so far I haven't run into many of them. In fact I suspect there's a large gap somewhere in memory right after various keyboard-related stuff. That could be used to store additional temporary flags, I guess... but it's too unpredictable to know for sure. The offset (0049E21C) doesn't show up in the code, but it COULD be pointed to from a pointer table (checking... nope) or calculated on the fly (unlikely, but not impossible.)

I'm not sure how big that section is. Use at your own risk.

The three 32-bit values before that offset control various input-related things (which keys are held, for instance) but since there's no reliable way to send commands to the player during an event, they're of little use.

That's all I know so far. Good luck finding the rest. :p

Edit: Y'know, it wouldn't be TOO hard to code a command that would take two values and use them to set an address to any value...

<SET0049E1C4:FF
<SET0049E1C5:80
<SET0049E1C6:00
<SET0049E1C7:00

I might look into that... there are so many things the script commands can't do. ;)

Edit 2: Actually it'd be even better to be able to also manipulate the stack and call our own functions. All's we'd need are...

- A MOV instruction (to and from).
- A PUSH instruction (direct and indirect).
- A CALL instruction.

Of course heavy familiarity with the internal workings of the game would be required but you'd have 100% control over EVERYTHING in the game during a script.
 
Jul 25, 2006 at 4:43 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
Hehe, I had fun with flags last night. I moved the offset they're read from by a few bytes, which allowed me to access other offsets in memory.

I'm still considering writing a MOV (assembly-style, not the tsc command) script command. I have two functions that can take hex from the script and convert it to binary values I can toy with. I was hoping I could create a PUSH command, but this is impossible: the stack doesn't get preserved between calls made to the script parser so it'd just end up putting crap on the stack. So much for that.

Once (if) I get a MOV instruction in place (gonna have to name it otherwise because MOV is a reserved mnemonic already in the commands...) I'll post the code here. It should prove highly useful for hackers who know what they're doing and want to script something that script commands simply cannot permit. Calling FL+ 32 times to set a 32bit value causes a noticeable delay. A, say... <SOV0049E1C4:00FF8000 command would mean only one call to the script parser and would have the same effect as 32 calls to FL+ (in this case, to set the color of flashes; SOV being a mnemonic for Set Offset Value.)

The best solution for maximum flexibility would be to write scripts directly in assembly. But one can only dream. :)
 
Jul 26, 2006 at 6:08 PM
Senior Member
"Huzzah!"
Join Date: Mar 24, 2006
Location:
Posts: 194
Age: 35
Pronouns: he/him
RuneLancer said:
I figured this wasn't thread-worthy, so I thought I'd post it here. Maybe this thread could be more of a "odds and ends" thing. Anyhow.

The max amount of maps a hack can have is 128 (0x80). The reason for this is that the code reserves 0x80 bytes for a structure contained at 0049E5B8 in RAM. This structure is indexed by the map ID, meaning that maps over 0x80 would end up messing around in memory reserved for other uses, which could screw the game up.

The function at 0x00014B20 is the main culprit. The CALL it makes to 00480D30 is basically a call to a function which zeroes out memory, and 0x80 is PUSHed onto the stack at some point (the function uses this to calculate how many bytes to affect by the function.) I suspect, for you C/C++ programmer out there, that this is a call to ZeroMemory() (which itself is an alias of sorts for memset(x, 0, y).) If this doesn't make sense to you, don't sweat it - basically, there are 0x80 entries reserved for maps in the code and in memory.

I have 129 maps in my mod & I haven't noticed any serious problems while playing the game all the way through

the last map is unused though
 
Jul 27, 2006 at 6:05 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
The problem shouldn't occure if you don't use the map. But the code makes it obvious Pixel intended for a max of 128 maps - additional maps could cause various problems, perhaps unnoticeable ones at first.

The offset I mentionned is actually not that big a problem (though there are other offsets related to map data with 0x80 entries.) It's actually used for MP+ and MPJ. Using MPJ on any map above 128 will cause unpredictable behavior (the byte immediately after the last entry (0x80th one) holds various flags about Quote's state.)

MP+ is very interesting in that it could be used just like FL+ to access other reserved memory offsets, by the way.
 
Aug 3, 2006 at 7:27 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 40
I figured this wasn't quite thread-worthy and, hey, this thread contains a slew of miscalenious info anyhow so...

I've been trying to find where the "Studio Pixel Presents" and the version/copyright info on the title screen are located, seeing as they're not in the title screen pbm file. Curiousity is the driving force that motivates a hacker, after all - we wouldn't be digging through the game for info if we weren't curious how it works. So I set about digging through the executable for these two elusive strings.

The first string, along with a number of images shown during the credits, can be found using any resource editor. They're bitmap resources and can be edited quite easily.

The second one is a bit more complicated. Pixel really went through unecessary trouble setting that part up. Regretfully I don't have the offset (not at home - no internet, etc etc) but it's not too hard to find. A series of MOV instructions in a function simply shove 1-byte values into the stack. A bit of digging with a dump of the game's code will turn it up relatively easily (IIRC it starts by mov byte ptr [ebp-20], 0xFF | mov byte ptr [ebp-1F], 0xFF) The values SEEM like they'd form a string, but mapping them out to ascii reveals... gibberish.

On a hunch (and because of the presence of 0x1F every once in a while - seemed like a space would go there (ascii code 0x20)) I added 1 to each value and it mapped out to " Studio Pixel presents" A quick run through the rest of the code revealed that, yes, it DID add 1 to every byte when reading these off of the stack.

So there you go. You can now edit these things to put your name in your own hack. Just keep in mind even if you've gone through extensive rewritings of the game's code, you did not write Cave Story. Give proper credit in your readme file at least. ;)
 
Back
Top