Special Effects Hacking

Jul 6, 2008 at 10:26 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 39
So everyone's going crazy over weapons and entities, and I can't help but feel bad for the little guy. The data that nobody notices but everyone would miss were it gone. That's right, I'm talking about effects.

There are 18 different types of effects. Each effect can have a mode which can alter what happens exactly.



Code:
00 Nothing
01 Pulsing Disc Particles (mode 0: blue discs, mode 1: red discs)
02 Rising Disc / Exploding Diamond (mode 0: green disc, mode 1: diamond explosion)
03 Star (mode 0 only)
04 Fireball Impact (mode 0 only)
05 ZzZ... (mode 0 only)
06 (same as 04)
07 Booster smoke (mode 0 only)
08 Drowned Quote (mode 0: face left, mode 1: face right)
09 Exclamation (mode 0: question mark, mode 1: exclamation mark)
0A Level Up/Down (mode 0: level up, mode 1: level down)
0B Red "damage" discs (mode 0 only)
0C White "explosion" disc (mode 0 only)
0D Headbump sparks (mode 0 only)
0E ?
0F Small white "explosion" disc (mode 0 only)
10 "Empty!" (mode 0 only)
11 "Push jump key!" (mode 0 only)
The rest seem rather buggy...

The pointer table to their code can be found at 0048F8C0.

Code:
70964000
80964000
80984000
809B4000
709C4000
009E4000
709C4000
609F4000
20A14000
B0A14000
80A24000
F0A34000
A0A54000
50A64000
E0A74000
F0A84000
E0A94000
A0AA4000
90C24800
A4C24800
BCC24800

Here's how the data is laid out.

Code:
0049BCA8	EffectObj[0x00].InUse		+0x00		0x44 in len
0049BCAC	EffectObj[0x00].ID		+0x04
0049BCB0	EffectObj[0x00].Mode		+0x08
0049BCB4	EffectObj[0x00].X			+0x0C
0049BCB8	EffectObj[0x00].Y			+0x10
0049BCBC	EffectObj[0x00].MoveX		+0x14
0049BCC0	EffectObj[0x00].MoveY		+0x18
0049BCC4	EffectObj[0x00].WasInit		+0x1C
0049BCC8	EffectObj[0x00].			+0x20 ; Unused?
0049BCCC	EffectObj[0x00].FrameID		+0x24 ; This is the actual frame to display, from the rects.
0049BCD0	EffectObj[0x00].FrameTimer	+0x28
0049BCD4	EffectObj[0x00].XOffset		+0x2C
0049BCD8	EffectObj[0x00].YOffset		+0x30
0049BCDC	EffectObj[0x00].Display_L	+0x34
0049BCE0	EffectObj[0x00].Display_U	+0x38
0049BCE4	EffectObj[0x00].Display_R	+0x3C
0049BCE8	EffectObj[0x00].Display_D	+0x40

Aside from this, here are a few functions that may prove interesting (I've transformed them into pseudocode to make them easier to understand.)

Code:
	|													|
|	Clear All Effects										|
|													|
409650::clear_all_effects
{
// Clear 64 x 68 bytes.
409650		push 0x00001100						// Size  : 4352 bytes (64 x 68)
409658		push 0x00000000						// Value : 0
40965a		push &EffectObj						// Offset: Effect Objects
40965f		call 480D30::memset

// Exit.
409670		return
}


|													|
|	Update All Effects										|
|													|
40ab50::update_all_effects
{
40ab50		L04_SlotID = 0
40ab5d		Goto 40ab68

// Iterate through all 64 effect slots.
40ab5f		{
L04_SlotID++
40ab68			if(L04_SlotID >= 64)
return

// Skip this slot if it's not in use.
40ab6e			if(EffectObj[L04_SlotID].InUse & 0x80 != 0x00)
{
// Call the appropriate effect code and move along.
40ab82				push &EffectObj[L04_SlotID]
40ab9e				call ROM_PEffects[EffectObj[L04_SlotID].ID]
}
40abab		}
}

|													|
|	Create Animated Effect										|
|	08_X				X position.							|
|	0C_Y				Y position.							|
|	10_ID				Effect ID.							|
|	14_Mode				Effect Mode.							|
|													|
40ac90::create_animated_effect
{
// Find a free slot.
40ac90		L04_EffectSlot = 0
40ac9b		Goto 40aca6

40ac9d		{
L04_EffectSlot++
40aca6			if(L04_EffectSlot >= 64)
break

40acac			if(EffectObj[L04_EffectSlot].InUse == 0)
40acbb				break
40acbd		}

// Exit if no slots are free.
// That is, if we've hit slot 64, that means we've gone through all slots without finding anything.
40acbf		if(L04_EffectSlot == 64)
40acc5			return

// Clear the slot.
// Writes 0x00 to 68 bytes.
40acca		push 0x00000044						// Size  : 68 bytes
40accc		push 0x00000000						// Value : 0
40acce		push &EffectObj[L04_EffectSlot]				// Offset: Specified Effect
40acdb		call 480D30::memset

// Fill the slot with data.
40ace3		EffectObj[L04_EffectSlot].InUse		= 0x80
40acf3		EffectObj[L04_EffectSlot].ID		= 10_ID
40ad02		EffectObj[L04_EffectSlot].X		= 08_X
40ad11		EffectObj[L04_EffectSlot].Y		= 0C_Y
40ad20		EffectObj[L04_EffectSlot].XOffset	= [10_ID * 8 + 0048f830]	// 0048F830: Effect Offset Table.X
40ad36		EffectObj[L04_EffectSlot].YOffset	= [10_ID * 8 + 0048f834]	// 0048F830: Effect Offset Table.Y
40ad4c		EffectObj[L04_EffectSlot].Mode		= 14_Mode

// Exit.
40ad5b		return
}

Happy hacking!
 
Jul 6, 2008 at 10:30 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 39
Code:
	|									|
|	Effect 0x01: Pulsing Disc Particles				|
|	08_Effect	The effect object for this.			|
|									|
|	INITIAL_VEL_X_MIN		0xFFFFFC00 (-4)			|
|	INITIAL_VEL_Y_MIN		0xFFFFFC00 (-4)			|
|	INITIAL_VEL_X_MAX		0x00000400 ( 4)			|
|	INITIAL_VEL_Y_MAX		0x00000000 ( 0)			|
|	FRAME_DELAY			0x05       ( 5)			|
|	NUM_FRAMES			0x03       ( 3)			|
|									|
409680::effect_0001
{
// Frame Data
409680		frames[-0x0040] = { 0x00000000, 0x00000040, 0x00000008, 0x00000048 }	// 000 064  008 072: Blue disc 4
4096a5		frames[-0x0030] = { 0x00000008, 0x00000040, 0x00000010, 0x00000048 }	// 008 064  016 072: Blue disc 3
4096c1		frames[-0x0020] = { 0x00000010, 0x00000040, 0x00000018, 0x00000048 }	// 016 064  024 072: Blue disc 2
4096dd		frames[-0x0010] = { 0x00000018, 0x00000040, 0x00000020, 0x00000048 }	// 024 064  032 072: Blue disc 1
4096f9		frames[-0x0080] = { 0x00000040, 0x00000018, 0x00000048, 0x00000020 }	// 064 024  072 032: Red disc 4
409715		frames[-0x0070] = { 0x00000048, 0x00000018, 0x00000050, 0x00000020 }	// 072 024  080 032: Red disc 3
409731		frames[-0x0060] = { 0x00000050, 0x00000018, 0x00000058, 0x00000020 }	// 080 024  088 032: Red disc 2
40974d		frames[-0x0050] = { 0x00000058, 0x00000018, 0x00000060, 0x00000020 }	// 088 024  096 032: Red disc 1

// If the effect wasn't initialized, we give it a random X/Y velocity.
// The velocity will make the particle go left or right randomly and upwards.
409769		if(not 08_Effect.WasInit)
{
409772			08_Effect.WasInit = 1
40977c			push INITIAL_VEL_X_MAX						// Max: +4
409781			push INITIAL_VEL_X_MIN						// Min: -4
409786			08_Effect.MoveX = {40f350::random_number}
409794			push INITIAL_VEL_Y_MAX						// Max: +0
409796			push INITIAL_VEL_Y_MIN						// Min: -4
40979b			08_Effect.MoveY = {40f350::random_number}
}

// Update the position.
// Slow down the Y velocity by 0.25 and add the X/Y velocity to the X/Y position.
4097a9		08_Effect.MoveY	= 08_Effect.MoveY	+ 0x40
4097bb		08_Effect.X	= 08_Effect.X		+ 08_Effect.MoveX
4097ca		08_Effect.Y	= 08_Effect.Y		+ 08_Effect.MoveY

// Update the frame to display.
// Frame delay: 5. Num frames: 3. Disabled after final frame.
4097dc		08_Effect.FrameTimer++
4097eb		if(08_Effect.FrameTimer > FRAME_DELAY)
{
4097f4			08_Effect.FrameTimer = 0
4097fe			08_Effect.FrameID++
40980d			if(08_Effect.FrameID > NUM_FRAMES)
409816				08_Effect.InUse	= 0
}

// Prepare the effect for rendering based on its mode.
// Setting the mode to a non-zero value makes it use the second set of frames.
40981f		if(08_Effect.Mode == 0)
409828			08_Effect->SetRect[08_Effect.FrameID - 0x0040]
409851		else
409853			08_Effect->SetRect[08_Effect.FrameID - 0x0080]

// Exit.
40987c		return
}

Here's one of the effects, to serve as an example of how things work. This is called every frame, btw.
 
Jul 6, 2008 at 11:44 PM
Hoxtilicious
"Life begins and ends with Nu."
Join Date: Dec 30, 2005
Location: Germany
Posts: 3218
Age: 32
Very nice that you acutally post that :eek:
After the NPC's I will look at either that or the weapons, but it will take some time I guess.

b.t.w. I posted the list in the Offsets thread already, but yours seems to have more details :D May I update mine with your information?
 
Jul 7, 2008 at 12:01 AM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 39
S. P. Gardebiter said:
May I update mine with your information?
Do as you wish; wether it's here or in another thread, the information is just as accessible to forum members. :eek: Either way, assuming that information comes from the notes I sent you a while back, you'd have the same thing I posted already.

I think it'd be good if we kept effect-related posts in this thread, though, so it could be like one big effect-hacking FAQ. :D
 
Jul 7, 2008 at 1:30 PM
Hoxtilicious
"Life begins and ends with Nu."
Join Date: Dec 30, 2005
Location: Germany
Posts: 3218
Age: 32
Yeah.

But that information didn't come from the notes :rolleyes:
I tested it myself, acutally.

~ Sticky ~
 
May 15, 2009 at 2:54 PM
Junior Member
"Wow! The more I drink of this magical beverage, the more games I can play! Wheee!"
Join Date: Jul 8, 2008
Location:
Posts: 22
o.o Nice post, I'll check this out later my self.
 
Top