Bung Game Doctor SF3, SF6, SF7 Headers
Version 1.0 - Copyright 2003: The Dumper
The Game Doctor SF3/SF6/SF7 backup units for the SNES use a 512 byte header.
The format is as follows (all numbers are hexadecimal):
47 41 4D 45 20 44 4F 43 54 4F 52 20 53 46 20 33 "GAME DOCTOR SF 3"
This is the ID string for a Game Doctor SF header.
SRAM size limit byte. This is used in conjunction with other bytes in the header that locate the SRAM in the address space of the SNES. Valid values are:
0x80: Either 0 SRAM or 256 Kbit SRAM depending on other bytes in the header (see below).
0x81: 64 Kbit SRAM
0x82: 16 Kbit SRAM
This byte limits the amount of address lines active to the SRAM. You also have to map the SRAM into the SNES address space with other bytes in the header. If you don't map it in the size is 0.
Maps DRAM chunks into the SNES address space.
One byte maps one 4 Mbit chunk of DRAM into the SNES address space. One DRAM logical unit is 8Mbit (holds two 4Mbit chunks). If you logically divide your ROM file into 4Mbit chunks, the first chunk will have ID
0x20, the second
0x21, the third
0x22, etc. Where you place the chunk ID in the header determines where the chunk gets mapped into the SNES address space. Here is the map key:
--------------------------------- --------------------------------- |00H|10H|20H|30H|40H|50H|60H|70H| |80H|90H|A0H|B0H|C0H|D0H|E0H|F0H| --------------------------------- --------------------------------- ----------------- ----------------- |40L|50L|60L|70L| |C0L|D0L|E0L|F0L| ----------------- ----------------- 00H = map dram chunk into $00-0F:8000-FFFF 10H = map dram chunk into $10-1F:8000-FFFF ... E0H = map dram chunk into $E0-EF:8000-FFFF F0H = map dram chunk into $F0-FF:8000-FFFF 40L = map dram chunk into $40-4F:0000-7FFF 50L = map dram chunk into $50-5F:0000-7FFF 60L = map dram chunk into $60-6F:0000-7FFF 70L = map dram chunk into $70-7F:0000-7FFF C0L = map dram chunk into $C0-CF:0000-7FFF D0L = map dram chunk into $D0-DF:0000-7FFF E0L = map dram chunk into $E0-EF:0000-7FFF F0L = map dram chunk into $F0-FF:0000-7FFF
In a LoROM game with SRAM you map SRAM into the address space by putting a
0x40 byte in the segment where you want it mapped. One common LoROM mapping puts SRAM in the lower 32K of the
$Fx banks. This is specified by putting a
0x40 in the bytes for 70L and F0L.
I think a 00 in one of these bytes means nothing is mapped to that range.
0x60 in one of these bytes is used in an entry to pass-through data to/from the cart in that address range. This can be used for anything with a special chip that needs direct access to the special chip registers in a certain address range. I think there is a timing problem with some special chips using the 0x60 pass-through accesses. With some types of special chips corruption sometimes occurs.
0x60 is not needed for HiROM DSP1 games. Those addresses are passed through by default. Also, the S-RTC address range (DKJM2) seems to be passed through by default.
0x60 (in 30H and B0H) is needed for LoROM DSP accesses to be passed through.
The Game Doctor has some restrictions on the use of memory units. A HiROM game must be loaded into two different memory units (I suspect that this was a hardware restriction of the SF3 or SF6). My working assumption, which is not correct but is probably over restrictive and will work in all cases, is that you cannot load both High and Low halves of a bank from the same dram unit.
These two bytes map the SRAM into the HiROM style of SRAM mapping.
Each bit controls whether SRAM is mapped for a specific range of banks.
When a bit is set it maps offsets
$6000-$7FFF to SRAM in the specified range of banks.
0029 002A ------------------------- ------------------------- |7x|6x|5x|4x|3x|2x|1x|0x| |Fx|Ex|Dx|Cx|Bx|Ax|9x|8x| ------------------------- -------------------------
If the game's SRAM size is 0 these bytes should be 00 00.
If the game is a LoROM game, these bytes will be 00 00.
Standard HiROM mapping bytes are 0C 0C, which corresponds to mapping SRAM to banks
There are one or two oddball HiROM SRAM mappings. One I've found is for some 10-12 Mbit HiROM games. Some use
0A 0A. I believe this to be a side effect of the way the MAD-1 decoder is wired in these carts. So far all the exceptions in this category work with the standard SRAM mapping of
0C 0C. They have ranges
3x,Bx:6000-7FFF in common with the standard mappings, which is where these games access the SRAM.
Reserved. Filled with
Game Doctor SF7
The BIOS mode memory map:
$00:8000-807F .... BIOS regs, so $80 bytes of the ROM is never accessible (so there is no need to worry about it). $00:8080-FFFF .... first 32kBytes of ROM $01:8000-FFFF .... second 32kBytes of ROM $02:8000-FFFF .... unused $03:8000-FFFF .... unused $04:8000-FFFF .... BRAM $05:8000-FFFF .... SRAM for real time save data (4kByte) $06:8000-FFFF .... SRAM for copier settings (4kByte) $07:8000-FFFF .... 32kB page of DRAM
And then this is just repeated for all banks $00-$7F. It can also be in $80-$FF depending on some register settings.
BIOS mode memory map:
$008000-$00807F registers Cartridge Mode memory map settings $008000-$008017 (read/write) each is a byte and holds the setting of a region of the memory map values have same meaning like in the header (gotten from code at 81/A1E3) $008018 write, "expansion mem" location settings ? $008019 write, "expansion mem" location settings ? Real Time Save information $008018 read, bit1 = $4016 bit0 $00801A read word, latch settings for double write word registers $008018 read bit7 = ? , bit = ? $008019 read bit1 = ? $00801A write ? $00801B write ? BIOS memory map settings $00801D write, changes what is mapped into banks $80-$FF only bit0-bit1 seem to matter 0 = use cartridge banks $00-$7F 1 = use cartridge banks $80-$FF 2 = mirror banks $00-$7F (BIOS regs and all?) 3 = mirror banks $00-$7F (BIOS regs and all?) $00801E write ? $008020 bit7 = 1, means "ready" or "continue" (code waits for bit=1) $008022 write ? $008024 write ? $008028 write ? $00802A write ? $00802B write ? parallel port $00802C data pins $00802D status (not direct pin reading?) read bit7 = /S7 (direct pin11) = "write bit7" AND not "write bit0" bit6 = "write bit4" bit5 = "write bit4" bit4 = "write bit4" bit3 = "write bit3" bit2 = /C3 (direct pin17) bit1 = C2 (direct pin16) bit0 = /C1 (direct pin14) write bit3 => S3 (direct pin15) bit4 => S4 (direct pin13) bit5 => S5 (direct pin12) bit6 => S6 (direct pin10) bit7 ... bit7 AND /bit0 ==> /S7 (direct pin11) $00802E control (not direct control reg values) bit7 = /C0 (direct pin1) bit0 = /C1 (direct pin14) bit1 = C2 (direct pin16) bit2 = /C3 (direct pin17) bit3-bit6, read = bit3-bit6 of $00802D $00802F read same as $00802D DRAM control ?? $008030 word, ?? controls what is mapped into $078000 valid $0000 - $01FF = 32kB page (out of 128 MBits) that is mapped in (gotten from code at 81/A235) $008030-$00803D ... 7 word table?? (gotten from code at 80/AE80) $008040-$00805F read same as $00802D $008060-$00807F read = $FF $0080xF (where x = 8 - F) any access to $00:80xF will cause a "switch to cartridge mode" $048000-$04FFFF 32k BRAM (not actually battery backed) $058000-$058FFF = 4k SRAM copier listens in on SNES register accesses and writes the results here $068000-$068FFF = 4k SRAM I believe the 8k SRAM chip is split between bank $05, $06 (gotten from code at 81/87B7) The BIOS seems to use this memory region to save copier settings. $078000-$07FFFF 32k DRAM everything appears to be mirrored to banks $2x $258000-$2585FF saved register settings ??,$21xx,$42xx,$43xx,$21xx,$21xx $068000 = 66 ($42) byte entries for each DRAM "slot" ... 16 slots -> $420 bytes routine at 81/A6C6 usually used $00-$11 ... 18 bytes, game name in slot $18-$22 ... 11 bytes, file name ... 1st two bytes: $53,$46 to be "valid" ie start with SF $23,$24 ... word: $54,$53 if "invalid" or something Actual GD3 ROM header info $25 ... SRAM setting $26-$3D ... memory map bytes $3E-$3F ... expansion mem setting $40 ... word: sum of words $00-$3E of this entry $068420 = saved $06842E $068422 = saved X $068424 = saved Y $068426 = saved stack $068428 = saved D $06842E = saved A $068436-$068535 temporary storage of first $100 bytes of WRAM $068541-$0685D2 $92 bytes of "settings", includes tables of jump code $0685D5 = saved word $00801A $0685DB = bit0 used for $801D in BIOS mode $068600 = 16 bytes 4 x 4byte settings - 24bit pointer (MSB first), then temp holding of a WRAM byte $068610 = 16 bytes for each "slot" the DRAM page/2 which holds the beginning of the ROM $068620 = $40 bytes, a copy of the internal ROM header $7FC0-$7FFF $06FFB0,X ?? holds bank settings of some sort? Data: $12 = (24bit pointer) stack pointer + 1 $1C = temporary delay counter $1D = " $1E = $10 * DRAM "slot" # that is start of game $20 = upper part of tilemap (settings) $23 = last byte sent to PC $25 = main menu #, 00 = PlayGame 01 = PlayDisk 02 = Utility $29 = word, frame number? $2E = 00,'D','X' depending on name in $0300 $3E = transfer setting 80 = ROM 40 = SAVER 00 = BRAM $3F = non-zero if we need to wait for $802E bit7 == nonzero zero if we need to wait for $802E bit7 == zero $80 = old Joypad1 data $82 = current Joypad1 data $84 = button just pressed JoyPad1 data $86 = very important, so please note that this needs more investigation = which DRAM "slot" ? $9F = temporary backup of $86 $C5-$C7 = RAM search findings ... see comments at 80/D842 for details $C8 = RAMsize setting (calculated when back up cart) $F5 = parallel port transfer mode/state ?? bit0 = 1, use GD3 = 0, use GD6 for GD6 bit1 = 1, read = 0, write $0300 = $0B byte buffer to hold DRAM section name (file split names) $0312 = $04 byte buffer to hold transfer info 1st: 00 2nd: 02 if header included, 00 if not 3rd: number of 64k chunks ($10 = 8 MBit) 4th: 00 $03B6 = $0B byte buffer ... intially a copy of $0300 $0600 = $200 byte buffer for ROM headers