It is currently Fri Dec 15, 2017 2:52 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Wed Jun 29, 2011 6:19 pm 
Offline
User avatar

Joined: Tue Jun 28, 2011 9:46 pm
Posts: 26
Location: Las Vegas, NV, USA
This question is a lot different than my other questions, so I figured a new topic would be better, but it's basically just the title, how do I compare to a value larger than $ff? I'm loading my background in, and it's saved in a label, backgrounds: and has all the backgrounds stored in .db's. The only problem, is that for the full screen, there is 32x32, 8x8 tiles, which is 1024 bytes of data.. Here's how I'm loading the backgrounds:
Code:
LoadBackgrounds:
  LDA $2002
  LDA #$20
  STA $2006
  LDA #$00
  STA $2006
  LDX $00
LoadBackgroundsLoop:
  LDA backgrounds, x
  STA $2007
  INX
  CPX #$FF ; Here's where I need to compare to 1024, or $0400, but it only allows 1 byte to be compared to
  BNE LoadBackgroundsLoop

So, is there a better to do this, or is there any to compare to a 2 byte value?
How do you guys normally load the background?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 6:43 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19348
Location: NE Indiana, USA (NTSC)
If you want to access an array bigger than 256 bytes, you first need to store the starting address on zero page (lda #<label sta src_addr lda #>label sta src_addr+1). You may want to load the number of 256-byte "pages" into X, which in the case of an uncompressed nametable is four (ldx #4). Then use the (d),Y addressing mode and step through each page with Y. When Y wraps around to zero (hint: your loop will use a BNE instruction), increase the high byte of the address (inc src_addr+1) and decrease X until you've gone through all four pages.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 7:06 pm 
Offline
User avatar

Joined: Tue Jun 28, 2011 9:46 pm
Posts: 26
Location: Las Vegas, NV, USA
Ahhh I think I understand that, like a double for loop? But I may have trouble translating that to code.. Here's my attempt
Code:
LoadBackgroundsLoopX:
  LDA backgrounds, x ; how do I add 1 to the high byte here?
  STA $2007
  INX
  CPX #$FF
  BNE LoadBackgroundsLoopX
LoadBackgroundsLoopY:
  DEY
  LDX #$00
  CPY #$00
  BNE LoadBackGroundsLoopX

But that's just going to load the first 256 bytes 4 times.. Any more tips? I'd still like to figure this out without someone handing me the code.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 7:08 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19348
Location: NE Indiana, USA (NTSC)
You need to store the address of 'backgrounds' in a pointer on zero page, and then you need to look at what the (d),y indirect addressing mode does.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 7:10 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
Since the 6502 is an 8-bit CPU, it can only manipulate 8 bits (which can hold values from 0 to 255) at a time. If you need numbers larger than that, you have to work with the individual bytes that form that larger number. For example, if you want to compare 2 16-bit numbers, you have to first compare the high byte and then the low byte.

But in this particular case, it's not a 16-bit compare you are looking for. Like tepples said, the 6502 has a very useful addressing mode that is meant to allow access data larger than 256 bytes. For this you need a pointer and an index. The pointer is stored in zero page RAM ($0000-$00FF), and the index is the Y register.

A pointer is a 16-bit value that indicates an address. Even though the 6502 can't manipulate 16-bit values internally, it can access 16-bit pointers in RAM. To read data using a pointer you need the instruction "LDA (Pointer), Y". When the CPU sees this instruction, it will go to the ZP location where the variable "Pointer" is, it will see what address is stored there and will then look for your data in that address. Y is used as an offset into that data, so you can access up to 256 bytes starting from the address indicated by the pointer.

If you need to access more than 256, just modify the pointer. By incrementing the high byte of the pointer you effectively add 256 to it, which will allow you to read 256 more bytes. If you keep doing this you can access as many bytes as you want.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 8:15 pm 
Offline
User avatar

Joined: Tue Jun 28, 2011 9:46 pm
Posts: 26
Location: Las Vegas, NV, USA
So like..
Code:
.rsset $0000
pointer .rs 2 ; it needs 2 bytes right?

LDA #<backgrounds ; low byte
STA pointer
LDA #>backgrounds ; high byte
STA pointer + 1 ; now pointer is background's full address
LDX #$04
LDY #$00

BackgroundLoop:
  LDA (pointer), y ; y is the low byte
  STA $2007
  INY
  CPY #$FF ; increase until it hits $FF
  BNE BackgroundLoop
DecX:
  INC pointer +1 ; increase the high byte
  LDY #$00 ; reset the low byte
  DEX ; and decrese x by one
  CPX #$00 ; check if X is down to 0 yet (after 4 loops)
  BNE BackgroundLoop

Ignore the comments, I was just figuring it out one piece at a time.
Man my brain hurts after that.. haha. I think that would work though, right?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 8:25 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
Canite wrote:
I think that would work though, right?

Almost! You got the right idea, there are just a couple of logic issues:

1. The "CPY #$FF" is not necessary. If you use it, you will actually copy 255 bytes instead of 256. Just let Y wrap back to $00 with the INY, and because the Z flag will be set the branch will not happen, so there's no need to compare anything. As a bonus you also don't need to reset Y later, as it will already be 0.

2. Similar to the above, you don't need the "CPX #$00". This isn't an error though, it's just redundant. If the result of any operation is zero, the Z flag will be set, so there's no need to compare against #$00.

The status flags are kinda mystical for people who have never programmed in assembly before (for me at least that was one of the weirdest things). Just keep in mind that a lot of instructions modify the flags (specially the ones that manipulate values in any way), and after these modifications you can use the branch instructions to make decisions about what to do next. You don't have to "compare" all the time, as most of the time the operations themselves will set the flags for you.


Last edited by tokumaru on Wed Jun 29, 2011 8:30 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 8:30 pm 
Offline
User avatar

Joined: Tue Jun 28, 2011 9:46 pm
Posts: 26
Location: Las Vegas, NV, USA
tokumaru wrote:
2. Similar to the above, you don't need the "CPX #$00". This isn't an error though, it's just redundant. If the result of any operation is zero, the Z flag will be set, so there's no need to compare against #$00.


Ah, I didn't even know you could do that, thanks. But when I try to compile it, NESASM throws some errors at me :/ It says that the LDA #<backgrounds part is an unknown instruction. Is my syntax wrong?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 8:34 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
NESASM uses weird syntax. All other assemblers use LDA (Pointer), Y, while NESASM uses LDA [Pointer], Y. For accessing the low and high bytes of a value you have to use LDA #LOW(Value) and LDA #HIGH(Value), I think. NEASM is realy weird.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 8:45 pm 
Offline
User avatar

Joined: Tue Jun 28, 2011 9:46 pm
Posts: 26
Location: Las Vegas, NV, USA
tokumaru wrote:
NESASM uses weird syntax. All other assemblers use LDA (Pointer), Y, while NESASM uses LDA [Pointer], Y. For accessing the low and high bytes of a value you have to use LDA #LOW(Value) and LDA #HIGH(Value), I think. NEASM is realy weird.


Gah, I've tried everything, always gives an error..
I have this now:
Code:
LDA #LOW(backgrounds) ; low byte
STA pointer
LDA #HIGH(backgrounds) ; high byte
STA pointer + 1 ; now pointer is background's full address

but it still gives an error?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 8:49 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
Did you also change LDA (pointer), Y to LDA [pointer], Y? It should be working...

EDIT: Maybe NESASM doesn't support the "pointer + 1" part? Have you tried declaring your pointer as two individual HI and LO bytes? Or putting "pointer + 1" between parenthesis? I really can't see what's wrong now.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 9:27 pm 
Offline
User avatar

Joined: Tue Jun 28, 2011 9:46 pm
Posts: 26
Location: Las Vegas, NV, USA
tokumaru wrote:
Did you also change LDA (pointer), Y to LDA [pointer], Y? It should be working...

Yeah, I did, here's there error
Image

Quote:
EDIT: Maybe NESASM doesn't support the "pointer + 1" part? Have you tried declaring your pointer as two individual HI and LO bytes? Or putting "pointer + 1" between parenthesis? I really can't see what's wrong now.

If I do it this way, what will I put in in the LDA (pointer), y part?


Last edited by Canite on Wed Jun 29, 2011 9:52 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 9:33 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3968
Time to switch to ASM6?

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 9:40 pm 
Offline
User avatar

Joined: Tue Jun 28, 2011 9:46 pm
Posts: 26
Location: Las Vegas, NV, USA
Dwedit wrote:
Time to switch to ASM6?


I guess? Haha.
I just started learning assembly yesterday, so I didn't really want to be switching around like that.. How different are assemblers from each other?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2011 10:01 pm 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1046
Canite wrote:
Image


My guess? You didn't indent those instructions.

Code:
sta pointer+1

is different than
Code:
 sta pointer+1;Note the space before the instruction


nesasm gives unknown instruction when you don't indent with whitespace characters. There's no other reason I can think of why STA pointer wouldn't work.
Edit:
tokumaru wrote:
Did you also change LDA (pointer), Y to LDA [pointer], Y? It should be working...

As of the latest nesasm, either of those works fine.
Edit again several months later: Both ASSEMBLE fine, but it with paranthesis it gives the wrong addressing mode. Sorry, I can be so confident when I'm wrong.


Last edited by Kasumi on Wed Apr 11, 2012 3:51 pm, edited 1 time in total.

Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 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