CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

DrawMisc.cpp (153833B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /*
     17 ** 
     18 ** 
     19 **  Misc asm functions from ww lib
     20 **  ST - 12/19/2018 1:20PM
     21 ** 
     22 ** 
     23 ** 
     24 ** 
     25 ** 
     26 ** 
     27 ** 
     28 ** 
     29 ** 
     30 ** 
     31 ** 
     32 */
     33 
     34 #include "gbuffer.h"
     35 #include "MISC.H"
     36 
     37 IconCacheClass::IconCacheClass (void)
     38 {
     39 	IsCached			=FALSE;
     40 	SurfaceLost		=FALSE;
     41 	DrawFrequency	=0;
     42 	CacheSurface	=NULL;
     43 	IconSource		=NULL;
     44 }
     45 
     46 IconCacheClass::~IconCacheClass (void)
     47 {
     48 }		  
     49 
     50 IconCacheClass	CachedIcons[MAX_CACHED_ICONS];
     51 
     52 extern "C"{
     53 IconSetType		IconSetList[MAX_ICON_SETS];
     54 short				IconCacheLookup[MAX_LOOKUP_ENTRIES];
     55 }
     56 
     57 int		CachedIconsDrawn=0;		//Counter of number of cache hits
     58 int		UnCachedIconsDrawn=0;	//Counter of number of cache misses
     59 BOOL	CacheMemoryExhausted;	//Flag set if we have run out of video RAM
     60 
     61 
     62 void Invalidate_Cached_Icons (void) {}
     63 void Restore_Cached_Icons (void) {}
     64 void Register_Icon_Set (void *icon_data , BOOL pre_cache) {};
     65 
     66 //
     67 // Prototypes for assembly language procedures in STMPCACH.ASM
     68 //
     69 extern "C" void __cdecl Clear_Icon_Pointers (void) {};
     70 extern "C" void __cdecl Cache_Copy_Icon (void const *icon_ptr ,void * , int) {};
     71 extern "C" int __cdecl Is_Icon_Cached (void const *icon_data , int icon) {return -1;};
     72 extern "C" int __cdecl Get_Icon_Index (void *icon_ptr) {return 0;};
     73 extern "C" int __cdecl Get_Free_Index (void) {return 0;};
     74 extern "C" BOOL __cdecl Cache_New_Icon (int icon_index, void *icon_ptr) {return -1;};
     75 extern "C" int __cdecl Get_Free_Cache_Slot(void) {return -1;}
     76 
     77 void IconCacheClass::Draw_It (LPDIRECTDRAWSURFACE dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height) {}
     78 
     79 
     80 
     81 extern	int	CachedIconsDrawn;
     82 extern	int	UnCachedIconsDrawn;
     83 
     84 
     85 extern "C" void __cdecl Set_Font_Palette_Range(void const *palette, INT start_idx, INT end_idx)
     86 {
     87 }		  
     88 
     89 
     90 /*
     91 ;***************************************************************************
     92 ;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *
     93 ;*                                                                         *
     94 ;* INPUT:	WORD sx_pixel 	- the starting x pixel position		   *
     95 ;*		WORD sy_pixel	- the starting y pixel position		   *
     96 ;*		WORD dx_pixel	- the destination x pixel position	   *
     97 ;*		WORD dy_pixel   - the destination y pixel position	   *
     98 ;*		WORD color      - the color of the line to draw		   *
     99 ;*                                                                         *
    100 ;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel	   *
    101 ;*       with the graphic viewport it has been assigned to.		   *
    102 ;*                                                                         *
    103 ;* HISTORY:                                                                *
    104 ;*   06/16/1994 PWG : Created.                                             *
    105 ;*   08/30/1994 IML : Fixed clipping bug.				   *
    106 ;*=========================================================================*
    107 	PROC	Buffer_Draw_Line C NEAR
    108 	USES	eax,ebx,ecx,edx,esi,edi
    109 */
    110 
    111 void __cdecl Buffer_Draw_Line(void *this_object, int sx, int sy, int dx, int dy, unsigned char color)
    112 {
    113 	unsigned int clip_min_x;
    114 	unsigned int clip_max_x;
    115 	unsigned int clip_min_y;
    116 	unsigned int clip_max_y;
    117 	unsigned int clip_var;
    118 	unsigned int accum;
    119 	unsigned int bpr;
    120 	
    121 	static int _one_time_init = 0;
    122 
    123 	//clip_tbl	DD	nada,a_up,a_dwn,nada
    124 	//		DD	a_lft,a_lft,a_dwn,nada
    125 	//		DD	a_rgt,a_up,a_rgt,nada
    126 	//		DD	nada,nada,nada,nada
    127 
    128 	static void *_clip_table [4*4] = {0};
    129 
    130 	unsigned int int_color = color;
    131 	unsigned int x1_pixel = (unsigned int) sx;
    132 	unsigned int y1_pixel = (unsigned int) sy;
    133 	unsigned int x2_pixel = (unsigned int) dx;
    134 	unsigned int y2_pixel = (unsigned int) dy;
    135 
    136 	__asm {		  
    137 		mov	eax,_one_time_init
    138 		and	eax,eax
    139 		jnz	init_done
    140 
    141 		call	do_init
    142 
    143 init_done:
    144 		
    145 		//;*==================================================================
    146 		//;* Take care of find the clip minimum and maximums
    147 		//;*==================================================================
    148 		mov	ebx,[this_object]
    149 		xor	eax,eax
    150 		mov	[clip_min_x],eax
    151 		mov	[clip_min_y],eax
    152 		mov	eax,[ebx]GraphicViewPortClass.Width
    153 		mov	[clip_max_x],eax
    154 		add	eax,[ebx]GraphicViewPortClass.XAdd
    155 		add	eax,[ebx]GraphicViewPortClass.Pitch
    156 		mov	[bpr],eax
    157 		mov	eax,[ebx]GraphicViewPortClass.Height
    158 		mov	[clip_max_y],eax
    159 
    160 		//;*==================================================================
    161 		//;* Adjust max pixels as they are tested inclusively.
    162 		//;*==================================================================
    163 		dec	[clip_max_x]
    164 		dec	[clip_max_y]
    165 
    166 		//;*==================================================================
    167 		//;* Set the registers with the data for drawing the line
    168 		//;*==================================================================
    169 		mov	eax,[x1_pixel]		//; eax = start x pixel position
    170 		mov	ebx,[y1_pixel]		//; ebx = start y pixel position
    171 		mov	ecx,[x2_pixel]		//; ecx = dest x pixel position
    172 		mov	edx,[y2_pixel]		//; edx = dest y pixel position
    173 
    174 		//;*==================================================================
    175 		//;* This is the section that "pushes" the line into bounds.
    176 		//;* I have marked the section with PORTABLE start and end to signify
    177 		//;* how much of this routine is 100% portable between graphics modes.
    178 		//;* It was just as easy to have variables as it would be for constants
    179 		//;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used
    180 		//;* to clip the line (default is the screen)
    181 		//;* PORTABLE start
    182 		//;*==================================================================
    183 
    184 		cmp	eax,[clip_min_x]
    185 		jl	short clip_it
    186 		cmp	eax,[clip_max_x]
    187 		jg	short clip_it
    188 		cmp	ebx,[clip_min_y]
    189 		jl	short clip_it
    190 		cmp	ebx,[clip_max_y]
    191 		jg	short clip_it
    192 		cmp	ecx,[clip_min_x]
    193 		jl	short clip_it
    194 		cmp	ecx,[clip_max_x]
    195 		jg	short clip_it
    196 		cmp	edx,[clip_min_y]
    197 		jl	short clip_it
    198 		cmp	edx,[clip_max_y]
    199 		jle	short on_screen
    200 
    201 		//;*==================================================================
    202 		//;* Takes care off clipping the line.
    203 		//;*==================================================================
    204 	clip_it:
    205 		call	set_bits
    206 		xchg	eax,ecx
    207 		xchg	ebx,edx
    208 		mov	edi,esi
    209 		call	set_bits
    210 		mov	[clip_var],edi
    211 		or	[clip_var],esi
    212 		jz	short on_screen
    213 		test	edi,esi
    214 		jne	short off_screen
    215 		shl	esi,2
    216 		//call	[clip_tbl+esi]
    217 		call	[_clip_table+esi]
    218 		jc	clip_it
    219 		xchg	eax,ecx
    220 		xchg	ebx,edx
    221 		shl	edi,2
    222 		//call	[clip_tbl+edi]
    223 		call	[_clip_table+edi]
    224 		jmp	clip_it
    225 
    226 	on_screen:
    227 		jmp	draw_it
    228 
    229 	off_screen:
    230 		jmp	and_out
    231 
    232 		//;*==================================================================
    233 		//;* Jump table for clipping conditions
    234 		//;*==================================================================
    235 	//clip_tbl	DD	nada,a_up,a_dwn,nada
    236 	//		DD	a_lft,a_lft,a_dwn,nada
    237 	//		DD	a_rgt,a_up,a_rgt,nada
    238 	//		DD	nada,nada,nada,nada
    239 
    240 	nada:
    241 		clc
    242 		ret
    243 
    244 	a_up:
    245 		mov	esi,[clip_min_y]
    246 		call	clip_vert
    247 		stc
    248 		ret
    249 
    250 	a_dwn:
    251 		mov	esi,[clip_max_y]
    252 		neg	esi
    253 		neg	ebx
    254 		neg	edx
    255 		call	clip_vert
    256 		neg	ebx
    257 		neg	edx
    258 		stc
    259 		ret
    260 
    261 		//;*==================================================================
    262 		//;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]
    263 		//;*==================================================================
    264 	clip_vert:
    265 		push	edx
    266 		push	eax
    267 		mov	[clip_var],edx		//; clip_var = yb
    268 		sub	[clip_var],ebx		//; clip_var = (yb-ya)
    269 		neg	eax			//; eax=-xa
    270 		add	eax,ecx			//; (ebx-xa)
    271 		mov	edx,esi			//; edx=miny
    272 		sub	edx,ebx			//; edx=(miny-ya)
    273 		imul	edx
    274 		idiv	[clip_var]
    275 		pop	edx
    276 		add	eax,edx
    277 		pop	edx
    278 		mov	ebx,esi
    279 		ret
    280 
    281 	a_lft:
    282 		mov	esi,[clip_min_x]
    283 		call	clip_horiz
    284 		stc
    285 		ret
    286 
    287 	a_rgt:
    288 		mov	esi,[clip_max_x]
    289 		neg	eax
    290 		neg	ecx
    291 		neg	esi
    292 		call	clip_horiz
    293 		neg	eax
    294 		neg	ecx
    295 		stc
    296 		ret
    297 
    298 		//;*==================================================================
    299 		//;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]
    300 		//;*==================================================================
    301 	clip_horiz:
    302 		push	edx
    303 		mov	[clip_var],ecx		//; clip_var = xb
    304 		sub	[clip_var],eax		//; clip_var = (xb-xa)
    305 		sub	edx,ebx			//; edx = (yb-ya)
    306 		neg	eax			//; eax = -xa
    307 		add	eax,esi			//; eax = (minx-xa)
    308 		imul	edx			//; eax = (minx-xa)(yb-ya)
    309 		idiv	[clip_var]		//; eax = (minx-xa)(yb-ya)/(xb-xa)
    310 		add	ebx,eax			//; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]
    311 		pop	edx
    312 		mov	eax,esi
    313 		ret
    314 
    315 		//;*==================================================================
    316 		//;* Sets the condition bits
    317 		//;*==================================================================
    318 	set_bits:
    319 		xor	esi,esi
    320 		cmp	ebx,[clip_min_y]	//; if y >= top its not up
    321 		jge	short a_not_up
    322 		or	esi,1
    323 
    324 	a_not_up:
    325 		cmp	ebx,[clip_max_y]	//; if y <= bottom its not down
    326 		jle	short a_not_down
    327 		or	esi,2
    328 
    329 	a_not_down:
    330 		cmp	eax,[clip_min_x]   	//; if x >= left its not left
    331 		jge	short a_not_left
    332 		or	esi,4
    333 
    334 	a_not_left:
    335 		cmp	eax,[clip_max_x]	//; if x <= right its not right
    336 		jle	short a_not_right
    337 		or	esi,8
    338 
    339 	a_not_right:
    340 		ret
    341 
    342 		//;*==================================================================
    343 		//;* Draw the line to the screen.
    344 		//;* PORTABLE end
    345 		//;*==================================================================
    346 	draw_it:
    347 		sub	edx,ebx			//; see if line is being draw down
    348 		jnz	short not_hline	//; if not then its not a hline
    349 		jmp	short hline		//; do special case h line
    350 
    351 	not_hline:
    352 		jg	short down		//; if so there is no need to rev it
    353 		neg	edx			//; negate for actual pixel length
    354 		xchg	eax,ecx			//; swap x's to rev line draw
    355 		sub	ebx,edx			//; get old edx
    356 
    357 	down:
    358 		push	edx
    359 		push	eax
    360 		mov	eax,[bpr]
    361 		mul	ebx
    362 		mov	ebx,eax
    363 		mov	eax,[this_object]
    364 		add	ebx,[eax]GraphicViewPortClass.Offset
    365 		pop	eax
    366 		pop	edx
    367 
    368 		mov	esi,1			//; assume a right mover
    369 		sub	ecx,eax			//; see if line is right
    370 		jnz	short not_vline	//; see if its a vertical line
    371 		jmp	vline
    372 
    373 	not_vline:
    374 		jg	short right		//; if so, the difference = length
    375 
    376 	//left:
    377 		neg	ecx			//; else negate for actual pixel length
    378 		neg	esi			//; negate counter to move left
    379 
    380 	right:
    381 		cmp	ecx,edx			//; is it a horiz or vert line
    382 		jge	short horiz		//; if ecx > edx then |x|>|y| or horiz
    383 
    384 	//vert:
    385 		xchg	ecx,edx			//; make ecx greater and edx lesser
    386 		mov	edi,ecx			//; set greater
    387 		mov	[accum],ecx		//; set accumulator to 1/2 greater
    388 		shr	[accum],1
    389 
    390 		//;*==================================================================
    391 		//;* at this point ...
    392 		//;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
    393 		//;* esi=adder; accum=accumulator
    394 		//;* in a vertical loop the adder is conditional and the inc constant
    395 		//;*==================================================================
    396 	//vert_loop:
    397 		add	ebx,eax
    398 		mov	eax,[int_color]
    399 
    400 	v_midloop:
    401 		mov	[ebx],al
    402 		dec	ecx
    403 		jl	and_out
    404 		add	ebx,[bpr]
    405 		sub	[accum],edx		//; sub the lesser
    406 		jge	v_midloop		//; any line could be new
    407 		add	[accum],edi		//; add greater for new accum
    408 		add	ebx,esi			//; next pixel over
    409 		jmp	v_midloop
    410 
    411 	horiz:
    412 		mov	edi,ecx			//; set greater
    413 		mov	[accum],ecx		//; set accumulator to 1/2 greater
    414 		shr	[accum],1
    415 
    416 		//;*==================================================================
    417 		//;* at this point ...
    418 		//;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
    419 		//;* esi=adder; accum=accumulator
    420 		//;* in a vertical loop the adder is conditional and the inc constant
    421 		//;*==================================================================
    422 	//horiz_loop:
    423 		add	ebx,eax
    424 		mov	eax,[int_color]
    425 
    426 	h_midloop:
    427 		mov	[ebx],al
    428 		dec	ecx				//; dec counter
    429 		jl	and_out				//; end of line
    430 		add	ebx,esi
    431 		sub     [accum],edx			//; sub the lesser
    432 		jge	h_midloop
    433 		add	[accum],edi			//; add greater for new accum
    434 		add	ebx,[bpr]			//; goto next line
    435 		jmp	h_midloop
    436 
    437 		//;*==================================================================
    438 		//;* Special case routine for horizontal line draws
    439 		//;*==================================================================
    440 	hline:
    441 		cmp	eax,ecx			//; make eax < ecx
    442 		jl	short hl_ac
    443 		xchg	eax,ecx
    444 
    445 	hl_ac:
    446 		sub	ecx,eax			//; get len
    447 		inc	ecx
    448 
    449 		push	edx
    450 		push	eax
    451 		mov	eax,[bpr]
    452 		mul	ebx
    453 		mov	ebx,eax
    454 		mov	eax,[this_object]
    455 		add	ebx,[eax]GraphicViewPortClass.Offset
    456 		pop	eax
    457 		pop	edx
    458 		add	ebx,eax
    459 		mov	edi,ebx
    460 		cmp	ecx,15
    461 		jg	big_line
    462 		mov	al,[color]
    463 		rep	stosb			//; write as many words as possible
    464 		jmp	short and_out		//; get outt
    465 
    466 
    467 	big_line:
    468 		mov	al,[color]
    469 		mov	ah,al
    470 		mov     ebx,eax
    471 		shl	eax,16
    472 		mov	ax,bx
    473 		test	edi,3
    474 		jz	aligned
    475 		mov	[edi],al
    476 		inc	edi
    477 		dec	ecx
    478 		test	edi,3
    479 		jz	aligned
    480 		mov	[edi],al
    481 		inc	edi
    482 		dec	ecx
    483 		test	edi,3
    484 		jz	aligned
    485 		mov	[edi],al
    486 		inc	edi
    487 		dec	ecx
    488 
    489 	aligned:
    490 		mov	ebx,ecx
    491 		shr	ecx,2
    492 		rep	stosd
    493 		mov	ecx,ebx
    494 		and	ecx,3
    495 		rep	stosb
    496 		jmp	and_out
    497 
    498 
    499 		//;*==================================================================
    500 		//;* a special case routine for vertical line draws
    501 		//;*==================================================================
    502 	vline:
    503 		mov	ecx,edx			//; get length of line to draw
    504 		inc	ecx
    505 		add	ebx,eax
    506 		mov	eax,[int_color]
    507 
    508 	vl_loop:
    509 		mov	[ebx],al		//; store bit
    510 		add	ebx,[bpr]
    511 		dec	ecx
    512 		jnz	vl_loop
    513 		jmp	and_out
    514 
    515 
    516 do_init:
    517 		mov	edi, offset _clip_table
    518 		
    519 		lea	esi, nada
    520 		mov	[edi], esi
    521 		mov	[edi+12], esi
    522 		lea	esi, a_up
    523 		mov	[edi+4], esi
    524 		lea	esi, a_dwn
    525 		mov	[edi+8], esi
    526 
    527 		add	edi, 16
    528 		
    529 		lea	esi, a_lft
    530 		mov	[edi], esi
    531 		mov	[edi+4], esi
    532 		lea	esi, a_dwn
    533 		mov	[edi+8], esi
    534 		lea	esi, nada
    535 		mov	[edi+12], esi
    536 
    537 		add	edi, 16
    538 
    539 		lea	esi, a_rgt
    540 		mov	[edi], esi
    541 		mov	[edi+8], esi
    542 		lea	esi, a_up
    543 		mov	[edi+4], esi
    544 		lea	esi, nada
    545 		mov	[edi+12], esi
    546 
    547 		add	edi, 16
    548 
    549 		lea	esi, nada
    550 		mov	[edi], esi
    551 		mov	[edi+4], esi
    552 		mov	[edi+8], esi
    553 		mov	[edi+12], esi
    554 		
    555 		mov	[_one_time_init], 1
    556 		ret
    557 
    558 	and_out:
    559 	}
    560 }
    561 
    562 
    563 
    564 
    565 
    566 /*
    567 ;***************************************************************************
    568 ;**   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   **
    569 ;***************************************************************************
    570 ;*                                                                         *
    571 ;*                 Project Name : Westwood 32 bit Library                  *
    572 ;*                                                                         *
    573 ;*                    File Name : DRAWLINE.ASM                             *
    574 ;*                                                                         *
    575 ;*                   Programmer : Phil W. Gorrow                           *
    576 ;*                                                                         *
    577 ;*                   Start Date : June 16, 1994                            *
    578 ;*                                                                         *
    579 ;*                  Last Update : August 30, 1994   [IML]                  *
    580 ;*                                                                         *
    581 ;*-------------------------------------------------------------------------*
    582 ;* Functions:                                                              *
    583 ;*   VVC::Scale -- Scales a virtual viewport to another virtual viewport   *
    584 ;*   Normal_Draw -- jump loc for drawing  scaled line of normal pixel      *
    585 ;*   __DRAW_LINE -- Assembly routine to draw a line                        *
    586 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
    587 
    588 IDEAL
    589 P386
    590 MODEL USE32 FLAT
    591 
    592 INCLUDE ".\drawbuff.inc"
    593 INCLUDE ".\gbuffer.inc"
    594 
    595 
    596 CODESEG
    597 */
    598 
    599 
    600 /*
    601 ;***************************************************************************
    602 ;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *
    603 ;*                                                                         *
    604 ;* INPUT:	WORD sx_pixel 	- the starting x pixel position		   *
    605 ;*		WORD sy_pixel	- the starting y pixel position		   *
    606 ;*		WORD dx_pixel	- the destination x pixel position	   *
    607 ;*		WORD dy_pixel   - the destination y pixel position	   *
    608 ;*		WORD color      - the color of the line to draw		   *
    609 ;*                                                                         *
    610 ;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel	   *
    611 ;*       with the graphic viewport it has been assigned to.		   *
    612 ;*                                                                         *
    613 ;* HISTORY:                                                                *
    614 ;*   06/16/1994 PWG : Created.                                             *
    615 ;*   08/30/1994 IML : Fixed clipping bug.				   *
    616 ;*=========================================================================*
    617 	PROC	Buffer_Draw_Line C NEAR
    618 	USES	eax,ebx,ecx,edx,esi,edi
    619 
    620 	;*==================================================================
    621 	;* Define the arguements that the function takes.
    622 	;*==================================================================
    623 	ARG	this_object:DWORD	; associated graphic view port
    624 	ARG	x1_pixel:DWORD		; the start x pixel position
    625 	ARG	y1_pixel:DWORD		; the start y pixel position
    626 	ARG	x2_pixel:DWORD		; the dest x pixel position
    627 	ARG	y2_pixel:DWORD		; the dest y pixel position
    628 	ARG	color:DWORD		; the color we are drawing
    629 
    630 	;*==================================================================
    631 	;* Define the local variables that we will use on the stack
    632 	;*==================================================================
    633 	LOCAL	clip_min_x:DWORD
    634 	LOCAL	clip_max_x:DWORD
    635 	LOCAL	clip_min_y:DWORD
    636 	LOCAL	clip_max_y:DWORD
    637 	LOCAL	clip_var:DWORD
    638 	LOCAL	accum:DWORD
    639 	LOCAL	bpr:DWORD
    640 
    641 	;*==================================================================
    642 	;* Take care of find the clip minimum and maximums
    643 	;*==================================================================
    644 	mov	ebx,[this_object]
    645 	xor	eax,eax
    646 	mov	[clip_min_x],eax
    647 	mov	[clip_min_y],eax
    648 	mov	eax,[(GraphicViewPort ebx).GVPWidth]
    649 	mov	[clip_max_x],eax
    650 	add	eax,[(GraphicViewPort ebx).GVPXAdd]
    651 	add	eax,[(GraphicViewPort ebx).GVPPitch]
    652 	mov	[bpr],eax
    653 	mov	eax,[(GraphicViewPort ebx).GVPHeight]
    654 	mov	[clip_max_y],eax
    655 
    656 	;*==================================================================
    657 	;* Adjust max pixels as they are tested inclusively.
    658 	;*==================================================================
    659 	dec	[clip_max_x]
    660 	dec	[clip_max_y]
    661 
    662 	;*==================================================================
    663 	;* Set the registers with the data for drawing the line
    664 	;*==================================================================
    665 	mov	eax,[x1_pixel]		; eax = start x pixel position
    666 	mov	ebx,[y1_pixel]		; ebx = start y pixel position
    667 	mov	ecx,[x2_pixel]		; ecx = dest x pixel position
    668 	mov	edx,[y2_pixel]		; edx = dest y pixel position
    669 
    670 	;*==================================================================
    671 	;* This is the section that "pushes" the line into bounds.
    672 	;* I have marked the section with PORTABLE start and end to signify
    673 	;* how much of this routine is 100% portable between graphics modes.
    674 	;* It was just as easy to have variables as it would be for constants
    675 	;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used
    676 	;* to clip the line (default is the screen)
    677 	;* PORTABLE start
    678 	;*==================================================================
    679 
    680 	cmp	eax,[clip_min_x]
    681 	jl	short ??clip_it
    682 	cmp	eax,[clip_max_x]
    683 	jg	short ??clip_it
    684 	cmp	ebx,[clip_min_y]
    685 	jl	short ??clip_it
    686 	cmp	ebx,[clip_max_y]
    687 	jg	short ??clip_it
    688 	cmp	ecx,[clip_min_x]
    689 	jl	short ??clip_it
    690 	cmp	ecx,[clip_max_x]
    691 	jg	short ??clip_it
    692 	cmp	edx,[clip_min_y]
    693 	jl	short ??clip_it
    694 	cmp	edx,[clip_max_y]
    695 	jle	short ??on_screen
    696 
    697 	;*==================================================================
    698 	;* Takes care off clipping the line.
    699 	;*==================================================================
    700 ??clip_it:
    701 	call	NEAR PTR ??set_bits
    702 	xchg	eax,ecx
    703 	xchg	ebx,edx
    704 	mov	edi,esi
    705 	call	NEAR PTR ??set_bits
    706 	mov	[clip_var],edi
    707 	or	[clip_var],esi
    708 	jz	short ??on_screen
    709 	test	edi,esi
    710 	jne	short ??off_screen
    711 	shl	esi,2
    712 	call	[DWORD PTR cs:??clip_tbl+esi]
    713 	jc	??clip_it
    714 	xchg	eax,ecx
    715 	xchg	ebx,edx
    716 	shl	edi,2
    717 	call	[DWORD PTR cs:??clip_tbl+edi]
    718 	jmp	??clip_it
    719 
    720 ??on_screen:
    721 	jmp	??draw_it
    722 
    723 ??off_screen:
    724 	jmp	??out
    725 
    726 	;*==================================================================
    727 	;* Jump table for clipping conditions
    728 	;*==================================================================
    729 ??clip_tbl	DD	??nada,??a_up,??a_dwn,??nada
    730 		DD	??a_lft,??a_lft,??a_dwn,??nada
    731 		DD	??a_rgt,??a_up,??a_rgt,??nada
    732 		DD	??nada,??nada,??nada,??nada
    733 
    734 ??nada:
    735 	clc
    736 	retn
    737 
    738 ??a_up:
    739 	mov	esi,[clip_min_y]
    740 	call	NEAR PTR ??clip_vert
    741 	stc
    742 	retn
    743 
    744 ??a_dwn:
    745 	mov	esi,[clip_max_y]
    746 	neg	esi
    747 	neg	ebx
    748 	neg	edx
    749 	call	NEAR PTR ??clip_vert
    750 	neg	ebx
    751 	neg	edx
    752 	stc
    753 	retn
    754 
    755 	;*==================================================================
    756 	;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]
    757 	;*==================================================================
    758 ??clip_vert:
    759 	push	edx
    760 	push	eax
    761 	mov	[clip_var],edx		; clip_var = yb
    762 	sub	[clip_var],ebx		; clip_var = (yb-ya)
    763 	neg	eax			; eax=-xa
    764 	add	eax,ecx			; (ebx-xa)
    765 	mov	edx,esi			; edx=miny
    766 	sub	edx,ebx			; edx=(miny-ya)
    767 	imul	edx
    768 	idiv	[clip_var]
    769 	pop	edx
    770 	add	eax,edx
    771 	pop	edx
    772 	mov	ebx,esi
    773 	retn
    774 
    775 ??a_lft:
    776 	mov	esi,[clip_min_x]
    777 	call	NEAR PTR ??clip_horiz
    778 	stc
    779 	retn
    780 
    781 ??a_rgt:
    782 	mov	esi,[clip_max_x]
    783 	neg	eax
    784 	neg	ecx
    785 	neg	esi
    786 	call	NEAR PTR ??clip_horiz
    787 	neg	eax
    788 	neg	ecx
    789 	stc
    790 	retn
    791 
    792 	;*==================================================================
    793 	;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]
    794 	;*==================================================================
    795 ??clip_horiz:
    796 	push	edx
    797 	mov	[clip_var],ecx		; clip_var = xb
    798 	sub	[clip_var],eax		; clip_var = (xb-xa)
    799 	sub	edx,ebx			; edx = (yb-ya)
    800 	neg	eax			; eax = -xa
    801 	add	eax,esi			; eax = (minx-xa)
    802 	imul	edx			; eax = (minx-xa)(yb-ya)
    803 	idiv	[clip_var]		; eax = (minx-xa)(yb-ya)/(xb-xa)
    804 	add	ebx,eax			; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]
    805 	pop	edx
    806 	mov	eax,esi
    807 	retn
    808 
    809 	;*==================================================================
    810 	;* Sets the condition bits
    811 	;*==================================================================
    812 ??set_bits:
    813 	xor	esi,esi
    814 	cmp	ebx,[clip_min_y]	; if y >= top its not up
    815 	jge	short ??a_not_up
    816 	or	esi,1
    817 
    818 ??a_not_up:
    819 	cmp	ebx,[clip_max_y]	; if y <= bottom its not down
    820 	jle	short ??a_not_down
    821 	or	esi,2
    822 
    823 ??a_not_down:
    824 	cmp	eax,[clip_min_x]   	; if x >= left its not left
    825 	jge	short ??a_not_left
    826 	or	esi,4
    827 
    828 ??a_not_left:
    829 	cmp	eax,[clip_max_x]	; if x <= right its not right
    830 	jle	short ??a_not_right
    831 	or	esi,8
    832 
    833 ??a_not_right:
    834 	retn
    835 
    836 	;*==================================================================
    837 	;* Draw the line to the screen.
    838 	;* PORTABLE end
    839 	;*==================================================================
    840 ??draw_it:
    841 	sub	edx,ebx			; see if line is being draw down
    842 	jnz	short ??not_hline	; if not then its not a hline
    843 	jmp	short ??hline		; do special case h line
    844 
    845 ??not_hline:
    846 	jg	short ??down		; if so there is no need to rev it
    847 	neg	edx			; negate for actual pixel length
    848 	xchg	eax,ecx			; swap x's to rev line draw
    849 	sub	ebx,edx			; get old edx
    850 
    851 ??down:
    852 	push	edx
    853 	push	eax
    854 	mov	eax,[bpr]
    855 	mul	ebx
    856 	mov	ebx,eax
    857 	mov	eax,[this_object]
    858 	add	ebx,[(GraphicViewPort eax).GVPOffset]
    859 	pop	eax
    860 	pop	edx
    861 
    862 	mov	esi,1			; assume a right mover
    863 	sub	ecx,eax			; see if line is right
    864 	jnz	short ??not_vline	; see if its a vertical line
    865 	jmp	??vline
    866 
    867 ??not_vline:
    868 	jg	short ??right		; if so, the difference = length
    869 
    870 ??left:
    871 	neg	ecx			; else negate for actual pixel length
    872 	neg	esi			; negate counter to move left
    873 
    874 ??right:
    875 	cmp	ecx,edx			; is it a horiz or vert line
    876 	jge	short ??horiz		; if ecx > edx then |x|>|y| or horiz
    877 
    878 ??vert:
    879 	xchg	ecx,edx			; make ecx greater and edx lesser
    880 	mov	edi,ecx			; set greater
    881 	mov	[accum],ecx		; set accumulator to 1/2 greater
    882 	shr	[accum],1
    883 
    884 	;*==================================================================
    885 	;* at this point ...
    886 	;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
    887 	;* esi=adder; accum=accumulator
    888 	;* in a vertical loop the adder is conditional and the inc constant
    889 	;*==================================================================
    890 ??vert_loop:
    891 	add	ebx,eax
    892 	mov	eax,[color]
    893 
    894 ??v_midloop:
    895 	mov	[ebx],al
    896 	dec	ecx
    897 	jl	??out
    898 	add	ebx,[bpr]
    899 	sub	[accum],edx		; sub the lesser
    900 	jge	??v_midloop		; any line could be new
    901 	add	[accum],edi		; add greater for new accum
    902 	add	ebx,esi			; next pixel over
    903 	jmp	??v_midloop
    904 
    905 ??horiz:
    906 	mov	edi,ecx			; set greater
    907 	mov	[accum],ecx		; set accumulator to 1/2 greater
    908 	shr	[accum],1
    909 
    910 	;*==================================================================
    911 	;* at this point ...
    912 	;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
    913 	;* esi=adder; accum=accumulator
    914 	;* in a vertical loop the adder is conditional and the inc constant
    915 	;*==================================================================
    916 ??horiz_loop:
    917 	add	ebx,eax
    918 	mov	eax,[color]
    919 
    920 ??h_midloop:
    921 	mov	[ebx],al
    922 	dec	ecx				; dec counter
    923 	jl	??out				; end of line
    924 	add	ebx,esi
    925 	sub     [accum],edx			; sub the lesser
    926 	jge	??h_midloop
    927 	add	[accum],edi			; add greater for new accum
    928 	add	ebx,[bpr]			; goto next line
    929 	jmp	??h_midloop
    930 
    931 	;*==================================================================
    932 	;* Special case routine for horizontal line draws
    933 	;*==================================================================
    934 ??hline:
    935 	cmp	eax,ecx			; make eax < ecx
    936 	jl	short ??hl_ac
    937 	xchg	eax,ecx
    938 
    939 ??hl_ac:
    940 	sub	ecx,eax			; get len
    941 	inc	ecx
    942 
    943 	push	edx
    944 	push	eax
    945 	mov	eax,[bpr]
    946 	mul	ebx
    947 	mov	ebx,eax
    948 	mov	eax,[this_object]
    949 	add	ebx,[(GraphicViewPort eax).GVPOffset]
    950 	pop	eax
    951 	pop	edx
    952 	add	ebx,eax
    953 	mov	edi,ebx
    954 	cmp	ecx,15
    955 	jg	??big_line
    956 	mov	al,[byte color]
    957 	rep	stosb			; write as many words as possible
    958 	jmp	short ??out		; get outt
    959 
    960 
    961 ??big_line:
    962 	mov	al,[byte color]
    963 	mov	ah,al
    964 	mov     ebx,eax
    965 	shl	eax,16
    966 	mov	ax,bx
    967 	test	edi,3
    968 	jz	??aligned
    969 	mov	[edi],al
    970 	inc	edi
    971 	dec	ecx
    972 	test	edi,3
    973 	jz	??aligned
    974 	mov	[edi],al
    975 	inc	edi
    976 	dec	ecx
    977 	test	edi,3
    978 	jz	??aligned
    979 	mov	[edi],al
    980 	inc	edi
    981 	dec	ecx
    982 
    983 ??aligned:
    984 	mov	ebx,ecx
    985 	shr	ecx,2
    986 	rep	stosd
    987 	mov	ecx,ebx
    988 	and	ecx,3
    989 	rep	stosb
    990 	jmp	??out
    991 
    992 
    993 	;*==================================================================
    994 	;* a special case routine for vertical line draws
    995 	;*==================================================================
    996 ??vline:
    997 	mov	ecx,edx			; get length of line to draw
    998 	inc	ecx
    999 	add	ebx,eax
   1000 	mov	eax,[color]
   1001 
   1002 ??vl_loop:
   1003 	mov	[ebx],al		; store bit
   1004 	add	ebx,[bpr]
   1005 	dec	ecx
   1006 	jnz	??vl_loop
   1007 
   1008 ??out:
   1009 	ret
   1010 	ENDP	Buffer_Draw_Line
   1011 
   1012 
   1013 */
   1014 
   1015 
   1016 
   1017 
   1018 
   1019 
   1020 
   1021 
   1022 
   1023 
   1024 
   1025 
   1026 
   1027 
   1028 
   1029 /*
   1030 
   1031 ;***************************************************************************
   1032 ;* GVPC::FILL_RECT -- Fills a rectangular region of a graphic view port	   *
   1033 ;*                                                                         *
   1034 ;* INPUT:	WORD the left hand x pixel position of region		   *
   1035 ;*		WORD the upper x pixel position of region		   *
   1036 ;*		WORD the right hand x pixel position of region		   *
   1037 ;*		WORD the lower x pixel position of region		   *
   1038 ;*		UBYTE the color (optional) to clear the view port to	   *
   1039 ;*                                                                         *
   1040 ;* OUTPUT:      none                                                       *
   1041 ;*                                                                         *
   1042 ;* NOTE:	This function is optimized to handle viewport with no XAdd *
   1043 ;*		value.  It also handles DWORD aligning the destination	   *
   1044 ;*		when speed can be gained by doing it.			   *
   1045 ;* HISTORY:                                                                *
   1046 ;*   06/07/1994 PWG : Created.                                             *
   1047 ;*=========================================================================*
   1048 */ 
   1049 
   1050 /*
   1051 ;******************************************************************************
   1052 ; Much testing was done to determine that only when there are 14 or more bytes
   1053 ; being copied does it speed the time it takes to do copies in this algorithm.
   1054 ; For this reason and because 1 and 2 byte copies crash, is the special case
   1055 ; used.  SKB 4/21/94.  Tested on 486 66mhz.  Copied by PWG 6/7/04.
   1056 */ 
   1057 #define OPTIMAL_BYTE_COPY	14
   1058 
   1059 
   1060 void __cdecl Buffer_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color)
   1061 {
   1062 /*
   1063 	;*===================================================================
   1064 	;* define the arguements that our function takes.
   1065 	;*===================================================================
   1066 	ARG    	this_object:DWORD			; this is a member function
   1067 	ARG	x1_pixel:WORD
   1068 	ARG	y1_pixel:WORD
   1069 	ARG	x2_pixel:WORD
   1070 	ARG	y2_pixel:WORD
   1071 	ARG    	color:BYTE			; what color should we clear to
   1072 */
   1073 	
   1074 	void *this_object = thisptr;
   1075 	int x1_pixel = sx;
   1076 	int y1_pixel = sy;
   1077 	int x2_pixel = dx;
   1078 	int y2_pixel = dy;
   1079 	
   1080 /*
   1081 	;*===================================================================
   1082 	; Define some locals so that we can handle things quickly
   1083 	;*===================================================================
   1084 	LOCAL	VPwidth:DWORD		; the width of the viewport
   1085 	LOCAL	VPheight:DWORD		; the height of the viewport
   1086 	LOCAL	VPxadd:DWORD		; the additional x offset of viewport
   1087 	LOCAL	VPbpr:DWORD		; the number of bytes per row of viewport
   1088 */
   1089 
   1090 	int VPwidth;
   1091 	int VPheight;
   1092 	int VPxadd;
   1093 	int VPbpr;
   1094 
   1095 	int local_ebp;	                      // Can't use ebp
   1096 
   1097 	__asm {
   1098 
   1099 		;*===================================================================
   1100 		;* save off the viewport characteristics on the stack
   1101 		;*===================================================================
   1102 		mov	ebx,[this_object]				; get a pointer to viewport
   1103 		mov	eax,[ebx]GraphicViewPortClass.Width		; get width from viewport
   1104 		mov	ecx,[ebx]GraphicViewPortClass.Height	; get height from viewport
   1105 		mov	edx,[ebx]GraphicViewPortClass.XAdd		; get xadd from viewport
   1106 		add	edx,[ebx]GraphicViewPortClass.Pitch		; extra pitch of direct draw surface
   1107 		mov	[VPwidth],eax				; store the width of locally
   1108 		mov	[VPheight],ecx
   1109 		mov	[VPxadd],edx
   1110 		add	eax,edx
   1111 		mov	[VPbpr],eax
   1112 
   1113 		;*===================================================================
   1114 		;* move the important parameters into local registers
   1115 		;*===================================================================
   1116 		mov	eax,[x1_pixel]
   1117 		mov	ebx,[y1_pixel]
   1118 		mov	ecx,[x2_pixel]
   1119 		mov	edx,[y2_pixel]
   1120 
   1121 		;*===================================================================
   1122 		;* Convert the x2 and y2 pixel to a width and height
   1123 		;*===================================================================
   1124 		cmp	eax,ecx
   1125 		jl	no_swap_x
   1126 		xchg	eax,ecx
   1127 
   1128 	no_swap_x:
   1129 		sub	ecx,eax
   1130 		cmp	ebx,edx
   1131 		jl	no_swap_y
   1132 		xchg	ebx,edx
   1133 	no_swap_y:
   1134 		sub	edx,ebx
   1135 		inc	ecx
   1136 		inc	edx
   1137 
   1138 		;*===================================================================
   1139 		;* Bounds check source X.
   1140 		;*===================================================================
   1141 		cmp	eax, [VPwidth]			; compare with the max
   1142 		jge	done				; starts off screen, then later
   1143 		jb	short sx_done			; if it's not negative, it's ok
   1144 
   1145 		;------ Clip source X to left edge of screen.
   1146 		add	ecx, eax			; Reduce width (add in negative src X).
   1147 		xor	eax, eax			; Clip to left of screen.
   1148 	sx_done:
   1149 
   1150 		;*===================================================================
   1151 		;* Bounds check source Y.
   1152 		;*===================================================================
   1153 		cmp	ebx, [VPheight]			; compare with the max
   1154 		jge	done				; starts off screen, then later
   1155 		jb	short sy_done			; if it's not negative, it's ok
   1156 
   1157 		;------ Clip source Y to top edge of screen.
   1158 		add	edx, ebx			; Reduce height (add in negative src Y).
   1159 		xor	ebx, ebx			; Clip to top of screen.
   1160 
   1161 	sy_done:
   1162 		;*===================================================================
   1163 		;* Bounds check width versus width of source and dest view ports
   1164 		;*===================================================================
   1165 		push	ebx				; save off ebx for later use
   1166 		mov	ebx,[VPwidth]			; get the source width
   1167 		sub	ebx, eax			; Maximum allowed pixel width (given coordinates).
   1168 		sub	ebx, ecx			; Pixel width undershoot.
   1169 		jns	short width_ok		; if not signed no adjustment necessary
   1170 		add	ecx, ebx			; Reduce width to screen limits.
   1171 
   1172 	width_ok:
   1173 		pop	ebx				; restore ebx to old value
   1174 
   1175 		;*===================================================================
   1176 		;* Bounds check height versus height of source view port
   1177 		;*===================================================================
   1178 		push	eax				; save of eax for later use
   1179 		mov	eax, [VPheight]			; get the source height
   1180 		sub	eax, ebx			; Maximum allowed pixel height (given coordinates).
   1181 		sub	eax, edx			; Pixel height undershoot.
   1182 		jns	short height_ok		; if not signed no adjustment necessary
   1183 		add	edx, eax			; Reduce height to screen limits.
   1184 	height_ok:
   1185 		pop	eax				; restore eax to old value
   1186 
   1187 		;*===================================================================
   1188 		;* Perform the last minute checks on the width and height
   1189 		;*===================================================================
   1190 		or	ecx,ecx
   1191 		jz	done
   1192 
   1193 		or	edx,edx
   1194 		jz	done
   1195 
   1196 		cmp	ecx,[VPwidth]
   1197 		ja	done
   1198 		cmp	edx,[VPheight]
   1199 		ja	done
   1200 
   1201 		;*===================================================================
   1202 		;* Get the offset into the virtual viewport.
   1203 		;*===================================================================
   1204 		xchg	edi,eax			; save off the contents of eax
   1205 		xchg	esi,edx			;   and edx for size test
   1206 		mov	eax,ebx			; move the y pixel into eax
   1207 		mul	[VPbpr]			; multiply by bytes per row
   1208 		add	edi,eax			; add the result into the x position
   1209 		mov	ebx,[this_object]
   1210 		add	edi,[ebx]GraphicViewPortClass.Offset
   1211 
   1212 		mov	edx,esi			; restore edx back to real value
   1213 		mov	eax,ecx			; store total width in ecx
   1214 		sub	eax,[VPwidth]		; modify xadd value to include clipped
   1215 		sub	[VPxadd],eax		;   width bytes (subtract a negative number)
   1216 
   1217 		;*===================================================================
   1218 		; Convert the color byte to a DWORD for fast storing
   1219 		;*===================================================================
   1220 		mov	al,[color]				; get color to clear to
   1221 		mov	ah,al					; extend across WORD
   1222 		mov	ebx,eax					; extend across DWORD in
   1223 		shl	eax,16					;   several steps
   1224 		mov	ax,bx
   1225 
   1226 		;*===================================================================
   1227 		; If there is no row offset then adjust the width to be the size of
   1228 		;   the entire viewport and adjust the height to be 1
   1229 		;*===================================================================
   1230 		mov	esi,[VPxadd]
   1231 		or	esi,esi					; set the flags for esi
   1232 		jnz	row_by_row_aligned			;   and act on them
   1233 
   1234 		xchg	eax,ecx					; switch bit pattern and width
   1235 		mul	edx					; multiply by edx to get size
   1236 		xchg	eax,ecx					; switch size and bit pattern
   1237 		mov	edx,1					; only 1 line off view port size to do
   1238 
   1239 		;*===================================================================
   1240 		; Find out if we should bother to align the row.
   1241 		;*===================================================================
   1242 	row_by_row_aligned:
   1243 		mov	[local_ebp],ecx					; width saved in ebp
   1244 		cmp	ecx,OPTIMAL_BYTE_COPY			; is it worth aligning them?
   1245 		jl	row_by_row				;   if not then skip
   1246 
   1247 		;*===================================================================
   1248 		; Figure out the alignment offset if there is any
   1249 		;*===================================================================
   1250 		mov	ebx,edi					; get output position
   1251 		and	ebx,3					;   is there a remainder?
   1252 		jz	aligned_loop				;   if not we are aligned
   1253 		xor	ebx,3					; find number of align bytes
   1254 		inc	ebx					; this number is off by one
   1255 		sub	[local_ebp],ebx					; subtract from width
   1256 
   1257 		;*===================================================================
   1258 		; Now that we have the alignment offset copy each row
   1259 		;*===================================================================
   1260 	aligned_loop:
   1261 		mov	ecx,ebx					; get number of bytes to align
   1262 		rep	stosb					;   and move them over
   1263 		mov	ecx,[local_ebp]					; get number of aligned bytes
   1264 		shr	ecx,2					;   convert to DWORDS
   1265 		rep	stosd					;   and move them over
   1266 		mov	ecx,[local_ebp]					; get number of aligned bytes
   1267 		and	ecx,3					;   find the remainder
   1268 		rep	stosb					;   and move it over
   1269 		add	edi,esi					; fix the line offset
   1270 		dec	edx					; decrement the height
   1271 		jnz	aligned_loop				; if more to do than do it
   1272 		jmp	done					; we are all done
   1273 
   1274 		;*===================================================================
   1275 		; If not enough bytes to bother aligning copy each line across a byte
   1276 		;    at a time.
   1277 		;*===================================================================
   1278 	row_by_row:
   1279 		mov	ecx,[local_ebp]					; get total width in bytes
   1280 		rep	stosb					; store the width
   1281 		add	edi,esi					; handle the xadd
   1282 		dec	edx					; decrement the height
   1283 		jnz	row_by_row				; if any left then next line
   1284 	done:
   1285 	}
   1286 }
   1287 
   1288 
   1289 
   1290 
   1291 /*
   1292 ;***************************************************************************
   1293 ;* VVPC::CLEAR -- Clears a virtual viewport instance                       *
   1294 ;*                                                                         *
   1295 ;* INPUT:	UBYTE the color (optional) to clear the view port to	   *
   1296 ;*                                                                         *
   1297 ;* OUTPUT:      none                                                       *
   1298 ;*                                                                         *
   1299 ;* NOTE:	This function is optimized to handle viewport with no XAdd *
   1300 ;*		value.  It also handles DWORD aligning the destination	   *
   1301 ;*		when speed can be gained by doing it.			   *
   1302 ;* HISTORY:                                                                *
   1303 ;*   06/07/1994 PWG : Created.                                             *
   1304 ;*   08/23/1994 SKB : Clear the direction flag to always go forward.       *
   1305 ;*=========================================================================*
   1306 */
   1307 void	__cdecl Buffer_Clear(void *this_object, unsigned char color)
   1308 {
   1309 	unsigned int local_color = color;
   1310 
   1311 	__asm {
   1312 
   1313 		cld 		 				; always go forward
   1314 
   1315 		mov	ebx,[this_object]			; get a pointer to viewport
   1316 		mov	edi,[ebx]GraphicViewPortClass.Offset	; get the correct offset
   1317 		mov	edx,[ebx]GraphicViewPortClass.Height	; get height from viewport
   1318 		mov	esi,[ebx]GraphicViewPortClass.Width		; get width from viewport
   1319 		//push	[dword (GraphicViewPort ebx).GVPPitch]	; extra pitch of direct draw surface
   1320 		push	[ebx]GraphicViewPortClass.Pitch
   1321 
   1322 		mov	ebx,[ebx]GraphicViewPortClass.XAdd		; esi = add for each line
   1323 		add	ebx,[esp]				; Yes, I know its nasty but
   1324 		add	esp,4					;      it works!
   1325 
   1326 		;*===================================================================
   1327 		; Convert the color byte to a DWORD for fast storing
   1328 		;*===================================================================
   1329 		mov	al,[color]				; get color to clear to
   1330 		mov	ah,al					; extend across WORD
   1331 		mov	ecx,eax					; extend across DWORD in
   1332 		shl	eax,16					;   several steps
   1333 		mov	ax,cx
   1334 
   1335 		;*===================================================================
   1336 		; Find out if we should bother to align the row.
   1337 		;*===================================================================
   1338 
   1339 		cmp	esi , OPTIMAL_BYTE_COPY			; is it worth aligning them?
   1340 		jl	byte_by_byte				;   if not then skip
   1341 
   1342 		;*===================================================================
   1343 		; Figure out the alignment offset if there is any
   1344 		;*===================================================================
   1345 		push	ebx
   1346 	
   1347 	dword_aligned_loop:
   1348 		    mov	ecx , edi
   1349 		    mov	ebx , esi
   1350 		    neg	ecx
   1351 		    and	ecx , 3
   1352 		    sub	ebx , ecx
   1353 		    rep	stosb
   1354 		    mov	ecx , ebx
   1355 		    shr	ecx , 2
   1356 		    rep	stosd
   1357 		    mov	ecx , ebx
   1358 		    and	ecx , 3
   1359 		    rep	stosb
   1360 		    add	edi , [ esp ]
   1361 		    dec	edx					; decrement the height
   1362 		    jnz	dword_aligned_loop				; if more to do than do it
   1363 		    pop	eax
   1364 			 jmp	done
   1365 		    //ret
   1366 
   1367 		;*===================================================================
   1368 		; If not enough bytes to bother aligning copy each line across a byte
   1369 		;    at a time.
   1370 		;*===================================================================
   1371 	byte_by_byte:
   1372 		mov	ecx,esi					; get total width in bytes
   1373 		rep	stosb					; store the width
   1374 		add	edi,ebx					; handle the xadd
   1375 		dec	edx					; decrement the height
   1376 		jnz	byte_by_byte				; if any left then next line
   1377 	done:
   1378 	}
   1379 }
   1380 
   1381 
   1382 
   1383 
   1384 
   1385 
   1386 
   1387 
   1388 
   1389 
   1390 
   1391 
   1392 
   1393 
   1394 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)
   1395 {
   1396 /*
   1397 	;*===================================================================
   1398 	;* define the arguements that our function takes.
   1399 	;*===================================================================
   1400 	ARG    	this_object :DWORD		; this is a member function
   1401 	ARG	dest        :DWORD		; what are we blitting to
   1402 	ARG	x_pixel     :DWORD		; x pixel position in source
   1403 	ARG	y_pixel     :DWORD		; y pixel position in source
   1404 	ARG	dest_x0     :dword
   1405 	ARG	dest_y0     :dword
   1406 	ARG	pixel_width :DWORD		; width of rectangle to blit
   1407 	ARG	pixel_height:DWORD		; height of rectangle to blit
   1408 	ARG	trans       :DWORD			; do we deal with transparents?
   1409 
   1410 	;*===================================================================
   1411 	; Define some locals so that we can handle things quickly
   1412 	;*===================================================================
   1413 	LOCAL 	x1_pixel :dword
   1414 	LOCAL	y1_pixel :dword
   1415 	LOCAL	dest_x1 : dword
   1416 	LOCAL	dest_y1 : dword
   1417 	LOCAL	scr_ajust_width:DWORD
   1418 	LOCAL	dest_ajust_width:DWORD
   1419         LOCAL	source_area :  dword
   1420         LOCAL	dest_area :  dword
   1421 */
   1422 	
   1423 	int	x1_pixel;
   1424 	int	y1_pixel;
   1425 	int	dest_x1;
   1426 	int	dest_y1;
   1427 	int	scr_adjust_width;
   1428 	int	dest_adjust_width;
   1429 	int	source_area;
   1430 	int	dest_area;
   1431 	
   1432 	__asm {	
   1433 	
   1434 		;This Clipping algorithm is a derivation of the very well known
   1435 		;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency
   1436 		;it is probably the most commontly implemented algorithm both in software
   1437 		;and hardware for clipping lines, rectangles, and convex polygons against
   1438 		;a rectagular clipping window. For reference see
   1439 		;"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes
   1440 		; pages 113 to 177".
   1441 		; Briefly consist in computing the Sutherland code for both end point of
   1442 		; the rectangle to find out if the rectangle is:
   1443 		; - trivially accepted (no further clipping test, display rectangle)
   1444 		; - trivially rejected (return with no action)
   1445 		; - retangle must be iteratively clipped again edges of the clipping window
   1446 		;   and the remaining retangle is display.
   1447 
   1448 		; Clip Source Rectangle against source Window boundaries.
   1449 			mov  	esi,[this_object]    ; get ptr to src
   1450 			xor 	ecx,ecx		    ; Set sutherland code to zero
   1451 			xor 	edx,edx		    ; Set sutherland code to zero
   1452 
   1453 		   ; compute the difference in the X axis and get the bit signs into ecx , edx
   1454 			mov	edi,[esi]GraphicViewPortClass.Width  ; get width into register
   1455 			mov	ebx,[x_pixel]	    ; Get first end point x_pixel into register
   1456 			mov	eax,[x_pixel]	    ; Get second end point x_pixel into register
   1457 			add	ebx,[pixel_width]   ; second point x1_pixel = x + width
   1458 			shld	ecx, eax,1	    ; the sign bit of x_pixel is sutherland code0 bit4
   1459 			mov	[x1_pixel],ebx	    ; save second for future use
   1460 			inc	edi		    ; move the right edge by one unit
   1461 			shld	edx,ebx,1	    ; the sign bit of x1_pixel is sutherland code0 bit4
   1462 			sub	eax,edi		    ; compute the difference x0_pixel - width
   1463 			sub	ebx,edi		    ; compute the difference x1_pixel - width
   1464 			shld	ecx,eax,1	    ; the sign bit of the difference is sutherland code0 bit3
   1465 			shld	edx,ebx,1	    ; the sign bit of the difference is sutherland code0 bit3
   1466 
   1467 		   ; the following code is just a repeticion of the above code
   1468 		   ; in the Y axis.
   1469 			mov	edi,[esi]GraphicViewPortClass.Height ; get height into register
   1470 			mov	ebx,[y_pixel]
   1471 			mov	eax,[y_pixel]
   1472 			add	ebx,[pixel_height]
   1473 			shld	ecx,eax,1
   1474 			mov	[y1_pixel ],ebx
   1475 			inc	edi
   1476 			shld	edx,ebx,1
   1477 			sub	eax,edi
   1478 			sub	ebx,edi
   1479 			shld	ecx,eax,1
   1480 			shld	edx,ebx,1
   1481 
   1482 		    ; Here we have the to Sutherland code into cl and dl
   1483 			xor	cl,5		       ; bit 2 and 0 are complented, reverse then
   1484 			xor	dl,5		       ; bit 2 and 0 are complented, reverse then
   1485 			mov	al,cl		       ; save code1 in case we have to clip iteratively
   1486 			test	dl,cl		       ; if any bit in code0 and its counter bit
   1487 			jnz	real_out	       ; in code1 is set then the rectangle in outside
   1488 			or	al,dl		       ; if all bit of code0 the counter bit in
   1489 			jz	clip_against_dest    ; in code1 is set to zero, then all
   1490 						       ; end points of the rectangle are
   1491 						       ; inside the clipping window
   1492 
   1493 		     ; if we are here the polygon have to be clip iteratively
   1494 			test	cl,1000b	       ; if bit 4 in code0 is set then
   1495 			jz	scr_left_ok	       ; x_pixel is smaller than zero
   1496 			mov	[x_pixel],0	       ; set x_pixel to cero.
   1497 
   1498 		scr_left_ok:
   1499 			test	cl,0010b	       ; if bit 2 in code0 is set then
   1500 			jz	scr_bottom_ok	       ; y_pixel is smaller than zero
   1501 			mov	[ y_pixel ],0	       ; set y_pixel to cero.
   1502 
   1503 		scr_bottom_ok:
   1504 			test	dl,0100b	       ; if bit 3 in code1 is set then
   1505 			jz	scr_right_ok	       ; x1_pixel is greater than the width
   1506 			mov	eax,[esi]GraphicViewPortClass.Width ; get width into register
   1507 			mov	[ x1_pixel ],eax       ; set x1_pixel to width.
   1508 		scr_right_ok:
   1509 			test	dl,0001b	       ; if bit 0 in code1 is set then
   1510 			jz	clip_against_dest    ; y1_pixel is greater than the width
   1511 			mov	eax,[esi]GraphicViewPortClass.Height  ; get height into register
   1512 			mov	[ y1_pixel ],eax       ; set y1_pixel to height.
   1513 
   1514 		; Clip Source Rectangle against destination Window boundaries.
   1515 		clip_against_dest:
   1516 
   1517 		   ; build the destination rectangle before clipping
   1518 		   ; dest_x1 = dest_x0 + ( x1_pixel - x_pixel )
   1519 		   ; dest_y1 = dest_y0 + ( y1_pixel - y_pixel )
   1520 			mov	eax,[dest_x0]	     ; get dest_x0 into eax
   1521 			mov	ebx,[dest_y0]	     ; get dest_y0 into ebx
   1522 			sub	eax,[x_pixel]	     ; subtract x_pixel from eax
   1523 			sub	ebx,[y_pixel]	     ; subtract y_pixel from ebx
   1524 			add	eax,[x1_pixel]	     ; add x1_pixel to eax
   1525 			add	ebx,[y1_pixel]	     ; add y1_pixel to ebx
   1526 			mov	[dest_x1],eax	     ; save eax into dest_x1
   1527 			mov	[dest_y1],ebx	     ; save eax into dest_y1
   1528 
   1529 
   1530 		  ; The followin code is a repeticion of the Sutherland clipping
   1531 		  ; descrived above.
   1532 			mov  	esi,[dest]	    ; get ptr to src
   1533 			xor 	ecx,ecx
   1534 			xor 	edx,edx
   1535 			mov	edi,[esi]GraphicViewPortClass.Width  ; get width into register
   1536 			mov	eax,[dest_x0]
   1537 			mov	ebx,[dest_x1]
   1538 			shld	ecx,eax,1
   1539 			inc	edi
   1540 			shld	edx,ebx,1
   1541 			sub	eax,edi
   1542 			sub	ebx,edi
   1543 			shld	ecx,eax,1
   1544 			shld	edx,ebx,1
   1545 
   1546 			mov	edi,[esi]GraphicViewPortClass.Height ; get height into register
   1547 			mov	eax,[dest_y0]
   1548 			mov	ebx,[dest_y1]
   1549 			shld	ecx,eax,1
   1550 			inc	edi
   1551 			shld	edx,ebx,1
   1552 			sub	eax,edi
   1553 			sub	ebx,edi
   1554 			shld	ecx,eax,1
   1555 			shld	edx,ebx,1
   1556 
   1557 			xor	cl,5
   1558 			xor	dl,5
   1559 			mov	al,cl
   1560 			test	dl,cl
   1561 			jnz	real_out
   1562 			or	al,dl
   1563 			jz	do_blit
   1564 
   1565 			test	cl,1000b
   1566 			jz	dest_left_ok
   1567 			mov	eax,[ dest_x0 ]
   1568 			mov	[ dest_x0 ],0
   1569 			sub	[ x_pixel ],eax
   1570 
   1571 		dest_left_ok:
   1572 			test	cl,0010b
   1573 			jz	dest_bottom_ok
   1574 			mov	eax,[ dest_y0 ]
   1575 			mov	[ dest_y0 ],0
   1576 			sub	[ y_pixel ],eax
   1577 
   1578 
   1579 		dest_bottom_ok:
   1580 			test	dl,0100b
   1581 			jz	dest_right_ok
   1582 			mov	ebx,[esi]GraphicViewPortClass.Width  ; get width into register
   1583 			mov	eax,[ dest_x1 ]
   1584 			mov	[ dest_x1 ],ebx
   1585 			sub	eax,ebx
   1586 			sub	[ x1_pixel ],eax
   1587 
   1588 		dest_right_ok:
   1589 			test	dl,0001b
   1590 			jz	do_blit
   1591 			mov	ebx,[esi]GraphicViewPortClass.Height  ; get width into register
   1592 			mov	eax,[ dest_y1 ]
   1593 			mov	[ dest_y1 ],ebx
   1594 			sub	eax,ebx
   1595 			sub	[ y1_pixel ],eax
   1596 
   1597 
   1598 		; Here is where	we do the actual blit
   1599 		do_blit:
   1600 		       cld
   1601 		       mov	ebx,[this_object]
   1602 		       mov	esi,[ebx]GraphicViewPortClass.Offset
   1603 		       mov	eax,[ebx]GraphicViewPortClass.XAdd
   1604 		       add	eax,[ebx]GraphicViewPortClass.Width
   1605 		       add	eax,[ebx]GraphicViewPortClass.Pitch
   1606 		       mov	ecx,eax
   1607 		       mul	[y_pixel]
   1608 		       add	esi,[x_pixel]
   1609 		       mov	[source_area],ecx
   1610 		       add	esi,eax
   1611 
   1612 		       add	ecx,[x_pixel ]
   1613 		       sub	ecx,[x1_pixel ]
   1614 		       mov	[scr_adjust_width ],ecx
   1615 
   1616 		       mov	ebx,[dest]
   1617 		       mov	edi,[ebx]GraphicViewPortClass.Offset
   1618 		       mov	eax,[ebx]GraphicViewPortClass.XAdd
   1619 		       add	eax,[ebx]GraphicViewPortClass.Width
   1620 		       add	eax,[ebx]GraphicViewPortClass.Pitch
   1621 		       mov	ecx,eax
   1622 		       mul	[ dest_y0 ]
   1623 		       add	edi,[ dest_x0 ]
   1624 		       mov	[ dest_area ],ecx
   1625 		       add	edi,eax
   1626 
   1627 		       mov	eax,[ dest_x1 ]
   1628 		       sub	eax,[ dest_x0 ]
   1629 		       jle	real_out
   1630 		       sub	ecx,eax
   1631 		       mov	[ dest_adjust_width ],ecx
   1632 
   1633 		       mov	edx,[ dest_y1 ]
   1634 		       sub	edx,[ dest_y0 ]
   1635 		       jle	real_out
   1636 
   1637 		       cmp	esi,edi
   1638 		       jz	real_out
   1639 		       jl	backupward_blit
   1640 
   1641 		; ********************************************************************
   1642 		; Forward bitblit
   1643 
   1644 		       test	[ trans ],1
   1645 		       jnz	forward_Blit_trans
   1646 
   1647 
   1648 		; the inner loop is so efficient that
   1649 		; the optimal consept no longer apply because
   1650 		; the optimal byte have to by a number greather than 9 bytes
   1651 		       cmp	eax,10
   1652 		       jl	forward_loop_bytes
   1653 
   1654 		forward_loop_dword:
   1655 		       mov	ecx,edi
   1656 		       mov	ebx,eax
   1657 		       neg	ecx
   1658 		       and	ecx,3
   1659 		       sub	ebx,ecx
   1660 		       rep	movsb
   1661 		       mov	ecx,ebx
   1662 		       shr	ecx,2
   1663 		       rep	movsd
   1664 		       mov	ecx,ebx
   1665 		       and	ecx,3
   1666 		       rep	movsb
   1667 		       add	esi,[ scr_adjust_width ]
   1668 		       add	edi,[ dest_adjust_width ]
   1669 		       dec	edx
   1670 		       jnz	forward_loop_dword
   1671 		       jmp	real_out	//ret
   1672 
   1673 		forward_loop_bytes:
   1674 		       mov	ecx,eax
   1675 		       rep	movsb
   1676 		       add	esi,[ scr_adjust_width ]
   1677 		       add	edi,[ dest_adjust_width ]
   1678 		       dec	edx
   1679 		       jnz	forward_loop_bytes
   1680 		       jmp	real_out
   1681 
   1682 		forward_Blit_trans:
   1683 		       mov	ecx,eax
   1684 		       and	ecx,01fh
   1685 		       lea	ecx,[ ecx + ecx * 4 ]
   1686 		       neg	ecx
   1687 		       shr	eax,5
   1688 		       lea	ecx,[ transp_reference + ecx * 2 ]
   1689 		       mov	[ y1_pixel ],ecx
   1690 
   1691 		forward_loop_trans:
   1692 		       mov	ecx,eax
   1693 		       jmp	[ y1_pixel ]
   1694 		forward_trans_line:
   1695 		       //REPT	32
   1696 		       //local	transp_pixel
   1697 				 //No REPT in msvc inline assembly.
   1698 				 // Save ECX and use as counter instead. ST - 12/19/2018 5:41PM
   1699 				 push	ecx
   1700 				 mov	ecx, 32
   1701 
   1702 		rept_loop:
   1703 				mov	bl,[ esi ]
   1704 				test	bl,bl
   1705 				jz		transp_pixel
   1706 				mov	[ edi ],bl
   1707 		transp_pixel:
   1708 				inc	esi
   1709 				inc	edi
   1710 
   1711 				dec	ecx			//ST - 12/19/2018 5:44PM
   1712 				jnz	rept_loop	//ST - 12/19/2018 5:44PM
   1713 
   1714 				pop	ecx			//ST - 12/19/2018 5:44PM
   1715 
   1716 			//ENDM
   1717 		    transp_reference:
   1718 		       dec	ecx
   1719 		       jge	forward_trans_line
   1720 		       add	esi,[ scr_adjust_width ]
   1721 		       add	edi,[ dest_adjust_width ]
   1722 		       dec	edx
   1723 		       jnz	forward_loop_trans
   1724 		       jmp	real_out		//ret
   1725 
   1726 
   1727 		; ************************************************************************
   1728 		; backward bitblit
   1729 
   1730 		backupward_blit:
   1731 
   1732 			mov	ebx,[ source_area ]
   1733 			dec	edx
   1734 			add	esi,eax
   1735 			imul    ebx,edx
   1736 			std
   1737 			lea	esi,[ esi + ebx - 1 ]
   1738 
   1739 			mov	ebx,[ dest_area ]
   1740 			add	edi,eax
   1741 			imul    ebx,edx
   1742 			lea	edi,[ edi + ebx - 1]
   1743 
   1744 		       test	[ trans ],1
   1745 		       jnz	backward_Blit_trans
   1746 
   1747 		        cmp	eax,15
   1748 		        jl	backward_loop_bytes
   1749 
   1750 		backward_loop_dword:
   1751 			push	edi
   1752 			push	esi
   1753 			lea	ecx,[edi+1]
   1754 			mov	ebx,eax
   1755 			and	ecx,3		; Get non aligned bytes.
   1756 			sub	ebx,ecx		; remove that from the total size to be copied later.
   1757 			rep	movsb		; do the copy.
   1758 			sub	esi,3
   1759 			mov	ecx,ebx		; Get number of bytes left.
   1760 		 	sub	edi,3
   1761 			shr	ecx,2		; Do 4 bytes at a time.
   1762 			rep	movsd		; do the dword copy.
   1763 			mov	ecx,ebx
   1764 			add	esi,3
   1765 			add	edi,3
   1766 			and	ecx,03h
   1767 			rep	movsb		; finnish the remaining bytes.
   1768 			pop	esi
   1769 			pop	edi
   1770 		        sub	esi,[ source_area ]
   1771 		        sub	edi,[ dest_area ]
   1772 			dec	edx
   1773 			jge	backward_loop_dword
   1774 			cld
   1775 			jmp	real_out		//ret
   1776 
   1777 		backward_loop_bytes:
   1778 			push	edi
   1779 			mov	ecx,eax		; remove that from the total size to be copied later.
   1780 			push	esi
   1781 			rep	movsb		; do the copy.
   1782 			pop	esi
   1783 			pop	edi
   1784 		        sub	esi,[ source_area ]
   1785 		        sub	edi,[ dest_area ]
   1786 			dec	edx
   1787 			jge	backward_loop_bytes
   1788 			cld
   1789 			jmp	real_out		//ret
   1790 
   1791 		backward_Blit_trans:
   1792 		       mov	ecx,eax
   1793 		       and	ecx,01fh
   1794 		       lea	ecx,[ ecx + ecx * 4 ]
   1795 		       neg	ecx
   1796 		       shr	eax,5
   1797 		       lea	ecx,[ back_transp_reference + ecx * 2 ]
   1798 		       mov	[ y1_pixel ],ecx
   1799 
   1800 		backward_loop_trans:
   1801 		       mov	ecx,eax
   1802 		       push	edi
   1803 		       push	esi
   1804 		       jmp	[ y1_pixel ]
   1805 		backward_trans_line:
   1806 		       //REPT	32
   1807 		       //local	transp_pixel2
   1808 				 //No REPT in msvc inline assembly.
   1809 				 // Save ECX and use as counter instead. ST - 12/19/2018 5:41PM
   1810 				 push	ecx
   1811 				 mov	ecx, 32
   1812 		rept_loop2:
   1813 				 mov	bl,[ esi ]
   1814 				 test	bl,bl
   1815 				 jz	transp_pixel2
   1816 				 mov	[ edi ],bl
   1817 		transp_pixel2:
   1818 				 dec	esi
   1819 				 dec	edi
   1820 
   1821 				 dec	ecx				//ST - 12/19/2018 5:44PM
   1822 				 jnz	rept_loop2		//ST - 12/19/2018 5:44PM
   1823 
   1824 				 pop	ecx				//ST - 12/19/2018 5:44PM
   1825 			
   1826 			//ENDM
   1827 		    
   1828 			 back_transp_reference:
   1829 		       dec	ecx
   1830 		       jge	backward_trans_line
   1831 		       pop	esi
   1832 		       pop	edi
   1833 		       sub	esi,[ source_area ]
   1834 		       sub	edi,[ dest_area ]
   1835 		       dec	edx
   1836 		       jge	backward_loop_trans
   1837 		       cld
   1838 		       //ret
   1839 
   1840 		real_out:
   1841 	}
   1842 }
   1843 
   1844 
   1845 
   1846 
   1847 
   1848 
   1849 
   1850 
   1851 
   1852 
   1853 
   1854 
   1855 /*
   1856 ;***************************************************************************
   1857 ;* VVC::SCALE -- Scales a virtual viewport to another virtual viewport     *
   1858 ;*                                                                         *
   1859 ;* INPUT:                                                                  *
   1860 ;*                                                                         *
   1861 ;* OUTPUT:                                                                 *
   1862 ;*                                                                         *
   1863 ;* WARNINGS:                                                               *
   1864 ;*                                                                         *
   1865 ;* HISTORY:                                                                *
   1866 ;*   06/16/1994 PWG : Created.                                             *
   1867 ;*=========================================================================*
   1868 	PROC	Linear_Scale_To_Linear C NEAR
   1869 	USES	eax,ebx,ecx,edx,esi,edi
   1870 */
   1871 
   1872 // Ran out of registers so had to use ebp. ST - 12/19/2018 6:22PM
   1873 #pragma warning (push)
   1874 #pragma warning (disable : 4731)
   1875 
   1876 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)
   1877 {
   1878 /*			  
   1879 
   1880 	;*===================================================================
   1881 	;* Define the arguements that our function takes.
   1882 	;*===================================================================
   1883 	ARG	this_object:DWORD		; pointer to source view port
   1884 	ARG	dest:DWORD		; pointer to destination view port
   1885 	ARG	src_x:DWORD		; source x offset into view port
   1886 	ARG	src_y:DWORD		; source y offset into view port
   1887 	ARG	dst_x:DWORD		; dest x offset into view port
   1888 	ARG	dst_y:DWORD		; dest y offset into view port
   1889 	ARG	src_width:DWORD		; width of source rectangle
   1890 	ARG	src_height:DWORD	; height of source rectangle
   1891 	ARG	dst_width:DWORD		; width of dest rectangle
   1892 	ARG	dst_height:DWORD	; width of dest height
   1893 	ARG	trans:DWORD		; is this transparent?
   1894 	ARG	remap:DWORD		; pointer to table to remap source
   1895 
   1896 	;*===================================================================
   1897 	;* Define local variables to hold the viewport characteristics
   1898 	;*===================================================================
   1899 	local	src_x0 : dword
   1900 	local	src_y0 : dword
   1901 	local	src_x1 : dword
   1902 	local	src_y1 : dword
   1903 
   1904 	local	dst_x0 : dword
   1905 	local	dst_y0 : dword
   1906 	local	dst_x1 : dword
   1907 	local	dst_y1 : dword
   1908 
   1909 	local	src_win_width : dword
   1910 	local	dst_win_width : dword
   1911 	local	dy_intr : dword
   1912 	local	dy_frac : dword
   1913 	local	dy_acc  : dword
   1914 	local	dx_frac : dword
   1915 
   1916 	local	counter_x     : dword
   1917 	local	counter_y     : dword
   1918 	local	remap_counter :dword
   1919 	local	entry : dword
   1920 */
   1921 	
   1922 	int src_x0;
   1923 	int src_y0;
   1924 	int src_x1;
   1925 	int src_y1;
   1926 
   1927 	int dst_x0;
   1928 	int dst_y0;
   1929 	int dst_x1;
   1930 	int dst_y1;
   1931 
   1932 	int src_win_width;
   1933 	int dst_win_width;
   1934 	int dy_intr;
   1935 	int dy_frac;
   1936 	int dy_acc;
   1937 	int dx_frac;
   1938 
   1939 	int counter_x;
   1940 	int counter_y;
   1941 	int remap_counter;
   1942 	int entry;
   1943 	
   1944 	
   1945 	__asm {
   1946 		
   1947 		;*===================================================================
   1948 		;* Check for scale error when to or from size 0,0
   1949 		;*===================================================================
   1950 		cmp	[dst_width],0
   1951 		je	all_done
   1952 		cmp	[dst_height],0
   1953 		je	all_done
   1954 		cmp	[src_width],0
   1955 		je	all_done
   1956 		cmp	[src_height],0
   1957 		je	all_done
   1958 
   1959 		mov	eax , [ src_x ]
   1960 		mov	ebx , [ src_y ]
   1961 		mov	[ src_x0 ] , eax
   1962 		mov	[ src_y0 ] , ebx
   1963 		add	eax , [ src_width ]
   1964 		add	ebx , [ src_height ]
   1965 		mov	[ src_x1 ] , eax
   1966 		mov	[ src_y1 ] , ebx
   1967 
   1968 		mov	eax , [ dst_x ]
   1969 		mov	ebx , [ dst_y ]
   1970 		mov	[ dst_x0 ] , eax
   1971 		mov	[ dst_y0 ] , ebx
   1972 		add	eax , [ dst_width ]
   1973 		add	ebx , [ dst_height ]
   1974 		mov	[ dst_x1 ] , eax
   1975 		mov	[ dst_y1 ] , ebx
   1976 
   1977 	; Clip Source Rectangle against source Window boundaries.
   1978 		mov  	esi , [ this_object ]	    ; get ptr to src
   1979 		xor 	ecx , ecx
   1980 		xor 	edx , edx
   1981 		mov	edi , [esi]GraphicViewPortClass.Width  ; get width into register
   1982 		mov	eax , [ src_x0 ]
   1983 		mov	ebx , [ src_x1 ]
   1984 		shld	ecx , eax , 1
   1985 		inc	edi
   1986 		shld	edx , ebx , 1
   1987 		sub	eax , edi
   1988 		sub	ebx , edi
   1989 		shld	ecx , eax , 1
   1990 		shld	edx , ebx , 1
   1991 
   1992 		mov	edi,[esi]GraphicViewPortClass.Height ; get height into register
   1993 		mov	eax , [ src_y0 ]
   1994 		mov	ebx , [ src_y1 ]
   1995 		shld	ecx , eax , 1
   1996 		inc	edi
   1997 		shld	edx , ebx , 1
   1998 		sub	eax , edi
   1999 		sub	ebx , edi
   2000 		shld	ecx , eax , 1
   2001 		shld	edx , ebx , 1
   2002 
   2003 		xor	cl , 5
   2004 		xor	dl , 5
   2005 		mov	al , cl
   2006 		test	dl , cl
   2007 		jnz	all_done
   2008 		or	al , dl
   2009 		jz	clip_against_dest
   2010 		mov	bl , dl
   2011 		test	cl , 1000b
   2012 		jz	src_left_ok
   2013 		xor	eax , eax
   2014 		mov	[ src_x0 ] , eax
   2015 		sub	eax , [ src_x ]
   2016 		imul	[ dst_width ]
   2017 		idiv	[ src_width ]
   2018 		add	eax , [ dst_x ]
   2019 		mov	[ dst_x0 ] , eax
   2020 
   2021 	src_left_ok:
   2022 		test	cl , 0010b
   2023 		jz	src_bottom_ok
   2024 		xor	eax , eax
   2025 		mov	[ src_y0 ] , eax
   2026 		sub	eax , [ src_y ]
   2027 		imul	[ dst_height ]
   2028 		idiv	[ src_height ]
   2029 		add	eax , [ dst_y ]
   2030 		mov	[ dst_y0 ] , eax
   2031 
   2032 	src_bottom_ok:
   2033 		test	bl , 0100b
   2034 		jz	src_right_ok
   2035 		mov	eax , [esi]GraphicViewPortClass.Width  ; get width into register
   2036 		mov	[ src_x1 ] , eax
   2037 		sub	eax , [ src_x ]
   2038 		imul	[ dst_width ]
   2039 		idiv	[ src_width ]
   2040 		add	eax , [ dst_x ]
   2041 		mov	[ dst_x1 ] , eax
   2042 
   2043 	src_right_ok:
   2044 		test	bl , 0001b
   2045 		jz	clip_against_dest
   2046 		mov	eax , [esi]GraphicViewPortClass.Height  ; get width into register
   2047 		mov	[ src_y1 ] , eax
   2048 		sub	eax , [ src_y ]
   2049 		imul	[ dst_height ]
   2050 		idiv	[ src_height ]
   2051 		add	eax , [ dst_y ]
   2052 		mov	[ dst_y1 ] , eax
   2053 
   2054 	; Clip destination Rectangle against source Window boundaries.
   2055 	clip_against_dest:
   2056 		mov  	esi , [ dest ]	    ; get ptr to src
   2057 		xor 	ecx , ecx
   2058 		xor 	edx , edx
   2059 		mov	edi , [esi]GraphicViewPortClass.Width  ; get width into register
   2060 		mov	eax , [ dst_x0 ]
   2061 		mov	ebx , [ dst_x1 ]
   2062 		shld	ecx , eax , 1
   2063 		inc	edi
   2064 		shld	edx , ebx , 1
   2065 		sub	eax , edi
   2066 		sub	ebx , edi
   2067 		shld	ecx , eax , 1
   2068 		shld	edx , ebx , 1
   2069 
   2070 		mov	edi,[esi]GraphicViewPortClass.Height ; get height into register
   2071 		mov	eax , [ dst_y0 ]
   2072 		mov	ebx , [ dst_y1 ]
   2073 		shld	ecx , eax , 1
   2074 		inc	edi
   2075 		shld	edx , ebx , 1
   2076 		sub	eax , edi
   2077 		sub	ebx , edi
   2078 		shld	ecx , eax , 1
   2079 		shld	edx , ebx , 1
   2080 
   2081 		xor	cl , 5
   2082 		xor	dl , 5
   2083 		mov	al , cl
   2084 		test	dl , cl
   2085 		jnz	all_done
   2086 		or	al , dl
   2087 		jz	do_scaling
   2088 		mov	bl , dl
   2089 		test	cl , 1000b
   2090 		jz	dst_left_ok
   2091 		xor	eax , eax
   2092 		mov	[ dst_x0 ] , eax
   2093 		sub	eax , [ dst_x ]
   2094 		imul	[ src_width ]
   2095 		idiv	[ dst_width ]
   2096 		add	eax , [ src_x ]
   2097 		mov	[ src_x0 ] , eax
   2098 
   2099 	dst_left_ok:
   2100 		test	cl , 0010b
   2101 		jz	dst_bottom_ok
   2102 		xor	eax , eax
   2103 		mov	[ dst_y0 ] , eax
   2104 		sub	eax , [ dst_y ]
   2105 		imul	[ src_height ]
   2106 		idiv	[ dst_height ]
   2107 		add	eax , [ src_y ]
   2108 		mov	[ src_y0 ] , eax
   2109 
   2110 	dst_bottom_ok:
   2111 		test	bl , 0100b
   2112 		jz	dst_right_ok
   2113 		mov	eax , [esi]GraphicViewPortClass.Width  ; get width into register
   2114 		mov	[ dst_x1 ] , eax
   2115 		sub	eax , [ dst_x ]
   2116 		imul	[ src_width ]
   2117 		idiv	[ dst_width ]
   2118 		add	eax , [ src_x ]
   2119 		mov	[ src_x1 ] , eax
   2120 
   2121 	dst_right_ok:
   2122 		test	bl , 0001b
   2123 		jz	do_scaling
   2124 
   2125 		mov	eax , [esi]GraphicViewPortClass.Height  ; get width into register
   2126 		mov	[ dst_y1 ] , eax
   2127 		sub	eax , [ dst_y ]
   2128 		imul	[ src_height ]
   2129 		idiv	[ dst_height ]
   2130 		add	eax , [ src_y ]
   2131 		mov	[ src_y1 ] , eax
   2132 
   2133 	do_scaling:
   2134 
   2135    	    cld
   2136    	    mov	ebx , [ this_object ]
   2137    	    mov	esi , [ebx]GraphicViewPortClass. Offset
   2138    	    mov	eax , [ebx]GraphicViewPortClass. XAdd
   2139    	    add	eax , [ebx]GraphicViewPortClass. Width
   2140    	    add	eax , [ebx]GraphicViewPortClass. Pitch
   2141    	    mov	[ src_win_width ] , eax
   2142    	    mul	[ src_y0 ]
   2143    	    add	esi , [ src_x0 ]
   2144    	    add	esi , eax
   2145 
   2146    	    mov	ebx , [ dest ]
   2147    	    mov	edi , [ebx]GraphicViewPortClass. Offset
   2148    	    mov	eax , [ebx]GraphicViewPortClass. XAdd
   2149    	    add	eax , [ebx]GraphicViewPortClass. Width
   2150    	    add	eax , [ebx]GraphicViewPortClass. Pitch
   2151    	    mov	[ dst_win_width ] , eax
   2152    	    mul	[ dst_y0 ]
   2153    	    add	edi , [ dst_x0 ]
   2154    	    add	edi , eax
   2155 
   2156    	    mov	eax , [ src_height ]
   2157    	    xor	edx , edx
   2158    	    mov	ebx , [ dst_height ]
   2159    	    idiv	[ dst_height ]
   2160    	    imul	eax , [ src_win_width ]
   2161    	    neg	ebx
   2162    	    mov	[ dy_intr ] , eax
   2163    	    mov	[ dy_frac ] , edx
   2164    	    mov	[ dy_acc ]  , ebx
   2165 
   2166    	    mov	eax , [ src_width ]
   2167    	    xor	edx , edx
   2168    	    shl	eax , 16
   2169    	    idiv	[ dst_width ]
   2170    	    xor	edx , edx
   2171    	    shld	edx , eax , 16
   2172    	    shl	eax , 16
   2173 
   2174    	    mov	ecx , [ dst_y1 ]
   2175    	    mov	ebx , [ dst_x1 ]
   2176    	    sub	ecx , [ dst_y0 ]
   2177    	    jle	all_done
   2178    	    sub	ebx , [ dst_x0 ]
   2179    	    jle	all_done
   2180 
   2181    	    mov	[ counter_y ] , ecx
   2182 
   2183    	    cmp	[ trans ] , 0
   2184    	    jnz	transparency
   2185 
   2186    	    cmp	[ remap ] , 0
   2187    	    jnz	normal_remap
   2188 
   2189 	; *************************************************************************
   2190 	; normal scale
   2191    	    mov	ecx , ebx
   2192    	    and	ecx , 01fh
   2193    	    lea	ecx , [ ecx + ecx * 2 ]
   2194    	    shr	ebx , 5
   2195    	    neg	ecx
   2196    	    mov	[ counter_x ] , ebx
   2197    	    lea	ecx , [ ref_point + ecx + ecx * 2 ]
   2198    	    mov	[ entry ] , ecx
   2199 
   2200  	outter_loop:
   2201    	    push	esi
   2202    	    push	edi
   2203    	    xor	ecx , ecx
   2204    	    mov	ebx , [ counter_x ]
   2205    	    jmp	[ entry ]
   2206  	inner_loop:
   2207    	    // REPT not supported for inline asm. ST - 12/19/2018 6:11PM
   2208 			 //REPT	32
   2209 			 	push ebx		//ST - 12/19/2018 6:11PM
   2210 				mov ebx,32	//ST - 12/19/2018 6:11PM
   2211 rept_loop:
   2212 		       mov	cl , [ esi ]
   2213 		       add	ecx , eax
   2214 		       adc	esi , edx
   2215 		       mov	[ edi ] , cl
   2216 		       inc	edi
   2217 
   2218 				dec ebx				//ST - 12/19/2018 6:11PM
   2219 				jnz rept_loop		//ST - 12/19/2018 6:11PM
   2220 				pop ebx				//ST - 12/19/2018 6:11PM
   2221    	    //ENDM
   2222  	ref_point:
   2223    	    dec	ebx
   2224    	    jge	inner_loop
   2225 
   2226    	    pop	edi
   2227    	    pop	esi
   2228    	    add	edi , [ dst_win_width ]
   2229    	    add	esi , [ dy_intr ]
   2230 
   2231    	    mov	ebx , [ dy_acc ]
   2232    	    add	ebx , [ dy_frac ]
   2233    	    jle	skip_line
   2234    	    add	esi , [ src_win_width ]
   2235    	    sub	ebx , [ dst_height ]
   2236 	skip_line:
   2237 		dec	[ counter_y ]
   2238 		mov	[ dy_acc ] , ebx
   2239 		jnz	outter_loop
   2240 		jmp	all_done	//ret
   2241 
   2242 
   2243 	; *************************************************************************
   2244 	; normal scale with remap
   2245 
   2246 	normal_remap:
   2247    	    mov	ecx , ebx
   2248    	    mov	[ dx_frac ], eax
   2249    	    and	ecx , 01fh
   2250    	    mov	eax , [ remap ]
   2251    	    shr	ebx , 5
   2252    	    imul	ecx , - 13
   2253    	    mov	[ counter_x ] , ebx
   2254    	    lea	ecx , [ remapref_point + ecx ]
   2255    	    mov	[ entry ] , ecx
   2256 
   2257  	remapoutter_loop:
   2258    	    mov	ebx , [ counter_x ]
   2259    	    push	esi
   2260    	    mov	[ remap_counter ] , ebx
   2261    	    push	edi
   2262    	    xor	ecx , ecx
   2263    	    xor	ebx , ebx
   2264    	    jmp	[ entry ]
   2265  	remapinner_loop:
   2266    	    // REPT not supported for inline asm. ST - 12/19/2018 6:11PM
   2267 			 //REPT	32
   2268 		       mov	bl , [ esi ]
   2269 		       add	ecx , [ dx_frac ]
   2270 		       adc	esi , edx
   2271 		       mov	cl , [ eax + ebx ]
   2272 		       mov	[ edi ] , cl
   2273 		       inc	edi
   2274 		       mov	bl , [ esi ]
   2275 		       add	ecx , [ dx_frac ]
   2276 		       adc	esi , edx
   2277 		       mov	cl , [ eax + ebx ]
   2278 		       mov	[ edi ] , cl
   2279 		       inc	edi
   2280 		       mov	bl , [ esi ]
   2281 		       add	ecx , [ dx_frac ]
   2282 		       adc	esi , edx
   2283 		       mov	cl , [ eax + ebx ]
   2284 		       mov	[ edi ] , cl
   2285 		       inc	edi
   2286 		       mov	bl , [ esi ]
   2287 		       add	ecx , [ dx_frac ]
   2288 		       adc	esi , edx
   2289 		       mov	cl , [ eax + ebx ]
   2290 		       mov	[ edi ] , cl
   2291 		       inc	edi
   2292 		       mov	bl , [ esi ]
   2293 		       add	ecx , [ dx_frac ]
   2294 		       adc	esi , edx
   2295 		       mov	cl , [ eax + ebx ]
   2296 		       mov	[ edi ] , cl
   2297 		       inc	edi
   2298 		       mov	bl , [ esi ]
   2299 		       add	ecx , [ dx_frac ]
   2300 		       adc	esi , edx
   2301 		       mov	cl , [ eax + ebx ]
   2302 		       mov	[ edi ] , cl
   2303 		       inc	edi
   2304 		       mov	bl , [ esi ]
   2305 		       add	ecx , [ dx_frac ]
   2306 		       adc	esi , edx
   2307 		       mov	cl , [ eax + ebx ]
   2308 		       mov	[ edi ] , cl
   2309 		       inc	edi
   2310 		       mov	bl , [ esi ]
   2311 		       add	ecx , [ dx_frac ]
   2312 		       adc	esi , edx
   2313 		       mov	cl , [ eax + ebx ]
   2314 		       mov	[ edi ] , cl
   2315 		       inc	edi
   2316 		       mov	bl , [ esi ]
   2317 		       add	ecx , [ dx_frac ]
   2318 		       adc	esi , edx
   2319 		       mov	cl , [ eax + ebx ]
   2320 		       mov	[ edi ] , cl
   2321 		       inc	edi
   2322 		       mov	bl , [ esi ]
   2323 		       add	ecx , [ dx_frac ]
   2324 		       adc	esi , edx
   2325 		       mov	cl , [ eax + ebx ]
   2326 		       mov	[ edi ] , cl
   2327 		       inc	edi
   2328 		       mov	bl , [ esi ]
   2329 		       add	ecx , [ dx_frac ]
   2330 		       adc	esi , edx
   2331 		       mov	cl , [ eax + ebx ]
   2332 		       mov	[ edi ] , cl
   2333 		       inc	edi
   2334 		       mov	bl , [ esi ]
   2335 		       add	ecx , [ dx_frac ]
   2336 		       adc	esi , edx
   2337 		       mov	cl , [ eax + ebx ]
   2338 		       mov	[ edi ] , cl
   2339 		       inc	edi
   2340 		       mov	bl , [ esi ]
   2341 		       add	ecx , [ dx_frac ]
   2342 		       adc	esi , edx
   2343 		       mov	cl , [ eax + ebx ]
   2344 		       mov	[ edi ] , cl
   2345 		       inc	edi
   2346 		       mov	bl , [ esi ]
   2347 		       add	ecx , [ dx_frac ]
   2348 		       adc	esi , edx
   2349 		       mov	cl , [ eax + ebx ]
   2350 		       mov	[ edi ] , cl
   2351 		       inc	edi
   2352 		       mov	bl , [ esi ]
   2353 		       add	ecx , [ dx_frac ]
   2354 		       adc	esi , edx
   2355 		       mov	cl , [ eax + ebx ]
   2356 		       mov	[ edi ] , cl
   2357 		       inc	edi
   2358 		       mov	bl , [ esi ]
   2359 		       add	ecx , [ dx_frac ]
   2360 		       adc	esi , edx
   2361 		       mov	cl , [ eax + ebx ]
   2362 		       mov	[ edi ] , cl
   2363 		       inc	edi
   2364 		       mov	bl , [ esi ]
   2365 		       add	ecx , [ dx_frac ]
   2366 		       adc	esi , edx
   2367 		       mov	cl , [ eax + ebx ]
   2368 		       mov	[ edi ] , cl
   2369 		       inc	edi
   2370 		       mov	bl , [ esi ]
   2371 		       add	ecx , [ dx_frac ]
   2372 		       adc	esi , edx
   2373 		       mov	cl , [ eax + ebx ]
   2374 		       mov	[ edi ] , cl
   2375 		       inc	edi
   2376 		       mov	bl , [ esi ]
   2377 		       add	ecx , [ dx_frac ]
   2378 		       adc	esi , edx
   2379 		       mov	cl , [ eax + ebx ]
   2380 		       mov	[ edi ] , cl
   2381 		       inc	edi
   2382 		       mov	bl , [ esi ]
   2383 		       add	ecx , [ dx_frac ]
   2384 		       adc	esi , edx
   2385 		       mov	cl , [ eax + ebx ]
   2386 		       mov	[ edi ] , cl
   2387 		       inc	edi
   2388 		       mov	bl , [ esi ]
   2389 		       add	ecx , [ dx_frac ]
   2390 		       adc	esi , edx
   2391 		       mov	cl , [ eax + ebx ]
   2392 		       mov	[ edi ] , cl
   2393 		       inc	edi
   2394 		       mov	bl , [ esi ]
   2395 		       add	ecx , [ dx_frac ]
   2396 		       adc	esi , edx
   2397 		       mov	cl , [ eax + ebx ]
   2398 		       mov	[ edi ] , cl
   2399 		       inc	edi
   2400 		       mov	bl , [ esi ]
   2401 		       add	ecx , [ dx_frac ]
   2402 		       adc	esi , edx
   2403 		       mov	cl , [ eax + ebx ]
   2404 		       mov	[ edi ] , cl
   2405 		       inc	edi
   2406 		       mov	bl , [ esi ]
   2407 		       add	ecx , [ dx_frac ]
   2408 		       adc	esi , edx
   2409 		       mov	cl , [ eax + ebx ]
   2410 		       mov	[ edi ] , cl
   2411 		       inc	edi
   2412 		       mov	bl , [ esi ]
   2413 		       add	ecx , [ dx_frac ]
   2414 		       adc	esi , edx
   2415 		       mov	cl , [ eax + ebx ]
   2416 		       mov	[ edi ] , cl
   2417 		       inc	edi
   2418 		       mov	bl , [ esi ]
   2419 		       add	ecx , [ dx_frac ]
   2420 		       adc	esi , edx
   2421 		       mov	cl , [ eax + ebx ]
   2422 		       mov	[ edi ] , cl
   2423 		       inc	edi
   2424 		       mov	bl , [ esi ]
   2425 		       add	ecx , [ dx_frac ]
   2426 		       adc	esi , edx
   2427 		       mov	cl , [ eax + ebx ]
   2428 		       mov	[ edi ] , cl
   2429 		       inc	edi
   2430 		       mov	bl , [ esi ]
   2431 		       add	ecx , [ dx_frac ]
   2432 		       adc	esi , edx
   2433 		       mov	cl , [ eax + ebx ]
   2434 		       mov	[ edi ] , cl
   2435 		       inc	edi
   2436 		       mov	bl , [ esi ]
   2437 		       add	ecx , [ dx_frac ]
   2438 		       adc	esi , edx
   2439 		       mov	cl , [ eax + ebx ]
   2440 		       mov	[ edi ] , cl
   2441 		       inc	edi
   2442 		       mov	bl , [ esi ]
   2443 		       add	ecx , [ dx_frac ]
   2444 		       adc	esi , edx
   2445 		       mov	cl , [ eax + ebx ]
   2446 		       mov	[ edi ] , cl
   2447 		       inc	edi
   2448 		       mov	bl , [ esi ]
   2449 		       add	ecx , [ dx_frac ]
   2450 		       adc	esi , edx
   2451 		       mov	cl , [ eax + ebx ]
   2452 		       mov	[ edi ] , cl
   2453 		       inc	edi
   2454 		       mov	bl , [ esi ]
   2455 		       add	ecx , [ dx_frac ]
   2456 		       adc	esi , edx
   2457 		       mov	cl , [ eax + ebx ]
   2458 		       mov	[ edi ] , cl
   2459 		       inc	edi
   2460 
   2461    	    //ENDM
   2462  	remapref_point:
   2463    	    dec	[ remap_counter ]
   2464    	    jge	remapinner_loop
   2465 
   2466    	    pop	edi
   2467    	    pop	esi
   2468    	    add	edi , [ dst_win_width ]
   2469    	    add	esi , [ dy_intr ]
   2470 
   2471    	    mov	ebx , [ dy_acc ]
   2472    	    add	ebx , [ dy_frac ]
   2473    	    jle	remapskip_line
   2474    	    add	esi , [ src_win_width ]
   2475    	    sub	ebx , [ dst_height ]
   2476 	remapskip_line:
   2477 		dec	[ counter_y ]
   2478 		mov	[ dy_acc ] , ebx
   2479 		jnz	remapoutter_loop
   2480 		jmp	all_done	//ret
   2481 
   2482 
   2483 	;****************************************************************************
   2484 	; scale with trnsparency
   2485 
   2486 	transparency:
   2487    	    cmp	[ remap ] , 0
   2488    	    jnz	trans_remap
   2489 
   2490 	; *************************************************************************
   2491 	; normal scale with transparency
   2492    	    mov	ecx , ebx
   2493    	    and	ecx , 01fh
   2494    	    imul	ecx , -13
   2495    	    shr	ebx , 5
   2496    	    mov	[ counter_x ] , ebx
   2497    	    lea	ecx , [ trans_ref_point + ecx ]
   2498    	    mov	[ entry ] , ecx
   2499 
   2500  	trans_outter_loop:
   2501    	    xor	ecx , ecx
   2502    	    push	esi
   2503    	    push	edi
   2504    	    mov	ebx , [ counter_x ]
   2505    	    jmp	[ entry ]
   2506  	trans_inner_loop:
   2507    	    
   2508    	    // REPT not supported for inline asm. ST - 12/19/2018 6:11PM
   2509 			 //REPT	32
   2510 			 	push ebx		//ST - 12/19/2018 6:11PM
   2511 				mov ebx,32	//ST - 12/19/2018 6:11PM
   2512 rept_loop2:
   2513 			 
   2514 		       mov	cl , [ esi ]
   2515 		       test	cl , cl
   2516 		       jz	trans_pixel
   2517 		       mov	[ edi ] , cl
   2518    	    trans_pixel:
   2519 		       add	ecx , eax
   2520 		       adc	esi , edx
   2521 		       inc	edi
   2522 				
   2523 				dec ebx				//ST - 12/19/2018 6:11PM
   2524 				jnz rept_loop2		//ST - 12/19/2018 6:11PM
   2525 				pop ebx				//ST - 12/19/2018 6:11PM
   2526    	    
   2527 			 //ENDM
   2528  	trans_ref_point:
   2529    	    dec	ebx
   2530    	    jge	trans_inner_loop
   2531 
   2532    	    pop	edi
   2533    	    pop	esi
   2534    	    add	edi , [ dst_win_width ]
   2535    	    add	esi , [ dy_intr ]
   2536 
   2537    	    mov	ebx , [ dy_acc ]
   2538    	    add	ebx , [ dy_frac ]
   2539    	    jle	trans_skip_line
   2540    	    add	esi , [ src_win_width ]
   2541    	    sub	ebx , [ dst_height ]
   2542 	trans_skip_line:
   2543 		dec	[ counter_y ]
   2544 		mov	[ dy_acc ] , ebx
   2545 		jnz	trans_outter_loop
   2546 		jmp	all_done	//ret
   2547 
   2548 
   2549 	; *************************************************************************
   2550 	; normal scale with remap
   2551 
   2552 	trans_remap:
   2553    	    mov	ecx , ebx
   2554    	    mov	[ dx_frac ], eax
   2555    	    and	ecx , 01fh
   2556    	    mov	eax , [ remap ]
   2557    	    shr	ebx , 5
   2558    	    imul	ecx , - 17
   2559    	    mov	[ counter_x ] , ebx
   2560    	    lea	ecx , [ trans_remapref_point + ecx ]
   2561    	    mov	[ entry ] , ecx
   2562 
   2563  	trans_remapoutter_loop:
   2564    	    mov	ebx , [ counter_x ]
   2565    	    push	esi
   2566    	    mov	[ remap_counter ] , ebx
   2567    	    push	edi
   2568    	    xor	ecx , ecx
   2569    	    xor	ebx , ebx
   2570    	    jmp	[ entry ]
   2571  	
   2572 	
   2573 	trans_remapinner_loop:
   2574    	    // REPT not supported for inline asm. ST - 12/19/2018 6:11PM
   2575 			 //REPT	32
   2576 			 // Run out of registers so use ebp
   2577 			 	push ebp		//ST - 12/19/2018 6:11PM
   2578 				mov ebp,32	//ST - 12/19/2018 6:11PM
   2579 rept_loop3:
   2580 		       mov	bl , [ esi ]
   2581 		       test	bl , bl
   2582 		       jz	trans_pixel2
   2583 		       mov	cl , [ eax + ebx ]
   2584 		       mov	[ edi ] , cl
   2585 		  trans_pixel2:
   2586 		       add	ecx , [ dx_frac ]
   2587 		       adc	esi , edx
   2588 		       inc	edi
   2589 				
   2590 				dec ebp				//ST - 12/19/2018 6:11PM
   2591 				jnz rept_loop3		//ST - 12/19/2018 6:11PM
   2592 				pop ebp				//ST - 12/19/2018 6:11PM
   2593 
   2594    	    //ENDM
   2595 
   2596  	trans_remapref_point:
   2597    	    dec	[ remap_counter ]
   2598    	    jge	trans_remapinner_loop
   2599 
   2600    	    pop	edi
   2601    	    pop	esi
   2602    	    add	edi , [ dst_win_width ]
   2603    	    add	esi , [ dy_intr ]
   2604 
   2605    	    mov	ebx , [ dy_acc ]
   2606    	    add	ebx , [ dy_frac ]
   2607    	    jle	trans_remapskip_line
   2608    	    add	esi , [ src_win_width ]
   2609    	    sub	ebx , [ dst_height ]
   2610 	trans_remapskip_line:
   2611 		dec	[ counter_y ]
   2612 		mov	[ dy_acc ] , ebx
   2613 		jnz	trans_remapoutter_loop
   2614 		//ret
   2615 
   2616 
   2617 	all_done:
   2618 	}
   2619 }
   2620 
   2621 
   2622 #pragma warning (pop)
   2623 
   2624 
   2625 
   2626 
   2627 
   2628 
   2629 
   2630 
   2631 
   2632 
   2633 
   2634 
   2635 
   2636 
   2637 
   2638 
   2639 
   2640 
   2641 
   2642 
   2643 unsigned int LastIconset = 0;
   2644 unsigned int StampPtr = 0;	//	DD	0	; Pointer to icon data.
   2645 
   2646 unsigned int IsTrans = 0;	//		DD	0	; Pointer to transparent icon flag table.
   2647 
   2648 unsigned int MapPtr = 0;	//		DD	0	; Pointer to icon map.
   2649 unsigned int IconWidth = 0;	//	DD	0	; Width of icon in pixels.
   2650 unsigned int IconHeight = 0;	//	DD	0	; Height of icon in pixels.
   2651 unsigned int IconSize = 0;		//	DD	0	; Number of bytes for each icon data.
   2652 unsigned int IconCount = 0;	//	DD	0	; Number of icons in the set.
   2653 
   2654 
   2655 
   2656 #if (0)
   2657 LastIconset	DD	0	; Pointer to last iconset initialized.
   2658 StampPtr	DD	0	; Pointer to icon data.
   2659 
   2660 IsTrans		DD	0	; Pointer to transparent icon flag table.
   2661 
   2662 MapPtr		DD	0	; Pointer to icon map.
   2663 IconWidth	DD	0	; Width of icon in pixels.
   2664 IconHeight	DD	0	; Height of icon in pixels.
   2665 IconSize	DD	0	; Number of bytes for each icon data.
   2666 IconCount	DD	0	; Number of icons in the set.
   2667 
   2668 
   2669 GLOBAL C	Buffer_Draw_Stamp:near
   2670 GLOBAL C	Buffer_Draw_Stamp_Clip:near
   2671 
   2672 ; 256 color icon system.
   2673 #endif
   2674 
   2675 
   2676 /*
   2677 ;***********************************************************
   2678 ; INIT_STAMPS
   2679 ;
   2680 ; VOID cdecl Init_Stamps(VOID *icondata);
   2681 ;
   2682 ; This routine initializes the stamp data.
   2683 ; Bounds Checking: NONE
   2684 ;
   2685 ;*
   2686 */ 
   2687 extern "C" void __cdecl Init_Stamps(unsigned int icondata)
   2688 {
   2689 
   2690 	__asm {
   2691 		pushad										// ST - 12/20/2018 10:30AM
   2692 		
   2693 		; Verify legality of parameter.
   2694 		cmp	[icondata],0
   2695 		je	short fini
   2696 
   2697 		; Don't initialize if already initialized to this set (speed reasons).
   2698 		mov	edi,[icondata]
   2699 		cmp	[LastIconset],edi
   2700 		je	short fini
   2701 		mov	[LastIconset],edi
   2702 
   2703 		; Record number of icons in set.
   2704 		movzx	eax,[edi]IControl_Type.Count
   2705 		mov	[IconCount],eax
   2706 
   2707 		; Record width of icon.
   2708 		movzx	eax,[edi]IControl_Type.Width
   2709 		mov	[IconWidth],eax
   2710 
   2711 		; Record height of icon.
   2712 		movzx	ebx,[edi]IControl_Type.Height
   2713 		mov	[IconHeight],ebx
   2714 
   2715 		; Record size of icon (in bytes).
   2716 		mul	ebx
   2717 		mov	[IconSize],eax
   2718 
   2719 		; Record hard pointer to icon map data.
   2720 		mov	eax,[edi]IControl_Type.Map
   2721 		add	eax,edi
   2722 		mov	[MapPtr],eax
   2723 
   2724 //nomap:
   2725 		; Record hard pointer to icon data.
   2726 		mov	eax,edi
   2727 		add	eax,[edi]IControl_Type.Icons
   2728 		mov	[StampPtr],eax
   2729 
   2730 		; Record the transparent table.
   2731 		mov	eax,edi
   2732 		add	eax,[edi]IControl_Type.TransFlag
   2733 		mov	[IsTrans],eax
   2734 
   2735 fini:
   2736 		popad										// ST - 12/20/2018 10:30AM
   2737 
   2738 	}
   2739 }
   2740 
   2741 
   2742 /*
   2743 ;***********************************************************
   2744 
   2745 ;***********************************************************
   2746 ; DRAW_STAMP
   2747 ;
   2748 ; VOID cdecl Buffer_Draw_Stamp(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap);
   2749 ;
   2750 ; This routine renders the icon at the given coordinate.
   2751 ;
   2752 ; The remap table is a 256 byte simple pixel translation table to use when
   2753 ; drawing the icon.  Transparency check is performed AFTER the remap so it is possible to
   2754 ; remap valid colors to be invisible (for special effect reasons).
   2755 ; This routine is fastest when no remap table is passed in.
   2756 ;*
   2757 */
   2758 
   2759 void __cdecl Buffer_Draw_Stamp(void const *this_object, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap)
   2760 {
   2761 	unsigned int	modulo = 0;
   2762 	unsigned int	iwidth = 0;
   2763 	unsigned char	doremap = 0;
   2764 
   2765 
   2766 /*
   2767 		PROC	Buffer_Draw_Stamp C near
   2768 
   2769 		ARG	this_object:DWORD		; this is a member function
   2770 		ARG	icondata:DWORD		; Pointer to icondata.
   2771 		ARG	icon:DWORD		; Icon number to draw.
   2772 		ARG	x_pixel:DWORD		; X coordinate of icon.
   2773 		ARG	y_pixel:DWORD		; Y coordinate of icon.
   2774 		ARG	remap:DWORD 		; Remap table.
   2775 
   2776 		LOCAL	modulo:DWORD		; Modulo to get to next row.
   2777 		LOCAL	iwidth:DWORD		; Icon width (here for speedy access).
   2778 		LOCAL	doremap:BYTE		; Should remapping occur?
   2779 */
   2780 		
   2781 	__asm {
   2782 
   2783 			pushad
   2784 			cmp	[icondata],0
   2785 			je	proc_out
   2786 
   2787 			; Initialize the stamp data if necessary.
   2788 			mov	eax,[icondata]
   2789 			cmp	[LastIconset],eax
   2790 			je		short noreset
   2791 			push	eax
   2792 			call	Init_Stamps
   2793 			pop	eax			             // Clean up stack. ST - 12/20/2018 10:42AM
   2794 noreset:
   2795 
   2796 			; Determine if the icon number requested is actually in the set.
   2797 			; Perform the logical icon to actual icon number remap if necessary.
   2798 			mov	ebx,[icon]
   2799 			cmp	[MapPtr],0
   2800 			je	short notmap
   2801 			mov	edi,[MapPtr]
   2802 			mov	bl,[edi+ebx]
   2803 notmap:
   2804 			cmp	ebx,[IconCount]
   2805 			jae	proc_out
   2806 			mov	[icon],ebx		; Updated icon number.
   2807 
   2808 			; If the remap table pointer passed in is NULL, then flag this condition
   2809 			; so that the faster (non-remapping) icon draw loop will be used.
   2810 			cmp	[remap],0
   2811 			setne	[doremap]
   2812 
   2813 			; Get pointer to position to render icon. EDI = ptr to destination page.
   2814 			mov	ebx,[this_object]
   2815 			mov	edi,[ebx]GraphicViewPortClass.Offset
   2816 			mov	eax,[ebx]GraphicViewPortClass.Width
   2817 			add	eax,[ebx]GraphicViewPortClass.XAdd
   2818 			add	eax,[ebx]GraphicViewPortClass.Pitch
   2819 			push	eax			; save viewport full width for lower
   2820 			mul	[y_pixel]
   2821 			add	edi,eax
   2822 			add	edi,[x_pixel]
   2823 
   2824 			; Determine row modulo for advancing to next line.
   2825 			pop	eax			; retrieve viewport width
   2826 			sub	eax,[IconWidth]
   2827 			mov	[modulo],eax
   2828 
   2829 			; Setup some working variables.
   2830 			mov	ecx,[IconHeight]	; Row counter.
   2831 			mov	eax,[IconWidth]
   2832 			mov	[iwidth],eax		; Stack copy of byte width for easy BP access.
   2833 
   2834 			; Fetch pointer to start of icon's data.  ESI = ptr to icon data.
   2835 			mov	eax,[icon]
   2836 			mul	[IconSize]
   2837 			mov	esi,[StampPtr]
   2838 			add	esi,eax
   2839 
   2840 			; Determine whether simple icon draw is sufficient or whether the
   2841 			; extra remapping icon draw is needed.
   2842 			cmp	[BYTE PTR doremap],0
   2843 			je	short istranscheck
   2844 
   2845 			;************************************************************
   2846 			; Complex icon draw -- extended remap.
   2847 			; EBX = Palette pointer (ready for XLAT instruction).
   2848 			; EDI = Pointer to icon destination in page.
   2849 			; ESI = Pointer to icon data.
   2850 			; ECX = Number of pixel rows.
   2851 		;;;	mov	edx,[remap]
   2852 		 mov ebx,[remap]
   2853 			xor	eax,eax
   2854 xrowloop:
   2855 			push	ecx
   2856 			mov	ecx,[iwidth]
   2857 
   2858 xcolumnloop:
   2859 			lodsb
   2860 		;;;	mov	ebx,edx
   2861 		;;;	add	ebx,eax
   2862 		;;;	mov	al,[ebx]		; New real color to draw.
   2863 		 xlatb
   2864 			or	al,al
   2865 			jz	short xskip1		; Transparency skip check.
   2866 			mov	[edi],al
   2867 xskip1:
   2868 			inc	edi
   2869 			loop	xcolumnloop
   2870 
   2871 			pop	ecx
   2872 			add	edi,[modulo]
   2873 			loop	xrowloop
   2874 			jmp	short proc_out
   2875 
   2876 
   2877 			;************************************************************
   2878 			; Check to see if transparent or generic draw is necessary.
   2879 istranscheck:
   2880 			mov	ebx,[IsTrans]
   2881 			add	ebx,[icon]
   2882 			cmp	[BYTE PTR ebx],0
   2883 			jne	short rowloop
   2884 
   2885 			;************************************************************
   2886 			; Fast non-transparent icon draw routine.
   2887 			; ES:DI = Pointer to icon destination in page.
   2888 			; DS:SI = Pointer to icon data.
   2889 			; CX = Number of pixel rows.
   2890 			mov	ebx,ecx
   2891 			shr	ebx,2
   2892 			mov	edx,[modulo]
   2893 			mov	eax,[iwidth]
   2894 			shr	eax,2
   2895 loop1:
   2896 			mov	ecx,eax
   2897 			rep movsd
   2898 			add	edi,edx
   2899 
   2900 			mov	ecx,eax
   2901 			rep movsd
   2902 			add	edi,edx
   2903 
   2904 			mov	ecx,eax
   2905 			rep movsd
   2906 			add	edi,edx
   2907 
   2908 			mov	ecx,eax
   2909 			rep movsd
   2910 			add	edi,edx
   2911 
   2912 			dec	ebx
   2913 			jnz	loop1
   2914 			jmp	short proc_out
   2915 
   2916 			;************************************************************
   2917 			; Transparent icon draw routine -- no extended remap.
   2918 			; ES:DI = Pointer to icon destination in page.
   2919 			; DS:SI = Pointer to icon data.
   2920 			; CX = Number of pixel rows.
   2921 rowloop:
   2922 			push	ecx
   2923 			mov	ecx,[iwidth]
   2924 
   2925 columnloop:
   2926 			lodsb
   2927 			or	al,al
   2928 			jz	short skip1		; Transparency check.
   2929 			mov	[edi],al
   2930 skip1:
   2931 			inc	edi
   2932 			loop	columnloop
   2933 
   2934 			pop	ecx
   2935 			add	edi,[modulo]
   2936 			loop	rowloop
   2937 
   2938 			; Cleanup and exit icon drawing routine.
   2939 proc_out:
   2940 			popad
   2941 			//ret
   2942 	}
   2943 }
   2944 
   2945 
   2946 
   2947 
   2948 /*
   2949 ;***********************************************************
   2950 ; DRAW_STAMP_CLIP
   2951 ;
   2952 ; VOID cdecl MCGA_Draw_Stamp_Clip(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap, LONG min_x, LONG min_y, LONG max_x, LONG max_y);
   2953 ;
   2954 ; This routine renders the icon at the given coordinate.
   2955 ;
   2956 ; The remap table is a 256 byte simple pixel translation table to use when
   2957 ; drawing the icon.  Transparency check is performed AFTER the remap so it is possible to
   2958 ; remap valid colors to be invisible (for special effect reasons).
   2959 ; This routine is fastest when no remap table is passed in.
   2960 ;*
   2961 */	
   2962 void __cdecl Buffer_Draw_Stamp_Clip(void const *this_object, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int min_x, int min_y, int max_x, int max_y)
   2963 {
   2964 	
   2965 	
   2966 	unsigned int	modulo = 0;
   2967 	unsigned int	iwidth = 0;
   2968 	unsigned int	skip = 0;
   2969 	unsigned char	doremap = 0;
   2970 	
   2971 		
   2972 /*		
   2973 	ARG	this_object:DWORD	; this is a member function
   2974 	ARG	icondata:DWORD		; Pointer to icondata.
   2975 	ARG	icon:DWORD		; Icon number to draw.
   2976 	ARG	x_pixel:DWORD		; X coordinate of icon.
   2977 	ARG	y_pixel:DWORD		; Y coordinate of icon.
   2978 	ARG	remap:DWORD 		; Remap table.
   2979 	ARG	min_x:DWORD		; Clipping rectangle boundary
   2980 	ARG	min_y:DWORD		; Clipping rectangle boundary
   2981 	ARG	max_x:DWORD		; Clipping rectangle boundary
   2982 	ARG	max_y:DWORD		; Clipping rectangle boundary
   2983 
   2984 	LOCAL	modulo:DWORD		; Modulo to get to next row.
   2985 	LOCAL	iwidth:DWORD		; Icon width (here for speedy access).
   2986 	LOCAL	skip:DWORD		; amount to skip per row of icon data
   2987 	LOCAL	doremap:BYTE		; Should remapping occur?
   2988 */
   2989 	__asm {
   2990 			pushad
   2991 			cmp	[icondata],0
   2992 			je	proc_out
   2993 
   2994 			; Initialize the stamp data if necessary.
   2995 			mov	eax,[icondata]
   2996 			cmp	[LastIconset],eax
   2997 			je		short noreset2
   2998 			push	eax
   2999 			call	Init_Stamps
   3000 			pop	eax			             // Clean up stack. ST - 12/20/2018 10:42AM
   3001 noreset2:
   3002 
   3003 			; Determine if the icon number requested is actually in the set.
   3004 			; Perform the logical icon to actual icon number remap if necessary.
   3005 			mov	ebx,[icon]
   3006 			cmp	[MapPtr],0
   3007 			je	short notmap2
   3008 			mov	edi,[MapPtr]
   3009 			mov	bl,[edi+ebx]
   3010 notmap2:
   3011 			cmp	ebx,[IconCount]
   3012 			jae	proc_out
   3013 			mov	[icon],ebx		; Updated icon number.
   3014 
   3015 			; Setup some working variables.
   3016 			mov	ecx,[IconHeight]	; Row counter.
   3017 			mov	eax,[IconWidth]
   3018 			mov	[iwidth],eax		; Stack copy of byte width for easy BP access.
   3019 
   3020 			; Fetch pointer to start of icon's data.  ESI = ptr to icon data.
   3021 			mov	eax,[icon]
   3022 			mul	[IconSize]
   3023 			mov	esi,[StampPtr]
   3024 			add	esi,eax
   3025 
   3026 			; Update the clipping window coordinates to be valid maxes instead of width & height
   3027 			; , and change the coordinates to be window-relative
   3028 			mov	ebx,[min_x]
   3029 			add	[max_x],ebx
   3030 			add	[x_pixel],ebx		; make it window-relative
   3031 			mov	ebx,[min_y]
   3032 			add	[max_y],ebx
   3033 			add	[y_pixel],ebx		; make it window-relative
   3034 
   3035 			; See if the icon is within the clipping window
   3036 			; First, verify that the icon position is less than the maximums
   3037 			mov	ebx,[x_pixel]
   3038 			cmp	ebx,[max_x]
   3039 			jge	proc_out
   3040 			mov	ebx,[y_pixel]
   3041 			cmp	ebx,[max_y]
   3042 			jge	proc_out
   3043 			; Now verify that the icon position is >= the minimums
   3044 			add	ebx,[IconHeight]
   3045 			cmp	ebx,[min_y]
   3046 			jle	proc_out
   3047 			mov	ebx,[x_pixel]
   3048 			add	ebx,[IconWidth]
   3049 			cmp	ebx,[min_x]
   3050 			jle	proc_out
   3051 
   3052 			; Now, clip the x, y, width, and height variables to be within the
   3053 			; clipping rectangle
   3054 			mov	ebx,[x_pixel]
   3055 			cmp	ebx,[min_x]
   3056 			jge	nominxclip
   3057 			; x < minx, so must clip
   3058 			mov	ebx,[min_x]
   3059 			sub	ebx,[x_pixel]
   3060 			add	esi,ebx		; source ptr += (minx - x)
   3061 			sub	[iwidth],ebx	; icon width -= (minx - x)
   3062 			mov	ebx,[min_x]
   3063 			mov	[x_pixel],ebx
   3064 
   3065 nominxclip:
   3066 			mov	eax,[IconWidth]
   3067 			sub	eax,[iwidth]
   3068 			mov	[skip],eax
   3069 
   3070 			; Check for x+width > max_x
   3071 			mov	eax,[x_pixel]
   3072 			add	eax,[iwidth]
   3073 			cmp	eax,[max_x]
   3074 			jle	nomaxxclip
   3075 			; x+width is greater than max_x, so must clip width down
   3076 			mov	eax,[iwidth]	; eax = old width
   3077 			mov	ebx,[max_x]
   3078 			sub	ebx,[x_pixel]
   3079 			mov	[iwidth],ebx	; iwidth = max_x - xpixel
   3080 			sub	eax,ebx
   3081 			add	[skip],eax	; skip += (old width - iwidth)
   3082 nomaxxclip:
   3083 			; check if y < miny
   3084 			mov	eax,[min_y]
   3085 			cmp	eax,[y_pixel]	; if(miny <= y_pixel), no clip needed
   3086 			jle	nominyclip
   3087 			sub	eax,[y_pixel]
   3088 			sub	ecx,eax		; height -= (miny - y)
   3089 			mul	[IconWidth]
   3090 			add	esi,eax		; icon source ptr += (width * (miny - y))
   3091 			mov	eax,[min_y]
   3092 			mov	[y_pixel],eax	; y = miny
   3093 nominyclip:
   3094 			; check if (y+height) > max y
   3095 			mov	eax,[y_pixel]
   3096 			add	eax,ecx
   3097 			cmp	eax,[max_y]	; if (y + height <= max_y), no clip needed
   3098 			jle	nomaxyclip
   3099 			mov	ecx,[max_y]	; height = max_y - y_pixel
   3100 			sub	ecx,[y_pixel]
   3101 nomaxyclip:
   3102 
   3103 			; If the remap table pointer passed in is NULL, then flag this condition
   3104 			; so that the faster (non-remapping) icon draw loop will be used.
   3105 			cmp	[remap],0
   3106 			setne	[doremap]
   3107 
   3108 			; Get pointer to position to render icon. EDI = ptr to destination page.
   3109 			mov	ebx,[this_object]
   3110 			mov	edi,[ebx]GraphicViewPortClass.Offset
   3111 			mov	eax,[ebx]GraphicViewPortClass.Width
   3112 			add	eax,[ebx]GraphicViewPortClass.XAdd
   3113 			add	eax,[ebx]GraphicViewPortClass.Pitch
   3114 			push	eax			; save viewport full width for lower
   3115 			mul	[y_pixel]
   3116 			add	edi,eax
   3117 			add	edi,[x_pixel]
   3118 
   3119 			; Determine row modulo for advancing to next line.
   3120 			pop	eax			; retrieve viewport width
   3121 			sub	eax,[iwidth]
   3122 			mov	[modulo],eax
   3123 
   3124 			; Determine whether simple icon draw is sufficient or whether the
   3125 			; extra remapping icon draw is needed.
   3126 			cmp	[BYTE PTR doremap],0
   3127 			je	short istranscheck2
   3128 
   3129 			;************************************************************
   3130 			; Complex icon draw -- extended remap.
   3131 			; EBX = Palette pointer (ready for XLAT instruction).
   3132 			; EDI = Pointer to icon destination in page.
   3133 			; ESI = Pointer to icon data.
   3134 			; ECX = Number of pixel rows.
   3135 			mov	ebx,[remap]
   3136 			xor	eax,eax
   3137 xrowloopc:
   3138 			push	ecx
   3139 			mov	ecx,[iwidth]
   3140 
   3141 xcolumnloopc:
   3142 			lodsb
   3143 			xlatb
   3144 			or	al,al
   3145 			jz	short xskip1c		; Transparency skip check.
   3146 			mov	[edi],al
   3147 xskip1c:
   3148 			inc	edi
   3149 			loop	xcolumnloopc
   3150 
   3151 			pop	ecx
   3152 			add	edi,[modulo]
   3153  		add esi,[skip]
   3154 			loop	xrowloopc
   3155 			jmp	short proc_out
   3156 
   3157 
   3158 			;************************************************************
   3159 			; Check to see if transparent or generic draw is necessary.
   3160 istranscheck2:
   3161 			mov	ebx,[IsTrans]
   3162 			add	ebx,[icon]
   3163 			cmp	[BYTE PTR ebx],0
   3164 			jne	short rowloopc
   3165 
   3166 			;************************************************************
   3167 			; Fast non-transparent icon draw routine.
   3168 			; ES:DI = Pointer to icon destination in page.
   3169 			; DS:SI = Pointer to icon data.
   3170 			; CX = Number of pixel rows.
   3171 			mov	ebx,ecx
   3172 			mov	edx,[modulo]
   3173 			mov	eax,[iwidth]
   3174 
   3175 			;
   3176 			; Optimise copy by dword aligning the destination
   3177 			;
   3178 loop1c:
   3179 			push	eax
   3180  		//rept 3					// No rept in inline asm. ST - 12/20/2018 10:43AM
   3181 			test	edi,3
   3182 			jz	aligned
   3183 			movsb
   3184 			dec	eax
   3185 			jz	finishedit
   3186 
   3187 			test	edi,3
   3188 			jz	aligned
   3189 			movsb
   3190 			dec	eax
   3191 			jz	finishedit
   3192 
   3193 			test	edi,3
   3194 			jz	aligned
   3195 			movsb
   3196 			dec	eax
   3197 			jz	finishedit
   3198 
   3199  		//endm
   3200 aligned:
   3201 			mov	ecx,eax
   3202 			shr	ecx,2
   3203 			rep	movsd
   3204 			mov	ecx,eax
   3205 			and	ecx,3
   3206 			rep	movsb
   3207 
   3208 finishedit:
   3209 			add	edi,edx
   3210 			add	esi,[skip]
   3211 			pop	eax
   3212 
   3213 			dec	ebx
   3214 			jnz	loop1c
   3215 			jmp	short proc_out
   3216 
   3217 			;************************************************************
   3218 			; Transparent icon draw routine -- no extended remap.
   3219 			; ES:DI = Pointer to icon destination in page.
   3220 			; DS:SI = Pointer to icon data.
   3221 			; CX = Number of pixel rows.
   3222 rowloopc:
   3223 			push	ecx
   3224 			mov	ecx,[iwidth]
   3225 
   3226 columnloopc:
   3227 			lodsb
   3228 			or	al,al
   3229 			jz	short skip1c		; Transparency check.
   3230 			mov	[edi],al
   3231 skip1c:
   3232 			inc	edi
   3233 			loop	columnloopc
   3234 
   3235 			pop	ecx
   3236 			add	edi,[modulo]
   3237  		add esi,[skip]
   3238 			loop	rowloopc
   3239 
   3240 			; Cleanup and exit icon drawing routine.
   3241 proc_out:
   3242 			popad
   3243 			//ret
   3244 	}
   3245 }
   3246 
   3247 
   3248 
   3249 
   3250 
   3251 
   3252 
   3253 
   3254 
   3255 
   3256 
   3257 
   3258 
   3259 
   3260 
   3261 	 VOID __cdecl Buffer_Draw_Line(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);
   3262 	 VOID __cdecl Buffer_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);
   3263 	 VOID __cdecl Buffer_Remap(void * thisptr, int sx, int sy, int width, int height, void *remap);
   3264 	 VOID __cdecl Buffer_Fill_Quad(void * thisptr, VOID *span_buff, int x0, int y0, int x1, int y1,
   3265 							 	int x2, int y2, int x3, int y3, int color);
   3266 	 void __cdecl Buffer_Draw_Stamp(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);
   3267 	 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);
   3268 	 void * __cdecl Get_Font_Palette_Ptr ( void );
   3269 
   3270 
   3271 /*
   3272 ;***************************************************************************
   3273 ;**   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   **
   3274 ;***************************************************************************
   3275 ;*                                                                         *
   3276 ;*                 Project Name : Westwood 32 bit Library                  *
   3277 ;*                                                                         *
   3278 ;*                    File Name : REMAP.ASM                                *
   3279 ;*                                                                         *
   3280 ;*                   Programmer : Phil W. Gorrow                           *
   3281 ;*                                                                         *
   3282 ;*                   Start Date : July 1, 1994                             *
   3283 ;*                                                                         *
   3284 ;*                  Last Update : July 1, 1994   [PWG]                     *
   3285 ;*                                                                         *
   3286 ;*-------------------------------------------------------------------------*
   3287 ;* Functions:                                                              *
   3288 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
   3289 */
   3290 
   3291 
   3292 VOID __cdecl Buffer_Remap(void * this_object, int sx, int sy, int width, int height, void *remap)
   3293 {
   3294 /*
   3295 	PROC	Buffer_Remap C NEAR
   3296 	USES	eax,ebx,ecx,edx,esi,edi
   3297 
   3298 	;*===================================================================
   3299 	;* Define the arguements that our function takes.
   3300 	;*===================================================================
   3301 	ARG	this_object:DWORD
   3302 	ARG	x0_pixel:DWORD
   3303 	ARG	y0_pixel:DWORD
   3304 	ARG	region_width:DWORD
   3305 	ARG	region_height:DWORD
   3306 	ARG	remap	:DWORD
   3307 
   3308 	;*===================================================================
   3309 	; Define some locals so that we can handle things quickly
   3310 	;*===================================================================
   3311 	local	x1_pixel  : DWORD
   3312 	local	y1_pixel  : DWORD
   3313 	local	win_width : dword
   3314 	local	counter_x : dword
   3315 */
   3316 
   3317 	unsigned int x0_pixel = (unsigned int) sx;
   3318 	unsigned int y0_pixel = (unsigned int) sy;
   3319 	unsigned int region_width = (unsigned int) width;
   3320 	unsigned int region_height = (unsigned int) height;
   3321 
   3322 	unsigned int x1_pixel = 0;
   3323 	unsigned int y1_pixel = 0;
   3324 	unsigned int win_width = 0;
   3325 	unsigned int counter_x = 0;
   3326 
   3327 	__asm {
   3328 		
   3329 		cmp	[ remap ] , 0
   3330 		jz		real_out
   3331 
   3332 	; Clip Source Rectangle against source Window boundaries.
   3333 		mov  	esi , [ this_object ]	    ; get ptr to src
   3334 		xor 	ecx , ecx
   3335 		xor 	edx , edx
   3336 		mov	edi , [esi]GraphicViewPortClass.Width  ; get width into register
   3337 		mov	ebx , [ x0_pixel ]
   3338 		mov	eax , [ x0_pixel ]
   3339 		add	ebx , [ region_width ]
   3340 		shld	ecx , eax , 1
   3341 		mov	[ x1_pixel ] , ebx
   3342 		inc	edi
   3343 		shld	edx , ebx , 1
   3344 		sub	eax , edi
   3345 		sub	ebx , edi
   3346 		shld	ecx , eax , 1
   3347 		shld	edx , ebx , 1
   3348 
   3349 		mov	edi,[esi]GraphicViewPortClass.Height ; get height into register
   3350 		mov	ebx , [ y0_pixel ]
   3351 		mov	eax , [ y0_pixel ]
   3352 		add	ebx , [ region_height ]
   3353 		shld	ecx , eax , 1
   3354 		mov	[ y1_pixel ] , ebx
   3355 		inc	edi
   3356 		shld	edx , ebx , 1
   3357 		sub	eax , edi
   3358 		sub	ebx , edi
   3359 		shld	ecx , eax , 1
   3360 		shld	edx , ebx , 1
   3361 
   3362 		xor	cl , 5
   3363 		xor	dl , 5
   3364 		mov	al , cl
   3365 		test	dl , cl
   3366 		jnz	real_out
   3367 		or	al , dl
   3368 		jz		do_remap
   3369 
   3370 		test	cl , 1000b
   3371 		jz		scr_left_ok
   3372 		mov	[ x0_pixel ] , 0
   3373 
   3374 scr_left_ok:
   3375 		test	cl , 0010b
   3376 		jz		scr_bottom_ok
   3377 		mov	[ y0_pixel ] , 0
   3378 
   3379 scr_bottom_ok:
   3380 		test	dl , 0100b
   3381 		jz		scr_right_ok
   3382 		mov	eax , [esi]GraphicViewPortClass.Width  ; get width into register
   3383 		mov	[ x1_pixel ] , eax
   3384 scr_right_ok:
   3385 		test	dl , 0001b
   3386 		jz		do_remap
   3387 		mov	eax , [esi]GraphicViewPortClass.Height  ; get width into register
   3388 		mov	[ y1_pixel ] , eax
   3389 
   3390 
   3391 do_remap:
   3392       	 cld
   3393       	 mov	edi , [esi]GraphicViewPortClass.Offset
   3394       	 mov	eax , [esi]GraphicViewPortClass.XAdd
   3395       	 mov	ebx , [ x1_pixel ]
   3396       	 add	eax , [esi]GraphicViewPortClass.Width
   3397       	 add	eax , [esi]GraphicViewPortClass.Pitch
   3398       	 mov	esi , eax
   3399       	 mul	[ y0_pixel ]
   3400       	 add	edi , [ x0_pixel ]
   3401       	 sub	ebx , [ x0_pixel ]
   3402       	 jle	real_out
   3403       	 add	edi , eax
   3404       	 sub	esi , ebx
   3405 
   3406       	 mov	ecx , [ y1_pixel ]
   3407       	 sub	ecx , [ y0_pixel ]
   3408       	 jle	real_out
   3409       	 mov	eax , [ remap ]
   3410       	 mov	[ counter_x ] , ebx
   3411       	 xor	edx , edx
   3412 
   3413 outer_loop:
   3414       	 mov	ebx , [ counter_x ]
   3415 inner_loop:
   3416       	 mov	dl , [ edi ]
   3417       	 mov	dl , [ eax + edx ]
   3418       	 mov	[ edi ] , dl
   3419       	 inc	edi
   3420       	 dec	ebx
   3421       	 jnz	inner_loop
   3422       	 add	edi , esi
   3423       	 dec	ecx
   3424       	 jnz	outer_loop
   3425 
   3426 
   3427 
   3428 
   3429 real_out:
   3430 //		ret
   3431 	}
   3432 }
   3433 
   3434 
   3435 
   3436 
   3437 
   3438 
   3439 
   3440 
   3441 
   3442 
   3443 
   3444 
   3445 
   3446 
   3447 
   3448 /*
   3449 ; **************************************************************************
   3450 ; **   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   *
   3451 ; **************************************************************************
   3452 ; *                                                                        *
   3453 ; *                 Project Name : WSA Support routines			   *
   3454 ; *                                                                        *
   3455 ; *                    File Name : XORDELTA.ASM                            *
   3456 ; *                                                                        *
   3457 ; *                   Programmer : Scott K. Bowen			   *
   3458 ; *                                                                        *
   3459 ; *                  Last Update :May 23, 1994   [SKB]                     *
   3460 ; *                                                                        *
   3461 ; *------------------------------------------------------------------------*
   3462 ; * Functions:                                                             *
   3463 ;*   Apply_XOR_Delta -- Apply XOR delta data to a buffer.                  *
   3464 ;*   Apply_XOR_Delta_To_Page_Or_Viewport -- Calls the copy or the XOR funti*
   3465 ;*   Copy_Delta_buffer -- Copies XOR Delta Data to a section of a page.    *
   3466 ;*   XOR_Delta_Buffer -- Xor's the data in a XOR Delta format to a page.   *
   3467 ; * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
   3468 
   3469 IDEAL
   3470 P386
   3471 MODEL USE32 FLAT
   3472 */
   3473 
   3474 
   3475 /*
   3476 LOCALS ??
   3477 
   3478 ; These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter.  If
   3479 ; These change, make sure and change their values in wsa.cpp.
   3480 DO_XOR		equ	0
   3481 DO_COPY		equ	1
   3482 TO_VIEWPORT	equ	0
   3483 TO_PAGE		equ	2
   3484 
   3485 ;
   3486 ; Routines defined in this module
   3487 ;
   3488 ;
   3489 ; UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr);
   3490 ; PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD copy)
   3491 ;
   3492 ;	PROC	C XOR_Delta_Buffer
   3493 ;	PROC	C Copy_Delta_Buffer
   3494 ;
   3495 
   3496 GLOBAL 	C Apply_XOR_Delta:NEAR
   3497 GLOBAL 	C Apply_XOR_Delta_To_Page_Or_Viewport:NEAR
   3498 */
   3499 
   3500 #define DO_XOR			0
   3501 #define DO_COPY		1
   3502 #define TO_VIEWPORT	0
   3503 #define TO_PAGE		2
   3504 
   3505 void __cdecl XOR_Delta_Buffer(int nextrow);
   3506 void __cdecl Copy_Delta_Buffer(int nextrow);
   3507 
   3508 
   3509 /*
   3510 ;***************************************************************************
   3511 ;* APPLY_XOR_DELTA -- Apply XOR delta data to a linear buffer.             *
   3512 ;*   AN example of this in C is at the botton of the file commented out.   *
   3513 ;*                                                                         *
   3514 ;* INPUT:  BYTE *target - destination buffer.                              *
   3515 ;*         BYTE *delta - xor data to be delta uncompress.                  *
   3516 ;*                                                                         *
   3517 ;* OUTPUT:                                                                 *
   3518 ;*                                                                         *
   3519 ;* WARNINGS:                                                               *
   3520 ;*                                                                         *
   3521 ;* HISTORY:                                                                *
   3522 ;*   05/23/1994 SKB : Created.                                             *
   3523 ;*=========================================================================*
   3524 */
   3525 unsigned int __cdecl Apply_XOR_Delta(char *target, char *delta)
   3526 {
   3527 /* 
   3528 PROC	Apply_XOR_Delta C near
   3529 	USES 	ebx,ecx,edx,edi,esi
   3530 	ARG	target:DWORD 		; pointers.
   3531 	ARG	delta:DWORD		; pointers.
   3532 */
   3533 	
   3534 	__asm {
   3535 		
   3536 			; Optimized for 486/pentium by rearanging instructions.
   3537 			mov	edi,[target]		; get our pointers into offset registers.
   3538 			mov	esi,[delta]
   3539 
   3540 			cld				; make sure we go forward
   3541 			xor	ecx,ecx			; use cx for loop
   3542 
   3543 		top_loop:
   3544 			xor	eax,eax			; clear out eax.
   3545 			mov	al,[esi]		; get delta source byte
   3546 			inc	esi
   3547 
   3548 			test	al,al			; check for a SHORTDUMP ; check al incase of sign value.
   3549 			je	short_run
   3550 			js	check_others
   3551 
   3552 		;
   3553 		; SHORTDUMP
   3554 		;
   3555 			mov	ecx,eax			; stick count in cx
   3556 
   3557 		dump_loop:
   3558 			mov	al,[esi]		;get delta XOR byte
   3559 			xor	[edi],al		; xor that byte on the dest
   3560 			inc	esi
   3561 			inc	edi
   3562 			dec	ecx
   3563 			jnz	dump_loop
   3564 			jmp	top_loop
   3565 
   3566 		;
   3567 		; SHORTRUN
   3568 		;
   3569 
   3570 		short_run:
   3571 			mov	cl,[esi]		; get count
   3572 			inc	esi			; inc delta source
   3573 
   3574 		do_run:
   3575 			mov	al,[esi]		; get XOR byte
   3576 			inc	esi
   3577 
   3578 		run_loop:
   3579 			xor	[edi],al		; xor that byte.
   3580 
   3581 			inc	edi			; go to next dest pixel
   3582 			dec	ecx			; one less to go.
   3583 			jnz	run_loop
   3584 			jmp	top_loop
   3585 
   3586 		;
   3587 		; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP
   3588 		;
   3589 
   3590 		check_others:
   3591 			sub	eax,080h		; opcode -= 0x80
   3592 			jnz	do_skip		; if zero then get next word, otherwise use remainder.
   3593 
   3594 			mov	ax,[esi]
   3595 			lea	esi,[esi+2]		; get word code in ax
   3596 			test	ax,ax			; set flags. (not 32bit register so neg flag works)
   3597 			jle	not_long_skip
   3598 
   3599 		;
   3600 		; SHORTSKIP AND LONGSKIP
   3601 		;
   3602 		do_skip:
   3603 			add	edi,eax			; do the skip.
   3604 			jmp	top_loop
   3605 
   3606 
   3607 		not_long_skip:
   3608 			jz	stop			; long count of zero means stop
   3609 			sub	eax,08000h     		; opcode -= 0x8000
   3610 			test	eax,04000h		; is it a LONGRUN (code & 0x4000)?
   3611 			je	long_dump
   3612 
   3613 		;
   3614 		; LONGRUN
   3615 		;
   3616 			sub	eax,04000h		; opcode -= 0x4000
   3617 			mov	ecx,eax			; use cx as loop count
   3618 			jmp	do_run		; jump to run code.
   3619 
   3620 
   3621 		;
   3622 		; LONGDUMP
   3623 		;
   3624 
   3625 		long_dump:
   3626 			mov	ecx,eax			; use cx as loop count
   3627 			jmp	dump_loop		; go to the dump loop.
   3628 
   3629 		stop:
   3630 	}
   3631 }
   3632 
   3633 
   3634 /*
   3635 ;----------------------------------------------------------------------------
   3636 
   3637 ;***************************************************************************
   3638 ;* APPLY_XOR_DELTA_To_Page_Or_Viewport -- Calls the copy or the XOR funtion.           *
   3639 ;*                                                                         *
   3640 ;*									   *
   3641 ;* 	This funtion is call to either xor or copy XOR_Delta data onto a   *
   3642 ;*	page instead of a buffer.  The routine will set up the registers   *
   3643 ;*	need for the actual routines that will perform the copy or xor.	   *
   3644 ;*									   *
   3645 ;*	The registers are setup as follows :				   *
   3646 ;*		es:edi - destination segment:offset onto page.		   *
   3647 ;*		ds:esi - source buffer segment:offset of delta data.	   *
   3648 ;*		dx,cx,ax - are all zeroed out before entry.		   *
   3649 ;*                                                                         *
   3650 ;* INPUT:                                                                  *
   3651 ;*                                                                         *
   3652 ;* OUTPUT:                                                                 *
   3653 ;*                                                                         *
   3654 ;* WARNINGS:                                                               *
   3655 ;*                                                                         *
   3656 ;* HISTORY:                                                                *
   3657 ;*   03/09/1992  SB : Created.                                             *
   3658 ;*=========================================================================*
   3659 */
   3660 
   3661 void __cdecl Apply_XOR_Delta_To_Page_Or_Viewport(void *target, void *delta, int width, int nextrow, int copy)
   3662 {
   3663 	/*
   3664 	USES 	ebx,ecx,edx,edi,esi
   3665 	ARG	target:DWORD		; pointer to the destination buffer.
   3666 	ARG	delta:DWORD		; pointer to the delta buffer.
   3667 	ARG	width:DWORD		; width of animation.
   3668 	ARG	nextrow:DWORD		; Page/Buffer width - anim width.
   3669 	ARG	copy:DWORD		; should it be copied or xor'd?
   3670 	*/
   3671 	
   3672 	__asm {
   3673 
   3674 		mov	edi,[target]		; Get the target pointer.
   3675 		mov	esi,[delta]		; Get the destination pointer.
   3676 
   3677 		xor	eax,eax			; clear eax, later put them into ecx and edx.
   3678 
   3679 		cld				; make sure we go forward
   3680 
   3681 		mov	ebx,[nextrow]		; get the amount to add to get to next row from end.  push it later...
   3682 
   3683 		mov	ecx,eax			; use cx for loop
   3684 		mov	edx,eax			; use dx to count the relative column.
   3685 
   3686 		push	ebx			; push nextrow onto the stack for Copy/XOR_Delta_Buffer.
   3687 		mov	ebx,[width]		; bx will hold the max column for speed compares
   3688 
   3689 	; At this point, all the registers have been set up.  Now call the correct function
   3690 	; to either copy or xor the data.
   3691 
   3692 		cmp	[copy],DO_XOR		; Do we want to copy or XOR
   3693 		je	xorfunct		; Jump to XOR if not copy
   3694 		call	Copy_Delta_Buffer	; Call the function to copy the delta buffer.
   3695 		jmp	didcopy		; jump past XOR
   3696 	xorfunct:
   3697 		call	XOR_Delta_Buffer	; Call funtion to XOR the deltat buffer.
   3698 	didcopy:
   3699 		pop	ebx			; remove the push done to pass a value.
   3700 	}
   3701 }
   3702 
   3703 
   3704 /*
   3705 ;----------------------------------------------------------------------------
   3706 
   3707 
   3708 ;***************************************************************************
   3709 ;* XOR_DELTA_BUFFER -- Xor's the data in a XOR Delta format to a page.     *
   3710 ;*	This will only work right if the page has the previous data on it. *
   3711 ;*	This function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *
   3712 ;*      The registers must be setup as follows :                           *
   3713 ;*                                                                         *
   3714 ;* INPUT:                                                                  *
   3715 ;*	es:edi - destination segment:offset onto page.		 	   *
   3716 ;*	ds:esi - source buffer segment:offset of delta data.	 	   *
   3717 ;*	edx,ecx,eax - are all zeroed out before entry.		 	   *
   3718 ;*                                                                         *
   3719 ;* OUTPUT:                                                                 *
   3720 ;*                                                                         *
   3721 ;* WARNINGS:                                                               *
   3722 ;*                                                                         *
   3723 ;* HISTORY:                                                                *
   3724 ;*   03/09/1992  SB : Created.                                             *
   3725 ;*=========================================================================*
   3726 */
   3727 void __cdecl XOR_Delta_Buffer(int nextrow)
   3728 {
   3729 	/*		  
   3730 	ARG	nextrow:DWORD
   3731 	*/
   3732 	
   3733 	__asm {
   3734 
   3735 		top_loop:
   3736 			xor	eax,eax			; clear out eax.
   3737 			mov	al,[esi]		; get delta source byte
   3738 			inc	esi
   3739 
   3740 			test	al,al			; check for a SHORTDUMP ; check al incase of sign value.
   3741 			je	short_run
   3742 			js	check_others
   3743 
   3744 		;
   3745 		; SHORTDUMP
   3746 		;
   3747 			mov	ecx,eax			; stick count in cx
   3748 
   3749 		dump_loop:
   3750 			mov	al,[esi]		; get delta XOR byte
   3751 			xor	[edi],al		; xor that byte on the dest
   3752 			inc	esi
   3753 			inc	edx			; increment our count on current column
   3754 			inc	edi
   3755 			cmp	edx,ebx			; are we at the final column
   3756 			jne	end_col1		; if not the jmp over the code
   3757 
   3758 			sub	edi,edx			; get our column back to the beginning.
   3759 			xor	edx,edx			; zero out our column counter
   3760 			add	edi,[nextrow]		; jump to start of next row
   3761 		end_col1:
   3762 
   3763 			dec	ecx
   3764 			jnz	dump_loop
   3765 			jmp	top_loop
   3766 
   3767 		;
   3768 		; SHORTRUN
   3769 		;
   3770 
   3771 		short_run:
   3772 			mov	cl,[esi]		; get count
   3773 			inc	esi			; inc delta source
   3774 
   3775 		do_run:
   3776 			mov	al,[esi]		; get XOR byte
   3777 			inc	esi
   3778 
   3779 		run_loop:
   3780 			xor	[edi],al		; xor that byte.
   3781 
   3782 			inc	edx			; increment our count on current column
   3783 			inc	edi			; go to next dest pixel
   3784 			cmp	edx,ebx			; are we at the final column
   3785 			jne	end_col2		; if not the jmp over the code
   3786 
   3787 			sub	edi,ebx			; get our column back to the beginning.
   3788 			xor	edx,edx			; zero out our column counter
   3789 			add	edi,[nextrow]		; jump to start of next row
   3790 		end_col2:
   3791 
   3792 
   3793 			dec	ecx
   3794 			jnz	run_loop
   3795 			jmp	top_loop
   3796 
   3797 		;
   3798 		; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP
   3799 		;
   3800 
   3801 		check_others:
   3802 			sub	eax,080h		; opcode -= 0x80
   3803 			jnz	do_skip		; if zero then get next word, otherwise use remainder.
   3804 
   3805 			mov	ax,[esi]		; get word code in ax
   3806 			lea	esi,[esi+2]
   3807 			test	ax,ax			; set flags. (not 32bit register so neg flag works)
   3808 			jle	not_long_skip
   3809 
   3810 		;
   3811 		; SHORTSKIP AND LONGSKIP
   3812 		;
   3813 		do_skip:
   3814 			sub	edi,edx			; go back to beginning or row.
   3815 			add	edx,eax			; incriment our count on current row
   3816 		recheck3:
   3817 			cmp	edx,ebx			; are we past the end of the row
   3818 			jb	end_col3  		; if not the jmp over the code
   3819 
   3820 			sub	edx,ebx			; Subtract width from the col counter
   3821 			add	edi,[nextrow]  		; jump to start of next row
   3822 			jmp	recheck3		; jump up to see if we are at the right row
   3823 		end_col3:
   3824 			add	edi,edx			; get to correct position in row.
   3825 			jmp	top_loop
   3826 
   3827 
   3828 		not_long_skip:
   3829 			jz	stop			; long count of zero means stop
   3830 			sub	eax,08000h     		; opcode -= 0x8000
   3831 			test	eax,04000h		; is it a LONGRUN (code & 0x4000)?
   3832 			je	long_dump
   3833 
   3834 		;
   3835 		; LONGRUN
   3836 		;
   3837 			sub	eax,04000h		; opcode -= 0x4000
   3838 			mov	ecx,eax			; use cx as loop count
   3839 			jmp	do_run		; jump to run code.
   3840 
   3841 
   3842 		;
   3843 		; LONGDUMP
   3844 		;
   3845 
   3846 		long_dump:
   3847 			mov	ecx,eax			; use cx as loop count
   3848 			jmp	dump_loop		; go to the dump loop.
   3849 
   3850 		stop:
   3851 
   3852 	}
   3853 }
   3854 
   3855 
   3856 /*
   3857 ;----------------------------------------------------------------------------
   3858 
   3859 
   3860 ;***************************************************************************
   3861 ;* COPY_DELTA_BUFFER -- Copies XOR Delta Data to a section of a page.      *
   3862 ;*	This function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport.   *
   3863 ;*      The registers must be setup as follows :                           *
   3864 ;*                                                                         *
   3865 ;* INPUT:                                                                  *
   3866 ;*	es:edi - destination segment:offset onto page.		 	   *
   3867 ;*	ds:esi - source buffer segment:offset of delta data.	 	   *
   3868 ;*	dx,cx,ax - are all zeroed out before entry.		 	   *
   3869 ;*                                                                         *
   3870 ;* OUTPUT:                                                                 *
   3871 ;*                                                                         *
   3872 ;* WARNINGS:                                                               *
   3873 ;*                                                                         *
   3874 ;* HISTORY:                                                                *
   3875 ;*   03/09/1992  SB : Created.                                             *
   3876 ;*=========================================================================*
   3877 */
   3878 void __cdecl Copy_Delta_Buffer(int nextrow)
   3879 {
   3880 	/*		  
   3881 	ARG	nextrow:DWORD
   3882 	*/
   3883 	
   3884 	__asm {
   3885 		
   3886 		top_loop:
   3887 			xor	eax,eax			; clear out eax.
   3888 			mov	al,[esi]		; get delta source byte
   3889 			inc	esi
   3890 
   3891 			test	al,al			; check for a SHORTDUMP ; check al incase of sign value.
   3892 			je	short_run
   3893 			js	check_others
   3894 
   3895 		;
   3896 		; SHORTDUMP
   3897 		;
   3898 			mov	ecx,eax			; stick count in cx
   3899 
   3900 		dump_loop:
   3901 			mov	al,[esi]		; get delta XOR byte
   3902 
   3903 			mov	[edi],al		; store that byte on the dest
   3904 
   3905 			inc	edx			; increment our count on current column
   3906 			inc	esi
   3907 			inc	edi
   3908 			cmp	edx,ebx			; are we at the final column
   3909 			jne	end_col1		; if not the jmp over the code
   3910 
   3911 			sub	edi,edx			; get our column back to the beginning.
   3912 			xor	edx,edx			; zero out our column counter
   3913 			add	edi,[nextrow]		; jump to start of next row
   3914 		end_col1:
   3915 
   3916 			dec	ecx
   3917 			jnz	dump_loop
   3918 			jmp	top_loop
   3919 
   3920 		;
   3921 		; SHORTRUN
   3922 		;
   3923 
   3924 		short_run:
   3925 			mov	cl,[esi]		; get count
   3926 			inc	esi			; inc delta source
   3927 
   3928 		do_run:
   3929 			mov	al,[esi]		; get XOR byte
   3930 			inc	esi
   3931 
   3932 		run_loop:
   3933 			mov	[edi],al		; store the byte (instead of XOR against current color)
   3934 
   3935 			inc	edx			; increment our count on current column
   3936 			inc	edi			; go to next dest pixel
   3937 			cmp	edx,ebx			; are we at the final column
   3938 			jne	end_col2		; if not the jmp over the code
   3939 
   3940 			sub	edi,ebx			; get our column back to the beginning.
   3941 			xor	edx,edx			; zero out our column counter
   3942 			add	edi,[nextrow]		; jump to start of next row
   3943 		end_col2:
   3944 
   3945 
   3946 			dec	ecx
   3947 			jnz	run_loop
   3948 			jmp	top_loop
   3949 
   3950 		;
   3951 		; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP
   3952 		;
   3953 
   3954 		check_others:
   3955 			sub	eax,080h		; opcode -= 0x80
   3956 			jnz	do_skip		; if zero then get next word, otherwise use remainder.
   3957 
   3958 			mov	ax,[esi]		; get word code in ax
   3959 			lea	esi,[esi+2]
   3960 			test	ax,ax			; set flags. (not 32bit register so neg flag works)
   3961 			jle	not_long_skip
   3962 
   3963 		;
   3964 		; SHORTSKIP AND LONGSKIP
   3965 		;
   3966 		do_skip:
   3967 			sub	edi,edx			; go back to beginning or row.
   3968 			add	edx,eax			; incriment our count on current row
   3969 		recheck3:
   3970 			cmp	edx,ebx			; are we past the end of the row
   3971 			jb	end_col3  		; if not the jmp over the code
   3972 
   3973 			sub	edx,ebx			; Subtract width from the col counter
   3974 			add	edi,[nextrow]  		; jump to start of next row
   3975 			jmp	recheck3		; jump up to see if we are at the right row
   3976 		end_col3:
   3977 			add	edi,edx			; get to correct position in row.
   3978 			jmp	top_loop
   3979 
   3980 
   3981 		not_long_skip:
   3982 			jz	stop			; long count of zero means stop
   3983 			sub	eax,08000h     		; opcode -= 0x8000
   3984 			test	eax,04000h		; is it a LONGRUN (code & 0x4000)?
   3985 			je	long_dump
   3986 
   3987 		;
   3988 		; LONGRUN
   3989 		;
   3990 			sub	eax,04000h		; opcode -= 0x4000
   3991 			mov	ecx,eax			; use cx as loop count
   3992 			jmp	do_run		; jump to run code.
   3993 
   3994 
   3995 		;
   3996 		; LONGDUMP
   3997 		;
   3998 
   3999 		long_dump:
   4000 			mov	ecx,eax			; use cx as loop count
   4001 			jmp	dump_loop		; go to the dump loop.
   4002 
   4003 		stop:
   4004 
   4005 	}
   4006 }
   4007 /*
   4008 ;----------------------------------------------------------------------------
   4009 */
   4010 
   4011 
   4012 
   4013 
   4014 
   4015 
   4016 
   4017 
   4018 
   4019 
   4020 
   4021 
   4022 
   4023 
   4024 
   4025 
   4026 
   4027 
   4028 
   4029 
   4030 
   4031 
   4032 /*
   4033 ;***************************************************************************
   4034 ;**   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        **
   4035 ;***************************************************************************
   4036 ;*                                                                         *
   4037 ;*                 Project Name : Westwood Library                         *
   4038 ;*                                                                         *
   4039 ;*                    File Name : FADING.ASM                               *
   4040 ;*                                                                         *
   4041 ;*                   Programmer : Joe L. Bostic                            *
   4042 ;*                                                                         *
   4043 ;*                   Start Date : August 20, 1993                          *
   4044 ;*                                                                         *
   4045 ;*                  Last Update : August 20, 1993   [JLB]                  *
   4046 ;*                                                                         *
   4047 ;*-------------------------------------------------------------------------*
   4048 ;* Functions:                                                              *
   4049 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
   4050 
   4051 IDEAL
   4052 P386
   4053 MODEL USE32 FLAT
   4054 
   4055 GLOBAL	C Build_Fading_Table	:NEAR
   4056 
   4057 	CODESEG
   4058 
   4059 ;***********************************************************
   4060 ; BUILD_FADING_TABLE
   4061 ;
   4062 ; void *Build_Fading_Table(void *palette, void *dest, long int color, long int frac);
   4063 ;
   4064 ; This routine will create the fading effect table used to coerce colors
   4065 ; from toward a common value.  This table is used when Fading_Effect is
   4066 ; active.
   4067 ;
   4068 ; Bounds Checking: None
   4069 ;*
   4070 */
   4071 void * __cdecl Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac)
   4072 {
   4073 	/*
   4074 	PROC	Build_Fading_Table C near
   4075 	USES	ebx, ecx, edi, esi
   4076 	ARG	palette:DWORD
   4077 	ARG	dest:DWORD
   4078 	ARG	color:DWORD
   4079 	ARG	frac:DWORD
   4080 
   4081 	LOCAL	matchvalue:DWORD	; Last recorded match value.
   4082 	LOCAL	targetred:BYTE		; Target gun red.
   4083 	LOCAL	targetgreen:BYTE	; Target gun green.
   4084 	LOCAL	targetblue:BYTE		; Target gun blue.
   4085 	LOCAL	idealred:BYTE
   4086 	LOCAL	idealgreen:BYTE
   4087 	LOCAL	idealblue:BYTE
   4088 	LOCAL	matchcolor:BYTE		; Tentative match color.
   4089 	*/
   4090 	
   4091 	int matchvalue = 0;	//:DWORD	; Last recorded match value.
   4092 	unsigned char targetred = 0;		//BYTE		; Target gun red.
   4093 	unsigned char targetgreen = 0;	//BYTE		; Target gun green.
   4094 	unsigned char targetblue = 0;		//BYTE		; Target gun blue.
   4095 	unsigned char idealred = 0;		//BYTE	
   4096 	unsigned char idealgreen = 0;		//BYTE	
   4097 	unsigned char idealblue = 0;		//BYTE	
   4098 	unsigned char matchcolor = 0;		//:BYTE		; Tentative match color.
   4099 	
   4100 	__asm {
   4101 		cld
   4102 
   4103 		; If the source palette is NULL, then just return with current fading table pointer.
   4104 		cmp	[palette],0
   4105 		je	fini
   4106 		cmp	[dest],0
   4107 		je	fini
   4108 
   4109 		; Fractions above 255 become 255.
   4110 		mov	eax,[frac]
   4111 		cmp	eax,0100h
   4112 		jb	short ok
   4113 		mov	[frac],0FFh
   4114 	ok:
   4115 
   4116 		; Record the target gun values.
   4117 		mov	esi,[palette]
   4118 		mov	ebx,[color]
   4119 		add	esi,ebx
   4120 		add	esi,ebx
   4121 		add	esi,ebx
   4122 		lodsb
   4123 		mov	[targetred],al
   4124 		lodsb
   4125 		mov	[targetgreen],al
   4126 		lodsb
   4127 		mov	[targetblue],al
   4128 
   4129 		; Main loop.
   4130 		xor	ebx,ebx			; Remap table index.
   4131 
   4132 		; Transparent black never gets remapped.
   4133 		mov	edi,[dest]
   4134 		mov	[edi],bl
   4135 		inc	edi
   4136 
   4137 		; EBX = source palette logical number (1..255).
   4138 		; EDI = running pointer into dest remap table.
   4139 	mainloop:
   4140 		inc	ebx
   4141 		mov	esi,[palette]
   4142 		add	esi,ebx
   4143 		add	esi,ebx
   4144 		add	esi,ebx
   4145 
   4146 		mov	edx,[frac]
   4147 		shr	edx,1
   4148 		; new = orig - ((orig-target) * fraction);
   4149 
   4150 		lodsb				; orig
   4151 		mov	dh,al			; preserve it for later.
   4152 		sub	al,[targetred]		; al = (orig-target)
   4153 		imul	dl			; ax = (orig-target)*fraction
   4154 		shl	ax,1
   4155 		sub	dh,ah			; dh = orig - ((orig-target) * fraction)
   4156 		mov	[idealred],dh		; preserve ideal color gun value.
   4157 
   4158 		lodsb				; orig
   4159 		mov	dh,al			; preserve it for later.
   4160 		sub	al,[targetgreen]	; al = (orig-target)
   4161 		imul	dl			; ax = (orig-target)*fraction
   4162 		shl	ax,1
   4163 		sub	dh,ah			; dh = orig - ((orig-target) * fraction)
   4164 		mov	[idealgreen],dh		; preserve ideal color gun value.
   4165 
   4166 		lodsb				; orig
   4167 		mov	dh,al			; preserve it for later.
   4168 		sub	al,[targetblue]		; al = (orig-target)
   4169 		imul	dl			; ax = (orig-target)*fraction
   4170 		shl	ax,1
   4171 		sub	dh,ah			; dh = orig - ((orig-target) * fraction)
   4172 		mov	[idealblue],dh		; preserve ideal color gun value.
   4173 
   4174 		; Sweep through the entire existing palette to find the closest
   4175 		; matching color.  Never matches with color 0.
   4176 
   4177 		mov	eax,[color]
   4178 		mov	[matchcolor],al		; Default color (self).
   4179 		mov	[matchvalue],-1		; Ridiculous match value init.
   4180 		mov	ecx,255
   4181 
   4182 		mov	esi,[palette]		; Pointer to original palette.
   4183 		add	esi,3
   4184 
   4185 		; BH = color index.
   4186 		mov	bh,1
   4187 	innerloop:
   4188 
   4189 		; Recursion through the fading table won't work if a color is allowed
   4190 		; to remap to itself.  Prevent this from occuring.
   4191 		add	esi,3
   4192 		cmp	bh,bl
   4193 		je	short notclose
   4194 		sub	esi,3
   4195 
   4196 		xor	edx,edx			; Comparison value starts null.
   4197 		mov	eax,edx
   4198 		; Build the comparison value based on the sum of the differences of the color
   4199 		; guns squared.
   4200 		lodsb
   4201 		sub	al,[idealred]
   4202 		mov	ah,al
   4203 		imul	ah
   4204 		add	edx,eax
   4205 
   4206 		lodsb
   4207 		sub	al,[idealgreen]
   4208 		mov	ah,al
   4209 		imul	ah
   4210 		add	edx,eax
   4211 
   4212 		lodsb
   4213 		sub	al,[idealblue]
   4214 		mov	ah,al
   4215 		imul	ah
   4216 		add	edx,eax
   4217 		jz	short perfect		; If perfect match found then quit early.
   4218 
   4219 		cmp	edx,[matchvalue]
   4220 		ja	short notclose
   4221 		mov	[matchvalue],edx	; Record new possible color.
   4222 		mov	[matchcolor],bh
   4223 	notclose:
   4224 		inc	bh			; Checking color index.
   4225 		loop	innerloop
   4226 		mov	bh,[matchcolor]
   4227 	perfect:
   4228 		mov	[matchcolor],bh
   4229 		xor	bh,bh			; Make BX valid main index again.
   4230 
   4231 		; When the loop exits, we have found the closest match.
   4232 		mov	al,[matchcolor]
   4233 		stosb
   4234 		cmp	ebx,255
   4235 		jne	mainloop
   4236 
   4237 	fini:
   4238 		mov	eax,[dest]
   4239 //			ret
   4240 
   4241 
   4242 	}
   4243 }
   4244 
   4245 
   4246 
   4247 
   4248 
   4249 
   4250 
   4251 
   4252 
   4253 
   4254 
   4255 
   4256 
   4257 
   4258 
   4259 
   4260 
   4261 
   4262 
   4263 
   4264 
   4265 
   4266 
   4267 
   4268 /*
   4269 ;***************************************************************************
   4270 ;**   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   **
   4271 ;***************************************************************************
   4272 ;*                                                                         *
   4273 ;*                 Project Name : Westwood Library                         *
   4274 ;*                                                                         *
   4275 ;*                    File Name : PAL.ASM                                  *
   4276 ;*                                                                         *
   4277 ;*                   Programmer : Joe L. Bostic                            *
   4278 ;*                                                                         *
   4279 ;*                   Start Date : May 30, 1992                             *
   4280 ;*                                                                         *
   4281 ;*                  Last Update : April 27, 1994   [BR]                    *
   4282 ;*                                                                         *
   4283 ;*-------------------------------------------------------------------------*
   4284 ;* Functions:                                                              *
   4285 ;*   Set_Palette_Range -- Sets changed values in the palette.              *
   4286 ;*   Bump_Color -- adjusts specified color in specified palette            *
   4287 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
   4288 ;********************** Model & Processor Directives ************************
   4289 IDEAL
   4290 P386
   4291 MODEL USE32 FLAT
   4292 
   4293 
   4294 ;include "keyboard.inc"
   4295 FALSE = 0
   4296 TRUE  = 1
   4297 
   4298 ;****************************** Declarations ********************************
   4299 GLOBAL 		C Set_Palette_Range:NEAR
   4300 GLOBAL 		C Bump_Color:NEAR
   4301 GLOBAL  	C CurrentPalette:BYTE:768
   4302 GLOBAL		C PaletteTable:byte:1024
   4303 
   4304 
   4305 ;********************************** Data ************************************
   4306 LOCALS ??
   4307 
   4308 	DATASEG
   4309 
   4310 CurrentPalette	DB	768 DUP(255)	; copy of current values of DAC regs
   4311 PaletteTable	DB	1024 DUP(0)
   4312 
   4313 IFNDEF LIB_EXTERNS_RESOLVED
   4314 VertBlank	DW	0		; !!!! this should go away
   4315 ENDIF
   4316 
   4317 
   4318 ;********************************** Code ************************************
   4319 	CODESEG
   4320 */
   4321 
   4322 extern "C" unsigned char CurrentPalette[768] = {255};	//	DB	768 DUP(255)	; copy of current values of DAC regs
   4323 extern "C" unsigned char PaletteTable[1024] = {0};		//	DB	1024 DUP(0)
   4324 
   4325 
   4326 /*
   4327 ;***************************************************************************
   4328 ;* SET_PALETTE_RANGE -- Sets a palette range to the new pal                *
   4329 ;*                                                                         *
   4330 ;* INPUT:                                                                  *
   4331 ;*                                                                         *
   4332 ;* OUTPUT:                                                                 *
   4333 ;*                                                                         *
   4334 ;* PROTO:                                                                  *
   4335 ;*                                                                         *
   4336 ;* WARNINGS:	This routine is optimized for changing a small number of   *
   4337 ;*		colors in the palette.
   4338 ;*                                                                         *
   4339 ;* HISTORY:                                                                *
   4340 ;*   03/07/1995 PWG : Created.                                             *
   4341 ;*=========================================================================*
   4342 */
   4343 void __cdecl Set_Palette_Range(void *palette)
   4344 {
   4345 	memcpy(CurrentPalette, palette, 768);
   4346 	Set_DD_Palette(palette);
   4347 
   4348 	/*
   4349 	PROC	Set_Palette_Range C NEAR
   4350 	ARG	palette:DWORD
   4351 
   4352 	GLOBAL	Set_DD_Palette_:near
   4353 	GLOBAL	Wait_Vert_Blank_:near
   4354 	
   4355 	pushad
   4356 	mov	esi,[palette]
   4357 	mov	ecx,768/4
   4358 	mov	edi,offset CurrentPalette
   4359 	cld
   4360 	rep	movsd
   4361 	;call	Wait_Vert_Blank_
   4362 	mov	eax,[palette]
   4363 	push	eax
   4364 	call	Set_DD_Palette_
   4365 	pop	eax
   4366 	popad
   4367 	ret
   4368 	*/
   4369 }
   4370 
   4371 
   4372 /*
   4373 ;***************************************************************************
   4374 ;* Bump_Color -- adjusts specified color in specified palette              *
   4375 ;*                                                                         *
   4376 ;* INPUT:                                                                  *
   4377 ;*	VOID *palette	- palette to modify				   *
   4378 ;*	WORD changable	- color # to change				   *
   4379 ;*	WORD target	- color to bend toward				   *
   4380 ;*                                                                         *
   4381 ;* OUTPUT:                                                                 *
   4382 ;*                                                                         *
   4383 ;* WARNINGS:                                                               *
   4384 ;*                                                                         *
   4385 ;* HISTORY:                                                                *
   4386 ;*   04/27/1994 BR : Converted to 32-bit.                                  *
   4387 ;*=========================================================================*
   4388 ; BOOL cdecl Bump_Color(VOID *palette, WORD changable, WORD target);
   4389 */ 
   4390 BOOL __cdecl Bump_Color(void *pal, int color, int desired)
   4391 {
   4392 	/*		  
   4393 PROC Bump_Color C NEAR
   4394 	USES ebx,ecx,edi,esi
   4395 	ARG	pal:DWORD, color:WORD, desired:WORD
   4396 	LOCAL	changed:WORD		; Has palette changed?
   4397 	 */ 
   4398 	
   4399 	short short_color = (short) color;
   4400 	short short_desired = (short) desired;
   4401 	bool changed = false;
   4402 	
   4403 	__asm {
   4404 		mov	edi,[pal]		; Original palette pointer.
   4405 		mov	esi,edi
   4406 		mov	eax,0
   4407 		mov	ax,[short_color]
   4408 		add	edi,eax
   4409 		add	edi,eax
   4410 		add	edi,eax			; Offset to changable color.
   4411 		mov	ax,[short_desired]
   4412 		add	esi,eax
   4413 		add	esi,eax
   4414 		add	esi,eax			; Offset to target color.
   4415 
   4416 		mov	[changed],FALSE		; Presume no change.
   4417 		mov	ecx,3			; Three color guns.
   4418 
   4419 		; Check the color gun.
   4420 	colorloop:
   4421 		mov	al,[BYTE PTR esi]
   4422 		sub	al,[BYTE PTR edi]	; Carry flag is set if subtraction needed.
   4423 		jz	short gotit
   4424 		mov	[changed],TRUE
   4425 		inc	[BYTE PTR edi]		; Presume addition.
   4426 		jnc	short gotit		; oops, subtraction needed so dec twice.
   4427 		dec	[BYTE PTR edi]
   4428 		dec	[BYTE PTR edi]
   4429 	gotit:
   4430 		inc	edi
   4431 		inc	esi
   4432 		loop	colorloop
   4433 
   4434 		movzx	eax,[changed]
   4435 	}
   4436 }
   4437 
   4438 
   4439 
   4440 
   4441 
   4442 
   4443 
   4444 
   4445 
   4446 
   4447 
   4448 
   4449 
   4450 
   4451 
   4452 /*
   4453 ;***************************************************************************
   4454 ;**     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       **
   4455 ;***************************************************************************
   4456 ;*                                                                         *
   4457 ;*                 Project Name : GraphicViewPortClass			   *
   4458 ;*                                                                         *
   4459 ;*                    File Name : PUTPIXEL.ASM                             *
   4460 ;*                                                                         *
   4461 ;*                   Programmer : Phil Gorrow				   *
   4462 ;*                                                                         *
   4463 ;*                   Start Date : June 7, 1994				   *
   4464 ;*                                                                         *
   4465 ;*                  Last Update : June 8, 1994   [PWG]                     *
   4466 ;*                                                                         *
   4467 ;*-------------------------------------------------------------------------*
   4468 ;* Functions:                                                              *
   4469 ;*   VVPC::Put_Pixel -- Puts a pixel on a virtual viewport                 *
   4470 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
   4471 
   4472 IDEAL
   4473 P386
   4474 MODEL USE32 FLAT
   4475 
   4476 INCLUDE ".\drawbuff.inc"
   4477 INCLUDE ".\gbuffer.inc"
   4478 
   4479 
   4480 CODESEG
   4481 */
   4482 
   4483 /*
   4484 ;***************************************************************************
   4485 ;* VVPC::PUT_PIXEL -- Puts a pixel on a virtual viewport                   *
   4486 ;*                                                                         *
   4487 ;* INPUT:	WORD the x position for the pixel relative to the upper    *
   4488 ;*			left corner of the viewport			   *
   4489 ;*		WORD the y pos for the pixel relative to the upper left	   *
   4490 ;*			corner of the viewport				   *
   4491 ;*		UBYTE the color of the pixel to write			   *
   4492 ;*                                                                         *
   4493 ;* OUTPUT:      none                                                       *
   4494 ;*                                                                         *
   4495 ;* WARNING:	If pixel is to be placed outside of the viewport then	   *
   4496 ;*		this routine will abort.				   *
   4497 ;*									   *
   4498 ;* HISTORY:                                                                *
   4499 ;*   06/08/1994 PWG : Created.                                             *
   4500 ;*=========================================================================*
   4501 	PROC	Buffer_Put_Pixel C near
   4502 	USES	eax,ebx,ecx,edx,edi
   4503 */
   4504 
   4505 void __cdecl Buffer_Put_Pixel(void * this_object, int x_pixel, int y_pixel, unsigned char color)
   4506 {
   4507 			  
   4508 	/*
   4509 	ARG    	this_object:DWORD				; this is a member function
   4510 	ARG	x_pixel:DWORD				; x position of pixel to set
   4511 	ARG	y_pixel:DWORD				; y position of pixel to set
   4512 	ARG    	color:BYTE				; what color should we clear to
   4513 	*/
   4514 	
   4515 	__asm {
   4516 		
   4517 	
   4518 			;*===================================================================
   4519 			; Get the viewport information and put bytes per row in ecx
   4520 			;*===================================================================
   4521 			mov	ebx,[this_object]				; get a pointer to viewport
   4522 			xor	eax,eax
   4523 			mov	edi,[ebx]GraphicViewPortClass.Offset	; get the correct offset
   4524 			mov	ecx,[ebx]GraphicViewPortClass.Height	; edx = height of viewport
   4525 			mov	edx,[ebx]GraphicViewPortClass.Width	; ecx = width of viewport
   4526 
   4527 			;*===================================================================
   4528 			; Verify that the X pixel offset if legal
   4529 			;*===================================================================
   4530 			mov	eax,[x_pixel]				; find the x position
   4531 			cmp	eax,edx					;   is it out of bounds
   4532 			jae	short done				; if so then get out
   4533 			add	edi,eax					; otherwise add in offset
   4534 
   4535 			;*===================================================================
   4536 			; Verify that the Y pixel offset if legal
   4537 			;*===================================================================
   4538 			mov	eax,[y_pixel]				; get the y position
   4539 			cmp	eax,ecx					;  is it out of bounds
   4540 			jae	done					; if so then get out
   4541 			add	edx,[ebx]GraphicViewPortClass.XAdd	; otherwise find bytes per row
   4542 			add	edx,[ebx]GraphicViewPortClass.Pitch	; add in direct draw pitch
   4543 			mul	edx					; offset = bytes per row * y
   4544 			add	edi,eax					; add it into the offset
   4545 
   4546 			;*===================================================================
   4547 			; Write the pixel to the screen
   4548 			;*===================================================================
   4549 			mov	al,[color]				; read in color value
   4550 			mov	[edi],al				; write it to the screen
   4551 		done:
   4552 	}
   4553 }
   4554 
   4555 
   4556 
   4557 
   4558 
   4559 
   4560 
   4561 
   4562 /*
   4563 ;***************************************************************************
   4564 ;**   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   **
   4565 ;***************************************************************************
   4566 ;*                                                                         *
   4567 ;*                 Project Name : Support Library                          *
   4568 ;*                                                                         *
   4569 ;*                    File Name : cliprect.asm                             *
   4570 ;*                                                                         *
   4571 ;*                   Programmer : Julio R Jerez                            *
   4572 ;*                                                                         *
   4573 ;*                   Start Date : Mar, 2 1995                              *
   4574 ;*                                                                         *
   4575 ;*                                                                         *
   4576 ;*-------------------------------------------------------------------------*
   4577 ;* Functions:                                                              *
   4578 ;* int Clip_Rect ( int * x , int * y , int * dw , int * dh , 		   *
   4579 ;*	       	   int width , int height ) ;          			   *
   4580 ;* int Confine_Rect ( int * x , int * y , int * dw , int * dh , 	   *
   4581 ;*	       	      int width , int height ) ;          		   *
   4582 ;*									   *
   4583 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
   4584 
   4585 
   4586 IDEAL
   4587 P386
   4588 MODEL USE32 FLAT
   4589 
   4590 GLOBAL	 C Clip_Rect	:NEAR
   4591 GLOBAL	 C Confine_Rect	:NEAR
   4592 
   4593 CODESEG
   4594 
   4595 ;***************************************************************************
   4596 ;* Clip_Rect -- clip a given rectangle against a given window		   *
   4597 ;*                                                                         *
   4598 ;* INPUT:   &x , &y , &w , &h  -> Pointer to rectangle being clipped       *
   4599 ;*          width , height     -> dimension of clipping window             *
   4600 ;*                                                                         *
   4601 ;* OUTPUT: a) Zero if the rectangle is totally contained by the 	   *
   4602 ;*	      clipping window.						   *
   4603 ;*	   b) A negative value if the rectangle is totally outside the     *
   4604 ;*            the clipping window					   *
   4605 ;*	   c) A positive value if the rectangle	was clipped against the	   *
   4606 ;*	      clipping window, also the values pointed by x, y, w, h will  *
   4607 ;*	      be modified to new clipped values	 			   *
   4608 ;*									   *
   4609 ;*   05/03/1995 JRJ : added comment                                        *
   4610 ;*=========================================================================*
   4611 ; int Clip_Rect (int* x, int* y, int* dw, int* dh, int width, int height);          			   *
   4612 */
   4613 
   4614 extern "C" int __cdecl Clip_Rect ( int * x , int * y , int * w , int * h , int width , int height )
   4615 {		
   4616 
   4617 /*
   4618 	PROC	Clip_Rect C near
   4619 	uses	ebx,ecx,edx,esi,edi
   4620 	arg	x:dword
   4621 	arg	y:dword
   4622 	arg	w:dword
   4623 	arg	h:dword
   4624 	arg	width:dword
   4625 	arg	height:dword
   4626 */
   4627 
   4628 	__asm {
   4629 
   4630 		;This Clipping algorithm is a derivation of the very well known
   4631 		;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency
   4632 		;it is probably the most commontly implemented algorithm both in software
   4633 		;and hardware for clipping lines, rectangles, and convex polygons against
   4634 		;a rectagular clipping window. For reference see
   4635 		;"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes
   4636 		; pages 113 to 177".
   4637 		; Briefly consist in computing the Sutherland code for both end point of
   4638 		; the rectangle to find out if the rectangle is:
   4639 		; - trivially accepted (no further clipping test, return the oroginal data)
   4640 		; - trivially rejected (return with no action, return error code)
   4641 		; - retangle must be iteratively clipped again edges of the clipping window
   4642 		;   and return the clipped rectangle
   4643 
   4644 			; get all four pointer into regisnters
   4645 			mov	esi,[x]		; esi = pointer to x
   4646 			mov	edi,[y]		; edi = pointer to x
   4647 			mov	eax,[w]		; eax = pointer to dw
   4648 			mov	ebx,[h]		; ebx = pointer to dh
   4649 
   4650 			; load the actual data into reg
   4651 			mov	esi,[esi]	; esi = x0
   4652 			mov	edi,[edi]	; edi = y0
   4653 			mov	eax,[eax]	; eax = dw
   4654 			mov	ebx,[ebx]	; ebx = dh
   4655 
   4656 			; create a wire frame of the type [x0,y0] , [x1,y1]
   4657 			add	eax,esi		; eax = x1 = x0 + dw
   4658 			add	ebx,edi		; ebx = y1 = y0 + dh
   4659 
   4660 			; we start we suthenland code0 and code1 set to zero
   4661 			xor 	ecx,ecx		; cl = sutherland boolean code0
   4662 			xor 	edx,edx		; dl = sutherland boolean code0
   4663 
   4664 			; now we start computing the to suthenland boolean code for x0 , x1
   4665 			shld	ecx,esi,1	; bit3 of code0 = sign bit of (x0 - 0)
   4666 			shld	edx,eax,1 	; bit3 of code1 = sign bit of (x1 - 0)
   4667 			sub	esi,[width]	; get the difference (x0 - (width + 1))
   4668 			sub	eax,[width]	; get the difference (x1 - (width + 1))
   4669 			dec	esi
   4670 			dec	eax
   4671 			shld	ecx,esi,1	; bit2 of code0 = sign bit of (x0 - (width + 1))
   4672 			shld	edx,eax,1	; bit2 of code1 = sign bit of (x0 - (width + 1))
   4673 
   4674 			; now we start computing the to suthenland boolean code for y0 , y1
   4675 			shld	ecx,edi,1   	; bit1 of code0 = sign bit of (y0 - 0)
   4676 			shld	edx,ebx,1	; bit1 of code1 = sign bit of (y0 - 0)
   4677 			sub	edi,[height]	; get the difference (y0 - (height + 1))
   4678 			sub	ebx,[height]	; get the difference (y1 - (height + 1))
   4679 			dec	edi
   4680 			dec	ebx
   4681 			shld	ecx,edi,1	; bit0 of code0 = sign bit of (y0 - (height + 1))
   4682 			shld	edx,ebx,1	; bit0 of code1 = sign bit of (y1 - (height + 1))
   4683 
   4684 			; Bit 2 and 0 of cl and bl are complemented
   4685 			xor	cl,5		; reverse bit2 and bit0 in code0
   4686 			xor	dl,5 		; reverse bit2 and bit0 in code1
   4687 
   4688 			; now perform the rejection test
   4689 			mov	eax,-1		; set return code to false
   4690 			mov	bl,cl 		; save code0 for future use
   4691 			test	dl,cl  		; if any two pair of bit in code0 and code1 is set
   4692 			jnz	clip_out	; then rectangle is outside the window
   4693 
   4694 			; now perform the aceptance test
   4695 			xor	eax,eax		; set return code to true
   4696 			or	bl,dl		; if all pair of bits in code0 and code1 are reset
   4697 			jz	clip_out	; then rectangle is insize the window.								      '
   4698 
   4699 			; we need to clip the rectangle iteratively
   4700 			mov	eax,-1		; set return code to false
   4701 			test	cl,1000b	; if bit3 of code0 is set then the rectangle
   4702 			jz	left_ok	; spill out the left edge of the window
   4703 			mov	edi,[x]		; edi = a pointer to x0
   4704 			mov	ebx,[w]		; ebx = a pointer to dw
   4705 			mov	esi,[edi]	; esi = x0
   4706 			mov	[dword ptr edi],0 ; set x0 to 0 "this the left edge value"
   4707 			add	[ebx],esi	; adjust dw by x0, since x0 must be negative
   4708 
   4709 		left_ok:
   4710 			test	cl,0010b	; if bit1 of code0 is set then the rectangle
   4711 			jz	bottom_ok	; spill out the bottom edge of the window
   4712 			mov	edi,[y]		; edi = a pointer to y0
   4713 			mov	ebx,[h]		; ebx = a pointer to dh
   4714 			mov	esi,[edi]	; esi = y0
   4715 			mov	[dword ptr edi],0 ; set y0 to 0 "this the bottom edge value"
   4716 			add	[ebx],esi	; adjust dh by y0, since y0 must be negative
   4717 
   4718 		bottom_ok:
   4719 			test	dl,0100b	; if bit2 of code1 is set then the rectangle
   4720 			jz	right_ok	; spill out the right edge of the window
   4721 			mov	edi,[w] 	; edi = a pointer to dw
   4722 			mov	esi,[x]		; esi = a pointer to x
   4723 			mov	ebx,[width]	; ebx = the width of the window
   4724 			sub	ebx,[esi] 	; the new dw is the difference (width-x0)
   4725 			mov	[edi],ebx	; adjust dw to (width - x0)
   4726 			jle	clip_out	; if (width-x0) = 0 then the clipped retangle
   4727 						; has no width we are done
   4728 		right_ok:
   4729 			test	dl,0001b	; if bit0 of code1 is set then the rectangle
   4730 			jz	clip_ok	; spill out the top edge of the window
   4731 			mov	edi,[h] 	; edi = a pointer to dh
   4732 			mov	esi,[y]		; esi = a pointer to y0
   4733 			mov	ebx,[height]	; ebx = the height of the window
   4734 			sub	ebx,[esi] 	; the new dh is the difference (height-y0)
   4735 			mov	[edi],ebx	; adjust dh to (height-y0)
   4736 			jle	clip_out	; if (width-x0) = 0 then the clipped retangle
   4737 						; has no width we are done
   4738 		clip_ok:
   4739 			mov	eax,1  	; signal the calling program that the rectangle was modify
   4740 		clip_out:
   4741 		//ret
   4742 	}
   4743 
   4744 	//ENDP	Clip_Rect
   4745 }
   4746 
   4747 /*
   4748 ;***************************************************************************
   4749 ;* Confine_Rect -- clip a given rectangle against a given window	   *
   4750 ;*                                                                         *
   4751 ;* INPUT:   &x,&y,w,h    -> Pointer to rectangle being clipped       *
   4752 ;*          width,height     -> dimension of clipping window             *
   4753 ;*                                                                         *
   4754 ;* OUTPUT: a) Zero if the rectangle is totally contained by the 	   *
   4755 ;*	      clipping window.						   *
   4756 ;*	   c) A positive value if the rectangle	was shifted in position    *
   4757 ;*	      to fix inside the clipping window, also the values pointed   *
   4758 ;*	      by x, y, will adjusted to a new values	 		   *
   4759 ;*									   *
   4760 ;*  NOTE:  this function make not attempt to verify if the rectangle is	   *
   4761 ;*	   bigger than the clipping window and at the same time wrap around*
   4762 ;*	   it. If that is the case the result is meaningless		   *
   4763 ;*=========================================================================*
   4764 ; int Confine_Rect (int* x, int* y, int dw, int dh, int width, int height);          			   *
   4765 */
   4766 
   4767 extern "C" int __cdecl Confine_Rect ( int * x , int * y , int w , int h , int width , int height )
   4768 {
   4769 	
   4770 /*
   4771 	PROC	Confine_Rect C near
   4772 	uses	ebx, esi,edi
   4773 	arg	x:dword
   4774 	arg	y:dword
   4775 	arg	w:dword
   4776 	arg	h:dword
   4777 	arg	width :dword
   4778 	arg	height:dword
   4779 */
   4780 	__asm {		  
   4781 	
   4782 			xor	eax,eax
   4783 			mov	ebx,[x]
   4784 			mov	edi,[w]
   4785 
   4786 			mov	esi,[ebx]
   4787 			add	edi,[ebx]
   4788 
   4789 			sub	edi,[width]
   4790 			neg	esi
   4791 			dec	edi
   4792 
   4793 			test	esi,edi
   4794 			jl	x_axix_ok
   4795 			mov	eax,1
   4796 
   4797 			test	esi,esi
   4798 			jl	shift_right
   4799 			mov	[dword ptr ebx],0
   4800 			jmp	x_axix_ok
   4801 		shift_right:
   4802 			inc	edi
   4803 			sub	[ebx],edi
   4804 		x_axix_ok:
   4805 			mov	ebx,[y]
   4806 			mov	edi,[h]
   4807 
   4808 			mov	esi,[ebx]
   4809 			add	edi,[ebx]
   4810 
   4811 			sub	edi,[height]
   4812 			neg	esi
   4813 			dec	edi
   4814 
   4815 			test	esi,edi
   4816 			jl	confi_out
   4817 			mov	eax,1
   4818 
   4819 			test	esi,esi
   4820 			jl	shift_top
   4821 			mov	[dword ptr ebx],0
   4822 
   4823 			//ret
   4824 			jmp confi_out
   4825 		shift_top:
   4826 			inc	edi
   4827 			sub	[ebx],edi
   4828 		confi_out:
   4829 			//ret
   4830 
   4831 			//ENDP	Confine_Rect
   4832 	}
   4833 }
   4834 
   4835 
   4836 
   4837 
   4838 
   4839 
   4840 
   4841 
   4842 
   4843 /*
   4844 ; $Header: //depot/Projects/Mobius/QA/Project/Run/SOURCECODE/TIBERIANDAWN/WIN32LIB/DrawMisc.cpp#139 $
   4845 ;***************************************************************************
   4846 ;**   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   **
   4847 ;***************************************************************************
   4848 ;*                                                                         *
   4849 ;*                 Project Name : Library routine                          *
   4850 ;*                                                                         *
   4851 ;*                    File Name : UNCOMP.ASM                               *
   4852 ;*                                                                         *
   4853 ;*                   Programmer : Christopher Yates                        *
   4854 ;*                                                                         *
   4855 ;*                  Last Update : 20 August, 1990   [CY]                   *
   4856 ;*                                                                         *
   4857 ;*-------------------------------------------------------------------------*
   4858 ;* Functions:                                                              *
   4859 ;*                                                                         *
   4860 ; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);		   *
   4861 ;*                                                                         *
   4862 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
   4863 
   4864 IDEAL
   4865 P386
   4866 MODEL USE32 FLAT
   4867 
   4868 GLOBAL            C LCW_Uncompress          :NEAR
   4869 
   4870 CODESEG
   4871 
   4872 ; ----------------------------------------------------------------
   4873 ;
   4874 ; Here are prototypes for the routines defined within this module:
   4875 ;
   4876 ; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);
   4877 ;
   4878 ; ----------------------------------------------------------------
   4879 */
   4880 
   4881 extern "C" unsigned long __cdecl LCW_Uncompress(void *source, void *dest, unsigned long length_)
   4882 {
   4883 //PROC	LCW_Uncompress C near
   4884 //
   4885 //	USES ebx,ecx,edx,edi,esi
   4886 //
   4887 //	ARG	source:DWORD
   4888 //	ARG	dest:DWORD
   4889 //	ARG	length:DWORD
   4890 //;LOCALS
   4891 //	LOCAL a1stdest:DWORD
   4892 //	LOCAL maxlen:DWORD
   4893 //	LOCAL lastbyte:DWORD
   4894 //	LOCAL lastcom:DWORD
   4895 //	LOCAL lastcom1:DWORD
   4896 		
   4897 	unsigned long a1stdest;
   4898 	unsigned long  maxlen;
   4899 	unsigned long lastbyte;
   4900 	//unsigned long lastcom;
   4901 	//unsigned long lastcom1;
   4902 
   4903 	__asm {
   4904 
   4905 
   4906 		mov	edi,[dest]
   4907 		mov	esi,[source]
   4908 		mov	edx,[length_]
   4909 
   4910 	;
   4911 	;
   4912 	; uncompress data to the following codes in the format b = byte, w = word
   4913 	; n = byte code pulled from compressed data
   4914 	;   Bit field of n		command		description
   4915 	; n=0xxxyyyy,yyyyyyyy		short run	back y bytes and run x+3
   4916 	; n=10xxxxxx,n1,n2,...,nx+1	med length	copy the next x+1 bytes
   4917 	; n=11xxxxxx,w1			med run		run x+3 bytes from offset w1
   4918 	; n=11111111,w1,w2		long copy	copy w1 bytes from offset w2
   4919 	; n=11111110,w1,b1		long run	run byte b1 for w1 bytes
   4920 	; n=10000000			end		end of data reached
   4921 	;
   4922 
   4923 		mov	[a1stdest],edi
   4924 		add	edx,edi
   4925 		mov	[lastbyte],edx
   4926 		cld			; make sure all lod and sto are forward
   4927 		mov	ebx,esi		; save the source offset
   4928 
   4929 	loop_label:
   4930 		mov	eax,[lastbyte]
   4931 		sub	eax,edi		; get the remaining byte to uncomp
   4932 		jz	short out_label		; were done
   4933 
   4934 		mov	[maxlen],eax	; save for string commands
   4935 		mov	esi,ebx		; mov in the source index
   4936 
   4937 		xor	eax,eax
   4938 		mov	al,[esi]
   4939 		inc	esi
   4940 		test	al,al		; see if its a short run
   4941 		js	short notshort
   4942 
   4943 		mov	ecx,eax		;put count nibble in cl
   4944 
   4945 		mov	ah,al		; put rel offset high nibble in ah
   4946 		and	ah,0Fh		; only 4 bits count
   4947 
   4948 		shr	cl,4		; get run -3
   4949 		add	ecx,3		; get actual run length
   4950 
   4951 		cmp	ecx,[maxlen]	; is it too big to fit?
   4952 		jbe	short rsok		; if not, its ok
   4953 
   4954 		mov	ecx,[maxlen]	; if so, max it out so it dosen't overrun
   4955 
   4956 	rsok:
   4957 		mov	al,[esi]	; get rel offset low byte
   4958 		lea	ebx,[esi+1]	; save the source offset
   4959 		mov	esi,edi		; get the current dest
   4960 		sub	esi,eax		; get relative offset
   4961 
   4962 		rep	movsb
   4963 
   4964 		jmp	loop_label
   4965 
   4966 	notshort:
   4967 		test	al,40h		; is it a length?
   4968 		jne	short notlength	; if not it could be med or long run
   4969 
   4970 		cmp	al,80h		; is it the end?
   4971 		je	short out_label		; if so its over
   4972 
   4973 		mov	cl,al		; put the byte in count register
   4974 		and	ecx,3Fh		; and off the extra bits
   4975 
   4976 		cmp	ecx,[maxlen]	; is it too big to fit?
   4977 		jbe	short lenok		; if not, its ok
   4978 
   4979 		mov	ecx,[maxlen]	; if so, max it out so it dosen't overrun
   4980 
   4981 	lenok:
   4982 		rep movsb
   4983 
   4984 		mov	ebx,esi		; save the source offset
   4985 		jmp	loop_label
   4986 
   4987 	out_label:
   4988 	      	mov	eax,edi
   4989 		sub	eax,[a1stdest]
   4990 		jmp	label_exit
   4991 
   4992 	notlength:
   4993 		mov	cl,al		; get the entire code
   4994 		and	ecx,3Fh		; and off all but the size -3
   4995 		add	ecx,3		; add 3 for byte count
   4996 
   4997 		cmp	al,0FEh
   4998 		jne	short notrunlength
   4999 
   5000 		xor	ecx,ecx
   5001 		mov	cx,[esi]
   5002 
   5003 		xor	eax,eax
   5004 		mov	al,[esi+2]
   5005 		lea	ebx,[esi+3]	;save the source offset
   5006 
   5007 		cmp	ecx,[maxlen]	; is it too big to fit?
   5008 		jbe	short runlenok		; if not, its ok
   5009 
   5010 		mov	ecx,[maxlen]	; if so, max it out so it dosen't overrun
   5011 
   5012 	runlenok:
   5013 		test	ecx,0ffe0h
   5014 		jnz	dont_use_stosb
   5015 		rep	stosb
   5016 		jmp	loop_label
   5017 
   5018 
   5019 	dont_use_stosb:
   5020 		mov	ah,al
   5021 		mov	edx,eax
   5022 		shl	eax,16
   5023 		or	eax,edx
   5024 
   5025 		test	edi,3
   5026 		jz	aligned
   5027 
   5028 		mov	[edi],eax
   5029 		mov	edx,edi
   5030 		and	edi,0fffffffch
   5031 		lea	edi,[edi+4]
   5032 		and	edx,3
   5033 		dec	dl
   5034 		xor	dl,3
   5035 		sub	ecx,edx
   5036 
   5037 	aligned:
   5038 		mov	edx,ecx
   5039 		shr	ecx,2
   5040 		rep	stosd
   5041 
   5042 		and	edx,3
   5043 		jz	loop_label
   5044 		mov	ecx,edx
   5045 		rep	stosb
   5046 		jmp	loop_label
   5047 
   5048 
   5049 
   5050 
   5051 
   5052 
   5053 	notrunlength:
   5054 		cmp	al,0FFh		; is it a long run?
   5055 		jne	short notlong	; if not use the code as the size
   5056 
   5057 		xor     ecx,ecx
   5058 		xor	eax,eax
   5059 		mov	cx,[esi]	; if so, get the size
   5060 		lea	esi,[esi+2]
   5061 
   5062 	notlong:
   5063 		mov	ax,[esi]	;get the real index
   5064 		add	eax,[a1stdest]	;add in the 1st index
   5065 		lea	ebx,[esi+2]	;save the source offset
   5066 		cmp	ecx,[maxlen]	;compare for overrun
   5067 		mov	esi,eax		;use eax as new source
   5068 		jbe	short runok	; if not, its ok
   5069 
   5070 		mov	ecx,[maxlen]	; if so, max it out so it dosen't overrun
   5071 
   5072 	runok:
   5073 		test	ecx,0ffe0h
   5074 		jnz	dont_use_movsb
   5075 		rep	movsb
   5076 		jmp	loop_label
   5077 
   5078 
   5079 
   5080 
   5081 	dont_use_movsb:
   5082 		lea	edx,[edi+0fffffffch]
   5083 		cmp	esi,edx
   5084 		ja	use_movsb
   5085 
   5086 		test	edi,3
   5087 		jz	aligned2
   5088 
   5089 		mov	eax,[esi]
   5090 		mov	[edi],eax
   5091 		mov	edx,edi
   5092 		and	edi,0fffffffch
   5093 		lea	edi,[edi+4]
   5094 		and	edx,3
   5095 		dec	dl
   5096 		xor	dl,3
   5097 		sub	ecx,edx
   5098 		add	esi,edx
   5099 
   5100 	aligned2:
   5101 		mov	edx,ecx
   5102 		shr	ecx,2
   5103 		and	edx,3
   5104 		rep	movsd
   5105 		mov	ecx,edx
   5106 	use_movsb:
   5107 		rep	movsb
   5108 		jmp	loop_label
   5109 
   5110 
   5111 
   5112 
   5113 	label_exit:
   5114 		mov	eax,edi
   5115 		mov	ebx,[dest]
   5116 		sub	eax,ebx
   5117 
   5118 		//ret
   5119 
   5120 	}
   5121 }
   5122 
   5123 
   5124 
   5125 
   5126 
   5127 
   5128 
   5129 
   5130 
   5131 
   5132 
   5133 
   5134 
   5135 
   5136 /*
   5137 ;***************************************************************************
   5138 ;**   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   **
   5139 ;***************************************************************************
   5140 ;*                                                                         *
   5141 ;*                 Project Name : Westwood 32 bit Library                  *
   5142 ;*                                                                         *
   5143 ;*                    File Name : TOPAGE.ASM                               *
   5144 ;*                                                                         *
   5145 ;*                   Programmer : Phil W. Gorrow                           *
   5146 ;*                                                                         *
   5147 ;*                   Start Date : June 8, 1994                             *
   5148 ;*                                                                         *
   5149 ;*                  Last Update : June 15, 1994   [PWG]                    *
   5150 ;*                                                                         *
   5151 ;*-------------------------------------------------------------------------*
   5152 ;* Functions:                                                              *
   5153 ;*   Buffer_To_Page -- Copies a linear buffer to a virtual viewport	   *
   5154 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
   5155 
   5156 IDEAL
   5157 P386
   5158 MODEL USE32 FLAT
   5159 
   5160 TRANSP	equ  0
   5161 
   5162 
   5163 INCLUDE ".\drawbuff.inc"
   5164 INCLUDE ".\gbuffer.inc"
   5165 
   5166 CODESEG
   5167 
   5168 ;***************************************************************************
   5169 ;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport		   *
   5170 ;*                                                                         *
   5171 ;* INPUT:	WORD	x_pixel		- x pixel on viewport to copy from *
   5172 ;*		WORD	y_pixel 	- y pixel on viewport to copy from *
   5173 ;*		WORD	pixel_width	- the width of copy region	   *
   5174 ;*		WORD	pixel_height	- the height of copy region	   *
   5175 ;*		BYTE *	src		- buffer to copy from		   *
   5176 ;*		VVPC *  dest		- virtual viewport to copy to	   *
   5177 ;*                                                                         *
   5178 ;* OUTPUT:      none                                                       *
   5179 ;*                                                                         *
   5180 ;* WARNINGS:    Coordinates and dimensions will be adjusted if they exceed *
   5181 ;*	        the boundaries.  In the event that no adjustment is 	   *
   5182 ;*	        possible this routine will abort.  If the size of the 	   *
   5183 ;*		region to copy exceeds the size passed in for the buffer   *
   5184 ;*		the routine will automatically abort.			   *
   5185 ;*									   *
   5186 ;* HISTORY:                                                                *
   5187 ;*   06/15/1994 PWG : Created.                                             *
   5188 ;*=========================================================================*
   5189  */ 
   5190 
   5191 extern "C" long __cdecl Buffer_To_Page(int x_pixel, int y_pixel, int pixel_width, int pixel_height, void *src, void *dest)
   5192 {
   5193 
   5194 /*
   5195 	PROC	Buffer_To_Page C near
   5196 	USES	eax,ebx,ecx,edx,esi,edi
   5197 
   5198 	;*===================================================================
   5199 	;* define the arguements that our function takes.
   5200 	;*===================================================================
   5201 	ARG	x_pixel     :DWORD		; x pixel position in source
   5202 	ARG	y_pixel     :DWORD		; y pixel position in source
   5203 	ARG	pixel_width :DWORD		; width of rectangle to blit
   5204 	ARG	pixel_height:DWORD		; height of rectangle to blit
   5205 	ARG    	src         :DWORD		; this is a member function
   5206 	ARG	dest        :DWORD		; what are we blitting to
   5207 
   5208 ;	ARG	trans       :DWORD			; do we deal with transparents?
   5209 
   5210 	;*===================================================================
   5211 	; Define some locals so that we can handle things quickly
   5212 	;*===================================================================
   5213 	LOCAL 	x1_pixel :dword
   5214 	LOCAL	y1_pixel :dword
   5215 	local	scr_x 	: dword
   5216 	local	scr_y 	: dword
   5217 	LOCAL	dest_ajust_width:DWORD
   5218 	LOCAL	scr_ajust_width:DWORD
   5219 	LOCAL	dest_area   :  dword
   5220 */
   5221 
   5222 	unsigned long x1_pixel;
   5223 	unsigned long y1_pixel;
   5224 	unsigned long scr_x;
   5225 	unsigned long scr_y;
   5226 	unsigned long dest_ajust_width;
   5227 	unsigned long scr_ajust_width;
   5228 	//unsigned long dest_area;
   5229 
   5230 	__asm {
   5231 	
   5232 			cmp	[ src ] , 0
   5233 			jz	real_out
   5234 
   5235 
   5236 		; Clip dest Rectangle against source Window boundaries.
   5237 
   5238 			mov	[ scr_x ] , 0
   5239 			mov	[ scr_y ] , 0
   5240 			mov  	esi , [ dest ]	    ; get ptr to dest
   5241 			xor 	ecx , ecx
   5242 			xor 	edx , edx
   5243 			mov	edi , [esi]GraphicViewPortClass.Width  ; get width into register
   5244 			mov	ebx , [ x_pixel ]
   5245 			mov	eax , [ x_pixel ]
   5246 			add	ebx , [ pixel_width ]
   5247 			shld	ecx , eax , 1
   5248 			mov	[ x1_pixel ] , ebx
   5249 			inc	edi
   5250 			shld	edx , ebx , 1
   5251 			sub	eax , edi
   5252 			sub	ebx , edi
   5253 			shld	ecx , eax , 1
   5254 			shld	edx , ebx , 1
   5255 
   5256 			mov	edi, [esi]GraphicViewPortClass.Height ; get height into register
   5257 			mov	ebx , [ y_pixel ]
   5258 			mov	eax , [ y_pixel ]
   5259 			add	ebx , [ pixel_height ]
   5260 			shld	ecx , eax , 1
   5261 			mov	[ y1_pixel ] , ebx
   5262 			inc	edi
   5263 			shld	edx , ebx , 1
   5264 			sub	eax , edi
   5265 			sub	ebx , edi
   5266 			shld	ecx , eax , 1
   5267 			shld	edx , ebx , 1
   5268 
   5269 			xor	cl , 5
   5270 			xor	dl , 5
   5271 			mov	al , cl
   5272 			test	dl , cl
   5273 			jnz	real_out
   5274 			or	al , dl
   5275 			jz	do_blit
   5276 
   5277 			test	cl , 1000b
   5278 			jz	dest_left_ok
   5279 			mov	eax , [ x_pixel ]
   5280 			neg	eax
   5281 			mov	[ x_pixel ] , 0
   5282 			mov	[ scr_x ] , eax
   5283 
   5284 		dest_left_ok:
   5285 			test	cl , 0010b
   5286 			jz	dest_bottom_ok
   5287 			mov	eax , [ y_pixel ]
   5288 			neg	eax
   5289 			mov	[ y_pixel ] , 0
   5290 			mov	[ scr_y ] , eax
   5291 
   5292 		dest_bottom_ok:
   5293 			test	dl , 0100b
   5294 			jz	dest_right_ok
   5295 			mov	eax , [esi]GraphicViewPortClass.Width  ; get width into register
   5296 			mov	[ x1_pixel ] , eax
   5297 		dest_right_ok:
   5298 			test	dl , 0001b
   5299 			jz	do_blit
   5300 			mov	eax , [esi]GraphicViewPortClass.Height  ; get width into register
   5301 			mov	[ y1_pixel ] , eax
   5302 
   5303 		do_blit:
   5304 
   5305    		    cld
   5306 
   5307    		    mov	eax , [esi]GraphicViewPortClass.XAdd
   5308    		    add	eax , [esi]GraphicViewPortClass.Width
   5309    		    add	eax , [esi]GraphicViewPortClass.Pitch
   5310    		    mov	edi , [esi]GraphicViewPortClass.Offset
   5311 
   5312    		    mov	ecx , eax
   5313    		    mul	[ y_pixel ]
   5314    		    add	edi , [ x_pixel ]
   5315    		    add	edi , eax
   5316 
   5317    		    add	ecx , [ x_pixel ]
   5318    		    sub	ecx , [ x1_pixel ]
   5319    		    mov	[ dest_ajust_width ] , ecx
   5320 
   5321 
   5322    		    mov	esi , [ src ]
   5323    		    mov	eax , [ pixel_width ]
   5324    		    sub	eax , [ x1_pixel ]
   5325    		    add	eax , [ x_pixel ]
   5326    		    mov	[ scr_ajust_width ] , eax
   5327 
   5328    		    mov	eax , [ scr_y ]
   5329    		    mul 	[ pixel_width ]
   5330    		    add	eax , [ scr_x ]
   5331    		    add	esi , eax
   5332 
   5333    		    mov	edx , [ y1_pixel ]
   5334    		    mov	eax , [ x1_pixel ]
   5335 
   5336    		    sub	edx , [ y_pixel ]
   5337    		    jle	real_out
   5338    		    sub	eax , [ x_pixel ]
   5339    		    jle	real_out
   5340 
   5341 
   5342 		; ********************************************************************
   5343 		; Forward bitblit only
   5344 
   5345 		//IF TRANSP
   5346    	//	    test	[ trans ] , 1
   5347    	//	    jnz	forward_Blit_trans
   5348 		//ENDIF
   5349 
   5350 
   5351 		; the inner loop is so efficient that
   5352 		; the optimal consept no longer apply because
   5353 		; the optimal byte have to by a number greather than 9 bytes
   5354    		    cmp	eax , 10
   5355    		    jl	forward_loop_bytes
   5356 
   5357 		forward_loop_dword:
   5358    		    mov	ecx , edi
   5359    		    mov	ebx , eax
   5360    		    neg	ecx
   5361    		    and	ecx , 3
   5362    		    sub	ebx , ecx
   5363    		    rep	movsb
   5364    		    mov	ecx , ebx
   5365    		    shr	ecx , 2
   5366    		    rep	movsd
   5367    		    mov	ecx , ebx
   5368    		    and	ecx , 3
   5369    		    rep	movsb
   5370    		    add	esi , [ scr_ajust_width ]
   5371    		    add	edi , [ dest_ajust_width ]
   5372    		    dec	edx
   5373    		    jnz	forward_loop_dword
   5374    		    jmp	real_out	//ret
   5375 
   5376 		forward_loop_bytes:
   5377    		    mov	ecx , eax
   5378    		    rep	movsb
   5379    		    add	esi , [ scr_ajust_width ]
   5380    		    add	edi , [ dest_ajust_width ]
   5381    		    dec	edx					; decrement the height
   5382    		    jnz	forward_loop_bytes
   5383    		  //  ret
   5384 
   5385 		//IF  TRANSP
   5386 		//
   5387 		//
   5388 		//forward_Blit_trans:
   5389 		//
   5390 		//
   5391    	//	    mov	ecx , eax
   5392    	//	    and	ecx , 01fh
   5393    	//	    lea	ecx , [ ecx + ecx * 4 ]
   5394    	//	    neg	ecx
   5395    	//	    shr	eax , 5
   5396    	//	    lea	ecx , [ transp_reference + ecx * 2 ]
   5397    	//	    mov	[ y1_pixel ] , ecx
   5398 		//
   5399 		//
   5400 		//forward_loop_trans:
   5401    	//	    mov	ecx , eax
   5402    	//	    jmp	[ y1_pixel ]
   5403 		//forward_trans_line:
   5404    	//	    REPT	32
   5405    	//	    local	transp_pixel
   5406    	//	    		mov	bl , [ esi ]
   5407    	//	    		inc	esi
   5408    	//	    		test	bl , bl
   5409    	//	    		jz	transp_pixel
   5410    	//	    		mov	[ edi ] , bl
   5411    	//	 	    transp_pixel:
   5412    	//	    		inc	edi
   5413 		//	ENDM
   5414    	//	 transp_reference:
   5415    	//	    dec	ecx
   5416    	//	    jge	forward_trans_line
   5417    	//	    add	esi , [ scr_ajust_width ]
   5418    	//	    add	edi , [ dest_ajust_width ]
   5419    	//	    dec	edx
   5420    	//	    jnz	forward_loop_trans
   5421    	//	    ret
   5422 		//ENDIF
   5423 
   5424 		real_out:
   5425    		    //ret
   5426 	}
   5427 }
   5428 
   5429 			//ENDP	Buffer_To_Page
   5430 		//END
   5431 
   5432 
   5433 
   5434 
   5435 
   5436 
   5437 
   5438 
   5439 
   5440 /*
   5441 
   5442 ;***************************************************************************
   5443 ;* VVPC::GET_PIXEL -- Gets a pixel from the current view port		   *
   5444 ;*                                                                         *
   5445 ;* INPUT:	WORD the x pixel on the screen.				   *
   5446 ;*		WORD the y pixel on the screen.				   *
   5447 ;*                                                                         *
   5448 ;* OUTPUT:      UBYTE the pixel at the specified location		   *
   5449 ;*                                                                         *
   5450 ;* WARNING:	If pixel is to be placed outside of the viewport then	   *
   5451 ;*		this routine will abort.				   *
   5452 ;*                                                                         *
   5453 ;* HISTORY:                                                                *
   5454 ;*   06/07/1994 PWG : Created.                                             *
   5455 ;*=========================================================================*
   5456 	PROC	Buffer_Get_Pixel C near
   5457 	USES	ebx,ecx,edx,edi
   5458 
   5459 	ARG    	this_object:DWORD				; this is a member function
   5460 	ARG	x_pixel:DWORD				; x position of pixel to set
   5461 	ARG	y_pixel:DWORD				; y position of pixel to set
   5462 */
   5463 
   5464 extern "C" int __cdecl Buffer_Get_Pixel(void * this_object, int x_pixel, int y_pixel)
   5465 {
   5466 	__asm {		  
   5467 
   5468 		;*===================================================================
   5469 		; Get the viewport information and put bytes per row in ecx
   5470 		;*===================================================================
   5471 		mov	ebx,[this_object]				; get a pointer to viewport
   5472 		xor	eax,eax
   5473 		mov	edi,[ebx]GraphicViewPortClass.Offset	; get the correct offset
   5474 		mov	ecx,[ebx]GraphicViewPortClass.Height	; edx = height of viewport
   5475 		mov	edx,[ebx]GraphicViewPortClass.Width	; ecx = width of viewport
   5476 
   5477 		;*===================================================================
   5478 		; Verify that the X pixel offset if legal
   5479 		;*===================================================================
   5480 		mov	eax,[x_pixel]				; find the x position
   5481 		cmp	eax,edx					;   is it out of bounds
   5482 		jae	short exit_label				; if so then get out
   5483 		add	edi,eax					; otherwise add in offset
   5484 
   5485 		;*===================================================================
   5486 		; Verify that the Y pixel offset if legal
   5487 		;*===================================================================
   5488 		mov	eax,[y_pixel]				; get the y position
   5489 		cmp	eax,ecx					;  is it out of bounds
   5490 		jae	exit_label					; if so then get out
   5491 		add	edx,[ebx]GraphicViewPortClass.XAdd	; otherwise find bytes per row
   5492 		add	edx,[ebx]GraphicViewPortClass.Pitch	; otherwise find bytes per row
   5493 		mul	edx					; offset = bytes per row * y
   5494 		add	edi,eax					; add it into the offset
   5495 
   5496 		;*===================================================================
   5497 		; Write the pixel to the screen
   5498 		;*===================================================================
   5499 		xor	eax,eax					; clear the word
   5500 		mov	al,[edi]				; read in the pixel
   5501 	exit_label:
   5502 		//ret
   5503 		//ENDP	Buffer_Get_Pixel
   5504 
   5505 	}
   5506 }
   5507 
   5508