Indirect Indexed name/attribute table loading loop confusion

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
CrowleyBluegrass
Posts: 42
Joined: Sun Jun 30, 2013 7:59 am

Indirect Indexed name/attribute table loading loop confusion

Post by CrowleyBluegrass »

Sorry for the rather muddled title, couldn't think of what to put exactly :?

In the nerdy nights tutorials, there is a comment on the 6th tutorial (http://nintendoage.com/forum/messagevie ... eadid=8172) in which someone (Zzap) loads the attribute and name tables in one loop. I'm having trouble understanding what's going on. Full code is here https://pastebin.com/f12cef2c1
Here's the part I'm having difficulties with:

Code: Select all

LDA #low(background)
  STA AddrLow
  LDA #high(background)
  STA AddrHigh
 
  LDX #$04              ; Loop X 4 times
  LDY #$00              ; Loop Y 256 times
LoadBackgroundsLoop:
  LDA [AddrLow],y
  STA $2007
  INY
  BNE LoadBackgroundsLoop
; Outer loop
  INC AddrHigh           ; increment high byte of address backg to next 256 byte chunk
  DEX                    ; one chunk done so X = X - 1.
  BNE LoadBackgroundsLoop   ; if X isn't zero, do again
I'm unsure of what value AddrLow and AddrHigh actually hold, because I don't understand what is being loaded into them.
LDA #low(background)
LDA #high(background)
What does this mean? there is no value set to low anywhere in the code. I've also never seen () used before. I understand the looping and branching in the rest of the code well enough, but those parts are baffling me. The label background precedes the tile data in bytes, I know that much. I've just never seen anything like this before so having trouble understanding what #low(background) means, especially when low hasn't been set to any value prior.

Sorry for being so inept. I'm making progress slowly after a long hiatus, really appreciate any help you guys can offer. Thank you :)
User avatar
dougeff
Posts: 3078
Joined: Fri May 08, 2015 7:17 pm

Re: Indirect Indexed name/attribute table loading loop confu

Post by dougeff »

Are you familiar with pointers in other programming languages?

AddrLow and AddrHigh are 2 zero page RAM addresses. You put the address of the data here, and then you can 'indirectly' load from the data using the (INDIRECT), Y mode.

So let's say the data is at address 9000. You load the pointer with values 90 and 00, then you are basically saying, load from 9000, when you do LDA (AddrLow), y assuming y is zero.

6502 is little endian, so the small byte of the address is first, the high byte is next.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Indirect Indexed name/attribute table loading loop confu

Post by pubby »

'background' is an address to the level data that's being copied. It could be defined in the source like this:

Code: Select all

background:
.byt 50
.byt 34
.byt 130
.byt 200
; continue for 1024 bytes
An address is 16 bits. The built-in functions 'low' and 'high' take 16 bit constant values and split them up into two 8 bit values: a low byte and a high byte.

'AddrLow' is being used for indirect indexed addressing, as Dougeff mentioned. Basically, this allows you to write a subroutine and reuse the code for different data (e.g. reuse it for different levels).

You could write the code like this:

Code: Select all

  LDX #$04              ; Loop X 4 times
  LDY #$00              ; Loop Y 256 times
LoadBackgroundsLoop:
  LDA background, y    ; look here!
  STA $2007
  INY
  BNE LoadBackgroundsLoop
; Outer loop
  INC AddrHigh           ; increment high byte of address backg to next 256 byte chunk
  DEX                    ; one chunk done so X = X - 1.
  BNE LoadBackgroundsLoop   ; if X isn't zero, do again
By replacing 'LDA [AddrLow],y' with 'LDA background,y', the data being copied becomes hard coded. If you wanted to write a more generic routine that could copy different data from different locations you'd use indexed indirect addressing.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Indirect Indexed name/attribute table loading loop confu

Post by unregistered »

Sorry, dougeff's example used indirect indexed addressing so you'd need zero-page variables, like he said; but, hope this post is helpful, otherwise. : )

To make dougeff's example have less of a chance of causing head hurt:

AddrHigh would be loaded with 90 and AddrLow would be loaded with 00. Like (in asm6):

Code: Select all

AddrHigh .equ $90
AddrLow .equ $00
---
But, like pubby said, since the code I put up there is a hardcoded address, a faster instruction, taking one byte more (3 bytes), is:

Code: Select all

;at some valid address below $8FFE:
lda background, y

;and then have something like:

.pad $9000 ;<sets background's (starting) address to $9000
background:
.db 50, 34, 130, 200, ...etc. ; <could also be .db $32, $22, $82, $C8, ...etc.

 ;or even .db 50, $22, $82, 200, ...etc.
edit.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Indirect Indexed name/attribute table loading loop confu

Post by unregistered »

unregistered wrote:Sorry, dougeff's example used indirect indexed addressing so you'd need zero-page variables, like he said; but, hope this post is helpful, otherwise. : )
indirect indexed addressing is lda (Oper), y

learned that from MOS Technology Family Programming Manual

A long time ago I printed out all of that manual's appendices. Just print pages 198 and 234 in landscape so it flips the pages.

MOS Technology created the 6502. The NES uses an alternate version called the 2A03; it lacks Decimal mode (the d flag is useless). It is really cool for me to have the creator's manual's appendices printed out; have used them so much. Appendix A and B are so nicely laid out! :)

Note: I've written lda (Oper), y next to Appendix E.9 to remind me of what indirect indexed addressing is. And I've added a small XOR truth table next to Appendix B's EOR. Writing small notes is really helpful for me. :)

edit:
wikipedia wrote:The 6502 used in the NES was a second source version by Ricoh, a partial system-on-a-chip, that lacked the binary-coded decimal mode but added 22 memory-mapped registers (and on-die hardware) for sound generation, joypad reading, and sprite list DMA. Called 2A03 in NTSC consoles and 2A07 in PAL consoles...
Noticed that I must have printed out an earlier version of the manual because my Appendix B is left justified, I like that better than the centered version in the first and second editions for some reason, but below the branches in my Appendix B it says
* Add 1 if branch occurs to same page.
* Add 2 if branch occurs to same page.
and so that was quite confusing. I failed at finding the earlier manual for you, but found that wikipedia quote and want to share it. :)
Post Reply