Here is the source code to a program I wrote for the NES. Note that it is written to be assembled using NESASM:
You can download the program here:
http://www.freewebs.com/beneficii/scroll.nes
This program works fine with Quietust's emulator, Nintendulator, LoopyNES, JNES, NNNesterJ, etc., but it does not work in FCEU or any of its derivatives, such as FCEUXD, that I have tried. This program uses the mapper MMC3 and does split-screen (vertical only) scrolling. When it finishes the beginning of the program, it writes to E000, which disables the IRQ counter, and then clears the interrupt-disable flag. When the NMI comes on, it does the scrolling, and then writes to C000, C001, and E001 the IRQ counter (thereby enabling it and starting the countdown). When the IRQ hits, it writes to E000 again to disable the IRQ counter, and then it does the graphics for the bottom part of the screen which do not scroll.
Now, when I ran a trace of this in Nintendulator, I saw the code work fine, and it went through the number of scanlines necessary before calling the IRQ. But when I ran a trace in FCEUXD, I find that as soon as the interrupt-disable flag is cleared, after every instruction an IRQ is called, despite my writes to E000. When the IRQ is finished, it goes for an instruction and calls the IRQ again. This of course, causes the display to be completely messed up. My question is, Why does FCEU and its derivatives seem to ignore my writes to E000 and call the IRQs anyway, when no other emulator seems to? I would greatly appreciate an answer to this question.
Thanks.
Code:
.inesprg 2
.ineschr 1
.inesmap 4
.inesmir 0
.code
.bank 3
.org $E000
palettedata: .incbin "scroll\pal.bin"
vblank:
lda $2002
bpl vblank
rts
main:
sei
cld
sta $e000
ldx #$01
stx $a000
ldx #$80
stx $a001
ldx #$ff
txs
jsr vblank
inx
stx $2000
stx $2001
lda #$00
clearzp:
sta <$00, x
inx
bne clearzp
ldy #$01
sty <$01
dey
ldx #$07
clearwram:
sta [$00], y
iny
bne clearwram
inc <$01
dex
bne clearwram
lda $2002
lda #$3f
sta $2006
stx $2006
ldy #$20
loadpal:
lda palettedata, x
sta $2007
inx
dey
bne loadpal
jsr vblank
lda #$28
sta $2006
sty $2006
ldx #$04
lda #$01
clearvram:
sta $2007
iny
bne clearvram
dex
bne clearvram
jsr vblank
lda #$20
sta $2006
sty $2006
ldx #$04
lda #$00
clearvram.b:
sta $2007
iny
bne clearvram.b
dex
bne clearvram.b
jsr vblank
lda #$2b
sta $2006
lda #$00
sta $2006
lda #$10
ldx #$c0
clearvram.c:
sta $2007
iny
dex
bne clearvram.c
lda #$00
sta $8000
sta $8001
lda #$01
sta $8000
lda #$02
sta $8001
sta $8000
lda #$04
sta $8001
lda #$03
sta $8000
lda #$05
sta $8001
lda #$04
sta $8000
lda #$06
sta $8001
lda #$05
sta $8000
lda #$07
sta $8001
lda #$06
sta $8000
lda #$00
sta $8001
lda #$07
sta $8000
lda #$00
sta $8001
lda #$2
sta $4014
lda #%10001000
sta $2000
lda #%00001010
sta $2001
sta $e000
cli
eternity:
jmp eternity
nmi:
pha
lda $2002
lda #$00
sta $2006
sta $2006
inc <$30
lda <$30
cmp #$c0
bcs reset
finishnmi:
lda $2002
lda #$00
sta $2005
lda <$30
sta $2005
lda #$bf
sta $c000
sta $c001
sta $e001
pla
rti
reset:
lda #$00
sta <$30
jmp finishnmi
irq:
sta $e000
pha
tya
pha
ldy #$0f
timer:
dey
bne timer
lda $2002
lda #$00
sta $2005
bit $2002
lda #$0b
sta $2006
lda #$00
sta $2006
pla
tay
pla
rti
.org $FFFA
.dw nmi
.dw main
.dw irq
.bank 4
.incbin "scroll\chr.bin"
.ineschr 1
.inesmap 4
.inesmir 0
.code
.bank 3
.org $E000
palettedata: .incbin "scroll\pal.bin"
vblank:
lda $2002
bpl vblank
rts
main:
sei
cld
sta $e000
ldx #$01
stx $a000
ldx #$80
stx $a001
ldx #$ff
txs
jsr vblank
inx
stx $2000
stx $2001
lda #$00
clearzp:
sta <$00, x
inx
bne clearzp
ldy #$01
sty <$01
dey
ldx #$07
clearwram:
sta [$00], y
iny
bne clearwram
inc <$01
dex
bne clearwram
lda $2002
lda #$3f
sta $2006
stx $2006
ldy #$20
loadpal:
lda palettedata, x
sta $2007
inx
dey
bne loadpal
jsr vblank
lda #$28
sta $2006
sty $2006
ldx #$04
lda #$01
clearvram:
sta $2007
iny
bne clearvram
dex
bne clearvram
jsr vblank
lda #$20
sta $2006
sty $2006
ldx #$04
lda #$00
clearvram.b:
sta $2007
iny
bne clearvram.b
dex
bne clearvram.b
jsr vblank
lda #$2b
sta $2006
lda #$00
sta $2006
lda #$10
ldx #$c0
clearvram.c:
sta $2007
iny
dex
bne clearvram.c
lda #$00
sta $8000
sta $8001
lda #$01
sta $8000
lda #$02
sta $8001
sta $8000
lda #$04
sta $8001
lda #$03
sta $8000
lda #$05
sta $8001
lda #$04
sta $8000
lda #$06
sta $8001
lda #$05
sta $8000
lda #$07
sta $8001
lda #$06
sta $8000
lda #$00
sta $8001
lda #$07
sta $8000
lda #$00
sta $8001
lda #$2
sta $4014
lda #%10001000
sta $2000
lda #%00001010
sta $2001
sta $e000
cli
eternity:
jmp eternity
nmi:
pha
lda $2002
lda #$00
sta $2006
sta $2006
inc <$30
lda <$30
cmp #$c0
bcs reset
finishnmi:
lda $2002
lda #$00
sta $2005
lda <$30
sta $2005
lda #$bf
sta $c000
sta $c001
sta $e001
pla
rti
reset:
lda #$00
sta <$30
jmp finishnmi
irq:
sta $e000
pha
tya
pha
ldy #$0f
timer:
dey
bne timer
lda $2002
lda #$00
sta $2005
bit $2002
lda #$0b
sta $2006
lda #$00
sta $2006
pla
tay
pla
rti
.org $FFFA
.dw nmi
.dw main
.dw irq
.bank 4
.incbin "scroll\chr.bin"
You can download the program here:
http://www.freewebs.com/beneficii/scroll.nes
This program works fine with Quietust's emulator, Nintendulator, LoopyNES, JNES, NNNesterJ, etc., but it does not work in FCEU or any of its derivatives, such as FCEUXD, that I have tried. This program uses the mapper MMC3 and does split-screen (vertical only) scrolling. When it finishes the beginning of the program, it writes to E000, which disables the IRQ counter, and then clears the interrupt-disable flag. When the NMI comes on, it does the scrolling, and then writes to C000, C001, and E001 the IRQ counter (thereby enabling it and starting the countdown). When the IRQ hits, it writes to E000 again to disable the IRQ counter, and then it does the graphics for the bottom part of the screen which do not scroll.
Now, when I ran a trace of this in Nintendulator, I saw the code work fine, and it went through the number of scanlines necessary before calling the IRQ. But when I ran a trace in FCEUXD, I find that as soon as the interrupt-disable flag is cleared, after every instruction an IRQ is called, despite my writes to E000. When the IRQ is finished, it goes for an instruction and calls the IRQ again. This of course, causes the display to be completely messed up. My question is, Why does FCEU and its derivatives seem to ignore my writes to E000 and call the IRQs anyway, when no other emulator seems to? I would greatly appreciate an answer to this question.
Thanks.