211 lines
6.4 KiB
NASM
211 lines
6.4 KiB
NASM
;
|
||
; 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
|
||
|
||
|