I am making a game with C and assembly for MS-DOS (I am planning to distribute the game with DOSBox or my own modification thereof). I large portions of the graphics code are in assembly, which is a language I am weaker in, but I saw it as something that was convenient to use due to its ability to change things to such a nitty-gritty level (down to things like the graphical palette and such).
However, I am basing my code off of a fade out function that I found from some old source code that was in 16 bit assembly, and I am trying to convert it to 32 bit assembly.
I got the code to work, but however, it keeps looping repeatedly instead of continuing the code.
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
If anyone has any more questions, I will gladly answer them.
Edit: for those of you wondering what the original code looked like, here you go:
AFObeg equ [bp+ABASE]
AFOcnt equ [bp+ABASE+2]
PBEGIN _FadeOut
push bp
mov bp,sp
push ds
push si
push di
push ds ; get data segment into es
pop es
mov dx, offset DGROUP:_WorkPalette
push dx ; save offset of opal
xor bx, bx
mov cx, 100h
mov ax, 1017h ; bios read dac registers function
int 10h ; read the palette registers into opal
pop di ; offset of opal, was in dx!
mov ax, AFObeg ; get offset of first palette byte to
mov bx, 3 ; be processed
mul bx
add di, ax ; adjust offset into opal
mov ax, AFOcnt ; find the number of bytes to be processed
mov bx, 3
mul bx ; leave it in ax
mov cx, 64 ; 64 passes through fade loop
o_fade_loop:
push cx ; save the fade loop counter
push di ; save offset of first byte processed in
mov bl, cl ; we'll use the pass number as a threshold
mov cx, ax ; load number of bytes to process into cx
o_pal_cmp_loop:
cmp bl, es:[di] ; start decrementing when palette value
jnz o_no_dec ; is equal loop count (it will stay equal
dec BYTE PTR es:[di] ; to loop count for the rest of this pass)
o_no_dec:
inc di
loop o_pal_cmp_loop ; do the next byte
mov bx, sp ; need the stack pointer for a moment
mov di, ss:[bx] ; restore offset into pal without popping
mov cx, AFOcnt ; number of triplets to process
push ax ; need to use ax for port i/o
mov dx, 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, BYTE PTR 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 di ; 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 di ; 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 di ; point to first byte of next triplet
dec dx ; address the dac index register
inc ah ; point to next palette register
loop o_pal_load_loop ; process next triplet
pop ax ; restore ax
pop di ; restore the offset into pal
pop cx ; 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
_FadeOut endp
And here is the macro ET.MAC file where things like ABASE are defined
; MACRO FILE FOR EGA320 LIBRARY
IFDEF _ML
%OUT LARGE MODEL
PBEGIN MACRO L
PUBLIC L
L PROC FAR
ENDM
PEXTRN MACRO L
EXTRN L:FAR
ENDM
ABASE EQU 6 ;BASE STACK PTR UPON PROCEDURE ENTRY
ENDIF
IFDEF _MC
PBEGIN MACRO L
PUBLIC L
L PROC NEAR
ENDM
PEXTRN MACRO L
EXTRN L:NEAR
ENDM
ABASE EQU 4 ;BASE STACK PTR UPON PROCEDURE ENTRY
%OUT COMPACT MODEL
ENDIF
XMOV MACRO A,B
PUSH B ;XFER SOURCE
POP A ; TO DEST.
ENDM
GEN MACRO OP,ARG
IRP X,<ARG>
OP X
ENDM
ENDM
XSTM MACRO S,O,D
MOV WORD PTR D,O
MOV WORD PTR D+2,S
ENDM
But to avoid using the file, I have switched over to just changing the value of ABASE to 4 or 6, but they both still give a relatively similar result.