8x16 and whatever else unreg wants to know
Moderator: Moderators
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.
-
- Posts: 1318
- 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.
added.
added.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 and whatever else unreg wants to know
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...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.
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?
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
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 and whatever else unreg wants to know
like this:?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
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
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.
-
- Posts: 1318
- 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
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
screen looks like this
Code: Select all
1111111112
1111111112
1111111112
Code: Select all
1212121212
1212121212
1212121212
-
- Posts: 1318
- 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
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.
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:
edit2: 6:38PM NEVERMIND I GOTS IT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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.
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
Code: Select all
1212121212
1212121212
1212121212
-
- Posts: 1318
- 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...
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.
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.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.
Now I'm scared to mess around with pointers in 6502 assembly.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.
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.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 and whatever else unreg wants to know
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.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.
Re: 8x16 and whatever else unreg wants to know
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:unregistered wrote:tokumaru, you mention that the pointer should be modified dynamically twice, could you show me an example of "modifying the pointer dynamically"?
Code: Select all
lda (pointer), Y
Code: Select all
lda #>RAMbufferw0
sta pointer
lda #<RAMbufferw0
sta pointer+1
jsr function_that_uses_the_pointer
Code: Select all
lda #<RAMbufferw0
sta pointer
lda #>RAMbufferw0
sta pointer+1
jsr function_that_uses_the_pointer
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.unregistered wrote:Dictionary.com says, "Dynamic memory must be constantly refreshed to avoid losing data." "...constantly refreshed" confuses me.
Last edited by Joe on Sat Oct 26, 2013 11:40 pm, edited 1 time in total.
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.
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 wrote:Dictionary.com says, "Dynamic memory must be constantly refreshed to avoid losing data." "...constantly refreshed" confuses me.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 and whatever else unreg wants to know
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.Joe wrote: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:unregistered wrote:tokumaru, you mention that the pointer should be modified dynamically twice, could you show me an example of "modifying the pointer dynamically"?Before calling the function that uses the pointer, you'd have to put a value into the pointer.Code: Select all
lda (pointer), Y
The "dynamic" part is the fact that you can set the pointer to different values each time you call the function.Code: Select all
lda #>RAMbufferw0 sta pointer lda #<RAMbufferw0 sta pointer+1 jsr function_that_uses_the_pointer
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.unregistered wrote:Dictionary.com says, "Dynamic memory must be constantly refreshed to avoid losing data." "...constantly refreshed" confuses me.
Ok thanks tokumaru!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.
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 wrote:Dictionary.com says, "Dynamic memory must be constantly refreshed to avoid losing data." "...constantly refreshed" confuses me.
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.
Re: 8x16 and whatever else unreg wants to know
Whoops! Good catch!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.
Let me just edit my post...
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 sprite is really a 16x32 pixel image?
.......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[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.
Re: 8x16 sprite is really a 16x32 pixel image?
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.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.