8x16 and whatever else unreg wants to know

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

User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: 8x16 sprite is really a 16x32 pixel image?

Post by Kasumi »

The 6502 deals with numbers low byte first. This means something like jmp $8D9A is assembled to $4C(opcode for the jmp instruction) $9A (low byte) $8D (high byte).

It may appear to be stored "backwards" to you, but it represents the exact same value. That's just how the CPU does things.

The PPU appears to like the high byte first. You write $8D to $2006, and then $9A to $2006. $2007 would be geared to write to $8D9A, not $9A8D. On one console, you get to deal with with both types of endianness!

If the 6502 is going to read a 16 bit value as an address or pointer, it has to be two contiguous bytes, low byte first.

But... any other time (like adding to an objects position), it doesn't matter.

consider this code:

Code: Select all

highbyte = $04
lowbyte = $EF

lda lowbyte
clc 
adc #$08
sta lowbyte

lda highbyte
adc #$00
sta highbyte
You'd get the expected high byte in the RAM location named highbyte, and the expected low byte in the RAM location named lowbyte. They don't even have to be contiguous.

I tend to store things high byte first because it's much easier to read when I'm peeking at the RAM in a debugger. It doesn't matter one way or the other except with pointers and addresses, which the 6502 will always read in its own way.

Just be consistent in your own code, and do what makes sense for you. I hope this post didn't serve to confuse you more.

edit: Wait. Is this the heart of the matter that you expect ox, ox+1, ox+2, and ox+3 to have the same values in the same order as position_hi etc?

Reversing those .ds statements for position_hi etc. wouldn't change the represented value at all. Even if they appeared in the "right" order after reversal, they represent the same thing either way. You could even do this:

Code: Select all

position_hi .DS 1
oX .ds 4
position_medium .DS 1
position_lo .ds 1
position_medihi .ds 1
The bytes that correspond with each other would still be equal, and together they would represent the same number, just in a different location in RAM. (which again, only matters for addresses and pointers.)

edit2: nevermind for what was once here. Not reading closely :(
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

Kasumi wrote:The PPU appears to like the high byte first. You write $8D to $2006, and then $9A to $2006. $2007 would be geared to write to $8D9A, not $9A8D. On one console, you get to deal with with both types of endianness!

If the 6502 is going to read a 16 bit value as an address or pointer, it has to be two contiguous bytes, low byte first.

But... any other time (like adding to an objects position), it doesn't matter.

consider this code:

Code: Select all

highbyte = $04
lowbyte = $EF

lda lowbyte
clc 
adc #$08
sta lowbyte

lda highbyte
adc #$00
sta highbyte
You'd get the expected high byte in the RAM location named highbyte, and the expected low byte in the RAM location named lowbyte. They don't even have to be contiguous.
:? I'm dumb I dont understand what you are saying to me. :( Won't they be contiguous (near each other) since highbyte is right above lowbyte at the top of your code there? :) : )
Kasumi wrote:edit: Wait. Is this the heart of the matter that you expect ox, ox+1, ox+2, and ox+3 to have the same values in the same order as position_hi etc?

Reversing those .ds statements for position_hi etc. wouldn't change the represented value at all. Even if they appeared in the "right" order after reversal, they represent the same thing either way. You could even do this:

Code: Select all

position_hi .DS 1
oX .ds 4
position_medium .DS 1
position_lo .ds 1
position_medihi .ds 1
The bytes that correspond with each other would still be equal, and together they would represent the same number, just in a different location in RAM. (which again, only matters for addresses and pointers.)
Yes the different location in RAM was is important to me. I was trying to understand how the code would work using the oX+0 oX+1 oX+2 and oX+3. More on that in a bit.

unregistered wrote:I'm under some trouble with this code...

Code: Select all

;6502 Simulator
 .START $1000
 .ORG $0000
 
  .DB "ABC"

position_lo .DS 1
position_medium .ds 1
position_medihi .DS 1
position_hi .ds 1
oX .ds 4

 
 .ORG $1000
 
    

  ; set the position to $01FC
  lda #$01
  sta position_hi
  LDA #$01
  sta position_medihi
  LDA #$00
  sta position_medium
  LDA #$02
  STA position_lo
  
  LDa #$01
  STa oX+3
  LDa #$01
  STa oX+2
  lda #$00
  sta oX+1
  lda #$02
  STA oX+0
    

  ; now subtract eight (#$0008) from this position
  sec 
  lda position_lo  ; subtract from the low byte first
  sbc #$08
  sta position_lo
  LDA position_medium
  SBC #$00
  STA position_medium
  LDA position_medihi
  SBC #$00
  sta position_medihi
  LDA position_hi
  sbc #$00
  STA position_hi
  
  ; now subtract eight (#$0008) from this position
  sec 
  lda oX+0  ; subtract from the low byte first
  sbc #$08
  sta oX+0
  LDA oX+1
  SBC #$00
  STA oX+1
  LDA oX+2
  SBC #$00
  sta oX+2
  LDA oX+3
  sbc #$00
  STA oX+3
See what I was saying...? I reversed the order of the section of memory declarations and the RAM inverted... it was the same answer but the order of the values in RAM was upside down... and that had been confusing me... though now I understand. :)

unregistered wrote:Ok well that is my code I've explored in the 6502 Simulator from tokumaru. The only thing is that at the top of it I had to reverse this code.

position_hi .DS 1
position_medihi .ds 1
position_medium .DS 1
position_lo .ds 1


I started with that because tepples made his code up there very tricky... I think... :? because he started with

Code: Select all

position_hi = $0701
position_lo = $0700
and that has been confusing me. Should position_lo be above position_hi? :? :)
See reversing the order of the declarations reversed my view of the memory. It was the same answer though, you are right, thank you for pointing that out! I really appreciate that! :D I've learned a lot thinking about all of this. The coolest thing I've learned is that little-endianness makes sense when using one variable name for multiple bytes. You start with the lowest value... (i'm going to use oX for my variable name) oX+0. Ok, then as the number increases the importantance increases!!! oX+1 oX+2 oX+3.... that is AWESOME! :mrgreen: I'm happy Nintendo chose to use little-endianness! "Little-endian" won't confuse me as much anymore! :D

And thank you Kasumi for your endianness link! :D I'm not extreemly excited about wikipedia though. :roll:
Kasumi wrote:edit2: nevermind for what was once here. Not reading closely :(
Kasumi, it's ok :) I don't remember reading it; I found this second edit when I got up this morning.

edit.
Last edited by unregistered on Tue Dec 11, 2012 1:26 pm, edited 2 times in total.
3gengames
Formerly 65024U
Posts: 2284
Joined: Sat Mar 27, 2010 12:57 pm

Re: 8x16 sprite is really a 16x32 pixel image?

Post by 3gengames »

With the order of the RAM things (Your first reply) it doesn't matter where the bytes of RAM are, you just have to add them and store them to the right places. I keep all mine next to each other, but they don't have to be. The processor just look at where to load and store, which you decide. It doesn't care if it's right next to each other or not. Now when you use an addressing mode like [ZeropageLocation],Y, then you DO have to have them next to each other (Low byte first since it's little endian) because then it does "care" about where they're at because the processor is hardwired to take the zero page location, then the zeropage location+1 the next time! When you're working with single bytes as 16-bit values, you don't have to keep them together because you probably aren't using the data with an addressing mode or anything like that.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

Thanks 3gengames for explaining my confusion away! :D I understand Kasumi more now.

I want to say that I edited my post up there twice because I came back to my computer and wrote that colored part in the middle. Then I submitted it without making it colored for adding/editing it. :(

edit.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: 8x16 sprite is really a 16x32 pixel image?

Post by Kasumi »

I'm dumb I dont understand what you are saying to me. :( Won't they be contiguous (near each other) since highbyte is right above lowbyte at the top of your code there? :) : )
To expand on this point a little, there are things in your code that don't end up in your actual rom. For instance, labels. Labels actually take up zero space by themselves.

Code: Select all

.org $8D9A
label1:
label2:
label3:
label4:
label5:
;etc, etc
You could put a million random labels in your code, and your program would (or at least should) be assembled exactly the same. They only take up space when they're used in an instruction. What a label does is names an address for you automatically.

I explained how jmp $8D9A was assembled in the last post. In the above code, jmp label1, jmp label2, jmp label3 etc would all assemble the same as jmp $8D9A. Because even though label2 is after label1, label1 doesn't take up any space. There are no instructions that do take up space between them, so they refer to the same location.

When you add code, it makes every label after the change need a new address. But all the code you previously made (in most cases) will work the same, despite the address move. Similarly, you can switch where the RAM your program is using is, and (in most cases) it will also work the same. That's what I was trying to demonstrate. It doesn't matter what order your DS statements are in.

Code: Select all

highbyte = $04
lowbyte = $EF
Above, highbyte and lowbyte don't refer to contiguous RAM. (Like $04 and $05, or $EF and $F0). The fact they they're next to each other in your code doesn't matter.

You could add a million text = $whatever in your code and it shouldn't affect how your rom is assembled. My assembler (and I assume others as well), doesn't care where they are in the slightest. I could even do something like this:

Code: Select all

	lda #mario
mario = $04;Right in the middle of the code!
	clc
	adc #$08
And it would assemble the same as if mario = $04 was anywhere else in the code.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

What does <> mean? Google search says nothing exists for <>

Post by unregistered »

Please help me understand what <> means?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: What does <> mean? Google search says nothing exists fo

Post by tokumaru »

unregistered wrote:what <> means
Different.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: What does <> mean? Google search says nothing exists fo

Post by unregistered »

tokumaru wrote:
unregistered wrote:what <> means
Different.
THANK YOU TOKUMARU!!! :D
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

Kasumi wrote:
I'm dumb I dont understand what you are saying to me. :( Won't they be contiguous (near each other) since highbyte is right above lowbyte at the top of your code there? :) : )
To expand on this point a little, there are things in your code that don't end up in your actual rom. For instance, labels. Labels actually take up zero space by themselves.

Code: Select all

.org $8D9A
label1:
label2:
label3:
label4:
label5:
;etc, etc
You could put a million random labels in your code, and your program would (or at least should) be assembled exactly the same. They only take up space when they're used in an instruction. What a label does is names an address for you automatically.

I explained how jmp $8D9A was assembled in the last post. In the above code, jmp label1, jmp label2, jmp label3 etc would all assemble the same as jmp $8D9A. Because even though label2 is after label1, label1 doesn't take up any space. There are no instructions that do take up space between them, so they refer to the same location.

When you add code, it makes every label after the change need a new address. But all the code you previously made (in most cases) will work the same, despite the address move. Similarly, you can switch where the RAM your program is using is, and (in most cases) it will also work the same. That's what I was trying to demonstrate. It doesn't matter what order your DS statements are in.

Code: Select all

highbyte = $04
lowbyte = $EF

Above, highbyte and lowbyte don't refer to contiguous RAM. (Like $04 and $05, or $EF and $F0). The fact they they're next to each other in your code doesn't matter.

You could add a million text = $whatever in your code and it shouldn't affect how your rom is assembled. My assembler (and I assume others as well), doesn't care where they are in the slightest. I could even do something like this:

Code: Select all

	lda #mario
mario = $04;Right in the middle of the code!
	clc
	adc #$08
And it would assemble the same as if mario = $04 was anywhere else in the code.
Thank you Kasumi. I kindof guessed that was true ("that" is a responce to your first sencence. After debugging with FCEUX for a whlile I noticed that my labels in the code were absent. It made me guess what you are talking about - I remember learning that labels dissappeared after assembly in one of my CS assembly @ut college courses.)... XFactor is coming on... I must go see and listen! ... but didn't know for sure ("didn't know for sure" is a response to your statement about how labels take up no space. All of your explaination made sense to me; it kind of solidified it all in my head-thanku! :)). Kasumi, Tthanks for your detailed explanations! :D

edit.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

Code: Select all

7  bit  0
---- ----
Rxxx xxxD
|       |
|       +- Data bit to be shifted into shift register, LSB first
+--------- 1: Reset shift register and write Control with (Control OR $0C),
              locking PRG ROM at $C000-$FFFF to the last bank.
When I come across something like this when looking through nes mappers on the nesdev wiki I always become confused. It looks like there is something there to write in a byte. But the bin is 8kb or something like that... and so I wonder if every byte in those 8kb should be setup in that form... but then I think that doesn't make sense... why would they require every byte to be like that? :?
3gengames
Formerly 65024U
Posts: 2284
Joined: Sat Mar 27, 2010 12:57 pm

Re: 8x16 sprite is really a 16x32 pixel image?

Post by 3gengames »

That's MMC1. Mapper 1. It uses four 5-bit registers. You write the registers 1 bit at a time. Bit 7 is the reset bit and automatically assigns a few registers the default way. But you write the 5 bits of each register with data bit 0. You basically LDA with a number less then $80 (Because 80 will have bit 7 set, and will reset it, you don't want that when programming it) and you basically just STA (Memory region of the register you want to write: $8xxx,$Axxx,$Cxxx,$Exxx) and LSR.

Code: Select all

...
LDA #$[ValueToWriteMMC1]
STA $8000 ;1st write
LSR A
STA $8000 ;2nd write
LSR A
STA $8000 ;3rd write
LSR A
STA $8000 ;4th write
LSR A
STA $8000 ;Register NOW is programmed and updated.
...
For MMC1, the last write also finally selects which register to update, so you can write any places you want above $8000 as long as the last write goes where you want it.
Last edited by 3gengames on Fri Dec 14, 2012 7:50 pm, edited 1 time in total.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 sprite is really a 16x32 pixel image?

Post by tokumaru »

unregistered wrote:the bin is 8kb or something like that
What bin are you talking about?

Anyway, those schematics show you how the mapper interprets writes to its registers, they have nothing to do with how data is set up. You know when you write to $2000 (one of the NES registers) and some bits select the active name table, another bit selects whether NMIs will happen, and so on? Mapper registers are just like that too. In the case of the MMC1, you have to write to the registers like 3gengames said.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

tokumaru wrote:
unregistered wrote:the bin is 8kb or something like that
What bin are you talking about?
Sorry... bank... an 8kb or a 16kb bank.

Lets say we are trying to use an 8kb register that is listed as $C000-$DFFF. How do you use it... write to it... it starts at $C000 so I could set that register with something like

Code: Select all

lda #00001011
sta $C000
and then how could I write 8kb of data to $C000-$DFFF?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 sprite is really a 16x32 pixel image?

Post by tokumaru »

unregistered wrote:Lets say we are trying to use an 8kb register
There's no such thing as an "8kb register".
that is listed as $C000-$DFFF.
This just means that the register can be accessed in any address between $C000 and $DFFF: writing to $CF8B is the same thing as writing to $DD0F, it doesn't matter. The register is mirrored across that range of memory, but it's still 1 register.
How do you use it... write to it... it starts at $C000 so I could set that register with something like

Code: Select all

lda #00001011
sta $C000
That's exactly it, but you could have used any address between $C000 and $DFFF.
and then how could I write 8kb of data to $C000-$DFFF?
There's no need to do this.
3gengames
Formerly 65024U
Posts: 2284
Joined: Sat Mar 27, 2010 12:57 pm

Re: 8x16 sprite is really a 16x32 pixel image?

Post by 3gengames »

It's not right, you have to shift and store it 5 times, remember that! And only the last right matters, but don't worry about that, just write the register you need 5 times.

But yeah, what does copying 8KB of data to ROM? You can't over write ROM. It won't do anything. To switch more ROM data in, it basically looks at the address lines when read, and switches them! So if the ROM is in 8000-BFFF, it will "spit out" the new data that goes in that area. When it's C000-FFFF, it will spit out whatever it is assigned to put out there. that's how mappers work. All their locations they change is different, though. This example is for an MMC1, which seperates it into a 16KB "data" bank and then a 16KB "fixed" bank that can't be moved.

Also, worth noting: when mappers are present, they "consume" the WRITES to the ROM. When read, the mapper doesn't do anything except let the CPU look at the ROM.
Post Reply