Clipping/Culling in GC and Wii games (Part 2)!

Game Hacks, Trainers, Cheats

Moderator: Ralf@gc-forever

Post Reply
Posts: 12
Joined: Fri Dec 05, 2014 5:09 am

Clipping/Culling in GC and Wii games (Part 2)!

Post by cegli » Tue Mar 03, 2015 12:36 am

Hi everyone,

A while ago I posted this: viewtopic.php?f=38&t=2644 and you guys were amazingly helpful. We took the codes/knowledge you gave us, and did two things:

1. We created a bruteforcer for Dolphin VR, that takes goes through every function and forces it to return a zero or one, takes a screen shot, and records the amount of primitives/draw calls so it is easy to find a code to stop all clipping/culling.

2. We created a way to combine a whole bunch of .map files in Dolphin, and then search a game without a .map file for the same code, so we can easily find similar functions in other games.

We've been finding codes and posting them here:

Here's the question. The bruteforcer only works on around 30-40% of games. We're trying to figure out why it doesn't work on every game. We want to be able to improve the bruteforcer to grab the code for any game we throw at it. Here's a list of games where the bruteforcer failed:

Code: Select all

[WII] mario galaxy
[GC] the incredible hulk
[WII]Epic mickey
[GC]The simpsons hit and run
[GC]SpongeBob SquarePants: Battle for Bikini Bottom
[GC]Kao The Kangaroo Round 2
[GC]Resident evil 4 (found one but messes character geometry and bullet collision detection) 04128A50
[GC]Lara Croft Tomb Raider: Legend
[WII]LEGO The Lord of the Rings
[WII]Monster House
[WII]Mini Ninjas
[GC]Soul Calibur 2
[GC]Second sight
[GC]Metal Arms
[GC]Paper mario, TTYD
[GC]Metal Gear Solid: The Twin Snakes
[GC]Star Wars Rogue Squadron II: Rogue Leader
[GC]Sphinx and the cursed mummy
[GC]Star fox assault
[WII]Donkey Kong Country Returns
[GC]Animal Crossing
The two things that would be amazingly useful are:

1. If anyone can find clipping/culling codes for any of these games, we could use the codes to figure out why our bruteforcer didn't find them. That would be a huuuge help.
2. If anyone has any suggestions of ways to expand our bruteforcer's coverage, that would be super useful too. Right now we use

Code: Select all

04yyyyyy     3860000x
04yyyyy(y+4) 4E800020
with x being either 0 or 1, and y being the starting address of each function. This is modeled after the codes Ralf helped us find for MKDD, LoZ: WW, and LoZ: TP.

Let me know if you have any questions or if anything wasn't clear, and thanks so much for your help!
Posts: 1249
Joined: Sun Mar 16, 2014 9:31 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by Ralf@gc-forever » Tue Mar 03, 2015 8:24 pm

Give me a couple of days and I'll see what I can do.
Posts: 12
Joined: Fri Dec 05, 2014 5:09 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by cegli » Tue Mar 03, 2015 10:54 pm

Awesome, thanks Ralf! One new update is that I was looking at the clipping function in LoTR, The Third Age, and I found that it returns:

2 - Clip
4 - Don't Clip
8 - Don't Clip (Reached End of Function without hitting a condition, maybe some kind of don't clip with internal warning)

Our bruteforcer only found it because returning 0 also triggers "don't clip" even though it would normally be impossible for the function to return that. I was thinking maybe this could be one of the issues with us only using "li r3, 0" and "li r3, 1" in our code. I'm sure there are other possible flaws as well, so I'm still really looking forward to what you come up with :).
Posts: 1249
Joined: Sun Mar 16, 2014 9:31 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by Ralf@gc-forever » Sun Mar 08, 2015 1:27 pm

I think I have found one of the main clipping routines of Star Fox Assault (PAL version):

Code: Select all

800695DC:  9421FFB0	stwu	r1,-80(r1)
800695E0:  7C0802A6	mflr	r0
800695E4:  90010054	stw	r0,84(r1)
800695E8:  DBE10040	stfd	f31,64(r1)
800695EC:  F3E10048	psq_st	f31,72(r1),0,0
800695F0:  DBC10030	stfd	f30,48(r1)
800695F4:  F3C10038	psq_st	f30,56(r1),0,0
800695F8:  DBA10020	stfd	f29,32(r1)
800695FC:  F3A10028	psq_st	f29,40(r1),0,0
80069600:  C002924C	lfs	f0,-28084(r2)
80069604:  FFA00890	fmr	f29,f1
80069608:  FC020040	fcmpo	cr0,f2,f0
8006960C:  4C401382	cror	2,0,2
80069610:  40820134	bne-	0x80069744
80069614:  FFC0E890	fmr	f30,f29
80069618:  2C040000	cmpwi	r4,0
80069680:  FC07F040	fcmpo	cr0,f7,f30
80069684:  4081000C	ble-	0x80069690
80069688:  C02292A8	lfs	f1,-27992(r2)	f1 = BF800000 = -1.0  => enable clipping
8006968C:  480001E0	b	0x8006986c
800696D0:  FC010040	fcmpo	cr0,f1,f0
800696D4:  4081000C	ble-	0x800696e0
800696D8:  C02292A8	lfs	f1,-27992(r2)
800696DC:  48000190	b	0x8006986c
800697B4:  FC1F0040	fcmpo	cr0,f31,f0
800697B8:  4081000C	ble-	0x800697c4
800697BC:  C02292A8	lfs	f1,-27992(r2)
800697C0:  480000AC	b	0x8006986c
80069824:  FC010040	fcmpo	cr0,f1,f0
80069828:  4081000C	ble-	0x80069834
8006982C:  C02292A8	lfs	f1,-27992(r2)
80069830:  4800003C	b	0x8006986c
80069868:  FC200818	frsp	f1,f1
8006986C:  E3E10048	psq_l	f31,72(r1),0,0
80069870:  CBE10040	lfd	f31,64(r1)
80069874:  E3C10038	psq_l	f30,56(r1),0,0
80069878:  CBC10030	lfd	f30,48(r1)
8006987C:  E3A10028	psq_l	f29,40(r1),0,0
80069880:  80010054	lwz	r0,84(r1)
80069884:  CBA10020	lfd	f29,32(r1)
80069888:  7C0803A6	mtlr	r0
8006988C:  38210050	addi	r1,r1,80
80069890:  4E800020	blr

This function returns a single precision (32 bits) floating-point number in register f1. The returned value can vary in the range -1.0, 0.0 ... 1.0, where the returned value -1.0 means that the object will be clipped.

Enable Clipping
040695DC C02292A8
040695E0 4E800020

The code below works fine for an older version of my 16:9 Aspect Ratio code, which has clipping problems.

Disable Clipping ???
0406968C 60000000
040696DC 60000000
040697C0 60000000
04069830 60000000

There is another clipping function for skybox objects (clouds etc.) at address 0x80071814, but needs further investigation.
Posts: 12
Joined: Fri Dec 05, 2014 5:09 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by cegli » Mon Mar 09, 2015 7:53 am

Thanks so much for your help on this! I had an hour to look at this today, and already managed to craft an interesting hack for Paper Mario: TTYD using the idea of looking at floating point calculations that effect culling and disabling branches around them. So far I've managed to make the camera zoom out, stabilize and have the culling disabled. I'm hoping to eventually separate the effects, but it's a good start!

Let me know if you find anything more, because each new idea will help us improve our bruteforcer! I'm already formulating some ideas based on these findings. :)
Posts: 1
Joined: Thu Dec 11, 2014 2:31 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by penkamaster » Tue Mar 10, 2015 2:37 am

Hello Ralph, I'm another of the developers of the bruteforcer, thanks for helping us in this war against the culling geometry in dolphin.
I've tried the culling codes for starfox assault that you pointed, but the geometry keeps getting culled out of the camera view.
There is something that I don't understand... maybe more than one XD.
If you say that the function returns a range between -1 and 1 being - 1 when the object is culled, why not disabling the culling by forcing the function to return a 1 in the F1 register?
Can you explain me a little what are you trying to do with the 60000000 in these positions (I suppose that you are trying to return a 1 in the F1 register, but my knowledge of ASM is very limited, only some 68000 so many years ago) , and suggest other things to try in order to found the way to disable culling in this function.
Thank you.
Posts: 12
Joined: Fri Dec 05, 2014 5:09 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by cegli » Tue Mar 10, 2015 8:11 am

0x60000000 is a NOP, so he is skipping the branches. If you BLR out of the function, everything turns black, so you can't do that. The function may set necessary floating point registers needed for other things. I haven't tried loading F1 = 1, then BLRing, but I have a feeling it might not render properly.

I have a question too. To load a floating point value into a fx register, I see that it is typically grabbed from the rtoc. So I'll see something like, lfs, f1, -0x7E14(rtoc) in the Dolphin debugger. How can I tell what is in the rtoc? Is there an easy way to tell what is loaded into each register in the Dolphin debugger, or do you use something else?
Posts: 564
Joined: Fri May 03, 2013 6:57 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by tueidj » Tue Mar 10, 2015 12:06 pm

rtoc is r2.
Posts: 1249
Joined: Sun Mar 16, 2014 9:31 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by Ralf@gc-forever » Tue Mar 10, 2015 8:40 pm

Some of the Gekko/PPC general-purpose registers (GPRs) are reserved for specific uses:

Code: Select all

R1  (SP)   stack pointer
R2  (RTOC) global pointer to _SDA2_BASE_ (global constants, mostly floating points & strings)
R13        global pointer to _SDA_BASE_  (global variables)

Usually, these reserved registers will be initialized on game start-up:

Code: Select all

80003324:  3C20803B	lis	r1,-32709
80003328:  60216478	ori	r1,r1,25720
8000332C:  3C40803A	lis	r2,-32710
80003330:  60429840	ori	r2,r2,38976
80003334:  3DA0803A	lis	r13,-32710
80003338:  61AD7D20	ori	r13,r13,32032
8000333C:  4E800020	blr

r2/rtoc = 0x803A9840

As for the clipping routine at address 0x800695DC, the returned floating-point value seems to be a clipping factor:

-1.0 = 100%
0.0 = 0% (no clipping)
0.5 = 50%
1.0 = 100%

A clipping factor of 0.0 significantly slows down the game on real hardware!

Disable Clipping (f0 = 0.0)
040695DC C02292AC
040695E0 4E800020

Below is a listing of the different caller functions of the routine at address 0x800695DC. The function at address 0x80164494 looks similar to the clipping functions in other games.

Code: Select all

80071050:  C021001C	lfs	f1,28(r1)
80071054:  38610020	addi	r3,r1,32
80071058:  38800000	li	r4,0
8007105C:  4BFF8581	bl	0x800695dc
80071060:  FFE00890	fmr	f31,f1		; f1/f31 = clipping factor
80071208:  7F83E378	mr	r3,r28		; r3/r28 = texture/object id
8007120C:  480F2D6D	bl	0x80163f78
80071210:  3B7B0001	addi	r27,r27,1
80071214:  3B9C0001	addi	r28,r28,1
80071218:  A81E0002	lha	r0,2(r30)
8007121C:  7C1C0000	cmpw	r28,r0
80071220:  4081FBDC	ble+	0x80070dfc

80163F78:  9421FFF0	stwu	r1,-16(r1)
80163F7C:  7C0802A6	mflr	r0
80163F80:  90010014	stw	r0,20(r1)
80163F84:  DBE10008	stfd	f31,8(r1)
80163F88:  FFE00890	fmr	f31,f1
80163F8C:  4800715D	bl	0x8016b0e8	; convert texture/object id to texture/object pointer (r3) 
80163F90:  28030000	cmplwi	r3,0
80163F94:  41820010	beq-	0x80163fa4
80163F98:  FC20F890	fmr	f1,f31
80163F9C:  38800000	li	r4,0
80163FA0:  480004F5	bl	0x80164494	; check if given texture/object needs to be clipped ?
80163FA4:  80010014	lwz	r0,20(r1)
80163FA8:  CBE10008	lfd	f31,8(r1)
80163FAC:  7C0803A6	mtlr	r0
80163FB0:  38210010	addi	r1,r1,16
80163FB4:  4E800020	blr

80164494:  9421FF10	stwu	r1,-240(r1)
80164498:  7C0802A6	mflr	r0
8016449C:  900100F4	stw	r0,244(r1)
801644A0:  DBE100E0	stfd	f31,224(r1)
801644A4:  F3E100E8	psq_st	f31,232(r1),0,0
801644A8:  DBC100D0	stfd	f30,208(r1)
801644AC:  F3C100D8	psq_st	f30,216(r1),0,0
801644B0:  BEA100A4	stmw	r21,164(r1)
801644E8:  FC000800	fcmpu	cr0,f0,f1
801644EC:  40820090	bne-	0x8016457c
801644F0:  C0030004	lfs	f0,4(r3)
801644F4:  FC000800	fcmpu	cr0,f0,f1
801644F8:  40820084	bne-	0x8016457c
801644FC:  C0030008	lfs	f0,8(r3)
80164500:  FC000800	fcmpu	cr0,f0,f1
80164504:  40820078	bne-	0x8016457c
80164508:  C003000C	lfs	f0,12(r3)
8016450C:  FC000800	fcmpu	cr0,f0,f1
80164510:  4082006C	bne-	0x8016457c
80164514:  C0030010	lfs	f0,16(r3)
80164518:  FC000800	fcmpu	cr0,f0,f1
8016451C:  40820060	bne-	0x8016457c
80164520:  C0030014	lfs	f0,20(r3)
80164524:  FC000800	fcmpu	cr0,f0,f1
80164528:  40820054	bne-	0x8016457c
8016452C:  C0030018	lfs	f0,24(r3)
80164530:  FC000800	fcmpu	cr0,f0,f1
80164534:  40820048	bne-	0x8016457c
80164CE0:  28000002	cmplwi	r0,2
80164CE4:  4082000C	bne-	0x80164cf0
80164CE8:  C02D983C	lfs	f1,-26564(r13)
80164CEC:  48013D3D	bl	0x80178a28
80164CF0:  E3E100E8	psq_l	f31,232(r1),0,0
80164CF4:  CBE100E0	lfd	f31,224(r1)
80164CF8:  E3C100D8	psq_l	f30,216(r1),0,0
80164CFC:  CBC100D0	lfd	f30,208(r1)
80164D00:  BAA100A4	lmw	r21,164(r1)
80164D04:  800100F4	lwz	r0,244(r1)
80164D08:  7C0803A6	mtlr	r0
80164D0C:  382100F0	addi	r1,r1,240
80164D10:  4E800020	blr

Posts: 12
Joined: Fri Dec 05, 2014 5:09 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by cegli » Thu Mar 12, 2015 7:16 pm

Very cool. I tried forcing this function to return f1 = 0 with the code you provided in Dolphin, but it crashed as soon as I started the level. I guess this could be caused by large amount of objects being rendered simultaneously. I may need to play around with the f0 value a bit.

I'm starting to understand the RTOC/R2 thing now, thanks for the explanation. I guess the location of the constants in the RTOC differs per game then :(? Is there an easy way to load 1 or 0 into f1 regardless of the game, or would you have to find where the RTOC is with the __start function, then parse it for a FP value of 1 or 0, then use the lfs command from there? What about using an AR code to force a FP value into unused memory somewhere, then use lfs referencing that area of memory?
Posts: 564
Joined: Fri May 03, 2013 6:57 am

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by tueidj » Thu Mar 12, 2015 8:25 pm

- load required float as immediate values into a GPR
- store GPR to stack memory
- load same memory into F1
User avatar
Posts: 1
Joined: Sun May 25, 2014 9:02 pm

Re: Clipping/Culling in GC and Wii games (Part 2)!

Post by sallim » Sat Feb 16, 2019 11:44 pm

Hey guys, first big thanks for making brute forcing possible!

I was looking for killer7 cull code and I think I found at least one working pretty good for the cutscenes.
Using dolphin-vr-x64-5.0-250.exe / Oculus SDK 1.3.0 or SteamVR

Here are the codes with bruteforce -0

Killer7 Disk1+2 / GK7J08 / JAP/NTSC / Jun 3, 2005 debug build
No Culling

Code: Select all

040a185c 60000000
040A1860 4E800020
Removing cutscene bars

Code: Select all

0407a11c 60000000
0407A120 4E800020
Hope this helps someone. Will bruteforce other regions too!
Shooting part seems to be broken, depending on the "zoom out" degree.

Update 210219:
No Culling Killer7 PAL
Killer7 Disk1 + 2/ GK7P08 / EUR/PAL

Code: Select all

04070E2C 60000000
04070E30 4E800020
No Culling Killer7 PAL debug build
Killer7 Disk1 + 2/ GK7P08 / EUR/PAL / May 11, 2005 debug build

Code: Select all

04148020 60000000
04148024 4E800020
No Culling Killer7 USA
Killer7 Disk1 + 2/ GK7E08 / USA

Code: Select all

040e4288 60000000 
040E428C 4E800020
If any codes don't work for you, let me know. I have more spare that might also work better.
All posted codes are tested, and as far as I can say, they work pretty good.I had some that blacked out textures but were showing objects.

You can find me on Discord on the killer7 mod server.

Cheers and thx again.
Post Reply