CnC_Red_Alert/WIN32LIB/DRAWBUFF/STAMP.ASM

601 lines
15 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/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Westwood Library *
;* *
;* File Name : STAMP.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : August 23, 1993 *
;* *
;* Last Update : August 23, 1993 [JLB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE ".\drawbuff.inc"
INCLUDE ".\gbuffer.inc"
INCLUDE "stamp.inc"
global C Init_Stamps:near
global LastIconset:dword
global MapPtr:dword
global IconCount:dword
global IconSize:dword
global StampPtr:dword
DATASEG
LastIconset DD 0 ; Pointer to last iconset initialized.
StampPtr DD 0 ; Pointer to icon data.
IsTrans DD 0 ; Pointer to transparent icon flag table.
MapPtr DD 0 ; Pointer to icon map.
IconWidth DD 0 ; Width of icon in pixels.
IconHeight DD 0 ; Height of icon in pixels.
IconSize DD 0 ; Number of bytes for each icon data.
IconCount DD 0 ; Number of icons in the set.
EVEN
CODESEG
GLOBAL C Buffer_Draw_Stamp:near
GLOBAL C Buffer_Draw_Stamp_Clip:near
; 256 color icon system.
;***********************************************************
; INIT_STAMPS
;
; VOID cdecl Init_Stamps(VOID *icondata);
;
; This routine initializes the stamp data.
; Bounds Checking: NONE
;
;*
PROC Init_Stamps C near USES eax ebx edx edi
ARG icondata:DWORD
; Verify legality of parameter.
cmp [icondata],0
je short ??fini
; Don't initialize if already initialized to this set (speed reasons).
mov edi,[icondata]
cmp [LastIconset],edi
je short ??fini
mov [LastIconset],edi
; Record number of icons in set.
movzx eax,[(IControl_Type edi).Count]
mov [IconCount],eax
; Record width of icon.
movzx eax,[(IControl_Type edi).Width]
mov [IconWidth],eax
; Record height of icon.
movzx ebx,[(IControl_Type edi).Height]
mov [IconHeight],ebx
; Record size of icon (in bytes).
mul ebx
mov [IconSize],eax
; Record hard pointer to icon map data.
mov eax,[(IControl_Type edi).Map]
add eax,edi
mov [MapPtr],eax
??nomap:
; Record hard pointer to icon data.
mov eax,edi
add eax,[(IControl_Type edi).Icons]
mov [StampPtr],eax
; Record the transparent table.
mov eax,edi
add eax,[(IControl_Type edi).TransFlag]
mov [IsTrans],eax
??fini:
ret
ENDP Init_Stamps
;***********************************************************
;***********************************************************
; DRAW_STAMP
;
; VOID cdecl Buffer_Draw_Stamp(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap);
;
; This routine renders the icon at the given coordinate.
;
; The remap table is a 256 byte simple pixel translation table to use when
; drawing the icon. Transparency check is performed AFTER the remap so it is possible to
; remap valid colors to be invisible (for special effect reasons).
; This routine is fastest when no remap table is passed in.
;*
PROC Buffer_Draw_Stamp C near
ARG this_object:DWORD ; this is a member function
ARG icondata:DWORD ; Pointer to icondata.
ARG icon:DWORD ; Icon number to draw.
ARG x_pixel:DWORD ; X coordinate of icon.
ARG y_pixel:DWORD ; Y coordinate of icon.
ARG remap:DWORD ; Remap table.
LOCAL modulo:DWORD ; Modulo to get to next row.
LOCAL iwidth:DWORD ; Icon width (here for speedy access).
LOCAL doremap:BYTE ; Should remapping occur?
pushad
cmp [icondata],0
je ??out
; Initialize the stamp data if necessary.
mov eax,[icondata]
cmp [LastIconset],eax
je short ??noreset
call Init_Stamps C,eax
??noreset:
; Determine if the icon number requested is actually in the set.
; Perform the logical icon to actual icon number remap if necessary.
mov ebx,[icon]
cmp [MapPtr],0
je short ??notmap
mov edi,[MapPtr]
mov bl,[edi+ebx]
??notmap:
cmp ebx,[IconCount]
jae ??out
mov [icon],ebx ; Updated icon number.
; If the remap table pointer passed in is NULL, then flag this condition
; so that the faster (non-remapping) icon draw loop will be used.
cmp [remap],0
setne [doremap]
; Get pointer to position to render icon. EDI = ptr to destination page.
mov ebx,[this_object]
mov edi,[(GraphicViewPort ebx).GVPOffset]
mov eax,[(GraphicViewPort ebx).GVPWidth]
add eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPPitch]
push eax ; save viewport full width for lower
mul [y_pixel]
add edi,eax
add edi,[x_pixel]
; Determine row modulo for advancing to next line.
pop eax ; retrieve viewport width
sub eax,[IconWidth]
mov [modulo],eax
; Setup some working variables.
mov ecx,[IconHeight] ; Row counter.
mov eax,[IconWidth]
mov [iwidth],eax ; Stack copy of byte width for easy BP access.
; Fetch pointer to start of icon's data. ESI = ptr to icon data.
mov eax,[icon]
mul [IconSize]
mov esi,[StampPtr]
add esi,eax
; Determine whether simple icon draw is sufficient or whether the
; extra remapping icon draw is needed.
cmp [BYTE PTR doremap],0
je short ??istranscheck
;************************************************************
; Complex icon draw -- extended remap.
; EBX = Palette pointer (ready for XLAT instruction).
; EDI = Pointer to icon destination in page.
; ESI = Pointer to icon data.
; ECX = Number of pixel rows.
;;; mov edx,[remap]
mov ebx,[remap]
xor eax,eax
??xrowloop:
push ecx
mov ecx,[iwidth]
??xcolumnloop:
lodsb
;;; mov ebx,edx
;;; add ebx,eax
;;; mov al,[ebx] ; New real color to draw.
xlatb
or al,al
jz short ??xskip1 ; Transparency skip check.
mov [edi],al
??xskip1:
inc edi
loop ??xcolumnloop
pop ecx
add edi,[modulo]
loop ??xrowloop
jmp short ??out
;************************************************************
; Check to see if transparent or generic draw is necessary.
??istranscheck:
mov ebx,[IsTrans]
add ebx,[icon]
cmp [BYTE PTR ebx],0
jne short ??rowloop
;************************************************************
; Fast non-transparent icon draw routine.
; ES:DI = Pointer to icon destination in page.
; DS:SI = Pointer to icon data.
; CX = Number of pixel rows.
mov ebx,ecx
shr ebx,2
mov edx,[modulo]
mov eax,[iwidth]
shr eax,2
??loop1:
mov ecx,eax
rep movsd
add edi,edx
mov ecx,eax
rep movsd
add edi,edx
mov ecx,eax
rep movsd
add edi,edx
mov ecx,eax
rep movsd
add edi,edx
dec ebx
jnz ??loop1
jmp short ??out
;************************************************************
; Transparent icon draw routine -- no extended remap.
; ES:DI = Pointer to icon destination in page.
; DS:SI = Pointer to icon data.
; CX = Number of pixel rows.
??rowloop:
push ecx
mov ecx,[iwidth]
??columnloop:
lodsb
or al,al
jz short ??skip1 ; Transparency check.
mov [edi],al
??skip1:
inc edi
loop ??columnloop
pop ecx
add edi,[modulo]
loop ??rowloop
; Cleanup and exit icon drawing routine.
??out:
popad
ret
ENDP Buffer_Draw_Stamp
;***********************************************************
; DRAW_STAMP_CLIP
;
; VOID cdecl MCGA_Draw_Stamp_Clip(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap, LONG min_x, LONG min_y, LONG max_x, LONG max_y);
;
; This routine renders the icon at the given coordinate.
;
; The remap table is a 256 byte simple pixel translation table to use when
; drawing the icon. Transparency check is performed AFTER the remap so it is possible to
; remap valid colors to be invisible (for special effect reasons).
; This routine is fastest when no remap table is passed in.
;*
PROC Buffer_Draw_Stamp_Clip C near
ARG this_object:DWORD ; this is a member function
ARG icondata:DWORD ; Pointer to icondata.
ARG icon:DWORD ; Icon number to draw.
ARG x_pixel:DWORD ; X coordinate of icon.
ARG y_pixel:DWORD ; Y coordinate of icon.
ARG remap:DWORD ; Remap table.
ARG min_x:DWORD ; Clipping rectangle boundary
ARG min_y:DWORD ; Clipping rectangle boundary
ARG max_x:DWORD ; Clipping rectangle boundary
ARG max_y:DWORD ; Clipping rectangle boundary
LOCAL modulo:DWORD ; Modulo to get to next row.
LOCAL iwidth:DWORD ; Icon width (here for speedy access).
LOCAL skip:DWORD ; amount to skip per row of icon data
LOCAL doremap:BYTE ; Should remapping occur?
pushad
cmp [icondata],0
je ??out2
; Initialize the stamp data if necessary.
mov eax,[icondata]
cmp [LastIconset],eax
je short ??noreset2
call Init_Stamps C,eax
??noreset2:
; Determine if the icon number requested is actually in the set.
; Perform the logical icon to actual icon number remap if necessary.
mov ebx,[icon]
cmp [MapPtr],0
je short ??notmap2
mov edi,[MapPtr]
mov bl,[edi+ebx]
??notmap2:
cmp ebx,[IconCount]
jae ??out2
mov [icon],ebx ; Updated icon number.
; Setup some working variables.
mov ecx,[IconHeight] ; Row counter.
mov eax,[IconWidth]
mov [iwidth],eax ; Stack copy of byte width for easy BP access.
; Fetch pointer to start of icon's data. ESI = ptr to icon data.
mov eax,[icon]
mul [IconSize]
mov esi,[StampPtr]
add esi,eax
; Update the clipping window coordinates to be valid maxes instead of width & height
; , and change the coordinates to be window-relative
mov ebx,[min_x]
add [max_x],ebx
add [x_pixel],ebx ; make it window-relative
mov ebx,[min_y]
add [max_y],ebx
add [y_pixel],ebx ; make it window-relative
; See if the icon is within the clipping window
; First, verify that the icon position is less than the maximums
mov ebx,[x_pixel]
cmp ebx,[max_x]
jge ??out2
mov ebx,[y_pixel]
cmp ebx,[max_y]
jge ??out2
; Now verify that the icon position is >= the minimums
add ebx,[IconHeight]
cmp ebx,[min_y]
jle ??out2
mov ebx,[x_pixel]
add ebx,[IconWidth]
cmp ebx,[min_x]
jle ??out2
; Now, clip the x, y, width, and height variables to be within the
; clipping rectangle
mov ebx,[x_pixel]
cmp ebx,[min_x]
jge ??nominxclip
; x < minx, so must clip
mov ebx,[min_x]
sub ebx,[x_pixel]
add esi,ebx ; source ptr += (minx - x)
sub [iwidth],ebx ; icon width -= (minx - x)
mov ebx,[min_x]
mov [x_pixel],ebx
??nominxclip:
mov eax,[IconWidth]
sub eax,[iwidth]
mov [skip],eax
; Check for x+width > max_x
mov eax,[x_pixel]
add eax,[iwidth]
cmp eax,[max_x]
jle ??nomaxxclip
; x+width is greater than max_x, so must clip width down
mov eax,[iwidth] ; eax = old width
mov ebx,[max_x]
sub ebx,[x_pixel]
mov [iwidth],ebx ; iwidth = max_x - xpixel
sub eax,ebx
add [skip],eax ; skip += (old width - iwidth)
??nomaxxclip:
; check if y < miny
mov eax,[min_y]
cmp eax,[y_pixel] ; if(miny <= y_pixel), no clip needed
jle ??nominyclip
sub eax,[y_pixel]
sub ecx,eax ; height -= (miny - y)
mul [IconWidth]
add esi,eax ; icon source ptr += (width * (miny - y))
mov eax,[min_y]
mov [y_pixel],eax ; y = miny
??nominyclip:
; check if (y+height) > max y
mov eax,[y_pixel]
add eax,ecx
cmp eax,[max_y] ; if (y + height <= max_y), no clip needed
jle ??nomaxyclip
mov ecx,[max_y] ; height = max_y - y_pixel
sub ecx,[y_pixel]
??nomaxyclip:
; If the remap table pointer passed in is NULL, then flag this condition
; so that the faster (non-remapping) icon draw loop will be used.
cmp [remap],0
setne [doremap]
; Get pointer to position to render icon. EDI = ptr to destination page.
mov ebx,[this_object]
mov edi,[(GraphicViewPort ebx).GVPOffset]
mov eax,[(GraphicViewPort ebx).GVPWidth]
add eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPPitch]
push eax ; save viewport full width for lower
mul [y_pixel]
add edi,eax
add edi,[x_pixel]
; Determine row modulo for advancing to next line.
pop eax ; retrieve viewport width
sub eax,[iwidth]
mov [modulo],eax
; Determine whether simple icon draw is sufficient or whether the
; extra remapping icon draw is needed.
cmp [BYTE PTR doremap],0
je short ??istranscheck2
;************************************************************
; Complex icon draw -- extended remap.
; EBX = Palette pointer (ready for XLAT instruction).
; EDI = Pointer to icon destination in page.
; ESI = Pointer to icon data.
; ECX = Number of pixel rows.
mov ebx,[remap]
xor eax,eax
??xrowloopc:
push ecx
mov ecx,[iwidth]
??xcolumnloopc:
lodsb
xlatb
or al,al
jz short ??xskip1c ; Transparency skip check.
mov [edi],al
??xskip1c:
inc edi
loop ??xcolumnloopc
pop ecx
add edi,[modulo]
add esi,[skip]
loop ??xrowloopc
jmp short ??out2
;************************************************************
; Check to see if transparent or generic draw is necessary.
??istranscheck2:
mov ebx,[IsTrans]
add ebx,[icon]
cmp [BYTE PTR ebx],0
jne short ??rowloopc
;************************************************************
; Fast non-transparent icon draw routine.
; ES:DI = Pointer to icon destination in page.
; DS:SI = Pointer to icon data.
; CX = Number of pixel rows.
mov ebx,ecx
mov edx,[modulo]
mov eax,[iwidth]
;
; Optimise copy by dword aligning the destination
;
??loop1c:
push eax
rept 3
test edi,3
jz ??aligned
movsb
dec eax
jz ??finishedit
endm
??aligned:
mov ecx,eax
shr ecx,2
rep movsd
mov ecx,eax
and ecx,3
rep movsb
??finishedit:
add edi,edx
add esi,[skip]
pop eax
dec ebx
jnz ??loop1c
jmp short ??out2
;************************************************************
; Transparent icon draw routine -- no extended remap.
; ES:DI = Pointer to icon destination in page.
; DS:SI = Pointer to icon data.
; CX = Number of pixel rows.
??rowloopc:
push ecx
mov ecx,[iwidth]
??columnloopc:
lodsb
or al,al
jz short ??skip1c ; Transparency check.
mov [edi],al
??skip1c:
inc edi
loop ??columnloopc
pop ecx
add edi,[modulo]
add esi,[skip]
loop ??rowloopc
; Cleanup and exit icon drawing routine.
??out2:
popad
ret
ENDP Buffer_Draw_Stamp_Clip
END