How to bypass the country-check protection of a Nintendo 64 game
Since I got some questions lately about what PALadin exactly does, I decided to write this doc (so I don't have to write it again and again ;) )
First thing you should know, is what country-check actually means.
While booting, the bootcode writes the kind of videosystem into a special address in the N64-Ram:
$80000300
This address is called osTvType and it's value is defined as follows:
#define OS_TV_PAL 0
#define OS_TV_NTSC 1
#define OS_TV_MPAL 2
That means, if your running a PAL-system, there's 0 (zero) written to $80000300.
The country-check just checks this value. If a ntsc-game doesn't finds 1 (OS_TV_NTSC), it won't start (sometimes displaying a msg about wrong video-system)
Usually a crack means killing all checks, but since there are several methods to read a value in asm, it takes some time to find them all (they could be encrypted/packed)
A much simpler way to kick the check is writing the expected value to osTvMode. Since this value is written only once in the bootup-procedure, it can be changed right after that when the execution of the real rom-code starts.
As you should already know (otherwise this whole info wouldn't help you much) the entry-point in RAM is stored in the header at $b0000008. The code beginning at $b0001000 (that's in the rom) is copied and execution continues there, after the boot-procedure is finished.
[The address itself is $1000. If we talk about an address in RAM we need to add $80000000 and if it's the ROM-address we have to add $b0000000]
Now, what does PALadin do?
Let's look into an example. This rom has it's entry-point at $80161600 and here's the original code:
$80161600 lui $t0, 8007
$80161604 addiu $t0, $t0, 8360
$80161608 addiu $t1, $zero, 2530
We don't care, what that code does. It's unimportant and we only need it to get the rom working again after we patched it.
PALadin inserts some code at the very end of the rom (hoping, there's no vital information stored ;) ) and replaces the code above with the following:
$80161600 lui $at, b0ff
$80161604 ori $at, $at, ffd8
$80161608 jr $at
You see that there are three lines changed
The first 2 instructions move $b0ffffd8 into the register $at. The next instructions jumps to the address stored in $at. $b0ffffd8 is the place, where PALadin has inserted his fixing-code (in this example!)
No let's move on to the code at the end of the rom:
$b0ffffd8 lui $t0, a000 ; $t1 = a0000000
$b0ffffdc ori $t1, $zero, 1 ; $t1 = 1 (1=NTSC, 0=PAL)
$b0ffffe0 sw $t1, 0300($t0) ; *a0000300 = $t1
Those 3 lines do the fix. To write to a ram-address we have to use $a0000300 instead of $80000300, because writing to $8xxxxxxx is always cached and it's not sure, that the cache is updated to ram when the first check of the address occurs.
This example is a PAL-Fix, that means we want the rom to "think" it's running on a NTSC-system. That's why we write OS_TV_NTSC to osTvType.
$b0ffffe4 lui $t0, 8007
$b0ffffe8 addiu $t0, $t0, 8360
$b0ffffec addiu $t1, $zero, 2530
Hmm..looks familiar...those are the 3 lines which have been overwritten at the entry of the rom. It's obvious that those lines have to be executed to get the rom working. So PALadin just copied them here.
$b0fffff0 lui $at, 8016
$b0fffff4 ori $at, $at, 160c
$b0fffff8 jr $at
$b0fffffc nop
This is the jump back to the entry-point right after PALadins first 3 instructions (no, we don't want them to be executed again).
This whole thing has one drawback: If the first 4 instructions of the entry look like:
$80161600 xxx
$80161604 lui $t1, 8360
$80161608 jr $t1
$8016160c addi $t1, $t1, fff8
PALadins fix won't work. You surely can find out yourself why not ;)
There's another possibility, which should always work. First the entry should be overwritten with 4 instr, the last one a simple NOP. That makes sure, that the jump always sux aeh succeeds
Instead of copying the 4 instr to the end we could just copy them back from the rom to ram and continue executing at the (now depatched and original) entry of the rom
Bullshit!
Of course we can't copy them back from rom, because they're not there ;) But we could copy them from where we stored it before (if we did). The advantage would be, that those instructions would be executed exactly where they would executed in the original rom - that would always work
Hmm...I think that's all I know it was to confusing :P
PS: Now you see why such a country-check-removing-only PAL-Fix doesn't help PAL-Only-Users. Even if the game would have an autodetection of the videomode and WOULD init PAL on PAL-systems, this fix forces them to NTSC. To make it playable on Non-Multi-TVs we need to patch the videotables (and sometimes the frequency of the sound) - but that's another story :)