Page 2 of 2
Posted: Mon Jul 10, 2006 4:36 pm
by nineTENdo
Ok my stupid brain finally understands how NMI works. WRITE SCREEN, VBLANK (NMI EXECUTION ON 7.2000 set), REPEAT. My Question is how do how do i impliment a code to keep vblanking. ive set my 7.2000 written simple ADC #$10 to move a sprite on #$4014. And still nothing. im thinking becasue the damn thing isnt vblanking. ive seen some code were vblank just loops in main loop. What should i do. So far ive got my backround to flicker and change color. well heres my code.
Code: Select all
nmi
pha
txa
pha
tya
pha
lda X_POS
adc #$10
sta X_POS
Lda #$7
sta $4014
Lda #$00
STA $2005
STA $2005
pla
tay
pla
tax
pla
rti
Thanks in advance,
EL
Posted: Wed Jul 12, 2006 4:07 pm
by Disch
Not sure I fully understand your question, but maybe I can help fill in the blanks.
how do i impliment a code to keep vblanking
VBlank isn't a thing you can control. VBlank happens roughly 60 times per second at steady intervals regardless of what your code is doing (one VBlank every ~29830 CPU cycles, which is very roughly every ~7458 instructions, assuming an average of 4 cycles per instruction). VBlank will always happen whether you're ready for it or not... or whether you want it to or not.
An NMI (if enabled) is tripped at the very start of VBlank to notify your program that VBlank is happening. NMIs will
always trip on
every VBlank as long as both of the following are true:
- they're enabled ($2000.7 is set)
- you're not reading $2002 around the time VBlank starts
I doubt very much you're doing the latter. So if NMIs are not occuring for you, it must be because you have them disabled. Make sure that when you write to $2000, the high bit (bit 7: $80) is set.
Another potential reason for your problem is that your 'X_POS' variable is defined wrong. Where in memory is 'X_POS'? Like... what do you define it as? (you probably have a line somewhere that's "X_POS = something")
Posted: Wed Jul 12, 2006 6:33 pm
by nineTENdo
NMIs will always trip on every VBlank as long as both of the following are true:
- they're enabled ($2000.7 is set)
- you're not reading $2002 around the time VBlank starts
Well i have 7.2000 set at the PPU initialization instead of it being cleared. And my is at X_POS = 0703 and is refreshed with a LDA #$7 and $4014 store. And i think i might not be reading $2002 around the time VBlank starts. I dont how i would do that. It looks like i might be doing it but then again i not sure. im kinda confused on the whole reading from $2002. Does the 7. $2000 have to set or cleared when reading. Heres what i have can you tell how to point to it or can i just include it in the NMI.
Code: Select all
infinite:
waitblank lda $2002 < this keeps my sprite moving
BPL waitblank and nice looking when i press A.
lda #$01
sta $4016
lda #$00
sta $4016
lda $4016
and #1
bne KEYDN
lda $4016
lda $4016
lda $4016
lda $4016
lda $4016
lda $4016
lda $4016
JMP infinite
KEYDN
clc
LDA Y_POS
ADC #$75
sta Y_POS
CLC
lda X_POS
ADC #$40
sta X_POS
lda #$7
sta $4014
BNE infinite
jmp infinite
nmi
pha
txa
pha
tya
pha
lda X_POS
adc #$10
sta X_POS
Lda #$7
sta $4014
Lda #$00
STA $2005
STA $2005
pla
tay
pla
tax
pla
rti
Posted: Wed Jul 12, 2006 6:57 pm
by Quietust
You shouldn't be waiting on $2002 outside of your initialization code - it's not reliable, and on an NES it will result in missed frames.
To do it properly, you should use this instead:
Code: Select all
waitblank lda gotnmi
BEQ waitblank
lda #0
sta gotnmi
and, right after the
in your NMI routine, insert
Oh, and declare "gotnmi" along with the rest of your variables.
This is what we talked about earlier about not polling $2002 to wait for VBLANK, but instead using a variable that you set whenever you get an NMI.
Posted: Wed Jul 12, 2006 7:19 pm
by nineTENdo
Quietust wrote:
To do it properly, you should use this instead:
Code: Select all
waitblank lda gotnmi
BEQ waitblank
lda #0
sta gotnmi
and, right after the
in your NMI routine, insert
What i dont understand is how $2002 gets worked into the code. I would think that it has to equal something or get stored.
But other than that i understand whats going.
Posted: Wed Jul 12, 2006 7:28 pm
by Quietust
nineTENdo wrote:What i dont understand is how $2002 gets worked into the code.
That's just it - you
shouldn't be using $2002 (except for in your RESET code in order to wait 2 frames, since that's required).
nineTENdo wrote:I would think that it has to equal something or get stored.
It isn't a byte of memory - it's a memory-mapped
I/O register. Its value changes on its own, and reading it performs other actions.
Posted: Wed Jul 12, 2006 7:33 pm
by nineTENdo
What would be the proper $2002 read a reset. Would this code be inclided at reset.
Code: Select all
waitblank lda gotnmi
BEQ waitblank
lda #0
sta gotnmi
Posted: Wed Jul 12, 2006 7:43 pm
by Quietust
nineTENdo wrote:What would be the proper $2002 read a reset. Would this code be inclided at reset.
Code: Select all
waitblank lda gotnmi
BEQ waitblank
lda #0
sta gotnmi
No - that doesn't use $2002.
Really, you should be able to figure this out by now.
Posted: Wed Jul 12, 2006 7:47 pm
by Disch
You misunderstood what I said before about $2002
NMIs will work reliably if you're NOT reading $2002. This means you SHOULDN'T be reading $2002 (since you want to be using NMIs)
But as Q is saying, you'll still want to use $2002 for waiting for the first two frames (when you wait for the PPU to warm up)
For that... you'll want to do something like this once at startup (at the start of your reset routine):
Code: Select all
: lda $2002
bpl :-
: lda $2002
bpl :-
Or if you're not using as nice of an assembler:
Code: Select all
wait1:
lda $2002
bpl wait1
wait2:
lda $2002
bpl wait2
But in your game logic, when you're waiting for VBlank, you should
not be reading $2002. To wait for the next VBlank, make sure NMIs are enabled, and then just wait for your NMI to trip.
Posted: Wed Jul 12, 2006 8:05 pm
by nineTENdo
Quietust wrote:
Really, you should be able to figure this out by now.
its not clicking. But heres what i have.
Code: Select all
Start:
sei
cld
jsr WVB
jsr LDPAL
JSR LDNT
NOTHING
JMP NOTHING
WVB
wait1:
lda $2002
bpl wait1
wait2:
lda $2002
bpl wait2
RTS
LDPAL
ldx #$00
lda #$3F
sta $2006
lda #$00
sta $2006
loadpal:
lda tilepal, x
sta $2007
inx
cpx #32
bne loadpal
rts
LDNT
lda #$20
sta $2006
sta $2006
ldx #$00
loadNames1:
lda ourMap, X
sta $2007
inx
bne loadNames1
loadNames2:
lda ourMap+$100, X
sta $2007
inx
bne loadNames2
loadNames3:
lda ourMap+$200, X
sta $2007
inx
bne loadNames3
loadNames4:
lda ourMap+$300, X
sta $2007
inx
cpx #$80
bne loadNames4
lda #%1001000
sta $2000
lda #%00011110
sta $2001
lda #$02
sta $0701
rts
waitblank
lda gotnmi
BEQ waitblank
lda #0
sta gotnmi
KEYDN
clc
LDA X_POS
ADC #$10
sta X_POS
lda #$7
sta $4014
rts
nmi
pha
txa
pha
tya
pha
lda #$01
sta gotnmi
lda #$00
Sta $2005
Sta $2005
jsr waitblank
pla
tay
pla
tax
pla
rti
Posted: Wed Jul 12, 2006 8:08 pm
by Quietust
Code: Select all
lda #%1001000
sta $2000
lda #%00011110
sta $2001
You're missing one bit somewhere in your write to $2000...
Posted: Wed Jul 12, 2006 8:13 pm
by nineTENdo
EUURRREEKKAAAAAA!!!!!!
Thanks Yall:)