News:

11 March 2016 - Forum Rules

Main Menu

VRAM Address in DMA

Started by bluephoenix, November 26, 2017, 12:38:46 AM

Previous topic - Next topic

bluephoenix

I am tracing some DMA-related 65816 code and have a few questions. The (annotated) code is:

REP #$10 16-bit X

LDA #$80
STA $2115 VRAM increment 128 (128 words, 256 bytes?)

LDA #$18
STA $4301 destination address $??18

LDX $188E (7800)
STX $2116 VRAM address $7800

LDX #$4000
STX $4302
LDA #$70
STA $4304 source address $704000

LDX $1890 (0010)
STX $4305 transfer 16 (16 words, 32 bytes?)

LDA #$01   
STA $4300 DMA transfer: up, auto-increment 1 word

LDA #$01   
STA $420B enable DMA, channel 0


My questions are:

  • Since VRAM addresses are words, I assume storing #$20 to $2115 sets the increment to 128 words (256 bytes) for VRAM writes. Is this correct? (Similarly, storing #$10 to $4305 transfers 32 bytes (16 words), correct?)
  • The destination address stored to $4301 - is this an offset from the base VRAM address set later by $2116, meaning the data is written to $7818?
Thanks!

mopoz

DMA port $18 = $2118 (write data, see hardware regs)
$2116 - VRAM address $7800 = $F000 in HEXeditor
Skate-punk rulezzzz

bluephoenix

Quote from: mopoz on November 26, 2017, 02:28:35 AM
DMA port $18 = $2118 (write data, see hardware regs)
$2116 - VRAM address $7800 = $F000 in HEXeditor


Thanks! So $4301 sets the destination relative to $21xx. In this case it's $2118, the register for writing data to VRAM. $2116 sets which section of RAM is reserved for VRAM, in this case $7800. So DMA is configured to write to $2118 and the data is then found in RAM at $7800.

mziab

Quote from: bluephoenix on November 26, 2017, 11:55:45 AM

Thanks! So $4301 sets the destination relative to $21xx. In this case it's $2118, the register for writing data to VRAM. $2116 sets which section of RAM is reserved for VRAM, in this case $7800. So DMA is configured to write to $2118 and the data is then found in RAM at $7800.

I'm not sure if it's just bad phrasing, but no RAM is reserved for anything. VRAM is a completely separate address space on a separate chip, which has nothing to do with regular RAM. Thus the need to copy the data by using DMA like in your example.

You set the target VRAM address by writing two bytes to $2116. Then you set the source address by writing the address to $4202 (two bytes) and the source bank to $4204 (one byte). $4205 (two bytes) is for setting the number of bytes you want transferred.

One more thing of note is that although VRAM is 64kB (0000-FFFF), the target addressing above is word-based, so you need to halve the address, so it fits in the 0000-7FFF range. So to transfer to VRAM at F000, you write 7800 to $2116. Make sense?

That is the gist of it. Hope this helps.

jonk

Quote from: mziab on November 26, 2017, 03:18:46 PM
You set the target VRAM address by writing two bytes to $2116. Then you set the source address by writing the address to $4202 (two bytes) and the source bank to $4204 (one byte). $4205 (two bytes) is for setting the number of bytes you want transferred.

One more thing of note is that although VRAM is 64kB (0000-FFFF), the target addressing above is word-based, so you need to halve the address, so it fits in the 0000-7FFF range. So to transfer to VRAM at F000, you write 7800 to $2116. Make sense?
So, the only way to copy memory from RAM to VRAM is to use the provided DMA unit? (No shock, if so. Just asking.) And is the RAM address a byte address while the VRAM address is a word address?

Also: It would seem to make sense to me, ignorant as I am, that there is no need to copy from VRAM to RAM. Is that correct? Does the DMA work in only one direction?

Thanks!
An equal right to an opinion isn't a right to an equal opinion. -- 1995, me
Saying religion is the source of morality is like saying a squirrel is the source of acorns.  -- 2002, me

bluephoenix

Quote from: mziab on November 26, 2017, 03:18:46 PM
VRAM is a completely separate address space on a separate chip, which has nothing to do with regular RAM. Thus the need to copy the data by using DMA like in your example.

Thank you for the clarification!

Quote from: jonk on November 26, 2017, 11:57:24 PM
Also: It would seem to make sense to me, ignorant as I am, that there is no need to copy from VRAM to RAM. Is that correct? Does the DMA work in only one direction?

It's my understanding that DMA works in both directions. The transfer direction is configured by writing to $043x0- setting the high bit 0 transfers from A to B while 1 (#$80) transfers from B to A.

mziab

Quote from: jonk on November 26, 2017, 11:57:24 PM
So, the only way to copy memory from RAM to VRAM is to use the provided DMA unit? (No shock, if so. Just asking.) And is the RAM address a byte address while the VRAM address is a word address?

Yes, as far as I'm aware there is no going behind the back of the PPU when it comes to VRAM access. You need to use the facilities described above. Apart from doing block transfers, you can also write to $2118 word by word to update VRAM. This wastes a lot of precious vblank time, though, so it only makes sense for really miniscule amounts of data, say, flashing a cursor. Lastly, yes, only the VRAM address is word-based and needs to be halved when setting the register.

QuoteAlso: It would seem to make sense to me, ignorant as I am, that there is no need to copy from VRAM to RAM. Is that correct? Does the DMA work in only one direction?

Actually, you can read data from VRAM, but in practice there's rarely a reason to, especially since, like VRAM writes, you need to do it during vblank. And since you're dealing with data you transferred there yourself in the first place, this makes little sense, unless the data was generated (e.g. a variable-width font routine) and isn't readily available at a later point (RAM constraints?). I've only encountered VRAM reads once in the wild and this was in an old Gulliver Boy translation patch and I'm not sure this was good practice and absolutely necessary, or just what the hacker was the most comfortable using.

optiroc

Quote from: jonk on November 26, 2017, 11:57:24 PM
So, the only way to copy memory from RAM to VRAM is to use the provided DMA unit? (No shock, if so. Just asking.) And is the RAM address a byte address while the VRAM address is a word address?

Also: It would seem to make sense to me, ignorant as I am, that there is no need to copy from VRAM to RAM. Is that correct? Does the DMA work in only one direction?

Thanks!
The limitation is rather that the only way to access VRAM is via the data registers (2118/9 for writing, 2139/A for reading). You can bang these ports however you want, but it's quite unusual to do it with the normal load/store CPU instructions.

KingMike

Quote from: jonk on November 26, 2017, 11:57:24 PM
So, the only way to copy memory from RAM to VRAM is to use the provided DMA unit? (No shock, if so. Just asking.) And is the RAM address a byte address while the VRAM address is a word address?

Also: It would seem to make sense to me, ignorant as I am, that there is no need to copy from VRAM to RAM. Is that correct? Does the DMA work in only one direction?

Thanks!

You can write to $2118/2119 directly to send data to VRAM (to the VRAM word address stored in $2116-2117) but there is usually no need to, since often data written to VRAM (such as graphics) is usually large enough that writing to the DMA registers is better. (DMA takes more setup, but can write faster than manual loops)
I recall one game I hacked, Magna Braban, doing that for the graphics decompression routine. Maybe they did that for some kind of intentional timing delay. As I recall, converting from an iterative loop to a DMA routine caused it to break, at least maybe on better emulators (than the ZSNES and SNES9X which were out at the time the translation patch was originally created).

But one game I remember is a famously shitty game called Maka-maka.
They had the concept of DMA completely backwards, they set up DMA writes to write a single byte at a time to WRAM (not even VRAM, the console RAM) while they used manual loops (not even the CPU's block-write instructions) to copy 64K at a time.
This results in a cartridge game that has even worse load times the some of the famously slow early CD-based games.

And the out-of-battle spell menu ignores which character the player selects from the character-select menu and only allows the main protagonist to chose spells.
To release an RPG with such a basic functionality as casting spells outside of battle broken is astounding. :P

The credits are apparently broken too, but we almost have to wonder the programmers purposely glitched it to kind of Alan-Smithee themselves. :D
"My watch says 30 chickens" Google, 2018

jonk

Thanks to all who helped me understand the DMA and RAM/VRAM systems a little better. It may come in handy as I help my son with his 65816 programming efforts (which actually he is currently doing even as we speak.) Every little bit helps! Much appreciated!
An equal right to an opinion isn't a right to an equal opinion. -- 1995, me
Saying religion is the source of morality is like saying a squirrel is the source of acorns.  -- 2002, me