CD64 Mods, Part 2

Was hoping to post this earlier, but anyway... I traced the CD64's expansion connector. It's definitely one of the simplest I've ever seen for the number of pins. A diagram is available here but unfortunately many programs can't render SVG flowed text correctly. This version has the text converted to paths, so it will show up properly in most programs, but it's also much larger (1.1MB) and not easy to edit.

This connector is interesting, as it connects directly to the bus, meaning all ROM access shows up here. There is no "enable" pin (nor high address pins) that can be used to tell whether the access is actually intended for the connected device (CD64 is in an appropriate mode and address is in the correct range). Pulling the data lines low will cause that bit to read 0, no matter what the address, so it will corrupt reads/writes to other sources, and blindly listening to these pins would also cause your device to respond to accesses intended for other things.

The only safe way to use this connector would be for your device to listen for a series of writes as an "enable" signal, and hope no game happens to trigger it by accident. Alternatively, patching into the high address lines on the cartridge bus would allow you to tell if the address is actually in the range reserved for this connector, but it wouldn't tell you the CD64 mode (unless you listened for those writes too), and different modes actually assign different ranges.

A remote possibility is that there's a way from software to control the +5VDC pins on this port, so the device isn't powered on until the system is ready. However I see no evidence to support this theory.

Pin 38 is interesting; it may have been intended to allow the device to access the third flash ROM when there is no other bus activity. Currently this chip stores Gameshark ("X-Terminator") codes, but it may have been intended for boot code or resources for the MPEG decoder that would have connected here.

The address pins keep their state after each access, while the data pins are at +3V whenever no access is occurring. I can't tell for sure with just a multimeter, but it looks like high=0 on the data lines, whereas high=1 on the address lines.

Since the bus is 16-bit, there is no A0 pin. Byte access returns only the high 8 bits; word access probably gets split into two halfword reads/writes.

The expansion connector is mapped to 0xB1xxxxxx (and sometimes 0xB0xxxxxx; see mode chart below). Beware that games' exception handlers will usually trigger and consider the game to have crashed if you perform any unaligned access.

I also dug up some other interesting information:

The disc read code is fussy about ROM size. If the ROM is not a multiple of some unknown size, it won't appear in the list. 13,107,200 bytes (12.5MB) works, 13,107,201 does not. Keep this in mind if you want to add on to the end of a ROM.

The CD64 enable register (0xB780000C) has an unknown quirk. Normally you write 0x0A to this address (as a word; the high 3 bytes are ignored) to enable the CD64 registers. Early versions of my test program did this immediately before setting the mode (0xB7800000) and the result was inconsistent behaviour, as if sometimes the mode wasn't changed. Setting it only once at the beginning of the program solved this problem. This could mean you must wait some time after enabling before using the registers, or that writing a second time disables it - obviously there needs to be some way to disable the registers before starting a game.

The third flash ROM, which currently stores Gameshark codes, is mapped to 0xB7000000. To read it, read a word and discard the high byte of each halfword, e.g.:
LUI $A0, 0xB700
LW $A1, xxxx($A0)
SLL $T0, $A1, 8
ANDI $T0, $T0, 0xFF00 ;first byte
ANDI $T1, $A1, 0xFF ;second byte
OR $A0, $T0, $T1
tmp = word[x]
byte1 = (tmp >> 16) & 0xFF
byte2 = tmp & 0xFF
data = (byte1 << 8) | byte2

The chip is an SST-29EE010 (128KB capacity). Writing would most likely follow the same method, placing a 16-bit payload in those two bytes. Accessing individual bytes (as halfwords) should also work the same.

The CD64 website documents some of the modes, but not all. The entire map appears to be:

Mode B0B1B2B3 B4B5B6B7
0 CD64 BIOS Expansion port Cartridge DRAM (R/W) CD64 BIOS X-Terminator & I/O
1 CD64 BIOS Expansion port Cartridge DRAM (R/W) CD64 BIOS X-Terminator & I/O
2 Expansion port Cartridge DRAM (R/W) BIOS/Expansion port
3 Expansion port Cartridge DRAM (R/W) BIOS/Expansion port
4 DRAM (read-only) Expansion port Cartridge BIOS/Expansion port
5 DRAM (read-only)
6 DRAM (read-only)
7 Cartridge

It's possible to switch out of any mode, but no modes allow writing beyond the first 32MB of DRAM, hence the ROM size limit. If I could find a 64MB module, it might be possible to defeat this limit by simply manually operating the write line and/or highest address line of the DRAM (which could then be connected to a pin on the expansion port and done automatically in software). Of course reprogramming the CPLD would be a better way, but having no method to do so (nor to even back it up) and no experience with CPLDs, I can't try this yet.

In mode 4 the 32MB DRAM is mirrored at B2 and B3, but this is probably because it's only 32MB; I suspect with a larger module all 64MB would be readable here.

In mode 5 (and 6) again the 32MB is mirrored across the entire range, but this would probably change if you installed a larger module. In theory up to 128MB is usable if you can write to it somehow.

Reading past the end of cartridge ROM or BIOS reads open bus; the result will be the low word of the address repeated for the entire word. Addresses above 0xB7xxxxxx are also open bus.

"BIOS/Expansion port" means the high 16 bits of each word will come from the expansion port and the low 16 will come from the BIOS. This isn't terribly useful since you can only read every other halfword of the BIOS (unaligned access throws an exception). 0xB7xxxxxx reads the X-Terminator chip instead of the BIOS (since BIOS is mapped to 0xB6xxxxxx and XT is mapped to 0xB7xxxxxx); in other words, in this range one halfword comes from the same place as it would in mode 0 and the other comes from the expansion port.

The parallel port adaptor (whose circuit diagram is on the CD64 website) contains some buffers and latches to make the port easier to use.

When you write a word to 0xB78xxx84 the low byte of that word is output to the data lines. They do not retain their state; when not being written, they read 0V (logical zero). For input, read a word from 0xB78xxx80; the state of the data lines is found in the low byte (+3VDC=1, 0V or disconnected=0). Thus, the adaptor adds latches to keep the last state written so the other end can read it without having to be in perfect lock-step (or having to run big slow loops).

There are still some things I want to try with this hardware. First I want to build this adaptor and dump the three flash ROMs. Then I'd like to play with the audio input port, look up documents and see if it has to be enabled in software or just given an input.

I'll also want to research how one goes about communicating with various IDE devices and see if I can interface with hard drives and CF cards, which will be the first step toward writing better software.

Finally I'd love to find a 64MB or even 128MB DRAM module I can install and see if I can get it to do anything interesting. I don't doubt I can work out some sort of hack for this.


M said...

Hello, did you ever figure out any way to write past 32mb?
I've been doing a bit of haxing on this machine lately:


Unfortunately I've never found a 64MB module. They may not even exist, and making an adaptor for two 32MB modules is beyond my skill level.

I'd be quite interested to see how this custom BIOS works, though. I assume you just connect CF cards directly to the IDE interface with an adaptor?

M said...

Hi, yea its just a CF->IDE adaptor im using, works with any regular hdd too, so there is no hardware modifications involved, it's all software.

Hm.. there are quite a lot of 64mb SIMM modules being sold on ebay, but knowing how damn picky this machine is with what modules it will accept im not sure how fun it is to buy different ones until one is found that actually works. :P I did try a 64mb(or was it 128mb hm) one i already had at home, but it wouldnt detect that one at all unfortunately. maybe it needs to be 50ns access time on those chips?

One interesting part that i found while analyzing the original bios is, it actually checks for presence of both 48mb and 64mb modules, so i wonder if they already had modified hw to accept such ones.


Interesting. Have you tried to access them with a custom BIOS? Maybe the original detection routine is just buggy.

M said...

Not yet, gonna complete my fat16 code first before i start playing with the ram stuff(a pain to test fat16 code on the n64 :P), however i did recode the detection routine in C quickly, its what i use in my own bios right now

Are you interested in helping doing anymore research and stuff on this machine? Not many ppl that still care at all about this old copier :P

Been considering to rewrite the cpld, but dont really have any clue about that stuff.. yet :)

But at least testing code is really fast now with CF card/HDD opposed to burning damn cd-rw's.


I'm definitely still interested, just haven't worked on it in a while due to distractions. Mainly I need to build the circuit to interface with the parallel port, and get my hands on a flash programmer... I wonder if I could repurpose a Gameshark for either of those uses. (Gameshark can be used to run code on N64 as well, so it'd be possible to reflash the BIOS even if it were broken... but it'd be necessary to boot a game with the unit still plugged in, so that might not be feasible.)

M said...

I tried building the PPA using schematics from icequake website, but still havent got that working..
And hm, what happens if one puts a game/gameshark in the top slot on n64 while still keeping the cd64 connected?

Possibly you could add a switch somehow to PCB to make it start in mode7 instead of mode0, altho im not very good at hw, but could be an easy fix to do.

Easiest way is to just get a cheap chinese flashrom programmer from ebay, thats what i use, then i can use the flashed bios to load updated versions of bios directly from CF card. Also keeping the cd64 plugged in to 9vdc you can load rom from CD and just turn off, switch cd drive with hdd and turn back on.

You use IRC?


I do hang out on IRC, yes.

From what I've tried, it won't boot at all if you have something in both the top and bottom slots. I think it must be possible, or else the 64DD would have been a huge pain to use, but maybe it was using some trickery to prevent bus conflicts. As far as I know, both connectors connect to the same pins.

M said...

Well, its not exactly a well engineered piece of hardware, might be it would need to be hw modified to get it to work..

Send a msg to 'ffff' on EFNet if you wanna talk some more, these captchas are hard as hell to get right. :P

Post a Comment