CnC_Red_Alert/WWFLAT32/MCGAPRIM/SHADOW.ASM

211 lines
6.4 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
; $Header: g:/library/source/rcs/./shadow.asm 1.9 1994/05/20 15:30:49 joe_bostic Exp $
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : LIBRARY *
;* *
;* File Name : SHADOW.ASM *
;* *
;* Programmer : Christopher Yates *
;* *
;* Last Update : February 28, 1995 [BG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* *
;* void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, GVPC dst, void *shadowbuff);
;* *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE "mcgaprim.inc"
INCLUDE ".\gbuffer.inc"
INCLUDE ".\keystruc.inc"
GLOBAL Shadow_Blit : NEAR
GLOBAL RealModePtr : DWORD
GLOBAL Hide_Mouse : NEAR
GLOBAL Show_Mouse : NEAR
CODESEG
; void Shadow_Blit(int xpix, int ypix, int width, int height, GVPC src, VBC dst, void *shadowbuff);
; Warning: Shadow_Blit appears to be relatively stupid, in that while it is
; optimized to perform word or dword blits, it only does so if the
; entire region is word or dword-sized. In other words, if you blit
; a region that is 200 pixels wide (clearly dword-sized), then it
; will use the dword loop. However, if you blit a region that is
; 201 pixels wide, the dumb thing will use the byte loop for the
; entire blit.
PROC Shadow_Blit C near
USES eax,ebx,ecx,edx,esi,edi
ARG x:DWORD
ARG y:DWORD
ARG width:DWORD
ARG height:DWORD
ARG srcpage:DWORD
ARG dstpage:DWORD
ARG shadow:DWORD
LOCAL modulo:DWORD ; Row modulo
LOCAL hidemouse:DWORD ; Was the mouse hidden?
LOCAL dwordwidth:DWORD
LOCAL bytewidth:DWORD
cld ; Always move forward.
mov [hidemouse],0 ; Presume mouse hasn't been hidden.
; Fetch the segment of the seenpage.
mov ebx,[dstpage]
mov ebx,[(GraphicViewPort ebx).GVPOffset]
; Determine if the mouse needs to be hidden at all. If this happens to be
; a shadow blit to non visible page (who knows why!?) then don't bother to
; hide the mouse since it isn't necessary.
; cmp ebx,0A0000h
; setne [BYTE PTR hidemouse] ; Flag that mouse need not be hidden.
; jne short ??itsok
mov esi,[RealModePtr]
cmp [(KeyboardType esi).MState],0
je short ??itsok
mov [hidemouse],1
call Hide_Mouse C ; Hides mouse again (just to be sure).
??itsok:
mov edi,[srcpage]
mov esi,[(GraphicViewPort edi).GVPOffset]
mov eax,[(GraphicViewPort edi).GVPWidth]
add eax,[(GraphicViewPort edi).GVPXAdd]
push eax ; save width+xadd for later calc
mov edx,[y]
mul edx
add eax,[x]
add esi,eax
; At this point, esi points to the source page and ebx points to the dest page
sub ebx,esi ; esi+ebx == dest page pointer
mov edi,[shadow] ; EDI points to shadow buffer.
mov ecx,[height] ; get the height of the window in cx
mov edx,[RealModePtr]
; Calculate the row add module.
pop eax ; restore width+xadd
sub eax,[width]
mov [modulo],eax
mov eax,[width]
shr eax,2
mov [dwordwidth],eax
mov eax,[width]
and eax,3
mov [bytewidth],eax
;---------------------------------------
; DOUBLE WORD shadow blit if possible.
;---------------------------------------
??dloop_top:
push ecx
mov ecx,[dwordwidth]
??lcontinue:
repe cmpsd ; check the entire row for changed longs
je short ??loop_top
; If this row would interfere with the mouse image, then hide it.
cmp [hidemouse],0
jnz short ??dok
mov eax,[(KeyboardType edx).MouseY]
sub eax,[(KeyboardType edx).MouseYHot]
cmp eax,[y]
jg short ??dok
add eax,[(KeyboardType edx).MouseHeight]
cmp eax,[y]
jb short ??dok
mov [hidemouse],1 ; Manual hide of the mouse.
call Hide_Mouse C
??dok:
mov eax,[esi-4]
mov [ebx+esi-4],eax ; Update destination page.
mov [edi-4],eax ; Update shadow buffer.
or ecx,ecx
jne short ??lcontinue
;---------------------------------------
; Row loop start for BYTES.
;---------------------------------------
??loop_top:
mov ecx,[bytewidth]
; Column loop start -- by bytes.
??continue:
repe cmpsb ; check the entire row for changed longs
je short ??done_x
; If this row would interfere with the mouse image, then hide it.
cmp [hidemouse],0
jnz short ??bok
mov eax,[(KeyboardType edx).MouseY]
sub eax,[(KeyboardType edx).MouseYHot]
cmp eax,[y]
jg short ??bok
add eax,[(KeyboardType edx).MouseHeight]
cmp eax,[y]
jl short ??bok
mov [hidemouse],1 ; Manual hide of the mouse.
call Hide_Mouse C
??bok:
mov al,[esi-1]
mov [ebx+esi-1],al ; Update destination page.
mov [edi-1],al ; Update shadow buffer.
or ecx,ecx
jne short ??continue
??done_x:
inc [y]
add esi,[modulo]
pop ecx
loop ??dloop_top
??fini:
; Re show the mouse if it was hidden by this routine.
cmp [hidemouse],0
je short ??reallyfini
call Show_Mouse C
??reallyfini:
ret
ENDP Shadow_Blit
END