Q&A- Controller Pak

QA1 How can you distinguish between damage to the Controller Pak and insertion of the Rumble Pak?
QA2 The number of characters in game titles in the Controller Pak Menu.
QA3 Identity of Controller Pak after Rumble Pak.
QA4 Every time I call osPfsInitPak() to initialize, the error PFS_ERR_CONTFAIL is returned.
QA5 How can I intentionally destroy the ID area of the Controller Pak?
QA6 How do I find the serial number?
QA7 Does the Controller Pak Menu have to use the specified nosPak?
QA8 What do the company code and the game code do?
QA9 I can't restore the Controller Pak.
QA10 When is PFS_ERR_NEW_PACK returned?
QA11 I can't access the 64GB Pak.
QA12 Will the motor absolutely stop on the third osMotrStop()?
QA13 Is a prompt necessary when only the Rumble Pak is being used?
QA14 How do I get a broken Controller Pak? (199906)
QA15 Is it taking too long to process the osMotorInit function? (199907)
QA16 Repairing Controller Paks whose batteries have been removed. (199911)
QA17 Are the register area specifications in the GB ROM different overseas? (200001)
QA18 How do I get an English version of the Controller Pak menu? (199912)
QA19 Data registration area of the overseas Game Boy. (200003)
QA20 Using different controllers. (200003)

Q1 When the error code, "PFS_ERR_ID_FATAL" is returned, (when I call osPfsInitPak while initializing the Controller Pak) how can I tell if the ID area has been destroyed or if a Rumble Pak has been inserted?

A1 Since OS2.0i Patch 5, PFS_ERR_ID_FATAL will be returned only when the ID area has been destroyed, while PFS_ERR_DEVICE will be returned if any Pak other than a Controller Pak is inserted.

Regardless of the OS version, the only way to tell if a Rumble Pak has been inserted is to execute osMotorInit and see if an error is returned.

Generally speaking, since there are no functions which find which kind of Pak has been inserted, this has to be determined by running the various initialization routines for those devices which will be used by the game.


Q2 We are currently involved in localization work to sell overseas Nintendo 64 software domestically (in Japan). We have encountered a problem with the current layout of the Controller Pak menu in which 16 characters cannot be displayed for game titles.

In the original overseas version, game titles of other manufacturers are processed as "OTHER GAME", without a space to attach an extension. Therefore, is it acceptable to list (for example, in the case of Mah Jong Master (10 characters in Japanese)) "Mah Jong Ma~" (8 characters in Japanese) and chop off the remaining characters which can't be displayed, representing them with a "~"?

A2 The following items are listed in the Programming Cautions:

>10-8 Normalize the display items in the Pak Menu (Required)
>When the Controller Pak menu is started, display a list of 
>the game notes titles, game notes extension, the number of 
>pages used, and the blank pages.

If this is not followed, it will result in a NG in the lot check.

While it is superfluous, rather than displaying OTHER GAME for the software titles of other companies in overseas versions, display the notes titles. However, since there probably isn't a katakana font in the overseas versions when a katakana note title is entered, OTHER GAME may as well be displayed.

Q3 I am developing software which is compatible with both the Controller Pak and the Rumble Pak. Data are initially loaded with the Controller Pak, the game is played with the Rumble Pak, and then I'd like to have the data saved again with the Controller Pak. However, since this would occur after inserting the Rumble Pak, it seems that I will have to execute osPfsInitPak(). If this is the case, it seems that if the Pfs structure is initialized, it will be impossible to distinguish between the Controller Pak before and after. Is this the case? Do I have any options?

A3 When inserting and removing the Controller Pak and the Rumble Pak, it is necessary to initialize with osPfsInitPak()

As for the Controller Pak, just because the ID, for example, is the same, does not mean it is the same Controller Pak. The Controller Pak is identified by checking the contents (where the individual ID is written) of the Controller Pak.


Q4 Every time I call osPfsInitPak() to initialize, PFS_ERR_CONTFAIL is returned.

A4 Check the connections for the base Controller Pak. (Check the insertion location for debris, dirty contacts, etc.)

See if a test program, such as nosPak in demos, will run properly. If there is a problem with this, there is probably a hardware problem.

If things seem to be running properly, there is probably a mistake in your code.


Q5 I would like to run a check for when the ID area of the Controller Pak has been destroyed, but how would I create a Controller Pak whose ID area has been destroyed?

A5 There is currently a program being distributed at NTSC-ONLINE which destroys the ID area of the Controller Pak. Download it and use it.

While it is not recommended, if you would like to write your own program, you may do the following.

There is an internal function in the OS called osContRamWrite(). You can use this function to write data to any area of the Controller Pak. A Controller Pak with a destroyed ID area can be created by destroying the first page of data with this function.

Following is the function specification for _osContRamWrite() (and the function to read it _osCountRamRead()).

Note: This function is an internal function of the OS. Its use for anything other than debugging is prohibited.

Function Name
        __osContRamRead  - Reads 32 bytes from the Controller Pak
        __osContRamWrite - Writes 32 bytes to the Controller Pak

        #include <ultra64.h>
        extern s32 __osContRamRead(OSMesgQueue *, int, u16, u8 *);
        extern s32 __osContRamWrite(OSMesgQueue *, int, u16, u8 *, int);

        s32 __osContRamRead(OSMesgQueue *mq, int channel, u16 address,
                u8 *buffer);

        s32 __osContRamWrite(OSMesgQueue *mq, int channel, u16 address,
                u8 *buffer, int force);

        The __osContRamRead function is for reading 32 bytes of data from the Controller Pak.  The
_osContRamWrite function is for writing 32 bytes of data to the Controller Pak.  *buffer indicates the buffer for reading/writing data.  Its size must be 32 bytes or greater.  channel specifies the port (0~3) of the Controller. 

address is the value shifted 5 bits to the right of the address of the Controller Pak.  An example is shown below. 

          address       CONTROLLER PAK real address
                0               0x0000 - 0x001f
                1               0x0020 - 0x003f
                2               0x0040 - 0x005f
                .                      .
                .                      .
                .                      .
                .                      .
siMessageQ is the message queue initialized in association with OS_EVENT_SI.  See osSetEventMesg(3P) for how to set up this association. 

force is the forced write flag.  When this value is 0 [zero], nothing will be written to the system area of the controller.  If 1 is specified, you can write to any area. 

osContInit(3P) must be called before calling
__osContRamRead or __osContRamWrite.  This for internal initialization of the OS.  

A 0 [zero] will be returned as the return value if the function ends normally.  One of the following errors will be returned if this is not the case. 

A Controller Pak is not inserted

A new Controller Pak has been inserted

Controller data transfer failure

        #define   CONTNO    0
          OSMesgQueue      intMesgQueue;
          OSMesg           intMesgBuf[1];
          OSContStatus     sdata[MAXCONTROLLERS];
          u8               cont_pattern, pak_pattern;
          OSPfs            pfs[MAXCONTROLLERS];
          int              i;
          u8               buffer[256];
          u8               *addr;

          osCreateMesgQueue(&intMesgQueue, intMesgBuf, 1);
          osSetEventMesg(OS_EVENT_SI, &intMesgQueue, dummyMessage);
          osContInit(&intMesgQueue, &cont_pattern, &sdata[0]);

          addr = buffer;
          for(i = 0 ; i < 8 ; i ++, addr+=32) {  /* 32 * 8 = 256 Bytes */
            if  ((ret = __osContRamRead(&intMessageQ, CONTNO, i,
                                addr)) != 0) {
            osSyncPrintf("Read Error in address %4x\n", i*32);
          for (i = 0 ; i < 256 ; i ++) {
            osSyncPrintf("%2x ", buffer[i]);


Q6 Can I get the Controller Pak serial number from the application side?

A6 There is no function for getting the serial number in a form that can be incorporated into the game application.


Q7 Does the Controller Pak menu have to use the nosPak in the OS?

A7 If the Controller Pak menu has the identical function as nosPak, you may create your own. Fonts and graphics are not specified.

As long as the game can be started by pressing RESET while holding down the START button, you may also use any other starting methods.


Q8 What procedure should be used to obtain the "company code" and the "game code" for writing to the Controller Pak?

A8 The company code is a two-digit code assigned to your company. We will provide you with a company code the first time you create software for our hardware.

The game code is a 4-digit game original code which is registered in the "N64 Software Specification Sheet" which we will provide after you have entered into a contract with us.

The term "game code" is used in the manuals, but "initial code" is the official term, and "initial code" is used in the Master ROM Submission Checklist.


Q9 Problems occur during Controller Pak recovery.


Call the above initialization functions using the variables for the same OSPfs structure. During recovery, after waiting for the next button to be pressed, osPfsRepairId() is called. The same OSPfs variables are used here as well. At this time, PFS_ERR_INVALID is returned as the return value and the recovery is not completed.

A9 To execute a Controller Pak recovery, it is necessary to use the OSPfs structure which was initialized with osPfsInitPak(). PFS_ERR_INVALID will be returned after using any other initialization function (osMotorInit(), osGbpakInit()).


Q10 When the following kind of sequence is performed, PFS_ERR_NEW_PACK is not returned when osPfsInitPak() is called. Shouldn't PFS_ERR_NEW_PACK be returned in this case?

  1. osContInit()
  2. osPfsInitPak()
  3. osContGetQuery() until CONT_CARD_PULL is returned
  4. osContGetQuery() until CONT_CARD_ON is returned
  5. osPfsInitPak()

In addition, PFS_ERR_NEW_PACK is returned if osPfsFreeBlocks(), etc., is called instead of osPfsInitPak(). Is this due to a difference in NEW_PACK determination methods?

A10 osPfsInitPak() performs the initial read of the Controller Pak ID. PFS_ERROR_NEW_PACK will be returned if the Controllers' tasks are CONT_CARD_ON=1 and CONT_CARD_PULL=1 during this read processing.

Since the CONT_CARD_PULL flag is set to 0 by osContGetQuery() in the sequence in your question, PFS_ERROR_NEW_PACK would not be returned by osPfsInitPak().

The NEW_PACK criteria are slightly different for osPfsFreeBlocks(). The initial read of the Controller Pak ID is the same, but instead of returning a NEW_PACK error when the status is CONT_CARD_ON=1 and CONT_CARD_PULL=1, the ID is simply read again. The ID value during this read is compared with the ID value read when osPfsInitPak() was called (the value in the pfs structure of the argument), and PFS_ERROR_NEW_PACK is returned if they are different.

If osPfsFreeBlocks() is used instead of osPfsInitPak(), you may think that you will be able to use PFS_ERR_NEW_PACK to determine if the Controller Pak has been replaced with a different one. However, since the same ID does not necessarily mean that the Controller Pak is the same, be sure to execute osPfsInitPak() at the timing of 5, above. Determination of whether or not the pak is the same must be done in the contents of the file.


Q11 I can't access the N64 Pak.

A11 Operation will become strange if another thread is accessing an SI device, such as the Controller. Consequently, exclusive control is necessary. This is the same for other SI device function, such the Rumble Pak functions.


Q12 The Rumble Pak precautions state to

"Execute osMotorStop() 3 consecutive times to turn the motor OFF."

but isn't it possible that the motor won't turn off even if you execute osMotorStop() 3 times?

A12 Contact defects develop in the connectors due to vibrations, and the motor frequently won't stop even if osMotorStop is executed once. It won't cause any problems to execute the function 3 times, but it may not stop the motor with 100% certainty.


Q13 Is the message "Insert the Rumble Pak at this time..." required when other Paks are used together with a Rumble Pak necessary when only the Rumble Pak is being used?

A13 It is not necessary. Of course, having the message won't cause any problems either.


Q14 I would like to get hold of a broken Controller Pak so that I can check programs when a broken Controller Pak is inserted. What should I do to get one?

A14 You can break the content of a Controller Pak with software called "pakfatal" on the Developer's Kit CD.

It is located in n64kit/misc/pakfatal.


Q15 It takes as long as 7 ms for osMotorInit to process. Is that normal?

On single-frame games with multiple Rumble Paks, I may be losing a key when I run osMotorInit repeatedly during a game.

A15 About 7 ms is normal.

When running osMotorInit on multiple Rumble Paks, please set it so that the process takes place once for each frame.


Q16 When I call the osPfsInitPak function with a Controller Pak inserted and the batteries removed, I get a PFS_ERR_ID_FATAL message. Thus, when I initialized using osPfsRepairId, the returned value becomes 0, the fix is considered successful and the program goes into operation. Is it acceptable to run the osPfsInitPak a second time (after fixing it) and check the returned value in order to avoid this?

A16 We assume that you tried removing the batteries in order to test the "broken Controller Pak." However, there is no way to detect a Pak without batteries or a Pak with dead batteries, so we don't perform tests using these types of Paks even when we perform lot checks.

If you want to test a Pak in a broken state, please use the utility in /n64kit/misc/pakfatal/ to break the Pak data.


Q17 I am localizing software to North American specifications that was released in Japan and, for software, I refer to the Company Code and the Game Code on the GB Game Pak using the N64 Transfer Pak. When running the same specifications as an overseas edition, is the data in the register areas of the overseas edition of the GB the same as the Japanese one?

A17 The specifications of the data registered in the ROM are the same all over the world. Naturally, even for the same game, if the manufacturers are different in North America and Japan, the Company Code is going to be different too. The Game Code is also going to be different if there is any sort of localization.


Q18 I am localizing software for the US that was developed in Japan and I heard that the English and Japanese Controller Pak menu libraries are different. Where can I get those libraries?

A18 If you are going to be using the library inside the nospak sample which is under demos, both the English and Japanese versions are in the directory, lib(if you are building nospak, you can have a nospak.a and a nospak_jpn.a) so when localizing, please change the linking libraries.

If using one of the Pak Menus developed by your company without relying on nospak, even if there are files with katakana names, display the file names as "-----", as if you were using nospak.a. Make sure that the katakana is not displayed and that the lettering is not corrupted.


Q19 I am localizing software for Japan that was released in the U.S. The software uses N64 Transfer Pak to refer to the Company Code and Game Code for the Game Boy Game Pak. Similar specifications will be implemented for overseas versions. Is the data in the registration area of oversees Game Boy the same as the Japanese one?

A19 The specifications of ROM registration data are universal throught the world. Of course, even the same game could have different Company Codes if the U.S. and Japan have different manufacturers. The Game Code could be different if some localization is done.


Q20 When I inserted the Fishing Controller (only available in Japan) into the port and called os ContInit() the value {type=5,status=1,errno=0} is returned to the osContStatus type structure. Because the same value is returned from a standard controller as well, it is impossible to distinguish between the two values. I would like for a warning to be displayed if the fishing controller is used. Is it possible, or is such a warning unnecessary?

A20 As you said, it is impossible to distinguish when os ContInit() is called. Since it has a clear purpose, it is assumed the fishing controller will not be substituded for the standard controller. Hence, a warning is not necessary. The same applies to the Master Controller for "Densha de go!" for N64 (only available in Japan). You need to contact us if you plan to use it intentionally.