Specified the status of the VRAM DMA register once a transfer is done.#624
Specified the status of the VRAM DMA register once a transfer is done.#624Phidias618 wants to merge 6 commits intogbdev:masterfrom
Conversation
|
Hi, the state of this register after a transfer complete is already described here and here (for each transfer mode). I'm not sure if I prefer to have this info in a different section than the one describing the register behavior itself (like this PR suggesting) but I do believe we should have this info described in a single place (DRY 😄). What do you think? |
avivace
left a comment
There was a problem hiding this comment.
Yep, this information is already present (and twice) - we should have it only in 1 place and maybe link/quote that paragraph if helpful
|
These section only mentions the state of FF55 but not the state of FF51, FF52, FF53 and FF54, (these 4 register cannot be read from but knowing their state after a transfer is still useful for some purposes). That's why i added the section "State of the registers after a transfer", and i choose to include as a repeat the state of FF55 in this section in order for the section to be complete, even if that resulted in some duplicate information.
|
|
Personally I think this is the better option:
I completely missed the description of the FF51-FF54 registers and I think moving it to the section describing how the registers behaves will help people find it easily (the state of the register after transfer is done is tightly coupled to its behavior). |
alloncm
left a comment
There was a problem hiding this comment.
While reviewing this, another question came to mind - what happens if only one register is written to after a transfer, does it updates only the relevant bits (high or low part) or it reloads both registers from the last values written.
My intuition says only the relevant bits but maybe is worth checking?
Co-authored-by: alloncm <alloncm@gmail.com>
|
Why would writing to one of the register revert the state of the other register of the register pair? As i understand it, the CGB VRAM DMA is just a very fast loop, as such it needs to keep track where to copy the current byte from and where to copy the current byte to, and for convenience the CGB internally uses the source and destination registers directly for that purposes without copying the them to another location, as a consequence, both the source and destination registers are incremented by $10 for each successful transfer, but most of that is unknown to the developer as these registers are write only. |
| address in VRAM will cause garbage to be copied. | ||
|
|
||
| The four lower bits of this address will be ignored and treated as 0. | ||
| The address specified by those registers is cached internally and incremented by $10 for each block of $10 bytes successfully transferred. The cached address persists until the registers are written again. |
There was a problem hiding this comment.
I have a suggestion for different wording to hopefully convey the same info.
| The address specified by those registers is cached internally and incremented by $10 for each block of $10 bytes successfully transferred. The cached address persists until the registers are written again. | |
| Writing to either of these registers updates part of an internal persistent address, which also gets incremented by 16 for each tile transferred. |
|
To avoid any further confusion i have added a few examples. |
|
|
||
| The four lower bits of this address will be ignored and treated as 0. | ||
| After a transfer the address contained in this register pair is | ||
| by $10 for each block of $10 bytes transfered, these |
There was a problem hiding this comment.
Maybe this can be moved to a footnote (the fact that they cannot be observed directly etc)
|
Looks OK to me now, just a minor comment. |
alloncm
left a comment
There was a problem hiding this comment.
I believe the extra section adds unnecessary noise (and the examples don't add much that the inline description doesn't already cover).
IMO keeping this info inline under each register's section makes it easier to find and keeps the page cleaner.
| After a transfer the address contained in this register pair is | ||
| by $10 for each block of $10 bytes transfered, these | ||
| registers being write-only, this can only be observed by doing another | ||
| transfer without updating these registers. | ||
|
|
||
|
|
||
| #### FF53–FF54 — HDMA3, HDMA4 (CGB Mode only): VRAM DMA destination (high, low) \[write-only\] | ||
|
|
||
| These two registers specify the address within 8000-9FF0 to which the | ||
| data will be copied. Only bits 12-4 are respected; others are ignored. | ||
| The four lower bits of this address will be ignored and treated as 0. | ||
|
|
||
| #### State of the VRAM DMA source/destination registers after a transfer | ||
|
|
||
| After a transfer, the source/destination registers are incremented by $10 | ||
| for each block of $10 bytes transfered. | ||
| Despite both the VRAM DMA source/destination registers being write-only, | ||
| knowing their state after a transfer can turn useful when performing | ||
| multiple transfer in a row. | ||
| For instance, a transfer of one large block is mostly equivalent to | ||
| multiple transfers of smaller blocks, without needing to update the source | ||
| nor the destination registers between each of the smaller transfers. | ||
| Another use case would be to fill VRAM with the same $10 bytes block repeated | ||
| all over, as only the source address register would need be updated after each | ||
| transfer, the destination register being automatically incremented by | ||
| the block size after each transfer. | ||
|
|
||
|
|
There was a problem hiding this comment.
IMO the "State of the VRAM DMA source/destination registers after a transfer" is redundant and just add noise to the page.
I think the best way representing this info is by adding the lines you added to FF51-FF52 to FF53-FF54 too by just copy pasting it.
Something like this:
| After a transfer the address contained in this register pair is | |
| by $10 for each block of $10 bytes transfered, these | |
| registers being write-only, this can only be observed by doing another | |
| transfer without updating these registers. | |
| #### FF53–FF54 — HDMA3, HDMA4 (CGB Mode only): VRAM DMA destination (high, low) \[write-only\] | |
| These two registers specify the address within 8000-9FF0 to which the | |
| data will be copied. Only bits 12-4 are respected; others are ignored. | |
| The four lower bits of this address will be ignored and treated as 0. | |
| #### State of the VRAM DMA source/destination registers after a transfer | |
| After a transfer, the source/destination registers are incremented by $10 | |
| for each block of $10 bytes transfered. | |
| Despite both the VRAM DMA source/destination registers being write-only, | |
| knowing their state after a transfer can turn useful when performing | |
| multiple transfer in a row. | |
| For instance, a transfer of one large block is mostly equivalent to | |
| multiple transfers of smaller blocks, without needing to update the source | |
| nor the destination registers between each of the smaller transfers. | |
| Another use case would be to fill VRAM with the same $10 bytes block repeated | |
| all over, as only the source address register would need be updated after each | |
| transfer, the destination register being automatically incremented by | |
| the block size after each transfer. | |
| After a transfer the address pointed by those two registers equals `initial_address + ($10 * num_of_blocks_transferred)`. | |
| Since those are write-only registers, this can only be observed by doing another transfer without writing them again. | |
| #### FF53–FF54 — HDMA3, HDMA4 (CGB Mode only): VRAM DMA destination (high, low) \[write-only\] | |
| These two registers specify the address within 8000-9FF0 to which the | |
| data will be copied. Only bits 12-4 are respected; others are ignored. | |
| The four lower bits of this address will be ignored and treated as 0. | |
| After a transfer the address pointed by those two registers equals `initial_address + ($10 * num_of_blocks_transferred)`. | |
| Since those are write-only registers, this can only be observed by doing another transfer without writing them again. | |
There was a problem hiding this comment.
I've found that it makes sense to describe the overall functioning of the system in a single place, so that the reader can start to form a vague mental picture before getting into the individual components; otherwise, IME, the scattered information is very hard to assemble into the big picture. This line of reasoning is what has led us to creating the Graphics or Audio introduction pages.
There was a problem hiding this comment.
I pretty much agree with you about the overview sections for complex systems, I just don't think that this specific case (post-transfer register state) rises to that level.
It's niche enough that IMO most developers will never really need it, and I worry that a dedicated section gives it more focus than it deserves and risks burying the more critical parts about the VRAM DMA system.
ISSOtm
left a comment
There was a problem hiding this comment.
Thanks for the contribution! I think we may improve the flow of the page by making that section be a more general description of the VRAM DMA process, perhaps something like “VRAM DMA operation”? I think there's editorial work that can be done in reorganising this info into the neighbouring sections.
But, if @Phidias618 doesn't feel like going through that back-and-forth, please let me know and I can push some commits suggesting my changes; or, if you'd rather opt out of the entire review process, that's also fine, but please let us know so we don't end up pinging or waiting on you. Thanks!
I specified what the content of the VRAM DMA registers are once a transfer is done.
"The source and destination address regisers are both incremented by $10 bytes for each block of $10 bytes transfered after the transfer is done.
FF55 is always equal to $FF once the transfer ends."
It is useful information when multiple VRAM DMA transfer need to be performed in a row.
For example if one wants to fill VRAM with only 0 using one array of 16 null bytes as the source, as the destination address registers don't need to be updated after each transfer, but the source address registers always need to be reset back to the address of the begining of the source array after each transfer
Here is some assembly code that takes advantage of this in order to clear one bank of VRAM
_zero_x16 is an array of 16 null bytes, aligned on a 16 bytes boundary
clear_vram.s