Writing to SRAM on retail carts

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
DNSDies
Posts: 87
Joined: Thu May 03, 2012 10:26 am

Writing to SRAM on retail carts

Post by DNSDies »

I have a save file from an emulator I'd like to transfer to a retail cart, but I don't have a SRAM writer.

What I do have is a super everdrive, a GQ-4X Programmer, and a Teensy 2.0.

How do I go about doing this?
Also, can I possibly use my teensy to do SRAM backups in preparation for battery replacements?
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: Writing to SRAM on retail carts

Post by blargg »

If you disable the CIC on your SNES, you can hotswap the flash cart to the retail cart, save the SRAM into internal RAM, hotswap the retail cart out while you swap the battery, then hotswap it back in and rewrite. Tricky since a crash on the SNES would mess the process up.

With the Teensy you can hook it to the controller port, run a bootloader from the flash cart (which I assume you can program from your PC), hotswap to the retail cart, and read/write SRAM from the PC via the Teensy.
User avatar
MottZilla
Posts: 2835
Joined: Wed Dec 06, 2006 8:18 pm

Re: Writing to SRAM on retail carts

Post by MottZilla »

How well does hot swapping work on the SNES though? I recall someone mentioning having DMA transfers going tends to reduce the chance of a crash.

Either way there is no ready to go way to do what you want with the materials you have on hand. Older style Copiers like the Game Doctor SF can do what you want though.
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: Writing to SRAM on retail carts

Post by blargg »

Hotswapping works reliably for me, yes, using 64K DMAs to make the CPU unlikely to crash. The only tricky parts are disabling the CIC (lift one pin) with a soldering iron and hooking the Teensy to the controller port. Agreed that unless you want to do some significant SNES stuff, a copier that can do this directly or sending the boards to someone who can makes more sense (remove them from cart cases and pay maybe $10 to send several cart boards round-trip, at least in the USA).
User avatar
mikejmoffitt
Posts: 1352
Joined: Sun May 27, 2012 8:43 pm

Re: Writing to SRAM on retail carts

Post by mikejmoffitt »

You could build an awful contraption like I did for an N64 when I had to give four copies of Super Smash Bros 64 the same fully unlocked save file:

Image
Image

However, this worked by playing both carts from a fresh state and progressing through them identically, so there weren't conflicts between the two (potentially mismatched) sets of SRAM data lines being merged into the one.

I guess you could do something like that but disable SRAM reading on one cartridge temporarily? unfortunately I don't know if that 's a reasonable thing, since without knowing better I'd expect it to be bidirectional and not have specific lines for reading and writing.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: Writing to SRAM on retail carts

Post by nocash »

blargg wrote:Hotswapping works reliably for me, yes, using 64K DMAs to make the CPU unlikely to crash.
Interesting way to misuse DMA for hotswapping. A different way is to store up to 8x12 bytes of program code in the DMA registers at 4300h-437Fh, and let the CPU execute that code, doing that should be absolutely stable and make it impossible to crash the CPU.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: Writing to SRAM on retail carts

Post by Near »

Have you tested and confirmed that?

I currently use the 64K DMA trick to avoid CPU crashes, and it's somewhat unreliable. About a 25% failure rate.

I mean the theory is sound, but code executing out of WRAM shouldn't crash when you swap carts either, and yet it does.

If this really works, I sure would have liked to have known about it before dumping 750 cartridges using the DMA trick :P
User avatar
infiniteneslives
Posts: 2102
Joined: Mon Apr 04, 2011 11:49 am
Location: WhereverIparkIt, USA
Contact:

Re: Writing to SRAM on retail carts

Post by infiniteneslives »

Putting a cart in with those big caps puts quite a surge on the power supply. That's probably what causes it to crash somewhat often.
If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: Writing to SRAM on retail carts

Post by blargg »

Thanks, DMA registers work. I first put the program that flashes the screen for a while, then runs the serial bootloader out of WRAM, but WRAM was apparently getting corrupted when I inserted/removed cartridge. So I rewrote the serial bootloader to fit entirely into DMA registers and it seems uncrashable/uncorruptible. It was a tad tricky to break the code into 12-byte chunks (with branches to the next) and get the timing right. The bootloader checks for a 3-byte header and does a checksum on received data, so there's no way it can get tricked by insertions while it's reading the controller port for data. It barely fit.

Code: Select all

; Receives data as 57600-bps serial on controller port 2
; Waits for 256-byte block beginning with $DC $4B $D2
; Writes it to 0-$FF in memory (zero-page)
; Verifies checksum in fourth byte (see code at end for preparing block and checksum)
; If all check out, starts executing at $0004, otherwise resumes waiting for header

; The following must be run before code is executed:

        sep #$30    ; make A, X, and Y 8 bits

; It works in emulation or native mode.
; The code below must be copied to DMA registers and executed from them (JMP $4300)

4300:A2 00    LDX #$00          ; X = bytes received
4302:A9 01    LDA #$01          ; A = mask
4304:2C 17 40 BIT $4017         ; Wait for start bit
4307:F0 FB    BEQ $4304
4309:80 05    BRA $4310
430B:FF FF FF FF FF
4310:A9 01    LDA #$01          ; A = initial delay to middle of start bit
4312:A0 FF    LDY #$FF          ; Y = received bits
4314:3A       DEC A             ; Delay A*30
4315:D0 FD    BNE $4314
4317:A9 01    LDA #$01          ; A = mask
4319:80 05    BRA $4320
431B:FF FF FF FF FF
4320:2D 17 40 AND $4017         ; Read in middle of bit
4323:49 FF    EOR #$FF          ; un-invert
4325:C9 FF    CMP #$FF          ; carry = bit
4327:98       TYA               ; Rotate into bits received
4328:6A       ROR
4329:80       BRA $4330
432B:FF FF FF FF FF
4330:95 00    STA $00,X         ; Store byte (also acts as delay)
4332:90 0C    BCC $4340         ; Done with byte if start bit was shifted out
4334:A8       TAY
4335:95 00    STA $00,X         ; delay
4337:EB       XBA
4338:A9 04    LDA #$04          ; delay between bits
433A:80 D8    BRA $4314
433C:FF FF FF D8
4340:E0 03    CPX #$03          ; First 3 bytes are signature
4342:B0 0C    BCS $4350
4344:7D 77 43 ADC $4376,X       ; Add negated correct byte, =0 if correct
4347:D0 B7    BNE $4300
4349:80 05    BRA $4350
434B:FF FF FF FF FF
4350:A9 07    LDA #$07          ; delay until middle of stop bit
4352:3A       DEC A
4353:D0 FD    BNE $4352
4355:E8       INX
4356:D0 AA    BNE $4302         ; more bytes
4358:80 06    BRA $4360
435A:FF FF FF FF FF FF
4360:8A       TXA               ; Calculate checksum (XOR and add)
4361:55 00    EOR $00,X
4363:0A       ASL
4364:69 99    ADC #$99
4366:E8       INX
4367:D0 F8    BNE $4361
4369:80 05    BRA $4370
436B:FF FF FF FF FF
4370:AA       TAX               ; if CRC != 0, go back and wait for new block
4371:D0 8D    BNE $4300
4373:4C 04 00 JMP $0004         ; Run the program!
4376:24 B5 2E                   ; negated header bytes

/* Converts 256-byte block of user code (beginning at offset 4)
into 256-byte program block ready to send to boot loader */
enum { boot_block_offset = 4 };
enum { boot_block_size = 0x100 };
static void make_boot_block( unsigned char block [boot_block_size] )
{
    int i, crc = 0;
    for ( i = boot_block_size - 1; i >= boot_block_offset - 1; i-- )
    {
        crc += 0x100 - 0x99;
        crc = (crc << 7 & 0x80) | (crc >> 1 & 0x7F);
        crc ^= block [i];
    }
    block [0]  = 0xDC;
    block [1]  = 0x4B;
    block [2]  = 0xD2;
    block [3] ^= crc ^ 0xCB;
}
EDIT: scope shows cartridge data bus quiet while executing above code out of DMA registers, so this does look like it will be uncrashable. Now to examine the +5V rail droop due to the cart's capacitors charging when hotswapped.

Nope, am not seeing any power dips on cartridge insertion. Also after doing all this scoping while code was running, it hadn't crashed.
Last edited by blargg on Thu May 09, 2013 8:34 pm, edited 2 times in total.
Ziggy587
Posts: 138
Joined: Fri Oct 08, 2010 6:08 pm
Location: NY, USA

Re: Writing to SRAM on retail carts

Post by Ziggy587 »

The programmer that is used for the Super Flash Cart from Tototek will allow you to write to the SRAM on retail carts.

http://tototek.com/store/index.php?main ... ucts_id=39

You can buy the programmer separately for only $20 (scroll down to bottom of page) but the catch is you need an EPP parallel port for it.
qwertymodo
Posts: 775
Joined: Mon Jul 02, 2012 7:46 am

Re: Writing to SRAM on retail carts

Post by qwertymodo »

I'm currently working on a Teensy++ based cart reader, should be a fun project.

I really should finish that hardware re-spin of the controller-port serial connection too... so many projects, so little time. No, wait, that's not true... so many projects, so *much* time... so much Netflix >_<
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Re: Writing to SRAM on retail carts

Post by blargg »

qwertymodo wrote:so many projects, so *much* time... so much Netflix >_<
Just ask yourself which you'd like to have done in a year: watch Netflix a lot yet still only watched a tiny fraction of what's available, or completed several projects.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Writing to SRAM on retail carts

Post by tepples »

If a game project involves creating an original setting, one may need to watch Netflix to get inspiration.
qwertymodo
Posts: 775
Joined: Mon Jul 02, 2012 7:46 am

Re: Writing to SRAM on retail carts

Post by qwertymodo »

blargg wrote:
qwertymodo wrote:so many projects, so *much* time... so much Netflix >_<
Just ask yourself which you'd like to have done in a year: watch Netflix a lot yet still only watched a tiny fraction of what's available, or completed several projects.
To be fair, I tend to work on my projects *while* watching Netflix. And really, Netflix isn't so much the problem as my ADD is, I have so many half-completed projects that I just got distracted by a new idea and set aside...
User avatar
Ramsis
Posts: 341
Joined: Sun Jul 01, 2012 6:44 am
Location: Lion's den :3
Contact:

Re: Writing to SRAM on retail carts

Post by Ramsis »

nocash wrote:A different way is to store up to 8x12 bytes of program code in the DMA registers at 4300h-437Fh, and let the CPU execute that code, doing that should be absolutely stable and make it impossible to crash the CPU.
blargg wrote:Thanks, DMA registers work. I first put the program that flashes the screen for a while, then runs the serial bootloader out of WRAM, but WRAM was apparently getting corrupted when I inserted/removed cartridge. So I rewrote the serial bootloader to fit entirely into DMA registers and it seems uncrashable/uncorruptible. It was a tad tricky to break the code into 12-byte chunks (with branches to the next) and get the timing right. The bootloader checks for a 3-byte header and does a checksum on received data, so there's no way it can get tricked by insertions while it's reading the controller port for data. It barely fit.
Executing code that's sitting on DMA registers! :shock: This is insanely cool. :D

Thinking of it (and reading nocash's docs again), I guess that implementing an "SPC was played" flag in the PowerPak firmware might be possible after all ... I'm definitely going to try! :P

Thanks a lot, nocash & blargg! :)
Some of my projects:
Furry RPG!
Unofficial SNES PowerPak firmware
(See my GitHub profile for more)
Post Reply