HDMA examples: Difference between revisions

From SNESdev Wiki
Jump to navigationJump to search
(→‎Non-repeat HDMA entries: Add annotated Mesen-S screenshots)
(→‎HDMA Tables: If Line-Counter is 0x80: count = 128, repeat flag = 0)
Line 81: Line 81:
  |+++-++++- Number of scanlines (count)
  |+++-++++- Number of scanlines (count)
  +--------- Repeat flag
  +--------- Repeat flag
If byte == 0x00:  End of HDMA table
If byte == 0x80:  count = 128, repeat flag = 0




=== Non-repeat HDMA entries ===
=== Non-repeat HDMA entries ===


A non-repeat HDMA entry (bit-7 of ''Line-Counter'' clear) is <tt>hdma_transfer_bytes + 1</tt> bytes in size.  It consist of the ''Line-Counter'' byte, followed by the data to transfer on the next Horizontal Blanking Period.  Afterwards, the HDMA controller will wait for ''count'' (bits 0-6 of ''Line-Counter'') scanlines before processing the next HDMA entry.
A non-repeat HDMA entry (bit-7 of ''Line-Counter'' clear or ''Line-Counter'' == <tt>0x80</tt>) is <tt>hdma_transfer_bytes + 1</tt> bytes in size.  It consist of the ''Line-Counter'' byte, followed by the data to transfer on the next Horizontal Blanking Period.  Afterwards, the HDMA controller will wait for ''count'' (bits 0-6 of ''Line-Counter'') scanlines before processing the next HDMA entry.
 
If the ''Line-Counter'' byte is <tt>0x80</tt>, the HDMA entry is a non-repeating entry that will wait 128 scanlines.




Line 108: Line 113:




Each non-repeat HDMA entry is a maximum of 127 scanlines tall.  Any HDMA entry with more then 127 scanlines must be split in two, with each entry containing the same data values.
Each non-repeat HDMA entry is a maximum of 128 scanlines tall.  Any HDMA entry with more then 128 scanlines must be split in two, with each entry containing the same data values.


<pre>
<pre>
Line 115: Line 120:
     // 160 scanlines with BG1HOFS = 0
     // 160 scanlines with BG1HOFS = 0
     // Too many scanlines to fit in a single HDMA entry.
     // Too many scanlines to fit in a single HDMA entry.
     db  127            // 127 scanlines, non-repeat entry (maximum number of scanlines per entry)
     db  127            // 127 scanlines, non-repeat entry
         dw  0
         dw  0
   
   

Revision as of 05:42, 25 November 2022

Examples for using HDMA.


Transfer patterns

The following is a suggested list of PPU registers that can be used in the various HDMA transfer patterns.


One register (DMAP pattern 0)

This pattern reads/writes a single byte to a single address on the B-bus (+0).

This pattern should not be used on write-twice or read-twice registers.

  • BG Mode: BGMODE
  • Mosaic Settings: MOSAIC
  • BG Settings: BG1SC, BG2SC, BG3SC, BG4SC, BG12NBA, BG34NBA
  • Mode 7 settings: M7SEL
  • CGRAM address: CGADD
    • A future HDMA channel should write to CGDATA on the same scanline as the CGADD write.
  • Window settings: W12SEL, W34SEL, WOBJSEL, WBGLOG, WOBJLOG
  • Layer enable: TM, TS, TMW, TSW
  • Color math: CGWSEL, CGADSUB
  • Screen Mode/Video Select: SETINI
  • Fixed color data: COLDATA
    • Only a single B/G/R channel can be changed in this pattern (unless multiple channels contain the same value). See COLDATA for more details.


Two registers (DMAP pattern 1)

This pattern reads/writes two bytes to two addresses on the B-bus (+0, +1). It is useful when writing to two adjacent byte registers.

This pattern must not be used on write-twice or read-twice registers.

  • Window 1 left and right position: WH0 & WH1
  • Window 2 left and right position: WH2 & WH3
  • Window mask settings: W12SEL & W34SEL, W34SEL & WOBJSEL
  • Window mask logic: WBGLOG & WOBJLOG
  • Layer Enable: TM & TS, TMW & TSW
  • Color math settings: CGWSEL & CGADSUB


One register, write twice (DMAP pattern 2)

This pattern reads/writes two bytes to a single write-twice or read-twice register on the B-bus (+0, +0).

  • BG horizontal scroll offset: BGnHOFS
  • BG vertical scroll offset: BGnVOFS
  • Mode 7 matrix: M7A, M7B, M7C, M7D, M7X, M7Y
  • CGRAM data: CGDATA
    • Note: A previous HDMA channel should set the CGRAM address on the same scanline as a CGDATA write
  • Fixed color data: COLDATA
    • Only two of the three B/G/R channels can be changed in this pattern (unless two channels share the same value). See COLDATA for more details.


Two registers, write twice (DMAP pattern 3)

This pattern reads/writes four bytes to two adjacent write-twice or read-twice registers on the B-bus (+0, +0, +1, +1).

  • BG scroll offsets: BGnHOFS & BGnVOFS
  • 2 adjacent mode 7 matrix values: M7A & M7B, M7C & M7D, M7X & M7Y
  • CGRAM address and data: CGADD & CGDATA
    • This transfer will write two values to the CGRAM address, followed by a color word value to CGDATA.
    • The first byte will be ignored by the PPU, the second byte contains the target CGRAM address (palette index), the third and forth bytes contain the color data.


Four registers (DMAP pattern 4)

This pattern reads/writes four bytes to four addresses on the B-bus (+0, +1, +2, +3).

This pattern must not be used on write-twice or read-twice registers.

  • All four window positions: WH0 & WH1 & WH2 & WH3


HDMA Tables

HDMA tables are made up of multiple HDMA entries. Each entry starts with a Line-Counter byte, followed by register data. If the Line-Counter byte is 0, the HDMA channel will be deactivated and will remain deactivated until the start of the next frame.

Line-Counter byte:

7  bit  0
---- ----
RLLL LLLL
|||| ||||
|+++-++++- Number of scanlines (count)
+--------- Repeat flag

If byte == 0x00:  End of HDMA table
If byte == 0x80:  count = 128, repeat flag = 0


Non-repeat HDMA entries

A non-repeat HDMA entry (bit-7 of Line-Counter clear or Line-Counter == 0x80) is hdma_transfer_bytes + 1 bytes in size. It consist of the Line-Counter byte, followed by the data to transfer on the next Horizontal Blanking Period. Afterwards, the HDMA controller will wait for count (bits 0-6 of Line-Counter) scanlines before processing the next HDMA entry.

If the Line-Counter byte is 0x80, the HDMA entry is a non-repeating entry that will wait 128 scanlines.


// HDMA Table targeting the `TM` register (One register transfer pattern).
HdmaTable:
    db  32              // 32 scanlines, non-repeat entry
        db  0x13        // TM = BG1, BG2, OBJ

    db  64              // 64 scanlines, non-repeat entry
        db  0x04        // TM = BG3

    db  1               // 1 scanline
        db  0x13        // TM = BG1, BG2, OBJ

    db  0               // End HDMA table

Annotated Mesen-S Event Viewer screenshot of a HDMA to the BG1HOFS register



Each non-repeat HDMA entry is a maximum of 128 scanlines tall. Any HDMA entry with more then 128 scanlines must be split in two, with each entry containing the same data values.

// HDMA Table for the `BG1HOFS` register (one register, write twice transfer pattern).
HdmaTable:
    // 160 scanlines with BG1HOFS = 0
    // Too many scanlines to fit in a single HDMA entry.
    db  127             // 127 scanlines, non-repeat entry
        dw  0
 
    db  33              // 33 scanlines, non-repeat entry (+127 = 160 scanlines total)
        dw  0           // Same data value as the previous entry
 
 
    // Change BG1HOFS every 16 scanlines
    db  16              // 16 scanlines, non-repeat entry
        dw  -2
 
    db  16              // 16 scanlines, non-repeat entry
        dw  -4
 
    db  16              // 16 scanlines, non-repeat entry
        dw  -6
 
    db  16              // 16 scanlines
        dw  -8
 
    db  0               // End HDMA table

Annotated Mesen-S Event Viewer screenshot of a HDMA to the BG1HOFS register

Links