Fixing the Race Drivin' Y2K Bug in Version 2.4         Jed Margolin  7/12/02

Hard Drivin'/Race Drivin' Y2K Problem

Although Max and Stephanie were the Game Programmers and  I was the Hardware Engineer, I wrote most of the Self-Test code, including the code for the 48T02 TimeKeeper.

Like many programmers in the early 1980s I was not thinking about the Y2K problem, so I simply tacked '19' before the year. I also restricted the year adjustment to 88-99.

I wasn't the only one who wasn't thinking about Y2K. The 48T02 does not have a Century register. If fact, TimeKeepers did not have a Century register until 1997. This applied to newly designed (larger) TimeKeepers only. The 48T02 was not redesigned. The Application Note (AN923) dealing with the Y2K problem was not issued until May 2000. (Good work, guys.).

(I did the original code for the TimeKeeper around 1984, for TomCat.)

The current data sheet for the M48T02 as well as Application Note 923 are available at the ST Microelectronics Web site ( . However, they do not make it easy to find the datasheets so I am posting them here as well. (48t02.pdf and an923.pdf)

More information about the TimeKeeper (like what to do when its internal battery dies) is contained in the article TimeKeeper and ZeroPower RAMs.

The following discussion applies to the final version of Race Drivin' Cockpit, which reports Version 2.4 in Self-Test.


I have the source code I wrote for the clock module used in Race Drivin' but no program listing so I reassembled it in order to compare it with the ROM code. The PC based 68010 assembler that I have does not work exactly the same as the one I used on the VAX, so that the addresses produced by the newly assembled clock file do not always exactly match the addresses in the ROM.  If you are interested, here is why.

The addresses in the ROM are, by definition, the real ones. Note that the 68010 has a 16 bit data bus which is why the ROMs are paired up and why it was necessary to combine (interleave) 77_5001.bin and 77_5002.bin .

Change Year Wrapping from xx88 - xx99 to xx00 - xx99:

From the newly assembled clock source file, this is the table entry for wrapping the year. It causes the year to wrap from xx88-xx99.

330    00008086 FFFF 4FFE              DC.L YEAR
331    0000808A 00FF 0088 0099         DC.W $0FF,$88,$99
333                               * D0.W contains the index number
334                               TSETINC:
335    00008090 40E7                   MOVE.W SR,-(A7)  * Save IMask

From the merged filed made from  77_5002.bin and 77_5001.bin:

8080:  00 01 00 31 ff ff 4f fe 00 ff 00 88 00 99 40 e7


The lower limit (88) is at location $808B in the merged pair. Therefore, change it to $00 (This will allow a year range from xx00 - xx99).

The upper limit (99) is at location $808D in the merged pair. It does not need to be changed.

Note: The addresses are out of sync between the listing and the ROMs.

In going from addresses in the merged pair back to the individual ROMs, odd addresses in the merged file are in 77_5001.bin and even addresses are in 77_5002.bin .

In ROM 77_5001.bin:

$808B/2 = $4045 ($808B is odd )
$808D/2 = $4046 ($808D is odd)

4040:  01 31 ff fe ff 88 99 e7 fc 00 79 60 08 79 60 1a

Therefore, in ROM 77_5001.bin, change address $4045 from $88 to $00

Unfortunately, this isn't enough, and will break the year-setting code because of the signs of the two limit numbers. When both limits are the same sign the code works properly. (In byte operations $88 and $99 can both be considered negative because the high bit is set.)

In the code that increments the count in TSETINC:

348   000080B6 2652                MOVE.L (A2),A3   * Get parameter
349   000080B8 1013                MOVE.B (A3),D0
350   000080BA C102                ABCD D2,D0
352   000080BC B02A 0009           CMP.B 9(A2),D0   * Compare to High Wrap
353   000080C0 6F00 0006           BLE TSLP1        * Overflow?
354                         * Yes
355   000080C4 102A 0007           MOVE.B 7(A2),D0  * Make it wrap
357                         * Mask the data
358   000080C8 322A 0004    TSLP1  MOVE.W 4(A2),D1  * Get the Bit

Line 353 should do a BLS  TSLP1  (Branch on Lower or Same). If you want to know more you can look it up in the 68K programmer's manual.

From the merged file of 77_ 5002.bin and 77_5001.bin:

80b0: 14 3c 00 01 26 52 10 13 c1 02 b0 2a 00 09 6f 00
80c0: 00 06 10 2a 00 07 32 2a 00 04 c0 01 46 41 c2 13

We want to change 80BE from $6F (BLE) to $63 (BLS).

This is in 77_5002.bin at address $80BE/2 = $405F ($80BE is even):

4050: 45 00 80 c0 00 d4 02 00 14 00 26 10 c1 b0 00 6f
4060: 00 10 00 32 00 c0 46 c2 80 00 00 ff 4f 16 02 00

Therefore, in ROM 77_5002.bin, change address $405F from $6F to $63 .

This lets us increment the years from 00 - 99 but still leaves us with a bug in the TSETDEC code that prevents Decrement Year from decrementing below 99. It also causes decrements between the years 80 - 99 to go to 99.

It does this because $80 - $99 are negative numbers and we are comparing it to a positive number ($00).

There are two ways to fix it.

1. Extend all arithmetic and compares to operate on word lengths, which would require more code and would not fit in the existing space. Although there is space at the end of the ROMs a number of locations would have to be patched to point to the new code and the new code would have to point to the correct references in the existing code.

2. Do a separate subroutine to decrement the years. This would be the same as TSETDEC but without the compare and the  two instructions after it. This is because the BCD adds and subtracts already wrap the values between 0 and 99. There would be fewer locations to patch to point to the new code.

Considering the amount of work involved, and since you can still get to any year by incrementing, my official recommendation is that if you really need to change the year alot you connect a low-force pushbutton switch in parallel with the Ignition Switch.

Century: Change 19xx to 20xx

From the newly assembled clock source file, this tacks '19' before the year.

670          0000840A 123C 0031            MOVE.B #'1',D1     * 19
671          0000840E 4EB9 0000 0000  E    JSR HAMMER
672          00008414 123C 0039            MOVE.B #'9',D1
673          00008418 4EB9 0000 0000  E    JSR HAMMER

From the merged file of 77_5002.bin and 77_5001.bin:

8400: 00 2c 4e b9 00 00 31 38 12 3c 00 31 4e b9 00 00

8410: 31 38 12 3c 00 39 4e b9 00 00 31 38 12 39 ff ff

Address $840B is the ASCII for '1'  ($31) so change it to '2' ($32).
Address $8415 is the ASCII for '9'  ($39) so change to '0' ($30).

Note: The addresses are out of sync between the listing and the ROMs.
          The 'E' on listing lines 671 and 673 mean External Reference. (It was resolved to $00003138.)

In ROM 77_5001.bin:

$840B/2 = $4205 ($840B is odd)

4200: 2c b9 00 38 3c 31 b9 00 38 3c 39 b9 00 38 39 ff

Therefore, change $4205 from $31 to $32

$8415/2 = $420A ($8415 is odd)

4200: 2c b9 00 38 3c 31 b9 00 38 3c 39 b9 00 38 39 ff

Therefore, change $420A from $39 to $30

Summary of Changes

In ROM 77_5001.bin:

      Change location $4045 from $88 to $00 (changes the year wrap from  xx88 - xx99 to xx00 - xx99)

      Change location $4205 from $31 to $32  ('1' to '2')

      Change location $420A from $39 to $30  ('9' to '0')

     Change  location $FFFF from $00 to $90 (Makes the checksum $5D01).

Label your new EPROM 77_6001.bin to avoid confusion with the original one.

In ROM 77_5002.bin:

    Change address $405F from $6F to $63 .

    Change address $FFFF from $00 to $0C (Makes the checksum $F402).

Label your new EPROM 77_6002.bin to avoid confusion with the original one.

The complete subroutines involved are listed here.

What if you have a different version, like the original Hard Drivin', or if you have a Compact?

The code in this part of Self-Test is the same although it will probably be at a different address.

The method used to find the code is explained here.

Now we will discuss what EPROMs to use.

The Main Board EPROMs used in the game are 27C512-200 (200 ns.).

Faster parts should work fine.

It should also be possible to use Flash EPROMs like the AT29C512 and the AT49F512.

The 'AT' means it is made by Atmel. ( Other manufacturers also make them.

There is a small problem, however.  The 27C512 used in the game has 28 pins, while the 29C512 and 49F512 have 32 pins.

If you install a 29C512 into a 27C512 socket with pins 16 and 17 of the 29C512 in pins 14 and 15 of the 27C512, all the address and data lines will be correct, as will the Chip Enable (/CE) and Output Enable (/OE).

That leaves pins 1,2,31, and 32.

Pins 1 and 2 are not connected (NC) in the chip.

Pin 32 needs +5V. Pin 31 is the Write Enable (/WE) and needs to be tied high. (+5V is good.)

Pin 30 is conveniently left NC, so plugging it into a 27C512 socket will put +5V on it which is ok.

So all we need to do is connect +5V to pins 31 and 32.

The best way to do it is to use a 32 pin IC socket (one with stamped pins). Bend pins 31 and 32 at right angles so it doesn't short to anything on the board, and use a small bare wire (like bare wirewrap wire) to connect pins 30, 31, and 32. When you connect it to pin 30 make sure the pin will still be able to plug into a socket.

That's because we want to plug this 32 pin socket into the 28 pin socket on the board with pins 1,2,31,32 hanging out. Then plug the 29C512 into the  32 pin socket.

The same procedure applies to using the 49F512.

Using Flash EPROMs has the advantage that you do not need an EPROM eraser. It also means you do not have to wait 20-30 minutes to erase them if the need should arise. You just pop them into the Device Programmer and reprogram them.

Naturally, you can still use 27C512s if that's what you have.

In any event, I strongly advise you to keep the original 27C512s.

That brings up another issue.

EPROMs are only guaranteed to hold the data for 10 years. Hard Drivin' was produced in 1989; Race Drivin' in 1991. Do the math. (The way EPROMs work is discussed in the article  EPROMS .)

As long as you are working on the game you should think about making a backup of all of the EPROMs on all of the boards.

There is some risk, however. When you are putting the EPROMs back in the sockets it is easy to bend a pin without knowing it. (You will find it out when the game doesn't  work.) If you mix up the EPROMs and put them in the wrong sockets you will find that out, too.

Fortunately, as long as 5001 and 5002 are installed correctly you can use Self-Test to look at the ROM checksums. The last two digits should match the last two digits on the ROM part number. For example, ROM 136077-5001 located at 210R has a checksum of $5D01 . ROM 136077-5002 located at 200R has a checksum of $F402. This was not an accident. I made everyone do it.

In any event, if you decide to make copies of your EPROMs, don't do it when you're tired.

The datasheets for the EPROMs are available at the Atmel Web site ( You can also download them here.

AT29C512 Flash EPROM

When I designed the MultiSync II Main Board, I put in a number of split pads so that it could be configured to use EPROM, Flash EPROM, or SRAM.

By then, most of the program development was done on PCs. Since emulation memory for the Applied Microsystems emulator was expensive and the emulator didn't care where the memory lived, it worked out really well. (Race Drivin' had an auxiliary RAM board for this purpose.)

I made an interface board for the Race Drivin' system with an ADSP-2101 so its fast serial port could be used to download the program from a PC. The PC used an ISA board designed by Matt Kendall and also had an ADSP-2101.

It was enormously faster than using the emulator's RS232 port, especially when the emulator was used with the VAX.

As far as I know, the only project to use the MultiSync II board was the Police Trainer. Each Police Trainer unit had the fast interface board so it allowed a number of them to be connected together. (Race Drivin' uses its onboard RS232 port and you can only link two games together.)

Several years after I left Atari I heard that the Police Trainer project had been sold to a company that was in the Police Trainer business, and that they were still using my hardware. I can't imagine that they are still using it today, but who knows.

Maybe they would like their Y2K bug fixed.

And finally, with these patches the Race Drivin' TimeKeeper is good until the year 2100.

After that, even if the Century Year is repatched to 21, the TimeKeeper itself will screw up leap years.

I wonder if there will be any Race Drivin' games working in the year 2100.

I wonder if the MAME version will be finished by them?  :-)

Jed Margolin
San Jose, CA
July 12, 2002        Revised: 7/18/02

While I believe this information is accurate and I have tested it in my own game I cannot assume any responsibility for its use.

Please send comments here