How my codes work
Introduction
On this page you will find information about how I made some of my codes for Super Mario 64 on the N64. In turn this will give you a good idea about how parts of the game work.
In this section I will talk about how some of my codes work which will help to explain a bit about the game's coding as some of my cheats alter that.
Control and use portals in Bob-omb battlefield
There are two main parts to this code; patching the game to remove the overlays and Mario transparency as well as making the warps look like portals and running a mini program to place one of two warps in front of Mario. I will go onto detail for the NTSC version of the code but the PAL version works the same.
So, for the first part of the code with comments as to what each line of the code does:
8124DF84 1000 Warp Mario as soon as he gets to the warp
8124AC8E 0001 Really quick overlay when warp
8125A6BC 0000 Warp immediately
8125A6BE 0000
8125A670 0000 Remove Mario transparency when first warp
8125A672 0000
8125A74C 0000 Mario not transparent at end of warp
8125A74E 0000
8034CDEB 0025 Warp 1: face camera
8134CDFC 800F Warp 1: use '0' graphic
8134CDFE 9E10
8134CE14 4080 Warp 1: increase X size
8134CE18 4080 Warp 1: increase Y size
8034D04B 0025 Warp 2: face camera
8134D05C 800F Warp 2: use '0' graphic
8134D05E 9E10
8134D074 4080 Warp 2: increase X size
8134D078 4080 Warp 2: increase Y size
8124ACE0 0000 Change overlay to black
8124ACE2 0000
When Mario warps there is a delay, he turns transparent and then the screen goes white. After warping the screen returns and Mario loses his transparency (actually he starts off transparent again).
The zero colourful character, as used on the HUD and for when you collect a red coin (but of course, the numbers other than zero) looked to me like a portal from the game Portal. The idea was to try to patch the warps so they were more like portals from Portal that you could just walk through; I've got close to that.
The next part is the mini program for placing the warps, which starts at address 8033D2D0 in the NTSC code. Below the listing is given with the instruction value first and then the assembler version to the right then comments (if any).
3C048034 LUI A0,0X8034
948AAFA0 LHU T2 0XAFA0(A0) Get 1P D-pad and other buttons state
3C048035 LUI A0,0X8035
24080800 LI T0,0X00000800
11480005 BEQ T2,T0,DPAD_PRESSED D-pad up pressed?
24080400 LI T0,0X00000400
11480003 BEQ T2,T0,DPAD_PRESSED D-pad down pressed?
24840260 ADDIU A0,A0,0X0260 Modify warp 2 position instead of warp 1 position
1000000C BEQ R0,R0,EXIT No button pressed, exit
00000000 NOP
3C058034 LUI A1,0X8034 DPAD_PRESSED
C4A4B1AC LWC1 F4,0XB1AC(A1) Get Mario X position
3C064300 LUI A2,0X4300 How much to offset (128)
44863000 MTC1 A2,F6
46062100 ADD.S F4,F4,F6 Add offset (128)
E484CE88 SWC1 F4,0XCE88(A0) Set warp X position to Mario X position + offset
C4A4B1B0 LWC1 F4,0XB1B0(A1) Get Mario Y position
46062100 ADD.S F4,F4,F6 Add offset
E484CE8C SWC1 F4,0XCE8C(A0) Set warp Y position to Mario Y position + offset
C4A4B1B4 LWC1 F4,0XB1B4(A1) Get Mario Z position
E484CE90 SWC1 F4,0XCE90(A0) Set warp Z position to Mario Z position
03E00008 JR RA EXIT
Basically, if D-pad up or down are pressed Mario's X, Y and Z position are looked up and an offset is added to the X and Y position and then applied to either warp 1 or warp 2. Adding an offset to the Y position makes sure the portal can fully be seen and the offset on the X position places it in front of Mario (not on the Z axis as I first thought). The selection between the two warps is simply done by adding an offset to a start address.
Lastly, Mario's behaviour script is modified so that the above code is called:
810EE060 8033 Call asm code
810EE062 D2D0
Certain yellow coins home in on Mario
(Added: 28/5/11)
The code:
PAL
810E1214 802C
810E1216 53B4
812C53C8 0C0A
812C53CA 2F58
812C53CC 0000
812C53CE 0000
812C53D0 1000
812C53D2 0020
812C53D4 0000
812C53D6 0000
812C4BB8 0000
812C4BBA 0000
NTSC
810EBB54 802F
810EBB56 496C
812F4978 0C0A
812F497A AE18
812F497C 0000
812F497E 0000
812F4980 1000
812F4982 002C
812F4984 0000
812F4986 0000
812F3FF8 0000
812F3FFA 0000
How the code works:
PAL Version:
1-up mushroom that homes in on Mario behaviour/GFX ID: 0x13004148/0xD4
Part of behaviour script (for updating 1-up):
800E49B4 0C000000 802C53B4
Yellow coin (from Goomba, big breakable box and wooden posts) behaviour/GFX ID: 0x1300091C/0x74
Part of behaviour script (for updating coin):
800E1210 0C000000 8028BD60 -> 0C000000 802C53B4 (this change makes the coin use the homing in 1-up behaviour)
Homing in 1-up behaviour coding:
802C53B4: LUI V1, 0x8033
802C53B8: ADDIU V1, V1, 0xED90
802C53BC: LW A3, 0x0000 (V1)
802C53C0: ADDIU SP, SP, 0xFFE8
802C53C4: SW RA, 0x0014 (SP)
802C53C8: LW V0, 0x014C (A3) -> 0C0A2F58 JAL 8028BD60 Call the coin behaviour coding so that it still acts like a coin
802C53CC: ADDIU AT, R0, 0x0001 -> 00000000 NOP (Nothing in the delay slot)
802C53D0: BEQL V0, R0, 0x802C53F4 -> 10000020 BEQ R0,R0,0x802C5454 Jump to the homing in coding
802C53D4: LH T6, 0x0002 (A3) -> 00000000 NOP (Nothing in the delay slot)
802C5454: JAL 0x802C4AC4
802C5458: NOP
802C545C: JAL 0x802B8AAC
802C5460: NOP
802C5464: BEQ R0, R0, 0x802C54FC
802C5468: LW RA, 0x0014 (SP)
802C54FC: ADDIU SP, SP, 0x0018
802C5500: JR RA
802C5504: NOP
So far, the yellow coins will home in on Mario but will increase his lives as well as coin total. So next, we need to patch the homing in 1-up behaviour coding so that it is used just for homing in on Mario.
802C4BB8: JAL 0x802C48EC -> 00000000 NOP Disable function which increases Mario's lives and plays sound.
802C4BBC: SWC1 F8, 0x00B8 (V1)
802C4BC0: LW RA, 0x001C (SP)
802C4BC4: LW S0, 0x0018 (SP)
802C4BC8: ADDIU SP, SP, 0x0030
802C4BCC: JR RA
802C4BD0: NOP
Note that if you get a homing in 1-up it will keep following or circling around Mario until it fades.
Press D-pad to start or stop screen shake (version 1.0)
(Added: 26/6/9)
Pressing D-pad up will start screen shake and D-pad down to stop screen shake.
PAL (UK)
810E3720 8030 //Replace function call in Mario behaviour script to call our code
810E3722 AF00
D0309260 0008 //Press D-pad up to start screen shake
8030B000 0001
D0309260 0004 //Press D-pad down to stop screen shake
8030B000 0000
8030AF00 27BDFFE8 ADDIU SP,SP,0XFFE8
8030AF04 AFBF0014 SW RA,0X0014(SP)
8030AF08 3C048031 LUI A0,0x8031
8030AF0C 0C0E0221 JAL 0x80380884 //Shake screen
8030AF10 9084B000 LBU A0,0XB000(A0) //How much to shake screen
8030AF14 8FBF0014 LW RA,0X0014(SP)
8030AF18 27BD0018 ADDIU SP,SP,0X0018
8030AF1C 03E00008 JR RA
8030B000 How much to shake screen
NTSC (USA)
810EE060 8033 //Replace function call in Mario behaviour script to call our code
810EE062 D2D0
D033AFA0 0008 //Press D-pad up to start screen shake
8033D3D0 0001
D033AFA0 0004 //Press D-pad down to stop screen shake
8033D3D0 0000
8033D2D0 27BDFFE8 ADDIU SP,SP,0XFFE8
8033D2D4 AFBF0014 SW RA,0X0014(SP)
8033D2D8 3C048034 LUI A0,0x8034
8033D2DC 0C0A943F JAL 0x802A50FC //Shake screen
8033D2E0 9084D3D0 LBU A0,0XD3D0(A0) //How much to shake screen
8033D2E4 8FBF0014 LW RA,0X0014(SP)
8033D2E8 27BD0018 ADDIU SP,SP,0X0018
8033D2EC 03E00008 JR RA
8033D3D0 How much to shake screen
Passing a value of zero to the function that shakes the screen doesn't shake the screen or stops it if it was shaking. A value of one causes the screen to shake so it was a simple matter of using two button activators to write zeero or one to the variable that is passed to the function that determines if the screen should shake.
D-pad tree remote control
For this hack I created a new behaviour which allows you to move an object using the D-pad and is quite simple, however, it requires many codes. A problem I did encounter was how to force the game to execute my code that would work both on a real N64 and an emulator. The solution was to change the function call address in the tree behaviour script to my program and this can be done with other objects.
Have a look at the PAL coding I created for the remote control:
3C098033 LUI T1,0X8033
8D29ED90 LW T1,0X8032ED90 Get pointer to object
C52000A0 LWC1 F0,0X00A0(T1) Get object X position
C52600A4 LWC1 F6,0X00A4(T1) Get object Y position
C52400A8 LWC1 F4,0X00A8(T1) Get object Z position
3C084200 LUI TO,0X4200 How fast to move object
44881000 MTC1 T0,F2
3C0A8031 LUI T2,0X8031
814A9260 LB T2 0X80309260 Get 1P D-pad state
24080001 LI T0,0X00000001
1148000D BEQ T2,T0,DPAD_RIGHT
24080002 LI TO,0X00000002
1148000A BEQ T2,T0,DPAD_LEFT
24080008 LI T0,0X00000008
1148000C BEQ T2,T0,DPAD_UP
24080004 LI T0,0X00000004
1148000B BEQ T2,T0,DPAD_DOWN
24080006 LI T0,0X00000006
1148000C BEQ T2,TO,DPAD_LEFT-DOWN
24080009 LI TO,0X00000009
1148000B BEQ T2,T0,DPAD_RIGHT-UP
00000000 NOP
03E00008 JR RA
46001087 NEG.S F2,F2 DPAD_LEFT
46020000 ADD.S F0,F0,F2 DPAD_RIGHT
E52000A0 SWC1 F0,0X00A0(T1) Update object X position
03E00008 JR RA
46001087 NEG.S F2,F2 DPAD_UP
46022100 ADD.S F4,F4,F2 DPAD_DOWN
E52400A8 SWC1 F4,0X00A8(T1) Update object Z position
03E00008 JR RA
46001087 NEG.S F2,F2 DPAD_LEFT-DOWN
46023180 ADD.S F6,F6,F2 DPAD_RIGHT-UP
E52600A4 SWC1 F6,0X00A4(T1) Update object Y position
03E00008 JR RA
Put simply, the behaviour checks the D-pad and then updates the object's position if a direction button was pressed. I also sneakily only used add instructions but negated (made negative) the value to add when needing to subtract.
Sparkling and invincible Mario
I had a request so that Mario always sparkles and had tried to trigger such an effect but at the time I could not do such a thing. But now I have been swapping Mario's first 0x0C behaviour call in his behaviour script with other objects' behaviour calls I found that the Koopa shell behaviour call causes Mario to constantly sparkle since the game is none the wiser. Unfortunately this is just a side effect since using the Koopa shell behaviour call for Mario does not do anything else, so no walking on water for example.
As nice as it was to see Mario looking more super than usual I thought about adding to the code, such as to make him invincible. After studing the neon code that makes Mario flicker I realised that it was actually a timer used by the game after Mario is hit by a bad guy during which time he can not be hurt by enemies.
Let's look at, for the PAL game, how the code updates the invincible flag (assuming that Mario is currently flickering) depending on the timer and then I'll show you how I patched it to make sure that no baddies can do him damage.
First the game gets the value of the flicker timer:
8024A314 lh v0, 0x0026(a0) 'v0=(80309456)
Next the code updates the register t8 depending on if the flicker value is less than zero or not:
8024A318 sltu t8, r0, v0 't8=1
The contents of register t8 is transferred to register v0:
8024A31C or v0, t8, r0 'v0=t8=1
And to finish off the invincible flag is written to with the value of register v0:
8024A320 sh v0, 0x9532(at) '(80309530)=1
Basically, the above coding sets the invincible flag if the flicker timer value is higher than zero or clears it if it's zero. You might think that I could have just used a code to force the invincible flag to always be set (equal one) but that is not possible due to the game's coding constantly changing it. The solution was to change the sltu instruction so that the result is always one:
8024A318 slti t8, r0, 0x0001
Anyone still awake at this point may realize that the just mentioned alternation seems pointless since we know that zero will always be less than one but that's exactly as was needed to force the invincible flag to always be set.
All content of this and related pages is copyright (c) James S. 2003-2013
New: Control and use portals in Bob-omb battlefield
You can email me at james.boshikoopa@gmail.com
To return to the main page please click here.