| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662 |
- ;
- ; 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 A S S O C I A T E S **
- ;***************************************************************************
- ;* *
- ;* Project Name : Westwood 32 bit Library *
- ;* *
- ;* File Name : BITBLIT.ASM *
- ;* *
- ;* Programmer : Philip W. Gorrow *
- ;* *
- ;* Start Date : December 12, 1995 *
- ;* *
- ;* *
- ;*-------------------------------------------------------------------------*
- ;* Functions: *
- ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- IDEAL
- P386
- MODEL USE32 FLAT
- LOCALS ??
- INCLUDE "drawbuff.inc"
- INCLUDE "gbuffer.inc"
- INCLUDE "shape.inc"
- INCLUDE ".\mouse.inc"
- GLOBAL C LCW_Uncompress:NEAR
- GLOBAL C Get_Shape_Uncomp_Size :NEAR
- GLOBAL C Get_Shape_Width :NEAR
- GLOBAL C Get_Shape_Original_Height :NEAR
- GLOBAL _ShapeBuffer :DWORD
- CODESEG
- ;***************************************************************************
- ;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer *
- ;* *
- ;* INPUT: MouseClass * - pointer to mouse class data *
- ;* GraphicBufferClass * - screen to draw the mouse on *
- ;* int x - x position to store the mouse at *
- ;* int y - y position to store the mouse at *
- ;* int store - whether to store buffer or save *
- ;* *
- ;* OUTPUT: none *
- ;* *
- ;* Note: The x and y that this routine expects to receive are based on *
- ;* the mouse cursor position. This routine automatically adjusts *
- ;* for hot spot, so that adjustment should not be made prior to *
- ;* this point. *
- ;* *
- ;* PROTO: void Mouse_Shadow_Buffer(GraphicBufferClass *src/dest, *
- ;* void *buffer
- ;* int x_pixel, *
- ;* int y_pixel, *
- ;* int store); *
- ;* *
- ;* HISTORY: *
- ;* 10/27/1994 PWG : Created. *
- ;*=========================================================================*
- GLOBAL C Mouse_Shadow_Buffer:NEAR
- PROC Mouse_Shadow_Buffer C NEAR
- USES eax,ebx,ecx,edx,edi,esi
- ARG this: DWORD
- ARG src_dst_obj: DWORD
- ARG buffer:DWORD
- ARG x: DWORD
- ARG y: DWORD
- ARG hotx: DWORD
- ARG hoty: DWORD
- ARG store: DWORD
- local x0: dword
- local y0: dword
- local x1: dword
- local y1: dword
- local buffx0: dword
- local buffy0: dword
- ;*=========================================================================*
- ; Direction flag must be forward in this routine.
- ;*=========================================================================*
- cld
- ;*===================================================================
- ;* Copy of X, Y, Width and Height into local registers
- ;*===================================================================
- mov esi, [this] ; get offset to mouse data
- mov edi, [src_dst_obj] ; get offset to mouse data
- mov eax, [x]
- mov ebx, [y]
- sub eax, [hotx]
- sub ebx, [hoty]
- mov [x0], eax
- mov [y0], ebx
- add eax, [(MouseType esi).CursorWidth]
- add ebx, [(MouseType esi).CursorHeight]
- mov [x1], eax
- mov [y1], ebx
- mov [buffx0], 0
- mov eax, [buffer]
- mov [buffy0], eax
- ;*===================================================================
- ;* Bounds check source X.
- ;*===================================================================
- xor eax, eax
- xor edx, edx
- mov ecx, [x0]
- mov ebx, [x1]
- shld eax, ecx, 1
- shld edx, ebx, 1
- mov ecx, [x0]
- mov ebx, [x1]
- sub ecx, [(GraphicViewPort edi).GVPWidth]
- sub ebx, [(GraphicViewPort edi).GVPWidth]
- dec ecx
- dec ebx
- shld eax, ecx, 1
- shld edx, ebx, 1
- mov ecx, [y0]
- mov ebx, [y1]
- shld eax, ecx, 1
- shld edx, ebx, 1
- mov ecx, [y0]
- mov ebx, [y1]
- sub ecx, [(GraphicViewPort edi).GVPHeight]
- sub ebx, [(GraphicViewPort edi).GVPHeight]
- dec ecx
- dec ebx
- shld eax, ecx, 1
- shld edx, ebx, 1
- xor al, 5
- xor dl, 5
- mov ah, al
- test dl, al
- jnz ??out
- or al, dl
- jz ??not_clip
- test ah, 1000b
- jz ??scr_left_ok
- mov ebx, [x0]
- neg ebx
- mov [buffx0], ebx
- mov [x0], 0
- ??scr_left_ok:
- test ah, 0010b
- jz ??scr_bottom_ok
- mov ebx, [y0]
- neg ebx
- imul ebx, [(MouseType esi).CursorWidth]
- add [buffy0], ebx
- mov [y0], 0
- ??scr_bottom_ok:
- test dl, 0100b
- jz ??scr_right_ok
- mov eax, [(GraphicViewPort edi).GVPWidth] ; get width into register
- mov [x1], eax
- ??scr_right_ok:
- test dl, 0001b
- jz ??not_clip
- mov eax, [(GraphicViewPort edi).GVPHeight] ; get width into register
- mov [y1], eax
- ??not_clip:
- ;*===================================================================
- ;* Get the offset into the screen.
- ;*===================================================================
- mov eax, [y0]
- mov edx, [(GraphicViewPort edi).GVPWidth]
- add edx, [(GraphicViewPort edi).GVPXAdd]
- add edx, [(GraphicViewPort edi).GVPPitch]
- imul eax, edx
- add eax, [x0]
- mov edi, [(GraphicViewPort edi).GVPOffset]
- add edi, eax
- ;*===================================================================
- ;* Adjust the source for the top clip.
- ;*===================================================================
- mov ebx, [(MouseType esi).CursorWidth] ; turn this into an offset
- mov esi, [buffy0] ; edx points to source
- add esi, [buffx0] ; plus clipped lines
- ;*===================================================================
- ;* Calculate the bytes per row add value
- ;*===================================================================
- mov eax, [x1]
- mov ecx, [y1]
- sub eax, [x0]
- jle ??out
- sub ecx, [y0]
- jle ??out
- sub edx, eax
- sub ebx, eax
- push ebp
- cmp [store], 1 ; are we storing page?
- je ??store_entry ; if so go to store
- ;*===================================================================
- ;* Handle restoring the buffer to the visible page
- ;*===================================================================
- mov ebp, ecx
- ??restore_loop:
- mov ecx, eax ; get number to really write
- rep movsb ; store them into the buffer
- add esi, ebx ; move past right clipped pixels
- add edi, edx ; adjust dest to next line
- dec ebp ; decrement number of rows to do
- jnz ??restore_loop ; if more to do, do it
- pop ebp
- ret
- ;*===================================================================
- ;* Handle soting the visible page into the Mouse Shadow Buffer
- ;*===================================================================
- ??store_entry:
- xchg esi, edi ; xchg the source and the dest
- mov ebp, ecx
- ??store_loop:
- mov ecx, eax ; get number to really write
- rep movsb ; store them into the buffer
- add esi, edx ; move past right clipped pixels
- add edi, ebx ; adjust dest to next line
- dec ebp ; decrement number of rows to do
- jnz ??store_loop ; if more to do, do it
- pop ebp
- ??out:
- ret
- ENDP Mouse_Shadow_Buffer
- ;***************************************************************************
- ;* DRAW_MOUSE -- Handles drawing the mouse cursor *
- ;* *
- ;* INPUT: MouseClass * - pointer to mouse class data *
- ;* GraphicBufferClass * - screen to draw the mouse on *
- ;* int x - x position to store the mouse at *
- ;* int y - y position to store the mouse at *
- ;* *
- ;* Note: The x and y that this routine expects to receive are based on *
- ;* the mouse cursor position. This routine automatically adjusts *
- ;* for hot spot, so that adjustment should not be made prior to *
- ;* this point. *
- ;* *
- ;* PROTO: void Draw_Mouse( MouseClass * mouse_data, *
- ;* GraphicBufferClass *destination, *
- ;* int x_pixel, *
- ;* int y_pixel); *
- ;* *
- ;* HISTORY: *
- ;* 10/27/1994 PWG : Created. *
- ;*=========================================================================*
- GLOBAL C Draw_Mouse:NEAR
- PROC Draw_Mouse C NEAR
- USES eax,ebx,ecx,edx,edi,esi
- ARG this:DWORD
- ARG dest:DWORD
- ARG mousex:DWORD
- ARG mousey:DWORD
- local x0:dword
- local y0:dword
- local x1:dword
- local y1:dword
- local buffx0:dword
- local buffy0:dword
- mov esi, [this] ; get 32 bit offset to mouse data
- mov edi, [dest] ; get 32 bit offset to dest buffer
- ;*===================================================================
- ;* Copy of X, Y, Width and Height into local registers
- ;*===================================================================
- mov eax, [mousex]
- mov ebx, [mousey]
- sub eax, [(MouseType esi).MouseXHot]
- sub ebx, [(MouseType esi).MouseYHot]
- mov [x0], eax
- mov [y0], ebx
- add eax,[(MouseType esi).CursorWidth]
- add ebx,[(MouseType esi).CursorHeight]
- mov [x1], eax
- mov [y1], ebx
- mov [buffx0], 0
- mov eax, [(MouseType esi).MouseCursor]
- mov [buffy0], eax
- ;*===================================================================
- ;* Bounds check source X. Y.
- ;*===================================================================
- xor eax, eax
- xor edx, edx
- mov ecx, [x0]
- mov ebx, [x1]
- shld eax, ecx, 1
- shld edx, ebx, 1
- mov ecx, [x0]
- mov ebx, [x1]
- sub ecx, [(GraphicViewPort edi).GVPWidth]
- sub ebx, [(GraphicViewPort edi).GVPWidth]
- dec ecx
- dec ebx
- shld eax, ecx, 1
- shld edx, ebx, 1
- mov ecx, [y0]
- mov ebx, [y1]
- shld eax, ecx, 1
- shld edx, ebx, 1
- mov ecx, [y0]
- mov ebx, [y1]
- sub ecx, [(GraphicViewPort edi).GVPHeight]
- sub ebx, [(GraphicViewPort edi).GVPHeight]
- dec ecx
- dec ebx
- shld eax, ecx, 1
- shld edx, ebx, 1
- xor al, 5
- xor dl, 5
- mov ah, al
- test dl, al
- jnz ??out
- or al, dl
- jz ??not_clip
- test ah, 1000b
- jz ??scr_left_ok
- mov ebx, [x0]
- neg ebx
- mov [buffx0], ebx
- mov [x0], 0
- ??scr_left_ok:
- test ah, 0010b
- jz ??scr_bottom_ok
- mov ebx, [y0]
- neg ebx
- imul ebx, [(MouseType esi).CursorWidth]
- add [buffy0], ebx
- mov [y0], 0
- ??scr_bottom_ok:
- test dl, 0100b
- jz ??scr_right_ok
- mov eax, [(GraphicViewPort edi).GVPWidth] ; get width into register
- mov [x1] , eax
- ??scr_right_ok:
- test dl, 0001b
- jz ??not_clip
- mov eax, [(GraphicViewPort edi).GVPHeight] ; get width into register
- mov [y1] , eax
- ??not_clip:
- ;*===================================================================
- ;* Get the offset into the screen.
- ;*===================================================================
- mov eax, [y0]
- mov edx, [(GraphicViewPort edi).GVPWidth]
- add edx, [(GraphicViewPort edi).GVPXAdd]
- add edx, [(GraphicViewPort edi).GVPPitch]
- imul eax, edx
- add eax, [x0]
- mov edi, [(GraphicViewPort edi).GVPOffset]
- add edi, eax
- ;*===================================================================
- ;* Adjust the source for the top clip.
- ;*===================================================================
- mov ebx, [(MouseType esi).CursorWidth] ; turn this into an offset
- mov esi, [buffy0] ; edx points to source
- add esi, [buffx0] ; plus clipped lines
- ;*===================================================================
- ;* Calculate the bytes per row add value
- ;*===================================================================
- mov eax, [x1]
- mov ecx, [y1]
- sub eax, [x0]
- jle ??out
- sub ecx, [y0]
- jle ??out
- sub edx, eax
- sub ebx, eax
- ;*===================================================================
- ;* Handle restoring the buffer to the visible page
- ;*===================================================================
- ??top_loop:
- mov ah, al
- ??inner_loop:
- mov ch, [esi]
- inc esi
- test ch, ch
- jz ??inc_edi
- mov [edi], ch
- ??inc_edi:
- inc edi
- dec ah
- jnz ??inner_loop
- add esi, ebx ; move past right clipped pixels
- add edi, edx ; adjust dest to next line
- dec cl ; decrement number of rows to do
- jnz ??top_loop ; if more to do, do it
- ??out:
- ret
- ENDP Draw_Mouse
- ;***************************************************************************
- ;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse. *
- ;* *
- ;* This will inform the system of the shape desired as the mouse *
- ;* cursor. *
- ;* *
- ;* INPUT: xhotspot -- Offset of click point into shape. *
- ;* *
- ;* yhotspot -- Offset of click point into shape. *
- ;* *
- ;* cursor -- Shape to use as the new mouse shape. *
- ;* *
- ;* OUTPUT: Returns with a pointer to the original mouse shape. *
- ;* *
- ;* PROTO: VOID *Set_Mouse_Cursor( int xhotspot, *
- ;* int yhotspot, *
- ;* void *cursor); *
- ;* *
- ;* HISTORY: *
- ;* 02/13/1992 JLB : Created. *
- ;*=========================================================================*
- GLOBAL C ASM_Set_Mouse_Cursor:NEAR
- PROC ASM_Set_Mouse_Cursor C NEAR
- USES ebx,ecx,edx,esi,edi
- ARG this:DWORD ; pointer to mouse cursor struct
- ARG xhotspot:DWORD ; the x hot spot of the mouse
- ARG yhotspot:DWORD ; the y hot spot of the mouse
- ARG cursor:DWORD ; ptr to the new mouse cursor
- LOCAL datasize:DWORD
- LOCAL stype:WORD
- LOCAL swidth:DWORD ; Shape width.
- LOCAL sheight:DWORD ; Shape height.
- LOCAL ssize:DWORD ; Size of raw shape.
- ;*=========================================================================*
- ; Direction flag must be forward in this routine.
- ;*=========================================================================*
- cld
- mov esi,[this] ; get offset of real mode data start
- ;-------------------------------------------------------------------
- ; Calculate the size of the buffer needed.
- ;-------------------------------------------------------------------
- push [cursor]
- call Get_Shape_Uncomp_Size
- pop edx
- mov [datasize],eax
- push [cursor]
- call Get_Shape_Width
- pop edx
- mov [swidth],eax
- cmp eax,[(MouseType esi).MaxWidth]
- jg ??end
- push [cursor]
- call Get_Shape_Original_Height
- pop edx
- mov [sheight],eax
- cmp eax,[(MouseType esi).MaxHeight]
- jg ??end
- mov ebx,[sheight]
- mov eax,[swidth]
- imul ebx,eax
- ??copy_mouse:
- mov edi,[(MouseType esi).MouseCursor] ; set edi to point to mouse buffer
- mov esi,[cursor] ; set esi to point to mouse shape
- mov ax,[esi] ; get the shape type byte
- mov [stype],ax ; save off the shape type
- test ax,MAKESHAPE_NOCOMP ; is it marked as no compression?
- je ??comp_shape ; if not go to the comped shape code
- ??copy_type:
- test [stype],MAKESHAPE_COMPACT ; if the shape a 16 color shape?
- jne ??16_color_copy ; if it is then go handle it
- ??normal_copy:
- ;-------------------------------------------------------------------
- ;* Uncompressed NORMAL shapes just get run-length uncompressed
- ;-------------------------------------------------------------------
- add esi,10 ; adjust past header of shape
- mov eax,[swidth] ; load up the width
- mul [sheight] ; find size of shape in pixels
- mov edx,eax ; save this in number of bytes
- xor ecx,ecx ; clear high of loop variable
- ??norm_unrle:
- mov al,[esi] ; get a byte out of the file
- inc esi ; increment to the next pos
- or al,al ; set the flags on register state
- jz ??norm_trans ; if its a zero its transparent
- mov [edi],al ; write out the pixel to dest
- inc edi ; move to next dest position
- dec edx ; we have now written another pix
- jnz ??norm_unrle ; if more to write then do it
- jmp ??done_copy ; otherwise we are all done
- ??norm_trans:
- mov cl,[esi] ; get how many zeros to write
- sub edx,ecx
- inc esi ; increment the source position
- xor al,al ; clear out al cuz we're writing zeros
- rep stosb ; write all of them out
- or edx,edx
- jnz ??norm_unrle ; if more to do then do it
- jmp ??done_copy ; otherwise we are done
- ??16_color_copy:
- ;-------------------------------------------------------------------
- ;* Uncompressed 16 color shapes just get remaped and UN-RLE'd
- ;-------------------------------------------------------------------
- add esi,10 ; adjust past header of shape
- mov ebx,esi ; save of position of remap
- add esi,16 ; move past remap table
- mov eax,[swidth] ; load up the width
- mul [sheight] ; load up the height
- mov edx,eax ; save this in number of bytes
- xor eax,eax ; clear high of lookup variable
- xor ecx,ecx ; clear high of loop variable
- ??16_color_unrle:
- mov al,[esi] ; get a byte out of the file
- inc esi ; increment to the next pos
- or al,al ; set the flags on register state
- jz ??16_color_trans ; if its a zero its transparent
- mov al,[ebx+eax] ; remap the pixel from 16 color table
- mov [edi],al ; store it out to the dest address
- inc edi ; move to next dest address
- dec edx ; we have now written a pixel
- jnz ??16_color_unrle
- jmp ??done_copy
- ??16_color_trans:
- mov cl,[esi] ; get how many zeros to write
- sub edx,ecx ; subtract off count ahead of time
- inc esi ; increment the source position
- xor al,al ; clear out al cuz we're writing zeros
- rep stosb ; write all of them out
- or edx,edx ; or edx to test for zero
- jnz ??16_color_unrle
- jmp ??done_copy
- ;-------------------------------------------------------------------
- ; Deal with the compressed shape by copying it into the shape
- ; staging buffer.
- ;-------------------------------------------------------------------
- ??comp_shape:
- mov edi,[ShapeBuffer] ; get a pointer to ShapeBuffer
- mov ax,[esi] ; load in the shape type
- add esi,2 ; increment the shape pointer
- or ax,MAKESHAPE_NOCOMP ; make the shape as uncompressed
- mov [stype],ax ; save off the shape type
- mov [edi],ax ; write out uncompressed shape
- add edi,2
- ;-------------------------------------------------------------------
- ; Process the shape header information and copy it over to the new
- ; location.
- ;-------------------------------------------------------------------
- mov ecx,4 ; transfer height, width, org and
- test eax,MAKESHAPE_COMPACT ; is it a 16 color shape?
- je ??copy_head ; no - don't worry about it
- add ecx,8 ; otherwise adjust ecx for header
- ??copy_head:
- rep movsw ; copy the necessary bytes
- mov eax,[datasize] ; get uncompressed length
- push eax ; push as third param
- push edi ; push the destination offset
- push esi ; push the source offset
- call LCW_Uncompress ; do the uncompress
- pop eax
- pop eax
- pop eax
- mov esi,[this]
- mov edi,[(MouseType esi).MouseCursor] ; set edi to point to mouse buffer
- mov esi,[ShapeBuffer]
- jmp ??copy_type
- ??done_copy:
- mov esi,[this] ; get offset of real mode data start
- mov eax,[xhotspot] ; get the mouse cursors x hotspot
- mov [(MouseType esi).MouseXHot],eax
- mov eax,[yhotspot] ; get the mouse cursors y hotspot
- mov [(MouseType esi).MouseYHot],eax
- mov ebx,[sheight] ; get shape height
- mov [(MouseType esi).CursorHeight],ebx
- mov ebx,[swidth]
- mov [(MouseType esi).CursorWidth],ebx
- ;-------------------------------------------------------------------
- ; Final cleanup and exit.
- ;-------------------------------------------------------------------
- ??end:
- push [cursor]
- push [(MouseType esi).PrevCursor]
- pop eax
- pop [(MouseType esi).PrevCursor]
- ret ; and return back to the world
- ENDP ASM_Set_Mouse_Cursor
- END
|