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
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 »

True, I didn't think about those cases... So yeah, you do have a 2 name table area you can use, so you can't have more than 2 screens between flips if you plan on turning rendering off to perform VRAM updates.

unregistered needs the screen-flipping because the time of a VBlank isn't enough for all the updates he needs, but these game you mentioned probably need it because of mirroring restrictions that make scrolling in both directions hard/impossible.
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 »

...my question today has to do with PPUADDR ($2006). Right now I've written #$203E. Why does my vertical line of 29 tile#3s start on the second to last column? Starts around $283E... :? Isn't $2000 the upper left corner of nametable 0?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

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

Post by tepples »

$203E is nametable 0 ($2000-$23FF), row 1 ($2020-$203F), column 30. The last column is column 31, so column 30 would be second to last.
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 »

tepples wrote:$203E is nametable 0 ($2000-$23FF), row 1 ($2020-$203F), column 30. The last column is column 31, so column 30 would be second to last.
Well... that is exactly where it is... you are correct! :) I'm confused... maybe I'll get less confused with more experience? :?

edit: Thank you tepples! :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 »

Here is the code I'm working on...

Code: Select all

update_vram: ;testing... :)
        lda my_copy_of_last_write_to_PPUCTRL
		ora #00000100b  ;change $2007 increment to +32
		sta PPUCTRL0
		sta my_copy_of_last_write_to_PPUCTRL
		
		lda #$20
		sta PPUADDR6
		lda #$00
		sta tE
		sta PPUADDR6
		
        ldy #$02
		ldx #60 ;should hold last spot written to RAMbuffer. each column is always full so #60
   ;**********LOOK AT CODE BELOW HERE***********************
	-	cpx #30 ;if x == 30
		  bne +past30stop
		 ;Welcome to 30stop.
		    inc tE  ;+1 (moves over to next column)
		  lda #$20
		  sta PPUADDR6
		  lda tE
		  sta PPUADDR6
	    +past30stop:
        lda RAMbuffer, x
		  sta PPUDATA7
		  dex
		  bne -
				
        rts ;end of update_vram.
This kills my attribute table data. All my pallets entries look the same now... after forming that loop at the bottom. Do you see anything wrong with this code?

edit: Here is what it is susposed to do... it correctly shows two full columns of tile #00 on nametable 0. It is written backwards because it seems like it would be faster if the columns are upsidedown. :)

edit2: All the code that's being tested right now is below the ***********line. This means everything else... all the clean code that works is not below that line.

after-supper-edit3: Um... is there a rule that says I should quit the write to vram?... There is a line of odd tiles up at the top of nametable 0. Thought maybe somehow those tiles are the attribute table pushed out to the top of nametable 0. Somehow... if you never increment the value that you store to $2006... the tiles are written into the attribute table of nametable 0 and then on into the first column of nametable 1 ...I think...
Last edited by unregistered on Tue Feb 26, 2013 6:26 pm, edited 1 time 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 »

Why would you not structure code like this?

Code: Select all

(Write PPU column here)
  LDX #$00
CDataWriteLoop:
  LDA Buffer,X
  STA PPUData
  INX
  CPX #30 ;30 tiles?
  BNE .CDataWriteLoop
  RTS
or even better, if you can put your buffer backwards: (Which you should do basically always)

Code: Select all

  LDX #30 ;30 Tiles
CDataWriteLoop:
  LDA Buffer,X
  STA PPUData
  DEX
  BNE .CDataWriteLoop
  RTS
to write the column of data? You should *nearly* never have to do a compare right out of the gate in a routine, it's a waste because you'll have to branch back then check, which adds even more cycles to an already inefficient routine. Not trying to be harsh, but code structure is everything.
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 »

3gengames wrote:or even better, if you can put your buffer backwards: (Which you should do basically always)

Code: Select all

  LDX #30 ;30 Tiles
CDataWriteLoop:
  LDA Buffer,X
  STA PPUData
  DEX
  BNE .CDataWriteLoop
  RTS
to write the column of data? You should *nearly* never have to do a compare right out of the gate in a routine, it's a waste because you'll have to branch back then check, which adds even more cycles to an already inefficient routine. Not trying to be harsh, but code structure is everything.
Oooh... well I started to think that... well I was thinking in a loop somehow... sorry, good point 3gengames. : )

edit: My code was like your second example... but it ended with a new address written to $2006... and I experienced the same problem... all the attribute tables left... everything was on the same palette... and so I guessed that it isn't good to have a loop end with a $2006 write.
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 »

This morning I found something that I dont understand. Could you help me?
Here is the code I'm working with

Code: Select all

  draw_RAMbuffer2:   ;"Prepare the (new nametable) writes in a RAM buffer during draw time..." tepples pg 59
      
	  sta $ff
	  ldy #$00 ;e
	  
	  
	  ldx #$02
	  jsr load_screen  ;this just enables us to use the lda ($10), y instruction
                                        ; and the ldx #$02 is used inside load_screen... loads screen #2
	  lda #30
	  sta t2
	  
	  ;---
	  ;
 --   lda ($10), y
	  tax 
 ;29  lda MetatileTile3, x
      lda MetatileTile3, x
	  pha ;--->
 ;30  lda MetatileTile1, x
      lda MetatileTile1, x
	  ldx t2           ;<--- this correctly sets X to write to RAMbuffer2
	  sta RAMbuffer2, x
	  dex
	  pla ;<---
	  sta RAMbuffer2, x
	  
	  ;increment y by 16!!!!
	  tya
	  clc
	  adc #$10 ;#16
	  tay
	  
	  dex
	  stx t2
      bne -- 
	  
	  rts ;end of draw_RAMbuffer2 and of nCPUmem
	  
Ok, this code works almost perfectly... it messes up on the first run... instead of tile #00 it loads tile #04 on the top of the screen. But, as I follow the code it has an = #$04 at the end of

Code: Select all

0F:C47A:BD EC C7  LDA $C7EC,X @ $C80A = #$12
0F:C47D:48        PHA
0F:C47E:BD 2E C6  LDA $C62E,X @ $C64C = #$13
0F:C481:A6 31     LDX $0031 = #$1E
0F:C483:95 51     STA $51,X @ $006F = #$04
0F:C485:CA        DEX
It shows the = #$04 once the assembler gets to that line... but the accumulator always holds #$00 before the step into button is clicked. I'm guessing that is trying to say that #$04 is already written there... that's confusing because after i click step into the accumulator writes the zero it has been holding... and there is always a tile #04 at the top of the screen. :?
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 having trouble following it, but:
I'm guessing that is trying to say that #$04 is already written there
Correct, it's the value in that RAM location before the sta.
and there is always a tile #04 at the top of the screen. :?
Break on writes to $006F. Is 4 written there ever? If not, it sounds more like there's an issue with your code that writes these bytes to $2007.
Also: It's tiny, but there's no need to do this:

Code: Select all

     adc #$10 ;#16
This would work fine on most assemblers:

Code: Select all

adc #16
Edit: While trying to optimize this, I might have found a potential problem.

Code: Select all

draw_RAMbuffer2:   ;"Prepare the (new nametable) writes in a RAM buffer during draw time..." tepples pg 59
     
     sta $ff
     ldy #$00 ;e
    
    
     ldx #$02
     jsr load_screen  ;this just enables us to use the lda ($10), y instruction
                                        ; and the ldx #$02 is used inside load_screen... loads screen #2
     lda #30
     sta t2
    
     ;---
    
 --   lda ($10), y ;What's in y? Does it stay #$00 after the jsr load_screen? 
If it were me, I would move the ldy #$00 directly above the loop. Because when you look at this code later, it will keep you from having to check whether load_screen changes it. Unless load_screen sets it up to some known expected value in which case, ignore what I just said. :lol:
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 having trouble following it, but:
I'm guessing that is trying to say that #$04 is already written there
Correct, it's the value in that RAM location before the sta.
Thanks very much! :D
Kasumi wrote:
and there is always a tile #04 at the top of the screen. :?
Break on writes to $006F. Is 4 written there ever?
Yes there is a 4 written there! Wahoo! Guess I could change it to 5... and see if the tile changes... (Looking back on this... I'm confused still because my code says

Code: Select all

0C4AF                           update_vram: ;testing... :)
0C4AF A5 6F                             lda my_copy_of_last_write_to_PPUCTRL
0C4B1 09 04                     		ora #00000100b  ;change $2007 increment to +32
0C4B3 8D 00 20                  		sta $2000
0C4B6 85 6F                     		sta my_copy_of_last_write_to_PPUCTRL
0C4B8                          
0C4B8 ...	
and so it somehow gets that value???) edit: it does change to tile #5[/color] :?
Kasumi wrote:Also: It's tiny, but there's no need to do this:

Code: Select all

     adc #$10 ;#16
This would work fine on most assemblers:

Code: Select all

adc #16
Muhahaha... I was trying to teach me that $10 is not equal to 10. :) :oops:
Kasumi wrote:Edit: While trying to optimize this, I might have found a potential problem.

Code: Select all

draw_RAMbuffer2:   ;"Prepare the (new nametable) writes in a RAM buffer during draw time..." tepples pg 59
     
     sta $ff
     ldy #$00 ;e
    
    
     ldx #$02
     jsr load_screen  ;this just enables us to use the lda ($10), y instruction
                                        ; and the ldx #$02 is used inside load_screen... loads screen #2
     lda #30
     sta t2
    
     ;---
    
 --   lda ($10), y ;What's in y? Does it stay #$00 after the jsr load_screen? 
If it were me, I would move the ldy #$00 directly above the loop. Because when you look at this code later, it will keep you from having to check whether load_screen changes it. Unless load_screen sets it up to some known expected value in which case, ignore what I just said. :lol:
Haha it's ok, no it doesn't do anything with y... that's quite a good comment! Thanks Kasumi! :D
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 »

Yes there is a 4 written there! Wahoo!
So you see the problem, right?

This: 0F:C483:95 51 STA $51,X @ $006F = #$04

And this: 0C4B6 85 6F sta my_copy_of_last_write_to_PPUCTRL

overlap. (Note that they both write to $6F.)

So anytime you write a number to "my_copy_of_last_write_to_PPUCTRL", it changes the tile because it overlaps the RAM you're using for the tile buffer (and vice versa). You gotta arrange your RAM so nothing overlaps.
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:
Yes there is a 4 written there! Wahoo!
So you see the problem, right?

This: 0F:C483:95 51 STA $51,X @ $006F = #$04

And this: 0C4B6 85 6F sta my_copy_of_last_write_to_PPUCTRL

overlap. (Note that they both write to $6F.)

So anytime you write a number to "my_copy_of_last_write_to_PPUCTRL", it changes the tile because it overlaps the RAM you're using for the tile buffer (and vice versa). You gotta arrange your RAM so nothing overlaps.
I didn't know RAM can overlap... thank you so much for telling me! :D Now I'm going to try to find out what to do to make it not overlap anymore.

edit.
edit2: Well... um how can I make my RAM not overlap? :?

Code: Select all

0002C                           SomethingSolidtoStandon .dsb 1
0002D                           ofracorhiX .dsb 2 ;<----.
0002F                           ofracorhiY .dsb 2 ;<--------- "... your position will need another byte to represent the fractional part of the position, which if you scroll means you'll need at least 3 bytes for the position alone ..." -Kasumi p. 51 +
00031                           t2 .dsb 2
00033                           RAMbuffer1 .dsb 30 ;just a temporary destination for writes to next collum of vram... they'll be written during vblank. :)
00051                           RAMbuffer2 .dsb 30
0006F                           my_copy_of_last_write_to_PPUCTRL .dsb 1
00070                           
00070                           
[/color]
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 »

edit2: Well... um how can I make my RAM not overlap? :?
Well... maybe your RAM isn't overlapping, but you're running past what you've allocated for RAMbuffer2.

So..

Code: Select all

00051                           RAMbuffer2 .dsb 30
0006F                           my_copy_of_last_write_to_PPUCTRL .dsb 1
So you've allocated 30 bytes for RAMbuffer2. This means $51+0 through $51+29 are allocated to RAMbuffer2. This is a range from $51 to $6E. Much like 0 and 1 is two numbers, 0-29 is 30.
Knowing this, here's the issue:

Code: Select all

     lda #30
     sta t2
So we've got #30 in T2.

Code: Select all

ldx t2           ;<--- this correctly sets X to write to RAMbuffer2
     sta RAMbuffer2, x
RAMbuffer2 ($51)+30(X) is outside the range of the buffer. Right now your code works from 30 to 1 instead of 29 to 0.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

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

Post by tepples »

unregistered wrote:I didn't know RAM can overlap
There are two kinds of assembly language programmers: those who have written a buffer overflow and those who have yet to.
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:
edit2: Well... um how can I make my RAM not overlap? :?
Well... maybe your RAM isn't overlapping, but you're running past what you've allocated for RAMbuffer2.

So..

Code: Select all

00051                           RAMbuffer2 .dsb 30
0006F                           my_copy_of_last_write_to_PPUCTRL .dsb 1
So you've allocated 30 bytes for RAMbuffer2. This means $51+0 through $51+29 are allocated to RAMbuffer2. This is a range from $51 to $6E. Much like 0 and 1 is two numbers, 0-29 is 30.
Knowing this, here's the issue:

Code: Select all

     lda #30
     sta t2
So we've got #30 in T2.

Code: Select all

ldx t2           ;<--- this correctly sets X to write to RAMbuffer2
     sta RAMbuffer2, x
RAMbuffer2 ($51)+30(X) is outside the range of the buffer. Right now your code works from 30 to 1 instead of 29 to 0.
Hmmm... :oops: Thank you Kasumi for your explanation here! :D :oops: I understand it much better after reading what tepples linked to...
tepples wrote:
unregistered wrote:I didn't know RAM can overlap
There are two kinds of assembly language programmers: those who have written a buffer overflow and those who have yet to.
It's quite odd amazing that my buffer overflow overflows a variable named RAMbuffer2. ...Hahaha :lol: 8-) :)

edit.
Post Reply