I have created a scrolling background. When I run it in Nintendulator, the scrolling seems to "shimmer". I noticed that the FPS tends to fluctuate between 59 and 60 frames. Is this the cause of the shimmer, or is it something in my code? (On that note, is there anything I'm doing or not doing in this code that I should do different? Sorry about the long code paste-in.)
Code:
;-----CODE START-----;
;iNES Header
.inesprg 1
.ineschr 1
.inesmir 1
.inesmap 0
;Code
.bank 0
.org $0000
ScrollPos: .db 0
A_Pressed: .db 0
B_Pressed: .db 0
.org $0300
Y_Pos: .db 0
Tile_Num: .db 0
Special_Byte: .db 0
X_Pos: .db 0
.org $8000
Reset:
sei
cld
ldx #$FF
txs
wvb1:
lda $2002
bpl wvb1
wvb2:
lda $2002
bpl wvb2
turnOffScreen:
lda #$00
sta $2000
sta $2001
jsr initVariables
jsr loadPalette
jsr loadNameTable1
jsr loadNameTable2
jsr initSound
wvb3:
lda $2002
bpl wvb3
wvb4:
lda $2002
bpl wvb4
setupScreen:
lda #$00
sta $2006
sta $2006
lda #%10001000
sta $2000
lda #%00011110
sta $2001
infinite:
jsr infinite
initVariables:
lda #50
sta X_Pos
sta Y_Pos
lda #0
sta Special_Byte
sta ScrollPos
sta A_Pressed
sta B_Pressed
lda #1
sta Tile_Num
rts
loadPalette:
lda #$3F
sta $2006
lda #$00
sta $2006
ldx #$00
paletteLoop:
lda colorPalette, x
sta $2007
inx
cpx #32
bne paletteLoop
rts
loadNameTable1:
lda #$20
sta $2006
lda #$00
sta $2006
ldy #$00
ldx #$04
lda #low(nameTable1)
sta $10
lda #high(nameTable1)
sta $11
loadNTLoop1:
lda [$10], y
sta $2007
iny
bne loadNTLoop1
inc $11
dex
bne loadNTLoop1
rts
loadNameTable2:
lda #$24
sta $2006
lda #$00
sta $2006
ldy #$00
ldx #$04
lda #low(nameTable1)
sta $10
lda #high(nameTable1)
sta $11
loadNTLoop2:
lda [$10], y
sta $2007
iny
bne loadNTLoop2
inc $11
dex
bne loadNTLoop2
rts
initSound:
lda #$01
sta $4015
lda #$00
sta $4001
lda #$40
sta $4017
rts
VBlank_Routine:
lda $2002
ldx #$00
stx $2006
stx $2006
lda ScrollPos
sta $2005
stx $2005
Sprite_DMA:
lda #$3
sta $4014
Controller_Strobe:
lda #$01
sta $4016
lda #$00
sta $4016
A_Check:
lda $4016
and #1
beq A_Not_Pressed
ldx A_Pressed
bne B_Check
sta A_Pressed
lda #$95
sta $4000
lda #$8F
sta $4001
lda #$F8
sta $4002
lda #$0C
sta $4003
jmp B_Check
A_Not_Pressed:
sta A_Pressed
B_Check:
lda $4016
and #1
beq B_Not_Pressed
ldx B_Pressed
bne Select_Check
sta B_Pressed
lda #$95
sta $4000
lda #$87
sta $4001
lda #$80
sta $4002
lda #$08
sta $4003
jmp Select_Check
B_Not_Pressed:
sta B_Pressed
Select_Check:
lda $4016
Start_Check:
lda $4016
Up_Check:
lda $4016
and #1
beq Down_Check
lda #7
cmp Y_Pos
beq Down_Check
dec Y_Pos
Down_Check:
lda $4016
and #1
beq Left_Check
lda #223
cmp Y_Pos
beq Left_Check
inc Y_Pos
Left_Check:
lda $4016
and #1
beq Right_Check
dec ScrollPos
Right_Check:
lda $4016
and #1
beq RTN_FROM_INT
inc ScrollPos
RTN_FROM_INT:
rti
colorPalette:
.incbin "demo.pal"
nameTable1:
.incbin "demo.map"
;Interrupt Handlers
.bank 1
.org $FFFA
.dw VBlank_Routine
.dw Reset
.dw RTN_FROM_INT
;CHR-ROM Data
.bank 2
.org $0000
.incbin "demo.bkg"
.incbin "demo.spr"
In your NMI routine I think you should set $2005 before clearing $2006. That could be the source of your scrolling problem, maybe.
Other than that, it looks alright to me. The infinite loop is amusing, JSR'ing to itself, heheh. If you change it to a JMP, it would free up a lot of RAM on the stack page for general use if you ever need it, as you probably know already.
Memblers wrote:
In your NMI routine I think you should set $2005 before clearing $2006. That could be the source of your scrolling problem, maybe.
You've got that backwards - you want to write $2000/$2005
AFTER messing with $2006/$2007. He has it correct.
Yeah, you're right. I looked in my older source and I did $2006 first also. Thanks for the correction.
Thanks for the JSR/JMP thing... don't know what I was thinking there! Anyway, any other thoughts on the shimmering? Could I send the file to one of you to look at in Nintendulator?
Oddly, I just checked it in FCEU; there it doesn't shimmer, it hiccups. One frame every 20 or so when the background scrolls, it looks like it pauses for one extra frame. Otherwise it looks perfect there.
I gave it a good once over and didn't see anything too wrong. Only thing I see is that you're not resetting the sprite address before writing to $4014 (I'd write 0 to $2003 before writing to $4014)
I don't know what you mean by "shimmering" -- unless you mean the screen is glowing =P. You mean like jittering/shaking? Perhaps you could upload the ROM so we could try it out for ourselves?
Okay... will do.... How?
Get some webspage (Geocities, Angelfire are free servers), upload your ROM there (preferably zipped) and post the link here.
http://www.kirabug.com/nighthawk/demo2.zip
File contains both the rom file and the code.[/url]
The scrolling seems OK on Nintendulator and on my NES.
I'll be darned... I think I owe an explanation...
I typically use my laptop (Centrino 1.6Ghz, ATI Mobility 9200, 512MB RAM) to do my programming, whether for the NES or in C/C++. Well, turns out that when I run the rom on my desktop machine (Athlon 64 3400+, ATI 9600 Pro, 1GB RAM) with Nintendulator it runs just fine...
Sorry for the fuss... and from now on, I'm make sure to check first on the desktop machine before reporting non-existant issues!
Quietust was a bit worried there for a second
I hear Laptops are infamous for having trouble with emulators since their timing functions work differently or some crap -- so emulators which work fine on desktops often jitter and stutter on laptops.
LCD panels have lots of subtle issues with how they refresh. With CRT it's just the electron gun scanning from top to bottom. Techmind has a page with several
color patterns that flicker and do other odd things only on LCD panels. When scrolling, pixels which are changing color/brightness will be darker than those which aren't. It's pretty easy to see this when scrolling in a web browser while looking at NES screenshots. Combine that with a refresh ratea lot different than 60 Hz and there might be shimmer (where it would just be a little jerky on a CRT).
One thing I like is that when doing quick horizontal scrolling, the picture doesn't "lean" when you follow the background with your eyes. On a CRT, there's inherent lean because the upper portion of the image is effectively always being redrawn slightly before the lower portion.
Disch wrote:
I gave it a good once over and didn't see anything too wrong. Only thing I see is that you're not resetting the sprite address before writing to $4014 (I'd write 0 to $2003 before writing to $4014)
Final Fantasy seems to don't do that at all (didn't you said you were fan of the game) ?
Hrm... whaddaya know, it doesn't.
I guess it isn't needed after all. I'd still do it though, just because I'm paranoid. I mean it's only 5 bytes.
Disch wrote:
I guess it isn't needed after all. I'd still do it though, just because I'm paranoid. I mean it's only 5 bytes.
This also helps emulator authors avoid the extra work of getting their emulators correct. :)
Okay, so to make this a real question(s), what are some of these numbers in the Register window?
P - processor status register?
IRQ - when BRK instruction encountered or sound routine generates one?
SLnum - Scan Line... why doesn't my NMI routine start at 240 instead of 241?
And what's the deal with scan line -1?
CPUTicks: Okay, I get the second number, that's the actual CPU cycles (how do you get 1/3 or 2/3 of a CPU tick?). What's the first one (other than 3 times the second one)? How do these work? Is there a document I should be reading?
CPU & PPU Pages.... Huh?
Is there like a manual for Nintendulator that I missed?
Thanks for all the help!
P: Processor Status Register, the official name of the Flags register. The flags themselves are shown immediately below.
IRQ: Currently active interrupt sources. Up to 4 can be shown, "DMC" (DPCM sample finished), "FRM" (APU frame IRQ), "EXT" (external, from the mapper), and "DBG" (triggered by the 'IRQ' button in the debugger, though with the current logic it will never actually be displayed in the debugger).
SLnum: The current scanline number. Scanline -1 is the 'dummy' scanline during which the background render pipeline is primed. Visible scanlines range from 0 to 239. The reason your NMI routine starts at scanline 241 instead of 240 is because that is how a real NES PPU actually works.
CPUTicks: The first number indicates the PPU's state within the current scanline - values 0-255 correspond to the rendered pixels, and 256-340 correspond to HBLANK.
CPU Pages: 16 numbers to indicate what is currently mapped at each 4KB memory range. ??? means unknown data (possibly empty), ### means PRG ROM, and A## means PRG RAM.
PPU Pages: 12 numbers to indicate what is mapped at each 1KB memory range, including the nametable region. ??? means unknown data (possibly empty), ### means CHR ROM, A## means CHR RAM, and N## means nametable RAM.
In general, if you don't understand what something means, it's not useful to you.
So, since there's 340 pixels in the horizontal line, that's where the 113.333 ticks comes from, right? Since the CPU and PPU run seperately, this weird kinda of syncing is normal.
Thank you for all the info... I hope that someday I'll need to know all of it!
There are actually 341 'pixels' in the horizontal line (numbered 0 to 340), giving the 113.666666 cycles per scanline. If you're in PAL, though, it's a bit different since there are 3.2 PPU clocks per CPU clock.
Disch wrote:
I hear Laptops are infamous for having trouble with emulators since their timing functions work differently or some crap -- so emulators which work fine on desktops often jitter and stutter on laptops.
It is due to a combination of things: the LCD and the dynamic CPU frequency scaling. I have played many games under both Windows and Linux that get screwed up if you have CPU frequency scaling enabled. It is used for saving battery life, by changing your CPU speed depending on the system load and the amount of battery available. It totally screws up the timing in some games, causing them to think that your computer is slower than it really is... as most likely the game checks for timing details when the CPU is throttled down and then when the CPU is sped up again, the game runs too fast.
Disabling CPU frequency scaling fixes the problem. Just remember to enable it when you are not playing games, as it is a good thing and it is really the game's fault for not working correctly. Off the top of my head, the games that have problems with it are: Deus Ex (under Windows and emulation on Linux) and More Quakeworld (under Windows and Linux).
The LCD screen is also a big problem. In my opinion, when it comes to gaming, a high-quality CRT is still king. However, the other technologies are gaining and the CRT is basically at its peak of what it can do.
Jagasian wrote:
Disch wrote:
I hear Laptops are infamous for having trouble with emulators since their timing functions work differently or some crap -- so emulators which work fine on desktops often jitter and stutter on laptops.
It is due to a combination of things: the LCD and the dynamic CPU frequency scaling.
The source of the problem is most likely the RDTSC (Read Time Stamp Counter) instruction which is the cpu's own high resolution timer. It's accurate as hell but will, as mentioned, wreck havoc on programs relying on its frequency being constant.
Nintendulator does use a high resolution timer [QueryPerformanceFrequency()/QueryPerformanceCounter()], but only for handling of auto-frameskip; speed throttling is done within the APU's sound output code (by waiting until there's enough room at the end of the buffer).
QPC should be fairly safe to use. The hardware counter it uses may be different across systems but the most common seems to be the PMT (3.57 MHz) or the PIT (1.19 MHz). Altough unlikely these days, it may also use the RDTSC in which case one should do a re-check with QPF once in a while to make sure the frequency is up to date.
As for myself, I use the QPC (unless vsync=ON and NES frame rate=monitor refresh rate) but enable the option to use the less accurate timeGetTime() which may be more reliable once it has been set up to use the highest resolution possible with timeBeginPeriod() / timeEndPeriod().
Does the PMT run at the same 3.579545 MHz as the NTSC color clock?