8x16 and whatever else unreg wants to know
Moderator: Moderators
Re: 8x16 sprite is really a 16x32 pixel image?
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 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.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 sprite is really a 16x32 pixel image?
...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?
Re: 8x16 sprite is really a 16x32 pixel image?
$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.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 sprite is really a 16x32 pixel image?
Well... that is exactly where it is... you are correct! I'm confused... maybe I'll get less confused with more experience?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.
edit: Thank you tepples!
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 sprite is really a 16x32 pixel image?
Here is the code I'm working on...
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...
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.
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.
Re: 8x16 sprite is really a 16x32 pixel image?
Why would you not structure code like this?
or even better, if you can put your buffer backwards: (Which you should do basically always)
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.
Code: Select all
(Write PPU column here)
LDX #$00
CDataWriteLoop:
LDA Buffer,X
STA PPUData
INX
CPX #30 ;30 tiles?
BNE .CDataWriteLoop
RTS
Code: Select all
LDX #30 ;30 Tiles
CDataWriteLoop:
LDA Buffer,X
STA PPUData
DEX
BNE .CDataWriteLoop
RTS
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 sprite is really a 16x32 pixel image?
Oooh...3gengames wrote:or even better, if you can put your buffer backwards: (Which you should do basically always)
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.Code: Select all
LDX #30 ;30 Tiles CDataWriteLoop: LDA Buffer,X STA PPUData DEX BNE .CDataWriteLoop RTS
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.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 sprite is really a 16x32 pixel image?
This morning I found something that I dont understand. Could you help me?
Here is the code I'm working with
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
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.
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
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
Re: 8x16 sprite is really a 16x32 pixel image?
I'm having trouble following it, but:
Also: It's tiny, but there's no need to do this:
This would work fine on most assemblers:
Edit: While trying to optimize this, I might have found a potential problem.
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.
Correct, it's the value in that RAM location before the sta.I'm guessing that is trying to say that #$04 is already written there
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.and there is always a tile #04 at the top of the screen.
Also: It's tiny, but there's no need to do this:
Code: Select all
adc #$10 ;#16
Code: Select all
adc #16
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?
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 sprite is really a 16x32 pixel image?
Thanks very much!Kasumi wrote:I'm having trouble following it, but:Correct, it's the value in that RAM location before the sta.I'm guessing that is trying to say that #$04 is already written there
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 saysKasumi wrote:Break on writes to $006F. Is 4 written there ever?and there is always a tile #04 at the top of the screen.
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 ...
Muhahaha... I was trying to teach me that $10 is not equal to 10.Kasumi wrote:Also: It's tiny, but there's no need to do this:This would work fine on most assemblers:Code: Select all
adc #$10 ;#16
Code: Select all
adc #16
Haha it's ok, no it doesn't do anything with y... that's quite a good comment! Thanks Kasumi!Kasumi wrote:Edit: While trying to optimize this, I might have found a potential problem.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.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?
Re: 8x16 sprite is really a 16x32 pixel image?
So you see the problem, right?Yes there is a 4 written there! Wahoo!
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.
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 sprite is really a 16x32 pixel image?
I didn't know RAM can overlap... thank you so much for telling me! Now I'm going to try to find out what to do to make it not overlap anymore.Kasumi wrote:So you see the problem, right?Yes there is a 4 written there! Wahoo!
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.
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
Re: 8x16 sprite is really a 16x32 pixel image?
Well... maybe your RAM isn't overlapping, but you're running past what you've allocated for RAMbuffer2.edit2: Well... um how can I make my RAM not overlap?
So..
Code: Select all
00051 RAMbuffer2 .dsb 30
0006F my_copy_of_last_write_to_PPUCTRL .dsb 1
Knowing this, here's the issue:
Code: Select all
lda #30
sta t2
Code: Select all
ldx t2 ;<--- this correctly sets X to write to RAMbuffer2
sta RAMbuffer2, x
Re: 8x16 sprite is really a 16x32 pixel image?
There are two kinds of assembly language programmers: those who have written a buffer overflow and those who have yet to.unregistered wrote:I didn't know RAM can overlap
-
- Posts: 1318
- Joined: Thu Apr 23, 2009 11:21 pm
- Location: cypress, texas
Re: 8x16 sprite is really a 16x32 pixel image?
Hmmm... Thank you Kasumi for your explanation here! I understand it much better after reading what tepples linked to...Kasumi wrote:Well... maybe your RAM isn't overlapping, but you're running past what you've allocated for RAMbuffer2.edit2: Well... um how can I make my RAM not overlap?
So..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.Code: Select all
00051 RAMbuffer2 .dsb 30 0006F my_copy_of_last_write_to_PPUCTRL .dsb 1
Knowing this, here's the issue:So we've got #30 in T2.Code: Select all
lda #30 sta t2
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.Code: Select all
ldx t2 ;<--- this correctly sets X to write to RAMbuffer2 sta RAMbuffer2, x
It's quite oddtepples wrote:There are two kinds of assembly language programmers: those who have written a buffer overflow and those who have yet to.unregistered wrote:I didn't know RAM can overlap
edit.