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

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

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

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

### Re: 8x16 and whatever else unreg wants to know

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

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

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! 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.
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.

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

### Re: 8x16 and whatever else unreg wants to know

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

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

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
lda #\$00

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

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
iny

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

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
;OAMDATA OAM data (\$2004) <> read/write
;PPUSCROLL Scroll (\$2005) >> write x2
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
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
sta CameraX+0

lda CameraX+1
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!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

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

### Re: 8x16 and whatever else unreg wants to know

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! 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.

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

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

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.

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

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

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

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

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!

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?

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?

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.