// // Copyright 2020 Electronic Arts Inc. // // TiberianDawn.DLL and RedAlert.dll and corresponding source code 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. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed // in the hope that it will be useful, but with permitted additional restrictions // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT // distributed with this program. You should have received a copy of the // GNU General Public License along with permitted additional restrictions // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection /* ** ** ** Misc asm functions from ww lib ** ST - 12/19/2018 1:20PM ** ** ** ** ** ** ** ** ** ** ** */ #include #include "gbuffer.h" #include "MISC.H" #include "WSA.H" IconCacheClass::IconCacheClass (void) { IsCached =FALSE; SurfaceLost =FALSE; DrawFrequency =0; //CacheSurface =NULL; IconSource =NULL; } IconCacheClass::~IconCacheClass (void) { } IconCacheClass CachedIcons[MAX_CACHED_ICONS]; extern "C"{ IconSetType IconSetList[MAX_ICON_SETS]; short IconCacheLookup[MAX_LOOKUP_ENTRIES]; } int CachedIconsDrawn=0; //Counter of number of cache hits int UnCachedIconsDrawn=0; //Counter of number of cache misses BOOL CacheMemoryExhausted; //Flag set if we have run out of video RAM void Invalidate_Cached_Icons (void) {} void Restore_Cached_Icons (void) {} void Register_Icon_Set (void *icon_data , BOOL pre_cache) {}; // // Prototypes for assembly language procedures in STMPCACH.ASM // extern "C" void __cdecl Clear_Icon_Pointers (void) {}; extern "C" void __cdecl Cache_Copy_Icon (void const *icon_ptr ,void * , int) {}; extern "C" int __cdecl Is_Icon_Cached (void const *icon_data , int icon) {return -1;}; extern "C" int __cdecl Get_Icon_Index (void *icon_ptr) {return 0;}; extern "C" int __cdecl Get_Free_Index (void) {return 0;}; extern "C" BOOL __cdecl Cache_New_Icon (int icon_index, void *icon_ptr) {return -1;}; extern "C" int __cdecl Get_Free_Cache_Slot(void) {return -1;} void IconCacheClass::Draw_It (void *dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height) {} extern bool renderHDTexture; extern int CachedIconsDrawn; extern int UnCachedIconsDrawn; /* ;*************************************************************************** ;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport * ;* * ;* INPUT: WORD sx_pixel - the starting x pixel position * ;* WORD sy_pixel - the starting y pixel position * ;* WORD dx_pixel - the destination x pixel position * ;* WORD dy_pixel - the destination y pixel position * ;* WORD color - the color of the line to draw * ;* * ;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel * ;* with the graphic viewport it has been assigned to. * ;* * ;* HISTORY: * ;* 06/16/1994 PWG : Created. * ;* 08/30/1994 IML : Fixed clipping bug. * ;*=========================================================================* PROC Buffer_Draw_Line C NEAR USES eax,ebx,ecx,edx,esi,edi */ void __cdecl Buffer_Draw_Line(void *this_object, int sx, int sy, int dx, int dy, unsigned char color) { unsigned int clip_min_x; unsigned int clip_max_x; unsigned int clip_min_y; unsigned int clip_max_y; unsigned int clip_var; unsigned int accum; unsigned int bpr; static int _one_time_init = 0; //clip_tbl DD nada,a_up,a_dwn,nada // DD a_lft,a_lft,a_dwn,nada // DD a_rgt,a_up,a_rgt,nada // DD nada,nada,nada,nada static void *_clip_table [4*4] = {0}; unsigned int int_color = color; unsigned int x1_pixel = (unsigned int) sx; unsigned int y1_pixel = (unsigned int) sy; unsigned int x2_pixel = (unsigned int) dx; unsigned int y2_pixel = (unsigned int) dy; __asm { mov eax,_one_time_init and eax,eax jnz init_done call do_init init_done: //;*================================================================== //;* Take care of find the clip minimum and maximums //;*================================================================== mov ebx,[this_object] xor eax,eax mov [clip_min_x],eax mov [clip_min_y],eax mov eax,[ebx]GraphicViewPortClass.Width mov [clip_max_x],eax add eax,[ebx]GraphicViewPortClass.XAdd add eax,[ebx]GraphicViewPortClass.Pitch mov [bpr],eax mov eax,[ebx]GraphicViewPortClass.Height mov [clip_max_y],eax //;*================================================================== //;* Adjust max pixels as they are tested inclusively. //;*================================================================== dec [clip_max_x] dec [clip_max_y] //;*================================================================== //;* Set the registers with the data for drawing the line //;*================================================================== mov eax,[x1_pixel] //; eax = start x pixel position mov ebx,[y1_pixel] //; ebx = start y pixel position mov ecx,[x2_pixel] //; ecx = dest x pixel position mov edx,[y2_pixel] //; edx = dest y pixel position //;*================================================================== //;* This is the section that "pushes" the line into bounds. //;* I have marked the section with PORTABLE start and end to signify //;* how much of this routine is 100% portable between graphics modes. //;* It was just as easy to have variables as it would be for constants //;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used //;* to clip the line (default is the screen) //;* PORTABLE start //;*================================================================== cmp eax,[clip_min_x] jl short clip_it cmp eax,[clip_max_x] jg short clip_it cmp ebx,[clip_min_y] jl short clip_it cmp ebx,[clip_max_y] jg short clip_it cmp ecx,[clip_min_x] jl short clip_it cmp ecx,[clip_max_x] jg short clip_it cmp edx,[clip_min_y] jl short clip_it cmp edx,[clip_max_y] jle short on_screen //;*================================================================== //;* Takes care off clipping the line. //;*================================================================== clip_it: call set_bits xchg eax,ecx xchg ebx,edx mov edi,esi call set_bits mov [clip_var],edi or [clip_var],esi jz short on_screen test edi,esi jne short off_screen shl esi,2 //call [clip_tbl+esi] call [_clip_table+esi] jc clip_it xchg eax,ecx xchg ebx,edx shl edi,2 //call [clip_tbl+edi] call [_clip_table+edi] jmp clip_it on_screen: jmp draw_it off_screen: jmp and_out //;*================================================================== //;* Jump table for clipping conditions //;*================================================================== //clip_tbl DD nada,a_up,a_dwn,nada // DD a_lft,a_lft,a_dwn,nada // DD a_rgt,a_up,a_rgt,nada // DD nada,nada,nada,nada nada: clc ret a_up: mov esi,[clip_min_y] call clip_vert stc ret a_dwn: mov esi,[clip_max_y] neg esi neg ebx neg edx call clip_vert neg ebx neg edx stc ret //;*================================================================== //;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)] //;*================================================================== clip_vert: push edx push eax mov [clip_var],edx //; clip_var = yb sub [clip_var],ebx //; clip_var = (yb-ya) neg eax //; eax=-xa add eax,ecx //; (ebx-xa) mov edx,esi //; edx=miny sub edx,ebx //; edx=(miny-ya) imul edx idiv [clip_var] pop edx add eax,edx pop edx mov ebx,esi ret a_lft: mov esi,[clip_min_x] call clip_horiz stc ret a_rgt: mov esi,[clip_max_x] neg eax neg ecx neg esi call clip_horiz neg eax neg ecx stc ret //;*================================================================== //;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)] //;*================================================================== clip_horiz: push edx mov [clip_var],ecx //; clip_var = xb sub [clip_var],eax //; clip_var = (xb-xa) sub edx,ebx //; edx = (yb-ya) neg eax //; eax = -xa add eax,esi //; eax = (minx-xa) imul edx //; eax = (minx-xa)(yb-ya) idiv [clip_var] //; eax = (minx-xa)(yb-ya)/(xb-xa) add ebx,eax //; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)] pop edx mov eax,esi ret //;*================================================================== //;* Sets the condition bits //;*================================================================== set_bits: xor esi,esi cmp ebx,[clip_min_y] //; if y >= top its not up jge short a_not_up or esi,1 a_not_up: cmp ebx,[clip_max_y] //; if y <= bottom its not down jle short a_not_down or esi,2 a_not_down: cmp eax,[clip_min_x] //; if x >= left its not left jge short a_not_left or esi,4 a_not_left: cmp eax,[clip_max_x] //; if x <= right its not right jle short a_not_right or esi,8 a_not_right: ret //;*================================================================== //;* Draw the line to the screen. //;* PORTABLE end //;*================================================================== draw_it: sub edx,ebx //; see if line is being draw down jnz short not_hline //; if not then its not a hline jmp short hline //; do special case h line not_hline: jg short down //; if so there is no need to rev it neg edx //; negate for actual pixel length xchg eax,ecx //; swap x's to rev line draw sub ebx,edx //; get old edx down: push edx push eax mov eax,[bpr] mul ebx mov ebx,eax mov eax,[this_object] add ebx,[eax]GraphicViewPortClass.Offset pop eax pop edx mov esi,1 //; assume a right mover sub ecx,eax //; see if line is right jnz short not_vline //; see if its a vertical line jmp vline not_vline: jg short right //; if so, the difference = length //left: neg ecx //; else negate for actual pixel length neg esi //; negate counter to move left right: cmp ecx,edx //; is it a horiz or vert line jge short horiz //; if ecx > edx then |x|>|y| or horiz //vert: xchg ecx,edx //; make ecx greater and edx lesser mov edi,ecx //; set greater mov [accum],ecx //; set accumulator to 1/2 greater shr [accum],1 //;*================================================================== //;* at this point ... //;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater; //;* esi=adder; accum=accumulator //;* in a vertical loop the adder is conditional and the inc constant //;*================================================================== //vert_loop: add ebx,eax mov eax,[int_color] v_midloop: mov [ebx],al dec ecx jl and_out add ebx,[bpr] sub [accum],edx //; sub the lesser jge v_midloop //; any line could be new add [accum],edi //; add greater for new accum add ebx,esi //; next pixel over jmp v_midloop horiz: mov edi,ecx //; set greater mov [accum],ecx //; set accumulator to 1/2 greater shr [accum],1 //;*================================================================== //;* at this point ... //;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater; //;* esi=adder; accum=accumulator //;* in a vertical loop the adder is conditional and the inc constant //;*================================================================== //horiz_loop: add ebx,eax mov eax,[int_color] h_midloop: mov [ebx],al dec ecx //; dec counter jl and_out //; end of line add ebx,esi sub [accum],edx //; sub the lesser jge h_midloop add [accum],edi //; add greater for new accum add ebx,[bpr] //; goto next line jmp h_midloop //;*================================================================== //;* Special case routine for horizontal line draws //;*================================================================== hline: cmp eax,ecx //; make eax < ecx jl short hl_ac xchg eax,ecx hl_ac: sub ecx,eax //; get len inc ecx push edx push eax mov eax,[bpr] mul ebx mov ebx,eax mov eax,[this_object] add ebx,[eax]GraphicViewPortClass.Offset pop eax pop edx add ebx,eax mov edi,ebx cmp ecx,15 jg big_line mov al,[color] rep stosb //; write as many words as possible jmp short and_out //; get outt big_line: mov al,[color] mov ah,al mov ebx,eax shl eax,16 mov ax,bx test edi,3 jz aligned mov [edi],al inc edi dec ecx test edi,3 jz aligned mov [edi],al inc edi dec ecx test edi,3 jz aligned mov [edi],al inc edi dec ecx aligned: mov ebx,ecx shr ecx,2 rep stosd mov ecx,ebx and ecx,3 rep stosb jmp and_out //;*================================================================== //;* a special case routine for vertical line draws //;*================================================================== vline: mov ecx,edx //; get length of line to draw inc ecx add ebx,eax mov eax,[int_color] vl_loop: mov [ebx],al //; store bit add ebx,[bpr] dec ecx jnz vl_loop jmp and_out do_init: mov edi, offset _clip_table lea esi, nada mov [edi], esi mov [edi+12], esi lea esi, a_up mov [edi+4], esi lea esi, a_dwn mov [edi+8], esi add edi, 16 lea esi, a_lft mov [edi], esi mov [edi+4], esi lea esi, a_dwn mov [edi+8], esi lea esi, nada mov [edi+12], esi add edi, 16 lea esi, a_rgt mov [edi], esi mov [edi+8], esi lea esi, a_up mov [edi+4], esi lea esi, nada mov [edi+12], esi add edi, 16 lea esi, nada mov [edi], esi mov [edi+4], esi mov [edi+8], esi mov [edi+12], esi mov [_one_time_init], 1 ret and_out: } } /* ;*************************************************************************** ;** 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 : DRAWLINE.ASM * ;* * ;* Programmer : Phil W. Gorrow * ;* * ;* Start Date : June 16, 1994 * ;* * ;* Last Update : August 30, 1994 [IML] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* VVC::Scale -- Scales a virtual viewport to another virtual viewport * ;* Normal_Draw -- jump loc for drawing scaled line of normal pixel * ;* __DRAW_LINE -- Assembly routine to draw a line * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * IDEAL P386 MODEL USE32 FLAT INCLUDE ".\drawbuff.inc" INCLUDE ".\gbuffer.inc" CODESEG */ /* ;*************************************************************************** ;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport * ;* * ;* INPUT: WORD sx_pixel - the starting x pixel position * ;* WORD sy_pixel - the starting y pixel position * ;* WORD dx_pixel - the destination x pixel position * ;* WORD dy_pixel - the destination y pixel position * ;* WORD color - the color of the line to draw * ;* * ;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel * ;* with the graphic viewport it has been assigned to. * ;* * ;* HISTORY: * ;* 06/16/1994 PWG : Created. * ;* 08/30/1994 IML : Fixed clipping bug. * ;*=========================================================================* PROC Buffer_Draw_Line C NEAR USES eax,ebx,ecx,edx,esi,edi ;*================================================================== ;* Define the arguements that the function takes. ;*================================================================== ARG this_object:DWORD ; associated graphic view port ARG x1_pixel:DWORD ; the start x pixel position ARG y1_pixel:DWORD ; the start y pixel position ARG x2_pixel:DWORD ; the dest x pixel position ARG y2_pixel:DWORD ; the dest y pixel position ARG color:DWORD ; the color we are drawing ;*================================================================== ;* Define the local variables that we will use on the stack ;*================================================================== LOCAL clip_min_x:DWORD LOCAL clip_max_x:DWORD LOCAL clip_min_y:DWORD LOCAL clip_max_y:DWORD LOCAL clip_var:DWORD LOCAL accum:DWORD LOCAL bpr:DWORD ;*================================================================== ;* Take care of find the clip minimum and maximums ;*================================================================== mov ebx,[this_object] xor eax,eax mov [clip_min_x],eax mov [clip_min_y],eax mov eax,[(GraphicViewPort ebx).GVPWidth] mov [clip_max_x],eax add eax,[(GraphicViewPort ebx).GVPXAdd] add eax,[(GraphicViewPort ebx).GVPPitch] mov [bpr],eax mov eax,[(GraphicViewPort ebx).GVPHeight] mov [clip_max_y],eax ;*================================================================== ;* Adjust max pixels as they are tested inclusively. ;*================================================================== dec [clip_max_x] dec [clip_max_y] ;*================================================================== ;* Set the registers with the data for drawing the line ;*================================================================== mov eax,[x1_pixel] ; eax = start x pixel position mov ebx,[y1_pixel] ; ebx = start y pixel position mov ecx,[x2_pixel] ; ecx = dest x pixel position mov edx,[y2_pixel] ; edx = dest y pixel position ;*================================================================== ;* This is the section that "pushes" the line into bounds. ;* I have marked the section with PORTABLE start and end to signify ;* how much of this routine is 100% portable between graphics modes. ;* It was just as easy to have variables as it would be for constants ;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used ;* to clip the line (default is the screen) ;* PORTABLE start ;*================================================================== cmp eax,[clip_min_x] jl short ??clip_it cmp eax,[clip_max_x] jg short ??clip_it cmp ebx,[clip_min_y] jl short ??clip_it cmp ebx,[clip_max_y] jg short ??clip_it cmp ecx,[clip_min_x] jl short ??clip_it cmp ecx,[clip_max_x] jg short ??clip_it cmp edx,[clip_min_y] jl short ??clip_it cmp edx,[clip_max_y] jle short ??on_screen ;*================================================================== ;* Takes care off clipping the line. ;*================================================================== ??clip_it: call NEAR PTR ??set_bits xchg eax,ecx xchg ebx,edx mov edi,esi call NEAR PTR ??set_bits mov [clip_var],edi or [clip_var],esi jz short ??on_screen test edi,esi jne short ??off_screen shl esi,2 call [DWORD PTR cs:??clip_tbl+esi] jc ??clip_it xchg eax,ecx xchg ebx,edx shl edi,2 call [DWORD PTR cs:??clip_tbl+edi] jmp ??clip_it ??on_screen: jmp ??draw_it ??off_screen: jmp ??out ;*================================================================== ;* Jump table for clipping conditions ;*================================================================== ??clip_tbl DD ??nada,??a_up,??a_dwn,??nada DD ??a_lft,??a_lft,??a_dwn,??nada DD ??a_rgt,??a_up,??a_rgt,??nada DD ??nada,??nada,??nada,??nada ??nada: clc retn ??a_up: mov esi,[clip_min_y] call NEAR PTR ??clip_vert stc retn ??a_dwn: mov esi,[clip_max_y] neg esi neg ebx neg edx call NEAR PTR ??clip_vert neg ebx neg edx stc retn ;*================================================================== ;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)] ;*================================================================== ??clip_vert: push edx push eax mov [clip_var],edx ; clip_var = yb sub [clip_var],ebx ; clip_var = (yb-ya) neg eax ; eax=-xa add eax,ecx ; (ebx-xa) mov edx,esi ; edx=miny sub edx,ebx ; edx=(miny-ya) imul edx idiv [clip_var] pop edx add eax,edx pop edx mov ebx,esi retn ??a_lft: mov esi,[clip_min_x] call NEAR PTR ??clip_horiz stc retn ??a_rgt: mov esi,[clip_max_x] neg eax neg ecx neg esi call NEAR PTR ??clip_horiz neg eax neg ecx stc retn ;*================================================================== ;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)] ;*================================================================== ??clip_horiz: push edx mov [clip_var],ecx ; clip_var = xb sub [clip_var],eax ; clip_var = (xb-xa) sub edx,ebx ; edx = (yb-ya) neg eax ; eax = -xa add eax,esi ; eax = (minx-xa) imul edx ; eax = (minx-xa)(yb-ya) idiv [clip_var] ; eax = (minx-xa)(yb-ya)/(xb-xa) add ebx,eax ; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)] pop edx mov eax,esi retn ;*================================================================== ;* Sets the condition bits ;*================================================================== ??set_bits: xor esi,esi cmp ebx,[clip_min_y] ; if y >= top its not up jge short ??a_not_up or esi,1 ??a_not_up: cmp ebx,[clip_max_y] ; if y <= bottom its not down jle short ??a_not_down or esi,2 ??a_not_down: cmp eax,[clip_min_x] ; if x >= left its not left jge short ??a_not_left or esi,4 ??a_not_left: cmp eax,[clip_max_x] ; if x <= right its not right jle short ??a_not_right or esi,8 ??a_not_right: retn ;*================================================================== ;* Draw the line to the screen. ;* PORTABLE end ;*================================================================== ??draw_it: sub edx,ebx ; see if line is being draw down jnz short ??not_hline ; if not then its not a hline jmp short ??hline ; do special case h line ??not_hline: jg short ??down ; if so there is no need to rev it neg edx ; negate for actual pixel length xchg eax,ecx ; swap x's to rev line draw sub ebx,edx ; get old edx ??down: push edx push eax mov eax,[bpr] mul ebx mov ebx,eax mov eax,[this_object] add ebx,[(GraphicViewPort eax).GVPOffset] pop eax pop edx mov esi,1 ; assume a right mover sub ecx,eax ; see if line is right jnz short ??not_vline ; see if its a vertical line jmp ??vline ??not_vline: jg short ??right ; if so, the difference = length ??left: neg ecx ; else negate for actual pixel length neg esi ; negate counter to move left ??right: cmp ecx,edx ; is it a horiz or vert line jge short ??horiz ; if ecx > edx then |x|>|y| or horiz ??vert: xchg ecx,edx ; make ecx greater and edx lesser mov edi,ecx ; set greater mov [accum],ecx ; set accumulator to 1/2 greater shr [accum],1 ;*================================================================== ;* at this point ... ;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater; ;* esi=adder; accum=accumulator ;* in a vertical loop the adder is conditional and the inc constant ;*================================================================== ??vert_loop: add ebx,eax mov eax,[color] ??v_midloop: mov [ebx],al dec ecx jl ??out add ebx,[bpr] sub [accum],edx ; sub the lesser jge ??v_midloop ; any line could be new add [accum],edi ; add greater for new accum add ebx,esi ; next pixel over jmp ??v_midloop ??horiz: mov edi,ecx ; set greater mov [accum],ecx ; set accumulator to 1/2 greater shr [accum],1 ;*================================================================== ;* at this point ... ;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater; ;* esi=adder; accum=accumulator ;* in a vertical loop the adder is conditional and the inc constant ;*================================================================== ??horiz_loop: add ebx,eax mov eax,[color] ??h_midloop: mov [ebx],al dec ecx ; dec counter jl ??out ; end of line add ebx,esi sub [accum],edx ; sub the lesser jge ??h_midloop add [accum],edi ; add greater for new accum add ebx,[bpr] ; goto next line jmp ??h_midloop ;*================================================================== ;* Special case routine for horizontal line draws ;*================================================================== ??hline: cmp eax,ecx ; make eax < ecx jl short ??hl_ac xchg eax,ecx ??hl_ac: sub ecx,eax ; get len inc ecx push edx push eax mov eax,[bpr] mul ebx mov ebx,eax mov eax,[this_object] add ebx,[(GraphicViewPort eax).GVPOffset] pop eax pop edx add ebx,eax mov edi,ebx cmp ecx,15 jg ??big_line mov al,[byte color] rep stosb ; write as many words as possible jmp short ??out ; get outt ??big_line: mov al,[byte color] mov ah,al mov ebx,eax shl eax,16 mov ax,bx test edi,3 jz ??aligned mov [edi],al inc edi dec ecx test edi,3 jz ??aligned mov [edi],al inc edi dec ecx test edi,3 jz ??aligned mov [edi],al inc edi dec ecx ??aligned: mov ebx,ecx shr ecx,2 rep stosd mov ecx,ebx and ecx,3 rep stosb jmp ??out ;*================================================================== ;* a special case routine for vertical line draws ;*================================================================== ??vline: mov ecx,edx ; get length of line to draw inc ecx add ebx,eax mov eax,[color] ??vl_loop: mov [ebx],al ; store bit add ebx,[bpr] dec ecx jnz ??vl_loop ??out: ret ENDP Buffer_Draw_Line */ /* ;*************************************************************************** ;* GVPC::FILL_RECT -- Fills a rectangular region of a graphic view port * ;* * ;* INPUT: WORD the left hand x pixel position of region * ;* WORD the upper x pixel position of region * ;* WORD the right hand x pixel position of region * ;* WORD the lower x pixel position of region * ;* UBYTE the color (optional) to clear the view port to * ;* * ;* OUTPUT: none * ;* * ;* NOTE: This function is optimized to handle viewport with no XAdd * ;* value. It also handles DWORD aligning the destination * ;* when speed can be gained by doing it. * ;* HISTORY: * ;* 06/07/1994 PWG : Created. * ;*=========================================================================* */ /* ;****************************************************************************** ; Much testing was done to determine that only when there are 14 or more bytes ; being copied does it speed the time it takes to do copies in this algorithm. ; For this reason and because 1 and 2 byte copies crash, is the special case ; used. SKB 4/21/94. Tested on 486 66mhz. Copied by PWG 6/7/04. */ #define OPTIMAL_BYTE_COPY 14 void __cdecl Buffer_Fill_Rect(void *thisptr, int x, int y, int w, int h, unsigned char color) { GraphicViewPortClass& vp = (*(GraphicViewPortClass *)thisptr); // If we aren't drawing within the viewport, return if (x >= vp.Get_Width() || y >= vp.Get_Height() || w < 0 || h < 0) { return; } // Clipping if (x < 0) { x = 0; } if (y < 0) { y = 0; } w = min(w, vp.Get_Width() - 1); h = min(h, vp.Get_Height() - 1); uint8_t* offset = (y * 4) * vp.Get_Full_Pitch() + (x * 4) + (uint8_t*)(vp.Get_Offset()); int height = h - y + 1; int width = w - x + 1; for (int i = 0; i < height; ++i) { FastScanlinePaletteBlit(offset, color, width); offset += vp.Get_Full_Pitch() * 4; } } /* ;*************************************************************************** ;* VVPC::CLEAR -- Clears a virtual viewport instance * ;* * ;* INPUT: UBYTE the color (optional) to clear the view port to * ;* * ;* OUTPUT: none * ;* * ;* NOTE: This function is optimized to handle viewport with no XAdd * ;* value. It also handles DWORD aligning the destination * ;* when speed can be gained by doing it. * ;* HISTORY: * ;* 06/07/1994 PWG : Created. * ;* 08/23/1994 SKB : Clear the direction flag to always go forward. * ;*=========================================================================* */ void __cdecl Buffer_Clear(void *this_object, unsigned char color) { GraphicViewPortClass* cls = (GraphicViewPortClass*)this_object; if (cls->Get_Graphic_Buffer()->GetMemoryBuffer() == NULL) return; memset(cls->Get_Graphic_Buffer()->GetMemoryBuffer(), color, cls->Get_Width() * cls->Get_Height()); } /* ;*************************************************************************** ;* VVC::SCALE -- Scales a virtual viewport to another virtual viewport * ;* * ;* INPUT: * ;* * ;* OUTPUT: * ;* * ;* WARNINGS: * ;* * ;* HISTORY: * ;* 06/16/1994 PWG : Created. * ;*=========================================================================* PROC Linear_Scale_To_Linear C NEAR USES eax,ebx,ecx,edx,esi,edi */ // jmarshall - ported to c unsigned char* Draw_Dropsample(const unsigned char* in, int inwidth, int inheight, int outwidth, int outheight) { int i, j, k; const unsigned char* inrow; const unsigned char* pix1; unsigned char* out, * out_p; static unsigned char ViewportPixelBuffer[4096 * 4096 * 4]; out = &ViewportPixelBuffer[0]; out_p = out; int bpp = 1; if (renderHDTexture) { bpp = 4; } for (i = 0; i < outheight; i++, out_p += outwidth * bpp) { inrow = in + bpp * inwidth * (int)((i + 0.25) * inheight / outheight); for (j = 0; j < outwidth; j++) { k = j * inwidth / outwidth; pix1 = inrow + k * bpp; if (renderHDTexture) { out_p[j * 4 + 0] = pix1[0]; out_p[j * 4 + 1] = pix1[1]; out_p[j * 4 + 2] = pix1[2]; out_p[j * 4 + 3] = pix1[3]; } else { out_p[j * 1 + 0] = pix1[0]; } //out_p[j * 3 + 1] = pix1[1]; //out_p[j * 3 + 2] = pix1[2]; } } return out; } /* ============== R_CopyImage ============== */ void Nearest_CopyImage(unsigned char* source, int sourceX, int sourceY, int sourceWidth, unsigned char* dest, int destX, int destY, int destWidth, int width, int height, BOOL trans) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int destPos = ((destWidth * (y + destY)) * 4) + ((x + destX) * 4); int sourcePos = (sourceWidth * (y + (sourceY))) + (x + (sourceX)); if (renderHDTexture) { sourcePos = ((sourceWidth * (y + sourceY)) * 4) + ((x + sourceX) * 4); // This needs some work! if (source[0] == 0 && source[1] == 0 && source[2] == 0 && trans) continue; dest[destPos + 0] = source[sourcePos + 0]; dest[destPos + 1] = source[sourcePos + 1]; dest[destPos + 2] = source[sourcePos + 2]; dest[destPos + 3] = 255; } else { unsigned char c = source[sourcePos]; if (c == 0 && trans) { continue; } dest[destPos + 0] = backbuffer_palette[(c * 3) + 0]; dest[destPos + 1] = backbuffer_palette[(c * 3) + 1]; dest[destPos + 2] = backbuffer_palette[(c * 3) + 2]; dest[destPos + 3] = 255; } } } } BOOL __cdecl Linear_Scale_To_Linear(void* this_object, void* dest, int src_x, int src_y, int dst_x, int dst_y, int src_width, int src_height, int dst_width, int dst_height, BOOL trans, char* remap) { GraphicViewPortClass* viewportClass = (GraphicViewPortClass*)this_object; GraphicViewPortClass* destViewportClass = (GraphicViewPortClass*)dest; unsigned char* viewportBuffer = ((unsigned char*)viewportClass->Get_Offset()); // Scale the GraphicViewPortClass to dest_x, dest_y unsigned char* scaled_buffer = Draw_Dropsample((unsigned char*)viewportBuffer, viewportClass->Get_Width(), viewportClass->Get_Height(), dst_width, dst_height); // Blit the scaled_buffer to dest. Nearest_CopyImage(scaled_buffer, src_x, src_y, dst_width, (unsigned char*)destViewportClass->Get_Offset(), dst_x, dst_y, destViewportClass->Get_Width(), dst_width, dst_height, trans); return true; } BOOL __cdecl Linear_Blit_To_Linear(void* this_object, void* dest, int x_pixel, int y_pixel, int dest_x0, int dest_y0, int pixel_width, int pixel_height, BOOL trans) { GraphicViewPortClass* viewportClass = (GraphicViewPortClass*)this_object; GraphicViewPortClass* destViewportClass = (GraphicViewPortClass*)dest; bool needsUnlock = false; bool sourceNeedsUnlock = false; unsigned char* viewportBuffer = NULL; viewportBuffer = ((unsigned char*)viewportClass->Get_Offset()); unsigned char* destBuffer = NULL; destBuffer = ((unsigned char*)destViewportClass->Get_Offset()); //if (destViewportClass->Get_Graphic_Buffer()->Get_Buffer() != NULL) { // destBuffer = (byte*)destViewportClass->Get_Graphic_Buffer()->Get_Buffer(); //} //else { // destViewportClass->Get_Graphic_Buffer()->Lock(); // destBuffer = ((byte*)destViewportClass->Get_Graphic_Buffer()->GetMemoryBuffer()); // needsUnlock = true; //} // //if (viewportBuffer == NULL) { // viewportClass->Get_Graphic_Buffer()->Lock(); // viewportBuffer = ((byte*)viewportClass->Get_Graphic_Buffer()->GetMemoryBuffer()); // sourceNeedsUnlock = true; //} // Blit the buffer to dest. Nearest_CopyImage(viewportBuffer, x_pixel, y_pixel, viewportClass->Get_Width(), (unsigned char*)destBuffer, dest_x0, dest_y0, destViewportClass->Get_Width(), pixel_width, pixel_height, trans); //if (needsUnlock) { // destViewportClass->Get_Graphic_Buffer()->Unlock(); //} // //if (sourceNeedsUnlock) { // viewportClass->Get_Graphic_Buffer()->Unlock(); //} return true; } BOOL __cdecl Linear_Blit_To_Linear_Pal(void* this_object, void* dest, int src_x, int src_y, int dst_x, int dst_y, int w, int h, BOOL use_key) { GraphicViewPortClass& src_vp = *(GraphicViewPortClass*)this_object; GraphicViewPortClass& dst_vp = *(GraphicViewPortClass*)dest; uint8_t* src = (uint8_t*)(src_vp.Get_Offset()); uint8_t* dst = (uint8_t*)(dst_vp.Get_Offset()); int src_pitch = src_vp.Get_Full_Pitch(); int dst_pitch = dst_vp.Get_Full_Pitch(); if (src_x >= src_vp.Get_Width() || src_y >= src_vp.Get_Height() || dst_x >= dst_vp.Get_Width() || dst_y >= dst_vp.Get_Height() || h < 0 || w < 1) { return 0; } src_x = max(0, src_x); src_y = max(0, src_y); dst_x = max(0, dst_x); dst_y = max(0, dst_y); h = (dst_y + h) > dst_vp.Get_Height() ? dst_vp.Get_Height() - 1 - dst_y : h; w = (dst_x + w) > dst_vp.Get_Width() ? dst_vp.Get_Width() - 1 - dst_x : w; // move our pointers to the start locations src += src_x + src_y * src_pitch; dst += dst_x + dst_y * dst_pitch; // If src is before dst, we run the risk of overlapping memory regions so we // need to move src and dst to the last line and work backwards if (src < dst) { uint8_t* esrc = src + (h - 1) * src_pitch; uint8_t* edst = dst + (h - 1) * dst_pitch; if (use_key) { char key_colour = 0; while (h-- != 0) { // Can't optimize as we need to check every pixel against key colour :( for (int i = w - 1; i >= 0; --i) { if (esrc[i] != key_colour) { edst[i] = esrc[i]; } } edst -= dst_pitch; esrc -= src_pitch; } } else { while (h-- != 0) { memmove(edst, esrc, w); edst -= dst_pitch; esrc -= src_pitch; } } } else { if (use_key) { uint8_t key_colour = 0; while (h-- != 0) { // Can't optimize as we need to check every pixel against key colour :( for (int i = 0; i < w; ++i) { if (src[i] != key_colour) { dst[i] = src[i]; } } dst += dst_pitch; src += src_pitch; } } else { while (h-- != 0) { memmove(dst, src, w); dst += dst_pitch; src += src_pitch; } } } return true; } // jmarshall end unsigned int LastIconset = 0; unsigned int StampPtr = 0; // DD 0 ; Pointer to icon data. unsigned int IsTrans = 0; // DD 0 ; Pointer to transparent icon flag table. unsigned int MapPtr = 0; // DD 0 ; Pointer to icon map. unsigned int IconWidth = 0; // DD 0 ; Width of icon in pixels. unsigned int IconHeight = 0; // DD 0 ; Height of icon in pixels. unsigned int IconSize = 0; // DD 0 ; Number of bytes for each icon data. unsigned int IconCount = 0; // DD 0 ; Number of icons in the set. #if (0) 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. GLOBAL C Buffer_Draw_Stamp:near GLOBAL C Buffer_Draw_Stamp_Clip:near ; 256 color icon system. #endif /* ;*********************************************************** ; INIT_STAMPS ; ; VOID cdecl Init_Stamps(VOID *icondata); ; ; This routine initializes the stamp data. ; Bounds Checking: NONE ; ;* */ extern "C" void __cdecl Init_Stamps(unsigned int icondata) { __asm { pushad // ST - 12/20/2018 10:30AM ; 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,[edi]IControl_Type.Count mov [IconCount],eax ; Record width of icon. movzx eax,[edi]IControl_Type.Width mov [IconWidth],eax ; Record height of icon. movzx ebx,[edi]IControl_Type.Height mov [IconHeight],ebx ; Record size of icon (in bytes). mul ebx mov [IconSize],eax ; Record hard pointer to icon map data. mov eax,[edi]IControl_Type.Map add eax,edi mov [MapPtr],eax //nomap: ; Record hard pointer to icon data. mov eax,edi add eax,[edi]IControl_Type.Icons mov [StampPtr],eax ; Record the transparent table. mov eax,edi add eax,[edi]IControl_Type.TransFlag mov [IsTrans],eax fini: popad // ST - 12/20/2018 10:30AM } } VOID __cdecl Buffer_Draw_Line(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color); VOID __cdecl Buffer_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color); VOID __cdecl Buffer_Remap(void * thisptr, int sx, int sy, int width, int height, void *remap); VOID __cdecl Buffer_Fill_Quad(void * thisptr, VOID *span_buff, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int color); void __cdecl Buffer_Draw_Stamp(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap); void __cdecl Buffer_Draw_Stamp_Clip(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int ,int,int,int); void * __cdecl Get_Font_Palette_Ptr ( void ); /* ;*************************************************************************** ;** 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 : REMAP.ASM * ;* * ;* Programmer : Phil W. Gorrow * ;* * ;* Start Date : July 1, 1994 * ;* * ;* Last Update : July 1, 1994 [PWG] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * */ VOID __cdecl Buffer_Remap(void * this_object, int sx, int sy, int width, int height, void *remap) { /* PROC Buffer_Remap C NEAR USES eax,ebx,ecx,edx,esi,edi ;*=================================================================== ;* Define the arguements that our function takes. ;*=================================================================== ARG this_object:DWORD ARG x0_pixel:DWORD ARG y0_pixel:DWORD ARG region_width:DWORD ARG region_height:DWORD ARG remap :DWORD ;*=================================================================== ; Define some locals so that we can handle things quickly ;*=================================================================== local x1_pixel : DWORD local y1_pixel : DWORD local win_width : dword local counter_x : dword */ unsigned int x0_pixel = (unsigned int) sx; unsigned int y0_pixel = (unsigned int) sy; unsigned int region_width = (unsigned int) width; unsigned int region_height = (unsigned int) height; unsigned int x1_pixel = 0; unsigned int y1_pixel = 0; unsigned int win_width = 0; unsigned int counter_x = 0; __asm { cmp [ remap ] , 0 jz real_out ; Clip Source Rectangle against source Window boundaries. mov esi , [ this_object ] ; get ptr to src xor ecx , ecx xor edx , edx mov edi , [esi]GraphicViewPortClass.Width ; get width into register mov ebx , [ x0_pixel ] mov eax , [ x0_pixel ] add ebx , [ region_width ] shld ecx , eax , 1 mov [ x1_pixel ] , ebx inc edi shld edx , ebx , 1 sub eax , edi sub ebx , edi shld ecx , eax , 1 shld edx , ebx , 1 mov edi,[esi]GraphicViewPortClass.Height ; get height into register mov ebx , [ y0_pixel ] mov eax , [ y0_pixel ] add ebx , [ region_height ] shld ecx , eax , 1 mov [ y1_pixel ] , ebx inc edi shld edx , ebx , 1 sub eax , edi sub ebx , edi shld ecx , eax , 1 shld edx , ebx , 1 xor cl , 5 xor dl , 5 mov al , cl test dl , cl jnz real_out or al , dl jz do_remap test cl , 1000b jz scr_left_ok mov [ x0_pixel ] , 0 scr_left_ok: test cl , 0010b jz scr_bottom_ok mov [ y0_pixel ] , 0 scr_bottom_ok: test dl , 0100b jz scr_right_ok mov eax , [esi]GraphicViewPortClass.Width ; get width into register mov [ x1_pixel ] , eax scr_right_ok: test dl , 0001b jz do_remap mov eax , [esi]GraphicViewPortClass.Height ; get width into register mov [ y1_pixel ] , eax do_remap: cld mov edi , [esi]GraphicViewPortClass.Offset mov eax , [esi]GraphicViewPortClass.XAdd mov ebx , [ x1_pixel ] add eax , [esi]GraphicViewPortClass.Width add eax , [esi]GraphicViewPortClass.Pitch mov esi , eax mul [ y0_pixel ] add edi , [ x0_pixel ] sub ebx , [ x0_pixel ] jle real_out add edi , eax sub esi , ebx mov ecx , [ y1_pixel ] sub ecx , [ y0_pixel ] jle real_out mov eax , [ remap ] mov [ counter_x ] , ebx xor edx , edx outer_loop: mov ebx , [ counter_x ] inner_loop: mov dl , [ edi ] mov dl , [ eax + edx ] mov [ edi ] , dl inc edi dec ebx jnz inner_loop add edi , esi dec ecx jnz outer_loop real_out: // ret } } /* ; ************************************************************************** ; ** 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 : WSA Support routines * ; * * ; * File Name : XORDELTA.ASM * ; * * ; * Programmer : Scott K. Bowen * ; * * ; * Last Update :May 23, 1994 [SKB] * ; * * ; *------------------------------------------------------------------------* ; * Functions: * ;* Apply_XOR_Delta -- Apply XOR delta data to a buffer. * ;* Apply_XOR_Delta_To_Page_Or_Viewport -- Calls the copy or the XOR funti* ;* Copy_Delta_buffer -- Copies XOR Delta Data to a section of a page. * ;* XOR_Delta_Buffer -- Xor's the data in a XOR Delta format to a page. * ; * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -* IDEAL P386 MODEL USE32 FLAT */ /* LOCALS ?? ; These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter. If ; These change, make sure and change their values in wsa.cpp. DO_XOR equ 0 DO_COPY equ 1 TO_VIEWPORT equ 0 TO_PAGE equ 2 ; ; Routines defined in this module ; ; ; UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr); ; PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD copy) ; ; PROC C XOR_Delta_Buffer ; PROC C Copy_Delta_Buffer ; GLOBAL C Apply_XOR_Delta:NEAR GLOBAL C Apply_XOR_Delta_To_Page_Or_Viewport:NEAR */ #define DO_XOR 0 #define DO_COPY 1 #define TO_VIEWPORT 0 #define TO_PAGE 2 void __cdecl XOR_Delta_Buffer(int nextrow); void __cdecl Copy_Delta_Buffer(int nextrow); /* ;*************************************************************************** ;* APPLY_XOR_DELTA -- Apply XOR delta data to a linear buffer. * ;* AN example of this in C is at the botton of the file commented out. * ;* * ;* INPUT: BYTE *target - destination buffer. * ;* BYTE *delta - xor data to be delta uncompress. * ;* * ;* OUTPUT: * ;* * ;* WARNINGS: * ;* * ;* HISTORY: * ;* 05/23/1994 SKB : Created. * ;*=========================================================================* */ unsigned int __cdecl Apply_XOR_Delta(char *target, char *delta) { /* PROC Apply_XOR_Delta C near USES ebx,ecx,edx,edi,esi ARG target:DWORD ; pointers. ARG delta:DWORD ; pointers. */ __asm { ; Optimized for 486/pentium by rearanging instructions. mov edi,[target] ; get our pointers into offset registers. mov esi,[delta] cld ; make sure we go forward xor ecx,ecx ; use cx for loop top_loop: xor eax,eax ; clear out eax. mov al,[esi] ; get delta source byte inc esi test al,al ; check for a SHORTDUMP ; check al incase of sign value. je short_run js check_others ; ; SHORTDUMP ; mov ecx,eax ; stick count in cx dump_loop: mov al,[esi] ;get delta XOR byte xor [edi],al ; xor that byte on the dest inc esi inc edi dec ecx jnz dump_loop jmp top_loop ; ; SHORTRUN ; short_run: mov cl,[esi] ; get count inc esi ; inc delta source do_run: mov al,[esi] ; get XOR byte inc esi run_loop: xor [edi],al ; xor that byte. inc edi ; go to next dest pixel dec ecx ; one less to go. jnz run_loop jmp top_loop ; ; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP ; check_others: sub eax,080h ; opcode -= 0x80 jnz do_skip ; if zero then get next word, otherwise use remainder. mov ax,[esi] lea esi,[esi+2] ; get word code in ax test ax,ax ; set flags. (not 32bit register so neg flag works) jle not_long_skip ; ; SHORTSKIP AND LONGSKIP ; do_skip: add edi,eax ; do the skip. jmp top_loop not_long_skip: jz stop ; long count of zero means stop sub eax,08000h ; opcode -= 0x8000 test eax,04000h ; is it a LONGRUN (code & 0x4000)? je long_dump ; ; LONGRUN ; sub eax,04000h ; opcode -= 0x4000 mov ecx,eax ; use cx as loop count jmp do_run ; jump to run code. ; ; LONGDUMP ; long_dump: mov ecx,eax ; use cx as loop count jmp dump_loop ; go to the dump loop. stop: } } /* ;---------------------------------------------------------------------------- ;*************************************************************************** ;* APPLY_XOR_DELTA_To_Page_Or_Viewport -- Calls the copy or the XOR funtion. * ;* * ;* * ;* This funtion is call to either xor or copy XOR_Delta data onto a * ;* page instead of a buffer. The routine will set up the registers * ;* need for the actual routines that will perform the copy or xor. * ;* * ;* The registers are setup as follows : * ;* es:edi - destination segment:offset onto page. * ;* ds:esi - source buffer segment:offset of delta data. * ;* dx,cx,ax - are all zeroed out before entry. * ;* * ;* INPUT: * ;* * ;* OUTPUT: * ;* * ;* WARNINGS: * ;* * ;* HISTORY: * ;* 03/09/1992 SB : Created. * ;*=========================================================================* */ void __cdecl Apply_XOR_Delta_To_Page_Or_Viewport(void *target, void *delta, int width, int nextrow, int copy) { /* USES ebx,ecx,edx,edi,esi ARG target:DWORD ; pointer to the destination buffer. ARG delta:DWORD ; pointer to the delta buffer. ARG width:DWORD ; width of animation. ARG nextrow:DWORD ; Page/Buffer width - anim width. ARG copy:DWORD ; should it be copied or xor'd? */ __asm { mov edi,[target] ; Get the target pointer. mov esi,[delta] ; Get the destination pointer. xor eax,eax ; clear eax, later put them into ecx and edx. cld ; make sure we go forward mov ebx,[nextrow] ; get the amount to add to get to next row from end. push it later... mov ecx,eax ; use cx for loop mov edx,eax ; use dx to count the relative column. push ebx ; push nextrow onto the stack for Copy/XOR_Delta_Buffer. mov ebx,[width] ; bx will hold the max column for speed compares ; At this point, all the registers have been set up. Now call the correct function ; to either copy or xor the data. cmp [copy],DO_XOR ; Do we want to copy or XOR je xorfunct ; Jump to XOR if not copy call Copy_Delta_Buffer ; Call the function to copy the delta buffer. jmp didcopy ; jump past XOR xorfunct: call XOR_Delta_Buffer ; Call funtion to XOR the deltat buffer. didcopy: pop ebx ; remove the push done to pass a value. } } /* ;---------------------------------------------------------------------------- ;*************************************************************************** ;* XOR_DELTA_BUFFER -- Xor's the data in a XOR Delta format to a page. * ;* This will only work right if the page has the previous data on it. * ;* This function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport. * ;* The registers must be setup as follows : * ;* * ;* INPUT: * ;* es:edi - destination segment:offset onto page. * ;* ds:esi - source buffer segment:offset of delta data. * ;* edx,ecx,eax - are all zeroed out before entry. * ;* * ;* OUTPUT: * ;* * ;* WARNINGS: * ;* * ;* HISTORY: * ;* 03/09/1992 SB : Created. * ;*=========================================================================* */ void __cdecl XOR_Delta_Buffer(int nextrow) { /* ARG nextrow:DWORD */ __asm { top_loop: xor eax,eax ; clear out eax. mov al,[esi] ; get delta source byte inc esi test al,al ; check for a SHORTDUMP ; check al incase of sign value. je short_run js check_others ; ; SHORTDUMP ; mov ecx,eax ; stick count in cx dump_loop: mov al,[esi] ; get delta XOR byte xor [edi],al ; xor that byte on the dest inc esi inc edx ; increment our count on current column inc edi cmp edx,ebx ; are we at the final column jne end_col1 ; if not the jmp over the code sub edi,edx ; get our column back to the beginning. xor edx,edx ; zero out our column counter add edi,[nextrow] ; jump to start of next row end_col1: dec ecx jnz dump_loop jmp top_loop ; ; SHORTRUN ; short_run: mov cl,[esi] ; get count inc esi ; inc delta source do_run: mov al,[esi] ; get XOR byte inc esi run_loop: xor [edi],al ; xor that byte. inc edx ; increment our count on current column inc edi ; go to next dest pixel cmp edx,ebx ; are we at the final column jne end_col2 ; if not the jmp over the code sub edi,ebx ; get our column back to the beginning. xor edx,edx ; zero out our column counter add edi,[nextrow] ; jump to start of next row end_col2: dec ecx jnz run_loop jmp top_loop ; ; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP ; check_others: sub eax,080h ; opcode -= 0x80 jnz do_skip ; if zero then get next word, otherwise use remainder. mov ax,[esi] ; get word code in ax lea esi,[esi+2] test ax,ax ; set flags. (not 32bit register so neg flag works) jle not_long_skip ; ; SHORTSKIP AND LONGSKIP ; do_skip: sub edi,edx ; go back to beginning or row. add edx,eax ; incriment our count on current row recheck3: cmp edx,ebx ; are we past the end of the row jb end_col3 ; if not the jmp over the code sub edx,ebx ; Subtract width from the col counter add edi,[nextrow] ; jump to start of next row jmp recheck3 ; jump up to see if we are at the right row end_col3: add edi,edx ; get to correct position in row. jmp top_loop not_long_skip: jz stop ; long count of zero means stop sub eax,08000h ; opcode -= 0x8000 test eax,04000h ; is it a LONGRUN (code & 0x4000)? je long_dump ; ; LONGRUN ; sub eax,04000h ; opcode -= 0x4000 mov ecx,eax ; use cx as loop count jmp do_run ; jump to run code. ; ; LONGDUMP ; long_dump: mov ecx,eax ; use cx as loop count jmp dump_loop ; go to the dump loop. stop: } } /* ;---------------------------------------------------------------------------- ;*************************************************************************** ;* COPY_DELTA_BUFFER -- Copies XOR Delta Data to a section of a page. * ;* This function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport. * ;* The registers must be setup as follows : * ;* * ;* INPUT: * ;* es:edi - destination segment:offset onto page. * ;* ds:esi - source buffer segment:offset of delta data. * ;* dx,cx,ax - are all zeroed out before entry. * ;* * ;* OUTPUT: * ;* * ;* WARNINGS: * ;* * ;* HISTORY: * ;* 03/09/1992 SB : Created. * ;*=========================================================================* */ void __cdecl Copy_Delta_Buffer(int nextrow) { /* ARG nextrow:DWORD */ __asm { top_loop: xor eax,eax ; clear out eax. mov al,[esi] ; get delta source byte inc esi test al,al ; check for a SHORTDUMP ; check al incase of sign value. je short_run js check_others ; ; SHORTDUMP ; mov ecx,eax ; stick count in cx dump_loop: mov al,[esi] ; get delta XOR byte mov [edi],al ; store that byte on the dest inc edx ; increment our count on current column inc esi inc edi cmp edx,ebx ; are we at the final column jne end_col1 ; if not the jmp over the code sub edi,edx ; get our column back to the beginning. xor edx,edx ; zero out our column counter add edi,[nextrow] ; jump to start of next row end_col1: dec ecx jnz dump_loop jmp top_loop ; ; SHORTRUN ; short_run: mov cl,[esi] ; get count inc esi ; inc delta source do_run: mov al,[esi] ; get XOR byte inc esi run_loop: mov [edi],al ; store the byte (instead of XOR against current color) inc edx ; increment our count on current column inc edi ; go to next dest pixel cmp edx,ebx ; are we at the final column jne end_col2 ; if not the jmp over the code sub edi,ebx ; get our column back to the beginning. xor edx,edx ; zero out our column counter add edi,[nextrow] ; jump to start of next row end_col2: dec ecx jnz run_loop jmp top_loop ; ; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP ; check_others: sub eax,080h ; opcode -= 0x80 jnz do_skip ; if zero then get next word, otherwise use remainder. mov ax,[esi] ; get word code in ax lea esi,[esi+2] test ax,ax ; set flags. (not 32bit register so neg flag works) jle not_long_skip ; ; SHORTSKIP AND LONGSKIP ; do_skip: sub edi,edx ; go back to beginning or row. add edx,eax ; incriment our count on current row recheck3: cmp edx,ebx ; are we past the end of the row jb end_col3 ; if not the jmp over the code sub edx,ebx ; Subtract width from the col counter add edi,[nextrow] ; jump to start of next row jmp recheck3 ; jump up to see if we are at the right row end_col3: add edi,edx ; get to correct position in row. jmp top_loop not_long_skip: jz stop ; long count of zero means stop sub eax,08000h ; opcode -= 0x8000 test eax,04000h ; is it a LONGRUN (code & 0x4000)? je long_dump ; ; LONGRUN ; sub eax,04000h ; opcode -= 0x4000 mov ecx,eax ; use cx as loop count jmp do_run ; jump to run code. ; ; LONGDUMP ; long_dump: mov ecx,eax ; use cx as loop count jmp dump_loop ; go to the dump loop. stop: } } /* ;---------------------------------------------------------------------------- */ /* ;*************************************************************************** ;** 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 : FADING.ASM * ;* * ;* Programmer : Joe L. Bostic * ;* * ;* Start Date : August 20, 1993 * ;* * ;* Last Update : August 20, 1993 [JLB] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * IDEAL P386 MODEL USE32 FLAT GLOBAL C Build_Fading_Table :NEAR CODESEG ;*********************************************************** ; BUILD_FADING_TABLE ; ; void *Build_Fading_Table(void *palette, void *dest, long int color, long int frac); ; ; This routine will create the fading effect table used to coerce colors ; from toward a common value. This table is used when Fading_Effect is ; active. ; ; Bounds Checking: None ;* */ void * __cdecl Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac) { /* PROC Build_Fading_Table C near USES ebx, ecx, edi, esi ARG palette:DWORD ARG dest:DWORD ARG color:DWORD ARG frac:DWORD LOCAL matchvalue:DWORD ; Last recorded match value. LOCAL targetred:BYTE ; Target gun red. LOCAL targetgreen:BYTE ; Target gun green. LOCAL targetblue:BYTE ; Target gun blue. LOCAL idealred:BYTE LOCAL idealgreen:BYTE LOCAL idealblue:BYTE LOCAL matchcolor:BYTE ; Tentative match color. */ int matchvalue = 0; //:DWORD ; Last recorded match value. unsigned char targetred = 0; //BYTE ; Target gun red. unsigned char targetgreen = 0; //BYTE ; Target gun green. unsigned char targetblue = 0; //BYTE ; Target gun blue. unsigned char idealred = 0; //BYTE unsigned char idealgreen = 0; //BYTE unsigned char idealblue = 0; //BYTE unsigned char matchcolor = 0; //:BYTE ; Tentative match color. __asm { cld ; If the source palette is NULL, then just return with current fading table pointer. cmp [palette],0 je fini cmp [dest],0 je fini ; Fractions above 255 become 255. mov eax,[frac] cmp eax,0100h jb short ok mov [frac],0FFh ok: ; Record the target gun values. mov esi,[palette] mov ebx,[color] add esi,ebx add esi,ebx add esi,ebx lodsb mov [targetred],al lodsb mov [targetgreen],al lodsb mov [targetblue],al ; Main loop. xor ebx,ebx ; Remap table index. ; Transparent black never gets remapped. mov edi,[dest] mov [edi],bl inc edi ; EBX = source palette logical number (1..255). ; EDI = running pointer into dest remap table. mainloop: inc ebx mov esi,[palette] add esi,ebx add esi,ebx add esi,ebx mov edx,[frac] shr edx,1 ; new = orig - ((orig-target) * fraction); lodsb ; orig mov dh,al ; preserve it for later. sub al,[targetred] ; al = (orig-target) imul dl ; ax = (orig-target)*fraction shl ax,1 sub dh,ah ; dh = orig - ((orig-target) * fraction) mov [idealred],dh ; preserve ideal color gun value. lodsb ; orig mov dh,al ; preserve it for later. sub al,[targetgreen] ; al = (orig-target) imul dl ; ax = (orig-target)*fraction shl ax,1 sub dh,ah ; dh = orig - ((orig-target) * fraction) mov [idealgreen],dh ; preserve ideal color gun value. lodsb ; orig mov dh,al ; preserve it for later. sub al,[targetblue] ; al = (orig-target) imul dl ; ax = (orig-target)*fraction shl ax,1 sub dh,ah ; dh = orig - ((orig-target) * fraction) mov [idealblue],dh ; preserve ideal color gun value. ; Sweep through the entire existing palette to find the closest ; matching color. Never matches with color 0. mov eax,[color] mov [matchcolor],al ; Default color (self). mov [matchvalue],-1 ; Ridiculous match value init. mov ecx,255 mov esi,[palette] ; Pointer to original palette. add esi,3 ; BH = color index. mov bh,1 innerloop: ; Recursion through the fading table won't work if a color is allowed ; to remap to itself. Prevent this from occuring. add esi,3 cmp bh,bl je short notclose sub esi,3 xor edx,edx ; Comparison value starts null. mov eax,edx ; Build the comparison value based on the sum of the differences of the color ; guns squared. lodsb sub al,[idealred] mov ah,al imul ah add edx,eax lodsb sub al,[idealgreen] mov ah,al imul ah add edx,eax lodsb sub al,[idealblue] mov ah,al imul ah add edx,eax jz short perfect ; If perfect match found then quit early. cmp edx,[matchvalue] ja short notclose mov [matchvalue],edx ; Record new possible color. mov [matchcolor],bh notclose: inc bh ; Checking color index. loop innerloop mov bh,[matchcolor] perfect: mov [matchcolor],bh xor bh,bh ; Make BX valid main index again. ; When the loop exits, we have found the closest match. mov al,[matchcolor] stosb cmp ebx,255 jne mainloop fini: mov eax,[dest] // ret } } /* ;*************************************************************************** ;** 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 Library * ;* * ;* File Name : PAL.ASM * ;* * ;* Programmer : Joe L. Bostic * ;* * ;* Start Date : May 30, 1992 * ;* * ;* Last Update : April 27, 1994 [BR] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* Set_Palette_Range -- Sets changed values in the palette. * ;* Bump_Color -- adjusts specified color in specified palette * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ;********************** Model & Processor Directives ************************ IDEAL P386 MODEL USE32 FLAT ;include "keyboard.inc" FALSE = 0 TRUE = 1 ;****************************** Declarations ******************************** GLOBAL C Set_Palette_Range:NEAR GLOBAL C Bump_Color:NEAR GLOBAL C CurrentPalette:BYTE:768 GLOBAL C PaletteTable:byte:1024 ;********************************** Data ************************************ LOCALS ?? DATASEG CurrentPalette DB 768 DUP(255) ; copy of current values of DAC regs PaletteTable DB 1024 DUP(0) IFNDEF LIB_EXTERNS_RESOLVED VertBlank DW 0 ; !!!! this should go away ENDIF ;********************************** Code ************************************ CODESEG */ extern "C" unsigned char CurrentPalette[768] = {255}; // DB 768 DUP(255) ; copy of current values of DAC regs extern "C" unsigned char PaletteTable[1024] = {0}; // DB 1024 DUP(0) /* ;*************************************************************************** ;* SET_PALETTE_RANGE -- Sets a palette range to the new pal * ;* * ;* INPUT: * ;* * ;* OUTPUT: * ;* * ;* PROTO: * ;* * ;* WARNINGS: This routine is optimized for changing a small number of * ;* colors in the palette. ;* * ;* HISTORY: * ;* 03/07/1995 PWG : Created. * ;*=========================================================================* */ void __cdecl Set_Palette_Range(void *palette) { memcpy(CurrentPalette, palette, 768); Set_DD_Palette(palette); /* PROC Set_Palette_Range C NEAR ARG palette:DWORD GLOBAL Set_DD_Palette_:near GLOBAL Wait_Vert_Blank_:near pushad mov esi,[palette] mov ecx,768/4 mov edi,offset CurrentPalette cld rep movsd ;call Wait_Vert_Blank_ mov eax,[palette] push eax call Set_DD_Palette_ pop eax popad ret */ } /* ;*************************************************************************** ;* Bump_Color -- adjusts specified color in specified palette * ;* * ;* INPUT: * ;* VOID *palette - palette to modify * ;* WORD changable - color # to change * ;* WORD target - color to bend toward * ;* * ;* OUTPUT: * ;* * ;* WARNINGS: * ;* * ;* HISTORY: * ;* 04/27/1994 BR : Converted to 32-bit. * ;*=========================================================================* ; BOOL cdecl Bump_Color(VOID *palette, WORD changable, WORD target); */ BOOL __cdecl Bump_Color(void *pal, int color, int desired) { /* PROC Bump_Color C NEAR USES ebx,ecx,edi,esi ARG pal:DWORD, color:WORD, desired:WORD LOCAL changed:WORD ; Has palette changed? */ short short_color = (short) color; short short_desired = (short) desired; bool changed = false; __asm { mov edi,[pal] ; Original palette pointer. mov esi,edi mov eax,0 mov ax,[short_color] add edi,eax add edi,eax add edi,eax ; Offset to changable color. mov ax,[short_desired] add esi,eax add esi,eax add esi,eax ; Offset to target color. mov [changed],FALSE ; Presume no change. mov ecx,3 ; Three color guns. ; Check the color gun. colorloop: mov al,[BYTE PTR esi] sub al,[BYTE PTR edi] ; Carry flag is set if subtraction needed. jz short gotit mov [changed],TRUE inc [BYTE PTR edi] ; Presume addition. jnc short gotit ; oops, subtraction needed so dec twice. dec [BYTE PTR edi] dec [BYTE PTR edi] gotit: inc edi inc esi loop colorloop movzx eax,[changed] } } /* ;*************************************************************************** ;** 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 : GraphicViewPortClass * ;* * ;* File Name : PUTPIXEL.ASM * ;* * ;* Programmer : Phil Gorrow * ;* * ;* Start Date : June 7, 1994 * ;* * ;* Last Update : June 8, 1994 [PWG] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* VVPC::Put_Pixel -- Puts a pixel on a virtual viewport * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * IDEAL P386 MODEL USE32 FLAT INCLUDE ".\drawbuff.inc" INCLUDE ".\gbuffer.inc" CODESEG */ /* ;*************************************************************************** ;* VVPC::PUT_PIXEL -- Puts a pixel on a virtual viewport * ;* * ;* INPUT: WORD the x position for the pixel relative to the upper * ;* left corner of the viewport * ;* WORD the y pos for the pixel relative to the upper left * ;* corner of the viewport * ;* UBYTE the color of the pixel to write * ;* * ;* OUTPUT: none * ;* * ;* WARNING: If pixel is to be placed outside of the viewport then * ;* this routine will abort. * ;* * ;* HISTORY: * ;* 06/08/1994 PWG : Created. * ;*=========================================================================* PROC Buffer_Put_Pixel C near USES eax,ebx,ecx,edx,edi */ void __cdecl Buffer_Put_Pixel(void * this_object, int x_pixel, int y_pixel, unsigned char color) { /* ARG this_object:DWORD ; this is a member function ARG x_pixel:DWORD ; x position of pixel to set ARG y_pixel:DWORD ; y position of pixel to set ARG color:BYTE ; what color should we clear to */ __asm { ;*=================================================================== ; Get the viewport information and put bytes per row in ecx ;*=================================================================== mov ebx,[this_object] ; get a pointer to viewport xor eax,eax mov edi,[ebx]GraphicViewPortClass.Offset ; get the correct offset mov ecx,[ebx]GraphicViewPortClass.Height ; edx = height of viewport mov edx,[ebx]GraphicViewPortClass.Width ; ecx = width of viewport ;*=================================================================== ; Verify that the X pixel offset if legal ;*=================================================================== mov eax,[x_pixel] ; find the x position cmp eax,edx ; is it out of bounds jae short done ; if so then get out add edi,eax ; otherwise add in offset ;*=================================================================== ; Verify that the Y pixel offset if legal ;*=================================================================== mov eax,[y_pixel] ; get the y position cmp eax,ecx ; is it out of bounds jae done ; if so then get out add edx,[ebx]GraphicViewPortClass.XAdd ; otherwise find bytes per row add edx,[ebx]GraphicViewPortClass.Pitch ; add in direct draw pitch mul edx ; offset = bytes per row * y add edi,eax ; add it into the offset ;*=================================================================== ; Write the pixel to the screen ;*=================================================================== mov al,[color] ; read in color value mov [edi],al ; write it to the screen done: } } /* ;*************************************************************************** ;** 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 : Support Library * ;* * ;* File Name : cliprect.asm * ;* * ;* Programmer : Julio R Jerez * ;* * ;* Start Date : Mar, 2 1995 * ;* * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* int Clip_Rect ( int * x , int * y , int * dw , int * dh , * ;* int width , int height ) ; * ;* int Confine_Rect ( int * x , int * y , int * dw , int * dh , * ;* int width , int height ) ; * ;* * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * IDEAL P386 MODEL USE32 FLAT GLOBAL C Clip_Rect :NEAR GLOBAL C Confine_Rect :NEAR CODESEG ;*************************************************************************** ;* Clip_Rect -- clip a given rectangle against a given window * ;* * ;* INPUT: &x , &y , &w , &h -> Pointer to rectangle being clipped * ;* width , height -> dimension of clipping window * ;* * ;* OUTPUT: a) Zero if the rectangle is totally contained by the * ;* clipping window. * ;* b) A negative value if the rectangle is totally outside the * ;* the clipping window * ;* c) A positive value if the rectangle was clipped against the * ;* clipping window, also the values pointed by x, y, w, h will * ;* be modified to new clipped values * ;* * ;* 05/03/1995 JRJ : added comment * ;*=========================================================================* ; int Clip_Rect (int* x, int* y, int* dw, int* dh, int width, int height); * */ extern "C" int __cdecl Clip_Rect ( int * x , int * y , int * w , int * h , int width , int height ) { /* PROC Clip_Rect C near uses ebx,ecx,edx,esi,edi arg x:dword arg y:dword arg w:dword arg h:dword arg width:dword arg height:dword */ __asm { ;This Clipping algorithm is a derivation of the very well known ;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency ;it is probably the most commontly implemented algorithm both in software ;and hardware for clipping lines, rectangles, and convex polygons against ;a rectagular clipping window. For reference see ;"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes ; pages 113 to 177". ; Briefly consist in computing the Sutherland code for both end point of ; the rectangle to find out if the rectangle is: ; - trivially accepted (no further clipping test, return the oroginal data) ; - trivially rejected (return with no action, return error code) ; - retangle must be iteratively clipped again edges of the clipping window ; and return the clipped rectangle ; get all four pointer into regisnters mov esi,[x] ; esi = pointer to x mov edi,[y] ; edi = pointer to x mov eax,[w] ; eax = pointer to dw mov ebx,[h] ; ebx = pointer to dh ; load the actual data into reg mov esi,[esi] ; esi = x0 mov edi,[edi] ; edi = y0 mov eax,[eax] ; eax = dw mov ebx,[ebx] ; ebx = dh ; create a wire frame of the type [x0,y0] , [x1,y1] add eax,esi ; eax = x1 = x0 + dw add ebx,edi ; ebx = y1 = y0 + dh ; we start we suthenland code0 and code1 set to zero xor ecx,ecx ; cl = sutherland boolean code0 xor edx,edx ; dl = sutherland boolean code0 ; now we start computing the to suthenland boolean code for x0 , x1 shld ecx,esi,1 ; bit3 of code0 = sign bit of (x0 - 0) shld edx,eax,1 ; bit3 of code1 = sign bit of (x1 - 0) sub esi,[width] ; get the difference (x0 - (width + 1)) sub eax,[width] ; get the difference (x1 - (width + 1)) dec esi dec eax shld ecx,esi,1 ; bit2 of code0 = sign bit of (x0 - (width + 1)) shld edx,eax,1 ; bit2 of code1 = sign bit of (x0 - (width + 1)) ; now we start computing the to suthenland boolean code for y0 , y1 shld ecx,edi,1 ; bit1 of code0 = sign bit of (y0 - 0) shld edx,ebx,1 ; bit1 of code1 = sign bit of (y0 - 0) sub edi,[height] ; get the difference (y0 - (height + 1)) sub ebx,[height] ; get the difference (y1 - (height + 1)) dec edi dec ebx shld ecx,edi,1 ; bit0 of code0 = sign bit of (y0 - (height + 1)) shld edx,ebx,1 ; bit0 of code1 = sign bit of (y1 - (height + 1)) ; Bit 2 and 0 of cl and bl are complemented xor cl,5 ; reverse bit2 and bit0 in code0 xor dl,5 ; reverse bit2 and bit0 in code1 ; now perform the rejection test mov eax,-1 ; set return code to false mov bl,cl ; save code0 for future use test dl,cl ; if any two pair of bit in code0 and code1 is set jnz clip_out ; then rectangle is outside the window ; now perform the aceptance test xor eax,eax ; set return code to true or bl,dl ; if all pair of bits in code0 and code1 are reset jz clip_out ; then rectangle is insize the window. ' ; we need to clip the rectangle iteratively mov eax,-1 ; set return code to false test cl,1000b ; if bit3 of code0 is set then the rectangle jz left_ok ; spill out the left edge of the window mov edi,[x] ; edi = a pointer to x0 mov ebx,[w] ; ebx = a pointer to dw mov esi,[edi] ; esi = x0 mov [dword ptr edi],0 ; set x0 to 0 "this the left edge value" add [ebx],esi ; adjust dw by x0, since x0 must be negative left_ok: test cl,0010b ; if bit1 of code0 is set then the rectangle jz bottom_ok ; spill out the bottom edge of the window mov edi,[y] ; edi = a pointer to y0 mov ebx,[h] ; ebx = a pointer to dh mov esi,[edi] ; esi = y0 mov [dword ptr edi],0 ; set y0 to 0 "this the bottom edge value" add [ebx],esi ; adjust dh by y0, since y0 must be negative bottom_ok: test dl,0100b ; if bit2 of code1 is set then the rectangle jz right_ok ; spill out the right edge of the window mov edi,[w] ; edi = a pointer to dw mov esi,[x] ; esi = a pointer to x mov ebx,[width] ; ebx = the width of the window sub ebx,[esi] ; the new dw is the difference (width-x0) mov [edi],ebx ; adjust dw to (width - x0) jle clip_out ; if (width-x0) = 0 then the clipped retangle ; has no width we are done right_ok: test dl,0001b ; if bit0 of code1 is set then the rectangle jz clip_ok ; spill out the top edge of the window mov edi,[h] ; edi = a pointer to dh mov esi,[y] ; esi = a pointer to y0 mov ebx,[height] ; ebx = the height of the window sub ebx,[esi] ; the new dh is the difference (height-y0) mov [edi],ebx ; adjust dh to (height-y0) jle clip_out ; if (width-x0) = 0 then the clipped retangle ; has no width we are done clip_ok: mov eax,1 ; signal the calling program that the rectangle was modify clip_out: //ret } //ENDP Clip_Rect } /* ;*************************************************************************** ;* Confine_Rect -- clip a given rectangle against a given window * ;* * ;* INPUT: &x,&y,w,h -> Pointer to rectangle being clipped * ;* width,height -> dimension of clipping window * ;* * ;* OUTPUT: a) Zero if the rectangle is totally contained by the * ;* clipping window. * ;* c) A positive value if the rectangle was shifted in position * ;* to fix inside the clipping window, also the values pointed * ;* by x, y, will adjusted to a new values * ;* * ;* NOTE: this function make not attempt to verify if the rectangle is * ;* bigger than the clipping window and at the same time wrap around* ;* it. If that is the case the result is meaningless * ;*=========================================================================* ; int Confine_Rect (int* x, int* y, int dw, int dh, int width, int height); * */ extern "C" int __cdecl Confine_Rect ( int * x , int * y , int w , int h , int width , int height ) { /* PROC Confine_Rect C near uses ebx, esi,edi arg x:dword arg y:dword arg w:dword arg h:dword arg width :dword arg height:dword */ __asm { xor eax,eax mov ebx,[x] mov edi,[w] mov esi,[ebx] add edi,[ebx] sub edi,[width] neg esi dec edi test esi,edi jl x_axix_ok mov eax,1 test esi,esi jl shift_right mov [dword ptr ebx],0 jmp x_axix_ok shift_right: inc edi sub [ebx],edi x_axix_ok: mov ebx,[y] mov edi,[h] mov esi,[ebx] add edi,[ebx] sub edi,[height] neg esi dec edi test esi,edi jl confi_out mov eax,1 test esi,esi jl shift_top mov [dword ptr ebx],0 //ret jmp confi_out shift_top: inc edi sub [ebx],edi confi_out: //ret //ENDP Confine_Rect } } /* ; $Header: //depot/Projects/Mobius/QA/Project/Run/SOURCECODE/REDALERT/WIN32LIB/DrawMisc.cpp#33 $ ;*************************************************************************** ;** 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 routine * ;* * ;* File Name : UNCOMP.ASM * ;* * ;* Programmer : Christopher Yates * ;* * ;* Last Update : 20 August, 1990 [CY] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* * ; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length); * ;* * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * IDEAL P386 MODEL USE32 FLAT GLOBAL C LCW_Uncompress :NEAR CODESEG ; ---------------------------------------------------------------- ; ; Here are prototypes for the routines defined within this module: ; ; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length); ; ; ---------------------------------------------------------------- */ #if (0)//ST 5/10/2019 extern "C" unsigned long __cdecl LCW_Uncompress(void *source, void *dest, unsigned long length_) { //PROC LCW_Uncompress C near // // USES ebx,ecx,edx,edi,esi // // ARG source:DWORD // ARG dest:DWORD // ARG length:DWORD //;LOCALS // LOCAL a1stdest:DWORD // LOCAL maxlen:DWORD // LOCAL lastbyte:DWORD // LOCAL lastcom:DWORD // LOCAL lastcom1:DWORD unsigned long a1stdest; unsigned long maxlen; unsigned long lastbyte; //unsigned long lastcom; //unsigned long lastcom1; __asm { mov edi,[dest] mov esi,[source] mov edx,[length_] ; ; ; uncompress data to the following codes in the format b = byte, w = word ; n = byte code pulled from compressed data ; Bit field of n command description ; n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3 ; n=10xxxxxx,n1,n2,...,nx+1 med length copy the next x+1 bytes ; n=11xxxxxx,w1 med run run x+3 bytes from offset w1 ; n=11111111,w1,w2 long copy copy w1 bytes from offset w2 ; n=11111110,w1,b1 long run run byte b1 for w1 bytes ; n=10000000 end end of data reached ; mov [a1stdest],edi add edx,edi mov [lastbyte],edx cld ; make sure all lod and sto are forward mov ebx,esi ; save the source offset loop_label: mov eax,[lastbyte] sub eax,edi ; get the remaining byte to uncomp jz short out_label ; were done mov [maxlen],eax ; save for string commands mov esi,ebx ; mov in the source index xor eax,eax mov al,[esi] inc esi test al,al ; see if its a short run js short notshort mov ecx,eax ;put count nibble in cl mov ah,al ; put rel offset high nibble in ah and ah,0Fh ; only 4 bits count shr cl,4 ; get run -3 add ecx,3 ; get actual run length cmp ecx,[maxlen] ; is it too big to fit? jbe short rsok ; if not, its ok mov ecx,[maxlen] ; if so, max it out so it dosen't overrun rsok: mov al,[esi] ; get rel offset low byte lea ebx,[esi+1] ; save the source offset mov esi,edi ; get the current dest sub esi,eax ; get relative offset rep movsb jmp loop_label notshort: test al,40h ; is it a length? jne short notlength ; if not it could be med or long run cmp al,80h ; is it the end? je short out_label ; if so its over mov cl,al ; put the byte in count register and ecx,3Fh ; and off the extra bits cmp ecx,[maxlen] ; is it too big to fit? jbe short lenok ; if not, its ok mov ecx,[maxlen] ; if so, max it out so it dosen't overrun lenok: rep movsb mov ebx,esi ; save the source offset jmp loop_label out_label: mov eax,edi sub eax,[a1stdest] jmp label_exit notlength: mov cl,al ; get the entire code and ecx,3Fh ; and off all but the size -3 add ecx,3 ; add 3 for byte count cmp al,0FEh jne short notrunlength xor ecx,ecx mov cx,[esi] xor eax,eax mov al,[esi+2] lea ebx,[esi+3] ;save the source offset cmp ecx,[maxlen] ; is it too big to fit? jbe short runlenok ; if not, its ok mov ecx,[maxlen] ; if so, max it out so it dosen't overrun runlenok: test ecx,0ffe0h jnz dont_use_stosb rep stosb jmp loop_label dont_use_stosb: mov ah,al mov edx,eax shl eax,16 or eax,edx test edi,3 jz aligned mov [edi],eax mov edx,edi and edi,0fffffffch lea edi,[edi+4] and edx,3 dec dl xor dl,3 sub ecx,edx aligned: mov edx,ecx shr ecx,2 rep stosd and edx,3 jz loop_label mov ecx,edx rep stosb jmp loop_label notrunlength: cmp al,0FFh ; is it a long run? jne short notlong ; if not use the code as the size xor ecx,ecx xor eax,eax mov cx,[esi] ; if so, get the size lea esi,[esi+2] notlong: mov ax,[esi] ;get the real index add eax,[a1stdest] ;add in the 1st index lea ebx,[esi+2] ;save the source offset cmp ecx,[maxlen] ;compare for overrun mov esi,eax ;use eax as new source jbe short runok ; if not, its ok mov ecx,[maxlen] ; if so, max it out so it dosen't overrun runok: test ecx,0ffe0h jnz dont_use_movsb rep movsb jmp loop_label dont_use_movsb: lea edx,[edi+0fffffffch] cmp esi,edx ja use_movsb test edi,3 jz aligned2 mov eax,[esi] mov [edi],eax mov edx,edi and edi,0fffffffch lea edi,[edi+4] and edx,3 dec dl xor dl,3 sub ecx,edx add esi,edx aligned2: mov edx,ecx shr ecx,2 and edx,3 rep movsd mov ecx,edx use_movsb: rep movsb jmp loop_label label_exit: mov eax,edi mov ebx,[dest] sub eax,ebx //ret } } #endif /* ;*************************************************************************** ;** 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 : TOPAGE.ASM * ;* * ;* Programmer : Phil W. Gorrow * ;* * ;* Start Date : June 8, 1994 * ;* * ;* Last Update : June 15, 1994 [PWG] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* Buffer_To_Page -- Copies a linear buffer to a virtual viewport * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * IDEAL P386 MODEL USE32 FLAT TRANSP equ 0 INCLUDE ".\drawbuff.inc" INCLUDE ".\gbuffer.inc" CODESEG ;*************************************************************************** ;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport * ;* * ;* INPUT: WORD x_pixel - x pixel on viewport to copy from * ;* WORD y_pixel - y pixel on viewport to copy from * ;* WORD pixel_width - the width of copy region * ;* WORD pixel_height - the height of copy region * ;* BYTE * src - buffer to copy from * ;* VVPC * dest - virtual viewport to copy to * ;* * ;* OUTPUT: none * ;* * ;* WARNINGS: Coordinates and dimensions will be adjusted if they exceed * ;* the boundaries. In the event that no adjustment is * ;* possible this routine will abort. If the size of the * ;* region to copy exceeds the size passed in for the buffer * ;* the routine will automatically abort. * ;* * ;* HISTORY: * ;* 06/15/1994 PWG : Created. * ;*=========================================================================* */ extern "C" long __cdecl Buffer_To_Page(int x, int y, int w, int h, void *buffer, void *dest) { GraphicViewPortClass& vp = *(GraphicViewPortClass*)dest; // from chronoshift int xstart = x; int ystart = y; int xend = x + w - 1; int yend = y + h - 1; int xoffset = 0; int yoffset = 0; // If we aren't drawing within the viewport, return if (!buffer || xstart >= vp.Get_Width() || ystart >= vp.Get_Height() || xend < 0 || yend < 0) { } // Clipping if (xstart < 0) { xoffset = -xstart; xstart = 0; } if (ystart < 0) { yoffset += h * (-ystart); ystart = 0; } xend = min(xend, vp.Get_Width() - 1); yend = min(yend, vp.Get_Height() - 1); int pitch = vp.Get_Pitch() + vp.Get_Width() + vp.Get_XAdd(); uint8_t* dst = (y * 4) * pitch + (x * 4) + (uint8_t*)(vp.Get_Offset()); uint8_t* src = xoffset + w * yoffset + static_cast(buffer); // int dst_pitch = x_pos + pitch - xend; // int src_pitch = x_pos + width - xend; int lines = yend - ystart + 1; int blit_width = xend - xstart + 1; // blit while (lines--) { FastScanlinePaletteBlit(dst, src, blit_width); src += w; dst += pitch * 4; } return 0; } //ENDP Buffer_To_Page //END /* ;*************************************************************************** ;* VVPC::GET_PIXEL -- Gets a pixel from the current view port * ;* * ;* INPUT: WORD the x pixel on the screen. * ;* WORD the y pixel on the screen. * ;* * ;* OUTPUT: UBYTE the pixel at the specified location * ;* * ;* WARNING: If pixel is to be placed outside of the viewport then * ;* this routine will abort. * ;* * ;* HISTORY: * ;* 06/07/1994 PWG : Created. * ;*=========================================================================* PROC Buffer_Get_Pixel C near USES ebx,ecx,edx,edi ARG this_object:DWORD ; this is a member function ARG x_pixel:DWORD ; x position of pixel to set ARG y_pixel:DWORD ; y position of pixel to set */ extern "C" int __cdecl Buffer_Get_Pixel(void * this_object, int x_pixel, int y_pixel) { __asm { ;*=================================================================== ; Get the viewport information and put bytes per row in ecx ;*=================================================================== mov ebx,[this_object] ; get a pointer to viewport xor eax,eax mov edi,[ebx]GraphicViewPortClass.Offset ; get the correct offset mov ecx,[ebx]GraphicViewPortClass.Height ; edx = height of viewport mov edx,[ebx]GraphicViewPortClass.Width ; ecx = width of viewport ;*=================================================================== ; Verify that the X pixel offset if legal ;*=================================================================== mov eax,[x_pixel] ; find the x position cmp eax,edx ; is it out of bounds jae short exit_label ; if so then get out add edi,eax ; otherwise add in offset ;*=================================================================== ; Verify that the Y pixel offset if legal ;*=================================================================== mov eax,[y_pixel] ; get the y position cmp eax,ecx ; is it out of bounds jae exit_label ; if so then get out add edx,[ebx]GraphicViewPortClass.XAdd ; otherwise find bytes per row add edx,[ebx]GraphicViewPortClass.Pitch ; otherwise find bytes per row mul edx ; offset = bytes per row * y add edi,eax ; add it into the offset ;*=================================================================== ; Write the pixel to the screen ;*=================================================================== xor eax,eax ; clear the word mov al,[edi] ; read in the pixel exit_label: //ret //ENDP Buffer_Get_Pixel } }