It is currently Mon Dec 18, 2017 4:00 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Nintendo PPU-data format
PostPosted: Tue Nov 12, 2013 9:14 am 
Offline
User avatar

Joined: Sun Mar 19, 2006 3:06 am
Posts: 584
Location: Gothenburg/Sweden
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:
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.

_________________
http://nes.goondocks.se/


Top
 Profile  
 
PostPosted: Tue Nov 12, 2013 10:11 am 
Offline
User avatar

Joined: Sun Jan 02, 2011 11:50 am
Posts: 522
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:
.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


Top
 Profile  
 
PostPosted: Wed Nov 13, 2013 3:16 pm 
Offline
User avatar

Joined: Wed Oct 15, 2008 11:50 am
Posts: 939
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.


Top
 Profile  
 
PostPosted: Thu Nov 14, 2013 7:02 am 
Offline
NESICIDE developer
User avatar

Joined: Mon Oct 13, 2008 7:55 pm
Posts: 1058
Location: Minneapolis, MN
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."


Top
 Profile  
 
PostPosted: Thu Nov 14, 2013 7:39 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19355
Location: NE Indiana, USA (NTSC)
Tool building has clearer requirements and needs less art.


Top
 Profile  
 
PostPosted: Thu Nov 14, 2013 7:49 am 
Offline
User avatar

Joined: Wed Oct 15, 2008 11:50 am
Posts: 939
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:


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google [Bot] and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group