Culling in GameCube and Wii Games (@Ralf)
Moderator: Ralf@gc-forever
Culling in GameCube and Wii Games (@Ralf)
Hey, I'm one of the developers of Dolphin VR. We've been working on a version of the emulator that lets you play gamecube/wii games in the Oculus Rift. Many games are working really well now, but one of the biggest problems we have is culling. I've been looking into whether game hacking can possibly fix this issue on a game-per-game basis.
I was looking at some of the codes here, and it looks like most games have a place in RAM they store a 32-bit single precision floating point value that relates to the aspect ratio (1.3333 usually). You replace this with 1.77777 and you have a 16:9 hack. I've tried these, because I thought they might effect culling, but it doesn't look that way.
I also noticed this thread: viewtopic.php?f=16&t=2597&start=12
It looks like you were changing the culling factor for MKDD. I tried playing with the AR code myself, but I actually didn't see any difference in culling with and without it. I tried setting it to 0 as well, and everything was still working. The 16:9 code worked fine though.
I guess my question is, do you think this is possible? How are the codes stored? Is it a value in radians or something else? Have you ever tried to completely disable culling in a game before? I was hoping changing a value to 6.28 (360 degrees in radians) might give 360 degree visibility, but no luck.
Any advice you could give would be greatly appreciated!
I was looking at some of the codes here, and it looks like most games have a place in RAM they store a 32-bit single precision floating point value that relates to the aspect ratio (1.3333 usually). You replace this with 1.77777 and you have a 16:9 hack. I've tried these, because I thought they might effect culling, but it doesn't look that way.
I also noticed this thread: viewtopic.php?f=16&t=2597&start=12
It looks like you were changing the culling factor for MKDD. I tried playing with the AR code myself, but I actually didn't see any difference in culling with and without it. I tried setting it to 0 as well, and everything was still working. The 16:9 code worked fine though.
I guess my question is, do you think this is possible? How are the codes stored? Is it a value in radians or something else? Have you ever tried to completely disable culling in a game before? I was hoping changing a value to 6.28 (360 degrees in radians) might give 360 degree visibility, but no luck.
Any advice you could give would be greatly appreciated!
- CosmoCortney
- Posts: 90
- Joined: Sun Nov 11, 2012 9:09 pm
- Location: under your bed
- Contact:
Re: Culling in GameCube and Wii Games (@Ralf)
What exactly do you mean with "culling"? The objects disappearing outside of the 4/3 area?
I have once found an address for wind waker that modified the render radius of the objects. it solved the problem for that game. but I don't remember it and found it by destiny (messing around with many floats).
if I remember correctly it had a value of 0x3DCCCCCC..
I have once found an address for wind waker that modified the render radius of the objects. it solved the problem for that game. but I don't remember it and found it by destiny (messing around with many floats).
if I remember correctly it had a value of 0x3DCCCCCC..
Also known as Lawn Meower
-
- Posts: 3832
- Joined: Sun Mar 16, 2014 9:31 am
Re: Culling in GameCube and Wii Games (@Ralf)
AFAIK, it's possible to enable/disable culling using the following GameCube SDK function:
void GXSetCullMode(GXCullMode mode)
GXCullModes
GX_CULL_NONE 0
GX_CULL_FRONT 1
GX_CULL_BACK 2
GX_CULL_ALL 3
I don't know how many different versions of this function exists, but it should be relatively easy to find this function for a specific game in memory and patch it. Here are two examples:
MKDD NTSC-U
GXSetCullMode function [GX release build: Jul 23 2003 11:27:39]
r3: GXCullMode
AR/Gecko code
Disable Culling
040BE0E8 4800001C
040BE104 38600000
LoZ Wind Waker NTSC-U
GXSetCullMode function [GX release build: Sep 5 2002 05:33:28]
Disable Culling
0432332C 4800001C
04323348 38600000
More info about culling can be found in the 5-Viewing.us.PDF document (Chapter 1.3 Culling, clipping, and scissoring) of the Nintendo GameCube SDK:
NINTENDO Gamecube PC Dolphin Emulator e2.8/docs/Developer/PDF/SDK1.0/Graphics Programmer's Guide/GX/5-Viewing.us.PDF
void GXSetCullMode(GXCullMode mode)
GXCullModes
GX_CULL_NONE 0
GX_CULL_FRONT 1
GX_CULL_BACK 2
GX_CULL_ALL 3
I don't know how many different versions of this function exists, but it should be relatively easy to find this function for a specific game in memory and patch it. Here are two examples:
MKDD NTSC-U
GXSetCullMode function [GX release build: Jul 23 2003 11:27:39]
r3: GXCullMode
Code: Select all
800BE0E4: 2C030002 cmpwi r3,2
800BE0E8: 4182001C beq- 0x800be104
800BE0EC: 4080001C bge- 0x800be108
800BE0F0: 2C030001 cmpwi r3,1
800BE0F4: 40800008 bge- 0x800be0fc
800BE0F8: 48000010 b 0x800be108
800BE0FC: 38600002 li r3,2
800BE100: 48000008 b 0x800be108
800BE104: 38600001 li r3,1
800BE108: 80828C08 lwz r4,-29688(r2)
800BE10C: 80040204 lwz r0,516(r4)
800BE110: 50607422 rlwimi r0,r3,14,16,17
800BE114: 90040204 stw r0,516(r4)
800BE118: 800405AC lwz r0,1452(r4)
800BE11C: 60000004 ori r0,r0,4
800BE120: 900405AC stw r0,1452(r4)
800BE124: 4E800020 blr
Disable Culling
040BE0E8 4800001C
040BE104 38600000
LoZ Wind Waker NTSC-U
GXSetCullMode function [GX release build: Sep 5 2002 05:33:28]
Code: Select all
80323328: 2C030002 cmpwi r3,2
8032332C: 4182001C beq- 0x80323348
80323330: 4080001C bge- 0x8032334c
80323334: 2C030001 cmpwi r3,1
80323338: 40800008 bge- 0x80323340
8032333C: 48000010 b 0x8032334c
80323340: 38600002 li r3,2
80323344: 48000008 b 0x8032334c
80323348: 38600001 li r3,1
8032334C: 8082CDD0 lwz r4,-12848(r2)
80323350: 54607022 rlwinm r0,r3,14,0,17
80323354: 80640204 lwz r3,516(r4)
80323358: 5463049E rlwinm r3,r3,0,18,15
8032335C: 7C600378 or r0,r3,r0
80323360: 90040204 stw r0,516(r4)
80323364: 800404F4 lwz r0,1268(r4)
80323368: 60000004 ori r0,r0,4
8032336C: 900404F4 stw r0,1268(r4)
80323370: 4E800020 blr
0432332C 4800001C
04323348 38600000
More info about culling can be found in the 5-Viewing.us.PDF document (Chapter 1.3 Culling, clipping, and scissoring) of the Nintendo GameCube SDK:
NINTENDO Gamecube PC Dolphin Emulator e2.8/docs/Developer/PDF/SDK1.0/Graphics Programmer's Guide/GX/5-Viewing.us.PDF
Re: Culling in GameCube and Wii Games (@Ralf)
Unrelated.Ralf@gc-forever wrote:AFAIK, it's possible to enable/disable culling using the following GameCube SDK function:
void GXSetCullMode(GXCullMode mode)
For first-party games, you're looking for J3DUClipper.
Some of these games come with a symbol map, how convenient!
Re: Culling in GameCube and Wii Games (@Ralf)
Hi Everyone,
Thanks so much for the help so far! Looking at the GX_CULL_NONE/BACK/FRONT/ALL, we have this done already in Dolphin VR. Basically all of those calls are being set to GX_CULL_NONE. We're still getting the object culling though. I tested some the MKDD code, but nothing changed, which I guess is expected considering we already are doing this in the emulator. Thanks for pointing out that SDK documentation! I didn't know that existed before. Very interesting resource.
Here's an example of what I mean by culling. Right now, when you play Mario Kart, you can look around at the track, the scenery, and everything looks great. The problem is, when another player gets behind you, and you look over your shoulder backwards, they are gone. The track and everything is there, but the player is not.
In something like Paper Mario: The Thousand Year door, this manifests itself as pop-in on many objects. As you get closer to bushes, enemies, etc they pop in. The actual level is fully rendered though.
So, J3DUClipper controls the remaining culling? Do you have any other examples/documentation/codes or have time to write up a quick guide on how to find them? I haven't done any game hacking before, but I'll definitely learn if that's what's needed...
Thanks so much for the help so far! Looking at the GX_CULL_NONE/BACK/FRONT/ALL, we have this done already in Dolphin VR. Basically all of those calls are being set to GX_CULL_NONE. We're still getting the object culling though. I tested some the MKDD code, but nothing changed, which I guess is expected considering we already are doing this in the emulator. Thanks for pointing out that SDK documentation! I didn't know that existed before. Very interesting resource.
Here's an example of what I mean by culling. Right now, when you play Mario Kart, you can look around at the track, the scenery, and everything looks great. The problem is, when another player gets behind you, and you look over your shoulder backwards, they are gone. The track and everything is there, but the player is not.
In something like Paper Mario: The Thousand Year door, this manifests itself as pop-in on many objects. As you get closer to bushes, enemies, etc they pop in. The actual level is fully rendered though.
So, J3DUClipper controls the remaining culling? Do you have any other examples/documentation/codes or have time to write up a quick guide on how to find them? I haven't done any game hacking before, but I'll definitely learn if that's what's needed...
Re: Culling in GameCube and Wii Games (@Ralf)
J3DUClipper::calcViewFrustum (mangled as calcViewFrustum__11J3DUClipperFv) pops out due to its usage of tan.
tan can be found through C_MTXPerspective, which is reliably found by Dolphin's debugger.
Accurate symbol maps can be found in:
tan can be found through C_MTXPerspective, which is reliably found by Dolphin's debugger.
Accurate symbol maps can be found in:
- The Legend of Zelda: The Wind Waker (maps/framework.map)
- The Legend of Zelda: Twilight Princess (map/Final/Release/frameworkF.map)
Re: Culling in GameCube and Wii Games (@Ralf)
Okay, I figured out how to load up the Dolphin Debugger, open Wind Waker's framework.map and locate that section in the assembly. Unfortunately, it's huge, and I haven't ever looked at PPC ASM before, so I'm having problems figuring out how to modify it correctly.
I was playing around NOPing some of the functions and at some point got all the grass to stay, and at other points had things culling all over the place, so that was something at least. Here's a pic of ASM:
http://imgur.com/a/7DLQJ
If anyone has any words of wisdom, that'd be amazing. If not, I'm sure I'll figure it out eventually...
I was playing around NOPing some of the functions and at some point got all the grass to stay, and at other points had things culling all over the place, so that was something at least. Here's a pic of ASM:
http://imgur.com/a/7DLQJ
If anyone has any words of wisdom, that'd be amazing. If not, I'm sure I'll figure it out eventually...
-
- Posts: 3832
- Joined: Sun Mar 16, 2014 9:31 am
Re: Culling in GameCube and Wii Games (@Ralf)
Culling and clipping are two seperate things. However, almost all GameCube games have their own clipping functions, only a handful of Nintendo GC games make use of the J3DU library functions. Finding these game-specific clipping routines requires a lot of reverse engineering. Anyway, the aspect ratio and perspective functions (C_MTXPerspective/C_MTXLightPerspective) are a good starting point in most cases. Here're some examples:
LoZ Wind Waker
Patched function (found via aspect ratio): view_setup__FP20camera_process_class
NTSC-U
Clipping Factor Modifier
04004500 3C608000
04004504 C043450C
04004508 48177A84
0400450C xxxxxxxx
0417BF88 4BE88578
xxxxxxxx = Clipping Factor (Default: 0x3FA3D70A = 1.28)
PAL
Clipping Factor Modifier
04004500 3C608000
04004504 C043450C
04004508 4817B804
0400450C xxxxxxxx
0417FD08 4BE847F8
xxxxxxxx = Clipping Factor (Default: 0x3FA3D70A = 1.28)
LoZ Twilight Princess (found via aspect ratio): view_setup__FP20camera_process_class
NTSC-U
Clipping Factor Modifier
04004580 3C608000
04004584 C043458C
04004588 4817D25C
0400458C xxxxxxxx
041817E0 4BE82DA0
xxxxxxxx = Clipping Factor (Default: 0x3FADB6DB = 1.3571428)
PAL
Clipping Factor Modifier
04004580 3C608000
04004584 C043458C
04004588 4817D468
0400458C xxxxxxxx
041819EC 4BE82B94
xxxxxxxx = Clipping Factor (Default: 0x3FADB6DB = 1.3571428)
MKDD
Patched function (J3DU library): calcViewFrustum__11J3DUClipperFv
NTSC-U & PAL
Clipping Factor Modifier
04004580 3C608000
04004584 C0234590
04004588 D03A0050
0400458C 48005D14
04004590 xxxxxxxx
0400A29C 4BFFA2E4
xxxxxxxx = Clipping Factor (Default: 0x3FADB6DB = 1.3571428)
Wave Race
PAL
Clipping Factor Modifier
04696434 xxxxxxxx
xxxxxxxx = Clipping Factor (Default: 0x3FAAAA8F = 1.333333)
LoZ Wind Waker
Patched function (found via aspect ratio): view_setup__FP20camera_process_class
NTSC-U
Clipping Factor Modifier
04004500 3C608000
04004504 C043450C
04004508 48177A84
0400450C xxxxxxxx
0417BF88 4BE88578
xxxxxxxx = Clipping Factor (Default: 0x3FA3D70A = 1.28)
PAL
Clipping Factor Modifier
04004500 3C608000
04004504 C043450C
04004508 4817B804
0400450C xxxxxxxx
0417FD08 4BE847F8
xxxxxxxx = Clipping Factor (Default: 0x3FA3D70A = 1.28)
LoZ Twilight Princess (found via aspect ratio): view_setup__FP20camera_process_class
NTSC-U
Clipping Factor Modifier
04004580 3C608000
04004584 C043458C
04004588 4817D25C
0400458C xxxxxxxx
041817E0 4BE82DA0
xxxxxxxx = Clipping Factor (Default: 0x3FADB6DB = 1.3571428)
PAL
Clipping Factor Modifier
04004580 3C608000
04004584 C043458C
04004588 4817D468
0400458C xxxxxxxx
041819EC 4BE82B94
xxxxxxxx = Clipping Factor (Default: 0x3FADB6DB = 1.3571428)
MKDD
Patched function (J3DU library): calcViewFrustum__11J3DUClipperFv
NTSC-U & PAL
Clipping Factor Modifier
04004580 3C608000
04004584 C0234590
04004588 D03A0050
0400458C 48005D14
04004590 xxxxxxxx
0400A29C 4BFFA2E4
xxxxxxxx = Clipping Factor (Default: 0x3FADB6DB = 1.3571428)
Wave Race
PAL
Clipping Factor Modifier
04696434 xxxxxxxx
xxxxxxxx = Clipping Factor (Default: 0x3FAAAA8F = 1.333333)
Re: Culling in GameCube and Wii Games (@Ralf)
Wow, awesome! Very nice work. I've been playing around with the one for Wind Waker, and it's definitely a step in the right direction. I tried a a factor of 0, 1.28, 3, 6.28, 10, 100, 255, 10000, and 100000 and it gets better up to around 10,000 but then seems to stop. Clipping is majorly reduced from side-to-side, and is reduced a bit backwards. It's a large improvement, but clipping behind the camera is still happening pretty significantly.
It's almost like I want to disable the function from being called or have it always return don't clip. I'm not sure what the function returns. Is it something like a bool, where an object calls the function and the clipping returns true or false, or is it more complicated than that? Can I modify the end of the function and force it to always return "Don't Clip?" Sorry, my assembly skills are terrible. I haven't used it at all since university...
It's almost like I want to disable the function from being called or have it always return don't clip. I'm not sure what the function returns. Is it something like a bool, where an object calls the function and the clipping returns true or false, or is it more complicated than that? Can I modify the end of the function and force it to always return "Don't Clip?" Sorry, my assembly skills are terrible. I haven't used it at all since university...
-
- Posts: 3832
- Joined: Sun Mar 16, 2014 9:31 am
Re: Culling in GameCube and Wii Games (@Ralf)
You can try to use the following codes to totally disable clipping in Wind Waker:
LoZ WW NTSC-U
Objects: clip__11J3DUClipperFPA4_Cf3Vecf
04256888 386000xx
0425688C 4E800020
Scenery: clip__11J3DUClipperFPA4_CfP3VecP3Vec
042569D0 386000xx
042569D4 4E800020
LoZ WW PAL
Objects: clip__11J3DUClipperFPA4_Cf3Vecf
0425BA28 386000xx
0425BA2C 4E800020
Scenery: clip__11J3DUClipperFPA4_CfP3VecP3Vec
0425BB70 386000xx
0425BB74 4E800020
xx = Clipping On/Off (01/00)
LoZ WW NTSC-U
Objects: clip__11J3DUClipperFPA4_Cf3Vecf
04256888 386000xx
0425688C 4E800020
Scenery: clip__11J3DUClipperFPA4_CfP3VecP3Vec
042569D0 386000xx
042569D4 4E800020
LoZ WW PAL
Objects: clip__11J3DUClipperFPA4_Cf3Vecf
0425BA28 386000xx
0425BA2C 4E800020
Scenery: clip__11J3DUClipperFPA4_CfP3VecP3Vec
0425BB70 386000xx
0425BB74 4E800020
xx = Clipping On/Off (01/00)
Re: Culling in GameCube and Wii Games (@Ralf)
Be warned you can run into hardware bugs if primitives behind the eyepoint aren't clipped before rendering (of course this won't happen with dolphin).
Re: Culling in GameCube and Wii Games (@Ralf)
Yes!! That's it! Wow, very impressive. It's working perfectly in Wind Waker now. You guys will be heros in the VR community, even with just the code for Wind Waker
. No more pop in while looking around in VR. So it seems like code like this is not very portable, and it would have to be figured out from scratch for each game?
I guess if I wanted to do the same for Paper Mario: The Thousand Year Door, I'd have to start from scratch. The whole process may be totally different. How did you find these functions? Look at the call stack and code in each function until it became clear? Is it possible without a full .map file, like found in Wind Waker and Twilight Princess?
I'm hoping I can eventually figure it out myself and not need to beg you guys to find them for me
. I'm starting to review my PPC ASM, and some it is starting to make more sense as I remember how it all works. This code also gives me a good starting point to try and figure out what you did, haha. Thanks so much for the help so far!
Edit: I see you went to the beginning of the two clipper functions and inserted a li to load 0 into r3, and then blr'd back, skipping the rest of the function. Very interesting!
Edit 2: I extracted the .map for MKDD and tried to mess with the clipping function in there. Skipping the clip_11J3DUClipperCFPA4_Cf3Vecf with:
0400776C 38600000
04007770 4E800020
wasn't successful. Looks like this really will require research to be done for every game
. Also, the games without .map files look very hard to figure out!

I guess if I wanted to do the same for Paper Mario: The Thousand Year Door, I'd have to start from scratch. The whole process may be totally different. How did you find these functions? Look at the call stack and code in each function until it became clear? Is it possible without a full .map file, like found in Wind Waker and Twilight Princess?
I'm hoping I can eventually figure it out myself and not need to beg you guys to find them for me

Right, that makes sense!tueidj wrote:Be warned you can run into hardware bugs if primitives behind the eyepoint aren't clipped before rendering (of course this won't happen with dolphin).
Edit: I see you went to the beginning of the two clipper functions and inserted a li to load 0 into r3, and then blr'd back, skipping the rest of the function. Very interesting!
Edit 2: I extracted the .map for MKDD and tried to mess with the clipping function in there. Skipping the clip_11J3DUClipperCFPA4_Cf3Vecf with:
0400776C 38600000
04007770 4E800020
wasn't successful. Looks like this really will require research to be done for every game

-
- Posts: 3832
- Joined: Sun Mar 16, 2014 9:31 am
Re: Culling in GameCube and Wii Games (@Ralf)
The Mario Kart .map file is for the debug version and not very useful. The code below should disable clipping in the retail version of the game.
MKDD NTSC-U & PAL
8000A3C8: clip__11J3DUClipperCFPA4_Cf3Vecf
Disable Clipping
0400A3C8 38600000
0400A3CC 4E800020
And since we're at it, here're the codes for Twilight Princess:
LoZ Twilight Princess NTSC-U
802738FC: clip__11J3DUClipperCFPA4_Cf3Vecf
80273A44: clip__11J3DUClipperCFPA4_CfP3VecP3Vec
Disable Clipping
042738FC 48000148
04273A44 38600000
04273A48 4E800020
LoZ Twilight Princess PAL
802746FC: clip__11J3DUClipperCFPA4_Cf3Vecf
80274844: clip__11J3DUClipperCFPA4_CfP3VecP3Vec
Disable Clipping
042746FC 48000148
04274844 38600000
04274848 4E800020
MKDD NTSC-U & PAL
8000A3C8: clip__11J3DUClipperCFPA4_Cf3Vecf
Disable Clipping
0400A3C8 38600000
0400A3CC 4E800020
And since we're at it, here're the codes for Twilight Princess:
LoZ Twilight Princess NTSC-U
802738FC: clip__11J3DUClipperCFPA4_Cf3Vecf
80273A44: clip__11J3DUClipperCFPA4_CfP3VecP3Vec
Disable Clipping
042738FC 48000148
04273A44 38600000
04273A48 4E800020
LoZ Twilight Princess PAL
802746FC: clip__11J3DUClipperCFPA4_Cf3Vecf
80274844: clip__11J3DUClipperCFPA4_CfP3VecP3Vec
Disable Clipping
042746FC 48000148
04274844 38600000
04274848 4E800020
Yep, each game is different and each development team implements things in a different way, so reverse engineering is your only option.cegli wrote:Looks like this really will require research to be done for every game. Also, the games without .map files look very hard to figure out!
Re: Culling in GameCube and Wii Games (@Ralf)
Thanks! Tried MKDD and it's working great! I see how the debug.map is actually wrong now. I tried quickly doing this in some more games that have .map files (Super Mario Sunshine, Animal Crossing, Zelda: OoT, etc) and of course there functions were totally different, and I couldn't figure them out at all... I hope to figure this out a bit better in the future when I have a bit more time to devote to learning game hacking...
Re: Culling in GameCube and Wii Games (@Ralf)
Hello
A little post to ask you what exactly is "culling" ?
I'm french ; I used google trad' but the french word it gave me doesn't mean anyting, i think it's a specific tech' word.
A little post to ask you what exactly is "culling" ?
I'm french ; I used google trad' but the french word it gave me doesn't mean anyting, i think it's a specific tech' word.
Re: Culling in GameCube and Wii Games (@Ralf)
MockyLock, culling = killing off/etc. It means when the camera is facing a certain direction, objects not in the viewport are usually killed off ("culled") from being displayed to ease up the GPU to process the current scene. With VR if you have headtracking, the entire scene needs to be rendered with zero culling since you might look in the direction behind where the character is facing.

Re: Culling in GameCube and Wii Games (@Ralf)
OK now i understand. Objets not in the picture are calculated but not displayed.
In french "gaming speaking", we use the english word "clipping" also, but it is used to describe some display artifact, when objects appear/disappear when they're still in the view window for exemple. Is it the meaning in this case too ?
In french "gaming speaking", we use the english word "clipping" also, but it is used to describe some display artifact, when objects appear/disappear when they're still in the view window for exemple. Is it the meaning in this case too ?
Re: Culling in GameCube and Wii Games (@Ralf)
Yep, clipping can also refer to when one object goes through another object. e.g. "Mario's arm clipped through the wall". In this case though, I'm trying to get every object to render, even if the in-game camera is not pointing at it.
Re: Culling in GameCube and Wii Games (@Ralf)
Culling normally refers to when primitives are discarded because they're completely obscured i.e. facing away from the viewer (the backside of an object) or behind something in the foreground. Clipping normally refers to primitives that are discarded because they're completely outside the field of view (also known as hard clipping) or only partially rendered because some of their vertices are outside the field of view (also known as soft clipping).
Re: Culling in GameCube and Wii Games (@Ralf)
Hello folks,
maybe someone could help me with a specific game:
RESIDENT EVIL-CODE:Veronica-X (pal)
I need to completely turn off the clipping of objects (performance doesnt really matter)
I already tried to change the value of a existing widescreen patch, but had no sucess.
Also I wasnt able to find the (any) function in the debugger of dolphin, because I´m not a coder.
thx in advance
maybe someone could help me with a specific game:
RESIDENT EVIL-CODE:Veronica-X (pal)
I need to completely turn off the clipping of objects (performance doesnt really matter)
I already tried to change the value of a existing widescreen patch, but had no sucess.
Also I wasnt able to find the (any) function in the debugger of dolphin, because I´m not a coder.
thx in advance