; ; 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 . ; ; $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