Ive been looking as a .rom nocarrier made called gallerynes to load a sequence of .nam files. I am trying to remove the blank frame each time a new .nam is loaded.
I can't work out how to approach it though as I assume you need to vblank before loading a new .nam so it loads cleanly but the vblank is causing the blank frame?
I have put a pastebin here of the code.
http://pastebin.com/p50y8HERWhat I am eventually trying to do is create a little rom to load a series of say 10 .nam files to make little full screen "page flip" animations like in the high hopes demo by aspect. The effect shown here
https://youtu.be/eQ-OcS2Gwvk?t=72And as far as I can work out, there isn't a blank frame shown during the "animation"
Anyone know where I would start?
thanks!
Normally, the blank frames between different screens are there because vblank doesn't provide enough time to change large amounts of VRAM data, so rendering has to be turned off to give the programmer full access to VRAM.
If the name tables are not being scrolled, you could instead load the new graphics progressively to the hidden name table across several frames during vblank (like, 128 or so bytes per vblank, instead of the whole 1024 bytes at once), and then switch to that name table when you're done. This technique is called "double buffering".
Thats awesome, I will give that a try. I am sorry if this is a silly question, would I need to reload the attribute table as well or just the .nam file?
lazerbeat wrote:
would I need to reload the attribute table as well
If the image uses more than 4 colors, yes, you probably have to modify the attribute table as well.
Quote:
or just the .nam file?
How big are your .nam files? If they're 1024 bytes, the attribute table is included, if not, they'll be 960 bytes.
Use both nametables. While you are showing one in $2000-$23FF, load the other to $2C00-$2FFF, 128 bytes at a time. Then when it's done, switch to the other nametable and its pattern table by changing the value written to PPUCTRL ($2000). Then vice versa.
Quote:
or just the .nam file?
How big are your .nam files? If they're 1024 bytes, the attribute table is included, if not, they'll be 960 bytes.[/quote]
They are 1024. Ok so I can set a counter for 8 frames, load 128 bytes each frame then transfer everything and reset the counter and in theory no flicker?
Nice little project for this week.
You're gonna need some extra variables in order to keep track of the extra state this will require. For example, if the program currently uses a single name table, this is hardcoded into the program. To change this you'll need a variable to indicate which name table is being displayed, so you can toggle this setting as necessary.
You'll also probably need a flag indicating whether a name table is being updated behind the scenes or not. This flag will be used by the NMI handler to decide whether it should transfer a 128-byte chunk of data or not.
I don't mind the flicker. It's one frame of black screen. It doesn't seem so bad to me. Seems like a lot of unnecessary programming just to avoid it.
dougeff wrote:
Seems like a lot of unnecessary programming just to avoid it.
I disagree. For a beginner, it's good practice, and for more experienced coders, it shouldn't take more than 30 minutes to do.
Actually, I had a follow up question. If the 2nd name table is being loaded "off screen" why is is necessary to load it 128 bytes at a time?
I totally trust you guys that it IS necessary, I would just clearly like to understand why.
Because the register that holds the PPU address is used internally by the PPU when rendering, so the value becomes unstable. This is true even for writing to VRAM that is not being used in the current display. As far as the number of bytes to write to the PPU, since you can only do that in Vblank when the display is on you have about 2300 cycles to do it and depending on how optimized your code is for speed you can write around 128~150ish bytes at a time.
lazerbeat wrote:
Actually, I had a follow up question. If the 2nd name table is being loaded "off screen" why is is necessary to load it 128 bytes at a time?
I totally trust you guys that it IS necessary, I would just clearly like to understand why.
You have a few thousand cycles in vblank where the NES is not drawing the screen. This is the only time you have to access the PPU. Any other time during the frame and the PPU is busy drawing the screen; trying to send data to it while it's doing that will corrupt your nametables and rendering.
Right so even if you are writing to the name table the PPU isn't currently displaying
rainwarrior wrote:
You have a few thousand cycles in vblank where the NES is not drawing the screen. This is the only time you have to access the PPU. Any other time during the frame and the PPU is busy drawing the screen; trying to send data to it while it's doing that will corrupt your nametables and rendering.
Thanks I didn't realize this applied even when writing to the nametable the PPU ISN'T currently displaying.
A hidden name table is still part of the same memory as the visible name table, and that memory cannot be used for anything else while the PPU is rendering the picture.
My old demos, Motion / Flame do this nametable double-buffering and flipping, if you want to check out the code for them (though ignore any bad coding practices that you find. ;-D)
http://www.chrismcovell.com/data/anims.zip
ccovell wrote:
My old demos, Motion / Flame do this nametable double-buffering and flipping, if you want to check out the code for them (though ignore any bad coding practices that you find. ;-D)
I actually found that yesterday! It is super handy. Thanks for the heads up though. I am still really pretty new to coding so this is pretty tough for me. I am going to try and learn how each part of the code works to build up an understanding of what is actually happening. So I am approaching it in more or less the following steps
1 - Load a nametable and display it
2 - load content into different name tables
3 - load content into different name tables and switch between them every X frames
4 - load content into different name tables at 1024 bytes per frame and switch every X frames
I am going to save a little folder with code for each step so hopefully it can be useful for someone else learning down the road.
The ultimate goal is to make a little animation looping demo where different buttons will play the animation forward, backwards, ping pong, forward loop etc.
1024 bytes per frame is impossible, that's why we mentioned doing 128 bytes per frame instead.
Dwedit wrote:
1024 bytes per frame is impossible, that's why we mentioned doing 128 bytes per frame instead.
Sorry! that was a total brainfart. I know it needs to be less. I even mentioned 128 earlier in the thread...
You might be able to push 1024 bytes in a frame if it was mostly forced blank. Maybe if your image area was limited to 16 scanlines or so?
OK, so I have spent a bit of time working on this and I have managed to load a different simple picture into each name table. Up and down will select which name table is being displayed which is great. I know it isn't anything major but I am pretty pleased with myself up to this point.
Start should make the frame tables switch automatically every X frames but it will only switch once. It never switches back. I think this is probably the problematic bit of code. Would anyone be kind enough to take a look at it? I have been stumped for a couple of hours
Code:
animation:
DEC framecounter
BNE noanimation
LDA nametableflag
CMP #$0
BNE flip
LDA #%10001010 ;switch to first name table
STA $2000
LDA #$1
STA nametableflag
flip:
LDA #%10001000 ;switch to second name table
STA $2000
LDA framenumber
STA framecounter
noanimation:
jmp animationover
I have included a pastebin of the full code just in case.
http://pastebin.com/nf1sCN4X
Just in case it is useful for someone in the future, I fixed the problem. I used this code
Code:
animation:
DEC framecounter
lda framecounter
CMP #$00
BNE noanimation
LDA nametableflag
CMP #$0
BEQ flip
LDA #%10001010 ;switch to first name table
STA $2000
JMP postflip
flip:
LDA #%10001000 ;switch to second name table
STA $2000
postflip:
LDA framenumber
STA framecounter
LDA nametableflag
EOR #$01
STA nametableflag
noanimation:
jmp animationover
But the main problem is I forgot to declare the framenumber variable!
You don't need either of the cmp #$00 / cmp #$0 statements. The preceding lda statements will set the zero flag if the value loaded is zero or not.
I am sorry to bug everyone again, I have done a fair amount of work on the code and I THINK I am loading information into alternating name tables and loading alternate name table each frame, but I still have a flash between frames.
This is the code I am using to write to the alternating name tables. Could this be the cause?
Also a couple of people mentioned I should try loading the code 128 bytes per frame but I haven't figured that out just yet. Would that be the cause of the problem?
Code:
DrawScreen:
LDA nametabletoggle
; cmp #0
BNE nametable2000
nametable2c00:
LDA #$2c ; set to beginning of first nametable
STA $2006
LDA #$00
STA $2006
jmp startdrawing
nametable2000:
LDA #$28 ; set to beginning of second nametable
STA $2006
LDA #$00
STA $2006
jmp startdrawing
startdrawing:
LDY #$00
LDX #$04
NameLoop: ; loop to draw entire nametable
LDA ($10),y
STA $2007
INY
BNE NameLoop
INC $11
DEX
BNE NameLoop
LDA nametabletoggle
EOR #$01
STA nametabletoggle
RTS
Here is the full code
http://pastebin.com/TDH3hb32The rom animates through 10 "frames" when you press start. I know it isn't super impressive but I happy I have got it this far!
Also the animation timing code wasn't written by me, it was a gentleman called nickmaynard who posted it on another forum quite a while back.
koitsu wrote:
You don't need either of the cmp #$00 / cmp #$0 statements. The preceding lda statements will set the zero flag if the value loaded is zero or not.
Thanks very much, I have removed them!
edit : attached the wrong file...
Well, you're transferring 1024 bytes at once. Which might look flickery in an emulator, but if done while rendering is on will corrupt the entire screen on real hardware. (As you will be attempting to write to PPU at the same time it's trying to fetch data)
Plus...maybe it looks like an efficient loop...but you really have very very small time during V-blank...you can only transfer 130-180 bytes per V-blank (difference depending on whether or not you do Sprite DMA) with this loop.
With more efficient code, you could squeeze 256 bytes per frame, but for now, maybe stick to 128 bytes per frame.
With your current system... maybe...
Code:
startdrawing:
LDY #$00
NameLoop:
LDA ($10),y
STA $2007
INY
BPL NameLoop
Would transfer 128 bytes.
dougeff wrote:
Plus...maybe it looks like an efficient loop...but you really have very very small time during V-blank...you can only transfer 130-180 bytes per V-blank (difference depending on whether or not you do Sprite DMA) with this loop..
Thanks I will work on that and report back!
Would the best way to do that be spend 8 frames transferring 128 bytes per frame, set a after the 8th frame , check for the flag during vblank and then transfer?
Rainwarrior said:
Quote:
You might be able to push 1024 bytes in a frame if it was mostly forced blank.
I can't think of a reliable way to time this, unless you ran the exact same code from the start of V-blank every frame (and had rendering off during the transfer)...you can't do a sprite zero hit with rendering off... But, even a conditional branch might be enough to throw you off a scanline, and you'd get screen jitter.
Maybe you could turn redering off about 1/4 from the bottom of the screen, timed with a sprite zero hit.
It was not a serious suggestion, dougeff, but yes if you want predictable timing you can either write code with no branches, or account for all branches. It's not that hard to deal with, a branch taken is 1 more cycle than a branch not taken, so if you want both paths to be the same you just add that extra cycle to the branch-not-taken path. It's entirely doable to write long stretches of precisely timed code (e.g. Rad Racer, Big Bird's Hide and Speak, SuperNSF, etc.). It's a lot more tedious than it is difficult (you can use a debugger to count cycles for you).
So I have been looking at Ccovell's motion demo which seems to do exactly what I am trying to do. Seriously thanks for making the source available it is super helpful.
http://nesdev.com/anims.zipI have converted it to ASM6 which compiles (yay!) and it is displaying content on the screen in the right colors and it seems to be loading 96 bytes per frame and switching name tables which is great. However there are a couple of problems.
1 - According to the PPU viewer in FCEUX It seems that data being written to the PPU looks corrupt
2 - The data written by the screen also looks corrupt.
So rather than nice smooth animation I am just getting kind of trippy glitches which is kind of cool but obviously not what I was hoping for.
Would anyone be kind enough to take a look for me?
Here's what's wrong...
clear memory routine is broken.
X = $ff
A = $80 ...only does one pass and puts $80 in xff addresses.
-add...
Code:
inx
lda #0
...before clear memory
why 'clear PPU' loop starts at $2400 and not $2000
-change to $20 for first sta 2006
use of the 'forbidden' $0d black, probably fine...I prefer $0f
locating cmcmap after the vectors, the assembler has them listed at address $0000, which is the RAM, nothing is there.
-relocate cmcmap somewhere in the ROM between the code and the vectors...
motion.nam is not a binary file, you should use .include not .incbin
Actually, it was really easy to make these changes to the source code...it looks pretty good to me...
dougeff wrote:
locating cmcmap after the vectors, the assembler has them listed at address $0000, which is the RAM, nothing is there.
-relocate cmcmap somewhere in the ROM between the code and the vectors...
motion.nam is not a binary file, you should use .include not .incbin.
Thank you so much for that! I have been fiddling about with it for a couple of days and I am pretty sure this was the cause. I am working on a little project with this which I will hopefully post soon.
similar gallerynes image generator