Untitled diff

Created Diff never expires
13 removals
891 lines
14 additions
892 lines
;Modded /VISUAL/SMOKE.ASM
;Original


;****************************************************************************
;****************************************************************************
;*
;*
;* SMOKE.ASM
;* SMOKE.ASM
;*
;*
;* Smoke effects generator.
;* Smoke effects generator.
;*
;*
;* 29.11.1992 - KJB
;* 29.11.1992 - KJB
;* 08.02.1993 - KJB - "air" smoke effects added.
;* 08.02.1993 - KJB - "air" smoke effects added.
;*
;*
;****************************************************************************
;****************************************************************************


OPTION M510 ;<<<<< MASM v5.10 <<<<<
OPTION M510 ;<<<<< MASM v5.10 <<<<<


PUBLIC MakeSmokeEffect
PUBLIC MakeSmokeEffect


PUBLIC ScanSmoke
PUBLIC ScanSmoke


EXTRN RandX:FAR
EXTRN RandX:FAR
EXTRN CalcGndHeight:FAR
EXTRN CalcGndHeight:FAR


EXTRN DrawSmoke:NEAR
EXTRN DrawSmoke:NEAR


EXTRN LastFrame:WORD
EXTRN LastFrame:WORD
EXTRN DeltaTime:WORD
EXTRN DeltaTime:WORD


;============================================================================
;============================================================================


INCLUDE VISDATA.INC
INCLUDE VISDATA.INC
INCLUDE PALETTES.INC
INCLUDE PALETTES.INC


INCLUDE \LIB8086\USEFUL.INC
INCLUDE \LIB8086\USEFUL.INC
;============================================================================
;============================================================================


DATA SEGMENT PARA PUBLIC 'DATA'
DATA SEGMENT PARA PUBLIC 'DATA'


NextSmokePtr DW OFFSET SmokeBuffer
NextSmokePtr DW OFFSET SmokeBuffer


TMP_SMOKE SMOKE <>
TMP_SMOKE SMOKE <>


;* init smoke effect switch
;* init smoke effect switch


InitSmoke DW InitCrater1 ;SMOKE_CRATER1
InitSmoke DW InitCrater1 ;SMOKE_CRATER1
DW InitCrater2 ;SMOKE_CRATER2
DW InitCrater2 ;SMOKE_CRATER2
DW InitCrater3 ;SMOKE_CRATER3
DW InitCrater3 ;SMOKE_CRATER3
DW InitBurning ;SMOKE_BURNING
DW InitBurning ;SMOKE_BURNING
DW InitKickUp ;SMOKE_KICK_UP
DW InitKickUp ;SMOKE_KICK_UP
DW InitAirExplo ;SMOKE_AIR_EXPLO
DW InitAirExplo ;SMOKE_AIR_EXPLO
DW InitAirTrail ;SMOKE_AIR_TRAIL
DW InitAirTrail ;SMOKE_AIR_TRAIL


;* control smoke switch
;* control smoke switch


CtrlSmoke DW CtrlNull ;STYPE_NULL
CtrlSmoke DW CtrlNull ;STYPE_NULL
DW CtrlGnd1 ;STYPE_GND1
DW CtrlGnd1 ;STYPE_GND1
DW CtrlAir1 ;STYPE_AIR1
DW CtrlAir1 ;STYPE_AIR1
DATA ENDS
DATA ENDS


;============================================================================
;============================================================================


SMOKEDATA SEGMENT PARA PUBLIC 'DATA'
SMOKEDATA SEGMENT PARA PUBLIC 'DATA'


;* cyclic buffer for smoke
;* cyclic buffer for smoke


SmokeBuffer LABEL SMOKE
SmokeBuffer LABEL SMOKE


SMOKE NUM_SMOKE DUP(<>)
SMOKE NUM_SMOKE DUP(<>)


SmokeBufEnd LABEL SMOKE
SmokeBufEnd LABEL SMOKE


SMOKEDATA ENDS
SMOKEDATA ENDS


;============================================================================
;============================================================================


VISCODE SEGMENT BYTE PUBLIC 'CODE'
VISCODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:VISCODE
ASSUME CS:VISCODE
ASSUME DS:DATA
ASSUME DS:DATA


;* MakeSmokeEffect
;* MakeSmokeEffect
;*
;*
;* pass: bx = smoke effect type (see VISDATA.INC)
;* pass: bx = smoke effect type (see VISDATA.INC)
;* si -> VIEWPOINT data block
;* si -> VIEWPOINT data block
;* ret : nothing
;* ret : nothing
;* kill: assume all
;* kill: assume all


MakeSmokeEffect PROC FAR
MakeSmokeEffect PROC FAR


;-----------------------
;-----------------------
;* copy viewpoint origin
;* copy viewpoint origin
;-----------------------
;-----------------------


mov ax,[si].VP_XSEC
mov ax,[si].VP_XSEC
mov TMP_SMOKE.SMOKE_XSEC,ax
mov TMP_SMOKE.SMOKE_XSEC,ax


mov ax,[si].VP_YSEC
mov ax,[si].VP_YSEC
mov TMP_SMOKE.SMOKE_YSEC,ax
mov TMP_SMOKE.SMOKE_YSEC,ax


mov ax,[si].VP_XFT
mov ax,[si].VP_XFT
mov TMP_SMOKE.SMOKE_XFT,ax
mov TMP_SMOKE.SMOKE_XFT,ax


mov ax,[si].VP_YFT
mov ax,[si].VP_YFT
mov TMP_SMOKE.SMOKE_YFT,ax
mov TMP_SMOKE.SMOKE_YFT,ax


mov ax,WORD PTR [si].VP_ZFT_LO
mov ax,WORD PTR [si].VP_ZFT_LO
mov WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax
mov WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax


mov ax,WORD PTR [si].VP_ZFT_HI
mov ax,WORD PTR [si].VP_ZFT_HI
mov WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,ax
mov WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,ax


;-------------------
;-------------------
;* init smoke effect
;* init smoke effect
;-------------------
;-------------------


call InitSmoke[bx]
call InitSmoke[bx]


ret
ret


MakeSmokeEffect ENDP
MakeSmokeEffect ENDP


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------


;* MakeSingleSmoke
;* MakeSingleSmoke
;*
;*
;* pass: NextSmokePtr
;* pass: NextSmokePtr
;* TMP_SMOKE data block
;* TMP_SMOKE data block
;* ret : NextSmokePtr
;* ret : NextSmokePtr
;* kill: assume all
;* kill: assume all


MakeSingleSmoke PROC NEAR
MakeSingleSmoke PROC NEAR


mov ax,SMOKEDATA
mov ax,SMOKEDATA
mov es,ax
mov es,ax


mov si,OFFSET TMP_SMOKE
mov si,OFFSET TMP_SMOKE
mov di,NextSmokePtr
mov di,NextSmokePtr
mov cx,SMOKE_REC_SIZE
mov cx,SMOKE_REC_SIZE


FAST_MOVE
FAST_MOVE


mov ax,DATA
mov ax,DATA
mov es,ax
mov es,ax


cmp di,OFFSET SmokeBufEnd ;end of buffer?
cmp di,OFFSET SmokeBufEnd ;end of buffer?
jb @F ;no ->
jb @F ;no ->


mov di,OFFSET SmokeBuffer ;wrap around
mov di,OFFSET SmokeBuffer ;wrap around


@@: mov NextSmokePtr,di
@@: mov NextSmokePtr,di


ret
ret


MakeSingleSmoke ENDP
MakeSingleSmoke ENDP


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------


;* RND_SMOKE_COL - set random smoke colour
;* RND_SMOKE_COL - set random smoke colour
;*
;*
;* pass: nothing
;* pass: nothing
;* ret : TMP_SMOKE.SMOKE_COL
;* ret : TMP_SMOKE.SMOKE_COL
;* kill: ax, flags
;* kill: ax, flags


RND_SMOKE_COL MACRO
RND_SMOKE_COL MACRO


call RandX
call RandX
and al,1
and al,1
add al,COL_SMOKE_GREY1
add al,COL_SMOKE_GREY1
mov TMP_SMOKE.SMOKE_COL,al
mov TMP_SMOKE.SMOKE_COL,al


ENDM
ENDM


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------


;* InitGnd1 - init ground smoke type 1 effects
;* InitGnd1 - init ground smoke type 1 effects
;*
;*
;* InitCrater1 - init smoke for SMOKE_CRATER1 effect
;* InitCrater1 - init smoke for SMOKE_CRATER1 effect
;* InitCrater2 - init smoke for SMOKE_CRATER2 effect
;* InitCrater2 - init smoke for SMOKE_CRATER2 effect
;* InitCrater3 - init smoke for SMOKE_CRATER3 effect
;* InitCrater3 - init smoke for SMOKE_CRATER3 effect
;* InitBurning - init smoke for SMOKE_BURNING effect
;* InitBurning - init smoke for SMOKE_BURNING effect
;* InitKickUp - init smoke for SMOKE_KICK_UP effect
;* InitKickUp - init smoke for SMOKE_KICK_UP effect
;*
;*
;* pass: si -> VIEWPOINT data block
;* pass: si -> VIEWPOINT data block
;* TMP_SMOKE
;* TMP_SMOKE
;* ret : TMP_SMOKE
;* ret : TMP_SMOKE
;* kill: assume all
;* kill: assume all


;---------------------------
;---------------------------
InitCrater1 LABEL NEAR
InitCrater1 LABEL NEAR
;---------------------------
;---------------------------


mov TMP_SMOKE.SMOKE_SIB_CNTR,0
mov TMP_SMOKE.SMOKE_SIB_CNTR,0


mov cx,1 ;number of additional smokes
mov cx,1 ;number of additional smokes


jmp InitGnd1
jmp InitGnd1


;---------------------------
;---------------------------
InitCrater2 LABEL NEAR
InitCrater2 LABEL NEAR
;---------------------------
;---------------------------


mov TMP_SMOKE.SMOKE_SIB_CNTR,0
mov TMP_SMOKE.SMOKE_SIB_CNTR,0


mov cx,3 ;number of additional smokes
mov cx,3 ;number of additional smokes


jmp InitGnd1
jmp InitGnd1


;---------------------------
;---------------------------
InitCrater3 LABEL NEAR
InitCrater3 LABEL NEAR
;---------------------------
;---------------------------


mov TMP_SMOKE.SMOKE_SIB_CNTR,0
mov TMP_SMOKE.SMOKE_SIB_CNTR,0


mov cx,7 ;number of additional smokes
mov cx,7 ;number of additional smokes


jmp InitGnd1
jmp InitGnd1


;---------------------------
;---------------------------
InitBurning LABEL NEAR
InitBurning LABEL NEAR
;---------------------------
;---------------------------


mov TMP_SMOKE.SMOKE_SIB_CNTR,10
mov TMP_SMOKE.SMOKE_SIB_CNTR,10


mov cx,9 ;number of additional smokes
mov cx,9 ;number of additional smokes


jmp InitGnd1
jmp InitGnd1


;---------------------------
;---------------------------
InitKickUp LABEL NEAR
InitKickUp LABEL NEAR
;---------------------------
;---------------------------


mov TMP_SMOKE.SMOKE_SIB_CNTR,0
mov TMP_SMOKE.SMOKE_SIB_CNTR,0


mov cx,3 ;number of additional smokes
mov cx,3 ;number of additional smokes


;---------------------------
;---------------------------
InitGnd1 PROC NEAR
InitGnd1 PROC NEAR
;---------------------------
;---------------------------


;------------------
;------------------
;* init first smoke (always at viewpoint datum)
;* init first smoke (always at viewpoint datum)
;------------------
;------------------


mov TMP_SMOKE.SMOKE_TYPE,STYPE_GND1
mov TMP_SMOKE.SMOKE_TYPE,STYPE_GND1


RND_SMOKE_COL
RND_SMOKE_COL


mov TMP_SMOKE.SMOKE_FLAGS,0
mov TMP_SMOKE.SMOKE_FLAGS,0


mov TMP_SMOKE.SMOKE_ZFINE,0
mov TMP_SMOKE.SMOKE_ZFINE,0


mov TMP_SMOKE.SMOKE_RFT,0
mov TMP_SMOKE.SMOKE_RFT,0


mov TMP_SMOKE.SMOKE_TIME,0
mov TMP_SMOKE.SMOKE_TIME,0


call RandX
call RandX
add ax,8 ;128
add ax,128
mov TMP_SMOKE.SMOKE_EXP_TIME,ax
mov TMP_SMOKE.SMOKE_EXP_TIME,ax


push cx
push cx
push si
push si
call MakeSingleSmoke
call MakeSingleSmoke
pop si
pop si
pop cx
pop cx


;------------------------
;------------------------
;* init additional smokes
;* init additional smokes
;------------------------
;------------------------


jcxz InitGnd1Exit ;no additional smokes ->
jcxz InitGnd1Exit ;no additional smokes ->


AddSmokeLoop: push cx
AddSmokeLoop: push cx


RND_SMOKE_COL
RND_SMOKE_COL


call RandX
call RandX
add ax,8;128
add ax,128
mov TMP_SMOKE.SMOKE_EXP_TIME,ax
mov TMP_SMOKE.SMOKE_EXP_TIME,ax


;* offset xft from origin (keep within sector)
;* offset xft from origin (keep within sector)


call RandX
call RandX
cbw
cbw
sar ax,1 ;-64ft .. +63ft offset
sar ax,1 ;-64ft .. +63ft offset
add ax,[si].VP_XFT
add ax,[si].VP_XFT
cmp ax,8191
cmp ax,8191
jle @F
jle @F
mov ax,8191
mov ax,8191
@@: cmp ax,-8192
@@: cmp ax,-8192
jge @F
jge @F
mov ax,-8192
mov ax,-8192
@@: mov TMP_SMOKE.SMOKE_XFT,ax
@@: mov TMP_SMOKE.SMOKE_XFT,ax


;* offset yft from origin (keep within sector)
;* offset yft from origin (keep within sector)


call RandX
call RandX
cbw
cbw
sar ax,1 ;-64ft .. +63ft offset
sar ax,1 ;-64ft .. +63ft offset
add ax,[si].VP_YFT
add ax,[si].VP_YFT
cmp ax,8191
cmp ax,8191
jle @F
jle @F
mov ax,8191
mov ax,8191
@@: cmp ax,-8192
@@: cmp ax,-8192
jge @F
jge @F
mov ax,-8192
mov ax,-8192
@@: mov TMP_SMOKE.SMOKE_YFT,ax
@@: mov TMP_SMOKE.SMOKE_YFT,ax


push si
push si
call MakeSingleSmoke
call MakeSingleSmoke
pop si
pop si


pop cx
pop cx


loop AddSmokeLoop
loop AddSmokeLoop


InitGnd1Exit: ret
InitGnd1Exit: ret


InitGnd1 ENDP
InitGnd1 ENDP


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------


;* InitAir1 - init air smoke type 1 effects
;* InitAir1 - init air smoke type 1 effects
;*
;*
;* InitAirExplo - init smoke for SMOKE_AIR_EXPLO effect
;* InitAirExplo - init smoke for SMOKE_AIR_EXPLO effect
;* InitAirTrail - init smoke for SMOKE_AIR_TRAIL effect
;* InitAirTrail - init smoke for SMOKE_AIR_TRAIL effect
;*
;*
;* pass: si -> VIEWPOINT data block
;* pass: si -> VIEWPOINT data block
;* TMP_SMOKE
;* TMP_SMOKE
;* ret : TMP_SMOKE
;* ret : TMP_SMOKE
;* kill: assume all
;* kill: assume all


;---------------------------
;---------------------------
InitAirExplo LABEL NEAR
InitAirExplo LABEL NEAR
;---------------------------
;---------------------------


mov cx,15 ;number of additional smokes
mov cx,15 ;number of additional smokes


jmp InitAir1
jmp InitAir1


;---------------------------
;---------------------------
InitAirTrail LABEL NEAR
InitAirTrail LABEL NEAR
;---------------------------
;---------------------------


mov cx,3 ;number of additional smokes
mov cx,3 ;number of additional smokes


;---------------------------
;---------------------------
InitAir1 PROC NEAR
InitAir1 PROC NEAR
;---------------------------
;---------------------------


push cx
push cx
push si
push si
call CalcGndHeight
call CalcGndHeight
pop si
pop si
pop cx
pop cx


mov bp,ax ;bp = ground height
mov bp,ax ;bp = ground height


;------------------
;------------------
;* init first smoke (always at viewpoint datum)
;* init first smoke (always at viewpoint datum)
;------------------
;------------------


mov TMP_SMOKE.SMOKE_TYPE,STYPE_AIR1
mov TMP_SMOKE.SMOKE_TYPE,STYPE_AIR1


RND_SMOKE_COL
RND_SMOKE_COL


mov TMP_SMOKE.SMOKE_FLAGS,0
mov TMP_SMOKE.SMOKE_FLAGS,0


mov TMP_SMOKE.SMOKE_ZFINE,0
mov TMP_SMOKE.SMOKE_ZFINE,0


mov TMP_SMOKE.SMOKE_RFT,0
mov TMP_SMOKE.SMOKE_RFT,0


mov TMP_SMOKE.SMOKE_TIME,0
mov TMP_SMOKE.SMOKE_TIME,0


mov TMP_SMOKE.SMOKE_SIB_CNTR,0
mov TMP_SMOKE.SMOKE_SIB_CNTR,0


call RandX
call RandX
add ax,8;128
add ax,128
mov TMP_SMOKE.SMOKE_EXP_TIME,ax
mov TMP_SMOKE.SMOKE_EXP_TIME,ax


call CheckAirPos
call CheckAirPos


push cx
push cx
push si
push si
push bp
push bp
call MakeSingleSmoke
call MakeSingleSmoke
pop bp
pop bp
pop si
pop si
pop cx
pop cx


;------------------------
;------------------------
;* init additional smokes
;* init additional smokes
;------------------------
;------------------------


jcxz InitAir1Exit ;no additional smokes ->
jcxz InitAir1Exit ;no additional smokes ->


AirSmokeLoop: push cx
AirSmokeLoop: push cx


RND_SMOKE_COL
RND_SMOKE_COL


call RandX
call RandX
add ax,8;128
add ax,128
mov TMP_SMOKE.SMOKE_EXP_TIME,ax
mov TMP_SMOKE.SMOKE_EXP_TIME,ax


;* offset xft from origin (keep within sector)
;* offset xft from origin (keep within sector)


call RandX
call RandX
cbw
cbw
sar ax,1 ;-64ft .. +63ft offset
sar ax,1 ;-64ft .. +63ft offset
add ax,[si].VP_XFT
add ax,[si].VP_XFT
cmp ax,8191
cmp ax,8191
jle @F
jle @F
mov ax,8191
mov ax,8191
@@: cmp ax,-8192
@@: cmp ax,-8192
jge @F
jge @F
mov ax,-8192
mov ax,-8192
@@: mov TMP_SMOKE.SMOKE_XFT,ax
@@: mov TMP_SMOKE.SMOKE_XFT,ax


;* offset yft from origin (keep within sector)
;* offset yft from origin (keep within sector)


call RandX
call RandX
cbw
cbw
sar ax,1 ;-64ft .. +63ft offset
sar ax,1 ;-64ft .. +63ft offset
add ax,[si].VP_YFT
add ax,[si].VP_YFT
cmp ax,8191
cmp ax,8191
jle @F
jle @F
mov ax,8191
mov ax,8191
@@: cmp ax,-8192
@@: cmp ax,-8192
jge @F
jge @F
mov ax,-8192
mov ax,-8192
@@: mov TMP_SMOKE.SMOKE_YFT,ax
@@: mov TMP_SMOKE.SMOKE_YFT,ax


;* offset zft from origin
;* offset zft from origin


call RandX
call RandX
cbw
cbw
sar ax,1 ;-64ft .. +63ft offset
sar ax,1 ;-64ft .. +63ft offset
cwd
cwd
add ax,WORD PTR [si].VP_ZFT_LO
add ax,WORD PTR [si].VP_ZFT_LO
adc dx,WORD PTR [si].VP_ZFT_HI
adc dx,WORD PTR [si].VP_ZFT_HI
jns @F
jns @F
xor ax,ax
xor ax,ax
xor dx,dx
xor dx,dx
@@: mov WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax
@@: mov WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax
mov WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,dx
mov WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,dx


call CheckAirPos
call CheckAirPos


push si
push si
push bp
push bp
call MakeSingleSmoke
call MakeSingleSmoke
pop bp
pop bp
pop si
pop si


pop cx
pop cx


loop AirSmokeLoop
loop AirSmokeLoop


InitAir1Exit: ret
InitAir1Exit: ret


InitAir1 ENDP
InitAir1 ENDP


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------


;* CheckAirPos - check air smoke does not penetrate ground
;* CheckAirPos - check air smoke does not penetrate ground
;*
;*
;* pass: TMP_SMOKE
;* pass: TMP_SMOKE
;* bp = ground height
;* bp = ground height
;* ret : TMP_SMOKE
;* ret : TMP_SMOKE
;* kill: ax, dx, flags
;* kill: ax, dx, flags


CheckAirPos PROC NEAR
CheckAirPos PROC NEAR


;* if zft < 65536 then
;* if zft < 65536 then
;*
;*
;* zdiff = zft - ground height
;* zdiff = zft - ground height
;*
;*
;* if zdiff < 0 then
;* if zdiff < 0 then
;* zft = ground height + 32
;* zft = ground height + 32
;* expand time = 128
;* expand time = 128
;* else
;* else
;* if zdiff < expand time / 4 then
;* if zdiff < expand time / 4 then
;* expand time = zdiff * 4
;* expand time = zdiff * 4
;* if expand time < 128 then
;* if expand time < 128 then
;* zft = ground height + 32
;* zft = ground height + 32
;* expand time = 128
;* expand time = 128
;* endif
;* endif
;* endif
;* endif
;* endif
;* endif
;* endif
;* endif


cmp WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0
cmp WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0
ja ExitAirPos
ja ExitAirPos


mov ax,WORD PTR TMP_SMOKE.SMOKE_ZFT_LO
mov ax,WORD PTR TMP_SMOKE.SMOKE_ZFT_LO
sub ax,bp
sub ax,bp


jb SetMinSize
jb SetMinSize


mov dx,TMP_SMOKE.SMOKE_EXP_TIME
mov dx,TMP_SMOKE.SMOKE_EXP_TIME


REPT 2
REPT 2
shr dx,1
shr dx,1
ENDM
ENDM


cmp ax,dx
cmp ax,dx
jae ExitAirPos
jae ExitAirPos


REPT 2
REPT 2
shl ax,1
shl ax,1
ENDM
ENDM


cmp ax,8;128
cmp ax,128
jae @F
jae @F


SetMinSize: mov ax,bp
SetMinSize: mov ax,bp
add ax,8;32
add ax,32


mov WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax
mov WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax


mov ax,8;128
mov ax,128


@@: mov TMP_SMOKE.SMOKE_EXP_TIME,ax
@@: mov TMP_SMOKE.SMOKE_EXP_TIME,ax


ExitAirPos: ret
ExitAirPos: ret


CheckAirPos ENDP
CheckAirPos ENDP


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------


;* ScanSmoke - scan smoke buffer and draw smoke
;* ScanSmoke - scan smoke buffer and draw smoke
;*
;*
;* pass: nothing
;* pass: nothing
;* ret : nothing
;* ret : nothing
;* kill: assume all
;* kill: assume all
;*
;*
;* note: Smoke circles are low priority objects and could possibly clog the
;* note: Smoke circles are low priority objects and could possibly clog the
;* object buffer. Therefore call this routine "later on" in the visual
;* object buffer. Therefore call this routine "later on" in the visual
;* drawing order.
;* drawing order.


ScanSmoke PROC NEAR
ScanSmoke PROC NEAR


;-----------
;-----------
;* scan loop
;* scan loop
;-----------
;-----------


mov cx,NUM_SMOKE
mov cx,NUM_SMOKE


mov si,OFFSET SmokeBuffer
mov si,OFFSET SmokeBuffer


mov ax,SMOKEDATA
mov ax,SMOKEDATA
mov ds,ax
mov ds,ax


SmokeLoop: cmp [si].SMOKE_TYPE,STYPE_NULL ;smoke active?
SmokeLoop: cmp [si].SMOKE_TYPE,STYPE_NULL ;smoke active?
jne SortSmoke ;yes ->
jne SortSmoke ;yes ->


NextSmoke: add si,SMOKE_REC_SIZE
NextSmoke: add si,SMOKE_REC_SIZE


loop SmokeLoop
loop SmokeLoop


mov ax,DATA
mov ax,DATA
mov ds,ax
mov ds,ax


ret
ret


;-----------------------------------
;-----------------------------------
;* copy smoke data into working copy
;* copy smoke data into working copy
;-----------------------------------
;-----------------------------------


SortSmoke: push cx ;store loop count
SortSmoke: push cx ;store loop count
push si ;store smoke ptr
push si ;store smoke ptr


mov di,OFFSET TMP_SMOKE
mov di,OFFSET TMP_SMOKE
mov cx,SMOKE_REC_SIZE
mov cx,SMOKE_REC_SIZE


FAST_MOVE
FAST_MOVE


mov ax,DATA
mov ax,DATA
mov ds,ax
mov ds,ax


;--------------
;--------------
;* update smoke
;* update smoke
;--------------
;--------------


mov bx,TMP_SMOKE.SMOKE_TYPE
mov bx,TMP_SMOKE.SMOKE_TYPE
call CtrlSmoke[bx]
call CtrlSmoke[bx]
jc @F ;smoke cleared ->
jc @F ;smoke cleared ->


;------------
;------------
;* draw smoke
;* draw smoke
;------------
;------------


mov si,OFFSET TMP_SMOKE
mov si,OFFSET TMP_SMOKE
call DrawSmoke
call DrawSmoke


;-----------------------------------
;-----------------------------------
;* copy smoke data from working copy
;* copy smoke data from working copy
;-----------------------------------
;-----------------------------------


@@: pop di ;smoke ptr
@@: pop di ;smoke ptr
push di
push di


mov cx,SMOKE_REC_SIZE
mov cx,SMOKE_REC_SIZE
mov si,OFFSET TMP_SMOKE
mov si,OFFSET TMP_SMOKE


mov ax,SMOKEDATA
mov ax,SMOKEDATA
mov es,ax
mov es,ax


FAST_MOVE
FAST_MOVE


mov ax,DATA
mov ax,DATA
mov es,ax
mov es,ax


;-------------------------------
;-------------------------------
;* prepare to re-enter scan loop
;* prepare to re-enter scan loop
;-------------------------------
;-------------------------------


mov ax,SMOKEDATA
mov ax,SMOKEDATA
mov ds,ax
mov ds,ax


pop si ;restore smoke ptr
pop si ;restore smoke ptr
pop cx ;restore loop count
pop cx ;restore loop count


jmp NextSmoke
jmp NextSmoke


ScanSmoke ENDP
ScanSmoke ENDP


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------


;* CtrlNull
;* CtrlNull
;*
;*
;* pass: nothing
;* pass: nothing
;* ret : cf = 1 = smoke cleared
;* ret : cf = 1 = smoke cleared
;* kill: nothing
;* kill: nothing


CtrlNull PROC NEAR
CtrlNull PROC NEAR


stc
stc
ret
ret


CtrlNull ENDP
CtrlNull ENDP


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------


;* CtrlGnd1 - control routine for ground smoke type 1
;* CtrlGnd1 - control routine for ground smoke type 1
;*
;*
;* pass: TMP_SMOKE
;* pass: TMP_SMOKE
;* ret : TMP_SMOKE
;* ret : TMP_SMOKE
;* cf = 0 = smoke ok
;* cf = 0 = smoke ok
;* cf = 1 = smoke cleared
;* cf = 1 = smoke cleared
;* kill: assume all (except cf)
;* kill: assume all (except cf)
;*
;*
;* note: Phase 1: Expand radius keeping base of smoke on crater base.
;* note: Phase 1: Expand radius keeping base of smoke on crater base.
;* Phase 2: Contract radius and drift upwards until radius is zero.
;* Phase 2: Contract radius and drift upwards until radius is zero.


CtrlGnd1 PROC NEAR
CtrlGnd1 PROC NEAR


;--------------
;--------------
;* update timer
;* update timer
;--------------
;--------------


mov ax,TMP_SMOKE.SMOKE_TIME
mov ax,TMP_SMOKE.SMOKE_TIME
add ax,LastFrame
add ax,LastFrame
mov TMP_SMOKE.SMOKE_TIME,ax
mov TMP_SMOKE.SMOKE_TIME,ax


;------------
;------------
;* sort phase
;* sort phase
;------------
;------------


mov dx,TMP_SMOKE.SMOKE_EXP_TIME
mov dx,TMP_SMOKE.SMOKE_EXP_TIME


cmp ax,dx ;expand phase?
cmp ax,dx ;expand phase?
jbe Gnd1Phase1 ;yes ->
jbe Gnd1Phase1 ;yes ->


sub ax,dx
sub ax,dx


shl dx,1 ;contract phase is double expand phase
shl dx,1 ;contract phase is double expand phase


cmp ax,dx ;contract phase?
cmp ax,dx ;contract phase?
jbe Gnd1Phase2 ;yes ->
jbe Gnd1Phase2 ;yes ->


;-------------------
;-------------------
;* end of smoke life
;* end of smoke life
;-------------------
;-------------------


mov TMP_SMOKE.SMOKE_TYPE,STYPE_NULL
mov TMP_SMOKE.SMOKE_TYPE,STYPE_NULL


stc ;cf = 1 = smoke cleared
stc ;cf = 1 = smoke cleared
ret
ret


;---------------------------
;---------------------------
Gnd1Phase1 LABEL NEAR ;expand radius
Gnd1Phase1 LABEL NEAR ;expand radius
;---------------------------
;---------------------------


REPT 3;2 ;radius = time / 4
REPT 2 ;radius = time / 4
shr ax,1
shr ax,1
ENDM
ENDM


mov dx,TMP_SMOKE.SMOKE_RFT
mov dx,TMP_SMOKE.SMOKE_RFT
mov TMP_SMOKE.SMOKE_RFT,ax
mov TMP_SMOKE.SMOKE_RFT,ax


;* reset base zft
;* reset base zft


sub WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,dx
sub WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,dx
sbb WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0
sbb WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0


;* set centre zft wrt radius
;* set centre zft wrt radius


add WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax
add WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax
adc WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0
adc WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0


clc ;cf = 0 = smoke ok
clc ;cf = 0 = smoke ok
ret
ret


;---------------------------
;---------------------------
Gnd1Phase2 LABEL NEAR ;contract radius and drift upwards
Gnd1Phase2 LABEL NEAR ;contract radius and drift upwards
;---------------------------
;---------------------------


;* reproduce sibling?
;* reproduce sibling?


test TMP_SMOKE.SMOKE_FLAGS,SFLG_REPRO ;already reproduced?
test TMP_SMOKE.SMOKE_FLAGS,SFLG_REPRO ;already reproduced?
_JNZ SkipRepro ;yes ->
_JNZ SkipRepro ;yes ->


cmp TMP_SMOKE.SMOKE_SIB_CNTR,0 ;reproduce any more?
cmp TMP_SMOKE.SMOKE_SIB_CNTR,0 ;reproduce any more?
_JE SkipRepro ;no ->
_JE SkipRepro ;no ->


;* reproduce
;* reproduce


push ax
push ax
push dx
push dx


dec TMP_SMOKE.SMOKE_SIB_CNTR
dec TMP_SMOKE.SMOKE_SIB_CNTR


push WORD PTR TMP_SMOKE.SMOKE_COL ;(col + flags)
push WORD PTR TMP_SMOKE.SMOKE_COL ;(col + flags)
push WORD PTR TMP_SMOKE.SMOKE_ZFT_LO
push WORD PTR TMP_SMOKE.SMOKE_ZFT_LO
push WORD PTR TMP_SMOKE.SMOKE_ZFT_HI
push WORD PTR TMP_SMOKE.SMOKE_ZFT_HI
push TMP_SMOKE.SMOKE_ZFINE
push TMP_SMOKE.SMOKE_ZFINE
push TMP_SMOKE.SMOKE_RFT
push TMP_SMOKE.SMOKE_RFT
push TMP_SMOKE.SMOKE_TIME
push TMP_SMOKE.SMOKE_TIME
push TMP_SMOKE.SMOKE_EXP_TIME
push TMP_SMOKE.SMOKE_EXP_TIME


mov ax,TMP_SMOKE.SMOKE_RFT
mov ax,TMP_SMOKE.SMOKE_RFT
sub WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax ;reset base zft
sub WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,ax ;reset base zft
sbb WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0
sbb WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0


RND_SMOKE_COL
RND_SMOKE_COL


mov TMP_SMOKE.SMOKE_FLAGS,0
mov TMP_SMOKE.SMOKE_FLAGS,0


mov TMP_SMOKE.SMOKE_ZFINE,0
mov TMP_SMOKE.SMOKE_ZFINE,0


mov TMP_SMOKE.SMOKE_RFT,0
mov TMP_SMOKE.SMOKE_RFT,0


mov TMP_SMOKE.SMOKE_TIME,0
mov TMP_SMOKE.SMOKE_TIME,0


call RandX
call RandX
add ax,8;128
add ax,128
mov TMP_SMOKE.SMOKE_EXP_TIME,ax
mov TMP_SMOKE.SMOKE_EXP_TIME,ax


call MakeSingleSmoke
call MakeSingleSmoke


pop TMP_SMOKE.SMOKE_EXP_TIME
pop TMP_SMOKE.SMOKE_EXP_TIME
pop TMP_SMOKE.SMOKE_TIME
pop TMP_SMOKE.SMOKE_TIME
pop TMP_SMOKE.SMOKE_RFT
pop TMP_SMOKE.SMOKE_RFT
pop TMP_SMOKE.SMOKE_ZFINE
pop TMP_SMOKE.SMOKE_ZFINE
pop WORD PTR TMP_SMOKE.SMOKE_ZFT_HI
pop WORD PTR TMP_SMOKE.SMOKE_ZFT_HI
pop WORD PTR TMP_SMOKE.SMOKE_ZFT_LO
pop WORD PTR TMP_SMOKE.SMOKE_ZFT_LO
pop WORD PTR TMP_SMOKE.SMOKE_COL ;(col + flags)
pop WORD PTR TMP_SMOKE.SMOKE_COL ;(col + flags)


or TMP_SMOKE.SMOKE_FLAGS,SFLG_REPRO
or TMP_SMOKE.SMOKE_FLAGS,SFLG_REPRO


pop dx
pop dx
pop ax
pop ax


SkipRepro: shr dx,1
SkipRepro: shr dx,1
shr ax,1
shr ax,1


sub dx,ax
sub dx,ax


REPT 3;2 ;radius = (expand time - time) / 4
REPT 2 ;radius = (expand time - time) / 4
shr dx,1
shr dx,1
ENDM
ENDM


mov TMP_SMOKE.SMOKE_RFT,dx
mov TMP_SMOKE.SMOKE_RFT,dx


;* drift upwards
;* drift upwards


mov ax,DeltaTime
mov ax,DeltaTime
xor dx,dx
xor dx,dx


REPT 6 ;climb rate = 32ft / sec (64 * bin frac)
REPT 6 ;climb rate = 32ft / sec (64 * bin frac)
shl ax,1
shl ax,1
rcl dx,1
rcl dx,1
ENDM
ENDM


add TMP_SMOKE.SMOKE_ZFINE,ax
add TMP_SMOKE.SMOKE_ZFINE,ax
add WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,dx
add WORD PTR TMP_SMOKE.SMOKE_ZFT_LO,dx
adc WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0
adc WORD PTR TMP_SMOKE.SMOKE_ZFT_HI,0


clc ;cf = 0 = smoke ok
clc ;cf = 0 = smoke ok
ret
ret


CtrlGnd1 ENDP
CtrlGnd1 ENDP


;----------------------------------------------------------------------------
;----------------------------------------------------------------------------


;* CtrlAir1 - control routine for air smoke type 1
;* CtrlAir1 - control routine for air smoke type 1
;*
;*
;* pass: TMP_SMOKE
;* pass: TMP_SMOKE
;* ret : TMP_SMOKE
;* ret : TMP_SMOKE
;* cf = 0 = smoke ok
;* cf = 0 = smoke ok
;* cf = 1 = smoke cleared
;* cf = 1 = smoke cleared
;* kill: assume all (except cf)
;* kill: assume all (except cf)
;*
;*
;* note: Phase 1: Expand radius.
;* note: Phase 1: Expand radius.
;* Phase 2: Contract radius.
;* Phase 2: Contract radius.


CtrlAir1 PROC NEAR
CtrlAir1 PROC NEAR


;--------------
;--------------
;* update timer
;* update timer
;--------------
;--------------


mov ax,TMP_SMOKE.SMOKE_TIME
mov ax,TMP_SMOKE.SMOKE_TIME
add ax,LastFrame
add ax,LastFrame
mov TMP_SMOKE.SMOKE_TIME,ax
mov TMP_SMOKE.SMOKE_TIME,ax


;------------
;------------
;* sort phase
;* sort phase
;------------
;------------


mov dx,TMP_SMOKE.SMOKE_EXP_TIME
mov dx,TMP_SMOKE.SMOKE_EXP_TIME


cmp ax,dx ;expand phase?
cmp ax,dx ;expand phase?
jbe Air1Phase1 ;yes ->
jbe Air1Phase1 ;yes ->


sub ax,dx
sub ax,dx


shl dx,1 ;contract phase is double expand phase
shl dx,1 ;contract phase is double expand phase


cmp ax,dx ;contract phase?
cmp ax,dx ;contract phase?
jbe Air1Phase2 ;yes ->
jbe Air1Phase2 ;yes ->


;-------------------
;-------------------
;* end of smoke life
;* end of smoke life
;-------------------
;-------------------


mov TMP_SMOKE.SMOKE_TYPE,STYPE_NULL
mov TMP_SMOKE.SMOKE_TYPE,STYPE_NULL


stc ;cf = 1 = smoke cleared
stc ;cf = 1 = smoke cleared
ret
ret


;---------------------------
;---------------------------
Air1Phase1 LABEL NEAR ;expand radius
Air1Phase1 LABEL NEAR ;expand radius
;---------------------------
;---------------------------


REPT 3;2 ;radius = time / 4
REPT 2 ;radius = time / 4
shr ax,1
shr ax,1
ENDM
ENDM


mov TMP_SMOKE.SMOKE_RFT,ax
mov TMP_SMOKE.SMOKE_RFT,ax


clc ;cf = 0 = smoke ok
clc ;cf = 0 = smoke ok
ret
ret


;---------------------------
;---------------------------
Air1Phase2 LABEL NEAR ;contract radius
Air1Phase2 LABEL NEAR ;contract radius
;---------------------------
;---------------------------


shr dx,1
shr dx,1
shr ax,1
shr ax,1


sub dx,ax
sub dx,ax


REPT 3;2 ;radius = (expand time - time) / 4
REPT 2 ;radius = (expand time - time) / 4
shr dx,1
shr dx,1
ENDM
ENDM


mov TMP_SMOKE.SMOKE_RFT,dx
mov TMP_SMOKE.SMOKE_RFT,dx


clc ;cf = 0 = smoke ok
clc ;cf = 0 = smoke ok
ret
ret


CtrlAir1 ENDP
CtrlAir1 ENDP


VISCODE ENDS
VISCODE ENDS


;============================================================================
;============================================================================


END
END