🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Any ideas for how to do a fading in and out effect in DOS?

Started by
7 comments, last by Winternight 2 years, 12 months ago

Hey all, how's it going?

I, as mentioned in my other posts, am making a DOS game, and I was wondering how I could do a fade in/fade out effect. The concept overall confuses me and I was wondering if anyone here could help me out.

In case you are wondering, I am compiling my code with Watcom C and TASM as my assembly compiler. Also, I am compiling these on a Windows 95 VMWare machine.

If more information is needed, I will gladly provide it!

Thank you so much to all who help me out!

-Ryan

Advertisement

The most important question, what graphic mode are you using?

Anything palette driven?

Then it's easy, just interpolate all color values down to zero (or whatever your RGB end color is).

GODDAMNEDITORTHISISNOTAWORDPROCESSORSTOPTHISDOUBLELINEBREAKCRAP

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Without knowing what graphics you are using can't really provide much specific. But 2 different approaches come to mind.

  1. Alpha blending. Just fade it from the normal solid (alpha = 1) to transparent (alpha = 0) over a period of time. Not sure how many colours you need to really make this look good (16bit seems like it should be fine, I can't recall clearly that far back. 24bit true colour is basically what is still commonly used).
  2. Dithering transparency. Basically for some amount of transparency you just skip drawing certain pixels of the source image entirely. For example if drawing a source image as 50% transparent, you would draw the first top-left pixel 0,0, then skip 1,0, draw 2,0, skip 3,0, etc. then on the next row you skip 0,1, draw 1,0, etc.
    This will work effectively even with very few colours, is faster, and also works in some places alpha just doesn't (and so is still found in some newer games, I think mostly ones that used deferred shading, although that concern is not relevant to what you are likely to do in DOS).

Modifying the hardware palette is definitely the way to if you can, but how smooth you can make it depends on the graphics mode. For example, in the CGA 4-color modes, the best you can do is to switch the high-intensity palette to the low-intensity palette, so just one intermediate between bright and black. At the other extreme of 256-color VGA, you have full 18-bit (6 bits per component) palette entries, so 62 intermediate levels between full brightness and black.

@a light breeze Ok so I managed to get it where it changes the color, and I even got it to fade out to black, but the issue is, it wont stop going to random colors after it fades to black, which is where my next issue starts…

Well, in that case you need to show some code.

Guesstimate: Your counter overflows and you re-enter from the very top of the RGB color space.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

@endurion Here is my FadeTransition code.


AFObeg	equ	[bp+4]
AFOcnt	equ	[bp+6+2]

proc FadeTransition_ near
    push    ebx
    push    ecx
    push    edx
	mov	ebp,esp
	push	ds
	push	esi
	push	edi

	push	ds		  ; get data segment into es
	pop	es
	mov	edx, offset _WorkPalette
	push	edx		  ; save offset of opal
	xor	ebx, ebx
	mov	ecx, 100h
	mov	eax, 1017h	  ; bios read dac registers function
	int	10h		  ; read the palette registers into opal
	pop	edi		  ; offset of opal, was in dx!
	mov	eax, AFObeg	  ; get offset of first palette byte to
	mov	ebx, 3		  ; be processed
	mul	ebx
	add	edi, eax		  ; adjust offset into opal
	mov	eax, AFOcnt	  ; find the number of bytes to be processed
	mov	ebx, 3
	mul	ebx		  ; leave it in ax
	mov	ecx, 64		  ; 64 passes through fade loop
o_fade_loop:
	push	ecx		  ; save the fade loop counter
	push	edi		  ; save offset of first byte processed in
	mov	bl, cl		  ; we'll use the pass number as a threshold
	mov	ecx, eax		  ; load number of bytes to process into cx
o_pal_cmp_loop:
	cmp	bl, es:[edi]	  ; start decrementing when palette value
	jnz	o_no_dec	  ; is equal loop count (it will stay equal
	dec	BYTE PTR es:[edi]  ; to loop count for the rest of this pass)
o_no_dec:
	inc	edi
	loop	o_pal_cmp_loop	    ; do the next byte

	mov	ebx, esp		    ; need the stack pointer for a moment
	mov	di, ss:[ebx]	    ; restore offset into pal without popping
	mov	ecx, AFOcnt	    ; number of triplets to process
	push	eax		    ; need to use ax for port i/o

	    mov edx, 03DAh		; CRT controller input status 1 register
o_vbi_1:
		in al, dx		    ; watch vertical blanking bit
		test al,08h		    ; wait for it to clear to make sure
		jnz o_vbi_1		    ; we're not in a blanking interval
o_vbi_2:
		in al, dx		    ; now wait for the start of the
		test al,08h		    ; next blanking interval
		jz o_vbi_2

	mov	ah, AFObeg ; get first register to process into ah
	mov	dx, 03c8h	    ; DAC palette index register
o_pal_load_loop:
	mov	al, ah		    ; get next palette number to write
	out	dx, al		    ; write the register number to the dac
	inc	dx		    ; address dac data register
	mov	al, BYTE PTR es:[di] ; get first byte of triplet
	out	dx, al		     ; write it to the dac data register
	inc	edi		     ; point to second byte
	mov	al, BYTE PTR es:[di] ; get second byte of triplet
	out	dx, al		     ; write it to the dac data register
	inc	edi		     ; point to third byte
	mov	al, BYTE PTR es:[di] ; get third byte of triplet
	out	dx, al		     ; write it to the dac data register
	inc	edi		     ; point to first byte of next triplet
	dec	edx		     ; address the dac index register
	inc	ah		     ; point to next palette register
	loop	o_pal_load_loop	     ; process next triplet

	pop	eax		  ; restore ax
	pop	edi		  ; restore the offset into pal
	pop	ecx		  ; restore the fade loop counter
	loop	o_fade_loop	  ; do the next pass through the fade loop



	pop	di
	pop	si
	pop	ds
	pop	bp
	ret
    endp

I am pretty sure that is what the issue is, but I am not very good at using assembly, and at the same time, I am trying to convert 16 bit Borland Assembly to 32 bit Watcom assembly. (I found this old demo I had downloaded like 6 years ago on my computer, and it compiled with Borland, so I am surprised that it worked this much!)

Here is what I have so far:

The function is defined as

public AckFadeOut_

WorkPalette is defined as

extrn	_WorkPalette:byte

The C code I am using is

void FadeTransition(int Begin,int Count);

and I use it by doing

FadeTransition(0,255);

WorkPalette also has its own variable definition too, and it is defined as

UCHAR WorkPalette[768];

These are all the variables that I can think would be necessary… If you need more code, just let me know.

Here is a video of what it does to the game:

For anyone who is curious, this is a level select screen.

Also, thanks for your help!

I'm not sure if you're still looking for help, this post is almost a month old, but maybe I can help. MS-DOS and assembly was a long time ago for me, so you'll have to forgive me if I'm a bit rusty. First of all, you defined WorkPalette as 768 bytes, so I'm assuming you're using good ole' 320x200x256 VGA. “a light breeze” was correct that the old VGA RAMDAC's could display 6 bits per color channel (a maximum of 262,144 potential colors, 256 at a time.), however the color value was still represented as a full byte (even if only 6 bits counted). in your o_fade_loop: you only loop though 64 times. This should be a full 256 if you're subtracting 1 at a time. I also noticed you've got some extra pushes in that loop, that's most likely the cause of some serious stack problems. For every push there must be an equivalent pop. Too many pushes, and you've got a stack overflow. Too many pop's and your machine will explode. It's best to only use pushes and pops at the beginning and end of a procedure in order to save registers that you plan to modify, then restoring them before returning. Using them in a loop is generally a cause for serious headaches.

This topic is closed to new replies.

Advertisement