Clearing the memory after RESET.

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
ludoVIC
Posts: 31
Joined: Fri Jan 08, 2021 8:36 am

Clearing the memory after RESET.

Post by ludoVIC » Fri Jan 22, 2021 4:32 am

In the Nerdy Nights tutorial, the CPU RAM is usually cleared after the RESET operation. Code:

Code: Select all

CLRMEM:
  lda #$00
  sta $0000, x
  sta $0100, x
  sta $0300, x
  sta $0400, x
  sta $0500, x
  sta $0600, x
  sta $0700, x
  lda #$FE 
  sta $0200, x
  inx
  bne CLRMEM
  rts
My question is: why do we assign the value #$FE to the range $0200-$02FF, instead of zero as in the remaining cases?
I think it is "because" these addresses are used for DMA access when loading Sprites, but then what are the advantages of #$FE over #$00?

User avatar
never-obsolete
Posts: 399
Joined: Wed Sep 07, 2005 9:55 am
Location: Phoenix, AZ
Contact:

Re: Clearing the memory after RESET.

Post by never-obsolete » Fri Jan 22, 2021 5:25 am

Page 2 is commonly used for sprite DMA, but is not a requirement of the hardware itself. Based on the code you posted, it seems like the NN tutorial does just that.

Having a Y and X position of $00 would put all sprites in the upper left corner, possibly in view of the player, while $FE ensures that they are not visible.
. That's just like, your opinion, man .

Pokun
Posts: 1746
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Clearing the memory after RESET.

Post by Pokun » Sat Jan 23, 2021 10:59 am

Yes using RAM page 2 ($0200-$02FF) as an OAM buffer is a convention used by most licensed NES games, and Nerdy Nights follows this convention as well. Technically you could use any RAM page for the OAM buffer, but there is no point in not following the convention. The page used as the OAM buffer is determined by what value you write to $4014 each vblank (writing $02 means page 2).

It's only the the Y-position that needs to be $FE to hide the sprites, the other bytes can be 0 if you want (though that requires some extra code). The value $FE seems arbitrary though, so I'm not sure why Nerdy Nights choose this particular odd value, as any Y-value between $EF-$FF will hide the sprite according to the wiki).




Note that Nerdy Nights makes a mistake in it's commenting which confused me back when I learned from it:

Code: Select all

  LDA #$00
  STA $2003  ; set the low byte (00) of the RAM address
  LDA #$02
  STA $4014  ; set the high byte (02) of the RAM address, start the transfer
This sounds like you set the RAM address of your OAM buffer to $2003 and $4014 (which is a very odd choice of registers considering $2xxx registers are PPU related and $4xxx registers are CPU/APU related), but that is wrong. Only $4014 affects the OAM buffer's address, and it assigns the whole RAM page (256 byte) in a single byte write. You write to $2003 only to set the OAM write address (used by both manual OAM writes and writes done by OAM-DMA) to $00 to make sure the OAM-DMA starts writing from the beginning of OAM. Since OAM is only 256 byte large, you only need a single byte to set the OAM write address (so there is no need for a high and low byte here). The DMA is performed by hardware inside the CPU chip, which explains why a $4xxx register is used to set and start the DMA process.
This is an infamous misconception that I believe comes from an older tutorial by GBAGuy.

The comments should therefore look like this:

Code: Select all

  LDA #$00
  STA $2003  ; set the destination OAM address to $00
  LDA #$02
  STA $4014  ; set the source RAM page (2), start the transfer
The code is correct though, so no need to change anything but the comments.

ludoVIC
Posts: 31
Joined: Fri Jan 08, 2021 8:36 am

Re: Clearing the memory after RESET.

Post by ludoVIC » Thu Jan 28, 2021 8:31 am

Thank you for your answers!
Roughly speaking, the code above clear all the memory with zeroes, except for the $0200 addresses where #$FF are used instead.
This is because these addresses relate to the sprites' DMA operations, so high coordinates like #$FF make the sprites disappear.
In other word, it is a sort of "clear screen" instruction.

Now, a comment concerning the $2003 address. Thanks for having clarified their true meaning, but there is a point that I might have misunderstood.
By doing something like:

Code: Select all

  LDA #$04
  STA $2003  ; set the OAM address to....#$04?
  LDA #$02
  STA $4014  ; set the source RAM page (2), start the transfer
are we setting the DMA operations only in the range $0204-02FF, ignoring therefore the first sprite?
Because I tested with a couple of examples, but it doesn't seem so: all the sprites are always load.

User avatar
Quietust
Posts: 1684
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: Clearing the memory after RESET.

Post by Quietust » Thu Jan 28, 2021 8:38 am

ludoVIC wrote:
Thu Jan 28, 2021 8:31 am
By doing something like:

Code: Select all

  LDA #$04
  STA $2003  ; set the OAM address to....#$04?
  LDA #$02
  STA $4014  ; set the source RAM page (2), start the transfer
are we setting the DMA operations only in the range $0204-02FF, ignoring therefore the first sprite?
Because I tested with a couple of examples, but it doesn't seem so: all the sprites are always load.
No, it will copy $0200-$02FB to Sprite RAM addresses $04-$FF and copy $02FC-$02FF to Sprite RAM addresses $00-$03.

For the most part, writing #$02 to $4014 is equivalent to doing this (except it's far faster and doesn't modify the X register):

Code: Select all

        LDX #$00
loop:   LDA $0200,X
        STA $2004
        INX
        BNE loop
In most emulators, this will just result in all of the sprites being shifted down by one slot (i.e. sprites 0-62 become 1-63, and sprite 63 becomes sprite zero), but on real hardware (especially NTSC) this can result in some sprites being corrupted (due to timing glitches within the PPU with regard to how writes to $2003 are handled).
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

ludoVIC
Posts: 31
Joined: Fri Jan 08, 2021 8:36 am

Re: Clearing the memory after RESET.

Post by ludoVIC » Thu Jan 28, 2021 9:48 am

No, it will copy $0200-$02FB to Sprite RAM addresses $04-$FF and copy $02FC-$02FF to Sprite RAM addresses $00-$03.
I think I got it. So, the DMA operation always involves 256 bytes, and in $2003 we communicate where to start the writing, moving then "cyclically", right?

Finally, that's interesting to see the "real" meaning of writing to $4014.
I can imagine how copying the sprite data is a critical operation for the NES performance: therefore, instead of manually writing them every time,
the constructor encoded it more efficiently into a single operation - nice.

Pokun
Posts: 1746
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Clearing the memory after RESET.

Post by Pokun » Fri Jan 29, 2021 7:35 am

Yes the OAM address wraps to 0 after 255. That is the intended behavior anyway, but as Quietust said due to PPU timing bugs it might not work correctly if you write any other value, so you should always write 0 to $2003 right before the OAM-DMA to guarantee that everything works.

Yeah DMA is some hardware in the CPU that connects directly to the OAM memory in the PPU and copies data to it many times much faster than you could do with the manual method of LDA and STA pairs to the PPU port registers ($2004 in the case of OAM). Besides the manual method doesn't work correctly for the OAM on the NTSC Famicom/NES due to bugs in the PPU (in other words $2004 is pretty worthless for games).

And yes I think sprite updates is a bottleneck for screen updates, lots of data that are changing all the time. So using DMA hardware for sprites makes sense.

The NES only has DMA set up for sprites (OAM) but on other consoles like the PC-Engine, Mega Drive, SNES and Game Boy Color you have DMA for other things like nametable characters, pattern tables and palette making them much faster at uploading more data to the video chip (though these systems also have much more data to upload). On the Mega Drive they basically like to call it "Blast Processing™".

ludoVIC
Posts: 31
Joined: Fri Jan 08, 2021 8:36 am

Re: Clearing the memory after RESET.

Post by ludoVIC » Fri Jan 29, 2021 8:05 am

Fantastic, and for today too, a new interesting fact is learnt !
...thanks to everybody for the help, very appreciated :beer:

Post Reply