Screen Fading

User avatar
Mugi
Posts: 781
Joined: Thu Dec 27, 2018 8:30 pm

Re: Screen Fading

Post by Mugi » Wed Mar 27, 2019 6:08 am

GameEngineData\Routines\Basic\DataLoadScripts\LoadPalettes.asm
needs some extra pokery for getting the fade to play nice. (im assuming this stuff was just modified after the fade stuff got disabled and somewhere down the line the script just would stop working.)

i can see why joe killed it off seeing the ridiculous amount of space it eats.
well oh well, here's the scripts i use for this. No idea how these will behave in games other than DS though (there's nothing left of the original load routines in DS anymore.)

loadpalettes.asm

Code: Select all

	LDA updatePalettes
	BEQ LoadPalettesEnd
	LDA #$3f
	STA $2006
	LDA #$10
	STA $2006
	LDX #$00
LoadSpritePal:
	LDA spritePalFade,x
	STA $2007
	INX
	CPX #$10
	BNE LoadSpritePal
	
;; load backgrounds last so that the *background* color gets overwritten correctly	
	
	LDA $2002
	LDA #$3F
	STA $2006
	LDA #$00
	STA $2006
	LDX #$00
LoadBackgroundPal:
	LDA updatePalettes
	CMP #$02
	BEQ ldFadePal
	LDA bckPal,x
	JMP doPalStore
ldFadePal:
	LDA bckPalFade,x
doPalStore:
	STA $2007
	INX
	CPX #$10
	BNE LoadBackgroundPal
	
	LDA #$00
	STA updatePalettes
LoadPalettesEnd:
handlefades.asm

Code: Select all

;; prior to this routine being called, the macro
;; needs info on the timer, so that it can appropriately set it to start with.

HandleFadeLevels:
	LDA fadeByte
	BNE doHandleFadeLevels
	RTS

doHandleFadeLevels:
	LDX #$00 ; start loop

LoadBackgroundPal_FADES:
	CPX #$08
	BCC palValueIsLessThan8
	LDA bitwiseLut,x
	AND fadeSelect_bck+1
	JMP checkThisPalVal

palValueIsLessThan8:
	LDA bitwiseLut,x
	AND fadeSelect_bck

checkThisPalVal:
	BNE getFadedAmountForThisValue 
	LDA bckPal,x
	JMP gotPalValue

getFadedAmountForThisValue:
	LDA fadeLevel
	ASL
	ASL
	ASL
	ASL
	CLC
	ADC bckPal,x
	BPL palValueIsGreaterThanZero
	;;pal value is less than zero.
	;;maintain the actual value for fades, but
	;;anything less than zero in a signed value
	;;draws #$0f (black).
	;; So actual buffer value is in tact for fade math,
	;; but keeps the appearance of fading to black.
	LDA #$0f
	JMP gotPalValue

palValueIsGreaterThanZero:
	CMP #$3c ;; is it as light as it can possibly be?  if so, make it white.
	BCC palValueIsLessThan3c
	LDA #$30

palValueIsLessThan3c:
	CMP #$0D
	BNE gotPalValue
	LDA #$0F

gotPalValue:
	STA bckPalFade,x
	INX
	CPX #$10
	BNE LoadBackgroundPal_FADES
	LDA #$02
	STA updatePalettes
	RTS


HandleFades:
	LDA fadeByte
	BNE doHandleFades
	RTS
doHandleFades:
	;uses fadeByte	
		; 7 = fade is active
		; 6 = fade darker / fade lighter ;; 0 = fade to dark color, 1 = fade to light color
		;_____________________________
		; 5 = LOOP
		; 4 = loading data
		; 3 = fade in
				;; now that we're doing this way, we can almost certainly
				;; combine this and just have one bit that determines if data is
				;; being loaded, to put fade on pause.
		;______________________________
		; 2 = "snap" fade out. Instant black or instant white, immediate to full step fade out.
			;whether black or white is determined by bit 6
		; 10 = how many steps to fade? - only 4 possible values - all the way out is 5.
		
		
	
	;uses fadeSpeed.
		;7 = load new data? 0=no, 1=yes
		;6 = does "fade out"? 0=no, 1=yes
			;; fade out in this case doesn't necessarily mean 'gets darker'.
			;; it just means ping pongs to the fade in script before
			;; returning to normal game.
		;5 = fade sprites? 0=no, 1=yes.
			;; if no, just the background will fade.
		;43210 = fade speed, *3 (asl x 3)
		
	;; checkFadeTimer
	DEC fadeTimer
	BEQ dontKeepRunningFadeTimer
	JMP keepRunningFadeTimer
dontKeepRunningFadeTimer:
	;;fade timer is up.  First thing to do is reset the timer.
	LDA fadeSpeed
	AND #%00011111
	ASL
	ASL
	STA fadeTimer
	LDA fadeByte
	AND #%01000000 ; is this fade to light or dark?
	BNE fadeToWhite
	;;; fade to black
	LDA fadeLevel
	sec
	sbc #$1
	JMP gotNewPalVal
fadeToWhite:
	LDA fadeLevel
	clc
	adc #$1
gotNewPalVal:
	STA fadeLevel
	BPL positiveValueForFadeLevel
	;; negative value for fade level
	EOR #$ff
	CLC
	ADC #$01

positiveValueForFadeLevel:
	STA temp
	;; first, check if this is looper.
	;; if it is not a looper (pulsing type of fade), then
	;; if this fade level is zero, it should *stop* fading. 
	;; this is the most standard type of fade...fade out, do things, fade back in to 0.
	LDA fadeLevel
	CLC
	ADC #$05
	BEQ stopFading 
	LDA fadeLevel
	SEC
	SBC #$05
	BEQ stopFading
	JMP nevermindCheckingForPalLoop
	
stopFading:	
	;; it is at zero
	LDA fadeByte
	AND #%00100000 ;; is it a looper?
	BEQ checkForPalLoop
	JMP nevermindCheckingForPalLoop ;; yes, it is a looper
checkForPalLoop:
	;;no, it is not a looper
	LDA #$00
	STA fadeByte

	;;;; check for load data first
	;;=================
	
	LDA fadeSpeed
	AND #%10000000 ;; this is the bit, in the byte, that sees if we need to load data
	BNE needToLoadData 
	JMP noNeedToLoadData
needToLoadData:
	;;; yes, we need to load new data.


	;LoadChrData #GraphicsBank01, #$10, #$40, #$0, BckChr00
	;LoadBackgroundPalette BckPal00
	
	;;load the pointer info
	;LDA currentBank
	;STA prevBank
	;LDY #$16
	;JSR bankswitchY
	;;; now we can get the offset from the screen tables.
	;;;;;;; if type is 0, check NameTablePointers
		;;; if type is 1, check NameTablePointers_Map1
		;;; if type is 2, check NameTablePointers_Map2
	;LDA newScreen	
	;ASL			
	;TAX
	;LDA NameTablePointers_Map1+0,X
	;STA temp16
	;LDA NameTablePointers_Map2+1,X
	;STA temp16+1
	
	;LoadNametableData #$01, NT_Rm50, #$01, #$80
	;LoadAttributeData #$01, AT_Rm50, #$38, #$08

	;LDY prevBank
	;JSR bankswitchY
	
	LDA #$00
	STA fadeLevel
	LDA #$00
	STA fadeByte
	
noNeedToLoadData:

	;; Check to see if we load data during fade
	;;====================
	
	JMP doneWithFade
nevermindCheckingForPalLoop:
	
	LDA fadeByte
	AND #%00000011
	CMP temp
	BNE doneWithFade ;; haven't reached the end yet.
	;;; we've reached the last step
	;;; we need to check to see if that's it, or if it should pingpong background

	;; now check to see if we're done or we're going to pingpong
	LDA fadeSpeed
	AND #%01000000 ;; does it pingpong?
	BNE doPingPongFade
	LDA #$00
	STA fadeByte
	LDA #$01
	STA updatePalettes
	JMP doneWithFade
doPingPongFade:
	LDA fadeLevel
	BMI changeToFadeIn
	;; change to fade out
	LDA fadeByte
	AND #%10111111
	JMP pingPongDone
changeToFadeIn:
	LDA fadeByte
	ORA #%01000000
pingPongDone:
	STA fadeByte
	
	
dontChangeThisValue:

	
keepRunningFadeTimer:

doneWithFade:
	RTS
after setting these up along with the required ZPvars, you may now call fade using beginfade macro.

now, some parts of this script were left broken, simply because of .....reasons. so not everything from it does work in this state.

you MUST NOT use modes other than what is stated below (they work but produce unwanted effects.)
you also MUST ALWAYS call FADE_LIGHTEN after using FADE_DARKEN to restore the screen, othervise you will eventually run into issues.

to fade out, use:
BeginFade FADE_DARKEN, #$03, #$00, #$00, FADE_AND_HOLD, FADE_ONCE, #%01110111, #%01110111

to fade in AFTER fading out, use:
BeginFade FADE_LIGHTEN, #$03, #$00, #$00, FADE_AND_HOLD, FADE_ONCE, #%01110111, #%01110111

you may toy with the speed and palette attributes, but changing the fade_and_hold or fade_once will propably break it at this state.
also, sprite fading doesnt work, i never looked into it since i didnt want to use it.

on a side note, i fixed the issue with fading out the "illegal" gray color that joe decided we cant use because it breaks fading, so now you can use the missing dark gray and it fades out and in just fine.

on another side note, it is possible to just throw this in handlescreenloads.asm and have it fade screen transitions all the time, but trust me, you dont really want to do that. Especially if you dont have scrolling,
waiting 4-5 seconds between every screen move is not fun after 5 minutes, as cool as it looks.

there is also the fact that these macros are not really small, so repeatedly littering them into every function eats tons of space from bank14 really fast.
the way i do this in DS, is that i have it set on warp tiles, and in addition to that, i have a custom handler that checks newscreen on screen transitions and hardcoded screen numbers (stage changes) are triggering it.
you might want to do something similar to your game to reduce using unnecessary copies of the macro.


just for a third side note, i didn't actually sit on this code just to be an asshat or whatever (im pretty sure people cursed me to hell for not sharing) i just really think this shouldn't be used, and it's bending a rewrite on my own project too
the way this fader works is just insane, you literally spend half of your ZP on this code alone. but since it looks like some people REALLY want to use it, here it is. Godspeed with resource management.
"what are you up to?" "Oh, not much... just... Parallaxing"
- Raftronaut
User avatar
chronicleroflegends
Posts: 190
Joined: Thu Sep 06, 2018 3:51 am

Re: Screen Fading

Post by chronicleroflegends » Wed Mar 27, 2019 6:13 pm

Thanks Mugi

No worries, I totally understand the reasons you were reluctant to release this. I can definitely see that its going to be a tough compromise between nice looking fades and the resource cost associated with it. I am more curious to learn how it works than to use it as is in my game. (Those variables literally take every last byte of my ZP ram)
Hoping to play around with it enough to learn how to do what you suggested: Make something much more game-specific and less resource heavy.
~Do you believe in legends? ~
My Games: Nix: The Paradox Relic
User avatar
Mugi
Posts: 781
Joined: Thu Dec 27, 2018 8:30 pm

Re: Screen Fading

Post by Mugi » Wed Mar 27, 2019 6:15 pm

i will share mine once i get it rewritten assuming it does any better in the resource department too, but for now it's on low priority, for me the scroll is taking the attention until we get it just right.
that said, the amount of optimizing that needs might force me to actually abandon this code in order to get ZP back into usable state :P
"what are you up to?" "Oh, not much... just... Parallaxing"
- Raftronaut
User avatar
chronicleroflegends
Posts: 190
Joined: Thu Sep 06, 2018 3:51 am

Re: Screen Fading

Post by chronicleroflegends » Wed Mar 27, 2019 6:22 pm

Your progress on the scrolling has been amazing so far. Keep up the good work :)
~Do you believe in legends? ~
My Games: Nix: The Paradox Relic
User avatar
Mugi
Posts: 781
Joined: Thu Dec 27, 2018 8:30 pm

Re: Screen Fading

Post by Mugi » Wed Mar 27, 2019 6:28 pm

i havent even shown the cool parts of it yet :P
"what are you up to?" "Oh, not much... just... Parallaxing"
- Raftronaut
User avatar
DanielT1985
Posts: 126
Joined: Sat Sep 01, 2018 7:44 pm

Re: Screen Fading

Post by DanielT1985 » Fri Mar 29, 2019 6:53 am

Mugi wrote:
Wed Mar 27, 2019 6:08 am
GameEngineData\Routines\Basic\DataLoadScripts\LoadPalettes.asm
needs some extra pokery for getting the fade to play nice. (im assuming this stuff was just modified after the fade stuff got disabled and somewhere down the line the script just would stop working.)

i can see why joe killed it off seeing the ridiculous amount of space it eats.
well oh well, here's the scripts i use for this. No idea how these will behave in games other than DS though (there's nothing left of the original load routines in DS anymore.)

loadpalettes.asm

Code: Select all

	LDA updatePalettes
	BEQ LoadPalettesEnd
	LDA #$3f
	STA $2006
	LDA #$10
	STA $2006
	LDX #$00
LoadSpritePal:
	LDA spritePalFade,x
	STA $2007
	INX
	CPX #$10
	BNE LoadSpritePal
	
;; load backgrounds last so that the *background* color gets overwritten correctly	
	
	LDA $2002
	LDA #$3F
	STA $2006
	LDA #$00
	STA $2006
	LDX #$00
LoadBackgroundPal:
	LDA updatePalettes
	CMP #$02
	BEQ ldFadePal
	LDA bckPal,x
	JMP doPalStore
ldFadePal:
	LDA bckPalFade,x
doPalStore:
	STA $2007
	INX
	CPX #$10
	BNE LoadBackgroundPal
	
	LDA #$00
	STA updatePalettes
LoadPalettesEnd:
handlefades.asm

Code: Select all

;; prior to this routine being called, the macro
;; needs info on the timer, so that it can appropriately set it to start with.

HandleFadeLevels:
	LDA fadeByte
	BNE doHandleFadeLevels
	RTS

doHandleFadeLevels:
	LDX #$00 ; start loop

LoadBackgroundPal_FADES:
	CPX #$08
	BCC palValueIsLessThan8
	LDA bitwiseLut,x
	AND fadeSelect_bck+1
	JMP checkThisPalVal

palValueIsLessThan8:
	LDA bitwiseLut,x
	AND fadeSelect_bck

checkThisPalVal:
	BNE getFadedAmountForThisValue 
	LDA bckPal,x
	JMP gotPalValue

getFadedAmountForThisValue:
	LDA fadeLevel
	ASL
	ASL
	ASL
	ASL
	CLC
	ADC bckPal,x
	BPL palValueIsGreaterThanZero
	;;pal value is less than zero.
	;;maintain the actual value for fades, but
	;;anything less than zero in a signed value
	;;draws #$0f (black).
	;; So actual buffer value is in tact for fade math,
	;; but keeps the appearance of fading to black.
	LDA #$0f
	JMP gotPalValue

palValueIsGreaterThanZero:
	CMP #$3c ;; is it as light as it can possibly be?  if so, make it white.
	BCC palValueIsLessThan3c
	LDA #$30

palValueIsLessThan3c:
	CMP #$0D
	BNE gotPalValue
	LDA #$0F

gotPalValue:
	STA bckPalFade,x
	INX
	CPX #$10
	BNE LoadBackgroundPal_FADES
	LDA #$02
	STA updatePalettes
	RTS


HandleFades:
	LDA fadeByte
	BNE doHandleFades
	RTS
doHandleFades:
	;uses fadeByte	
		; 7 = fade is active
		; 6 = fade darker / fade lighter ;; 0 = fade to dark color, 1 = fade to light color
		;_____________________________
		; 5 = LOOP
		; 4 = loading data
		; 3 = fade in
				;; now that we're doing this way, we can almost certainly
				;; combine this and just have one bit that determines if data is
				;; being loaded, to put fade on pause.
		;______________________________
		; 2 = "snap" fade out. Instant black or instant white, immediate to full step fade out.
			;whether black or white is determined by bit 6
		; 10 = how many steps to fade? - only 4 possible values - all the way out is 5.
		
		
	
	;uses fadeSpeed.
		;7 = load new data? 0=no, 1=yes
		;6 = does "fade out"? 0=no, 1=yes
			;; fade out in this case doesn't necessarily mean 'gets darker'.
			;; it just means ping pongs to the fade in script before
			;; returning to normal game.
		;5 = fade sprites? 0=no, 1=yes.
			;; if no, just the background will fade.
		;43210 = fade speed, *3 (asl x 3)
		
	;; checkFadeTimer
	DEC fadeTimer
	BEQ dontKeepRunningFadeTimer
	JMP keepRunningFadeTimer
dontKeepRunningFadeTimer:
	;;fade timer is up.  First thing to do is reset the timer.
	LDA fadeSpeed
	AND #%00011111
	ASL
	ASL
	STA fadeTimer
	LDA fadeByte
	AND #%01000000 ; is this fade to light or dark?
	BNE fadeToWhite
	;;; fade to black
	LDA fadeLevel
	sec
	sbc #$1
	JMP gotNewPalVal
fadeToWhite:
	LDA fadeLevel
	clc
	adc #$1
gotNewPalVal:
	STA fadeLevel
	BPL positiveValueForFadeLevel
	;; negative value for fade level
	EOR #$ff
	CLC
	ADC #$01

positiveValueForFadeLevel:
	STA temp
	;; first, check if this is looper.
	;; if it is not a looper (pulsing type of fade), then
	;; if this fade level is zero, it should *stop* fading. 
	;; this is the most standard type of fade...fade out, do things, fade back in to 0.
	LDA fadeLevel
	CLC
	ADC #$05
	BEQ stopFading 
	LDA fadeLevel
	SEC
	SBC #$05
	BEQ stopFading
	JMP nevermindCheckingForPalLoop
	
stopFading:	
	;; it is at zero
	LDA fadeByte
	AND #%00100000 ;; is it a looper?
	BEQ checkForPalLoop
	JMP nevermindCheckingForPalLoop ;; yes, it is a looper
checkForPalLoop:
	;;no, it is not a looper
	LDA #$00
	STA fadeByte

	;;;; check for load data first
	;;=================
	
	LDA fadeSpeed
	AND #%10000000 ;; this is the bit, in the byte, that sees if we need to load data
	BNE needToLoadData 
	JMP noNeedToLoadData
needToLoadData:
	;;; yes, we need to load new data.


	;LoadChrData #GraphicsBank01, #$10, #$40, #$0, BckChr00
	;LoadBackgroundPalette BckPal00
	
	;;load the pointer info
	;LDA currentBank
	;STA prevBank
	;LDY #$16
	;JSR bankswitchY
	;;; now we can get the offset from the screen tables.
	;;;;;;; if type is 0, check NameTablePointers
		;;; if type is 1, check NameTablePointers_Map1
		;;; if type is 2, check NameTablePointers_Map2
	;LDA newScreen	
	;ASL			
	;TAX
	;LDA NameTablePointers_Map1+0,X
	;STA temp16
	;LDA NameTablePointers_Map2+1,X
	;STA temp16+1
	
	;LoadNametableData #$01, NT_Rm50, #$01, #$80
	;LoadAttributeData #$01, AT_Rm50, #$38, #$08

	;LDY prevBank
	;JSR bankswitchY
	
	LDA #$00
	STA fadeLevel
	LDA #$00
	STA fadeByte
	
noNeedToLoadData:

	;; Check to see if we load data during fade
	;;====================
	
	JMP doneWithFade
nevermindCheckingForPalLoop:
	
	LDA fadeByte
	AND #%00000011
	CMP temp
	BNE doneWithFade ;; haven't reached the end yet.
	;;; we've reached the last step
	;;; we need to check to see if that's it, or if it should pingpong background

	;; now check to see if we're done or we're going to pingpong
	LDA fadeSpeed
	AND #%01000000 ;; does it pingpong?
	BNE doPingPongFade
	LDA #$00
	STA fadeByte
	LDA #$01
	STA updatePalettes
	JMP doneWithFade
doPingPongFade:
	LDA fadeLevel
	BMI changeToFadeIn
	;; change to fade out
	LDA fadeByte
	AND #%10111111
	JMP pingPongDone
changeToFadeIn:
	LDA fadeByte
	ORA #%01000000
pingPongDone:
	STA fadeByte
	
	
dontChangeThisValue:

	
keepRunningFadeTimer:

doneWithFade:
	RTS
after setting these up along with the required ZPvars, you may now call fade using beginfade macro.

now, some parts of this script were left broken, simply because of .....reasons. so not everything from it does work in this state.

you MUST NOT use modes other than what is stated below (they work but produce unwanted effects.)
you also MUST ALWAYS call FADE_LIGHTEN after using FADE_DARKEN to restore the screen, othervise you will eventually run into issues.

to fade out, use:
BeginFade FADE_DARKEN, #$03, #$00, #$00, FADE_AND_HOLD, FADE_ONCE, #%01110111, #%01110111

to fade in AFTER fading out, use:
BeginFade FADE_LIGHTEN, #$03, #$00, #$00, FADE_AND_HOLD, FADE_ONCE, #%01110111, #%01110111

you may toy with the speed and palette attributes, but changing the fade_and_hold or fade_once will propably break it at this state.
also, sprite fading doesnt work, i never looked into it since i didnt want to use it.

on a side note, i fixed the issue with fading out the "illegal" gray color that joe decided we cant use because it breaks fading, so now you can use the missing dark gray and it fades out and in just fine.

on another side note, it is possible to just throw this in handlescreenloads.asm and have it fade screen transitions all the time, but trust me, you dont really want to do that. Especially if you dont have scrolling,
waiting 4-5 seconds between every screen move is not fun after 5 minutes, as cool as it looks.

there is also the fact that these macros are not really small, so repeatedly littering them into every function eats tons of space from bank14 really fast.
the way i do this in DS, is that i have it set on warp tiles, and in addition to that, i have a custom handler that checks newscreen on screen transitions and hardcoded screen numbers (stage changes) are triggering it.
you might want to do something similar to your game to reduce using unnecessary copies of the macro.


just for a third side note, i didn't actually sit on this code just to be an asshat or whatever (im pretty sure people cursed me to hell for not sharing) i just really think this shouldn't be used, and it's bending a rewrite on my own project too
the way this fader works is just insane, you literally spend half of your ZP on this code alone. but since it looks like some people REALLY want to use it, here it is. Godspeed with resource management.
1. I'm having problems with the loadpalettes asm code. "Routines\Basic\\DataLoadScripts\LoadPalettes.asm(30): Unknown label." with that line 30 code, for me, being "LDA bckPalFade,x"

2. Can this be used for the title screen only? I'm assuming so.
User avatar
Mugi
Posts: 781
Joined: Thu Dec 27, 2018 8:30 pm

Re: Screen Fading

Post by Mugi » Fri Mar 29, 2019 3:04 pm

bckPalFade is a variable you will have to set to ZP, if you get an error with it, you have it disabled there,

as far as using this for only to fade a title screen, yeah, it can be used for that, but enabling this code only to fade the title screen and nothing else makes even less sense than to use this code for fades in general.
i highly advice you not to.

at any rate, i did state it already that this is simply how i use this on my game, and since my engine is a mess, i have no idea if this even works in the vanilla engine or not.
if it doesnt, then it's out of my hands really. (by all means it should but i really have no time to test it for that.)
"what are you up to?" "Oh, not much... just... Parallaxing"
- Raftronaut
Post Reply