Basic question about RAM and pointers

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
casprog
Posts: 70
Joined: Fri Oct 28, 2016 12:37 pm

Basic question about RAM and pointers

Post by casprog »

Hello,

I want to reserve a small chunk of RAM as a PPU buffer, so to test a small concept first I have:

Code: Select all

LDA #$06
STA $80

LDA #$07
STA $80 + 1

LDA #$08
STA $80 + 2
So just storing values 6, 7, and 8 in memory locations $80 through $80 + 2.

I tested this using Indirect Indexing which works:

Code: Select all

LDA ($80), y
; do stuff
First question is, by writing to $80 I'm still in Zero Page correct? And am writing into NES RAM? If nothing else in my code explicitly touches $80 through $80 + 2, can anything else from the NES alter those values in any way?

Last question is, when I try to make a pointer to $80 my Indirect Indexing no longer seems to work. So instead of writing $80, I wanted to write something descriptive.

I tried setting the pointer like so:

Code: Select all

ppuBufferPtr .rs 1
.......
LDA $80
STA ppuBufferPtr
.......
LDA [ppuBufferPtr], y ; also tried LDA (ppuBufferPtr), y
But no luck. My comparisons don't match up like when I use the memory address directly.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Basic question about RAM and pointers

Post by tepples »

lda ($80),Y: Look up the 16-bit address stored in $0080 and $0081, add Y, and use that as the address

That's probably not what you want if you're using $0080-$00FF as a VRAM transfer buffer. What you're more likely to want is this:

lda $80,Y: Add Y to $0080 and use that as the address

But there usually isn't much advantage of storing an array on zero page unless A. you're strapped for code size or B. you're going to store X or Y (as opposed to A) to this array often. I tend to keep my VRAM transfer buffers in $0100-$019F and never let the stack pile up that high.


Advanced corner (newbies may skip without missing anything)
The third use for an array on zero page is an array of pointers with which you use the rarely used (d,X) addressing mode. I haven't seen a good use for (d,X) outside A. music engines, which need to seek in parallel streams one per channel, and B. the Missile Command arcade hardware, whose memory controller detected (d,X) mode opcodes and used them as a special case to rearrange the frame buffer as packed pixels.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Basic question about RAM and pointers

Post by tokumaru »

casprog wrote:

Code: Select all

LDA #$06
STA $80

LDA #$07
STA $80 + 1

Code: Select all

LDA ($80), y
; do stuff
This would load into A the value at memory location $0706+y. Is that what you intended? Unless you're using NESASM, in which case I think the LDA ($80), y would assemble to LDA $80, y, so the value at $0080+y would end up in the accumulator.
First question is, by writing to $80 I'm still in Zero Page correct? And am writing into NES RAM?
Yes, zero page is RAM. For the 6502, the 64KB address space is conceptually divided into 256 pages of 256 bytes. Page zero is the first page, where addresses have $00 as the high byte (i.e. $0000-$00FF). The reason the term "zero page" exists is because some instructions only work in that space, and other instructions have faster versions that work in that space. These instructions are faster because don't care about the high byte of the addresses, which is assumed to always be $00.
If nothing else in my code explicitly touches $80 through $80 + 2, can anything else from the NES alter those values in any way?
No. The only memory that's automatically overwritten by the system is the stack, since interrupts and subroutine calls put data there. If you're coding everything yourself, only your own code will touch $0000-$00FF and $0200-$07FF. Be careful if you use someone else's music engine for example, because it will certainly need so use memory somewhere, so be sure not to create conflicts in this case.

Code: Select all

ppuBufferPtr .rs 1
.......
LDA $80
STA ppuBufferPtr
.......
LDA [ppuBufferPtr], y ; also tried LDA (ppuBufferPtr), y
Pointers are always 16-bit, and you're trying to use a single byte as a pointer. A proper pointer to $0080 works like this:

Code: Select all

ppuBufferPtr .rs 2
.......
LDA #$80
STA ppuBufferPtr
LDA #$00
STA ppuBufferPtr+1
.......
LDA [ppuBufferPtr], y ; if NESASM
LDA (ppuBufferPtr), y ; if anything else
Note that you also forgot the # in LDA #$80, which means you want to put the immediate value $80 into the accumulator. LDA $80 will get the value at memory location $0080 and put that into the accumulator, which is not what you want if your intention is to create a pointer to $0080.
casprog
Posts: 70
Joined: Fri Oct 28, 2016 12:37 pm

Re: Basic question about RAM and pointers

Post by casprog »

This would load into A the value at memory location $0706+y. Is that what you intended? Unless you're using NESASM, in which case I think the LDA ($80), y would assemble to LDA $80, y, so the value at $0080+y would end up in the accumulator.
I'm using NESASM v3.1, so that explains it. It must have been translating that because each of my comparisons were matching up during my tests.
Pointers are always 16-bit, and you're trying to use a single byte as a pointer.
Ah, okay, I thought I could use a single byte pointer in Zero Page since the memory is in the first page. I didn't think about $0080 to represent it.
Note that you also forgot the # in LDA #$80, which means you want to put the immediate value $80 into the accumulator.
Another rookie mistake. I was thinking about this backwards, still on a one byte pointer mind, thought I would be pointing the pointer to address $80..
I tend to keep my VRAM transfer buffers in $0100-$019F
I will check that out.

I made updates based on feedback and it is working now, thanks! By the way, is NESASM a good assembler to use?
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Basic question about RAM and pointers

Post by tepples »

NESASM uses some nonstandard syntax, assumes 8K banking (MMC3/VRC6/MMC5/FME-7) due to its TurboGrafx heritage, and doesn't try to automatically recognize zero page instructions (also due to TG16 whose CPU puts direct page at $2000). It has its fans, among them zzo38 who if I recall correctly maintains a somewhat enhanced fork. But ASM6 is probably the best overall choice for a "simple" assembler, or ca65 for more complex projects or C language compatibility.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Basic question about RAM and pointers

Post by tokumaru »

The biggest cons of NESASM are the non-standard syntax, the mandatory bank size of 8KB, some poorly explained assembly errors, and the occasional silently produced malformed binary due to certain errors in the source. ASM6 actually suffers from the latter issue as well, but to me it still feels more robust. It's very versatile and many things can be automated with the use of macros. It has no bulshit limitations, meaning it can be used to program any 6502 machine without hassle (I often use it for Atari 2600 coding, for example).

The pros are that NESASM is often used in beginner tutorials (which IMO explains why it's still so widely used), so there are more resources for beginners using its syntax, that it has directives for generating the iNES header, and that it's simple to use (no setup/configurations whatsoever). ASM6 is just as simple to use, and you can very easily create an iNES header using .db statements or macros.

I've used ASM6 a lot, and it's still my assembler of choice for simpler programs. For complex projects I switched to ca65, which can be a pain to setup, specially if you don't know what you're doing, but once everything's in place, it has tons of features that really help with managing larger amounts of code and data.
User avatar
Jarhmander
Formerly ~J-@D!~
Posts: 521
Joined: Sun Mar 12, 2006 12:36 am
Location: Rive nord de Montréal

Re: Basic question about RAM and pointers

Post by Jarhmander »

cc65, a pain to setup... It all depends on your familiarity with linkers in the first place. The linker script has its own syntax, distinct of the other linkers I know (GNU ld, TI's linker etc), but when you know in general how linkers work, it's not difficult at all, you only need to learn its linker script syntax, its features and its limitations.
((λ (x) (x x)) (λ (x) (x x)))
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Basic question about RAM and pointers

Post by tokumaru »

I agree with you now, that I finally understand how ca65 works, but it took me a while to get here.
Post Reply