- Joined: 15 Feb 2016
- Posts: 19
|
Help with a color fade out trick
Posted: Wed Jan 18, 2017 10:47 pm
|
So here's what I've been trying to hammer out for several weeks now. I thought fading the screen out when moving into a new room, switching the background and fading it back in again would be a pretty neato effect. I've gotten it to fade out just fine, but fading it back in is posing quite a problem.
I find myself trying to juggle registers because I don't have enough working room to handle the color value that I need to compare the current value against.
I'm at my wit's end at this point and just can't see what I'm missing. Why the new colors aren't loaded into the RAM space I have set up for them. I'm pasting my fade out and fade in subroutines here. If anyone could nudge me in the right direction or point out a critical flaw in this system I would greatly appreciate it! Thanks in advance!
.section "Fade Screen" free
FadeScreen:
ld a , 4 ;Cycling through this routine four times should get us where we need to be
ld (FadeTimer), a
-:
ld bc, 32
ld hl, ActiveSpritePalette ;This is a section in RAM where my screen update routine looks for the palette data
;ActiveBGPalette is located 16 bytes after this so it is one continuous block
_Blue:
ld a, (hl)
and %00110000 ;Mask off the color value bits that we want to manipulate
jr z, _Green ;If it's already 00, we can move on to the next value bits
sbc a, %00010000 ;Otherwise knock it down 1 and put it back
or %11001111
and (hl)
ld (hl), a
_Green:
ld a, (hl)
and %00001100
jr z, _Red
sbc a, %00000100
or %11110011
and (hl)
ld (hl), a
_Red:
ld a, (hl)
and %00000011
jr z, +
sbc a, %00000001
or %11111100
and (hl)
ld (hl), a
+:
inc hl
djnz _Blue ;32 colors in total
push bc
push hl
ld a, 4 ;Delay a few frames so we can actually see the fade effect
ld (FrameTimer), a
call WaitFrames
pop hl
pop bc
ld a, (FadeTimer)
dec a
ld (FadeTimer), a
cp 0
jp nz, -
ret
.ends
.section "Fade exterior" free
FadeInExterior:
ld a , 4
ld (FadeTimer), a
-:
ld ix, 16
ld bc, ActiveBGPalette
ld de, ExteriorPalette ;Palette data in ROM to compare our current colors to
_Blue:
ld a, (de)
and %00110000
ld (ColorCompare), a
ld a, (bc)
and %00110000
ld hl, ColorCompare
cp (hl)
jr z, _Red
push bc
pop hl
adc a, %00010000
or %11001111
and (hl)
ld (hl), a
push hl
pop bc
_Red:
ld a, (de)
and %00001100
ld (ColorCompare), a
ld a, (bc)
and %00110000
ld hl, ColorCompare
cp (hl)
jr z, _Green
push bc
pop hl
adc a, %00000100
or %11110011
and (hl)
ld (hl), a
push hl
pop bc
_Green:
ld a, (de)
and %00001100
ld (ColorCompare), a
ld a, (bc)
and %00001100
ld hl, ColorCompare
cp (hl)
jr z, +
push bc
pop hl
adc a, %00000100
or %11110011
and (hl)
ld (hl), a
push hl
pop bc
+:
inc bc
inc de
dec ix
jr nz, _Blue
push de
push bc
push ix
ld a, 4
ld (FrameTimer), a
call WaitFrames
pop ix
pop bc
pop de
ld a, (FadeTimer)
dec a
ld (FadeTimer), a
cp 0
jr nz, -
ret
.ends
[/code]
|
- Joined: 26 Dec 2004
- Posts: 374
- Location: Japan
|
Posted: Thu Jan 19, 2017 12:12 am
|
In your fade out/in code, you're doing OR #%11110011 etc, which will set all colours to white; then you're doing AND (HL) which is also wrong.
How about AND #%11110011, and then OR (HL)?
|
- Joined: 15 Feb 2016
- Posts: 19
|
Posted: Thu Jan 19, 2017 4:23 am
|
It's based on something I worked out on paper on my lunch break but I did go over it a dozen times. Let's assume the color byte we are working on is:
%00111010
This is what (hl) is pointing to and we are just interested in the rightmost two bits for now. I have it labeled Red in my code, but it doesn't matter. ANDing it with %00000011 is trivial but now this is in a:
%00000010
We're fading out so knock it down 1 because it isn't black.
%00000001
Now I had to insert just those two bits back into (hl) without messing up the other values in it so we can have a smooth transition. The only way I found that would work was by ORing it with %11111100 which should give me:
%11111101
The weird part is ANDing this with the original byte which, if I'm not insane, yeilds:
%00111001
Please feel free to correct me, but fading out and injecting the new value into the color byte seems to work this way. To be fair, I haven't spent much time working it out the other way around so it may very well be advantageous if it does work!
In the end, I just hand picked color values, stuck them in ROM in a data table and loaded each one individually every few frames when fading back in. Good practices be damned.
|
- Joined: 14 Oct 2008
- Posts: 511
|
Posted: Thu Jan 19, 2017 4:53 am
|
OR makes the resulting bit 1 if the corresponding bit is 1 in either of the values. In the comparison X OR Y, effectively all 1 bits in Y will always be turned to Y.
00010011
11001001
--------
11011011 - Result is a 1 when there is a 1 in either value
X AND Y
00010011
11001001
--------
00000001 - Result is a 1 only when there is a 1 in both values.
And for completion, X XOR/EOR Y (exclusive-or)
00010011
11001001
--------
11011010 - Result is a 1 when there is a 1 in either but not both values
|
- Joined: 15 Feb 2016
- Posts: 19
|
Posted: Thu Jan 19, 2017 6:39 am
|
I do understand how logic gates work (I've got drawers FULL of 7400 series chips) But can you see what I was trying to do with these color bytes? Fade out works well enough but it falls apart when I introduce more registers and a comparison value.
As I've said thougg, I just hacked something together for now that works very smoothly. It's at the expense of a few extra bytes of ROM but it's all the same to the player and frankly I'm tired of thinking about it!
|
- Site Admin
- Joined: 08 Jul 2001
- Posts: 8651
- Location: Paris, France
|
Posted: Thu Jan 19, 2017 9:24 am
|
Quote In the end, I just hand picked color values, stuck them in ROM in a data table and loaded each one individually every few frames when fading back in. Good practices be damned.
What you could do instead of storing faded values for your actual palette, is to just create a fading table, which for each of the 64 possible colors gives you 0..3 variations, then the fading out is just a lookup in this table and you can keep your palettes flexible.
Another idea is that you might experiment with increasing the 0..3 range to a larger range and decrement each components at a different step during the fade, which might create the illusion of a smoother (if weirder?) fade. I'm not sure if many games do that but I guess some would.
|
- Site Admin
- Joined: 19 Oct 1999
- Posts: 14744
- Location: London
|
Posted: Thu Jan 19, 2017 1:54 pm
|
Many games fade one channel at a time to make it take more frames, Phantasy Star does it fairly slowly if you want an example.
|
- Joined: 26 Dec 2004
- Posts: 374
- Location: Japan
|
Posted: Thu Jan 19, 2017 2:06 pm
|
Here's one that I had prepared earlier:
Psychic World on the Sega Master System had a pretty smooth and nice-looking fade in & out routine, so I wanted to find out how it did it. Turns out it was a very simple 3-step process: for fade-outs, ramp down the red channel to zero, then do the same with green and blue sequentially. Almost a bit too primitive, but it actually looks good in-game.
The SMS has only 3 shades of each colour channel so a fade would have only a total of 4 steps if all 3 channels were simply faded out at the same time. Doing it sequentially gives 10 steps total.
The eye is sensitive to the different channels of colour differently, and so Sega/Hertz exploit that, not to mention fading through 4 or 8 (on the Gen/MD) levels only will look too abrupt and might look like it's "shaking" to some viewers.
|
- Joined: 05 Sep 2013
- Posts: 3827
- Location: Stockholm, Sweden
|
Posted: Thu Jan 19, 2017 3:33 pm
|
so it all boils down to
3x: if col>0x0F then col-=0x10
3x: if col>0x03 then col-=0x04
3x: if col>0x00 then col-=0x01
|
- Joined: 15 Feb 2016
- Posts: 19
|
Posted: Thu Jan 19, 2017 7:28 pm
|
Bock wrote Quote In the end, I just hand picked color values, stuck them in ROM in a data table and loaded each one individually every few frames when fading back in. Good practices be damned.
What you could do instead of storing faded values for your actual palette, is to just create a fading table, which for each of the 64 possible colors gives you 0..3 variations, then the fading out is just a lookup in this table and you can keep your palettes flexible.
A fade table isn't a bad idea and I'll play around with that when I have more time.
The little noir style proof of concept game I'm working on has a limited palette and fades nicely enough when all channels are reduced at once. If I find this is unsatisfactory when I make more colorful games I'll keep the rest in mind. Thanks!
[/quote]
|