Posted: Mon Jun 25, 2012 8:58 am
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.
NES Development Forums
https://forums.nesdev.org/
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! Thank you Shiru!Shiru wrote:I personally mostly use FCEUX.
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: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.
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 ;<-----------------------
Code: Select all
0C292 48 pha ;----------------------->
0C293 48 pha ;---------------------->
Code: Select all
0C299 D0 03 bne +
0C29B 4C B1 C2 jmp +normal
0C29E 68 + pla ;<----------------------
0C29F 68 pla ;<-----------------------
0C2A0 A9 01 lda #$01
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
Code: Select all
lda #%00010000
Code: Select all
0C299 D0 03 bne +
0C29B 4C B1 C2 jmp +normal
0C29E 68 + pla ;<----------------------
0C29F 68 pla ;<-----------------------
Code: Select all
0C299 D0 03 beq +normal
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:
tepples, thank you for telling me this! I assumed that the one I had found, FCEUX 2.0.3, was the latest one... FCEUX 2.1.5 looks amazing! That does work!!! 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.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.
This would be enjoyable for me too if I could accomplish making my code quicker. You are extreemly good at it Kasumi! Thanks! 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.Kasumi wrote:Please give a temp variable a try.
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
0C292 48 pha ;-----------------------> 0C293 48 pha ;---------------------->
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.Code: Select all
0C299 D0 03 bne + 0C29B 4C B1 C2 jmp +normal 0C29E 68 + pla ;<---------------------- 0C29F 68 pla ;<----------------------- 0C2A0 A9 01 lda #$01
Another tiny thing:I may be off base here but can't those asl instructions be replaced with just this?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
Since that seems to be what A is guaranteed to be anyway.Code: Select all
lda #%00010000
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.
+normal should be close enough to branch to.Code: Select all
0C299 D0 03 bne + 0C29B 4C B1 C2 jmp +normal 0C29E 68 + pla ;<---------------------- 0C29F 68 pla ;<-----------------------
And here's something to consider:Code: Select all
0C299 D0 03 beq +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)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:
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.
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 wrote:it appears to go eight pixels and then is reset to zero
Here's the end of the last routine scroll_screen run in my vblank:tokumaru wrote: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 wrote:it appears to go eight pixels and then is reset to zero
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
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
It's quite alright to repeat the phrase "messes with" instead of cussing, I think. : )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.
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