DMA to WRAM on FC Twin

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.
bunnyboy
Posts: 449
Joined: Thu Oct 27, 2005 1:44 pm
Location: CA
Contact:

DMA to WRAM on FC Twin

Post by bunnyboy » Wed Jun 03, 2009 4:41 pm

I have some DMA code that appears to run correctly on a real SNES and the RetroDuo, but not the FC Twin.

I am using channel 1 (0-7) to do graphics updates during vblank. That part is working fine on all systems.

I am using channel 0 to do data transfer from ROM to WRAM, not necessarily in vblank. This is the part that doesn't work on the FC Twin. Putting WAI before the DMA code doesn't help, and neither does forcing vblank using $2100 before the DMA. My code seems pretty basic:

Code: Select all

  
  (16 bit X/Y, 8 bit A)
  ldx destLo
  stx $2181
  lda #$00
  sta $2183  ;;load the WRAM dest address
  
  lda #$08
  sta $4300   ;;no source increment
  
  lda #$80
  sta $4301   ;;dest = wram, $2180
  
  lda sourcelow
  sta $4302
  lda sourcehigh
  sta $4303
  lda sourcebank
  sta $4304
  
  ldx sourceBytes16
  stx $4305   ;;size in bytes

  lda #$01
  sta $420B   ;Initiate transfer using channel 0

Any more ideas?

User avatar
koitsu
Posts: 4217
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Post by koitsu » Wed Jun 03, 2009 8:43 pm

I'm a little confused by what it is you're trying to do here. :-)

My first question is: why are you using $2180 and $2181? WRAM is memory mapped to $0000-1FFF in banks $00-3F and $80-BF, as well as bank $7E (I think).

Next, you're claiming you're copying part of the ROM space to WRAM directly (e.g. A-bus --> B-bus, where A-bus == ROM/CPU and B-bus == $2180), but I see you're setting D3 of $4300 to 1, which stops the A-bus address from incrementing when reading from the source.

This would cause the DMA transfer to essentially copy a single byte of data in ROM to $2180, for a total of sourceBytes16 times. You also have the code comment "no source increment", which implies that's what you want.

This means your DMA transfer is being used solely to clear WRAM by using a DMA transfer, copying a single byte from sourcebank/sourcehigh/sourcelow into $2180 over and over. You can accomplish the exact same using a simple loop.

Otherwise, if you're trying to copy a "chunk" of existing memory (ROM or otherwise) into WRAM, you should set D3 of $4300 to 0 and D4 of $4300 to 0, to ensure that the A-bus address is incremented.

Another workaround for copying data using DMA is to use the MVN opcode. The SFC's DMA gives you a lot more control than MVN, but for copying memory around, MVN can get the job done. Or just go with a custom loop... :-)

bunnyboy
Posts: 449
Joined: Thu Oct 27, 2005 1:44 pm
Location: CA
Contact:

Post by bunnyboy » Wed Jun 03, 2009 9:43 pm

koitsu wrote:My first question is: why are you using $2180 and $2181? WRAM is memory mapped to $0000-1FFF in banks $00-3F and $80-BF, as well as bank $7E (I think).
Because the DMA dest can only access the $21xx range on the A bus, when the source is the B bus. But somehow I think you already knew that :)
koitsu wrote:Next, you're claiming you're copying part of the ROM space to WRAM directly (e.g. A-bus --> B-bus, where A-bus == ROM/CPU and B-bus == $2180), but I see you're setting D3 of $4300 to 1, which stops the A-bus address from incrementing when reading from the source.
Think of it as memory mapped IO, not an actual ROM chip. I will test it but I doubt the non incrementing source is the problem anyways.

Of course there are other (slower) ways of doing it, but that wasn't the question. Code like the starter kit uses it to clear WRAM, but that is likely before the PPU is enabled. I don't want to say it is just clone incompatibility since the SNES clones seem to be very good.

User avatar
Bregalad
Posts: 7872
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Post by Bregalad » Thu Jun 04, 2009 3:02 am

I'm pretty sure anomie's doc mentionned trying to DMA to WRAM by $2180 won't work (so I don't even understand why can $2180 be usefull, why won't you adress WRAM directly ?). I could be wrong tough. Check anomie's docs on DMA.
Life is complex: it has both real and imaginary components.

tepples
Posts: 21947
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Thu Jun 04, 2009 3:57 am

koitsu wrote:Another workaround for copying data using DMA is to use the MVN opcode. The SFC's DMA gives you a lot more control than MVN, but for copying memory around, MVN can get the job done. Or just go with a custom loop... :-)
But isn't that slow? From my Apple IIGS days, I seem to remember MVN taking 7 cycles per byte and requiring self-modifying code to set the source and destination banks. On the GBA at least, the fastest memcpy() from ROM to WRAM is DMA; the LDMIA/STMIA loop comes in a close second and has better IRQ latency.

bunnyboy
Posts: 449
Joined: Thu Oct 27, 2005 1:44 pm
Location: CA
Contact:

Post by bunnyboy » Thu Jun 04, 2009 6:03 am

Bregalad wrote:I'm pretty sure anomie's doc mentionned trying to DMA to WRAM by $2180 won't work
Anomie's docs say you can't DMA between WRAM and $2180, because the WRAM can't respond to both buses at once. Between ROM and $2180 is no problem, and works on the real SNES.

User avatar
Bregalad
Posts: 7872
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Post by Bregalad » Thu Jun 04, 2009 8:56 am

Oh thanks for correcting me.
Life is complex: it has both real and imaginary components.

User avatar
koitsu
Posts: 4217
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Post by koitsu » Thu Jun 04, 2009 12:20 pm

tepples wrote:
koitsu wrote:Another workaround for copying data using DMA is to use the MVN opcode. The SFC's DMA gives you a lot more control than MVN, but for copying memory around, MVN can get the job done. Or just go with a custom loop... :-)
But isn't that slow? From my Apple IIGS days, I seem to remember MVN taking 7 cycles per byte and requiring self-modifying code to set the source and destination banks. On the GBA at least, the fastest memcpy() from ROM to WRAM is DMA; the LDMIA/STMIA loop comes in a close second and has better IRQ latency.
You remember correctly -- MVN/MVP are indeed slow. My point was to offer an alternative if needed. Plus, given that I wasn't sure what bunnyboy was trying to do (re: is this code intended to just init WRAM, or is it actually wanting to copy ROM contents into WRAM?), it's a legitimate alternative to said problem. That said, it's almost always faster to do things in an actual loop vs. using MVN/MVP, but again, depends on what the code was trying to do.

I'll read the rest of the thread after I've slept. :)

bunnyboy
Posts: 449
Joined: Thu Oct 27, 2005 1:44 pm
Location: CA
Contact:

Post by bunnyboy » Thu Jun 04, 2009 4:30 pm

Slight bit of additional info: it looks like the DMA is happening but the bytes are shifted to the left, like the first byte was skipped. Next to check if its actually copying the right amount, or the address is wrong, etc...

bunnyboy
Posts: 449
Joined: Thu Oct 27, 2005 1:44 pm
Location: CA
Contact:

Post by bunnyboy » Fri Jun 05, 2009 10:31 am

F YOU FC Twin!

Turns out there is frequently a sysclk glitch at the beginning of DMA. This is no problem when reading from ROM, because the value doesn't change. When reading from IO the glitch triggers and extra read, shifting everything over. Now to figure out how to detect that clone and switch to a fixed loop...

Image

tepples
Posts: 21947
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Fri Jun 05, 2009 11:10 am

Hmmm... What could cause a glitch? Did the SPC700 fetch a sample at that exact moment? ;-)

You could try to do an I/O from a known data source and if it screws up, it's a clone.

bunnyboy
Posts: 449
Joined: Thu Oct 27, 2005 1:44 pm
Location: CA
Contact:

Post by bunnyboy » Fri Jun 05, 2009 2:56 pm

tepples wrote:Hmmm... What could cause a glitch? Did the SPC700 fetch a sample at that exact moment? ;-)

You could try to do an I/O from a known data source and if it screws up, it's a clone.
Don't have any audio running so I hope its not the same DPCM bug :)

Can't just check for alignment wrong because it doesn't happen every time. Would have to do something like run it 10-20x and see if any fail.

User avatar
koitsu
Posts: 4217
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Post by koitsu » Fri Jun 05, 2009 7:12 pm

You're not doing any HDMA transfers anywhere in your program are you?

bunnyboy
Posts: 449
Joined: Thu Oct 27, 2005 1:44 pm
Location: CA
Contact:

Post by bunnyboy » Fri Jun 05, 2009 8:44 pm

Nope no HDMA, IRQs also off, turning NMI off or making it happen before the DMA doesn't make a diff either. I can test doing the DMA before any of the screen is turned on but I am skeptical that will make a difference. Wonder if its something with the clock alignment.

User avatar
koitsu
Posts: 4217
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Post by koitsu » Sat Jun 06, 2009 10:44 am

bunnyboy wrote:Nope no HDMA, IRQs also off, turning NMI off or making it happen before the DMA doesn't make a diff either. I can test doing the DMA before any of the screen is turned on but I am skeptical that will make a difference. Wonder if its something with the clock alignment.
The reason I ask about HDMA is that there's a documented bug in the SFC (and possibly the Twin, or maybe they have to emulate it!) which happens where an HDMA transfer starts shortly before a DMA transfer finishes. I can outline the bug if people need details, but it sounds unrelated to this problem.

I guess you've found a nice quirk in the FC Twin... :)

Post Reply