Reserving Zeropage?

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
dsilberg
Posts: 3
Joined: Sat Aug 06, 2022 7:07 am

Reserving Zeropage?

Post by dsilberg »

I'm working through the https://famicom.party tutorial/ebook and it's going really well. It's a great tutorial and it's well written and approachable for somebody completely new to nesdev. I'm mostly through the book but I'm stumbling on a few statements and would love an assist from somebody more experiened.

In the section on Sprite Movement: https://famicom.party/book/14-spritemovement/ the book discusses initializing some zeropage memory, and discusses how to do that, and also how to make the symbols available to the rest of the code. That makes sense, but I'm hung up on this statement:
Let's start using zero-page RAM in our code. Because only addresses from $8000 and up are ROM (i.e., part of your actual cartridge / code that you write), we can't just write zero page values directly. Instead, we tell the assembler to reserve memory in page zero, like this:

Code: Select all

.segment "ZEROPAGE"
player_x: .res 1
player_y: .res 1
specifically "we can't just write zero page values directly"

Can't we? I'm sure that the assembler (ca65) wouldn't complain if I referred to a memory address directly, such as

Code: Select all

LDA $01
My hunch is that what he's trying to say is that if you want to declare a VARIABLE (label) and point it at a memory address, you can't just initialize it with a byte directly and expect it to land in zeropage. But even that doesn't totally make sense to me. Would this be invalid (or function in a way I don't expect)?

Code: Select all

.segment "ZEROPAGE"
player_x: 
.byte $00
player_y: 
.byte $00
Again, my hunch is that the assembler is doing some things here that are hidden to me. That if I want to use ZP addressing, I'm welcome to, but that if I want to use some more sophisticated features of the assembler, I need to speak the language of that assembler. In this case, stating that things need to happen in ZP, but then being limited to what I can actually do in the "ZEROPAGE" segment.

Finally, I notice that the book reserves and initializes the ZP mem separately. Is there a reason it doesn't use the single instruction to do both? For example:

Code: Select all

.segment "ZEROPAGE"
player_x: .res 1, $80
Thanks in advance. I look forward to the day I'm answering questions here instead of asking them :)
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Reserving Zeropage?

Post by rainwarrior »

All of your ROM code is in a separate memory area than the NES's RAM, so nothing in RAM is initialized at startup.

If you want to initialize ZP or other RAM you have to write code to copy values to it.

cc65 has a default segment "DATA" which has an associated "copydata" utility subroutine called at startup that copies a block of initialization values into the place in RAM that the DATA segment resides. If using assembly rather than C, you'll probably have to set up something similar for yourself if you need it. Most of my projects have some startup code that just initializes all of NES RAM to 0.

Otherwise you could write lda/sta to set each variable up at the time it's needed.

And yes, you could just address them by number instead of label if you want, but usually .res with labels is less error prone and easier to work with.


So, if you set up your segment as "bss" or "zp", it's uninitialized and it should give you an error if you try to put a ".byte" in it. If you set up the segment as "rw", it could be used as an initialized RAM segment (though you have to add your own code to do the initialization).

The reason ".res" doesn't have a value option is that ".byte" already does everything that would do. The size of reservation made by ".byte" in an initialized segment is already just the number of bytes. ".res" was made to reserve space only.


On some platforms (e.g. Apple II, C64) programs are loaded into RAM instead of ROM, and "rw" segments might be automatically initialized by the loading of the program. Not on NES, though.

All of this is normally determined by your project's .cfg file, used by the linker ld65. Documentation here.
dsilberg
Posts: 3
Joined: Sat Aug 06, 2022 7:07 am

Re: Reserving Zeropage?

Post by dsilberg »

Thanks for the informative reply. Much appreciated.

I think this is my key takeaway:
And yes, you could just address them by number instead of label if you want, but usually .res with labels is less error prone and easier to work with.
I wrote some assembly without using the features of the assembler and it's challenging to keep it all straight. Definitely easier if "variables" can be used, and I could even see how this might support porting the code into another platform (at some point). I'm sure there's a lot more complexity there.
Post Reply