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

tepples
Posts: 22052
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 8x16 and whatever else unreg wants to know

Post by tepples » Tue Oct 01, 2013 1:36 pm

If your metatiles are the same size as those of Super Mario Bros. series, then nametable 0 contains metatile columns 0-15, and nametable 1 contains metatile columns 16-31. Once the camera begins to advance toward the right, nametable 0 will fill up with columns 32-47, etc.

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Tue Oct 01, 2013 1:55 pm

Yes I understand thanks! My RAMbuffer is now 16 pixels wide. ... it seems easier to keep track of two buffers instead of 4.

added.

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Fri Oct 04, 2013 3:07 pm

tepples wrote:If your metatiles are the same size as those of Super Mario Bros. series, then nametable 0 contains metatile columns 0-15, and nametable 1 contains metatile columns 16-31. Once the camera begins to advance toward the right, nametable 0 will fill up with columns 32-47, etc.
Ok so visible_left should be 16bit? My column 32 is 0 right now. ...well no not 16bit... I'm not sure what to do. hmmmmmm...

edit.
edit2: So, I need to store my value in visible_left after I divide ColumnX by 8... How do I divide a 16 bit number by 8?

tepples
Posts: 22052
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 8x16 and whatever else unreg wants to know

Post by tepples » Fri Oct 04, 2013 3:55 pm

To divide a number by 8, shift it to the right three times. For a 16-bit number it'll look like this:

Code: Select all

lda num_lo
sta tmp0
lda num_hi
lsr a
ror tmp0
lsr a
ror tmp0
lsr a
ror tmp0

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Fri Oct 04, 2013 3:58 pm

tepples wrote:To divide a number by 8, shift it to the right three times. For a 16-bit number it'll look like this:

Code: Select all

lda num_lo
sta tmp0
lda num_hi
lsr a
ror tmp0
lsr a
ror tmp0
lsr a
ror tmp0
like this:?

Code: Select all

  lda CameraX+1
  lsr
  ror visible_left
  lsr CameraX+1
  ror visible_left
  lsr CameraX+1
  ror visible_left
  
  sta visible_left
but my column 32 is still 0...

edit: Thank you so much tepples! :D It is nice to know that the carry will definitly keep track of the numbers... my code still says zero... but I'm gonna fix this.
edit2: I'm feeling proud of myself for trying and guessing correctly how to do this divide a 16bit number by 8. :D
edit3: Woah I should say that I'm probably wrong... I guessed correctly about the lsr and ror... but have just noticed you usse a different variable at the top... why do you do that? :?
last edit: Ah yes, now it works great. I understand now... thank you for allowing me enough time to figure this out. :oops: :) :D :mrgreen:

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Thu Oct 10, 2013 1:47 pm

Code: Select all

;/****************************************
next:  ;me grab toward the next nametable column
;  columnLo and columnHi are the address of the place to draw new columns
;****************************************/
  ;name table0 ($2000)
 ; wait until the second nametable switch
  
  lda CameraX+0
  lsr a
  lsr a
  lsr a           ; shift right 3 times = divide by 8
  sta columnLo ;instead of this dividing by 8... just add 2 to the previous value of columnLo...duh.
                           ;well, adding 2 works fine until columnLo becomes > 32... then it becomes very not good.
  
  lda currNameTable
  and #$01
  eor #$01      ; invert low bit, A = $00 or $01
  asl a			; shift up, A = $00 or $02
  asl a			; $00 or $04
  clc
  adc #$20      ; add high byte of nametable base address ($2000)
  sta columnHi  ; now address = $20 or $24 for nametable 0 or 1
  
  rts ;end of next
This is just code from nerdy nights scrolling tutorial... The problem I'm having is that it draws the next column in the next 16 bits... and then draws the next column 8 pixels over....

screen looks like this

Code: Select all

1111111112
1111111112
1111111112
instead of this

Code: Select all

1212121212
1212121212
1212121212
How do I make it draw a column (each column is 16 pixels wide)... then skip 2 spaces and draw the next column? Does this make sense?

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Mon Oct 21, 2013 9:13 am

Im continuing with this today... had other work to do till now.

thought I would add that each 16 pixel column would look like this

Code: Select all

12
12
12

Code: Select all

update_vram: ;testing... good sofar!
        sta $ff
		
		
		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 iBeginAtOne  ;ahahahahahhahahahahahahahahaha!  it works!!!  :)
		bne +end


            bit PPUSTATUS2 ;"And I did lda $2002 in this examples, but using bit lets you read it without changing A, so that's usually what you'd want to do." -Kasumi p. 70;
     		lda #$20
		    sta PPUADDR6
		    lda #$00
		    sta PPUADDR6
		
		    tay
		    ldx #58 ;58 ;should hold last even spot written to RAMbufferw0. both columns are always full so #58 and #59
	    -   lda RAMbufferw0, x
		    sta PPUDATA7
            dex
			dex  ;subtract 2 to stay in the even column
		    bpl -
		    
              iny
	          lda #$20
		      sta PPUADDR6
		      sty PPUADDR6
            
			ldx #59;59 for the odd column
	    -	lda RAMbufferw0, x
		    sta PPUDATA7
            dex
			dex  ;stay in odd column
		    bpl -

              bit PPUSTATUS2 ;"And I did lda $2002 in this examples, but using bit lets you read it without changing A, so that's usually what you'd want to do." -Kasumi p. 70;
			  lda #$20
		      sta PPUADDR6
		      iny
			  sty PPUADDR6

            tay
			ldx #58 ;58 ;should hold last even spot written to RAMbufferw1. both columns are always full so #58 and #59
	    -   lda RAMbufferw1, x
		    sta PPUDATA7
            dex
			dex  ;subtract 2 to stay in the even column
		    bpl -

			  iny
	          lda #$20
		      sta PPUADDR6
		      sty PPUADDR6
			  
            ldx #59;59 for the odd column
	    -	lda RAMbufferw1, x
		    sta PPUDATA7
            dex
			dex  ;stay in odd column
		    bpl -
			

		jsr update_colors		
 +end:	rts ;end of update_vram.
This ^ is what I have so far minus the commented lines of code... it's just too much code to put here. I'm hoping that one of you can show me a way to draw each entire 16 pixel column... Each of them are specified in either RAMbufferw0 or RAMbufferw1.

edit: Ok what I'm wanting seems to be help with my scrolling code.

Code: Select all

scroll_screen:
;PPUCTRL Controller ($2000) > write
;PPUMASK Mask ($2001) > write
;PPUSTATUS Status ($2002) < read
;OAMADDR address ($2003) > write
;OAMDATA OAM data ($2004) <> read/write
;PPUSCROLL Scroll ($2005) >> write x2
;PPUADDR Address ($2006) >> write x2
;PPUDATA Data ($2007) <> read/write
  sta $ff
  lda CameraX+0
  sta visible_left
  lda CameraX+1
  lsr a
  ror visible_left
  lsr a
  ror visible_left
  lsr a
  ror visible_left
  
  
   ;if CameraX == 0
  lda CameraX+0
  bne +
   lda currNameTable
   eor #$01  ;invert the nametable bit
   sta currNameTable  ;and make it current. :)
   and #00000001b
   beq +special
   jmp +
    +special: 
       lda #$00
	   sta iBeginAtOne

  +  ;if oX >= 128
  sec      ;Set Subtract. Clear Add.
  lda oX+0
  sbc #$80
  bcc +skipincrem

    ;if player is pressing right
	lda currControllerButtons
    and #BUTTON_RIGHT
    beq +skipincrem
    

      ;lda CameraX+1
	  ;beq +
	 ; lda CameraX+0
	 ; sec             ;Set subtract. Clear Add.
	 ; sbc #255
     ; bne +
	   ;jsr camera_aim ; jsr next ;beq +skippingscroll

        
		+ ;increment SCROLL position

        lda CameraX+0
	    clc
	    adc #$01
	    sta CameraX+0
	    
	    lda CameraX+1
	    adc #$00
	    sta CameraX+1


  +skipincrem:
    lda #10001000b
    sta currNameTable

    lda CameraX+1 ;get the high byte of the camera ((is #$ff in the start after reset) WHY?)
	and #$01 ;keep only the lowest (first) bit
	ora currNameTable ;combine with the other PPU settings
	sta currNameTable ;this is what you'll write to $2000 when setting the scroll

    ; run other game graphic updating code here
	;lda CameraX+0
	;and #00000111b    ; throw away higher bits
	;bne +  ; see if lower bits == 0

    
	  ;jsr draw_me_a_column

+	lda currNameTable
    sta PPUCTRL0
	sta my_copy_of_last_write_to_PPUCTRL
	
	bit PPUSTATUS2  ;<reading $2002 resets both double write registers ($2005 and $2006) so that my first write will go to Xcoord.
	
	lda CameraX+0  ; time to MOVE THE CAMERA OBJECT!
	sta PPUSCROLL5     ; write the horizontal scroll count register
	
	lda #$00        ; (no vertical srolling)
    sta PPUSCROLL5     ; set the vertical scroll

  rts ;end of scroll_screen
I want each entire 16 bit column to be drawn. When the scrolling code scrolls the screen I still want it to look like this:

Code: Select all

1212121212
1212121212
1212121212
edit2: 6:38PM NEVERMIND I GOTS IT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :D :mrgreen:

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Tue Oct 22, 2013 8:06 pm

Ok, so now here's what's next. Right now I have a draw_me_a_column method that excellently draws one of the two 16pixelwide columns RAMbufferw0 and RAMbufferw1. It draws RAMbufferw1 currently. I want to be able to choose which buffer on the fly... like with pointers...
tokumaru[color=#00FF40], on page 29,[/color] wrote:A pointer is an address you can modify dynamically, so if you use pointers to access the data you can have the same code work with different sets of data just by modifying the pointer dynamically.
Excellent thanks again tokumaru! :D I want my method to work with both sets of data (RAMbufferw0 and RAMbufferw1). In this thread, on page 4, yall discussed pointer tables... I do think my pointers situation isn't as complex as pointer tables. Maybe I could use them... I'm don't know right now. :?
Kasumi[color=#FF00FF], on page 31,[/color] wrote:6502 assembly isn't "type safe" like C is. What this means is your program/assembler doesn't know or care what you are using your variables for. C will actually fix how operations work on a variable based on what you're using that variable for. For instance, pointer++; could increase the address the pointer is holding by 1, 2 or any other number depending on how large the type of data is that the pointer is supposed to point to. Assembly doesn't care, so it's up to you to keep track.
Now I'm scared to mess around with pointers in 6502 assembly. :shock:

So please could you help me figure these pointers out? :) I'm susposed to use the addressing mode (), y to access the pointers; however, I don't know how to write the pointer code out... my brain is dead right now sorry.

edit.

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Sat Oct 26, 2013 10:07 am

unregistered wrote:I want to be able to choose which buffer on the fly... like with pointers...
tokumaru[color=#00FF40], on page 29,[/color] wrote:A pointer is an address you can modify dynamically, so if you use pointers to access the data you can have the same code work with different sets of data just by modifying the pointer dynamically.
tokumaru, you mention that the pointer should be modified dynamically twice, could you show me an example of "modifying the pointer dynamically"? Dictionary.com says, "Dynamic memory must be constantly refreshed to avoid losing data." "...constantly refreshed" confuses me. :?

Joe
Posts: 437
Joined: Mon Apr 01, 2013 11:17 pm

Re: 8x16 and whatever else unreg wants to know

Post by Joe » Sat Oct 26, 2013 11:08 am

unregistered wrote:tokumaru, you mention that the pointer should be modified dynamically twice, could you show me an example of "modifying the pointer dynamically"?
Modifying the pointer dynamically just means setting it to different values before calling the function. For example, the pointer might be stored in the zero page, and the function would do something like this:

Code: Select all

lda (pointer), Y
Before calling the function that uses the pointer, you'd have to put a value into the pointer.

Code: Select all

lda #>RAMbufferw0
sta pointer
lda #<RAMbufferw0
sta pointer+1
jsr function_that_uses_the_pointer
[/strikeout]Edit: Let me try that again...

Code: Select all

lda #<RAMbufferw0
sta pointer
lda #>RAMbufferw0
sta pointer+1
jsr function_that_uses_the_pointer
The "dynamic" part is the fact that you can set the pointer to different values each time you call the function.
unregistered wrote:Dictionary.com says, "Dynamic memory must be constantly refreshed to avoid losing data." "...constantly refreshed" confuses me. :?
It sounds similar, but "dynamic memory" has nothing to do with "dynamically modifying memory". Don't worry; you don't have to constantly refresh anything.
Last edited by Joe on Sat Oct 26, 2013 11:40 pm, edited 1 time in total.

User avatar
tokumaru
Posts: 11858
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru » Sat Oct 26, 2013 12:19 pm

Joe is correct, you just have to make your pointers point to the location you want to read/write before you do any reading/writing. The address is "dynamic" because it can be changed, it's not fixed like is the case with absolute addressing.
unregistered wrote:Dictionary.com says, "Dynamic memory must be constantly refreshed to avoid losing data." "...constantly refreshed" confuses me. :?
This is a hardware detail (that "constant refreshing" is performed by the hardware itself in machines that need it) that has nothing to do with what you're doing now, so don't worry.

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Sat Oct 26, 2013 10:20 pm

Joe wrote:
unregistered wrote:tokumaru, you mention that the pointer should be modified dynamically twice, could you show me an example of "modifying the pointer dynamically"?
Modifying the pointer dynamically just means setting it to different values before calling the function. For example, the pointer might be stored in the zero page, and the function would do something like this:

Code: Select all

lda (pointer), Y
Before calling the function that uses the pointer, you'd have to put a value into the pointer.

Code: Select all

lda #>RAMbufferw0
sta pointer
lda #<RAMbufferw0
sta pointer+1
jsr function_that_uses_the_pointer
The "dynamic" part is the fact that you can set the pointer to different values each time you call the function.
unregistered wrote:Dictionary.com says, "Dynamic memory must be constantly refreshed to avoid losing data." "...constantly refreshed" confuses me. :?
It sounds similar, but "dynamic memory" has nothing to do with "dynamically modifying memory". Don't worry; you don't have to constantly refresh anything.
Thank you Joe! Thanks for the example code! :D In my opinion now, it seems that your pointer would be created backwards with the switched >< signs. The low byte should be stored first... then the high byte. That's what I've learned so far I think.
tokumaru wrote:Joe is correct, you just have to make your pointers point to the location you want to read/write before you do any reading/writing. The address is "dynamic" because it can be changed, it's not fixed like is the case with absolute addressing.
unregistered wrote:Dictionary.com says, "Dynamic memory must be constantly refreshed to avoid losing data." "...constantly refreshed" confuses me. :?
This is a hardware detail (that "constant refreshing" is performed by the hardware itself in machines that need it) that has nothing to do with what you're doing now, so don't worry.
Ok thanks tokumaru! :D

Joe and tokumaru and everyone else please forgive me... I've not achieved anything yet... it will take some time tomorrow... I have to think all of this over. Goodnight everyone. :)

Joe
Posts: 437
Joined: Mon Apr 01, 2013 11:17 pm

Re: 8x16 and whatever else unreg wants to know

Post by Joe » Sat Oct 26, 2013 11:38 pm

unregistered wrote:In my opinion now, it seems that your pointer would be created backwards with the switched >< signs. The low byte should be stored first... then the high byte. That's what I've learned so far I think.
Whoops! Good catch! :oops:

Let me just edit my post...

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

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

Post by unregistered » Tue Oct 29, 2013 3:19 pm

tepples[color=#FF0080], on pg 69,[/color] wrote:Depending on how you organize the map data, you may have to either draw two columns at once like Super Mario Bros. and Contra or store enough information to regenerate the attributes for the column that you're updating.
.......so when drawing two columns at once... you have to wait on the columns to enter the rightmost attribute table spot before coloring them? That would be kind of odd. While playing Super Mario Bros. there wasn't any flickering of the last two columns that I could see.

tepples
Posts: 22052
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 » Tue Oct 29, 2013 4:39 pm

unregistered wrote:so when drawing two columns at once... you have to wait on the columns to enter the rightmost attribute table spot before coloring them? That would be kind of odd. While playing Super Mario Bros. there wasn't any flickering of the last two columns that I could see.
Momentary miscoloring occurs at the seam. Super Mario Bros. arranges its nametables horizontally ("vertical mirroring"), letting it keep the seam offscreen. Go play Super Mario Bros. 3 once if you want to see color artifacts. SMB3 uses two vertically arranged nametables ("horizontal mirroring") for a 27-metatile-tall playfield plus status bar at the cost of miscoloring the tiles at the far right.

Post Reply