It is currently Sun Dec 10, 2017 5:29 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sat Jan 28, 2006 6:02 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
I ask myself how abordable would be to change the pallette each scanline (or every two or three scanlines). Memblers already did it in it's FAU demo, but I'd like to have more info about it.
The goal would be to be able to make cool background between text boxes by changing color luminosity like does a lot of SNES RPGs, Tales of Phantasia, for example, changes the background color to make a cool luminosity effect. I'd like to end up with something similar to ToP.
Now, I need to turn the screen off ($2001), write the new palette data ($2006,7), setup the good nametable adress for next scanline ($2005,6) and turn the screen on back ($2001) each HBlank, right ? Scince HBlank is very short, this should be done a bit before, making the right border unusable.
How obtain not-too awfull gliches on the right border ? Ideas, suggetions ? Thanks.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 10:32 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
I know we look up to SNES games and MEGADRIVE games when thinking of nice effects for the NES, but in this case, we can not forget the ATARI 2600. To get decent colors with it, you HAVE to change the palette every scanline. It has 1 background color (much like color 0), then there is the playfield color (making your background effectivelly a 2-color one) and the sprites of each player get 1 color each. Many games just used the 2 color BG and the 1 color players, but later games changed the palette along the way to have more detailed sprites and colorfull backgrounds. The player palette could be black when it's head was being drawn (hair), and then skin-colored (face) and then the color of his clothes, etc.

I'd also really like to use this technique with NES projects. But the fact that you have to not only change the palette, but also set the scroll values for the next scanline make it a little difficult. I guess we could have tables to speed up the scanline address setting.

And that thing that the PPU will draw the color $2006 (oh well, the VRAM address register, right?) points to (if pointing to the palette) when rendering is off, wich can be a very useful resource sometimes, gets in the way of changing the palette, as pointing to it to write the new values will result in glitches. Unless we used the HBlank time to set the colors and the beginning of the next scanline to set the scroll. Then you'd have a blank part at the right, not at the left.

How many cycles do we have in HBlank... 28,333 or something? Maybe it is enough to change 3 palette entries? We'd have to think of a clever way to do this quickly enough. And then, on the next line set the scroll. Setting the scroll at the beginning of a scanline can be hard, though, right?

What happens to $2006 and the address register when in VBlank? Do we need to turn rendering off to use $2006 or since it's in HBlank we're free to use it for some time? If we could just change the palette without turning rendering off it would save some precious time. We'd then turn it off only after having changed the palette (just before the new scanline starts) to set the scroll an then turn it on again.

Would this work? Maybe my idea is crap, if rendering must be off in HBlank.....


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 10:59 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
Rendering isn't off in HBlank. Setup the scroll at the begining of a scanline is impossible, only the fine scroll will be taken in account, and the main scroll will take effect only after the next HBlank. I relly think the solution is to quickly change the palette during HBlank and then setup the good adress for the next scanline before the scanline starts to be rendered.
I do only want to change one single palette entrie. I can hardly see the interest of changing more, at least to do what I want to do.
But... how ? I'm very confused with that HBlank thing. And I want to know what will be rendered exactly... I mean if it is impossible to have that without a lot of gliches, it would be way better to just stay with black windows than having windows with nice color but a quarter of the screen rendering glitches.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 12:35 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
Bregalad wrote:
Rendering isn't off in HBlank.

I didn't say it was, I just though maybe we could use $2006 at will during HBlank as it is possible in VBlank, without turning rendering off. You can use $2006 in VBlank without turning rendering off, or am I wrong here?

Quote:
Setup the scroll at the begining of a scanline is impossible, only the fine scroll will be taken in account, and the main scroll will take effect only after the next HBlank.

Why is it impossible? I thought it was just hard to get the timing right. Doesn't the VRAM address get updated after the second write to $2006, no matter how deep you are in the scanline? If you always take the same time to update the palette and set the scroll, rendering will most likely be turned on at the same column every scanline, or am I dreaming here? Maybe the tile fetching gets in the way, but I don't know much about that.

Quote:
I relly think the solution is to quickly change the palette during HBlank and then setup the good adress for the next scanline before the scanline starts to be rendered.

But then you'd have to fit the whole code inside VBlank. Maybe you could start a little sooner, disable rendering and write the first byte of the address. Then, when actually inside HBlank you'd set the second byte, quickly set the color, and prepare the scroll for the next line. I don't think there is time to set the scroll still inside HBlank, though.

Quote:
I do only want to change one single palette entrie. I can hardly see the interest of changing more, at least to do what I want to do.

One already helps, if you want to build a gradient for the sky, or something like this.

Quote:
But... how ? I'm very confused with that HBlank thing. And I want to know what will be rendered exactly... I mean if it is impossible to have that without a lot of gliches, it would be way better to just stay with black windows than having windows with nice color but a quarter of the screen rendering glitches.

Yeah, better stick to the basics and have no glitches. Effects are totally useless if very noticeable glitches come along with them.

I'm still a bit confused about these tiny little details of how we can do stuff that's not protocol. If I had some sort of dev system I'd definatelly try all that stuff out.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 1:50 pm 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
Yeah, I'm very confusing about tricky HBlank and scanline timing. I think there is people with more tricky scanline experience out there.
Help would be greetly apprecied.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 2:17 pm 
Offline

Joined: Wed Mar 09, 2005 9:08 am
Posts: 348
As much as we'd like to compare the NES to other systems, it is not a 2600 nor a C-64, and thanks to the braindead palette architecture, you can't do these neat raster bar effects without paying a huge price for it.

I've tried a lot of effects based on changing the palette at each hblank and have come to the conclusion that they are useless for most (though not all) practical purposes. One reason is the large number of cycles you need to dedicate to turning rendering off and back on again and restoring the scroll values, meaning you will be able to change at most one or two colors in the palette before you will get a very noticable artifact at the right edge of your screen since the PPU will not output BG0 when you point $2006 at $3Fxx, but rather the color $2006 points to. (this is AFTER applying insane amounts of optimization scheduling and self-modifying code)

But the biggest reason is that turning rendering off in hblank will effectively kill all sprites on the next scanline. The 2-bit color tiles and 16x16 palette selection is quite limiting when doing NES graphics, and the best way of getting a bit more color out of your pictures is to overlay sprites on BG like all good game makers did back in the days. Throwing away that oppurtunity to be able to change at most 2 BG colors per scanline just doesn't make sense for most purposes.

And last but not least, don't even think about trying to pull these tricks off unless you're testing it on the real deal. The glitches from turning off rendering and writing $2007 in hblank is the least supported "feature" in emulators.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 2:28 pm 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
Bananmos wrote:
But the biggest reason is that turning rendering off in hblank will effectively kill all sprites on the next scanline. The 2-bit color tiles and 16x16 palette selection is quite limiting when doing NES graphics, and the best way of getting a bit more color out of your pictures is to overlay sprites on BG like all good game makers did back in the days.

That's right when working on cutscenes or portraits.
What I had in mind is changing palette for background in text boxes (wide for all the screen exept maybe a right border ?). So lack of sprites isn't a problem.
But why would the sprites disapear ? Disabling them would stop all sprite evaluation for the next scanline ?

Quote:
And last but not least, don't even think about trying to pull these tricks off unless you're testing it on the real deal. The glitches from turning off rendering and writing $2007 in hblank is the least supported "feature" in emulators.

Yeah, that is embarassing. However, I think Nintendulator should be helpfull in such cases, isn't it ?

Well... all that tricky scanline stuff makes me very confusing. I think black backgrounded text boxes aren't that bad after all. But well, I'm still asking.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 2:49 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
Assuming you want to avoid all graphical glitches... this means the earliest you can start messing with the PPU address is just after it increments the Y scroll (PPU cycle 257 on the scanline). You must also finish and have the scroll values reset before it begins fetching bytes for the next scanline (cycle 320 -- meaning you must be done by 319) This leaves you a window of 62 PPU cycles -- or roughly 20 CPU cycles.

Now note that you only have 20 CPU cycles if you happen to hit HBlank at EXACTLY the right time --- which typically won't be the case, since the last CPU instruction might have left you 1 cycle into HBlank. So to be safe you should probably only work around having have 18 cycles or less -- depending on the length of the instructions you use. But for this, let's just say you have 18.

that gives you time for 4 writes (STA,STX,STY absolute are 4 cycles).. and I guess 1 load (LDA,LDX or LDY immediate for the final 2 cycles). If you have A,X,Y all set up with what you want to have written before HBlank, you may be able to take advantage of all these writes.

Now, you'll want the last 2 writes to be resetting the scroll -- so that means you're stuck with the last 2 writes being $2006 writes. Which I guess would make the write before that your palette write (to $2007). Making this stunt just BARELY possible... with a minor problem:

Fine Y scroll will be lost, since you can't set it with just $2006 writes alone, and you don't have time to alternate $2005/$2006 writes to set it properly. This means that you won't be able to change a palette color on every scanline -- but only on half of them (the ones where the fine Y scroll for the next scanline would be less than 4)


Now note that only the second $2006 write needs to come after PPU cycle 257 (since that's the only one that changes the PPU address directly). The first can come a little earlier. In the end, you'll probably want something like this:

Code:
LDX #desired_scroll_high
LDY #desired_scroll_low
LDA #$3F
STA $2006   ;  note - key time 1 .. see below.
LDA #palette_address_you_want_to_change
STA $2006   ;  note - key time 2 .. see below.  HBlank starts now
LDA #desired_color
STA $2007
STX $2006
STY $2006
; end HBlank


The Key time 1 (that first $2006 write) can be dangerous depending on the H scroll of the screen. At this time (before HBlank starts), the PPU is still fetching/rendering tiles, and in the process of doing so, is incrementing the PPU address by 1 every 8 PPU cycles. This wouldn't be a problem, except that if it increments the address so that the low 5 bits wrap from $xx1F, it will reload bit 10 from the temp PPU address -- which this write is changing. If this write rubs that bit the wrong way, it's okay as long as only the last fetched tile is affected (since it's never rendered to the screen). If you mess up the tile before that you could have up to 7 distored pixels on the right side... the tile before that = up to 15 pixels. And so on. Now in this case... "distorted" only means they could be loaded from the wrong nametable ($2400 instead of $2000 ... or $2C00 instead of $2800). So if you have both nametables containing the same tile for this part of the screen (or more simply, if you have horizontal mirroring), this problem will be avoided altogether.

The Key time 2 (that second $2006 write) is what's most important. HBlank (scanline cycle 257) must hit BEFORE the final cycle of that instruction (the write cycle). If not, you risk distorting the next scanline (and possibly the rest of the frame).


Of course the hardest part of all this (and wouldn't you know it... the part I didn't cover ;P ) is actually FINDING HBlank with any degree of accuracy. IRQs are slow and coarse -- and could leave you up to 7 or so cycles off (chopping your slim-but-doable 18 available cycles down to a don't-even-bother 12 cycles). Sprite 0 hit might be good enough since BIT is moderately quick (4 cycles) -- but with a 4 cycle error you'd only have about 15 cycles (and if you count the cycles in my code above, you'll see I need AT LEAST 15 cycles for it to work -- so this could be very dangerous)


EDIT -- also note that this is all theoretical. As has been said this just flat out might not work on the real system.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 4:14 pm 
You seem to forget that you HAVE TO turn off rendering completely by writing $2001 for writes to $2007. Otherwise, the palette color won't be set. (trust me on this one, I tried to make a work-around 5 years ago in all ways I could imagine)

One of the problems you mention is indeed that you cannot get in perfect sync with the PPU on the NES like you can on a C-64. (where you can write the *exact* pixel location at every frame) The only way I've found out to get a minimal phase error is to time all your code from start of vblank to the beginning of the effect, and make sure the next vblank will end with a bunch of NOPs.

That still leaves you with a cycle off though. Maybe it's doable if you manage to have a last "sta zero-page" instruction after a final NOP and time your code so that NMI would either occur directly before it (i.e., after the last NOP) or always one cycle inside of it. Then you could check the zero-page variable inside the NMI and skip 2 cycles in the timed code if the write was sucessful. I think I tried something like this once, but for some reason wasn't able to get it working without glitches.


Top
  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 4:15 pm 
Offline

Joined: Wed Mar 09, 2005 9:08 am
Posts: 348
That was me above. (checked that damn "log me in on each visit" check-.box now)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 29, 2006 1:25 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
Oh my god.... Dish I wouldn't be able to do a such developpement on my own. Plus time to turn off $2001 and turn it back later, I think glitches are unavoidable.
Also, in PAL, a CPU clock is 3.2 pixels and not 3, so this leves even less time for HBlank (or am I wrong ?).
Now, what kind of glitches would happen ? Turning the rendering off will render the background color, but then set $2006 during the right border time before the actual HBlank, what kind of effect could it have ?
By written only to $2006, the only flaw is that fine H scroll cannot be set, and that fine V scroll can only be between 0 and 3 (bit 2 always clear), right ? If so I think I could work with it.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 05, 2006 8:23 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
Here you are the best I can do :
http://jonathan.microclub.ch/window
Could it be improved in any way ? (there is glitches on the rightside of the screen). Does it looks the same on a real NTSC hardware ?

PS : My commented cycle counting on tricky routines is most probably outdated, so don't care.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 05, 2006 8:48 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
It's nice that you got to make a demo of it. I think it looks OK, but why do the text and the borders get the color changed too? If only the background changed it would be nicer. It looks somewhat glitchy with the "white" color also changing. The right side is pretty glitchy, as expected. I can't think of a way for the player to ignore that. You can't just make the text box smaller and cover the rest with sprites 'cause they're disabled too, right?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 05, 2006 9:22 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
The text color actually isn't changed, the color emphasis it.
However, I got a better idea. When I'm able to change the $2006 adress (so at the top of a non-space tile and at the bottom of the space tiles), I'll change the color and keep the emphasis solid. When I'm not able to change the $2006 palette because it would require some $2005 writes, I'll only change the emphasis on $2001. So the bottom part of the letters may look to change. If it really looks to strange, I may try to compensate this with palette (or to simply not use emphasis bits).
I think glitches at the right will be less visible if I make the box smaller, letting 2 blank tiles to the right boxrder instead of just one.

EDIT : I now uploaded a new version that looks way better, but still has several glitches. If anyone has improvement ideas, please tell me !

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 05, 2006 11:31 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7312
Location: Chexbres, VD, Switzerland
A big problem is that I cannot guess how it would be on the real NTSC hardware. Could someone test it for me please ?
Is it possible to make a PAL adaptation of it ?

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: cppchriscpp, Majestic-12 [Bot] and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group