SNES DMA write pattern

Strictly for discussing ZSNES development and for submitting code. You can also join us on IRC at irc.libera.chat in #zsnes.
Please, no requests here.

Moderator: ZSNES Mods

Post Reply
kammedo
Rookie
Posts: 11
Joined: Mon Oct 18, 2004 5:26 pm

SNES DMA write pattern

Post by kammedo »

I know this may sound strange, but :
could someone explain to me one time and for all the way 32x32, 64x64 etc write modes selectable in $2115 works?
smkdan
Hazed
Posts: 88
Joined: Sun Dec 19, 2004 4:55 am

Post by smkdan »

You might want to clear that up because I don't think anyone will get much sense out of that post.

If you mean writing to tile maps, then the Increment mode of 32 words will help alot. You can write to a column of tile map entries in succession because each row of entries happens ot be 64 bytes long. If you're in 64x64 mode you can just change the target tilemap.

If you're talking about 'address translation' then I don't have a clue. The concept is simple but I'm having alot of trouble finding a good scenario where it will come in handy. Someone please enlighten me :?:.

Also, development forum is the place for this. Any SNES development including ZSNES goes over there.
kammedo
Rookie
Posts: 11
Joined: Mon Oct 18, 2004 5:26 pm

Post by kammedo »

smkdan wrote:
Also, development forum is the place for this. Any SNES development including ZSNES goes over there.
Great. Sorry for the wrong posting, first post here and too lazy to check for the right forum to post. Mod's feel free to move !!!
smkdan wrote: If you mean writing to tile maps, then the Increment mode of 32 words will help alot. You can write to a column of tile map entries in succession because each row of entries happens ot be 64 bytes long. If you're in 64x64 mode you can just change the target tilemap.

If you're talking about 'address translation' then I don't have a clue. The concept is simple but I'm having alot of trouble finding a good scenario where it will come in handy. Someone please enlighten me :?:.
Yes actually that's what I dont get. How does DMA map its writes to the VRAM addres space accordingli to the settings of $2115?

for example : 32x32 means
a) write word at Offset $xxxxxx to VRAM $0000
b) write word at Offset $yyyyyy to VRAM $0020
c) write word at Offset $zzzzzz to VRAM $0040
.
.
.

and so on? How many times? 32? Or for size_of_the_DMA_tx times?
Also, if it writes 32 times in steps of 32 bytes, does it write the same value (aka takes it from the same source offset) 32 times?
sou you would have

a) write #$FFFF to VRAM $0000
b) write #$FFFF to VRAM $0020
c) write #$FFFF to VRAM $0040
.
.
.
?
Please enlighten me!
byuu

Re: SNES DMA write pattern

Post by byuu »

DMA has nothing to do with $2115. DMA just writes to registers $2118/$2119 that subsequently map where to write to VRAM at. There are two separate settings for $2115 writes: mapping and increment size. The code is more descriptive than anything I could say ...

Code: Select all

//VMAIN
void mmio_w2115(uint8 value) {
  regs.vram_incmode = !!(value & 0x80);
  regs.vram_mapping = (value >> 2) & 3;
  switch(value & 3) {
  case 0: regs.vram_incsize =   1; break;
  case 1: regs.vram_incsize =  32; break;
  case 2: regs.vram_incsize = 128; break;
  case 3: regs.vram_incsize = 128; break;
  }
}

//VMDATAL
void mmio_w2118(uint8 value) {
uint16 addr = get_vram_address();
  vram_mmio_write(addr, value);
  if(regs.vram_incmode == 0) {
    regs.vram_addr += regs.vram_incsize;
  }
}

//VMDATAH
void mmio_w2119(uint8 value) {
uint16 addr = get_vram_address() + 1;
  vram_mmio_write(addr, value);
  if(regs.vram_incmode == 1) {
    regs.vram_addr += regs.vram_incsize;
  }
}

uint16 get_vram_address() {
uint16 addr = regs.vram_addr;
  switch(regs.vram_mapping) {
  //mere mortals dare not try and understand the below bit blender ...
  case 0: break;
  case 1: addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7); break;
  case 2: addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7); break;
  case 3: addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7); break;
  }
  return (addr << 1);
}
VRAM reads are even more fun, but I'll spare you those details as you didn't ask :)
kammedo
Rookie
Posts: 11
Joined: Mon Oct 18, 2004 5:26 pm

Re: SNES DMA write pattern

Post by kammedo »

byuu wrote:DMA has nothing to do with $2115. DMA just writes to registers $2118/$2119 that subsequently map where to write to VRAM at. There are two separate settings for $2115 writes: mapping and increment size. The code is more descriptive than anything I could say ...

Code: Select all

//VMAIN
void mmio_w2115(uint8 value) {
  regs.vram_incmode = !!(value & 0x80);
  regs.vram_mapping = (value >> 2) & 3;
  switch(value & 3) {
  case 0: regs.vram_incsize =   1; break;
  case 1: regs.vram_incsize =  32; break;
  case 2: regs.vram_incsize = 128; break;
  case 3: regs.vram_incsize = 128; break;
  }
}

//VMDATAL
void mmio_w2118(uint8 value) {
uint16 addr = get_vram_address();
  vram_mmio_write(addr, value);
  if(regs.vram_incmode == 0) {
    regs.vram_addr += regs.vram_incsize;
  }
}

//VMDATAH
void mmio_w2119(uint8 value) {
uint16 addr = get_vram_address() + 1;
  vram_mmio_write(addr, value);
  if(regs.vram_incmode == 1) {
    regs.vram_addr += regs.vram_incsize;
  }
}

uint16 get_vram_address() {
uint16 addr = regs.vram_addr;
  switch(regs.vram_mapping) {
  //mere mortals dare not try and understand the below bit blender ...
  case 0: break;
  case 1: addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7); break;
  case 2: addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7); break;
  case 3: addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7); break;
  }
  return (addr << 1);
}
VRAM reads are even more fun, but I'll spare you those details as you didn't ask :)
Thanks byuu! ^^
Thats exactly what I was looking for!
Nice to see your emulator is coming so well along !
Post Reply