Friday, May 7, 2010

Going in depth on N64's country check system.

Heres another text file from the old N64 scene days that I thought was very informative:).

Fixing-Doc - Part 1.1

by Hotblack/Dextrose 1999

Uh oh...first doc and immediately wrong :(
I kicked the wrong part about back-copying original code from rom
But since I heard that no one can follow my explanations - who cares anyway :)

The Country-Check

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:


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 entrypoint 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 roentry 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 possibillity, 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

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

Any suggestions, corrections or flames to
(well flames please to ;) )

Hotblack :)

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 :)

Original text file can be found here

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.