- Joined
- May 15, 2015
- Messages
- 423
This light-weight module lets you easily hide JObjs (Joint Objects) and PObjs (Polygon Objects) in a way that can be toggled on or off without destroying information. These edits can be done either from codes that access these objects, or from edits to the file structures that the objects are defined in. GObj GX Callback events have also been modified to be toggleable, allowing the drawing of any GObj to become optional.
Together these extra GObj, JObj, and PObj Hide flags afford varying degrees of specificity for toggling the visibility of model assets in Melee in a way that is universal, non-destructive, and easy to invoke without requiring any kind of external functions -- just 3 lines of code that directly modify the object structures. (Hiding these assets in the game is possible by conventional means -- but every method of doing so is destructive, and can’t be undone without first making some kind of copy of the destroyed information.)
Any other code may make use of this module after it has been installed, regardless of the installation method used:
HSD_Hide Module:
You may include the module with your own codes to automatically install the module if it is missing from an MCM Mods Library.
To access the installed flags, use the following mask interfaces with their corresponding objects:
Below is a brief tutorial demonstrating how to use each flag type, with standalone code examples that you can install through MCM.
---
The Draw_GObj sign bit:
GObjs are like general-purpose objects that can be fashioned into things like model skeletons for drawing and updating each frame. They are used to streamline the process of instantiating parts of the game that vary between things as different as menu items, player characters, or cameras inside of a scene. The GX Callback of a GObj is used to streamline the process of drawing most models in Melee through the use of HSD Object assets that can be attached to it.
GObjs are organized into meaningful groups that can be navigated from the p_link and gx_link arrays available at r13 offsets -0x3E74 and -0x3E7C, respectively. These arrays create 64 slots for pointers to be indexed at the start of scenes for the purpose of starting different lists of GObjs. The function of each slot varies depending on the scene.
These p_link and gx_link arrays are globally accessible, meaning that you can easily access them at any point in the game code.
For example, using:
Every GObj has a variable at offset 0x1C in its structure that points to a GX callback function. This basically tells the game what function to use in order to draw this GObj to the camera that’s in charge of its gx_link group. GObjs that are grouped together in the same gx_link are usually related to the same drawing process.
Not all GObjs have one of these GX Callback functions, so the pointer is blank (0) if there is none.
To Hide GObjs, this code simply lets you use a positive number (>0) to mimic the logic of using one of these blank pointer values -- allowing you to toggle the sign bit from the address in order to turn off the display of a GObj. Toggling the sign bit back on will restore the preserved pointer address, re-enabling the drawing function. This may be used like an inverted “Hide” flag. A “Show” flag; or a “Draw_GObj” flag.
It’s worth noting that this is very similar to the code in this thread, but has an additional safeguard to prevent attempting to execute re-enabled null pointers.
Pokemon Stadium - Remove Entire Background
An example of hiding GObjs
With this module, you can hide any GObj like so:
---
The Hide_JObj Flag:
JObjs are like puppet joints that store information about the size, position, rotation, and other things that a collection of Polygon objects can be transformed by. JObjs link together to make trees that can be used to represent skeletons. Each JObj has a set of flags that can be used to control various statuses. Included in this set of default flags is a bit called
To prevent this destruction of information, an unused bit in the field (08000000) has been assigned in this code to create a sort of subtle doppelganger for the vanilla
By loading the flags from offset 0x14 of any JObj, you can OR in this extra Hide_JObj flag to update it with a hide effect that will not be overwritten by other processes in the game. You may also AND it out of the mask to disable the effect:
Pokemon Stadium - Remove Background Screen
An example of hiding JObjs
With the HSD_Hide module, you can hide any JObj like so:
---
The Hide_PObj Flag:
PObjs are Polygon objects. They hold a list of vertices, with other information describing the geometry of a model.
PObjs have a pair of flags that let you control whether or not to “cull” the drawing of geometry belonging to front or back faces -- preventing those faces from being drawn. If both flags are set to true, then the whole model is culled -- effectively hiding it -- however there is no way to recover the lost culling flags when doing this.
To prevent this destruction of information, this code uses the unused bit (08000000 -- same as the JObj) to create a Hide_PObj flag that invokes 2-sided culling behavior without using the culling flags.
You can load the PObj flags from offset 0xC of any PObj, and OR in this flag to hide it. You may also AND it out of the mask to disable the effect:
Pokemon Stadium - No Grain effect in Background Screen
An example of hiding PObjs
Pokemon Stadium - Remove Sides of Background Screen
An example of hiding PObjs
With the HSD_Hide module, you can hide any PObj like so:
Together these extra GObj, JObj, and PObj Hide flags afford varying degrees of specificity for toggling the visibility of model assets in Melee in a way that is universal, non-destructive, and easy to invoke without requiring any kind of external functions -- just 3 lines of code that directly modify the object structures. (Hiding these assets in the game is possible by conventional means -- but every method of doing so is destructive, and can’t be undone without first making some kind of copy of the destroyed information.)
Any other code may make use of this module after it has been installed, regardless of the installation method used:
HSD_Hide Module:
-==-
HSD_Hide module
Enables easy control over how model assets are hidden through the following extensions:
0x1C of GObj: GX Callback (sign logic)
# +80000000 = bit 0: pretend sign is a bool -- "Draw_GObj"
0x14 of JObj: flags field
0x04 of JObjDesc: flag field
# +08000000 = bit 4: "Hide_JObj" (without interfering with JObj_Hide logic)
0x0C of PObj: flags field
0x0C of PObjDesc: flags field
# +08000000 = bit 4: "Hide_PObj" (forces geometry culling)
[Punkline]
NTSC 1.02 ----- 8036e8d8 --- a0e3000c -> Branch
A0E3000C 70E00800 41A20008 60E7C000 00000000
--------------- 8037449c --- 80630014 -> Branch
80630014 74600800 41A20008 60630010 00000000
--------------- 80390ff8 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
--------------- 80390f38 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
HSD_Hide module
Enables easy control over how model assets are hidden through the following extensions:
0x1C of GObj: GX Callback (sign logic)
# +80000000 = bit 0: pretend sign is a bool -- "Draw_GObj"
0x14 of JObj: flags field
0x04 of JObjDesc: flag field
# +08000000 = bit 4: "Hide_JObj" (without interfering with JObj_Hide logic)
0x0C of PObj: flags field
0x0C of PObjDesc: flags field
# +08000000 = bit 4: "Hide_PObj" (forces geometry culling)
[Punkline]
NTSC 1.02 ----- 8036e8d8 --- a0e3000c -> Branch
A0E3000C 70E00800 41A20008 60E7C000 00000000
--------------- 8037449c --- 80630014 -> Branch
80630014 74600800 41A20008 60630010 00000000
--------------- 80390ff8 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
--------------- 80390f38 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
Rich (BB code):
-==-
!
ASM - HSD_Hide module
Enables easy control over how model assets are hidden through the following extensions:
0x1C of GObj: GX Callback (sign logic)
# +80000000 = bit 0: pretend sign is a bool -- "Draw_GObj"
0x14 of JObj: flags field
0x04 of JObjDesc: flag field
# +08000000 = bit 4: "Hide_JObj" (without interfering with JObj_Hide logic)
0x0C of PObj: flags field
0x0C of PObjDesc: flags field
# +08000000 = bit 4: "Hide_PObj" (forces geometry culling)
[Punkline]
NTSC 1.02 ----- 8036e8d8 --- a0e3000c -> Branch
# --- PObjs
lhz r7, 0xC(r3)
andi. r0, r7, 0x0800
beq+ _return
ori r7, r7, 0xC000
_return:
.long 0
--------------- 8037449c --- 80630014 -> Branch
# --- JObjs
lwz r3, 0x14(r3)
andis. r0, r3, 0x0800
beq+ _return
ori r3, r3, 0x10
_return:
.long 0
--------------- 80390ff8 --- 28000000 -> Branch
# --- GObjs
cmpwi cr1, r0, 0; cr1.lt=4; eq=2
rlwinm. r15, r0, 0, ~(1<<31)
crorc eq, eq, cr1.lt
.long 0
--------------- 80390f38 --- 28000000 -> Branch
cmpwi cr1, r0, 0; cr1.lt=4; eq=2
rlwinm. r15, r0, 0, ~(1<<31)
crorc eq, eq, cr1.lt
.long 0
Code:
$HSD_Hide module [Punkline]
C236E8D8 00000003
A0E3000C 70E00800
41A20008 60E7C000
60000000 00000000
C237449C 00000003
80630014 74600800
41A20008 60630010
60000000 00000000
C2390FF8 00000002
2C800000 540F007F
4C422342 00000000
C2390F38 00000002
2C800000 540F007F
4C422342 00000000
You may include the module with your own codes to automatically install the module if it is missing from an MCM Mods Library.
To access the installed flags, use the following mask interfaces with their corresponding objects:
Rich (BB code):
0x1C of GObj: GX Callback (sign logic)
# +80000000 = bit 0: pretend sign is a bool -- "Draw_GObj"
0x14 of JObj: flags field
0x04 of JObjDesc: flag field
# +08000000 = bit 4: "Hide_JObj" (without interfering with JObj_Hide logic)
0x0C of PObj: flags field
0x0C of PObjDesc: flags field
# +08000000 = bit 4: "Hide_PObj" (forces geometry culling)
Below is a brief tutorial demonstrating how to use each flag type, with standalone code examples that you can install through MCM.
---
The Draw_GObj sign bit:
GObjs are like general-purpose objects that can be fashioned into things like model skeletons for drawing and updating each frame. They are used to streamline the process of instantiating parts of the game that vary between things as different as menu items, player characters, or cameras inside of a scene. The GX Callback of a GObj is used to streamline the process of drawing most models in Melee through the use of HSD Object assets that can be attached to it.
GObjs are organized into meaningful groups that can be navigated from the p_link and gx_link arrays available at r13 offsets -0x3E74 and -0x3E7C, respectively. These arrays create 64 slots for pointers to be indexed at the start of scenes for the purpose of starting different lists of GObjs. The function of each slot varies depending on the scene.
These p_link and gx_link arrays are globally accessible, meaning that you can easily access them at any point in the game code.
For example, using:
lwz r3, -0x3E74(r13); lwz rGObj, 0x14(r3)
will let you access the list of stage assets used by any stage from any code that executes in the Melee VS scene.Every GObj has a variable at offset 0x1C in its structure that points to a GX callback function. This basically tells the game what function to use in order to draw this GObj to the camera that’s in charge of its gx_link group. GObjs that are grouped together in the same gx_link are usually related to the same drawing process.
Not all GObjs have one of these GX Callback functions, so the pointer is blank (0) if there is none.
To Hide GObjs, this code simply lets you use a positive number (>0) to mimic the logic of using one of these blank pointer values -- allowing you to toggle the sign bit from the address in order to turn off the display of a GObj. Toggling the sign bit back on will restore the preserved pointer address, re-enabling the drawing function. This may be used like an inverted “Hide” flag. A “Show” flag; or a “Draw_GObj” flag.
It’s worth noting that this is very similar to the code in this thread, but has an additional safeguard to prevent attempting to execute re-enabled null pointers.
Pokemon Stadium - Remove Entire Background
An example of hiding GObjs
Rich (BB code):
-==-
Pokemon Stadium - Remove Entire Background
Example of the "Draw GObj" flag. Requires HSD_Hide module.
[Punkline]
NTSC 1.02 ----- 801d10b8 --- 8001000c -> Branch
# --- Symbols -- x- indeX r- Register m- Mask
r13.xPLink=-0x3E74; PLink.xStage=5<<2
GObj.xNext=0x8; GObj.xGX=0x1C;
mDraw_GObj=1<<31
rGObj=3;
# --- Find GObj:
lwz rGObj, r13.xPLink(r13)
# r13 can be used like this anywhere in the game code to reach the PLink table
lwz rGObj, PLink.xStage(rGObj)
# PLink 5 is used by Melee stages to group stage assets into a linked list
lwz rGObj, GObj.xNext(rGObj)
# The second GObj in the stage assets list has the pokemon stadium background assets
# --- Hide GObj:
lwz r0, GObj.xGX(rGObj)
rlwinm r0, r0, 0, ~mDraw_GObj # ~ prefix inverts the mask
stw r0, GObj.xGX(rGObj)
# mask out sign bit and update GX pointer to disable GX drawing
_return:
lwz r0, 0xC(sp)
.long 0
NTSC 1.02 ----- 8036e8d8 --- a0e3000c -> Branch
A0E3000C 70E00800 41A20008 60E7C000 00000000
--------------- 8037449c --- 80630014 -> Branch
80630014 74600800 41A20008 60630010 00000000
--------------- 80390ff8 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
--------------- 80390f38 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
With this module, you can hide any GObj like so:
Rich (BB code):
GObj.xGX=0x1C; mDraw_GObj=1<<31
lwz r0, GObj.xGX(rGObj)
rlwinm r0, r0, 0, ~mDraw_GObj # ~ prefix inverts the mask
stw r0, GObj.xGX(rGObj)
# mask out sign bit and update GX pointer to disable GX drawing
The Hide_JObj Flag:
JObjs are like puppet joints that store information about the size, position, rotation, and other things that a collection of Polygon objects can be transformed by. JObjs link together to make trees that can be used to represent skeletons. Each JObj has a set of flags that can be used to control various statuses. Included in this set of default flags is a bit called
JOBJ_HIDDEN
-- however the game uses this to drive the logic of certain processes in many implementations, so interfering with it can sometimes create unwanted changes in behavior.To prevent this destruction of information, an unused bit in the field (08000000) has been assigned in this code to create a sort of subtle doppelganger for the vanilla
JObj_HIDDEN
flag, extending the logic of the check normally made right before drawing from a list of DObjs. This extra check is made at no other place in the game, so the modification only applies to the moment DObjs are parsed for drawing. In other words, it cannot interfere with the normal hide logic, and will not be broken by vanilla mechanics in the game.By loading the flags from offset 0x14 of any JObj, you can OR in this extra Hide_JObj flag to update it with a hide effect that will not be overwritten by other processes in the game. You may also AND it out of the mask to disable the effect:
Pokemon Stadium - Remove Background Screen
An example of hiding JObjs
Rich (BB code):
-==-
Pokemon Stadium - Remove Background Screen
Example of the "Hide JObj" flag.
[Punkline]
NTSC 1.02 ----- 801d10b8 --- 8001000c -> Branch
# --- Symbols:
r13.xPLink=-0x3E74; PLink.xStage=5<<2
GObj.xNext=0x8; GObj.xGX=0x1C; GObj.xObj=0x28;
JObj.xChild=0x10; JObj.xNext=0x8; JObj.xFlags=0x14
mDraw_GObj=1<<31; mHide_JObj=1<<27
rGObj=3; rJObj=4
# --- Find GObj:
lwz rGObj, r13.xPLink(r13)
lwz rGObj, PLink.xStage(rGObj)
lwz rGObj, GObj.xNext(rGObj)
# rGObj = object containing joints we want to hide, and joints we want to keep visible
# --- Find JObjs:
lwz rJObj, GObj.xObj(rGObj)
# load root JObj from GObj
.rept 2; lwz rJObj, JObj.xChild(rJObj); .endr
# load last child JObj from root
# rJObj = first of 10 visible Screen JObj siblings
# --- Hide JObjs:
li r0, 9; mtctr r0
_for_8_JObjs:
lwz r0, JObj.xFlags(rJObj)
oris r0, r0, mHide_JObj@h # use @h to select only high 16-bits for oris instruction
stw r0, JObj.xFlags(rJObj)
lwz rJObj, JObj.xNext(rJObj)
bdnz+ _for_8_JObjs
# OR in flags and update 8 JObjs
# Leave the last 2 visible so there's something in the background
_return:
lwz r0, 0xC(sp)
.long 0
NTSC 1.02 ----- 8036e8d8 --- a0e3000c -> Branch
A0E3000C 70E00800 41A20008 60E7C000 00000000
--------------- 8037449c --- 80630014 -> Branch
80630014 74600800 41A20008 60630010 00000000
--------------- 80390ff8 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
--------------- 80390f38 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
With the HSD_Hide module, you can hide any JObj like so:
Rich (BB code):
JObj.xFlags=0x14; mHide_JObj=1<<27
lwz r0, JObj.xFlags(rJObj)
oris r0, r0, mHide_JObj@h # use @h to select only high 16-bits for oris instruction
stw r0, JObj.xFlags(rJObj)
# OR in the Hide_JObj flag
The Hide_PObj Flag:
PObjs are Polygon objects. They hold a list of vertices, with other information describing the geometry of a model.
PObjs have a pair of flags that let you control whether or not to “cull” the drawing of geometry belonging to front or back faces -- preventing those faces from being drawn. If both flags are set to true, then the whole model is culled -- effectively hiding it -- however there is no way to recover the lost culling flags when doing this.
To prevent this destruction of information, this code uses the unused bit (08000000 -- same as the JObj) to create a Hide_PObj flag that invokes 2-sided culling behavior without using the culling flags.
You can load the PObj flags from offset 0xC of any PObj, and OR in this flag to hide it. You may also AND it out of the mask to disable the effect:
Pokemon Stadium - No Grain effect in Background Screen
An example of hiding PObjs
Rich (BB code):
Pokemon Stadium - No Grain effect in Background Screen
Example of the "Hide PObj" flag.
[Punkline]
NTSC 1.02 ----- 801d10b8 --- 8001000c -> Branch
# --- Symbols:
r13.xPLink=-0x3E74; PLink.xStage=5<<2
GObj.xNext=0x8; GObj.xGX=0x1C; GObj.xObj=0x28;
JObj.xChild=0x10; JObj.xNext=0x8; JObj.xFlags=0x14; JObj.xDObj=0x18;
DObj.xNext=0x4; DObj.xPObj=0xC; PObj.xFlags=0xC
mDraw_GObj=1<<31; mHide_JObj=1<<27; mHide_PObj=1<<27
rGObj=3; rJObj=4; rDObj=5; rPObj=6
# --- Find GObj:
lwz rGObj, r13.xPLink(r13)
lwz rGObj, PLink.xStage(rGObj)
lwz rGObj, GObj.xNext(rGObj)
# rGObj = object screen overlay model
# --- Find JObj:
lwz rJObj, GObj.xObj(rGObj);
.rept 2; lwz rJObj, JObj.xChild(rJObj); .endr
# rJObj = Screen frame/overlay
# --- Find PObj:
lwz rDObj, JObj.xDObj(rJObj)
# load root DObj in list of display objects for this joint
lwz rDObj, DObj.xNext(rDObj)
# load second DObj to select the overlay that causes grain, and the grid pattern
lwz rPObj, DObj.xPObj(rDObj)
# rPObj= polygon mesh used for this display object.
# --- Hide PObj:
lwz r0, PObj.xFlags(rPObj)
oris r0, r0, mHide_PObj@h
stw r0, PObj.xFlags(rPObj)
# update flags with the Hide_PObj flag
_return:
lwz r0, 0xC(sp)
.long 0
NTSC 1.02 ----- 8036e8d8 --- a0e3000c -> Branch
A0E3000C 70E00800 41A20008 60E7C000 00000000
--------------- 8037449c --- 80630014 -> Branch
80630014 74600800 41A20008 60630010 00000000
--------------- 80390ff8 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
--------------- 80390f38 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
Pokemon Stadium - Remove Sides of Background Screen
An example of hiding PObjs
Rich (BB code):
-==-
Pokemon Stadium - Remove Sides of Background Screen
Example of the "Hide PObj" flag.
[Punkline]
NTSC 1.02 ----- 801d10b8 --- 8001000c -> Branch
# --- Symbols:
r13.xPLink=-0x3E74; PLink.xStage=5<<2
GObj.xNext=0x8; GObj.xGX=0x1C; GObj.xObj=0x28;
JObj.xChild=0x10; JObj.xNext=0x8; JObj.xFlags=0x14; JObj.xDObj=0x18;
DObj.xNext=0x4; DObj.xPObj=0xC; PObj.xFlags=0xC
mDraw_GObj=1<<31; mHide_JObj=1<<27; mHide_PObj=1<<27
rGObj=3; rJObj=4; rDObj=5; rPObj=6
# --- Find GObj:
lwz rGObj, r13.xPLink(r13)
lwz rGObj, PLink.xStage(rGObj)
lwz rGObj, GObj.xNext(rGObj)
# rGObj = object screen overlay model
# --- Find JObj:
lwz rJObj, GObj.xObj(rGObj);
.rept 2; lwz rJObj, JObj.xChild(rJObj); .endr
# rJObj = Screen frame/overlay
# --- Find PObjs:
lwz rDObj, JObj.xDObj(rJObj)
i=-1
.rept 5; i=i+1
.if i; lwz rDObj, DObj.xNext(rDObj)
.else; lwz rDObj, JObj.xDObj(rJObj)
.endif # load root DObj first, then load siblings for each after
.if i>2 # for last 2 DObjs in siblings list...
# --- Hide PObjs:
lwz rPObj, DObj.xPObj(rDObj)
lwz r0, PObj.xFlags(rPObj)
oris r0, r0, mHide_PObj@h
stw r0, PObj.xFlags(rPObj)
# Hide side-bar things in the Screen frame
.endif
.endr
_return:
lwz r0, 0xC(sp)
.long 0
NTSC 1.02 ----- 8036e8d8 --- a0e3000c -> Branch
A0E3000C 70E00800 41A20008 60E7C000 00000000
--------------- 8037449c --- 80630014 -> Branch
80630014 74600800 41A20008 60630010 00000000
--------------- 80390ff8 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
--------------- 80390f38 --- 28000000 -> Branch
2C800000 540F007F 4C422342 00000000
With the HSD_Hide module, you can hide any PObj like so:
Rich (BB code):
PObj.xFlags=0xC; mHide_PObj=1<<27
lwz r0, PObj.xFlags(rPObj)
oris r0, r0, mHide_PObj@h
stw r0, PObj.xFlags(rPObj)
# Hide PObj
Last edited: