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

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

Post by unregistered »

I went through FamiToneUpdate and was looking for PPU accesses, but Shiru used names and at the top all the names are equal to $40xx addresses... Those are APU addresses I remember it said that... my memory is getting better! :D :oops:... so I wanted to tell you, tokumaru, that moving my scroll function up just above the SkipUpdates: (line $0C350) reverts my .nes file back to the problem preventing scrolling. ...So you are incredibly right when you say updating the scroll should always be the last step of vblank! Thank you so much telling me that! :D

I also want to say a little bit more about the quick flashing of alternate nametables that happens right now (after the screen has started scrolling). Before scrolling the screen the top half is the correct tiles... the bottom half is mostly tile 0. Like about three rows or so... ok so it's not mostly :( ...There are about three rows at the bottom of the screen; they're all tile 0. When scrolling starts there are a little over five rows of tile 0 at the bottom of the second screen that scrolls over. And then I can see both the first and second screen. In NINTENDULATOR as well as FCEUX 2.1.5. haha! I could try this on the powerpack... but... well maybe I shouldn't? :?
3gengames wrote:But I don't really see any problems, does the glitch happen with varying levels of height? it might be a wrong variable name somewhere or something like that. Log all your writes and make sure they're all right...
3gengames, I'm sorry I don't think I noticed this help... no the glitch happens at any height. "Log all my writes..."; so I need to use the logger on FCEUX.........? How... well, I know I can click writes in the debugger when setting a breakpoint... I'm confused; going to try doing ? :? Thank you so much for helping me too. :D

edit.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Post by Kasumi »

Long post. Forgive spelling/grammar/forgotten words, please. Usually I spend more time proofreading, but I've got some things I have to do tonight.

What's draw_sprite?
0C35D A2 00 ldx #$00 ; Reset VRAM
0C35F 8E 06 20 stx $2006
0C362 8E 06 20 stx $2006
I don't think there's a need for this. This would set the address $2007 would write to to zero if you wanted to do that, but it doesn't reset anything. If you're worried about the latches being out of sync, you could bit $2002.

Now, I don't understand your scrolling logic at all. Posting lots of code usually doesn't bother me, but I have to have an idea of what it's doing. Some stuff here is specific to your game which I have no clue about. I'm under the impression you're doing something like, "If the player is close to the edge of the screen, and he's holding right we scroll slightly faster than his walk speed" Is this correct?

Now, I just do this in my vblank:

Code: Select all

lda scrollxhigh
and #%00000001
ora mir2000;A variable that contains a mirror of $2000 that has already had its low two bits cleared out
sta $2000

lda scrollxlow
sta $2005
lda scrollyscreenlow
sta $2005
My vblank routine doesn't care about what the values are, nor does it try to update them because my game logic should take care of that.

Code: Select all

;ldx oX  work on this now
0C365                                 ;if oX > 192
0C365 A5 04                           lda oX
0C367 38                              sec
0C368 E9 C0                           sbc #192
0C36A 30 13                           bmi +skipscroll
First question: What's oX? Second thing, I think this won't branch in some cases you'd want it to. Let's say oX is 0. #$00-#$C0 (192) = #$40. #$40 = #%01000000. The high bit isn't set. No branch. So from #$00-#$3F this would NOT branch to skipscroll. From #$40-#$BF it would. Then from #$C0-#$FF it would not.

You may want to use the carry flag if you're trying to check if oX-192 was less than 0.

Code: Select all

0C36C                           
0C36C A5 00                             lda currControllerButtons  ;make sure the
0C36E 29 01                           and #00000001b          ;Right Button is being pressed
0C370 F0 0D                           beq +skipscroll
0C372                                 
0C372                           
0C372                                 ;lda #255
0C372                                 ;sta scroll
0C372 A5 1D                           lda CameraX+0
0C374 38                              sec             ;Set subtract. Clear Add.
0C375 E9 FF                           sbc #255
0C377 F0 06                           beq +skipscroll          ;skip incrementing scroll when it gets to #255
If CameraX is 253 or 254, the beq won't skip the scroll and we'll add 3 to cameraX because of the code below, scrolling past zero which seems like something you don't want to have happen.

Code: Select all

0C379                                 
0C379 E6 1D                        INC CameraX+0       ; add one to our camera variable each frame
0C37B E6 1D                        INC CameraX+0       ; add one to our camera variable each frame
0C37D E6 1D                        INC CameraX+0       ; add one to our camera variable each frame 

Code: Select all

0C37F A9 88                        lda #%10001000
0C381 85 1A                       ; sta currNameTable;No need to store here. You're doing it again without loading the value immediately after.
0C383 29 FE                        and #$fe ;clear the lowest bit;You don't need to do this. You loaded an immediate number that already has this bit clear.
0C385 85 1A                        sta currNameTable ;Als
As well, I can see no condition where CameraX+1 ever changes. This means that once you scroll hits 255 for nametable 1, you'll be seeing MOST of nametable 2. But then when it hits 0, you'll see none of nametable 2 and all of nametable 1 again. Right now this problem will happen for you at least some of the time, because if those three inc CameraX instructions I posted above wrap CameraX back to 0, the high byte is never updated.

Those are some problems I see. They actually probably won't fix the problem you describe, though. Please post anything that updates CameraX and CameraX+1 that outside of the vblank routine. (If there IS any code that updates them outside of the vblank.)

The camera should be a 16bit variable.

Want to scroll 8 pixels to the right?

Code: Select all

lda CameraX
clc
adc #$08
sta CameraX

lda CameraX+1
adc #$00
sta CameraX+1
If you want to not scroll past a certain value, check the high byte after the add to see if it became too large. If it did, set both the high and low byte to the furthest you want it to scroll.

Do any camera logic outside of your vblank.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Kasumi wrote:Long post. Forgive spelling/grammar/forgotten words, please. Usually I spend more time proofreading, but I've got some things I have to do tonight.
It's ok, thank you for the quick help! :D In 30 minutes I have to go mow... will try to reply to as much as I can now.
Kasumi wrote:

What's draw_sprite?
Oh sorry the code at bottom of page 43 should have continued... to the end of my vblank file...

Code: Select all

0C39D                           
0C39D                           
0C39D                           ;80 81       
0C39D                           ;90 91       
0C39D                           ;a0 a1       
0C39D                           ;b0 b1   
0C39D                           ;        .db aY, $80, $00, aX, aY, $81, $00, aX+8,
0C39D                           ;		    aY+8, $90, $00, aX, aY+8, $91, $00, aX+8,
0C39D                           ;		    aY+16, $a0, $00, aX, aY+16, $a1, $00, aX+8,
0C39D                           ;			aY+24, $b0, $00, aX, aY+24, $b1, $00, aX+8
0C39D                                   		
0C39D                             draw_sprite:
0C39D                           	  ; t0-t2 are temporary zero page locations holding
0C39D                           	  ; the address of a particular sprite layout and the
0C39D                           	  ; number of sprites left to draw
0C39D BD 14 D9                  	  lda sprite_layouts_lo, x  ;<-- ABSOLUTE INDEXED ADDRESSING
0C3A0 85 07                     	  sta t0
0C3A2 BD 28 D9                  	  lda sprite_layouts_hi, x  ;<-- ABSOLUTE INDEXED ADDRESSING
0C3A5 85 08                     	  sta t0+1
0C3A7 BD 3C D9                  	  lda sprite_layouts_count, x  ;<-- ABSOLUTE INDEXED ADDRESSING
0C3AA 85 09                     	  sta t2
0C3AC A0 00                     	  ldy #0
0C3AE                           	  ; oamIndex is a variable tracking how far you've written
0C3AE                           	  ; into shadow OAM (customarily at $0200-$02FF)
0C3AE A6 0B                     	  ldx oamIndex
0C3B0                           	@loop:
0C3B0                           	  ; If you have the address of an array in a zero page pointer,
0C3B0                           	  ; you use the (d),y addressing mode and increase Y to go
0C3B0                           	  ; to the next byte.
0C3B0 B1 07                     	  lda (t0), y  ;<-- INDIRECT INDEXED ADDRESSING
0C3B2 C8                        	  iny
0C3B3                           	  ;ect. start
0C3B3 18                        	  clc
0C3B4 65 05                     	  adc oY
0C3B6 9D 00 02                  	  sta sprite, x  ;<-- ABSOLUTE INDEXED ADDRESSING
0C3B9 E8                        	  inx
0C3BA                           	  
0C3BA B1 07                     	  lda (t0), y
0C3BC C8                        	  iny
0C3BD 9D 00 02                  	  sta sprite, x
0C3C0 E8                        	  inx
0C3C1                           	  
0C3C1 B1 07                     	  lda (t0), y
0C3C3 C8                        	  iny
0C3C4 9D 00 02                  	  sta sprite, x
0C3C7 E8                        	  inx
0C3C8                           	  
0C3C8 B1 07                     	  lda (t0), y
0C3CA C8                        	  iny
0C3CB 18                        	  clc
0C3CC 65 04                     	  adc oX
0C3CE 9D 00 02                  	  sta sprite, x
0C3D1 E8                        	  inx
0C3D2                           	  
0C3D2                           	  ;end ect.		  
0C3D2 C6 09                     	  dec t2
0C3D4 D0 DA                     	  bne @loop
0C3D6 86 0B                     	  stx oamIndex
0C3D8 60                        	  rts
there this is the very end of my vblank file.
Kasumi wrote:
0C35D A2 00 ldx #$00 ; Reset VRAM
0C35F 8E 06 20 stx $2006
0C362 8E 06 20 stx $2006
I don't think there's a need for this. This would set the address $2007 would write to to zero if you wanted to do that, but it doesn't reset anything. If you're worried about the latches being out of sync, you could bit $2002.
Sorry, I don't understand. :?
Kasumi wrote:Now, I don't understand your scrolling logic at all. Posting lots of code usually doesn't bother me, but I have to have an idea of what it's doing. Some stuff here is specific to your game which I have no clue about. I'm under the impression you're doing something like, "If the player is close to the edge of the screen, and he's holding right we scroll slightly faster than his walk speed" Is this correct?
Yes, that's how it works now... not complicated... I know.
Kasumi wrote:Now, I just do this in my vblank:

Code: Select all

lda scrollxhigh
and #%00000001
ora mir2000;A variable that contains a mirror of $2000 that has already had its low two bits cleared out
sta $2000

lda scrollxlow
sta $2005
lda scrollyscreenlow
sta $2005
My vblank routine doesn't care about what the values are, nor does it try to update them because my game logic should take care of that.
...I can't follow... :oops:

Kasumi wrote:

Code: Select all

;ldx oX  work on this now
0C365                                 ;if oX > 192
0C365 A5 04                           lda oX
0C367 38                              sec
0C368 E9 C0                           sbc #192
0C36A 30 13                           bmi +skipscroll
First question: What's oX?
oX is my variable for the x-coordinate location of my one sprite on the screen. oY is the y-coordinate... cause 'x' and 'y' refer to the x-register and y-register
Sorry, must go mow now...
edited.
Last edited by unregistered on Mon Jul 02, 2012 3:41 pm, edited 2 times in total.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Now, I dont have to mow... so here's the rest...
Kasumi wrote:Second thing, I think this won't branch in some cases you'd want it to. Let's say oX is 0. #$00-#$C0 (192) = #$40. #$40 = #%01000000. The high bit isn't set. No branch. So from #$00-#$3F this would NOT branch to skipscroll. From #$40-#$BF it would. Then from #$C0-#$FF it would not.
Ah, yes... after trying this with calculator Hex it read FFFFFFFFFFF40 and so I didn't see the fact that FF40 means 1111111101000000. In my head all the Fs made it confusing for me; thank you so much for seeing this and pointing it out! :D
Kasumi wrote:
You may want to use the carry flag if you're trying to check if oX-192 was less than 0.
Yes, thank you, I understand that now! :D
Kasumi wrote:

Code: Select all

0C36C                           
0C36C A5 00                             lda currControllerButtons  ;make sure the
0C36E 29 01                           and #00000001b          ;Right Button is being pressed
0C370 F0 0D                           beq +skipscroll
0C372                                 
0C372                           
0C372                                 ;lda #255
0C372                                 ;sta scroll
0C372 A5 1D                           lda CameraX+0
0C374 38                              sec             ;Set subtract. Clear Add.
0C375 E9 FF                           sbc #255
0C377 F0 06                           beq +skipscroll          ;skip incrementing scroll when it gets to #255
If CameraX is 253 or 254, the beq won't skip the scroll and we'll add 3 to cameraX because of the code below, scrolling past zero which seems like something you don't want to have happen.

Code: Select all

0C379                                 
0C379 E6 1D                        INC CameraX+0       ; add one to our camera variable each frame
0C37B E6 1D                        INC CameraX+0       ; add one to our camera variable each frame
0C37D E6 1D                        INC CameraX+0       ; add one to our camera variable each frame 

Code: Select all

0C37F A9 88                        lda #%10001000
0C381 85 1A                       ; sta currNameTable;No need to store here. You're doing it again without loading the value immediately after.
0C383 29 FE                        and #$fe ;clear the lowest bit;You don't need to do this. You loaded an immediate number that already has this bit clear.
0C385 85 1A                        sta currNameTable ;Als
As well, I can see no condition where CameraX+1 ever changes. This means that once you scroll hits 255 for nametable 1, you'll be seeing MOST of nametable 2. But then when it hits 0, you'll see none of nametable 2 and all of nametable 1 again. Right now this problem will happen for you at least some of the time, because if those three inc CameraX instructions I posted above wrap CameraX back to 0, the high byte is never updated.

Those are some problems I see. They actually probably won't fix the problem you describe, though. Please post anything that updates CameraX and CameraX+1 that outside of the vblank routine. (If there IS any code that updates them outside of the vblank.)

The camera should be a 16bit variable.

Want to scroll 8 pixels to the right?

Code: Select all

lda CameraX
clc
adc #$08
sta CameraX

lda CameraX+1
adc #$00
sta CameraX+1
If you want to not scroll past a certain value, check the high byte after the add to see if it became too large.
Ahhh this is making sense! :D Thank you, but I don't understand these next 2 parts... it's ok that I dont understand; you are not at fault. :)
Kasumi wrote:If it did, set both the high and low byte to the furthest you want it to scroll.
:?
Kasumi wrote: Do any camera logic outside of your vblank.
Why? :?
Denine
Posts: 397
Joined: Wed Feb 17, 2010 5:42 pm

Post by Denine »

unregistered wrote:Ahhh this is making sense! Very Happy Thank you, but I don't understand these next 2 parts... it's ok that I dont understand; you are not at fault. :)
Kasumi wrote:
If it did, set both the high and low byte to the furthest you want it to scroll.
Say, you want to restrict scrolling to 1 (high byte) and 40(low byte).
So when it get bigger(for example 1 and 41) you manually set bytes back to 1 and 40.Of course you can make different approach. For example, instead of setting bytes manualy, simply jump over scrolling increasement code.
unregistered wrote:
Kasumi wrote: Do any camera logic outside of your vblank.
Why? :?
Because Vblank time is precious and should not be wasted on thing that can be done in frame time. The thing is that during Vblank you can do various things that can't be done in frame time like writing to $2007(update tiles on screen, update pallete etc.) while screen rendering is turned ON.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

unregistered wrote:
Kasumi wrote:
0C35D A2 00 ldx #$00 ; Reset VRAM
0C35F 8E 06 20 stx $2006
0C362 8E 06 20 stx $2006
I don't think there's a need for this. This would set the address $2007 would write to to zero if you wanted to do that, but it doesn't reset anything. If you're worried about the latches being out of sync, you could bit $2002.
Sorry, I don't understand. :?
Writing zeroes to $2006 is something that bad NES programmers do when they don't know how to properly set the scroll and the screen is jumping. I seemingly fixes the problem, but it doesn't fully reset the scroll. BTW, since your game does scroll, you shouldn't be trying to reset the scroll at all, because if you were successful your screen just wouldn't move.

Anyway, the correct way to set the scroll is by writing once to $2000 (to select the name table) and twice to $2005 (to set the X and Y scroll values). $2006 should only be used for scrolling under special circumstances that newbies shouldn't be worried about (such as changing the scroll mid-frame). Under normal circumstances, $2006 should only be used for setting the PPU address before reading/writing data through $2007, and there's absolutely no need to reset that address.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Post by Kasumi »

unregistered wrote:In my head all the Fs made it confusing for me; thank you so much for seeing this and pointing it out! :D
Windows calculator? If so, protip: Switch it to byte mode. (There's a choice between Qword, Dword, Word, Byte when it's in hex or binary mode) That will make $00-$C0=$40, or turn -192 into $40 when switching to hex mode. No extra F's.

On another note: Provided I'm understanding it correctly, draw_sprite seems to be updating at least part of $0200-02FF. But you run update_sprite (which actually copies the sprite's data from $0200-$02FF) before it. This means whatever draw_sprite is writing will only appear during the NEXT vblank.

Edit: Hmm... I guess this DOES keep updates that don't need to be done before rendering after things that do which is good. But, I'd recommend moving it out of vblank entirely if that's possible.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Denine wrote:
unregistered wrote:Ahhh this is making sense! Very Happy Thank you, but I don't understand these next 2 parts... it's ok that I dont understand; you are not at fault. :)
Kasumi wrote:
If it did, set both the high and low byte to the furthest you want it to scroll.
Say, you want to restrict scrolling to 1 (high byte) and 40(low byte).
So when it get bigger(for example 1 and 41) you manually set bytes back to 1 and 40.Of course you can make different approach. For example, instead of setting bytes manualy, simply jump over scrolling increasement code.
unregistered wrote:
Kasumi wrote: Do any camera logic outside of your vblank.
Why? :?
Because Vblank time is precious and should not be wasted on thing that can be done in frame time. The thing is that during Vblank you can do various things that can't be done in frame time like writing to $2007(update tiles on screen, update pallete etc.) while screen rendering is turned ON.
Thank you Denine! :D

tokumaru wrote:
unregistered wrote:
Kasumi wrote: I don't think there's a need for this. This would set the address $2007 would write to to zero if you wanted to do that, but it doesn't reset anything. If you're worried about the latches being out of sync, you could bit $2002.
Sorry, I don't understand. :?
Writing zeroes to $2006 is something that bad NES programmers do when they don't know how to properly set the scroll and the screen is jumping. I seemingly fixes the problem, but it doesn't fully reset the scroll. BTW, since your game does scroll, you shouldn't be trying to reset the scroll at all, because if you were successful your screen just wouldn't move.

Anyway, the correct way to set the scroll is by writing once to $2000 (to select the name table) and twice to $2005 (to set the X and Y scroll values). $2006 should only be used for scrolling under special circumstances that newbies shouldn't be worried about (such as changing the scroll mid-frame). Under normal circumstances, $2006 should only be used for setting the PPU address before reading/writing data through $2007, and there's absolutely no need to reset that address.
Thank you tokumaru! :D
Kasumi wrote:
unregistered wrote:In my head all the Fs made it confusing for me; thank you so much for seeing this and pointing it out! :D
Windows calculator? If so, protip: Switch it to byte mode. (There's a choice between Qword, Dword, Word, Byte when it's in hex or binary mode) That will make $00-$C0=$40, or turn -192 into $40 when switching to hex mode. No extra F's.
Kasumi, thanks for mentioning that! :) It's good to know that there's a purpose for using byte mode.
Kasumi wrote:
On another note: Provided I'm understanding it correctly, draw_sprite seems to be updating at least part of $0200-02FF. But you run update_sprite (which actually copies the sprite's data from $0200-$02FF) before it. This means whatever draw_sprite is writing will only appear during the NEXT vblank.

Edit: Hmm... I guess this DOES keep updates that don't need to be done before rendering after things that do which is good. But, I'd recommend moving it out of vblank entirely if that's possible.
Hmm... :|
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Kasumi wrote:

Code: Select all

;ldx oX  work on this now
0C365                                 ;if oX > 192
0C365 A5 04                           lda oX
0C367 38                              sec
0C368 E9 C0                           sbc #192
0C36A 30 13                           bmi +skipscroll
...Second thing, I think this won't branch in some cases you'd want it to. Let's say oX is 0. #$00-#$C0 (192) = #$40. #$40 = #%01000000. The high bit isn't set. No branch. So from #$00-#$3F this would NOT branch to skipscroll. From #$40-#$BF it would. Then from #$C0-#$FF it would not.

You may want to use the carry flag if you're trying to check if oX-192 was less than 0.
Do you mean to say that I could change the bmi to branch on carry set or clear?

If not then I don't understand what you mean by, "You may want to use the carry flag if you're trying to check if oX-192 was less than 0." :? I'm sorry Kasumi. :(
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Post by Kasumi »

Code: Select all

;ldx oX  work on this now
0C365                                 ;if oX > 192 don't branch
0C365 A5 04                           lda oX
0C367 38                              sec
0C368 E9 C0                           sbc #192
0C36A 30 13                           bmi +skipscroll 
For unsigned subtracting, the carry is clear when the result (in actual arithmetic, forgetting all the byte stuff) would have been negative. Otherwise, it's set.

The minus flag will check if the result byte (with wrap around) is signed negative. It's different in some cases.

Forgetting hex for a moment:
0 - 192 = -192.
The carry would be clear after this subtraction because the result in real world math < 0.

But a signed byte can only store negative numbers from -1 through -128. Since the above subtraction is < -128, we wrapped back to positive numbers. This is why the minus bit isn't useful for this particular check. 0-192= -192. But -192 = $40 which doesn't have the high bit set.

(Before this edit, I made a definitive statement that you wanted to use bcc)
Edit: Err... wait. I take that back. Give me a second to puzzle over which to use.

And, I think I had it right. Should be bcc. See below for the reason for my confusion.

I always get confused when if statements are mixed with branches. (Do we not branch and run the code below if the statement is true, or do we branch if the statement is true?)

I avoid this confusion now by ending the if statements with the expected action. (If variable - 8 > 64, branch) or even (If variable - 8 <= 64, don't branch). It's a style choice you don't have to adopt, but it helps me a lot with reading old/unfamiliar code. :D

Now with it stated I may have it confused, I think your if statement comment may be incorrect. You may want it to say >=.

oX = 193
193 - 192 = 1.
Positive number. No branch.
193>192
No problem.

oX = 192
192-192 = 0.
Positive number. No branch.
192>192?
Nope.

The statement doesn't match the behavior, so whichever is "correct" should be updated to match the other.

I gotta learn to write shorter posts.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

^Thank you so much Kasumi!! :D Especially, thanks for letting me learn the logic below! Alot of your long letters have been lavishly learnable and likeable for me. :) A littler length may not only lose its luster, but it could also leave me lost, low, and lazily learning less.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Inside Nesst... there is an x variable that goes from 0 to 31 and thenthere's a y variable that increments to 1 as I move down to where x == 32. Is it possible to use a y variable... but how would you use it? Make it be a variable that increments on each #$20??
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Kasumi wrote:Those are some problems I see. They actually probably won't fix the problem you describe, though. Please post anything that updates CameraX and CameraX+1 that outside of the vblank routine. (If there IS any code that updates them outside of the vblank.)

Code: Select all

0C048                           	;matthew's init RAM
0C048 A9 8B                     	lda #$8b
0C04A 85 04                     	sta $0004 ;oX
0C04C 85 05                     	sta $0005 ;oY
0C04E A9 00                     	lda #$00
0C050 85 06                     	sta $0006 ;scroll
0C052 85 1B                     	sta $001b ;CameraX (object)
0C054 85 1C                     	sta $001c ;CameraX+1
0C056                           	
0C056                           	
0C056 A9 00                     	lda #$00
0C058 85 1A                     	sta currNameTable
0C05A                           	
0C05A                           	
0C05A 58                        	cli
0C05B                           ;----------------------------END OF RESET----------------------------------
There is the only time CameraX is updated (well initialized would be better) outside of vblank.

It is still messed up... with the screen switching back and forth from nametable 1 and nametable 2... they switch so fast I've been trying to find where in the code that it is doing this; after much efforts I have still not discovered it... and I've watched it through the repeating of the MainLoop... the screen never changed! :( :?
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Post by Kasumi »

Provided you've made all the changes I've talked about, and provided I haven't told you to make a change that was messed up (which is certainly possible), I've really found about all I can while just reading the code and I cannot debug for you any other way. Whenever I end up with a problem that I absolutely cannot solve, I just rewrite it.

There are very few variables involved here.

There are only two registers that should be affecting how to scroll the nametables when your screen is being rendered. $2005, and $2000. (Well, others can affect it, but not if you write to these last.) Break on writes to them, and find out what variables are stored there. Then find the code that updates those variables and find out why it's wrong. The fact that CameraX+1 is basically never touched makes it seem like you should be checking CameraX to see if it's doing something like switching between 0 and 255. (The only way I think that the nametables could be switching that quickly without CameraX+1's help).

Edit: You know what? Try commenting out jsr draw_sprite and/or jsr FamiToneUpdate. If doing that works, you've run out of vblank time. It probably isn't FamiTone, but last time I check draw_sprite was before scroll_screen. It's tough for me to tell how much time draw_sprite would take, but if commenting it out helps it should be moved directly before or directly after FamiToneUpdate.

But at this point, if that edit isn't true, I'd honestly just rewrite it. Remove 100% of the code that affects scroll variables and scroll registers. Then rewrite them slowly, and make sure independent parts work before putting them together. I may be wrong here, but I think you're trying to write too large pieces of code at once without verifying each small part. There's no reason not to verify even tiny things. Even for stuff that doesn't have any graphical output, you can just look at RAM values in a memory viewer.

d-pad->moves character->affects scroll variables->affects scroll registers
is harder to debug than
d-pad->affects scroll variables->affects scroll registers
which is harder to debug than
d-pad->affects scroll variables
which is harder to debug than
d-pad (And I assume you already have working code to check for button presses!)

I did something like this before I made my scrolling dependent on my character.
(I was already sure my d-pad checking subroutines worked well)

Code: Select all

;variables scrollxlow, scrollxhigh

jsr p1left;If left is not being pressed
bne skipscrollleft;branch
lda scrollxlow
sec
sbc #$01
sta scrollxlow

lda scrollxhigh
sbc #$00
sta scrollxhigh
skipscrollleft:

jsr p1right;if right is not being pressed
bne skipscrollright;branch
lda scrollxlow
clc
adc #$01
sta scrollxlow

lda scrollxhigh
adc #$00
sta scrollxhigh
skipscrollright:
You can actually look at those variables being updated in a memory viewer when you press the d-pad. If for some reason it's wrong (which it may be!), you'll only have to look at <30 lines of code.

When it's right, you can use those variables to actually update the scroll registers.

At the end of the NMI...

Code: Select all

lda ppu2000;a variable that contains the same value in $2000
and #%11111100
sta ppu2000

lda scrollxhigh
and #%00000001
ora ppu2000
sta ppu2000
sta $2000

lda scrollxlow
sta $2005
lda #$00
sta $2005
If something goes wrong, I'll only have to look at <20 lines of code.

Once I'm sure that works, I can make it so the scroll variables can't scroll past a max value or min value I set. When that works, I can make it so the scroll values are only added to when the character is past 192. When I'm sure that works, I can make it so a heavy enemy landing can shake the screen a little. If at any point something goes wrong, you'll know the newest thing is what's going wrong. (Well, sometimes something new creates a situation something old handles wrong that was never tested. But then... that usually means something old wasn't as well tested as it could have been before something new was added :D)

Doing this also really helps us, since we don't have to follow as much of the thread to help.

Short version: I've done about as much as I can with the info I've been given, and don't know what other info I could ask for that would help. I would rewrite it and check each very small part before moving on. I'm almost certain it will be faster than debugging what you've got, since I am rather stumped.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Kasumi wrote:Provided you've made all the changes I've talked about, and provided I haven't told you to make a change that was messed up (which is certainly possible), I've really found about all I can while just reading the code and I cannot debug for you any other way. Whenever I end up with a problem that I absolutely cannot solve, I just rewrite it.

There are very few variables involved here.

There are only two registers that should be affecting how to scroll the nametables when your screen is being rendered. $2005, and $2000. (Well, others can affect it, but not if you write to these last.) Break on writes to them, and find out what variables are stored there. Then find the code that updates those variables and find out why it's wrong. The fact that CameraX+1 is basically never touched makes it seem like you should be checking CameraX to see if it's doing something like switching between 0 and 255. (The only way I think that the nametables could be switching that quickly without CameraX+1's help).
So... I haven't rewritten my scrolling code because there is some other flashing of the nametables that happens if I press the A button 19 times in a row. And so I spent some time a few days trying to find a solution so that the A button could be pressed an infinite number of times in a row and the flashing would never happen. I kind of succeeded with this code

Code: Select all

0C35C                             draw_sprite:
0C35C                           	  
0C35C 85 FF                     	  sta $ff
0C35E E0 13                     	  cpx #19 ;this will prevent the screen from flashing
0C360 10 0F                     	  bpl  +
0C362                           	    
0C362                           	  
0C362                           	  
0C362                           	  ; t0-t2 are temporary zero page locations holding
0C362                           	  ; the address of a particular sprite layout and the
0C362                           	  ; number of sprites left to draw
0C362 BD D9 D8                  	  lda sprite_layouts_lo, x  ;<-- ABSOLUTE INDEXED ADDRESSING
0C365 85 07                     	  sta t0
0C367 BD ED D8                  	  lda sprite_layouts_hi, x  ;<-- ABSOLUTE INDEXED ADDRESSING
0C36A 85 08                     	  sta t0+1
0C36C BD 01 D9                  	  lda sprite_layouts_count, x  ;<-- ABSOLUTE INDEXED ADDRESSING
0C36F 85 09                     	  sta t2
0C371 A0 00                     	+ ldy #0
0C373                           	  ; oamIndex is a variable tracking how far you've written
0C373                           	  ; into shadow OAM (customarily at $0200-$02FF)
0C373 A6 0B                     	  ldx oamIndex
0C375                           	@loop:
0C375                           	  ; If you have the address of an array in a zero page pointer,
0C375                           	  ; you use the (d),y addressing mode and increase Y to go
0C375                           	  ; to the next byte.
0C375 B1 07                     	  lda (t0), y  ;<-- INDIRECT INDEXED ADDRESSING
0C377 C8                        	  iny
0C378                           	  ;ect. start
0C378 18                        	  clc
0C379 65 05                     	  adc oY
0C37B 9D 00 02                  	  sta sprite, x  ;<-- ABSOLUTE INDEXED ADDRESSING
Up there at the top I added to the code two lines
1)cpx #19
2)bpl +

Here's the place where the x is assigned right before jsring to... draw_sprite (^above).

Code: Select all

0C347                           
0C347 A6 0F                     	    		ldx aFrame
0C349 20 5C C3                  		jsr draw_sprite
0C34C                           
I was concerned that the X value could be more than #19... then the flashing would start I thought... but after having the red and orange line in place the flashing starts on the #19th press of the A button... and that flashing continues until B is pressed (the B button resets aFrame back down to 0).

edit: and by 'flashing' I mean the top of nametable 1 starts flashing on and off the lower part of the screen. And ok... I am going to rewrite scrollland. Maybe start tomorrow. good night yall.
Many thanks to Kasumi!!!! :D
Last edited by unregistered on Thu Jul 26, 2012 8:03 pm, edited 1 time in total.
Post Reply