|
Learn how Super Mario 64 for the N64 works, discover what was hidden that may have been used in the final game, and how the game can be modified to be played in a different way. Also, I will help you with making your own codes for Super Mario 64.
Not counting any alpha or beta versions there were four main versions of Super Mario 64; the original Japanese, USA (commonly known as NTSC), UK (a.k.a. PAL), and the second Japnese version which goes by the name of Shindou Edition and features rumble pack support.
Much of my findings come from using an actual N64 and various cheat devices such as an X-plorer 64 and Equalizer cheat code cartridge, and more recently, emulators-notably Nemu. My intimate understanding of SM64 shows in the codes that I have created, some of which have never been done before. Please read on to learn my findings and discover how Mario's first 3D platform game works while discovering some secrets.
|
| 00 | 0 |
| 01 | 1 |
| 02 | 2 |
| 03 | 3 |
| 04 | 4 |
| 05 | 5 |
| 06 | 6 |
| 07 | 7 |
| 08 | 8 |
| 09 | 9 |
| 0A | A |
| 0B | B |
| 0C | C |
| 0D | D |
| 0E | E |
| 0F | F |
| 10 | G |
| 11 | H |
| 12 | I |
| 14 | K |
| 15 | L |
| 16 | M |
| 17 | N |
| 18 | O |
| 19 | P |
| 1B | R |
| 1C | S |
| 1D | T |
| 1E | U |
| 1F | V |
| 20 | W |
| 22 | Y |
| 23 | Z |
| 9E | (space) |
|
FF |
(terminator) |
0X802FDB78 19 0A 1E 1C 0E FF
Which spells out PAUSE (the 0xFF is the terminating character since 0x00 is used for the number zero). Change these values and if the game is paused the changes will have imediate effect. Note: If you move the terminating character to the left the string will shrink but the opposite doesn't work even if you add more characters; it may be that the bytes that follow the 0xFF are used for other reasons and this explains why going into that area causes problems.
You may be wondering what's so wonderful about modifying text. Well apart from the amusing words you can come up with there are more practical uses such as for when you write your own programs and insert them into the game's execution. You'll need a convenient way to show data as the game is being played rather than having to use a memory editor.
Here are some addresses of more English strings (foreign strings follow the English ones):
0x802FDA10 COURSE
0X802FDA28 MY SCORE
0X802FDAE0 CONTINUE
To find other strings, take two adjacent characters on even boundaries (the first two characters are ideal, like 'PA' for PAUSE), convert to the hex values (0x19 and 0x0A for 'PA') and convert to decimal to use in the 16-bit search (if need be). Once you've found a possible address you'll know if it's the string by looking at the values that follow and by modifying them.
The level select uses the colourful text even though there's the problem of the few missing letters coupled with the strange names makes reading them difficult. It's weird since the level select names are actually stored in the RAM in ASCII so why not display them correctly by using the normal text?
Now let's look at the colourful character values used by the text functions that accept the ASCII standard.
0x2A cross (used for lives for example)
0x2B coin symbol
0x2C Mario head symbol
0x2D star symbol
0x2F Ü (no Ü in NTSC game. Key symbol for Japanese versions.)
0x30 0
0x31 1
0x32 2
0x33 3
0x34 4
0x35 5
0x36 6
0x37 7
0x38 8
0x39 9
0x41 A
0x42 B
0x43 C
0x44 D
0x45 E
0x46 F
0x47 G
0x48 H
0x49 I
0x4A (should be J but glitched up)
0x4B K
0x4C L
0x4D M
0x4E N
0x4F O
0x50 P
0x51 (should be Q but glitched up)
0x52 R
0x53 S
0x54 T
0x55 U
0x56 V (no V in NTSC game)
0x57 W
0x58 (should be X but glitched up)
0x59 Y
0x5A Z (no Z in NTSC game)
0x61 to 0x7A are A-Z (would be a-z in normal ASCII)
Other values will result in blank or glitched up characters. It can be seen that the PAL game has more colourful characters than the NTSC game as the PAL version supports English, French and German languages. Starting at address 0x80305C98 in the RAM for the PAL game are the strings TIME, TEMPS and ZEIT which is Time in English (d'oh!), French and German.
Create your own codes
Debug
AREA
WX
WY
WZ
BGY
ANGY
BGCODE
BGSTATUS
BGAREA
DPRINT OVER
Expansion pack memory
80400004 0C000000
80400008 80400100
8040000C 09000000
80400104 lb a1, 0x94DD(a0) Get the number of lives Mario has
80400108 addiu a1,a1,0x0001 Increase lives
8040010C sb a1, 0x94DD(a0) Update lives
80400110 lui a0,0x8033
80400118 sh r0, 0x0074(a0) Remove object
8040011C jr ra
FAQ
A. Some cheat cartridges and emulators don't like long codes, so if you've checked that you entered every digit of the code correctly, try splitting the code in half and turning on both halves as if they were a single code.
A. Yes, although if you do make a mistake when typing a code, by chance you may discover another cheat.
A. Some codes can conflict with each other and having too many codes on at the same time can cause problems or even crash the game. Try turning on less codes or different combinations. A few of my codes won't work if used together since they use the same memory.
A. If you've checked that you entered the code correctly it may be that it uses an activator. This requires you to press a certain button or combination of buttons to trigger the cheat.
A. This is usually only necessary with emulators, which cache (backup) the game's coding that the cheat modifies. If the emulator caches the game's coding before the cheat has altered it the emulator will use the unmodified coding and so the cheat will have no affect. I have found with SM64 that any codes that alter the game's coding should be turned on as soon as possible, at the latest at the file select screen.
Functions
Graphics
(Update: 27/9/8)
The objects in Super Mario 64 can look very simple such as the trees and the coins, or they can have a complicated 3D apperance such as Mario. Nintendo used numerous tricks to make sure that the game ran smoothly; many of the objects are 2D like the trees, coins, 1-up mushrooms and so on but always face the camera to appear more 3D (known as billboarding). The coins do not actually rotate but appear to by cycling through several pre-rendered frames (textures) of the coin at different angles.
The Mario graphic is without doubt the most complicated, although Bowser is not far away. Of course normally only one object has the Mario graphic (two when mirror Mario is visible), but if too many objects were to use the Mario graphic the game would crash.
What has always puzzled me although nothing major is why the programmers went to the trouble of having coins and other objects with and without shadows. Did Nintendo really go to so much trouble to not have shadows except where absolutely necessary such as for objects that move (an e.g. is that the only boxes to have shadows are those that jump and can move). Fortunately having a graphic without a shadow is simply a matter of bypassing the shadow value in the graphic structure.
The graphic structure is what I call the values that describe what an object looks like including such information as its starting size (a single value for X, Y and Z; the size modifiers in any object that uses a graphic can then adjust the graphic's size even more and in each of the three directions). Also, the graphic structures have details about the type of shadow (if any) and how the (if any) sub parts of the graphic are positioned accordingly like the head, torso, legs, arms, and so on.
Although nothing new where 3D graphics are concerned, you may be surprised that the graphic structures can contain pointers to functions to use that typically would adjust a graphic in some way. For example, part of the coin behaviour updates a variable in the coin object to remember what coin animation frame (texture) to use. The function call in the coin graphic structure then copies the coin object frame variable to the coin graphic structure as a temporary variable (a pointer to each object that use the graphic is also copied to the graphic structure).
Something I've wanted to do for ages but I didn't know if it was possible is to use scenery graphics for objects like Mario, coins, doors, etc. As can be seen when using my Attack of the big Goomba castles I changed the signposts to look like the castle and surrounding area and then used the (big) Goomba behaviour.
For most of the levels the scenery graphics are actually objects but with other courses including inside and outside the castle, and Bob-omb battlefield the scenery is nothing to do with the objects (i.e., it cannot move or be sized like the objects). Since the graphic structures used by the objects contain segment/offset values for what graphics to use, these values can be changed to use scenery graphics (but remember that the scenery graphics will only be loaded for the one level).
Changing the signposts to look like the castle worked well since the signposts are made up of two parts; the post and the actual sign. So I swapped the sign part with the castle graphics and the post part with the grass and hills area. The signposts still use the signpost graphic structure but that has been modified to use different graphics for the post and sign parts.
The levels are made up of several layers, for example, outside the castle the castle is one layer, the surrounding area is another. Then there are the fences, tree shadows, castle windows and castle door way as more layers-and let's not forget the castle tower but that is an object.
Most likely the reason for splitting up the level scenery graphics is so it's more manageable and let's not forget the objects also are made up of many parts like the signposts. But for some objects such as Mario who is animated he has to be made up of lots of parts (Head, torso, legs, and so on) so they can be moved independently of each other.
Graphics Pointer Values
Please go to SM64 Exposed Graphic Values.
How many stars?
Super Mario 64 reinvented the Mario universe and introduced the concept of earning stars to progress in the game. But just how many stars had Nintendo originally intend for the player to collect? The DS remake features a lot more stars, though some were dropped from the N64 version.
65535 stars?
Address 803094DA in the PAL version stores the current amount of stars obtained. What's strange is that this value is unsigned, 16-bit, meaning a maximum star total of 65535. This is an unrealistic amount, however, though 16-bits would be needed for stars above 255, which is much more likely. This cannot be used as hard evidence, because the programmers might just of got lazy and forgot to make the variable 8-bit (i.e. 0 to 255).
No more than 99 stars?
This is probably overlooked by most people but even though you can obtain more than 99 stars, the display misses out the 'x' after the star symbol and before the amount, instead of shifting the star total right one space to avoid overwritting the 'x'.
Further proof: the amount of stars stored in RAM is then converted to text form for the colourful text, which is the number of digits followed by the codes for the numbers (see above). For the PAL game, If the star total has 1 or 2 digits it's stored at address 0x8005C185 but for 3-5 digits the text is at address 0x8005C141. Did Nintendo suddenly realise that they could do 100 or more stars and had to use 2 addresses?
How my codes work
810E3722 AF00
8030B000 0001
D0309260 0004 //Press D-pad down to stop screen shake
8030B000 0000
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
810EE062 D2D0
8033D3D0 0001
D033AFA0 0004 //Press D-pad down to stop screen shake
8033D3D0 0000
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
D-pad tree remote control (update: 29/6/8)
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 (update: 16/6/8)
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.
How Bullet Bill works (update: 3/06/08)
Most Mario fans will recall many Bullet Bills fired at Mario from many directions but in Super Mario 64 there is only one Bullet Bill blaster near where the tower is located in Whomp's fortress. I assumed that the blaster spawned a Bullet Bill whenever Mario neared it but I couldn't find the code that did such a thing. Have a look at this screen capture:
(pic to be added)
I removed the Bullet Bill blaster object yet the Bullet Bill still fired itself and after it was 'destroyed' it returned to its starting position. This means that the blaster simply hides the Bullet Bill until it fires itself; the reason this was done was perhaps due to there only being one Bullet Bill ever needed.
Global behaviour changes (update: 2/06/08)
If you want a simple way to swap objects for all levels then all you need to do is modify the list of object values that can be found in the RAM. Study the following values from the PAL game:
802FDE38 130032E0007C0000
Above is the global control for the signposts which controls how the object looks and how it reacts to Mario and other objects. We can break the data down into important values:
130032E0 is the pointer to the start of the behaviour script for a signpost, so it controls what behaviour is to be used.
007C is the graphic ID for a signpost, that is, what it looks like.
0000 is extra values used by the behaviour, such as the Goombas as can be seen below:
802FDE80 1300472C00C00001
802FDE88 1300472C00C00002
802FDEB8 1300472C00C00000
Can you see that the only variation for the three Goomba types is the end value which tells the Goomba behaviour if it should be tiny, normal or big. The changes do not happen until you go to another level or re-enter the same course.
Whomps fall from the sky in Bob-omb Battlefield (update: 30/05/08)
You know those water bombs that fall from the sky in Bob-omb Battlefield, well, they don't come out of that cannon higher up that a Bob-omb guards. They are actually spawned when Mario nears an invisible object which acts like a trigger.
Trying out different ideas to replace the water bombs such as yellow coins I settled on a Whomp since you can have their graphics in Bob-omb Battlefield but they aren't normally in the level as an actual object.
The following is the ASM for the PAL game that determins what is spawned when Mario gets into the danger area:
802D3670 li t4, 0x13004BA8
802D3674 li t3, 0x00000054
To get Whomps to appear instead of water bombs it's a simple mater of changing the behaviour value (first line) and the graphic ID (second line). There are two interesting things to note; the Whomp bounces somewhat when he lands and only one Whomp shows up for each bomb area.
Force Mario to always face the camera (update: 19/05/08)
If an object is 3D but you trick the game into thinking it is 2D, it will have the affect so that the object always faces the camera. The problem is that you would need a code for every course and star unless the coding was altered which is what I did.
Take a look at this coding for the PAL game:
8024D5F0 lh t7, 0x0002(v0)
8024D5F4 andi t8, t7, 0xffef
8024D5F8 sh t8, 0x0002(v0)
The variable at offset 0x0002 in an object's structure enables or disables billboarding, 0x0021 is used for 3D objects like Mario and 0x0025 is for 2D objects such as the trees. What I needed to do was easily write the 0x0025 to Mario's object structure at offset 0x0002.
To do that I created a code that used 0x0005 instead of 0xffef and swaped the andi instruction for an ori command. In other words, 0x0021 is loaded and combined with the value 0x0005 which results in the number 0x0025.
Spawning items from Goombas (update: 18/05/08)
One of my goals was to change what items can be spawned from item boxes and other objects such as Goombas and now I can do that having had looked at the behaviour coding for a Goomba. There are two main values used for spawning a yellow coin from a Goomba and they are the graphic ID and the pointer to the behaviour script for the yellow coin.
Because I had found the global item box item type table in the RAM I recognised certain values used in the Goomba's behaviour coding. First Have a look at this instructions for the PAL game:
8037E0B8 li t6, 0x00000074
The 0x00000074 is the graphic ID for a yellow coin, if you alter this value the coin that comes out of a Goomba will look different but it will behave like the usual coin.
The next important command used for spawning also for the PAL game:
8037E0C4 addiu a3, a3, 0x09A4
The register a3 is set to the value 0x09A4 but that's only the bottom half of the pointer to behaviour, however, all we need to do is modify the lower half which is the offset and keep the segment value the same.
By changing both the graphic ID and pointer to behaviour you can spawn any item from a Goomba like my 'Goombas give Bob-ombs' code.
Global changes (update: 17/05/08)
Wouldn't it be great if you could, for example, force the game to give out loads of coins instead of one like from the Goombas-well, you can! This was something I've wanted to do for a long time and eventually I worked out how but not without looking at the coding and being sneaky.
First of all I checked to see if the Goomba's behaviour script wrote to the variable in a Goomba's object structure during initialization to set how many coins a Goomba releases when it's killed. There was no such instruction so I then checked the behaviour call to ASM in the Goomba's beaviour script and found this (PAL):
8037F38C 80A90007 lb t1, 0x0007(A1)
8037F390 AC890198 sw t1, 0x0198(A0)
A byte is loaded from an offset of the location pointed to by register A1 and then stored at offset 0x198 in every Goomba's object structure, i.e., how many coins it gives out. By changing the instruction that loads the value or the store instruction you could easily force Goombas to give out no coins by using r0 (which always equals zero) but I wanted to create a code that will force more than one coin to come out of a Goomba.
If I had been using Nemu at the time I could have easily found out where A1 pointed to but with only my Equalizer I decided to be sneaky by changing the store instruction so that it dumped the value of A1 to the variable at offset 0x198 in every Goomba's object structure (and making sure not to stomp a Goomba).
Now I knew that A1 pointed to 0x802FEE70 in the RAM and at offset 0x0007 from that was the value 0x01. By changing that byte it would have the global affect that all Goombas would pay Mario as many yellow coins as you wanted, although too high values will crash the game as there won't be enough free object structures.
Item box
Memory Map
Multiplayer
(Added: 28/10/8)
You may know that during the credits you can control the camera using a second controller which suggests that it's possible to add, if only limited, multiplayer to SM64. The truth is, as long as the controller is plugged in, the game will update the controller data stored in the RAM, but of course only take notice of that data for the second controller while the credits are being shown.
A problem I had was although emulators would read the second controller my N64 wouldn't but I realized what was going wrong. For some reason, if you enter the Equalizer's in-game menu and then return to the game, the second controller is deactivated as if it had been unplugged.
To do a simple 2-player, I patched the spawn debug mode so that it responded to the second controller instead of the first. In the PAL version a pointer to the location of the controller data is loaded just once, but in the NTSC game the pointer is loaded each time a d-pad button is checked (i.e. three times). Here is the first time the controller data pointer is loaded for the NTSC game for the spawn debug mode:
0x802CB298 lui t9, 0x8033
0x802CB29C lw t9, 0xD5E4(t9) Get pointer to 1P controller data
To change it so that the second controller is used instead, just change the 0xD5E4 to 0xD5E8. Note that code activators use the controller data directly rather than look up the pointer first since that's not possible without using the codes to make a mini program.
Nintendo's Tricks
Nintendo made sure to save as much memory as possible and keep the game running smoothly by using polygons only were necessary. Examples are the fact that Peach has no legs (her dress hides that area) and the pendulum in the clock in the castle has no back to it since you never normally see that side.
As well as that, any hidden polygons of non transparent objects like Mario, are removed. This can be shown by removing polygons of an object facing the camera and you will see right through the object; you won't see the back polygons.
The Rooms of Darkness
Nintendo used many tricks to lower the amount of memory and CPU time that Super Mario 64 needed to work, one of which can be seen in the castle. Any room you're not in is put into darkness by the game (think of it as something switching out the lights when Mario leaves a room) though you can't normally see that happening. This is done because anything black doesn't need to be drawn, thus lowering the number of polygons that need to be rendered. This was actually a common trick used in 3D games, hence why so many video games were set in buildings.
One way to see the rooms put into darkness is to turn off a door's graphics or just move it out of the way (it's fun walking through a door that doesn't lead to anywhere). The 'lights' will still be activated as you approach a room but before then you will see a room of darkness.
The above picture shows the door that leads into the mirror room is missing, or appears to be, by turning off its graphics. This shows that the room has been put in darkness so it doesn't need to be drawn, it's not enough just to hide it with the door, since sprite and scenery graphics are handled differently.
There's something strange about Lakitu's cloud, for one thing it's a separate object to the actual cameraman. The white object against the black is Lakitu's cloud (which is still animated) yet Lakitu himself doesn't appear until the 'lights' are turned on.
Normal Text
0x00-0x09 0-9
0x0A-0x23 A-Z
0x24-0x3D a-z
0x3E '
0x3F .
0x50 Arrow Up
0x51 Arrow Down
0x52 Arrow Left
0x53 Arrow Right
0x54 A
0x55 B
0x56 C
0x57 Z
0x58 R
0xFE [New Line]
Note: Arrow Up, Down, Left and Right are the actual graphical symboles used to represent the N64 controller's camera buttons. The A, B, C, Z and R refer to the controller's buttons and are bigger than the normal letters.
Save Files
To better understand how the game saves your progress, what follows is the addresses containing the saved variables for file save D, like what stars you've collected, for the PAL game:
0x80203058 [Byte] Secret stars.
0x8020305A [Byte] Various:
Bit #0:
Bit #1:
Bit #2:
Bit #3: (=1) Used star power: door no. 1 (Whomp's Fortress).
Bit #4: (=1) Used star power: door no. 3 (Cool, Cool Mountain).
Bit #5: (=1) Used star power: door no. 3 (Jolly Roger Bay).
Bit #6: (=1) Used star power: door to first Bowser. Bit #7: 0x8020305B [Byte] Various:
Bit #0: Used star power at least once.
Bit #1: Light in castle on(=0) or off (=1).
Bit #2:
Bit #3:
Bit #4:
Bit #5:
Bit #6:
Bit #7:
0x8020305C [Byte] Bob-omb Battlefield stars.
0x8020305D [Byte] Whomp's fortress stars.
0x8020305E [Byte] Jolly Roger Bay stars.
0x8020305F [Byte] Cool, Cool Mountain stars.
0x80203060 [Byte] Big Boo's Haunt stars.
0x80203061 [Byte] Hazy Maze Cave stars.
0x80203062 [Byte] Lethal Lava Land.
0x80203063 [Byte] Shifting Sand Land stars.
0x80203064 [Byte] Dire, Dire Docks stars.
0x80203065 [Byte] Snow Man's Land stars.
0x80203066 [Byte] Wet-Dry World stars.
0x80203067 [Byte] Tall, Tall Mountain stars.
0x80203068 [Byte] Tiny-Huge Island stars.
0x80203069 [Byte] Tick Tock Clock stars.
0x8020306A [Byte] Rainbow Ride stars.
Screen Special effects
(Added: 19/11/8)
Moving and sizing the screen
In the ending cut-scene there is a border at the top and bottom of the screen and in the end credits the screen appears to move and change size. There is a special function that allows the screen to be moved and its sized to be changed, although it doesn't actually affect the screen, more of a window on the world. So, if you were to make the screen smaller, or move it, you would see less of the game world.
The function uses several input values, one of which appears to be a pointer to where certain screen values are stored to set its size, position and other attributes. Note that the function must be called every frame otherwise the screen will return to its normal size.
When the screen is in the window mode, the area of the screen that is not showing the game world, that is the border, can be any colour you want. In the end movie and credits it is black, most likely to hide the fact that the text characters are on a black background that would show up if the border colour was not black. That and the tradition of having black borders in movie sequences.
The function that allows you to set the screen attributes requires that you specify the colour of the unused area of the screen when using window mode, as RGB. The red and green colour amount are placed into two seprate registers but the blue colour amount strangely has to be put on the stack before calling the function, although that may be due to how Nintendo's compiler converted from C to machine code. The colour values are then combined by the function and stored to memory.
There is an extra value to be passed to the function, one with a bit of mystery about it. In the NTSC game the value is stored to memory but in the PAL version it is never used by the function suggesting that it is an unused feature. Also, elsehwere in the game's code this unknown feature is disabled by writing zero to it, however, if the code is patched you can write to the variable without the game changing it. But, placing any value other than zero there seriously messes up the screen display, either showing darkness or zoming in greatly on the game world is a strange way.
Below is a screenshot of a code of mine that makes uses of the window mode, and also changes how red the border is depending on how much health Mario has (i.e. bright red for full health down to dark red for no health). This picture is from the PAL game running on Project64, but it works on a real N64 as well.
Unfortunately, the NTSC game has a black border at the top and bottom of the screen that's fixed and unaffected by the window mode.
Secrets of the Camera
As Mario moves even further away from the camera, the boxes and signposts have also gone; if the camera had moved with Mario those sprites wouldn't be seen.
This code also messes up the demos; because the camera does not move the scenery stays where it is and so collisions still occur between Mario and the scenery, but Mario 'thinks' he is somewhere else. So, to summarise the sprites appear and disappear depending on Mario's position in the level but what part of the scenery can be seen depends on the camera's position.
Segment/Offset Addressing
Sound and music
0x80380360 LH T4, 0x0004(T3) -> LH T4, 0xD3D0(T3)
Size modifiers
Every object has its own size modifiers (as floating-point values) stored in its object structure; some objects use the individual X, Y and Z size modifiers, others use a single size variable for sizing along the three dimensions equally.
With objects including Mario their size is constantly updated by their behaviour, meaning it's not possible to use their size modifiers in the object structures (as the game will just overwrite what you put there). Instead, you need to alter the game's coding which on the plus side will affect the object's size for all levels.
I created a code that patches the coding loaded into the RAM so that different values are used for the X, Y, and Z size modifiers in Mario's object structure. When it came to do the NTSC version I realised how difficult it would be due to the differences in coding between the two versions. I couldn't add a set value to the address or search for certain opcodes for specific instructions.
Fortunately I found the coding used by the NTSC game by using Nemu's hacking plugins and discovered that the NTSC SM64 is actually simpler to patch than the PAL game. Here is a comparison of the code side-by-side for the PAL game on the left and NTSC version on the right:
8024C7E4 MFC1 A1, F0 Mario's X size 802535BC LUI A1, 0x3F80
8024C8E8 MFC1 A2, F0 Mario's Y size 802535C0 LUI A2, 0x3F80
8024C7EC MFC1 A3, F0 Mario's Z size 802535C8 LUI A3, 0x3F80
In the PAL game a single value is used which is copied to 3 different registers but in the NTSC game three separate values are used. This makes sense since Nintendo saw that it was better that one value be used rather than three since the values are the same. What's interesting is that it suggests that Nintendo had planned that Mario could be sized differently and the simplest way to have Luigi in SM64 would be to change a few visual details about Mario and then alter his size.
Rayman Bob-omb
By increasing or decreasing Mario's size strange things happen when Mario picks up a box or Bob-omb when he's a different size to normal.
(pic to be added)
The larger Mario picks up a Bob-omb that patrols near Chain chomp, and behold its body parts split like Rayman! A box when picked up changes size to reflect Mario's size modification.
The coding
Even if you're not familiar with the coding used by N64 games please try to follow and understand it. Although the game was probably programmed in C, we can still look at the assembler (ASM) that is produced from the C coding. This ASM is for the PAL game and thus the instructions and addresses will differ for the NTSC game (due to bug fixes, etc).
Add 1-up
The coding that handles increasing Mario's lives by one:
0x802C4924 lui v0,0Cx8030
0x802C4928 lui v0,0xC802f9B0C
0x802C492C lui t8,0x8033
0x802C4930 lb t6,0x00AD(v0) 't6=Mario's lives(0x803094DD)
0x802C4934 addiu t7,t6,0x0001 'Add 1 life
0x802C4938 sb t7,0x00AD(v0) 'Update Mario's lives
The most obvious change we can make here is to award Mario with more lives each time he collects a 1-up, or to make the game harder, subtract a life each time (such as used in my Poison 1-up mushrooms code).
Add 1 red coin
0x802C3EF8 lw t8,0x00F4(v1) 't8=Mario's red coins(0x8031BBAF)
0x802C4EFC lui t0,0x8033
0x802C3F00 li at,0x00000008
0x802C3F04 addiu t9,t8,0x0001 'Add 1 red coin
0x802C3F08 sw t9,0x00F4(v1) 'Update red coins collected
Similar to the 1-ups, you can vary how many red coins to give Mario each time.
Start with no coins
0x80246EF0 lui at,0x8031
0x80246EF4 lui a0,0x8030
0x80246EF8 sh zero,0x00A8(t0)
0x80246EFC sh zero,0x94FA(at) 'Start with no coins (0x803094FA)=0
This coding ensures that Mario starts with no coins at the start of any level (including the castle). By NOPping the last instruction above, you can keep the number of coins you collected from a previous level.
The Level Select
The analogue stick doesn't work with the level select, instead use the D-PAD:
D-Pad Up: select previous level.
D-Pad Down: select next level.
D-Pad Left: Select the level 10 levels before current one.
D-Pad Right: Select the level 10 levels after current one.
Stranely, some of the names are difficult to relate to the actual levels, others fairly obvious such as 'kuppa1' for the first Bowser fight (i.e. Koopa 1 since King Koopa is what Bowser is known as in Japan). There are a few glitched up letters due to some of the colourful characters not existing which also doesn't help in selecting the right level (but all the colourful characters are in the Japanese version). The blank names were perhaps where more levels were to be added; if selected you are returned to the title screen.
The MIPS Processor
The N64 uses a 64-bit RISC MIPS processor that is part of the MIPS family that was used in other devices including the Playstation 1 and Playstation 2 (different bit power, with the N64 in the middle). Nintendo were obviously so impressed by the MIPS processor that they named the rabbit in SM64 that you have to catch MIPS.
It is unlikely that Nintendo programed SM64 using the MIPS' native language (machine code), instead they would have used C or C++ which was then converted to the machine code that the MIPS actually uses. We can view and modify the machine code but we would use assembler which is a more easier to understand than just numbers. Some of my codes actually change the game's coding that is loaded into the memory (RAM) so that more advanced cheats are possible.
Compared to other processors, the MIPS assembler is somewhat simpler to work with, however, working so low level is difficult and not ideal for everyone. In this section I will talk about how the MIPS processor works to help your understanding of how SM64 comes to life and it will also be useful for anyone who wants to make advanced codes
Bit sizes
First, let me put something to you: is Super Mario 64 really 64-bit? The answer is NO-let me explain. Super Mario 64 is 64-bit in that it is running on a 64-bit processor but coding wise it is actually more 32-bit. For one thing, pointers (variables that remember where something is in memory) only need to be 32-bit and this is the case for many of the other variables. This is also true for other N64 games, especially those ported from the Playstation 1 (which is 32-bit). The advantage of using 32-bit variables is that they take up half the space of 64-bit variables and can be processed quicker, however, 32-bit variables cannot deal with as high or as accurate values as 64-bit variables.
Many of the MIPS' instructions can load or store different size variables which are known as byte (8-bit), half word (16-bit), word (32-bit) and double word (64-bit). Other instructions can use immediate data stored with the instruction (as opposed to a variable), but is limited to 16-bit which is the reason why N64 Gameshark codes have the 16-bit limit to simplify how the cheats are converted to MIPS coding. The reason why immediate data is limited to 16-bit is so that all instructions use 32-bits each, so the other 16-bit determines what the instruction is.
Another thing to be aware of is that when using anything other than a byte (i.e., half word, word or double word) the variable must be located starting at an even address. You can test that using a Gameshark code such of the 81 type using an odd address-the game will crash.
Registers
Not everything is stored in the memory (RAM), temporary values are copied to the MIPS processor's registers which are variables that are inside the actual processor and thus can be accessed quicker than the external memory where all the other values are stored such as Mario's lives, and so on. One of the MIPS' registers isn't actually a variabe, it is called r0 and always equals zero. If you need to clear a variable to zero-including registers-rather than have to load zero as an immediate value you can just use r0 which saves time and memory and can make patching easier.
Pointers
A pointer is a 32-bit (word) variable whose value is the address of something in memory, such as graphics and audio information, variables like position, speed, etc, and even other pointers. Pointers are important as they tell the game where data is stored in memory and as a way of the game keeping track of what it is processing.
Examples of pointers are the pointer to the Mario object (where the Mario object is in memory changes from one level to another), the pointer to each object as it is being updated (including the Mario object), and the pointer to the part of the behaviour script being executed.
Mario is a special exception compared to the other objects and it's no surprise as he's who the player controls. All the objects are updated constantly (although not at times such as when the game is paused), but often the game must reference the Mario object like when Mario looses health due to hitting a baddy, so that's where the Mario object pointer is needed.
Usually a register is loaded with a pointer value from memory (RAM) and an offset is added to get at a variable or other data, the result of which is another address (this is very common when processing the objects). This is not to be confused with segment/offset addressing which although is sort of a pointer it isn't an actual address (which is calculated from the segment/offset value).
Functions
Functions are simply a group of instructions that perform a set task, anything from copying a value from place to another, displaying values on the screen, to spawning objects. Functions remove the need to repeat coding whenever a job needs to be done again, instead the function is called and thus the code exists only once in memory.
A function may need information about what it is supposed to do, for example, a function that dislays a message on the screen will need to know where the text is stored in memory and where it should appear on the screen. These parameters are passed to the function through the processor's registers although the function can also look at variables in memory which will treated as parameters.
Also, a function can return a value, in a register or a variable in the main memory (RAM). If you had a function that added two or more numbers the result would be the return value. But just as a function doesn't have to have input parameters it doesn't have to return a value.
Most function calls in MIPS assembler take on the form of a jal (jump and link) instruction such as jal 0x802523C8. The address of the function MUST be even and divisible by 4 (each instruction is 4 bytes long). When a function is called using jal, the return address is placed in the register ra. At the end of the function you will usually see jr ra so that the processor continues after where the function was called.
Delay slot
When you look at MIPS assembler you may become confused at the way branches and jumps are handled, thanks to what is known as the delay slot. If a branch is encountered, even if it isn't taken (the condition fails) or the processor comes across a function call (a jal), the following instruction will always be executed before the jumps occurs.
Let's look at an example for the NTSC (USA) version of SM64:
802E5780 lui a2, 0x1300
802E5784 addiu a2, a2, 0x3068 Yellow coin behaviour
802E5788 lw a0, 0x0020(sp) Get pointer to parent object
802E578C jal 0x8029EDCC Spawn object
802E5790 addiu a1, r0, 0x0074 Yellow coin GFX ID
The behaviour value of the yellow coin (0x13003068) to be spawned is loaded into register a2. The spawn function also needs two other parameters, one of which is a pointer to the parent object (the object whose behaviour spawns the object so that it can be positioned accordingly), which is what a0 is used for (the value was previously saved to the stack and is then retrieved). Lastly, the yellow coin GFX ID (0x0074) is loaded into a1 (note the use of r0, i.e. a1=0+0x0074), but the instruction is after the jal. Thanks to the delay slot, however, register a1 will contain the GFX ID value and then the spawn function will be called.
After the spawn function has finished, the MIPS processor will continue executing from address 0x802E5794. The addiu a1, r0, 0x0074 could have been placed before the jal but a nop (do nothing) would have to be placed after the jal, that is, in the delay slot.
The Mystery of The Mirror Room
1. It was easier at the time, especially as SM64 was an early N64 game.
2. Some things (such as paintings) musn't be reflected, so a surface reflection wouldn't work because it would (presumably) reflect everything.
3. Because Nintendo originally planned for Mario to go into the mirror world, if the DS remake is anything to go by (where you get a star).
Nevertheless, there is a certain strangness about the mirror world. To get past the mirror, you can move a door between the mirror or just alter Mario's position using a code. As can be seen in the picture below, the real Mario is on the right in the 'mirror' world where Lakitu appears as just a cloud.
Other information is that the mirror's only shiny on the real side and there is a black area beyond one of the mirror walls that could possibly have been used for the DS version star room.
Interesting, any change in Mario's graphics are mirrored perfectly which suggests to me that another playable character was likely for the original Super Mario 64, as in the DS version adds three playable characters. You can make Mario look like a door and his mirrored version will copy, and even the cap powers are 'reflected', again this can be seen in the DS version with Luigi or using a code in the N64 version.
The mystery of the Ü-solved!
What this means is that the Ü character isn't significant, there was likely to be a different character or symbol to be used instead; the fact that the variable and the associated code is in the NTSC game as well as the PAL game means it's an unused feature. So, there were plans to display up to 6 of the same symbols at the right of the screen but likely Nintendo realized that they got in the way too much.
So I worked out the code for the Japanese versions which, as can be seen below, reveal that it was to show how many keys you had collected, most likely the small key in Big Boo's Haunt. (As with the other versions of SM64 the display works for all levels.) The key colourful character is only in the Japanese versions, for the USA game it was removed and for the PAL version it was swapped with the Ü (although usually only used for normal text).
The Textures
What if you wanted, for example, to change Mario's eyes to those of Peach's or another object? That's actually easy to do if you remember that Mario and other objects appear to blink because the game cycles through different phases of the eyes, i.e. open, half closed, completely closed.
At the time, and for some while other, it was easy to use different textures to give the apperance that a character blinks or to show emotion. When Mario dies he has crosses over his eyes which is also simply a change of texture. In the case of SM64, both of Mario's eyes are a single texture so he wouldn't be able to shut just one eye.
If you're outside the castle and you want to swap Mario's eyes for Peach's then you first need to look for the texture commands for Mario's eyes:
FD10000004003090 (Mario's eyes open wide)
FD10000004003890 (Mario's eyes closed)
FD10000004003890 (Mario's eyes 3/4 shut)
See the end values change for each texture, those numbers 'point' to where the texture is located in memory (as a segment/offset value) so you need to change only them. When you have found them you need to change them to use Peach's eye textures (Peach actually has one more eye blink texture than Mario but that isn't used here):
FD10000005000A28 (Peach's eyes open wide)
FD10000005002228 (Peach's eyes closed)
FD10000005001A28 (Peach's eyes 3/4 shut)
Shame it doesn't quite work out and another problem is that Peach's graphic can only be accessed outside the castle. So if you wanted to totally change Mario's eyes to Peach's for all levels you'd have to find a way to load Peach's graphics all the time.
801C75C4: 0A000E40
801C75C8: 0A001AC0
801C75CC: 0A002740
801C75D4: 0A004040
801C75D8: 0A004CC0
801C75DC: 0A005940
The objects in detail
The Opening Movie
So, during the opening sequence Peach reads a letter to Mario inviting him over for some cake; there are some interesting points about what happens during that introduction.
* After Peach vanishes, the Peach object turns into the pipe Mario comes out of. Why they didn't use a different object for the pipe is a little strange but it may be due to the way objects are spawned.
Unused and Beta Graphics
Stored in the RAM there is always a list of pointers to the graphics structures for each object. This is so the game knows where the graphics are stored especially as some of the common graphics move about in memory from level to level. A few of these pointers are actually invalid (the game doesn't update the pointers for certain graphics) for some courses but as for the rest, the game alters the values to reflect the new position of the graphics from level to level, with the exception of the common graphics which always live at the same place in memory.
Let me make this clear by dividing the graphics into three types:
(1) The very common graphic objects such as the coins, stars and Mario are in all or most levels and live at the same place in memory, not far from the start of the RAM.
(2) The not so common graphic items are Goombas, bat, Bob-ombs and so on and are loaded into memory at a different position depending on the level. A lot of these objects are actually unused in some levels including the cannon and common baddies.
(3) Lastly is the more uncommon graphics that move about in memory from course to course and include beta and unsed objects such as Blarrg and (except in Hazy Maze Cave) the sea creature (Dorrie).
By checking each graphic pointer value you'll find some very familiar objects and some that weren't used in a particular level but there may have been plans to use them. And as for the common graphics, you can easily swap them so you could have a butterfly that looks like a star, for example, and the change will remain for all the levels that have those graphics.
Now I will tell you about the unused and beta graphics in each level, please be aware that if the graphics are available then so are the associated animations.
In Wet-dry world some of the unused graphics are Bullet Bill, a Yoshi egg and the owl. Also, there's a Thwomp, a small Cheep-cheep and the spike bomb we know from the Bowser fights (the spike bomb was to be used in at least one of the water levels as a mine but was removed as an actual object).
(pics to be added)
Now onto The Princess' secret slide where we find Lakitu the cameraman, Boo, and MIPS the rabbit (a bit dangerous to try and catch it in this level). Most strange is the wing cap switch; could the secret slide have been the original home for the cap button? Note, like a lot of objects in SM64, the main part of the switch and its bottom are separate graphic objects. A few other graphics are flyguy and very interesting, Toad.
(pics to be added)
Now for a strange graphic in the Tower Wing cap course: a solid red box. Not very interesting but maybe that's how the unactivated wing cap boxes would have looked like before Nintendo decided on the version we are more familiar with, either that or it is missing some textures perhaps.
(pics to be added)
Does this ring any bells-Bullet Bill, a Yoshi egg and owl-but in Tick Tock clock.
(pics to be added)
The Cheep-cheep fish graphic is in Jolly Roger Bay, the spike bomb and the green spider pond skater, probably as they belong to the water set of graphics.
(pics to be added)
And surprise, surprise the spike bomb is also available in Dire, Dire Docks, as well as the green spider and Chuk-ya.
(pics to be added)
The piranha plant and Whomp graphics are both loaded into memory when in Bob-omb Battlefield, possible they were to be used in that level or it may just be due to the course being similiar to Whomp's fortress.
(pics to be added)
In Cool, cool mountain I found the graphics of a small and large blue ice bully; you may remember the big ice bully from Snowman's land. What's strange is that there are two separate graphics when they could have just resized one of them. The only other find worthy of mention is the handbag baddy that can be found in Snowman's land but its graphics can also be used in Cool, cool mountain.
(pics to be added)
Who's the creature you'd least expect to see in Hazy Maze cave...the monkey! And another baddy from Tall, tall mountain whose graphic can be used in Hazy maze cave is that cloud with a face.
(pics to be added)
We know that a Blarrg creature was to be in Lethal Lava land and its gaphics have not been removed in the released game, he is joined by the sea creature (Dorrie) we know from Hazy Maze cave.
(pics to be added)
This was a shock to find-the Blarrg graphic-in the Wing Mario over the Rainbow level along with the cavern beast (Dorrie). There's a lava theme here as there is also the graphic of the bat (can be seen in Hazy maze cave but also available in Lethal lava land), and a small and big lava bully.
(pics to be added)
Onto The Secret Aquarium course there are water creatures and other objects used in the bigger water levels, such as the manta ray, eel and shark graphic. Two more unused graphcs in The Secret Aquarium are the Cheep-cheep and spike bomb.
(pics to be added)
Where else could there possibly be unused lava themed creatures-Bowser in the Fire sea! There is the Blarrg, big lava bully, bat and the Dorrie sea creature.
(pics to be added)
There is much mystery about Big Boo's haunt and these three items are no exceptions, they are a key quite different to the Bowser key, the sea creature (Dorrie) and the cage that is the same as the one you use to get to the ghost level. It seems that the key you would get from a Boo judging by a beta picture, possibly the key was to be used to get to the second floor of the ghost house.
(pics to be added)
There are several unused graphics in the Rainbow ride course which are Wiggler (who is split up into two parts) and the large Cheep-cheep like fish. Both of these objects we know from Tiny-huge Island so maybe Wiggler was to be found in Rainbow ride originally. But even Nintendo wouldn't have had that huge fish swimming about in the air so Rainbow ride or whatever it started out as could have had water in it.
(pics to be added)
In Tiny-huge island there are two unused graphics which are Chain-chomp and Whomp. Think about it, the Tiny-huge island course has the same music as Bob-omb Battlefield and similiar enemies.
(pics to be added)
The only unsed graphic in Snowman's land that's worth talking about is a small ice bully.
(pics to be added)
Here's two very eye opening graphics in Whomp's fortress, and they are the Yoshi egg and a wind-up baddy that we know from Tick tock clock. What is the connection between Wet-dry World, Tick tock clock and Whomp's fortress that all have the Yoshi egg?
Considering Whomp's fortress uses the Bob-omb battlefield music it may not be so much of a surprise to find graphics from that course which are Chain-chomp, and koopa with and without his shell. The wooden post is not so interesting but the Koopa flag is: was there to be a race to where you find King Whomp similiar to King Bob-omb in Bob-omb battlefield?
(pics to be added)
In Vanish Cap Under the Moat you can use some of the graphics from outside the castle: the pipe and green tree.The other graphics, such as Peach and the castle tower, crash the game if used despite their structures appearing valid (there must be other data missing). This may not be significant but it suggests that this course may have been quite different.
(pics to be added)
Now onto the courtyard with the Boos there are many unused graphics that crash the game if you try to use them and most curious is a white square that brought the game to a halt within seconds so I took the screenshot as quickly as I could. Along with the strange graphic is Toad who wouldn't look out of place except for those Boos in the way so perhaps that's why there are just signposts instead.
Considering that the cage is an unused graphic in Big Boo's haunt I should have expected to find some of Big Boo's haunt graphics unused in the courtyard. There is the small key, chair, piano and book baddies and the ordinary book.
(pics to be added)
In the Cavern of the Metal Cap where you activate the metal cap boxes, the unused graphics are those available in Hazy Maze Cave so they probably weren't intended to be used. But they can be used if you wanted to and a couple of them are the bat and the spider.
(pics to be added)
Water
Something that features in many of the courses is water and Wet-dry World is known for its adjustable water level. Here I show you what happens when you mess with the water by removing it and as for Wet-dry world, it's possble to flood it to a super level!
The position of the water switches in Wet-dry world do not affect how high or low the water level changes but there is a varible in the RAM that does set the water level. For the PAL game this variable is located at address 0x8032EDBA and for NTSC 0x8036118A. This variable has the value of 0x0400 when you enter the course (assuming a normal jump into the painting), 0x0028 for the lowest water level and 0x0A00 for the highest water level.
Now for removing the water in different levels and this can be done by setting the water pointer to null which lives at address 0x8032EDB4 for the PAL game and 0x80361184 for the NTSC version. If you disable the water in Tiny-huge island the killer fish continues to swim, but on the sand, and if he tries to eat Mario he will end up head first into the sand.
As for Hazy Maze Cave, getting rid of the water doesn't affect Dorrie who swims about normally and with no water in The Secret Aquarium you can walk about at the bottom and the fish swim as usual but also making it impossible to get the high up red coins (unless you had wing cap).
All content of this and related pages is copyright (c) James S. 2007-2009