Nintendo 64 console with EverDrive cartridge

Nintendo 64 Part 19: Developing for Multiple Regions

, Nintendo 64, Programming

PAL users deserve a larger framebuffer. What do I mean by that?

NTSC and PAL

The two most common standards for analogue terrestrial TV were NTSC and PAL. The reasons for their differences are steeped in history and make for good reading on Wikipedia, but the parts I care about are:

PAL variants of the Nintendo 64 produce the full 576i signal you would expect, and there are three ways that your Nintendo 64 program can make that happen.

  1. You can keep you 320×240 pixel framebuffer and put black bars at the top and bottom of the screen. Your game will look equally sharp on NTSC and PAL systems, but it will not fill the screen on PAL, and the image will not have a square aspect ratio on PAL.
  2. You can keep the 320×240 framebuffer and stretch the image out on PAL systems. The VI will interpolate between lines in the framebuffer to make this work (by default, the VI does this already which makes the image a little soft but reduces flicker). Your game will look mostly the same on NTSC and PAL systems, but it will be a little softer on PAL systems and it won’t use the resolution available to PAL.
  3. You can use a 320×288 framebuffer on PAL systems. This mode mode is called “FPAL” in the Nintendo 64 documentation. Your game will look equally sharp on both NTSC and PAL systems and will use the full screen on both, but the aspect ratio will be different and you may need different 2D assets for the PAL version.

Real games often used options #1 or #2 because they’re easy.

My thoughts are this: if the PAL systems are running at a slower framerate and you have 20% extra time per frame (1/50 s versus 1/60 s), but the framebuffer is also exactly 20% larger (288 lines versus 240 lines), then isn’t that just perfect?

Option #3 it is.

Cat in lap
Cat, not relevant to this post

Practical Considerations

3D is easy. All I have to do is set the correct aspect ratio in the projection matrix, and 3D graphics will appear on-screen with the correct proportions.

2D may require some additional thought. Images which appear on-screen may need to be stretched to match the different pixel aspect ratio that the Nintendo 64 “FPAL” (full-screen PAL) mode uses. I figure that some user interface elements can just look a little different on NTSC and PAL systems, but that that doesn’t apply to things like character portraits, which shouldn’t get squashed.

Memory could also be a problem, since the FPAL mode uses a 20% larger framebuffer. My plan is to allocate memory for an FPAL framebuffer in all game builds. This way, I won’t accidentally use the memory while testing on NTSC systems and then later discover that the PAL build is broken.

Building and Testing PAL

Hardware

I can’t test on PAL hardware because I don’t have a PAL Nintendo 64. In a hardware system, the system type (NTSC, PAL, or Brazil’s PAL-M) is fixed, and can be checked at run-time by examining the osTvType variable exposed by LibUltra.

CEN64

CEN64 is similar. The system type is fixed by the choice of PIF ROM, which is passed as an argument to the emulator. I had some difficulty acquiring the PAL versions of the PIF ROM. To make this easier for you, here are the checksums (MD5, SHA-1, and SHA-256) of the NTSC and PAL variants of the PIF ROM:

NTSC PIF ROM

PAL PIF ROM

Other Emulators

Mupen64Plus (and I suspect, many other emulators) automatically choose the system type based on the ROM header, which contains region information at offset 0x3c. From the En64: ROM page, I can see a list of region codes:

CodeRegion
7Beta
AAsian (NTSC)
BBrazilian
CChinese
DGerman
ENorth America
FFrench
GGateway 64 (NTSC)
HDutch
IItalian
JJapanese
KKorean
LGateway 64 (PAL)
NCanadian
PEuropean (basic spec.)
SSpanish
UAustralian
WScandinavian
XEuropean
YEuropean

I examined the header of an arbitrary PAL game for the Nintendo 64, and saw that it used the “P” region code, so I picked “P” for PAL. (Maybe “P” stands for PAL in the first place? Or does it stand for euroPe?) My NTSC build will use the “E” code for North America.

Mode Setting

In the end, I have two ROMs: an NTSC “E” region ROM and a PAL “P” region ROM. The two ROMs have identical code. The code is only compiled once, but copied into two ROM images with different headers.

The ROMs choose the mode by checking the osTvType variable:

OSViMode *mode;
switch (osTvType) {
case OS_TV_PAL:
  mode = &osViModeFpalLpn1;
  break;
default:
case OS_TV_NTSC:
  mode = &osViModeNtscLpn1;
  break;
case OS_TV_MPAL:
  mode = &osViModeMpalLpn1;
  break;
}
osViSetMode(mode);

I can figure out any potential differences with 2D assets later. For now, the ROMs are also given the exact same data. The main benefit—for the moment—is that I can run the PAL ROM in Mupen64Plus and it will automatically choose the correct region from the ROM header.

Test Program

I wrote a test program to see how emulators detect region.

TVType rev 236 64.6 kB

One ROM has the “E” region for NTSC, and the other has the “P” region for PAL. Here is what they look like when run in Mupen64Plus:

Test program running in NTSC
NTSC ROM
Test program running in PAL
PAL ROM

The test program draws a rectangle which is an equal number of pixels high and wide—this will show up as square on NTSC systems because the Nintendo 64 has a 1:1 pixel aspect ratio in NTSC video modes, and it will show up as a 1.2:1 ratio rectangle on PAL systems due to the increased vertical resolution.

These programs still detect the TV type using osTvType.