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: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

I'll have to try that later tonight to see why PHA instructions aren't being caught by FCEUX's debugger. I wonder, however, whether a bug report will be answered, seeing as the latest FCEUX is a year old.
Shiru
Posts: 1161
Joined: Sat Jan 23, 2010 11:41 pm

Post by Shiru »

Since there aren't too many NES emulators with debuggers in general, it could be considered a decent one, along with Nintendulator and Mednafen. I personally mostly use FCEUX.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Wow, ok thanks tepples. :D
Shiru wrote:I personally mostly use FCEUX.
Me too. Though, I'm just beginning to understand a small bit of the nes... and while you have released some nes games and have made an awesome Famitone sound engine! :D Thank you Shiru!
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

tepples wrote:I'll have to try that later tonight to see why PHA instructions aren't being caught by FCEUX's debugger. I wonder, however, whether a bug report will be answered, seeing as the latest FCEUX is a year old.
Well, I just figured it out! :) Yes, there were two 0s on the stack because my code pushed them there... and then a branch could occure to the wrong place... then there was .... well, like this:

Code: Select all

0C291                           	;checks and saves upper left tile
0C291 0A                            asl a                          ;<pushes bit #6 into carry.
0C292 48                        	pha ;----------------------->
0C293 48                        	pha ;---------------------->
0C294 29 00                     	and #$00 ; clear accumulator
0C296 2A                        	rol a
0C297 85 2A                     	sta solidMETATILE ;if  this is true  all the rc_s should be 1s 
0C299 D0 03                     	bne +
0C29B 4C B1 C2                  	jmp +normal
0C29E 68                            + pla ;<----------------------
0C29F 68                        	  pla ;<-----------------------
0C2A0 A9 01                     	  lda #$01 
0C2A2 85 2B                     	  sta rc_upleft
0C2A4 85 2C                     	  sta rc_upright
0C2A6 85 2D                     	  sta rc_loleft
0C2A8 85 2E                     	  sta rc_loright
0C2AA 0A                        	  asl a
0C2AB 0A                        	  asl a
0C2AC 0A                        	  asl a
0C2AD 0A                        	  asl a
0C2AE 4C D1 C2                  	  jmp +rc_s ; nooooooooooooooooooooooooooooooooo!!!!!!!!!!!!!!!!!!!!!jmp attributetable
0C2B1                           +normal:		
0C2B1 68                        	pla ;<----------------------
0C2B2 0A                        	asl a                          ;moves bit #5 into carry
0C2B3 29 00                     	and #%00
0C2B5 2A                        	rol a
0C2B6 85 2B                     	sta rc_upleft;
0C2B8 68                        	pla ;<-----------------------
Lines 0C29E and 0C29F weren't there and so the two 0s were pushed and missed their pull if the code chose that path. It also used to jmp attributetable which was also not correct... that was into a totally different file... I remember writing that and then I changed the order of the code to correct a problem without changing that label back to what it had been. So now that 8 pixel black line never appears anymore! :D And my sprite appears again!! :D And the controller started to function again!!! :mrgreen: It's not fixed all the way yet... more learning and searching ahead. :)

That would be amazing if there was a bug fix... thanks for submitting it tepples. :)
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Post by Kasumi »

Please give a temp variable a try.

Code: Select all

0C292 48                           pha ;----------------------->
0C293 48                           pha ;---------------------->
You're pushing the same value twice. You'd only need it to store it to temp RAM once, and the value would be the same after you loaded it once, unlike if you pull from the stack.

Code: Select all

0C299 D0 03                        bne +
0C29B 4C B1 C2                     jmp +normal
0C29E 68                            + pla ;<----------------------
0C29F 68                             pla ;<----------------------- 
0C2A0 A9 01                          lda #$01 
You'll pulling twice here to fix the stack but not even using the values. If you used a variable you have no obligation to read the value back.

Another tiny thing:

Code: Select all

0C2A0 A9 01                          lda #$01;A is a known state. #%00000001
0C2A2 85 2B                          sta rc_upleft
0C2A4 85 2C                          sta rc_upright
0C2A6 85 2D                          sta rc_loleft
0C2A8 85 2E                          sta rc_loright
0C2AA 0A                             asl a;A is now guaranteed to be #%00000010
0C2AB 0A                             asl a;A is now guaranteed to be #%00000100
0C2AC 0A                             asl a;A is now guaranteed to be #%00001000
0C2AD 0A                             asl a;A is now guaranteed to be #%00010000
0C2AE 4C D1 C2                       jmp +rc_s 
I may be off base here but can't those asl instructions be replaced with just this?

Code: Select all

lda #%00010000
Since that seems to be what A is guaranteed to be anyway.

But actually I suppose I shouldn't talk too much about this sort of thing. It's only worth thinking about that stuff too much when it does exactly what you want it to do.

Edit: Hmm, but I can't stop myself.

Code: Select all

0C299 D0 03                        bne +
0C29B 4C B1 C2                     jmp +normal
0C29E 68                            + pla ;<----------------------
0C29F 68                             pla ;<----------------------- 
+normal should be close enough to branch to.

Code: Select all

0C299 D0 03                        beq +normal
And here's something to consider:

Code: Select all

0C291                              ;checks and saves upper left tile
0C291 0A                            asl a                          ;<pushes bit #6 into carry.
                                bcs entry;Don't use a generic label name like I just did ;)
0C292 48                           pha ;----------------------->
0C293 48                           pha ;---------------------->
0C294 29 00                        and #$00 ; clear accumulator
0C296 2A                         ;  rol a;No need for this, we already branched on this condition above
0C297 85 2A                        sta solidMETATILE ;if  this is true  all the rc_s should be 1s
0C299 D0 03                        beq +normal;This could actually be a jmp now
0C29E 68                            entry:
0C2A0 A9 01                          lda #$01
0C2A2 85 2B                          sta rc_upleft
0C2A4 85 2C                          sta rc_upright
0C2A6 85 2D                          sta rc_loleft
0C2A8 85 2E                          sta rc_loright
                                          sta solidMETATILE;Since we skipped doing this above
0C2AA 0A                             asl a
0C2AB 0A                             asl a
0C2AC 0A                             asl a
0C2AD 0A                             asl a;lda #%00010000?
0C2AE 4C D1 C2                       jmp +rc_s ; nooooooooooooooooooooooooooooooooo!!!!!!!!!!!!!!!!!!!!!jmp attributetable
0C2B1                           +normal:       
That should skip using the stack entirely in the case you don't need it, if I'm understanding everything correctly. (I may not be, so if it looks wrong it probably is)

You have more than one condition dependent on that shifted bit six, and you check it multiple times. I check it once at the beginning, and skip the pha instructions and pla instruction, the sta solidMETATILE (I set it later), and the additional branch in the case where "bit 6" set. It's also the same speed when it's clear, because we skip out on the rol a. (Again I may not be doing something your code needs, but this seems right)

Sorry for going crazy, (which may not even help if the code is broken, I just tried to make it get the exact same end result) messing with assembly like this is actually pretty enjoyable for me.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

I didn't submit anything.

Today I made a test ROM that executes several PHA and PLA instructions, one PHP and PLP, one each of BRK, /NMI, and /IRQ, each with its corresponding RTI, and a JSR and RTS pair. I ran it in FCEUX 2.1.5 with a breakpoint on reads and writes to $0100-$01FF (the stack), and it stopped on PHA, PLA, RTI, JSR, RTS, PHP, PLP. It didn't appear to stop on BRK or on the JMP instruction that gets interrupted, but most breakpoints on the stack appear to work.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

tepples wrote:I didn't submit anything.

Today I made a test ROM that executes several PHA and PLA instructions, one PHP and PLP, one each of BRK, /NMI, and /IRQ, each with its corresponding RTI, and a JSR and RTS pair. I ran it in FCEUX 2.1.5 with a breakpoint on reads and writes to $0100-$01FF (the stack), and it stopped on PHA, PLA, RTI, JSR, RTS, PHP, PLP. It didn't appear to stop on BRK or on the JMP instruction that gets interrupted, but most breakpoints on the stack appear to work.
tepples, thank you for telling me this! :D I assumed that the one I had found, FCEUX 2.0.3, was the latest one... :oops: FCEUX 2.1.5 looks amazing! That does work!!! :D But maybe it would have worked in FCEUX 2.0.3... maybe it didn't work because of my subpar coding skills... I don't know; I do know that I set the breakpoint up correctly in 2.0.3. :)


---
Kasumi, that is also fun for me too! I will reply more later... sorry... it's lunch time... :)
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Kasumi wrote:Please give a temp variable a try.

Code: Select all

0C292 48                           pha ;----------------------->
0C293 48                           pha ;---------------------->
You're pushing the same value twice. You'd only need it to store it to temp RAM once, and the value would be the same after you loaded it once, unlike if you pull from the stack.

Code: Select all

0C299 D0 03                        bne +
0C29B 4C B1 C2                     jmp +normal
0C29E 68                            + pla ;<----------------------
0C29F 68                             pla ;<----------------------- 
0C2A0 A9 01                          lda #$01 
You'll pulling twice here to fix the stack but not even using the values. If you used a variable you have no obligation to read the value back.

Another tiny thing:

Code: Select all

0C2A0 A9 01                          lda #$01;A is a known state. #%00000001
0C2A2 85 2B                          sta rc_upleft
0C2A4 85 2C                          sta rc_upright
0C2A6 85 2D                          sta rc_loleft
0C2A8 85 2E                          sta rc_loright
0C2AA 0A                             asl a;A is now guaranteed to be #%00000010
0C2AB 0A                             asl a;A is now guaranteed to be #%00000100
0C2AC 0A                             asl a;A is now guaranteed to be #%00001000
0C2AD 0A                             asl a;A is now guaranteed to be #%00010000
0C2AE 4C D1 C2                       jmp +rc_s 
I may be off base here but can't those asl instructions be replaced with just this?

Code: Select all

lda #%00010000
Since that seems to be what A is guaranteed to be anyway.

But actually I suppose I shouldn't talk too much about this sort of thing. It's only worth thinking about that stuff too much when it does exactly what you want it to do.

Edit: Hmm, but I can't stop myself.

Code: Select all

0C299 D0 03                        bne +
0C29B 4C B1 C2                     jmp +normal
0C29E 68                            + pla ;<----------------------
0C29F 68                             pla ;<----------------------- 
+normal should be close enough to branch to.

Code: Select all

0C299 D0 03                        beq +normal
And here's something to consider:

Code: Select all

0C291                              ;checks and saves upper left tile
0C291 0A                            asl a                          ;<pushes bit #6 into carry.
                                bcs entry;Don't use a generic label name like I just did ;)
0C292 48                           pha ;----------------------->
0C293 48                           pha ;---------------------->
0C294 29 00                        and #$00 ; clear accumulator
0C296 2A                         ;  rol a;No need for this, we already branched on this condition above
0C297 85 2A                        sta solidMETATILE ;if  this is true  all the rc_s should be 1s
0C299 D0 03                        beq +normal;This could actually be a jmp now
0C29E 68                            entry:
0C2A0 A9 01                          lda #$01
0C2A2 85 2B                          sta rc_upleft
0C2A4 85 2C                          sta rc_upright
0C2A6 85 2D                          sta rc_loleft
0C2A8 85 2E                          sta rc_loright
                                          sta solidMETATILE;Since we skipped doing this above
0C2AA 0A                             asl a
0C2AB 0A                             asl a
0C2AC 0A                             asl a
0C2AD 0A                             asl a;lda #%00010000?
0C2AE 4C D1 C2                       jmp +rc_s ; nooooooooooooooooooooooooooooooooo!!!!!!!!!!!!!!!!!!!!!jmp attributetable
0C2B1                           +normal:       
That should skip using the stack entirely in the case you don't need it, if I'm understanding everything correctly. (I may not be, so if it looks wrong it probably is)

You have more than one condition dependent on that shifted bit six, and you check it multiple times. I check it once at the beginning, and skip the pha instructions and pla instruction, the sta solidMETATILE (I set it later), and the additional branch in the case where "bit 6" set. It's also the same speed when it's clear, because we skip out on the rol a. (Again I may not be doing something your code needs, but this seems right)

Sorry for going crazy, (which may not even help if the code is broken, I just tried to make it get the exact same end result) messing with assembly like this is actually pretty enjoyable for me.
This would be enjoyable for me too if I could accomplish making my code quicker. You are extreemly good at it Kasumi! Thanks! :D Yes, I also agree that my code doesn't accomplish what its susposed to do; and I'll wait on attempting your suggestions until it seems to be surviving just fine.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Now the screen doesn't scroll to the right anymore. It struggles to but is always reset to 0.. so it appears to go eight pixels and then is reset to zero and then scrolls at most 8 pixels... and repeat until the count reaches 255 and it stops as normal, I guess, for that reason... . Can you think of what I should do... just asking for suggestions. So far I haven't worried about checking my scrolling code file because I never have changed it after it started working well.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

unregistered wrote:it appears to go eight pixels and then is reset to zero
Sounds to me like you are writing $00 to $2006, which resets the scroll. The only part of the scroll that isn't reset by this is the fine X scroll, which could be why you are able to scroll ~8 pixels. Make sure that the writes to $2005 are the last PPU operation of your VBlank handler.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

tokumaru wrote:
unregistered wrote:it appears to go eight pixels and then is reset to zero
Sounds to me like you are writing $00 to $2006, which resets the scroll. The only part of the scroll that isn't reset by this is the fine X scroll, which could be why you are able to scroll ~8 pixels. Make sure that the writes to $2005 are the last PPU operation of your VBlank handler.
Here's the end of the last routine scroll_screen run in my vblank:

Code: Select all

0C38F 85 1A                        sta currNameTable ;this is what you'll write to $2000 when setting the scroll       
0C391                           
0C391                             ; run other game graphics updating code here
0C391 8D 00 20                          sta $2000
0C394                             
0C394 A5 1D                       lda CameraX+0   ; MOVE THE CAMERA OBJECT!  
0C396 8D 05 20                    STA $2005        ; write the horizontal scroll count register
0C399                             
0C399 A9 00                       LDA #$00         ; no vertical scrolling
0C39B 8D 05 20                    STA $2005
0C39E                           
0C39E                           ;		ldx scroll                ; Do we need to scroll at all?
0C39E                           ;        beq no_scroll
0C39E                           ;        dex
0C39E                           ;        stx scroll
0C39E                           ;        lda #$00
0C39E                           ;        stx $2005                ;Write the value of 'scroll' for Horiz. Scroll value
0C39E                           ;        sta $2005               ;Write 0 for Vert. Scroll value
0C39E                           ;                
0C39E                           ;no_scroll:
0C39E 60                                rts
So yes the last 2 writes to PPU is at the end. :) After line 0C39E is the rti ending my vblank. But no, there is other stuff inbetween! Here is the start of my vblank routine:

Code: Select all

0C342 E6 1C                     vblank: inc FRAME_CNT
0C344                                   .incsrc "daprg-vblank.asm"
0C344                              ;skip the video updates if the frame calculations aren't over yet 
0C344 24 1F                        bit FrameReady 
0C346 10 0D                        bpl SkipUpdates 
0C348                           
0C348                              ;PERFORM VIDEO UPDATES HERE 
0C348 20 59 C3                    jsr update_sprite
0C34B 20 5F C3                    jsr scroll_screen
0C34E                           
0C34E                           
0C34E A6 0F                     	    		ldx aFrame
0C350 20 9F C3                  		jsr draw_sprite
0C353                           
0C353                           
0C353                              ;modify the flag 
0C353 E6 1F                        inc FrameReady 
0C355                           
0C355                           SkipUpdates: 
0C355                           
0C355                              ;PERFORM TASKS THAT MUST BE PERFORMED EVEN 
0C355                              ;WHEN THE FRAME IS NOT READY, SUCH AS UPDATING 
0C355                              ;THE MUSIC OR DRAWING A STATUS BAR 
0C355 20 3E DA                      jsr FamiToneUpdate
0C358                           
0C358                           
0C358                              ;return from the NMI (vblank) 
0C358 40                           rti
Is my draw_sprite routine causing the problem? Or maybe FamiToneUpdate?
3gengames
Formerly 65024U
Posts: 2284
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames »

Include a little source and not a disassembly with half the stuff removed? Scared somebody will take your source? Get over it, nobody really cares what the source does, just finds it because stealing it is 200x harder than just making something themselves.

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...
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

It seems you are updating the scroll and then updating other things, while it should be the other way around. Setting the scroll should ALWAYS be the very last thing in your VBlank handler. Any PPU operation involving $2006/$2007 messes with the VRAM address, which fucks up the scroll.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

Sorry 3gengames. :( I had my entire vblank routine ready to go... but the end was what I was really thinking about and so I deleted most of the first part. I remember having someone once complain that I posted too much code. :?
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered »

tokumaru wrote:It seems you are updating the scroll and then updating other things, while it should be the other way around. Setting the scroll should ALWAYS be the very last thing in your VBlank handler. Any PPU operation involving $2006/$2007 messes with the VRAM address, which messes with the scroll.
It's quite alright to repeat the phrase "messes with" instead of cussing, I think. : )
...Thank you for saying so; I'll change that... put it at the very end.... after the rts comes the rti! :D

edit: woah not very good...it's kind of good... The screen scrolls at the right time but it goes back and forth between nametable1 and nametable2 really quickly.

Code: Select all

0C340 E6 1C                     vblank: inc FRAME_CNT
0C342                                   .incsrc "daprg-vblank.asm"
0C342                              ;skip the video updates if the frame calculations aren't over yet 
0C342 24 1F                        bit FrameReady 
0C344 10 0A                        bpl SkipUpdates 
0C346                           
0C346                              ;PERFORM VIDEO UPDATES HERE 
0C346 20 57 C3                    jsr update_sprite
0C349                             
0C349                           
0C349 A6 0F                     	    		ldx aFrame
0C34B 20 9D C3                  		jsr draw_sprite
0C34E                           
0C34E                           
0C34E                              ;modify the flag 
0C34E E6 1F                        inc FrameReady 
0C350                           
0C350                           SkipUpdates: 
0C350                           
0C350                              ;PERFORM TASKS THAT MUST BE PERFORMED EVEN 
0C350                              ;WHEN THE FRAME IS NOT READY, SUCH AS UPDATING 
0C350                              ;THE MUSIC OR DRAWING A STATUS BAR 
0C350 20 3C DA                      jsr FamiToneUpdate
0C353                           
0C353 20 5D C3                    jsr scroll_screen ;"Setting the scroll should ALWAYS be the very last thing in your VBlank handler." -tokumaru pg 43
0C356                              ;return from the NMI (vblank) 
0C356 40                           rti
0C357                           
0C357                           
0C357                           
0C357                           
0C357                           
0C357                           
0C357                           update_sprite:
0C357 A9 02                     		lda #>sprite
0C359 8D 14 40                          sta $4014 ;OAM_DMA register ; Jam page $200-$2FF into SPR-RAM
0C35C                                                 ;takes 513 cycles.
0C35C                           					  
0C35C 60                                rts
0C35D                           
0C35D                           scroll_screen:
0C35D                             .include "daprg-scrollland.asm"
0C35D                           ;PPUCTRL Controller ($2000) > write
0C35D                           ;PPUMASK Mask ($2001) > write
0C35D                           ;PPUSTATUS Status ($2002) < read
0C35D                           ;OAMADDR address ($2003) > write
0C35D                           ;OAMDATA OAM data ($2004) <> read/write
0C35D                           ;PPUSCROLL Scroll ($2005) >> write x2
0C35D                           ;PPUADDR Address ($2006) >> write x2
0C35D                           ;PPUDATA Data ($2007) <> read/write
0C35D                           
0C35D A2 00                             ldx #$00                ; Reset VRAM
0C35F 8E 06 20                          stx $2006
0C362 8E 06 20                          stx $2006
0C365                           
0C365                                  
0C365                           		
0C365                           		;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
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
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
0C37F                           		
0C37F                           		
0C37F                           +skipscroll		
0C37F A9 88                        lda #%10001000
0C381 85 1A                        sta currNameTable 
0C383 29 FE                        and #$fe ;clear the lowest bit 
0C385 85 1A                        sta currNameTable 
0C387                           
0C387 A5 1E                        lda CameraX+1 ;get the high byte of the camera 
0C389 29 01                        and #$01 ;keep only the lowest bit 
0C38B 05 1A                        ora currNameTable ;combine with the other value 
0C38D 85 1A                        sta currNameTable ;this is what you'll write to $2000 when setting the scroll       
0C38F                           
0C38F                             ; run other game graphics updating code here
0C38F 8D 00 20                          sta $2000
0C392                             
0C392 A5 1D                       lda CameraX+0   ; MOVE THE CAMERA OBJECT!  
0C394 8D 05 20                    STA $2005        ; write the horizontal scroll count register
0C397                             
0C397 A9 00                       LDA #$00         ; no vertical scrolling
0C399 8D 05 20                    STA $2005
0C39C                           
0C39C                           ;		ldx scroll                ; Do we need to scroll at all?
0C39C                           ;        beq no_scroll
0C39C                           ;        dex
0C39C                           ;        stx scroll
0C39C                           ;        lda #$00
0C39C                           ;        stx $2005                ;Write the value of 'scroll' for Horiz. Scroll value
0C39C                           ;        sta $2005               ;Write 0 for Vert. Scroll value
0C39C                           ;                
0C39C                           ;no_scroll:
0C39C 60                                rts
There 3gengames... it's all there. :)
Post Reply