Question about sprite data.

Status
Not open for further replies.
Jan 29, 2009 at 1:12 AM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6223
Age: 39
Pronouns: he/him
How is sprite information (direction, position, which sprite it is, etc.) stored within the exe? Do events draw sprite to the screen or are they all bundled together? How are the hex values for this information laid out?

This isn't for modding, but rather as a curiosity thing that is driving be nuts! Just a general idea please, regardless of if Cave Story is the example you use.

Please help.

p.s. If my terminology is bad then recall that, while I have hacked before, I have never modded (or hacked) Cave Story before (profile.dat doesn't count).
 
Jan 29, 2009 at 1:15 AM
Senior Member
"I, Ikachan. The Life and Documentary of the OrigiNAL SQuiD."
Join Date: Dec 28, 2008
Location:
Posts: 174
I think the scripts decide which sprite to use.

(EX: Pretend Sue's standing sprite is #0003, the script probably uses a command choosing the sprite ending with 0003.)
 
Jan 29, 2009 at 12:35 PM
graters gonna grate
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Jul 2, 2008
Location: &
Posts: 1886
Age: 32
Pronouns: he/him
That's basically true, but as far as I know, no one has figured out how to change what images an entity uses or what coordinates on the spritesheets the images are taken from. We do know how to change which spritesheets the images are taken from, though (npc.tbl hacking).
 
Jan 30, 2009 at 2:14 AM
Administrator
Forum Administrator
"Life begins and ends with Nu."
Join Date: Jul 15, 2007
Location: Australia
Posts: 6223
Age: 39
Pronouns: he/him
So basically the script places the sprite, and the framerects, which sprite it is, etc are called from the exe by the number 0003?
 
Jan 30, 2009 at 2:35 AM
In front of a computer
"Man, if only I had an apple..."
Join Date: Mar 1, 2008
Location: Grasstown
Posts: 1435
I bet it's hardcoded into the executable... which may or may not mean it is interspersed with the code. (I don't know how these things work really.) Anyway, wherever constants from the code are stored.
 
Jan 30, 2009 at 12:38 PM
Senior Member
"I, Ikachan. The Life and Documentary of the OrigiNAL SQuiD."
Join Date: Dec 28, 2008
Location:
Posts: 174
andwhyisit said:
So basically the script places the sprite, and the framerects, which sprite it is, etc are called from the exe by the number 0003?

That's what I would have to guess. But different numbers can be placed, and don't forget about Eternities.
 
Feb 1, 2009 at 12:47 PM
Junior Member
"It's dangerous to go alone!"
Join Date: Jan 3, 2009
Location:
Posts: 36
I'm not really sure what you mean about direction and position. That's a game engine thing so there is no "hex data" for it. Direction is at +0x4C in each object structure in the game's internal array; which is literally just a simple 200-entry array, not a linked-list or anything. X and Y coordinates are +8 and +C, and are left-shifted by 9 bits.

Each object IS it's sprite, there is no "assigning a sprite to an object" like with some game engines. In other words there doesn't seem to be any distinction between a graphic (the sprite) and it's AI code (an object).

Each sprite has a frame number at +68. At the end of every objects AI function there is a macro (C preprocessor macro) which looks at the current value of +68 and sets other variables based on that which tell the game engine where to pull it's source blit from off the spritesheet. I'm not clear on exactly how that part works because I never looked into it but it seems to have something to do with the +5X range of bytes. Though the fact that the code to set the spritesheet source rect is actually IN each AI func may explain why there is no distinction between sprites and objects.

OTOH if you were talking about scripting, then direction and animation is done with the CNP and ANP type commands. For the same "animation" value those commands can have totally different effects on one sprite vs another because what they're really doing is directly setting the objects internal state (+74).

I believe the object structure begins at 4a6294 although that's not really of much practical use--what you'll actually be wanting if you want to look at how the objects work is the AI function pointer table. It's at 498548 and consists of 370 4-byte entries that point at AI functions. The deference into it is at 46FA62; the EAX you see there is the object type, he's just calling a function pointer out of an array.

Did that answer your question? If not maybe you can elaborate on what you're asking.
 
Feb 1, 2009 at 12:55 PM
Junior Member
"It's dangerous to go alone!"
Join Date: Jan 3, 2009
Location:
Posts: 36
supermario566 said:
I think the scripts decide which sprite to use.

(EX: Pretend Sue's standing sprite is #0003, the script probably uses a command choosing the sprite ending with 0003.)
No, the scripts will do an ANP to a STATE such as 0003, which will result in Sue standing, however I do not believe the sprites themselves are numbered in that way. Again I only know what I've seen in passing because I was not interested in that, but I think the internal sprite mechanism is pretty 'loose' and based more on coordinates on the spritesheet than on any sort of "sprite index". I can tell you without a doubt though that the scripts do NOT pick the sprite. They set the object's state variable, which causes the object to change it's frame, which causes a different sprite to be shown. If scripts picked the sprite, then things like blinking and running animations would all have to be coded into all the TSC's.
 
Feb 1, 2009 at 4:41 PM
In front of a computer
"Man, if only I had an apple..."
Join Date: Mar 1, 2008
Location: Grasstown
Posts: 1435
sshsigi said:
That's a game engine thing so there is no "hex data" for it.
If a value is used by the program, then it's stored in the executable (or an external file). So yes, there would be "hex data" for it.

sshsigi said:
At the end of every objects AI function there is a macro (C preprocessor macro) which looks at the current value of +68 and sets other variables based on that which tell the game engine where to pull it's source blit from off the spritesheet.
Hmm... there's something very wrong here...

sshsigi said:
(C preprocessor macro)
Bingo! That's 32768% false! A C preprocessor macro does not appear in the executable. It is substituted before the code is even compiled!

Most likely the "macro" in question is a function in the original code.

EDIT: Also, as I understand it, a macro (other than C preprocessor macros) is actually a function that returns a function, or something like that.
 
Feb 2, 2009 at 1:22 AM
Junior Member
"It's dangerous to go alone!"
Join Date: Jan 3, 2009
Location:
Posts: 36
Celtic Minstrel said:
If a value is used by the program, then it's stored in the executable (or an external file). So yes, there would be "hex data" for it.

There would be "hex data" in the form of machine instructions, but what I meant to say is that there can be no sort of table that encodes the directions and locations of sprites, since that's a dynamic thing that changes at runtime. The "locations of sprites" can only be stored as an algorithm that determines the physics and rules of the game.

If you're talking about their starting positions, then yes all NPC locations are stored in the .pxe file, and the starting coordinates and map of the player come from either the executable or a saved game file. Everything after that though must be a function of the game's logic + the player's input.

Bingo! That's 32768% false! A C preprocessor macro does not appear in the executable. It is substituted before the code is even compiled!

Most likely the "macro" in question is a function in the original code.

EDIT: Also, as I understand it, a macro (other than C preprocessor macros) is actually a function that returns a function, or something like that.

Well if you want to be picky about it, then yes of course there is no ACTUAL macro. What I meant to say is that I can tell that the source code was USING a macro, since the final assembly code is exactly the same every time, except for variations in the "plugged in" constants.

For example, there is another common code sequence I know was generated by a macro, which is the macro that animates all the NPCs and enemies. It looked something like this:

PHP:
#define ANIMATE(SPEED, FIRSTFRAME, LASTFRAME)		\
{													\
if (++o->animtimer > SPEED)						\
{												\
o->animtimer = 0;							\
if (++o->frame > LASTFRAME) o->frame = FIRSTFRAME;	\
}	\
}

So he'd call like ANIMATE(2, 0, 5) every time through an AI func and the sprite would loop from frames 0 through 5 at a rate of one frame changed every 2 ticks.

Here's the good part. The reason I know this is a macro and not just repeated similar C code is that sometimes he would want a sprite to change it's frame EVERY tick. So he said:

PHP:
ANIMATE(0, 0, 5);

Which results in:

PHP:
if (++o->animframe > 0) { o->animframe = 0; if (++o->frame > 5) { o->frame = 0; } }

Now why would ANYONE code that? ++o->animframe will ALWAYS ALWAYS be greater than zero. It's a waste of typing and code space and makes no sense. A human would write:

PHP:
if (++o->frame > 5) o->frame = 0;

...for these instances. UNLESS they were used to using a macro for all their animations. Then they just see it as passing in a "speed" value of 0 meaning they want to change frames every tick. ANIMATE(0, 0, 5);
looks nice and neat in the source.

That's why I said it's a macro, because I'm 99% certain it came from a macro. If you want to be picky about it, the executable doesn't really have any "variables" or "functions" in it either, does it? It's just a big blob that writes to various memory addresses. And sometimes, it pushes the IP onto the stack and jumps to other places. And sometimes, it pulls a DWORD off the stack and copies that value into the instruction pointer. We call these things "macros", "variables", and "functions" because that's how the programmer thought of them when he laid them out. So even though the macros are now all expanded out, I still think it's ok to think of them as macros, and a good idea too, since it enhances our understanding of the code.
 
Status
Not open for further replies.
Back
Top