I tried writing a fade out function for my MS-DOS game in assembly. The function works, but however, it keeps looping endlessly for some reason, and I can not figure out why it wont stop doing so.
Here is what I have:
AFObeg equ [bp+4]
AFOcnt equ [bp+4+2]
proc FadeOut_ 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 da21c 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 edi
pop esi
pop ds
pop ebp
ret
endp ;end of the fade out function
This is the result of the effect tested out on my (very poorly made) level select screen. The effect works to an extent, but when it fades out, it does not stop the fade out, but it restarts the fading out process, and it keeps on looping forever.
Please let me know what yall's thoughts are about how I could fix the issue. Any help is greatly appreciated.
I had asked this in a previous question, but it kinda died out…
I also asked the question on another website.