Page 1 of 1

Nintendo PPU-data format

Posted: Tue Nov 12, 2013 9:14 am
by oRBIT2002
I've discovered that Nintendo often uses the same way of storing PPU data into their NES-games. I was on my way writing some kind of ripper-tool but got a bit bored so I might never finish it, so perhaps someone else is interested in my findings.
The structure looks like this:

Code: Select all

dc.w PPUAddress (hi+lowbyte)
dc.b CONTROL
dc.b DATA (*CONTROL.LENGTH)
The structure can be repeated as a list (PPUAddress,Control,Data,PPUAddress,Control,Data etc.) and is terminated by a $0.

CONTROL has a few features:
bit 5-0 = LENGTH (number of bytes to insert).
bit 6 = RLE mode (1=Active)
bit 7 = PPU Write mode (0=Increment by 1, 1=Increment by 32)

When RLE mode is active (=1), DATA byte is inserted <CONTROL.LENGTH> number of times.

Re: Nintendo PPU-data format

Posted: Tue Nov 12, 2013 10:11 am
by Movax12
Slightly modified code from Super Mario Brothers to write such data to PPU: (using HL macros in ca65)

Note this is sub-optimal code: it's pretty slow compared to some techniques, but fast enough for many games:

Code: Select all

.proc WriteVRAMBufferToScreen                         

    ; Note: execution is to start at label: UpdateScreen
    ; register y is used to index the Buffer
    ; needed: 
    ;    define location for temp_word
    ;    define Mirror_PPU_CTRL

    .export ResetScroll, UpdateScreen

    VRAM_Buffer_pointer = temp_word
    
    repeat

        ; set PPU vram address:
        mb PPU_ADDRESS := a
        iny
        mb PPU_ADDRESS := (VRAM_Buffer_pointer)[ y ]
        iny

        ; load next third byte in stream, shift to the left and save in stack:
        mb a := (VRAM_Buffer_pointer)[ y ] << 1
        pha

            ; set ppu to increment by 32 by default
            mb a := Mirror_PPU_CTRL | #%00000100

            ; if d7 of third byte was clear, ppu will increment address by 1 byte every write:
            if carry clear
                mb a := a & #%11111011
            endif

            ; write contents of A to PPU_CTRL:
            sta PPU_CTRL
        ; restore a
        pla
        
        ; if d6 of third byte is set, repeat byte:
        if a << 1 == carry set
            ; set d1, which will be shifted right and become carry
            ; and increment the index by one only
            ora #%00000010
            iny
        endif

        ; shift back to the right twice to restore length value
        ; carry will be set now if repeat byte bit was set
        mb a := a >> 2
        
        ; copy length into x
        mb x := a
        ; loop and write data to vram:
        repeat
            ; only increment index if this is not a repeating value:
            if carry clear
                iny       
            endif
            mb PPU_DATA := (VRAM_Buffer_pointer)[ y ]
        until dex == zero

        ; add end length plus one to the indirect at VRAM_Buffer_pointer
        sec
        ; copy index to a
        mb a := y
        ; add index to pointer base:
        mb VRAM_Buffer_pointer      := a +c VRAM_Buffer_pointer
        mb VRAM_Buffer_pointer[ 1 ] := VRAM_Buffer_pointer[ 1 ] + C

        ; start here:
        UpdateScreen:

        ; reset latch and load y with index zero
        ldx PPU_STATUS
        ldy #0

        ; if not zero, write to vram again:
    until lda (VRAM_Buffer_pointer)[ y ] == zero

    ResetScroll:
    sta PPU_SCROLL
    sta PPU_SCROLL
    rts
.endproc

Re: Nintendo PPU-data format

Posted: Wed Nov 13, 2013 3:16 pm
by qbradq
That's pretty cool that they had some sort of shared libraries back in the day. When I was working on my NES software projects (before falling into the tool building trap :oops: ) I used a similar, all-be-it more simplistic format for my PPU updates.

Re: Nintendo PPU-data format

Posted: Thu Nov 14, 2013 7:02 am
by cpow
qbradq wrote:(before falling into the tool building trap :oops: )
Ah yes..."I'd rather write programs that help write programs than write programs." Been there, living that! :lol:
The quote is referenced in a wonderful book I wish everyone in software management and software development would read. Sadly, though, as the author mentions [in quoting Joel Spolsky], "most software engineers don't read enough [or anything] about their own field."

Re: Nintendo PPU-data format

Posted: Thu Nov 14, 2013 7:39 am
by tepples
Tool building has clearer requirements and needs less art.

Re: Nintendo PPU-data format

Posted: Thu Nov 14, 2013 7:49 am
by qbradq
tepples wrote:Tool building has clearer requirements and needs less art.
Word.

Plus, once I'm done with the tool I'll be able to pump out games lightning fast!

:lol: