- For making cartridges of your Super NES games, see Reproduction.
Some fascinating findings ...
$230e, the version control register, doesn't exist. It's open bus on both the SNES CPU and on the SA1. We should test with many more SA1 carts to be 100% sure, but so far it's looking like this doesn't exist. Overload reported getting $10 once, and we see pure open bus. It's possible Overload had $10 on the data bus when he read the SA1 CPU register, and possible his cart actually DID have this register.
The SA1 memory conflict occurs even on idle cycles of the SNES CPU.
The +1 cycle penalty for JMP/JML/JSR/JSL/RTS/RTL/RTI instructions only applies when the SA1 is running off of the ROM. It's actually a 2-clock (@ 21MHz) penalty, or a 4-clock penalty if the CPU is also accessing ROM during this time.
The SA1 executing out of ROM takes 2 cycles, or 4 cycles if the CPU is executing there too.
The SA1 executing out of BWRAM takes 4 cycles, or 8 cycles if the CPU is executing there too.
The SA1 executing out of IRAM takes 2 cycles, or 6 cycles if the CPU is executing there too.
I'm missing something when both the SA1 and CPU execute out of IRAM ... my timings are very very slightly slower than real hardware ...
The SA1 ROM itself is 16-bit (as is the SD Gundam G Next - Unit & Map Collection BS Memory Cassette ... and any BS Memory Cassettes on SA1 cartridges are treated as though they're in 16-bit configuration mode. You can't dump a 16-bit BS cart through a non-SA1 base cart, nor an 8-bit BS cart through an SA1 base cart.)
BWRAM is 8-bit. I have no idea what IRAM is internally.
There's apparently another penalty when you branch to an odd address, due to the 16-bit reads.
Only $2300 can be read by the SNES CPU, the rest of the I/O registers are for the SA1 only.
Writes are a whole lot more complicated.
The CPU can write to:
2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208
2220, 2221, 2222, 2223, 2224, 2226, 2228, 2229
The SA1 can write to:
2209, 220a, 220b, 220c, 220d, 220e, 220f
2210, 2211, 2212, 2213, 2214, 2215
2225, 2227, 222a
2230, 2238, 2239, 223f
2240 - 224f
2250, 2251, 2252, 2253, 2254, 2258, 2259, 225a, 225b
Both the CPU and SA1 can write to:
2231, 2232, 2233, 2234, 2235, 2236, 2237
Absolutely bizarre ... I really would have thought the CPU would be unable to write the DMA registers, if it can't write the actual DMA control register.
Now for the really wild stuff ... SNES CPU DMA timing.
His DMA ROM <> ROM test clocks at either ~5.07MHz or ~5.19MHz, and tends to flicker between the two.
His DMA ROM <> IRAM test clocks at ~10.63MHz, and is stable at that speed on real 2/1/3 hardware.
Here's a hardware recording of it in action:
https://cdn.discordapp.com/attachments/ ... -31-54.mkv
Many things seem to influence this in higan: whether the DMA/HDMA idle cycles happen before or after transfers, whether I try and emulate the branch to odd addresses penalty, etc.
So far at least, I can't quite match hardware no matter what combination I try.
This should be a fascinating area of research for nocash and Overload, should they be interested.
The SA1 is revealing internal CPU state (the address bus values) that's not readily observable under normal circumstances.
I believe that trying to read $2137 from CPU DMA and HDMA could help to validate this. I've not tried that before, surprisingly.
Code: Select all
cpu 013502 cmp #$00 A:a900 X:004b Y:000f S:01f8 D:0000 B:00 nvMXdIZC 225,716 * opcode fetch * operand fetch cpu 013504 bmi $3509  A:a900 X:004b Y:000f S:01f8 D:0000 B:00 nvMXdIZC 225,644 * opcode fetch * idle 6 <EF && hi(PC) != hi(address)> == false * idle == false * SA1 ROM idle branch == false cpu 013506 jmp $3502  A:a900 X:004b Y:000f S:01f8 D:0000 B:00 nvMXdIZC 225,656 * opcode fetch * operand fetch * operand fetch * SA1 ROM idle jump sa1 003606 adc #$0000 A:000b X:00f0 Y:0001 S:07fb D:0000 B:00 nvmXdizc 210,442 * opcode fetch * operand fetch * operand fetch sa1 003609 adc #$0000 A:000b X:00f0 Y:0001 S:07fb D:0000 B:00 nvmXdizc 210,460 * opcode fetch * operand fetch * operand fetch sa1 00360c adc #$0000 A:000b X:00f0 Y:0001 S:07fb D:0000 B:00 nvmXdizc 210,478 * opcode fetch * operand fetch * operand fetch sa1 00360f adc #$0001 A:000b X:00f0 Y:0001 S:07fb D:0000 B:00 nvmXdizc 210,496 * opcode fetch * operand fetch * operand fetch sa1 003612 jmp $3606  A:000c X:00f0 Y:0001 S:07fb D:0000 B:00 nvmXdizc 210,514 * opcode fetch * operand fetch * operand fetch * SA1 ROM idle jump
Yet a naive step(iram.conflict() ? 6 : 2); yields 3.58MHz instead of 3.72MHz.
If we look at an SA1 PCB, we see that the DRAM refresh pin is connected. And indeed, it would appear that IRAM is allowed to execute with only a 2-cycle wait during DRAM refresh.
But again, a naive check where DRAM refresh remains set for all 40 clocks yields a rate of 3.80MHz.
I remember from a long time ago, someone with a logic analyzer advised that DRAM refresh pulsed.
5 high, 3 low; 5 high, 3 low; 5 high, 3 low; 5 high, 3 low; 5 high, 3 low
That yields 3.73MHz, as does a 6-2 pattern (since the SA1 runs in two-clock increments.)