5509 lines
150 KiB
C++
5509 lines
150 KiB
C++
//
|
|
// Copyright 2020 Electronic Arts Inc.
|
|
//
|
|
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
|
|
// software: you can redistribute it and/or modify it under the terms of
|
|
// the GNU General Public License as published by the Free Software Foundation,
|
|
// either version 3 of the License, or (at your option) any later version.
|
|
|
|
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
|
|
// in the hope that it will be useful, but with permitted additional restrictions
|
|
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
|
|
// distributed with this program. You should have received a copy of the
|
|
// GNU General Public License along with permitted additional restrictions
|
|
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
|
|
|
/*
|
|
**
|
|
**
|
|
** Misc asm functions from ww lib
|
|
** ST - 12/19/2018 1:20PM
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
*/
|
|
|
|
#include "gbuffer.h"
|
|
#include "MISC.H"
|
|
#include "WSA.H"
|
|
|
|
IconCacheClass::IconCacheClass (void)
|
|
{
|
|
IsCached =FALSE;
|
|
SurfaceLost =FALSE;
|
|
DrawFrequency =0;
|
|
CacheSurface =NULL;
|
|
IconSource =NULL;
|
|
}
|
|
|
|
IconCacheClass::~IconCacheClass (void)
|
|
{
|
|
}
|
|
|
|
IconCacheClass CachedIcons[MAX_CACHED_ICONS];
|
|
|
|
extern "C"{
|
|
IconSetType IconSetList[MAX_ICON_SETS];
|
|
short IconCacheLookup[MAX_LOOKUP_ENTRIES];
|
|
}
|
|
|
|
int CachedIconsDrawn=0; //Counter of number of cache hits
|
|
int UnCachedIconsDrawn=0; //Counter of number of cache misses
|
|
BOOL CacheMemoryExhausted; //Flag set if we have run out of video RAM
|
|
|
|
|
|
void Invalidate_Cached_Icons (void) {}
|
|
void Restore_Cached_Icons (void) {}
|
|
void Register_Icon_Set (void *icon_data , BOOL pre_cache) {};
|
|
|
|
//
|
|
// Prototypes for assembly language procedures in STMPCACH.ASM
|
|
//
|
|
extern "C" void __cdecl Clear_Icon_Pointers (void) {};
|
|
extern "C" void __cdecl Cache_Copy_Icon (void const *icon_ptr ,void * , int) {};
|
|
extern "C" int __cdecl Is_Icon_Cached (void const *icon_data , int icon) {return -1;};
|
|
extern "C" int __cdecl Get_Icon_Index (void *icon_ptr) {return 0;};
|
|
extern "C" int __cdecl Get_Free_Index (void) {return 0;};
|
|
extern "C" BOOL __cdecl Cache_New_Icon (int icon_index, void *icon_ptr) {return -1;};
|
|
extern "C" int __cdecl Get_Free_Cache_Slot(void) {return -1;}
|
|
|
|
void IconCacheClass::Draw_It (LPDIRECTDRAWSURFACE dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height) {}
|
|
|
|
|
|
|
|
extern int CachedIconsDrawn;
|
|
extern int UnCachedIconsDrawn;
|
|
|
|
|
|
extern "C" void __cdecl Set_Font_Palette_Range(void const *palette, INT start_idx, INT end_idx)
|
|
{
|
|
}
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *
|
|
;* *
|
|
;* INPUT: WORD sx_pixel - the starting x pixel position *
|
|
;* WORD sy_pixel - the starting y pixel position *
|
|
;* WORD dx_pixel - the destination x pixel position *
|
|
;* WORD dy_pixel - the destination y pixel position *
|
|
;* WORD color - the color of the line to draw *
|
|
;* *
|
|
;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel *
|
|
;* with the graphic viewport it has been assigned to. *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 06/16/1994 PWG : Created. *
|
|
;* 08/30/1994 IML : Fixed clipping bug. *
|
|
;*=========================================================================*
|
|
PROC Buffer_Draw_Line C NEAR
|
|
USES eax,ebx,ecx,edx,esi,edi
|
|
*/
|
|
|
|
void __cdecl Buffer_Draw_Line(void *this_object, int sx, int sy, int dx, int dy, unsigned char color)
|
|
{
|
|
unsigned int clip_min_x;
|
|
unsigned int clip_max_x;
|
|
unsigned int clip_min_y;
|
|
unsigned int clip_max_y;
|
|
unsigned int clip_var;
|
|
unsigned int accum;
|
|
unsigned int bpr;
|
|
|
|
static int _one_time_init = 0;
|
|
|
|
//clip_tbl DD nada,a_up,a_dwn,nada
|
|
// DD a_lft,a_lft,a_dwn,nada
|
|
// DD a_rgt,a_up,a_rgt,nada
|
|
// DD nada,nada,nada,nada
|
|
|
|
static void *_clip_table [4*4] = {0};
|
|
|
|
unsigned int int_color = color;
|
|
unsigned int x1_pixel = (unsigned int) sx;
|
|
unsigned int y1_pixel = (unsigned int) sy;
|
|
unsigned int x2_pixel = (unsigned int) dx;
|
|
unsigned int y2_pixel = (unsigned int) dy;
|
|
|
|
__asm {
|
|
mov eax,_one_time_init
|
|
and eax,eax
|
|
jnz init_done
|
|
|
|
call do_init
|
|
|
|
init_done:
|
|
|
|
//;*==================================================================
|
|
//;* Take care of find the clip minimum and maximums
|
|
//;*==================================================================
|
|
mov ebx,[this_object]
|
|
xor eax,eax
|
|
mov [clip_min_x],eax
|
|
mov [clip_min_y],eax
|
|
mov eax,[ebx]GraphicViewPortClass.Width
|
|
mov [clip_max_x],eax
|
|
add eax,[ebx]GraphicViewPortClass.XAdd
|
|
add eax,[ebx]GraphicViewPortClass.Pitch
|
|
mov [bpr],eax
|
|
mov eax,[ebx]GraphicViewPortClass.Height
|
|
mov [clip_max_y],eax
|
|
|
|
//;*==================================================================
|
|
//;* Adjust max pixels as they are tested inclusively.
|
|
//;*==================================================================
|
|
dec [clip_max_x]
|
|
dec [clip_max_y]
|
|
|
|
//;*==================================================================
|
|
//;* Set the registers with the data for drawing the line
|
|
//;*==================================================================
|
|
mov eax,[x1_pixel] //; eax = start x pixel position
|
|
mov ebx,[y1_pixel] //; ebx = start y pixel position
|
|
mov ecx,[x2_pixel] //; ecx = dest x pixel position
|
|
mov edx,[y2_pixel] //; edx = dest y pixel position
|
|
|
|
//;*==================================================================
|
|
//;* This is the section that "pushes" the line into bounds.
|
|
//;* I have marked the section with PORTABLE start and end to signify
|
|
//;* how much of this routine is 100% portable between graphics modes.
|
|
//;* It was just as easy to have variables as it would be for constants
|
|
//;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used
|
|
//;* to clip the line (default is the screen)
|
|
//;* PORTABLE start
|
|
//;*==================================================================
|
|
|
|
cmp eax,[clip_min_x]
|
|
jl short clip_it
|
|
cmp eax,[clip_max_x]
|
|
jg short clip_it
|
|
cmp ebx,[clip_min_y]
|
|
jl short clip_it
|
|
cmp ebx,[clip_max_y]
|
|
jg short clip_it
|
|
cmp ecx,[clip_min_x]
|
|
jl short clip_it
|
|
cmp ecx,[clip_max_x]
|
|
jg short clip_it
|
|
cmp edx,[clip_min_y]
|
|
jl short clip_it
|
|
cmp edx,[clip_max_y]
|
|
jle short on_screen
|
|
|
|
//;*==================================================================
|
|
//;* Takes care off clipping the line.
|
|
//;*==================================================================
|
|
clip_it:
|
|
call set_bits
|
|
xchg eax,ecx
|
|
xchg ebx,edx
|
|
mov edi,esi
|
|
call set_bits
|
|
mov [clip_var],edi
|
|
or [clip_var],esi
|
|
jz short on_screen
|
|
test edi,esi
|
|
jne short off_screen
|
|
shl esi,2
|
|
//call [clip_tbl+esi]
|
|
call [_clip_table+esi]
|
|
jc clip_it
|
|
xchg eax,ecx
|
|
xchg ebx,edx
|
|
shl edi,2
|
|
//call [clip_tbl+edi]
|
|
call [_clip_table+edi]
|
|
jmp clip_it
|
|
|
|
on_screen:
|
|
jmp draw_it
|
|
|
|
off_screen:
|
|
jmp and_out
|
|
|
|
//;*==================================================================
|
|
//;* Jump table for clipping conditions
|
|
//;*==================================================================
|
|
//clip_tbl DD nada,a_up,a_dwn,nada
|
|
// DD a_lft,a_lft,a_dwn,nada
|
|
// DD a_rgt,a_up,a_rgt,nada
|
|
// DD nada,nada,nada,nada
|
|
|
|
nada:
|
|
clc
|
|
ret
|
|
|
|
a_up:
|
|
mov esi,[clip_min_y]
|
|
call clip_vert
|
|
stc
|
|
ret
|
|
|
|
a_dwn:
|
|
mov esi,[clip_max_y]
|
|
neg esi
|
|
neg ebx
|
|
neg edx
|
|
call clip_vert
|
|
neg ebx
|
|
neg edx
|
|
stc
|
|
ret
|
|
|
|
//;*==================================================================
|
|
//;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]
|
|
//;*==================================================================
|
|
clip_vert:
|
|
push edx
|
|
push eax
|
|
mov [clip_var],edx //; clip_var = yb
|
|
sub [clip_var],ebx //; clip_var = (yb-ya)
|
|
neg eax //; eax=-xa
|
|
add eax,ecx //; (ebx-xa)
|
|
mov edx,esi //; edx=miny
|
|
sub edx,ebx //; edx=(miny-ya)
|
|
imul edx
|
|
idiv [clip_var]
|
|
pop edx
|
|
add eax,edx
|
|
pop edx
|
|
mov ebx,esi
|
|
ret
|
|
|
|
a_lft:
|
|
mov esi,[clip_min_x]
|
|
call clip_horiz
|
|
stc
|
|
ret
|
|
|
|
a_rgt:
|
|
mov esi,[clip_max_x]
|
|
neg eax
|
|
neg ecx
|
|
neg esi
|
|
call clip_horiz
|
|
neg eax
|
|
neg ecx
|
|
stc
|
|
ret
|
|
|
|
//;*==================================================================
|
|
//;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]
|
|
//;*==================================================================
|
|
clip_horiz:
|
|
push edx
|
|
mov [clip_var],ecx //; clip_var = xb
|
|
sub [clip_var],eax //; clip_var = (xb-xa)
|
|
sub edx,ebx //; edx = (yb-ya)
|
|
neg eax //; eax = -xa
|
|
add eax,esi //; eax = (minx-xa)
|
|
imul edx //; eax = (minx-xa)(yb-ya)
|
|
idiv [clip_var] //; eax = (minx-xa)(yb-ya)/(xb-xa)
|
|
add ebx,eax //; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]
|
|
pop edx
|
|
mov eax,esi
|
|
ret
|
|
|
|
//;*==================================================================
|
|
//;* Sets the condition bits
|
|
//;*==================================================================
|
|
set_bits:
|
|
xor esi,esi
|
|
cmp ebx,[clip_min_y] //; if y >= top its not up
|
|
jge short a_not_up
|
|
or esi,1
|
|
|
|
a_not_up:
|
|
cmp ebx,[clip_max_y] //; if y <= bottom its not down
|
|
jle short a_not_down
|
|
or esi,2
|
|
|
|
a_not_down:
|
|
cmp eax,[clip_min_x] //; if x >= left its not left
|
|
jge short a_not_left
|
|
or esi,4
|
|
|
|
a_not_left:
|
|
cmp eax,[clip_max_x] //; if x <= right its not right
|
|
jle short a_not_right
|
|
or esi,8
|
|
|
|
a_not_right:
|
|
ret
|
|
|
|
//;*==================================================================
|
|
//;* Draw the line to the screen.
|
|
//;* PORTABLE end
|
|
//;*==================================================================
|
|
draw_it:
|
|
sub edx,ebx //; see if line is being draw down
|
|
jnz short not_hline //; if not then its not a hline
|
|
jmp short hline //; do special case h line
|
|
|
|
not_hline:
|
|
jg short down //; if so there is no need to rev it
|
|
neg edx //; negate for actual pixel length
|
|
xchg eax,ecx //; swap x's to rev line draw
|
|
sub ebx,edx //; get old edx
|
|
|
|
down:
|
|
push edx
|
|
push eax
|
|
mov eax,[bpr]
|
|
mul ebx
|
|
mov ebx,eax
|
|
mov eax,[this_object]
|
|
add ebx,[eax]GraphicViewPortClass.Offset
|
|
pop eax
|
|
pop edx
|
|
|
|
mov esi,1 //; assume a right mover
|
|
sub ecx,eax //; see if line is right
|
|
jnz short not_vline //; see if its a vertical line
|
|
jmp vline
|
|
|
|
not_vline:
|
|
jg short right //; if so, the difference = length
|
|
|
|
//left:
|
|
neg ecx //; else negate for actual pixel length
|
|
neg esi //; negate counter to move left
|
|
|
|
right:
|
|
cmp ecx,edx //; is it a horiz or vert line
|
|
jge short horiz //; if ecx > edx then |x|>|y| or horiz
|
|
|
|
//vert:
|
|
xchg ecx,edx //; make ecx greater and edx lesser
|
|
mov edi,ecx //; set greater
|
|
mov [accum],ecx //; set accumulator to 1/2 greater
|
|
shr [accum],1
|
|
|
|
//;*==================================================================
|
|
//;* at this point ...
|
|
//;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
|
|
//;* esi=adder; accum=accumulator
|
|
//;* in a vertical loop the adder is conditional and the inc constant
|
|
//;*==================================================================
|
|
//vert_loop:
|
|
add ebx,eax
|
|
mov eax,[int_color]
|
|
|
|
v_midloop:
|
|
mov [ebx],al
|
|
dec ecx
|
|
jl and_out
|
|
add ebx,[bpr]
|
|
sub [accum],edx //; sub the lesser
|
|
jge v_midloop //; any line could be new
|
|
add [accum],edi //; add greater for new accum
|
|
add ebx,esi //; next pixel over
|
|
jmp v_midloop
|
|
|
|
horiz:
|
|
mov edi,ecx //; set greater
|
|
mov [accum],ecx //; set accumulator to 1/2 greater
|
|
shr [accum],1
|
|
|
|
//;*==================================================================
|
|
//;* at this point ...
|
|
//;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
|
|
//;* esi=adder; accum=accumulator
|
|
//;* in a vertical loop the adder is conditional and the inc constant
|
|
//;*==================================================================
|
|
//horiz_loop:
|
|
add ebx,eax
|
|
mov eax,[int_color]
|
|
|
|
h_midloop:
|
|
mov [ebx],al
|
|
dec ecx //; dec counter
|
|
jl and_out //; end of line
|
|
add ebx,esi
|
|
sub [accum],edx //; sub the lesser
|
|
jge h_midloop
|
|
add [accum],edi //; add greater for new accum
|
|
add ebx,[bpr] //; goto next line
|
|
jmp h_midloop
|
|
|
|
//;*==================================================================
|
|
//;* Special case routine for horizontal line draws
|
|
//;*==================================================================
|
|
hline:
|
|
cmp eax,ecx //; make eax < ecx
|
|
jl short hl_ac
|
|
xchg eax,ecx
|
|
|
|
hl_ac:
|
|
sub ecx,eax //; get len
|
|
inc ecx
|
|
|
|
push edx
|
|
push eax
|
|
mov eax,[bpr]
|
|
mul ebx
|
|
mov ebx,eax
|
|
mov eax,[this_object]
|
|
add ebx,[eax]GraphicViewPortClass.Offset
|
|
pop eax
|
|
pop edx
|
|
add ebx,eax
|
|
mov edi,ebx
|
|
cmp ecx,15
|
|
jg big_line
|
|
mov al,[color]
|
|
rep stosb //; write as many words as possible
|
|
jmp short and_out //; get outt
|
|
|
|
|
|
big_line:
|
|
mov al,[color]
|
|
mov ah,al
|
|
mov ebx,eax
|
|
shl eax,16
|
|
mov ax,bx
|
|
test edi,3
|
|
jz aligned
|
|
mov [edi],al
|
|
inc edi
|
|
dec ecx
|
|
test edi,3
|
|
jz aligned
|
|
mov [edi],al
|
|
inc edi
|
|
dec ecx
|
|
test edi,3
|
|
jz aligned
|
|
mov [edi],al
|
|
inc edi
|
|
dec ecx
|
|
|
|
aligned:
|
|
mov ebx,ecx
|
|
shr ecx,2
|
|
rep stosd
|
|
mov ecx,ebx
|
|
and ecx,3
|
|
rep stosb
|
|
jmp and_out
|
|
|
|
|
|
//;*==================================================================
|
|
//;* a special case routine for vertical line draws
|
|
//;*==================================================================
|
|
vline:
|
|
mov ecx,edx //; get length of line to draw
|
|
inc ecx
|
|
add ebx,eax
|
|
mov eax,[int_color]
|
|
|
|
vl_loop:
|
|
mov [ebx],al //; store bit
|
|
add ebx,[bpr]
|
|
dec ecx
|
|
jnz vl_loop
|
|
jmp and_out
|
|
|
|
|
|
do_init:
|
|
mov edi, offset _clip_table
|
|
|
|
lea esi, nada
|
|
mov [edi], esi
|
|
mov [edi+12], esi
|
|
lea esi, a_up
|
|
mov [edi+4], esi
|
|
lea esi, a_dwn
|
|
mov [edi+8], esi
|
|
|
|
add edi, 16
|
|
|
|
lea esi, a_lft
|
|
mov [edi], esi
|
|
mov [edi+4], esi
|
|
lea esi, a_dwn
|
|
mov [edi+8], esi
|
|
lea esi, nada
|
|
mov [edi+12], esi
|
|
|
|
add edi, 16
|
|
|
|
lea esi, a_rgt
|
|
mov [edi], esi
|
|
mov [edi+8], esi
|
|
lea esi, a_up
|
|
mov [edi+4], esi
|
|
lea esi, nada
|
|
mov [edi+12], esi
|
|
|
|
add edi, 16
|
|
|
|
lea esi, nada
|
|
mov [edi], esi
|
|
mov [edi+4], esi
|
|
mov [edi+8], esi
|
|
mov [edi+12], esi
|
|
|
|
mov [_one_time_init], 1
|
|
ret
|
|
|
|
and_out:
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
|
|
;***************************************************************************
|
|
;* *
|
|
;* Project Name : Westwood 32 bit Library *
|
|
;* *
|
|
;* File Name : DRAWLINE.ASM *
|
|
;* *
|
|
;* Programmer : Phil W. Gorrow *
|
|
;* *
|
|
;* Start Date : June 16, 1994 *
|
|
;* *
|
|
;* Last Update : August 30, 1994 [IML] *
|
|
;* *
|
|
;*-------------------------------------------------------------------------*
|
|
;* Functions: *
|
|
;* VVC::Scale -- Scales a virtual viewport to another virtual viewport *
|
|
;* Normal_Draw -- jump loc for drawing scaled line of normal pixel *
|
|
;* __DRAW_LINE -- Assembly routine to draw a line *
|
|
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
|
|
|
IDEAL
|
|
P386
|
|
MODEL USE32 FLAT
|
|
|
|
INCLUDE ".\drawbuff.inc"
|
|
INCLUDE ".\gbuffer.inc"
|
|
|
|
|
|
CODESEG
|
|
*/
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *
|
|
;* *
|
|
;* INPUT: WORD sx_pixel - the starting x pixel position *
|
|
;* WORD sy_pixel - the starting y pixel position *
|
|
;* WORD dx_pixel - the destination x pixel position *
|
|
;* WORD dy_pixel - the destination y pixel position *
|
|
;* WORD color - the color of the line to draw *
|
|
;* *
|
|
;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel *
|
|
;* with the graphic viewport it has been assigned to. *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 06/16/1994 PWG : Created. *
|
|
;* 08/30/1994 IML : Fixed clipping bug. *
|
|
;*=========================================================================*
|
|
PROC Buffer_Draw_Line C NEAR
|
|
USES eax,ebx,ecx,edx,esi,edi
|
|
|
|
;*==================================================================
|
|
;* Define the arguements that the function takes.
|
|
;*==================================================================
|
|
ARG this_object:DWORD ; associated graphic view port
|
|
ARG x1_pixel:DWORD ; the start x pixel position
|
|
ARG y1_pixel:DWORD ; the start y pixel position
|
|
ARG x2_pixel:DWORD ; the dest x pixel position
|
|
ARG y2_pixel:DWORD ; the dest y pixel position
|
|
ARG color:DWORD ; the color we are drawing
|
|
|
|
;*==================================================================
|
|
;* Define the local variables that we will use on the stack
|
|
;*==================================================================
|
|
LOCAL clip_min_x:DWORD
|
|
LOCAL clip_max_x:DWORD
|
|
LOCAL clip_min_y:DWORD
|
|
LOCAL clip_max_y:DWORD
|
|
LOCAL clip_var:DWORD
|
|
LOCAL accum:DWORD
|
|
LOCAL bpr:DWORD
|
|
|
|
;*==================================================================
|
|
;* Take care of find the clip minimum and maximums
|
|
;*==================================================================
|
|
mov ebx,[this_object]
|
|
xor eax,eax
|
|
mov [clip_min_x],eax
|
|
mov [clip_min_y],eax
|
|
mov eax,[(GraphicViewPort ebx).GVPWidth]
|
|
mov [clip_max_x],eax
|
|
add eax,[(GraphicViewPort ebx).GVPXAdd]
|
|
add eax,[(GraphicViewPort ebx).GVPPitch]
|
|
mov [bpr],eax
|
|
mov eax,[(GraphicViewPort ebx).GVPHeight]
|
|
mov [clip_max_y],eax
|
|
|
|
;*==================================================================
|
|
;* Adjust max pixels as they are tested inclusively.
|
|
;*==================================================================
|
|
dec [clip_max_x]
|
|
dec [clip_max_y]
|
|
|
|
;*==================================================================
|
|
;* Set the registers with the data for drawing the line
|
|
;*==================================================================
|
|
mov eax,[x1_pixel] ; eax = start x pixel position
|
|
mov ebx,[y1_pixel] ; ebx = start y pixel position
|
|
mov ecx,[x2_pixel] ; ecx = dest x pixel position
|
|
mov edx,[y2_pixel] ; edx = dest y pixel position
|
|
|
|
;*==================================================================
|
|
;* This is the section that "pushes" the line into bounds.
|
|
;* I have marked the section with PORTABLE start and end to signify
|
|
;* how much of this routine is 100% portable between graphics modes.
|
|
;* It was just as easy to have variables as it would be for constants
|
|
;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used
|
|
;* to clip the line (default is the screen)
|
|
;* PORTABLE start
|
|
;*==================================================================
|
|
|
|
cmp eax,[clip_min_x]
|
|
jl short ??clip_it
|
|
cmp eax,[clip_max_x]
|
|
jg short ??clip_it
|
|
cmp ebx,[clip_min_y]
|
|
jl short ??clip_it
|
|
cmp ebx,[clip_max_y]
|
|
jg short ??clip_it
|
|
cmp ecx,[clip_min_x]
|
|
jl short ??clip_it
|
|
cmp ecx,[clip_max_x]
|
|
jg short ??clip_it
|
|
cmp edx,[clip_min_y]
|
|
jl short ??clip_it
|
|
cmp edx,[clip_max_y]
|
|
jle short ??on_screen
|
|
|
|
;*==================================================================
|
|
;* Takes care off clipping the line.
|
|
;*==================================================================
|
|
??clip_it:
|
|
call NEAR PTR ??set_bits
|
|
xchg eax,ecx
|
|
xchg ebx,edx
|
|
mov edi,esi
|
|
call NEAR PTR ??set_bits
|
|
mov [clip_var],edi
|
|
or [clip_var],esi
|
|
jz short ??on_screen
|
|
test edi,esi
|
|
jne short ??off_screen
|
|
shl esi,2
|
|
call [DWORD PTR cs:??clip_tbl+esi]
|
|
jc ??clip_it
|
|
xchg eax,ecx
|
|
xchg ebx,edx
|
|
shl edi,2
|
|
call [DWORD PTR cs:??clip_tbl+edi]
|
|
jmp ??clip_it
|
|
|
|
??on_screen:
|
|
jmp ??draw_it
|
|
|
|
??off_screen:
|
|
jmp ??out
|
|
|
|
;*==================================================================
|
|
;* Jump table for clipping conditions
|
|
;*==================================================================
|
|
??clip_tbl DD ??nada,??a_up,??a_dwn,??nada
|
|
DD ??a_lft,??a_lft,??a_dwn,??nada
|
|
DD ??a_rgt,??a_up,??a_rgt,??nada
|
|
DD ??nada,??nada,??nada,??nada
|
|
|
|
??nada:
|
|
clc
|
|
retn
|
|
|
|
??a_up:
|
|
mov esi,[clip_min_y]
|
|
call NEAR PTR ??clip_vert
|
|
stc
|
|
retn
|
|
|
|
??a_dwn:
|
|
mov esi,[clip_max_y]
|
|
neg esi
|
|
neg ebx
|
|
neg edx
|
|
call NEAR PTR ??clip_vert
|
|
neg ebx
|
|
neg edx
|
|
stc
|
|
retn
|
|
|
|
;*==================================================================
|
|
;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]
|
|
;*==================================================================
|
|
??clip_vert:
|
|
push edx
|
|
push eax
|
|
mov [clip_var],edx ; clip_var = yb
|
|
sub [clip_var],ebx ; clip_var = (yb-ya)
|
|
neg eax ; eax=-xa
|
|
add eax,ecx ; (ebx-xa)
|
|
mov edx,esi ; edx=miny
|
|
sub edx,ebx ; edx=(miny-ya)
|
|
imul edx
|
|
idiv [clip_var]
|
|
pop edx
|
|
add eax,edx
|
|
pop edx
|
|
mov ebx,esi
|
|
retn
|
|
|
|
??a_lft:
|
|
mov esi,[clip_min_x]
|
|
call NEAR PTR ??clip_horiz
|
|
stc
|
|
retn
|
|
|
|
??a_rgt:
|
|
mov esi,[clip_max_x]
|
|
neg eax
|
|
neg ecx
|
|
neg esi
|
|
call NEAR PTR ??clip_horiz
|
|
neg eax
|
|
neg ecx
|
|
stc
|
|
retn
|
|
|
|
;*==================================================================
|
|
;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]
|
|
;*==================================================================
|
|
??clip_horiz:
|
|
push edx
|
|
mov [clip_var],ecx ; clip_var = xb
|
|
sub [clip_var],eax ; clip_var = (xb-xa)
|
|
sub edx,ebx ; edx = (yb-ya)
|
|
neg eax ; eax = -xa
|
|
add eax,esi ; eax = (minx-xa)
|
|
imul edx ; eax = (minx-xa)(yb-ya)
|
|
idiv [clip_var] ; eax = (minx-xa)(yb-ya)/(xb-xa)
|
|
add ebx,eax ; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]
|
|
pop edx
|
|
mov eax,esi
|
|
retn
|
|
|
|
;*==================================================================
|
|
;* Sets the condition bits
|
|
;*==================================================================
|
|
??set_bits:
|
|
xor esi,esi
|
|
cmp ebx,[clip_min_y] ; if y >= top its not up
|
|
jge short ??a_not_up
|
|
or esi,1
|
|
|
|
??a_not_up:
|
|
cmp ebx,[clip_max_y] ; if y <= bottom its not down
|
|
jle short ??a_not_down
|
|
or esi,2
|
|
|
|
??a_not_down:
|
|
cmp eax,[clip_min_x] ; if x >= left its not left
|
|
jge short ??a_not_left
|
|
or esi,4
|
|
|
|
??a_not_left:
|
|
cmp eax,[clip_max_x] ; if x <= right its not right
|
|
jle short ??a_not_right
|
|
or esi,8
|
|
|
|
??a_not_right:
|
|
retn
|
|
|
|
;*==================================================================
|
|
;* Draw the line to the screen.
|
|
;* PORTABLE end
|
|
;*==================================================================
|
|
??draw_it:
|
|
sub edx,ebx ; see if line is being draw down
|
|
jnz short ??not_hline ; if not then its not a hline
|
|
jmp short ??hline ; do special case h line
|
|
|
|
??not_hline:
|
|
jg short ??down ; if so there is no need to rev it
|
|
neg edx ; negate for actual pixel length
|
|
xchg eax,ecx ; swap x's to rev line draw
|
|
sub ebx,edx ; get old edx
|
|
|
|
??down:
|
|
push edx
|
|
push eax
|
|
mov eax,[bpr]
|
|
mul ebx
|
|
mov ebx,eax
|
|
mov eax,[this_object]
|
|
add ebx,[(GraphicViewPort eax).GVPOffset]
|
|
pop eax
|
|
pop edx
|
|
|
|
mov esi,1 ; assume a right mover
|
|
sub ecx,eax ; see if line is right
|
|
jnz short ??not_vline ; see if its a vertical line
|
|
jmp ??vline
|
|
|
|
??not_vline:
|
|
jg short ??right ; if so, the difference = length
|
|
|
|
??left:
|
|
neg ecx ; else negate for actual pixel length
|
|
neg esi ; negate counter to move left
|
|
|
|
??right:
|
|
cmp ecx,edx ; is it a horiz or vert line
|
|
jge short ??horiz ; if ecx > edx then |x|>|y| or horiz
|
|
|
|
??vert:
|
|
xchg ecx,edx ; make ecx greater and edx lesser
|
|
mov edi,ecx ; set greater
|
|
mov [accum],ecx ; set accumulator to 1/2 greater
|
|
shr [accum],1
|
|
|
|
;*==================================================================
|
|
;* at this point ...
|
|
;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
|
|
;* esi=adder; accum=accumulator
|
|
;* in a vertical loop the adder is conditional and the inc constant
|
|
;*==================================================================
|
|
??vert_loop:
|
|
add ebx,eax
|
|
mov eax,[color]
|
|
|
|
??v_midloop:
|
|
mov [ebx],al
|
|
dec ecx
|
|
jl ??out
|
|
add ebx,[bpr]
|
|
sub [accum],edx ; sub the lesser
|
|
jge ??v_midloop ; any line could be new
|
|
add [accum],edi ; add greater for new accum
|
|
add ebx,esi ; next pixel over
|
|
jmp ??v_midloop
|
|
|
|
??horiz:
|
|
mov edi,ecx ; set greater
|
|
mov [accum],ecx ; set accumulator to 1/2 greater
|
|
shr [accum],1
|
|
|
|
;*==================================================================
|
|
;* at this point ...
|
|
;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
|
|
;* esi=adder; accum=accumulator
|
|
;* in a vertical loop the adder is conditional and the inc constant
|
|
;*==================================================================
|
|
??horiz_loop:
|
|
add ebx,eax
|
|
mov eax,[color]
|
|
|
|
??h_midloop:
|
|
mov [ebx],al
|
|
dec ecx ; dec counter
|
|
jl ??out ; end of line
|
|
add ebx,esi
|
|
sub [accum],edx ; sub the lesser
|
|
jge ??h_midloop
|
|
add [accum],edi ; add greater for new accum
|
|
add ebx,[bpr] ; goto next line
|
|
jmp ??h_midloop
|
|
|
|
;*==================================================================
|
|
;* Special case routine for horizontal line draws
|
|
;*==================================================================
|
|
??hline:
|
|
cmp eax,ecx ; make eax < ecx
|
|
jl short ??hl_ac
|
|
xchg eax,ecx
|
|
|
|
??hl_ac:
|
|
sub ecx,eax ; get len
|
|
inc ecx
|
|
|
|
push edx
|
|
push eax
|
|
mov eax,[bpr]
|
|
mul ebx
|
|
mov ebx,eax
|
|
mov eax,[this_object]
|
|
add ebx,[(GraphicViewPort eax).GVPOffset]
|
|
pop eax
|
|
pop edx
|
|
add ebx,eax
|
|
mov edi,ebx
|
|
cmp ecx,15
|
|
jg ??big_line
|
|
mov al,[byte color]
|
|
rep stosb ; write as many words as possible
|
|
jmp short ??out ; get outt
|
|
|
|
|
|
??big_line:
|
|
mov al,[byte color]
|
|
mov ah,al
|
|
mov ebx,eax
|
|
shl eax,16
|
|
mov ax,bx
|
|
test edi,3
|
|
jz ??aligned
|
|
mov [edi],al
|
|
inc edi
|
|
dec ecx
|
|
test edi,3
|
|
jz ??aligned
|
|
mov [edi],al
|
|
inc edi
|
|
dec ecx
|
|
test edi,3
|
|
jz ??aligned
|
|
mov [edi],al
|
|
inc edi
|
|
dec ecx
|
|
|
|
??aligned:
|
|
mov ebx,ecx
|
|
shr ecx,2
|
|
rep stosd
|
|
mov ecx,ebx
|
|
and ecx,3
|
|
rep stosb
|
|
jmp ??out
|
|
|
|
|
|
;*==================================================================
|
|
;* a special case routine for vertical line draws
|
|
;*==================================================================
|
|
??vline:
|
|
mov ecx,edx ; get length of line to draw
|
|
inc ecx
|
|
add ebx,eax
|
|
mov eax,[color]
|
|
|
|
??vl_loop:
|
|
mov [ebx],al ; store bit
|
|
add ebx,[bpr]
|
|
dec ecx
|
|
jnz ??vl_loop
|
|
|
|
??out:
|
|
ret
|
|
ENDP Buffer_Draw_Line
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
;***************************************************************************
|
|
;* GVPC::FILL_RECT -- Fills a rectangular region of a graphic view port *
|
|
;* *
|
|
;* INPUT: WORD the left hand x pixel position of region *
|
|
;* WORD the upper x pixel position of region *
|
|
;* WORD the right hand x pixel position of region *
|
|
;* WORD the lower x pixel position of region *
|
|
;* UBYTE the color (optional) to clear the view port to *
|
|
;* *
|
|
;* OUTPUT: none *
|
|
;* *
|
|
;* NOTE: This function is optimized to handle viewport with no XAdd *
|
|
;* value. It also handles DWORD aligning the destination *
|
|
;* when speed can be gained by doing it. *
|
|
;* HISTORY: *
|
|
;* 06/07/1994 PWG : Created. *
|
|
;*=========================================================================*
|
|
*/
|
|
|
|
/*
|
|
;******************************************************************************
|
|
; Much testing was done to determine that only when there are 14 or more bytes
|
|
; being copied does it speed the time it takes to do copies in this algorithm.
|
|
; For this reason and because 1 and 2 byte copies crash, is the special case
|
|
; used. SKB 4/21/94. Tested on 486 66mhz. Copied by PWG 6/7/04.
|
|
*/
|
|
#define OPTIMAL_BYTE_COPY 14
|
|
|
|
|
|
void __cdecl Buffer_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color)
|
|
{
|
|
/*
|
|
;*===================================================================
|
|
;* define the arguements that our function takes.
|
|
;*===================================================================
|
|
ARG this_object:DWORD ; this is a member function
|
|
ARG x1_pixel:WORD
|
|
ARG y1_pixel:WORD
|
|
ARG x2_pixel:WORD
|
|
ARG y2_pixel:WORD
|
|
ARG color:BYTE ; what color should we clear to
|
|
*/
|
|
|
|
void *this_object = thisptr;
|
|
int x1_pixel = sx;
|
|
int y1_pixel = sy;
|
|
int x2_pixel = dx;
|
|
int y2_pixel = dy;
|
|
|
|
/*
|
|
;*===================================================================
|
|
; Define some locals so that we can handle things quickly
|
|
;*===================================================================
|
|
LOCAL VPwidth:DWORD ; the width of the viewport
|
|
LOCAL VPheight:DWORD ; the height of the viewport
|
|
LOCAL VPxadd:DWORD ; the additional x offset of viewport
|
|
LOCAL VPbpr:DWORD ; the number of bytes per row of viewport
|
|
*/
|
|
|
|
int VPwidth;
|
|
int VPheight;
|
|
int VPxadd;
|
|
int VPbpr;
|
|
|
|
int local_ebp; // Can't use ebp
|
|
|
|
__asm {
|
|
|
|
;*===================================================================
|
|
;* save off the viewport characteristics on the stack
|
|
;*===================================================================
|
|
mov ebx,[this_object] ; get a pointer to viewport
|
|
mov eax,[ebx]GraphicViewPortClass.Width ; get width from viewport
|
|
mov ecx,[ebx]GraphicViewPortClass.Height ; get height from viewport
|
|
mov edx,[ebx]GraphicViewPortClass.XAdd ; get xadd from viewport
|
|
add edx,[ebx]GraphicViewPortClass.Pitch ; extra pitch of direct draw surface
|
|
mov [VPwidth],eax ; store the width of locally
|
|
mov [VPheight],ecx
|
|
mov [VPxadd],edx
|
|
add eax,edx
|
|
mov [VPbpr],eax
|
|
|
|
;*===================================================================
|
|
;* move the important parameters into local registers
|
|
;*===================================================================
|
|
mov eax,[x1_pixel]
|
|
mov ebx,[y1_pixel]
|
|
mov ecx,[x2_pixel]
|
|
mov edx,[y2_pixel]
|
|
|
|
;*===================================================================
|
|
;* Convert the x2 and y2 pixel to a width and height
|
|
;*===================================================================
|
|
cmp eax,ecx
|
|
jl no_swap_x
|
|
xchg eax,ecx
|
|
|
|
no_swap_x:
|
|
sub ecx,eax
|
|
cmp ebx,edx
|
|
jl no_swap_y
|
|
xchg ebx,edx
|
|
no_swap_y:
|
|
sub edx,ebx
|
|
inc ecx
|
|
inc edx
|
|
|
|
;*===================================================================
|
|
;* Bounds check source X.
|
|
;*===================================================================
|
|
cmp eax, [VPwidth] ; compare with the max
|
|
jge done ; starts off screen, then later
|
|
jb short sx_done ; if it's not negative, it's ok
|
|
|
|
;------ Clip source X to left edge of screen.
|
|
add ecx, eax ; Reduce width (add in negative src X).
|
|
xor eax, eax ; Clip to left of screen.
|
|
sx_done:
|
|
|
|
;*===================================================================
|
|
;* Bounds check source Y.
|
|
;*===================================================================
|
|
cmp ebx, [VPheight] ; compare with the max
|
|
jge done ; starts off screen, then later
|
|
jb short sy_done ; if it's not negative, it's ok
|
|
|
|
;------ Clip source Y to top edge of screen.
|
|
add edx, ebx ; Reduce height (add in negative src Y).
|
|
xor ebx, ebx ; Clip to top of screen.
|
|
|
|
sy_done:
|
|
;*===================================================================
|
|
;* Bounds check width versus width of source and dest view ports
|
|
;*===================================================================
|
|
push ebx ; save off ebx for later use
|
|
mov ebx,[VPwidth] ; get the source width
|
|
sub ebx, eax ; Maximum allowed pixel width (given coordinates).
|
|
sub ebx, ecx ; Pixel width undershoot.
|
|
jns short width_ok ; if not signed no adjustment necessary
|
|
add ecx, ebx ; Reduce width to screen limits.
|
|
|
|
width_ok:
|
|
pop ebx ; restore ebx to old value
|
|
|
|
;*===================================================================
|
|
;* Bounds check height versus height of source view port
|
|
;*===================================================================
|
|
push eax ; save of eax for later use
|
|
mov eax, [VPheight] ; get the source height
|
|
sub eax, ebx ; Maximum allowed pixel height (given coordinates).
|
|
sub eax, edx ; Pixel height undershoot.
|
|
jns short height_ok ; if not signed no adjustment necessary
|
|
add edx, eax ; Reduce height to screen limits.
|
|
height_ok:
|
|
pop eax ; restore eax to old value
|
|
|
|
;*===================================================================
|
|
;* Perform the last minute checks on the width and height
|
|
;*===================================================================
|
|
or ecx,ecx
|
|
jz done
|
|
|
|
or edx,edx
|
|
jz done
|
|
|
|
cmp ecx,[VPwidth]
|
|
ja done
|
|
cmp edx,[VPheight]
|
|
ja done
|
|
|
|
;*===================================================================
|
|
;* Get the offset into the virtual viewport.
|
|
;*===================================================================
|
|
xchg edi,eax ; save off the contents of eax
|
|
xchg esi,edx ; and edx for size test
|
|
mov eax,ebx ; move the y pixel into eax
|
|
mul [VPbpr] ; multiply by bytes per row
|
|
add edi,eax ; add the result into the x position
|
|
mov ebx,[this_object]
|
|
add edi,[ebx]GraphicViewPortClass.Offset
|
|
|
|
mov edx,esi ; restore edx back to real value
|
|
mov eax,ecx ; store total width in ecx
|
|
sub eax,[VPwidth] ; modify xadd value to include clipped
|
|
sub [VPxadd],eax ; width bytes (subtract a negative number)
|
|
|
|
;*===================================================================
|
|
; Convert the color byte to a DWORD for fast storing
|
|
;*===================================================================
|
|
mov al,[color] ; get color to clear to
|
|
mov ah,al ; extend across WORD
|
|
mov ebx,eax ; extend across DWORD in
|
|
shl eax,16 ; several steps
|
|
mov ax,bx
|
|
|
|
;*===================================================================
|
|
; If there is no row offset then adjust the width to be the size of
|
|
; the entire viewport and adjust the height to be 1
|
|
;*===================================================================
|
|
mov esi,[VPxadd]
|
|
or esi,esi ; set the flags for esi
|
|
jnz row_by_row_aligned ; and act on them
|
|
|
|
xchg eax,ecx ; switch bit pattern and width
|
|
mul edx ; multiply by edx to get size
|
|
xchg eax,ecx ; switch size and bit pattern
|
|
mov edx,1 ; only 1 line off view port size to do
|
|
|
|
;*===================================================================
|
|
; Find out if we should bother to align the row.
|
|
;*===================================================================
|
|
row_by_row_aligned:
|
|
mov [local_ebp],ecx ; width saved in ebp
|
|
cmp ecx,OPTIMAL_BYTE_COPY ; is it worth aligning them?
|
|
jl row_by_row ; if not then skip
|
|
|
|
;*===================================================================
|
|
; Figure out the alignment offset if there is any
|
|
;*===================================================================
|
|
mov ebx,edi ; get output position
|
|
and ebx,3 ; is there a remainder?
|
|
jz aligned_loop ; if not we are aligned
|
|
xor ebx,3 ; find number of align bytes
|
|
inc ebx ; this number is off by one
|
|
sub [local_ebp],ebx ; subtract from width
|
|
|
|
;*===================================================================
|
|
; Now that we have the alignment offset copy each row
|
|
;*===================================================================
|
|
aligned_loop:
|
|
mov ecx,ebx ; get number of bytes to align
|
|
rep stosb ; and move them over
|
|
mov ecx,[local_ebp] ; get number of aligned bytes
|
|
shr ecx,2 ; convert to DWORDS
|
|
rep stosd ; and move them over
|
|
mov ecx,[local_ebp] ; get number of aligned bytes
|
|
and ecx,3 ; find the remainder
|
|
rep stosb ; and move it over
|
|
add edi,esi ; fix the line offset
|
|
dec edx ; decrement the height
|
|
jnz aligned_loop ; if more to do than do it
|
|
jmp done ; we are all done
|
|
|
|
;*===================================================================
|
|
; If not enough bytes to bother aligning copy each line across a byte
|
|
; at a time.
|
|
;*===================================================================
|
|
row_by_row:
|
|
mov ecx,[local_ebp] ; get total width in bytes
|
|
rep stosb ; store the width
|
|
add edi,esi ; handle the xadd
|
|
dec edx ; decrement the height
|
|
jnz row_by_row ; if any left then next line
|
|
done:
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;* VVPC::CLEAR -- Clears a virtual viewport instance *
|
|
;* *
|
|
;* INPUT: UBYTE the color (optional) to clear the view port to *
|
|
;* *
|
|
;* OUTPUT: none *
|
|
;* *
|
|
;* NOTE: This function is optimized to handle viewport with no XAdd *
|
|
;* value. It also handles DWORD aligning the destination *
|
|
;* when speed can be gained by doing it. *
|
|
;* HISTORY: *
|
|
;* 06/07/1994 PWG : Created. *
|
|
;* 08/23/1994 SKB : Clear the direction flag to always go forward. *
|
|
;*=========================================================================*
|
|
*/
|
|
void __cdecl Buffer_Clear(void *this_object, unsigned char color)
|
|
{
|
|
unsigned int local_color = color;
|
|
|
|
__asm {
|
|
|
|
cld ; always go forward
|
|
|
|
mov ebx,[this_object] ; get a pointer to viewport
|
|
mov edi,[ebx]GraphicViewPortClass.Offset ; get the correct offset
|
|
mov edx,[ebx]GraphicViewPortClass.Height ; get height from viewport
|
|
mov esi,[ebx]GraphicViewPortClass.Width ; get width from viewport
|
|
//push [dword (GraphicViewPort ebx).GVPPitch] ; extra pitch of direct draw surface
|
|
push [ebx]GraphicViewPortClass.Pitch
|
|
|
|
mov ebx,[ebx]GraphicViewPortClass.XAdd ; esi = add for each line
|
|
add ebx,[esp] ; Yes, I know its nasty but
|
|
add esp,4 ; it works!
|
|
|
|
;*===================================================================
|
|
; Convert the color byte to a DWORD for fast storing
|
|
;*===================================================================
|
|
mov al,[color] ; get color to clear to
|
|
mov ah,al ; extend across WORD
|
|
mov ecx,eax ; extend across DWORD in
|
|
shl eax,16 ; several steps
|
|
mov ax,cx
|
|
|
|
;*===================================================================
|
|
; Find out if we should bother to align the row.
|
|
;*===================================================================
|
|
|
|
cmp esi , OPTIMAL_BYTE_COPY ; is it worth aligning them?
|
|
jl byte_by_byte ; if not then skip
|
|
|
|
;*===================================================================
|
|
; Figure out the alignment offset if there is any
|
|
;*===================================================================
|
|
push ebx
|
|
|
|
dword_aligned_loop:
|
|
mov ecx , edi
|
|
mov ebx , esi
|
|
neg ecx
|
|
and ecx , 3
|
|
sub ebx , ecx
|
|
rep stosb
|
|
mov ecx , ebx
|
|
shr ecx , 2
|
|
rep stosd
|
|
mov ecx , ebx
|
|
and ecx , 3
|
|
rep stosb
|
|
add edi , [ esp ]
|
|
dec edx ; decrement the height
|
|
jnz dword_aligned_loop ; if more to do than do it
|
|
pop eax
|
|
jmp done
|
|
//ret
|
|
|
|
;*===================================================================
|
|
; If not enough bytes to bother aligning copy each line across a byte
|
|
; at a time.
|
|
;*===================================================================
|
|
byte_by_byte:
|
|
mov ecx,esi ; get total width in bytes
|
|
rep stosb ; store the width
|
|
add edi,ebx ; handle the xadd
|
|
dec edx ; decrement the height
|
|
jnz byte_by_byte ; if any left then next line
|
|
done:
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
{
|
|
/*
|
|
;*===================================================================
|
|
;* define the arguements that our function takes.
|
|
;*===================================================================
|
|
ARG this_object :DWORD ; this is a member function
|
|
ARG dest :DWORD ; what are we blitting to
|
|
ARG x_pixel :DWORD ; x pixel position in source
|
|
ARG y_pixel :DWORD ; y pixel position in source
|
|
ARG dest_x0 :dword
|
|
ARG dest_y0 :dword
|
|
ARG pixel_width :DWORD ; width of rectangle to blit
|
|
ARG pixel_height:DWORD ; height of rectangle to blit
|
|
ARG trans :DWORD ; do we deal with transparents?
|
|
|
|
;*===================================================================
|
|
; Define some locals so that we can handle things quickly
|
|
;*===================================================================
|
|
LOCAL x1_pixel :dword
|
|
LOCAL y1_pixel :dword
|
|
LOCAL dest_x1 : dword
|
|
LOCAL dest_y1 : dword
|
|
LOCAL scr_ajust_width:DWORD
|
|
LOCAL dest_ajust_width:DWORD
|
|
LOCAL source_area : dword
|
|
LOCAL dest_area : dword
|
|
*/
|
|
|
|
int x1_pixel;
|
|
int y1_pixel;
|
|
int dest_x1;
|
|
int dest_y1;
|
|
int scr_adjust_width;
|
|
int dest_adjust_width;
|
|
int source_area;
|
|
int dest_area;
|
|
|
|
__asm {
|
|
|
|
;This Clipping algorithm is a derivation of the very well known
|
|
;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency
|
|
;it is probably the most commontly implemented algorithm both in software
|
|
;and hardware for clipping lines, rectangles, and convex polygons against
|
|
;a rectagular clipping window. For reference see
|
|
;"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes
|
|
; pages 113 to 177".
|
|
; Briefly consist in computing the Sutherland code for both end point of
|
|
; the rectangle to find out if the rectangle is:
|
|
; - trivially accepted (no further clipping test, display rectangle)
|
|
; - trivially rejected (return with no action)
|
|
; - retangle must be iteratively clipped again edges of the clipping window
|
|
; and the remaining retangle is display.
|
|
|
|
; Clip Source Rectangle against source Window boundaries.
|
|
mov esi,[this_object] ; get ptr to src
|
|
xor ecx,ecx ; Set sutherland code to zero
|
|
xor edx,edx ; Set sutherland code to zero
|
|
|
|
; compute the difference in the X axis and get the bit signs into ecx , edx
|
|
mov edi,[esi]GraphicViewPortClass.Width ; get width into register
|
|
mov ebx,[x_pixel] ; Get first end point x_pixel into register
|
|
mov eax,[x_pixel] ; Get second end point x_pixel into register
|
|
add ebx,[pixel_width] ; second point x1_pixel = x + width
|
|
shld ecx, eax,1 ; the sign bit of x_pixel is sutherland code0 bit4
|
|
mov [x1_pixel],ebx ; save second for future use
|
|
inc edi ; move the right edge by one unit
|
|
shld edx,ebx,1 ; the sign bit of x1_pixel is sutherland code0 bit4
|
|
sub eax,edi ; compute the difference x0_pixel - width
|
|
sub ebx,edi ; compute the difference x1_pixel - width
|
|
shld ecx,eax,1 ; the sign bit of the difference is sutherland code0 bit3
|
|
shld edx,ebx,1 ; the sign bit of the difference is sutherland code0 bit3
|
|
|
|
; the following code is just a repeticion of the above code
|
|
; in the Y axis.
|
|
mov edi,[esi]GraphicViewPortClass.Height ; get height into register
|
|
mov ebx,[y_pixel]
|
|
mov eax,[y_pixel]
|
|
add ebx,[pixel_height]
|
|
shld ecx,eax,1
|
|
mov [y1_pixel ],ebx
|
|
inc edi
|
|
shld edx,ebx,1
|
|
sub eax,edi
|
|
sub ebx,edi
|
|
shld ecx,eax,1
|
|
shld edx,ebx,1
|
|
|
|
; Here we have the to Sutherland code into cl and dl
|
|
xor cl,5 ; bit 2 and 0 are complented, reverse then
|
|
xor dl,5 ; bit 2 and 0 are complented, reverse then
|
|
mov al,cl ; save code1 in case we have to clip iteratively
|
|
test dl,cl ; if any bit in code0 and its counter bit
|
|
jnz real_out ; in code1 is set then the rectangle in outside
|
|
or al,dl ; if all bit of code0 the counter bit in
|
|
jz clip_against_dest ; in code1 is set to zero, then all
|
|
; end points of the rectangle are
|
|
; inside the clipping window
|
|
|
|
; if we are here the polygon have to be clip iteratively
|
|
test cl,1000b ; if bit 4 in code0 is set then
|
|
jz scr_left_ok ; x_pixel is smaller than zero
|
|
mov [x_pixel],0 ; set x_pixel to cero.
|
|
|
|
scr_left_ok:
|
|
test cl,0010b ; if bit 2 in code0 is set then
|
|
jz scr_bottom_ok ; y_pixel is smaller than zero
|
|
mov [ y_pixel ],0 ; set y_pixel to cero.
|
|
|
|
scr_bottom_ok:
|
|
test dl,0100b ; if bit 3 in code1 is set then
|
|
jz scr_right_ok ; x1_pixel is greater than the width
|
|
mov eax,[esi]GraphicViewPortClass.Width ; get width into register
|
|
mov [ x1_pixel ],eax ; set x1_pixel to width.
|
|
scr_right_ok:
|
|
test dl,0001b ; if bit 0 in code1 is set then
|
|
jz clip_against_dest ; y1_pixel is greater than the width
|
|
mov eax,[esi]GraphicViewPortClass.Height ; get height into register
|
|
mov [ y1_pixel ],eax ; set y1_pixel to height.
|
|
|
|
; Clip Source Rectangle against destination Window boundaries.
|
|
clip_against_dest:
|
|
|
|
; build the destination rectangle before clipping
|
|
; dest_x1 = dest_x0 + ( x1_pixel - x_pixel )
|
|
; dest_y1 = dest_y0 + ( y1_pixel - y_pixel )
|
|
mov eax,[dest_x0] ; get dest_x0 into eax
|
|
mov ebx,[dest_y0] ; get dest_y0 into ebx
|
|
sub eax,[x_pixel] ; subtract x_pixel from eax
|
|
sub ebx,[y_pixel] ; subtract y_pixel from ebx
|
|
add eax,[x1_pixel] ; add x1_pixel to eax
|
|
add ebx,[y1_pixel] ; add y1_pixel to ebx
|
|
mov [dest_x1],eax ; save eax into dest_x1
|
|
mov [dest_y1],ebx ; save eax into dest_y1
|
|
|
|
|
|
; The followin code is a repeticion of the Sutherland clipping
|
|
; descrived above.
|
|
mov esi,[dest] ; get ptr to src
|
|
xor ecx,ecx
|
|
xor edx,edx
|
|
mov edi,[esi]GraphicViewPortClass.Width ; get width into register
|
|
mov eax,[dest_x0]
|
|
mov ebx,[dest_x1]
|
|
shld ecx,eax,1
|
|
inc edi
|
|
shld edx,ebx,1
|
|
sub eax,edi
|
|
sub ebx,edi
|
|
shld ecx,eax,1
|
|
shld edx,ebx,1
|
|
|
|
mov edi,[esi]GraphicViewPortClass.Height ; get height into register
|
|
mov eax,[dest_y0]
|
|
mov ebx,[dest_y1]
|
|
shld ecx,eax,1
|
|
inc edi
|
|
shld edx,ebx,1
|
|
sub eax,edi
|
|
sub ebx,edi
|
|
shld ecx,eax,1
|
|
shld edx,ebx,1
|
|
|
|
xor cl,5
|
|
xor dl,5
|
|
mov al,cl
|
|
test dl,cl
|
|
jnz real_out
|
|
or al,dl
|
|
jz do_blit
|
|
|
|
test cl,1000b
|
|
jz dest_left_ok
|
|
mov eax,[ dest_x0 ]
|
|
mov [ dest_x0 ],0
|
|
sub [ x_pixel ],eax
|
|
|
|
dest_left_ok:
|
|
test cl,0010b
|
|
jz dest_bottom_ok
|
|
mov eax,[ dest_y0 ]
|
|
mov [ dest_y0 ],0
|
|
sub [ y_pixel ],eax
|
|
|
|
|
|
dest_bottom_ok:
|
|
test dl,0100b
|
|
jz dest_right_ok
|
|
mov ebx,[esi]GraphicViewPortClass.Width ; get width into register
|
|
mov eax,[ dest_x1 ]
|
|
mov [ dest_x1 ],ebx
|
|
sub eax,ebx
|
|
sub [ x1_pixel ],eax
|
|
|
|
dest_right_ok:
|
|
test dl,0001b
|
|
jz do_blit
|
|
mov ebx,[esi]GraphicViewPortClass.Height ; get width into register
|
|
mov eax,[ dest_y1 ]
|
|
mov [ dest_y1 ],ebx
|
|
sub eax,ebx
|
|
sub [ y1_pixel ],eax
|
|
|
|
|
|
; Here is where we do the actual blit
|
|
do_blit:
|
|
cld
|
|
mov ebx,[this_object]
|
|
mov esi,[ebx]GraphicViewPortClass.Offset
|
|
mov eax,[ebx]GraphicViewPortClass.XAdd
|
|
add eax,[ebx]GraphicViewPortClass.Width
|
|
add eax,[ebx]GraphicViewPortClass.Pitch
|
|
mov ecx,eax
|
|
mul [y_pixel]
|
|
add esi,[x_pixel]
|
|
mov [source_area],ecx
|
|
add esi,eax
|
|
|
|
add ecx,[x_pixel ]
|
|
sub ecx,[x1_pixel ]
|
|
mov [scr_adjust_width ],ecx
|
|
|
|
mov ebx,[dest]
|
|
mov edi,[ebx]GraphicViewPortClass.Offset
|
|
mov eax,[ebx]GraphicViewPortClass.XAdd
|
|
add eax,[ebx]GraphicViewPortClass.Width
|
|
add eax,[ebx]GraphicViewPortClass.Pitch
|
|
mov ecx,eax
|
|
mul [ dest_y0 ]
|
|
add edi,[ dest_x0 ]
|
|
mov [ dest_area ],ecx
|
|
add edi,eax
|
|
|
|
mov eax,[ dest_x1 ]
|
|
sub eax,[ dest_x0 ]
|
|
jle real_out
|
|
sub ecx,eax
|
|
mov [ dest_adjust_width ],ecx
|
|
|
|
mov edx,[ dest_y1 ]
|
|
sub edx,[ dest_y0 ]
|
|
jle real_out
|
|
|
|
cmp esi,edi
|
|
jz real_out
|
|
jl backupward_blit
|
|
|
|
; ********************************************************************
|
|
; Forward bitblit
|
|
|
|
test [ trans ],1
|
|
jnz forward_Blit_trans
|
|
|
|
|
|
; the inner loop is so efficient that
|
|
; the optimal consept no longer apply because
|
|
; the optimal byte have to by a number greather than 9 bytes
|
|
cmp eax,10
|
|
jl forward_loop_bytes
|
|
|
|
forward_loop_dword:
|
|
mov ecx,edi
|
|
mov ebx,eax
|
|
neg ecx
|
|
and ecx,3
|
|
sub ebx,ecx
|
|
rep movsb
|
|
mov ecx,ebx
|
|
shr ecx,2
|
|
rep movsd
|
|
mov ecx,ebx
|
|
and ecx,3
|
|
rep movsb
|
|
add esi,[ scr_adjust_width ]
|
|
add edi,[ dest_adjust_width ]
|
|
dec edx
|
|
jnz forward_loop_dword
|
|
jmp real_out //ret
|
|
|
|
forward_loop_bytes:
|
|
mov ecx,eax
|
|
rep movsb
|
|
add esi,[ scr_adjust_width ]
|
|
add edi,[ dest_adjust_width ]
|
|
dec edx
|
|
jnz forward_loop_bytes
|
|
jmp real_out
|
|
|
|
forward_Blit_trans:
|
|
mov ecx,eax
|
|
and ecx,01fh
|
|
lea ecx,[ ecx + ecx * 4 ]
|
|
neg ecx
|
|
shr eax,5
|
|
lea ecx,[ transp_reference + ecx * 2 ]
|
|
mov [ y1_pixel ],ecx
|
|
|
|
forward_loop_trans:
|
|
mov ecx,eax
|
|
jmp [ y1_pixel ]
|
|
forward_trans_line:
|
|
//REPT 32
|
|
//local transp_pixel
|
|
//No REPT in msvc inline assembly.
|
|
// Save ECX and use as counter instead. ST - 12/19/2018 5:41PM
|
|
push ecx
|
|
mov ecx, 32
|
|
|
|
rept_loop:
|
|
mov bl,[ esi ]
|
|
test bl,bl
|
|
jz transp_pixel
|
|
mov [ edi ],bl
|
|
transp_pixel:
|
|
inc esi
|
|
inc edi
|
|
|
|
dec ecx //ST - 12/19/2018 5:44PM
|
|
jnz rept_loop //ST - 12/19/2018 5:44PM
|
|
|
|
pop ecx //ST - 12/19/2018 5:44PM
|
|
|
|
//ENDM
|
|
transp_reference:
|
|
dec ecx
|
|
jge forward_trans_line
|
|
add esi,[ scr_adjust_width ]
|
|
add edi,[ dest_adjust_width ]
|
|
dec edx
|
|
jnz forward_loop_trans
|
|
jmp real_out //ret
|
|
|
|
|
|
; ************************************************************************
|
|
; backward bitblit
|
|
|
|
backupward_blit:
|
|
|
|
mov ebx,[ source_area ]
|
|
dec edx
|
|
add esi,eax
|
|
imul ebx,edx
|
|
std
|
|
lea esi,[ esi + ebx - 1 ]
|
|
|
|
mov ebx,[ dest_area ]
|
|
add edi,eax
|
|
imul ebx,edx
|
|
lea edi,[ edi + ebx - 1]
|
|
|
|
test [ trans ],1
|
|
jnz backward_Blit_trans
|
|
|
|
cmp eax,15
|
|
jl backward_loop_bytes
|
|
|
|
backward_loop_dword:
|
|
push edi
|
|
push esi
|
|
lea ecx,[edi+1]
|
|
mov ebx,eax
|
|
and ecx,3 ; Get non aligned bytes.
|
|
sub ebx,ecx ; remove that from the total size to be copied later.
|
|
rep movsb ; do the copy.
|
|
sub esi,3
|
|
mov ecx,ebx ; Get number of bytes left.
|
|
sub edi,3
|
|
shr ecx,2 ; Do 4 bytes at a time.
|
|
rep movsd ; do the dword copy.
|
|
mov ecx,ebx
|
|
add esi,3
|
|
add edi,3
|
|
and ecx,03h
|
|
rep movsb ; finnish the remaining bytes.
|
|
pop esi
|
|
pop edi
|
|
sub esi,[ source_area ]
|
|
sub edi,[ dest_area ]
|
|
dec edx
|
|
jge backward_loop_dword
|
|
cld
|
|
jmp real_out //ret
|
|
|
|
backward_loop_bytes:
|
|
push edi
|
|
mov ecx,eax ; remove that from the total size to be copied later.
|
|
push esi
|
|
rep movsb ; do the copy.
|
|
pop esi
|
|
pop edi
|
|
sub esi,[ source_area ]
|
|
sub edi,[ dest_area ]
|
|
dec edx
|
|
jge backward_loop_bytes
|
|
cld
|
|
jmp real_out //ret
|
|
|
|
backward_Blit_trans:
|
|
mov ecx,eax
|
|
and ecx,01fh
|
|
lea ecx,[ ecx + ecx * 4 ]
|
|
neg ecx
|
|
shr eax,5
|
|
lea ecx,[ back_transp_reference + ecx * 2 ]
|
|
mov [ y1_pixel ],ecx
|
|
|
|
backward_loop_trans:
|
|
mov ecx,eax
|
|
push edi
|
|
push esi
|
|
jmp [ y1_pixel ]
|
|
backward_trans_line:
|
|
//REPT 32
|
|
//local transp_pixel2
|
|
//No REPT in msvc inline assembly.
|
|
// Save ECX and use as counter instead. ST - 12/19/2018 5:41PM
|
|
push ecx
|
|
mov ecx, 32
|
|
rept_loop2:
|
|
mov bl,[ esi ]
|
|
test bl,bl
|
|
jz transp_pixel2
|
|
mov [ edi ],bl
|
|
transp_pixel2:
|
|
dec esi
|
|
dec edi
|
|
|
|
dec ecx //ST - 12/19/2018 5:44PM
|
|
jnz rept_loop2 //ST - 12/19/2018 5:44PM
|
|
|
|
pop ecx //ST - 12/19/2018 5:44PM
|
|
|
|
//ENDM
|
|
|
|
back_transp_reference:
|
|
dec ecx
|
|
jge backward_trans_line
|
|
pop esi
|
|
pop edi
|
|
sub esi,[ source_area ]
|
|
sub edi,[ dest_area ]
|
|
dec edx
|
|
jge backward_loop_trans
|
|
cld
|
|
//ret
|
|
|
|
real_out:
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;* VVC::SCALE -- Scales a virtual viewport to another virtual viewport *
|
|
;* *
|
|
;* INPUT: *
|
|
;* *
|
|
;* OUTPUT: *
|
|
;* *
|
|
;* WARNINGS: *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 06/16/1994 PWG : Created. *
|
|
;*=========================================================================*
|
|
PROC Linear_Scale_To_Linear C NEAR
|
|
USES eax,ebx,ecx,edx,esi,edi
|
|
*/
|
|
|
|
// Ran out of registers so had to use ebp. ST - 12/19/2018 6:22PM
|
|
#pragma warning (push)
|
|
#pragma warning (disable : 4731)
|
|
|
|
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)
|
|
{
|
|
/*
|
|
|
|
;*===================================================================
|
|
;* Define the arguements that our function takes.
|
|
;*===================================================================
|
|
ARG this_object:DWORD ; pointer to source view port
|
|
ARG dest:DWORD ; pointer to destination view port
|
|
ARG src_x:DWORD ; source x offset into view port
|
|
ARG src_y:DWORD ; source y offset into view port
|
|
ARG dst_x:DWORD ; dest x offset into view port
|
|
ARG dst_y:DWORD ; dest y offset into view port
|
|
ARG src_width:DWORD ; width of source rectangle
|
|
ARG src_height:DWORD ; height of source rectangle
|
|
ARG dst_width:DWORD ; width of dest rectangle
|
|
ARG dst_height:DWORD ; width of dest height
|
|
ARG trans:DWORD ; is this transparent?
|
|
ARG remap:DWORD ; pointer to table to remap source
|
|
|
|
;*===================================================================
|
|
;* Define local variables to hold the viewport characteristics
|
|
;*===================================================================
|
|
local src_x0 : dword
|
|
local src_y0 : dword
|
|
local src_x1 : dword
|
|
local src_y1 : dword
|
|
|
|
local dst_x0 : dword
|
|
local dst_y0 : dword
|
|
local dst_x1 : dword
|
|
local dst_y1 : dword
|
|
|
|
local src_win_width : dword
|
|
local dst_win_width : dword
|
|
local dy_intr : dword
|
|
local dy_frac : dword
|
|
local dy_acc : dword
|
|
local dx_frac : dword
|
|
|
|
local counter_x : dword
|
|
local counter_y : dword
|
|
local remap_counter :dword
|
|
local entry : dword
|
|
*/
|
|
|
|
int src_x0;
|
|
int src_y0;
|
|
int src_x1;
|
|
int src_y1;
|
|
|
|
int dst_x0;
|
|
int dst_y0;
|
|
int dst_x1;
|
|
int dst_y1;
|
|
|
|
int src_win_width;
|
|
int dst_win_width;
|
|
int dy_intr;
|
|
int dy_frac;
|
|
int dy_acc;
|
|
int dx_frac;
|
|
|
|
int counter_x;
|
|
int counter_y;
|
|
int remap_counter;
|
|
int entry;
|
|
|
|
|
|
__asm {
|
|
|
|
;*===================================================================
|
|
;* Check for scale error when to or from size 0,0
|
|
;*===================================================================
|
|
cmp [dst_width],0
|
|
je all_done
|
|
cmp [dst_height],0
|
|
je all_done
|
|
cmp [src_width],0
|
|
je all_done
|
|
cmp [src_height],0
|
|
je all_done
|
|
|
|
mov eax , [ src_x ]
|
|
mov ebx , [ src_y ]
|
|
mov [ src_x0 ] , eax
|
|
mov [ src_y0 ] , ebx
|
|
add eax , [ src_width ]
|
|
add ebx , [ src_height ]
|
|
mov [ src_x1 ] , eax
|
|
mov [ src_y1 ] , ebx
|
|
|
|
mov eax , [ dst_x ]
|
|
mov ebx , [ dst_y ]
|
|
mov [ dst_x0 ] , eax
|
|
mov [ dst_y0 ] , ebx
|
|
add eax , [ dst_width ]
|
|
add ebx , [ dst_height ]
|
|
mov [ dst_x1 ] , eax
|
|
mov [ dst_y1 ] , ebx
|
|
|
|
; Clip Source Rectangle against source Window boundaries.
|
|
mov esi , [ this_object ] ; get ptr to src
|
|
xor ecx , ecx
|
|
xor edx , edx
|
|
mov edi , [esi]GraphicViewPortClass.Width ; get width into register
|
|
mov eax , [ src_x0 ]
|
|
mov ebx , [ src_x1 ]
|
|
shld ecx , eax , 1
|
|
inc edi
|
|
shld edx , ebx , 1
|
|
sub eax , edi
|
|
sub ebx , edi
|
|
shld ecx , eax , 1
|
|
shld edx , ebx , 1
|
|
|
|
mov edi,[esi]GraphicViewPortClass.Height ; get height into register
|
|
mov eax , [ src_y0 ]
|
|
mov ebx , [ src_y1 ]
|
|
shld ecx , eax , 1
|
|
inc edi
|
|
shld edx , ebx , 1
|
|
sub eax , edi
|
|
sub ebx , edi
|
|
shld ecx , eax , 1
|
|
shld edx , ebx , 1
|
|
|
|
xor cl , 5
|
|
xor dl , 5
|
|
mov al , cl
|
|
test dl , cl
|
|
jnz all_done
|
|
or al , dl
|
|
jz clip_against_dest
|
|
mov bl , dl
|
|
test cl , 1000b
|
|
jz src_left_ok
|
|
xor eax , eax
|
|
mov [ src_x0 ] , eax
|
|
sub eax , [ src_x ]
|
|
imul [ dst_width ]
|
|
idiv [ src_width ]
|
|
add eax , [ dst_x ]
|
|
mov [ dst_x0 ] , eax
|
|
|
|
src_left_ok:
|
|
test cl , 0010b
|
|
jz src_bottom_ok
|
|
xor eax , eax
|
|
mov [ src_y0 ] , eax
|
|
sub eax , [ src_y ]
|
|
imul [ dst_height ]
|
|
idiv [ src_height ]
|
|
add eax , [ dst_y ]
|
|
mov [ dst_y0 ] , eax
|
|
|
|
src_bottom_ok:
|
|
test bl , 0100b
|
|
jz src_right_ok
|
|
mov eax , [esi]GraphicViewPortClass.Width ; get width into register
|
|
mov [ src_x1 ] , eax
|
|
sub eax , [ src_x ]
|
|
imul [ dst_width ]
|
|
idiv [ src_width ]
|
|
add eax , [ dst_x ]
|
|
mov [ dst_x1 ] , eax
|
|
|
|
src_right_ok:
|
|
test bl , 0001b
|
|
jz clip_against_dest
|
|
mov eax , [esi]GraphicViewPortClass.Height ; get width into register
|
|
mov [ src_y1 ] , eax
|
|
sub eax , [ src_y ]
|
|
imul [ dst_height ]
|
|
idiv [ src_height ]
|
|
add eax , [ dst_y ]
|
|
mov [ dst_y1 ] , eax
|
|
|
|
; Clip destination Rectangle against source Window boundaries.
|
|
clip_against_dest:
|
|
mov esi , [ dest ] ; get ptr to src
|
|
xor ecx , ecx
|
|
xor edx , edx
|
|
mov edi , [esi]GraphicViewPortClass.Width ; get width into register
|
|
mov eax , [ dst_x0 ]
|
|
mov ebx , [ dst_x1 ]
|
|
shld ecx , eax , 1
|
|
inc edi
|
|
shld edx , ebx , 1
|
|
sub eax , edi
|
|
sub ebx , edi
|
|
shld ecx , eax , 1
|
|
shld edx , ebx , 1
|
|
|
|
mov edi,[esi]GraphicViewPortClass.Height ; get height into register
|
|
mov eax , [ dst_y0 ]
|
|
mov ebx , [ dst_y1 ]
|
|
shld ecx , eax , 1
|
|
inc edi
|
|
shld edx , ebx , 1
|
|
sub eax , edi
|
|
sub ebx , edi
|
|
shld ecx , eax , 1
|
|
shld edx , ebx , 1
|
|
|
|
xor cl , 5
|
|
xor dl , 5
|
|
mov al , cl
|
|
test dl , cl
|
|
jnz all_done
|
|
or al , dl
|
|
jz do_scaling
|
|
mov bl , dl
|
|
test cl , 1000b
|
|
jz dst_left_ok
|
|
xor eax , eax
|
|
mov [ dst_x0 ] , eax
|
|
sub eax , [ dst_x ]
|
|
imul [ src_width ]
|
|
idiv [ dst_width ]
|
|
add eax , [ src_x ]
|
|
mov [ src_x0 ] , eax
|
|
|
|
dst_left_ok:
|
|
test cl , 0010b
|
|
jz dst_bottom_ok
|
|
xor eax , eax
|
|
mov [ dst_y0 ] , eax
|
|
sub eax , [ dst_y ]
|
|
imul [ src_height ]
|
|
idiv [ dst_height ]
|
|
add eax , [ src_y ]
|
|
mov [ src_y0 ] , eax
|
|
|
|
dst_bottom_ok:
|
|
test bl , 0100b
|
|
jz dst_right_ok
|
|
mov eax , [esi]GraphicViewPortClass.Width ; get width into register
|
|
mov [ dst_x1 ] , eax
|
|
sub eax , [ dst_x ]
|
|
imul [ src_width ]
|
|
idiv [ dst_width ]
|
|
add eax , [ src_x ]
|
|
mov [ src_x1 ] , eax
|
|
|
|
dst_right_ok:
|
|
test bl , 0001b
|
|
jz do_scaling
|
|
|
|
mov eax , [esi]GraphicViewPortClass.Height ; get width into register
|
|
mov [ dst_y1 ] , eax
|
|
sub eax , [ dst_y ]
|
|
imul [ src_height ]
|
|
idiv [ dst_height ]
|
|
add eax , [ src_y ]
|
|
mov [ src_y1 ] , eax
|
|
|
|
do_scaling:
|
|
|
|
cld
|
|
mov ebx , [ this_object ]
|
|
mov esi , [ebx]GraphicViewPortClass. Offset
|
|
mov eax , [ebx]GraphicViewPortClass. XAdd
|
|
add eax , [ebx]GraphicViewPortClass. Width
|
|
add eax , [ebx]GraphicViewPortClass. Pitch
|
|
mov [ src_win_width ] , eax
|
|
mul [ src_y0 ]
|
|
add esi , [ src_x0 ]
|
|
add esi , eax
|
|
|
|
mov ebx , [ dest ]
|
|
mov edi , [ebx]GraphicViewPortClass. Offset
|
|
mov eax , [ebx]GraphicViewPortClass. XAdd
|
|
add eax , [ebx]GraphicViewPortClass. Width
|
|
add eax , [ebx]GraphicViewPortClass. Pitch
|
|
mov [ dst_win_width ] , eax
|
|
mul [ dst_y0 ]
|
|
add edi , [ dst_x0 ]
|
|
add edi , eax
|
|
|
|
mov eax , [ src_height ]
|
|
xor edx , edx
|
|
mov ebx , [ dst_height ]
|
|
idiv [ dst_height ]
|
|
imul eax , [ src_win_width ]
|
|
neg ebx
|
|
mov [ dy_intr ] , eax
|
|
mov [ dy_frac ] , edx
|
|
mov [ dy_acc ] , ebx
|
|
|
|
mov eax , [ src_width ]
|
|
xor edx , edx
|
|
shl eax , 16
|
|
idiv [ dst_width ]
|
|
xor edx , edx
|
|
shld edx , eax , 16
|
|
shl eax , 16
|
|
|
|
mov ecx , [ dst_y1 ]
|
|
mov ebx , [ dst_x1 ]
|
|
sub ecx , [ dst_y0 ]
|
|
jle all_done
|
|
sub ebx , [ dst_x0 ]
|
|
jle all_done
|
|
|
|
mov [ counter_y ] , ecx
|
|
|
|
cmp [ trans ] , 0
|
|
jnz transparency
|
|
|
|
cmp [ remap ] , 0
|
|
jnz normal_remap
|
|
|
|
; *************************************************************************
|
|
; normal scale
|
|
mov ecx , ebx
|
|
and ecx , 01fh
|
|
lea ecx , [ ecx + ecx * 2 ]
|
|
shr ebx , 5
|
|
neg ecx
|
|
mov [ counter_x ] , ebx
|
|
lea ecx , [ ref_point + ecx + ecx * 2 ]
|
|
mov [ entry ] , ecx
|
|
|
|
outter_loop:
|
|
push esi
|
|
push edi
|
|
xor ecx , ecx
|
|
mov ebx , [ counter_x ]
|
|
jmp [ entry ]
|
|
inner_loop:
|
|
// REPT not supported for inline asm. ST - 12/19/2018 6:11PM
|
|
//REPT 32
|
|
push ebx //ST - 12/19/2018 6:11PM
|
|
mov ebx,32 //ST - 12/19/2018 6:11PM
|
|
rept_loop:
|
|
mov cl , [ esi ]
|
|
add ecx , eax
|
|
adc esi , edx
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
|
|
dec ebx //ST - 12/19/2018 6:11PM
|
|
jnz rept_loop //ST - 12/19/2018 6:11PM
|
|
pop ebx //ST - 12/19/2018 6:11PM
|
|
//ENDM
|
|
ref_point:
|
|
dec ebx
|
|
jge inner_loop
|
|
|
|
pop edi
|
|
pop esi
|
|
add edi , [ dst_win_width ]
|
|
add esi , [ dy_intr ]
|
|
|
|
mov ebx , [ dy_acc ]
|
|
add ebx , [ dy_frac ]
|
|
jle skip_line
|
|
add esi , [ src_win_width ]
|
|
sub ebx , [ dst_height ]
|
|
skip_line:
|
|
dec [ counter_y ]
|
|
mov [ dy_acc ] , ebx
|
|
jnz outter_loop
|
|
jmp all_done //ret
|
|
|
|
|
|
; *************************************************************************
|
|
; normal scale with remap
|
|
|
|
normal_remap:
|
|
mov ecx , ebx
|
|
mov [ dx_frac ], eax
|
|
and ecx , 01fh
|
|
mov eax , [ remap ]
|
|
shr ebx , 5
|
|
imul ecx , - 13
|
|
mov [ counter_x ] , ebx
|
|
lea ecx , [ remapref_point + ecx ]
|
|
mov [ entry ] , ecx
|
|
|
|
remapoutter_loop:
|
|
mov ebx , [ counter_x ]
|
|
push esi
|
|
mov [ remap_counter ] , ebx
|
|
push edi
|
|
xor ecx , ecx
|
|
xor ebx , ebx
|
|
jmp [ entry ]
|
|
remapinner_loop:
|
|
// REPT not supported for inline asm. ST - 12/19/2018 6:11PM
|
|
//REPT 32
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
mov bl , [ esi ]
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
inc edi
|
|
|
|
//ENDM
|
|
remapref_point:
|
|
dec [ remap_counter ]
|
|
jge remapinner_loop
|
|
|
|
pop edi
|
|
pop esi
|
|
add edi , [ dst_win_width ]
|
|
add esi , [ dy_intr ]
|
|
|
|
mov ebx , [ dy_acc ]
|
|
add ebx , [ dy_frac ]
|
|
jle remapskip_line
|
|
add esi , [ src_win_width ]
|
|
sub ebx , [ dst_height ]
|
|
remapskip_line:
|
|
dec [ counter_y ]
|
|
mov [ dy_acc ] , ebx
|
|
jnz remapoutter_loop
|
|
jmp all_done //ret
|
|
|
|
|
|
;****************************************************************************
|
|
; scale with trnsparency
|
|
|
|
transparency:
|
|
cmp [ remap ] , 0
|
|
jnz trans_remap
|
|
|
|
; *************************************************************************
|
|
; normal scale with transparency
|
|
mov ecx , ebx
|
|
and ecx , 01fh
|
|
imul ecx , -13
|
|
shr ebx , 5
|
|
mov [ counter_x ] , ebx
|
|
lea ecx , [ trans_ref_point + ecx ]
|
|
mov [ entry ] , ecx
|
|
|
|
trans_outter_loop:
|
|
xor ecx , ecx
|
|
push esi
|
|
push edi
|
|
mov ebx , [ counter_x ]
|
|
jmp [ entry ]
|
|
trans_inner_loop:
|
|
|
|
// REPT not supported for inline asm. ST - 12/19/2018 6:11PM
|
|
//REPT 32
|
|
push ebx //ST - 12/19/2018 6:11PM
|
|
mov ebx,32 //ST - 12/19/2018 6:11PM
|
|
rept_loop2:
|
|
|
|
mov cl , [ esi ]
|
|
test cl , cl
|
|
jz trans_pixel
|
|
mov [ edi ] , cl
|
|
trans_pixel:
|
|
add ecx , eax
|
|
adc esi , edx
|
|
inc edi
|
|
|
|
dec ebx //ST - 12/19/2018 6:11PM
|
|
jnz rept_loop2 //ST - 12/19/2018 6:11PM
|
|
pop ebx //ST - 12/19/2018 6:11PM
|
|
|
|
//ENDM
|
|
trans_ref_point:
|
|
dec ebx
|
|
jge trans_inner_loop
|
|
|
|
pop edi
|
|
pop esi
|
|
add edi , [ dst_win_width ]
|
|
add esi , [ dy_intr ]
|
|
|
|
mov ebx , [ dy_acc ]
|
|
add ebx , [ dy_frac ]
|
|
jle trans_skip_line
|
|
add esi , [ src_win_width ]
|
|
sub ebx , [ dst_height ]
|
|
trans_skip_line:
|
|
dec [ counter_y ]
|
|
mov [ dy_acc ] , ebx
|
|
jnz trans_outter_loop
|
|
jmp all_done //ret
|
|
|
|
|
|
; *************************************************************************
|
|
; normal scale with remap
|
|
|
|
trans_remap:
|
|
mov ecx , ebx
|
|
mov [ dx_frac ], eax
|
|
and ecx , 01fh
|
|
mov eax , [ remap ]
|
|
shr ebx , 5
|
|
imul ecx , - 17
|
|
mov [ counter_x ] , ebx
|
|
lea ecx , [ trans_remapref_point + ecx ]
|
|
mov [ entry ] , ecx
|
|
|
|
trans_remapoutter_loop:
|
|
mov ebx , [ counter_x ]
|
|
push esi
|
|
mov [ remap_counter ] , ebx
|
|
push edi
|
|
xor ecx , ecx
|
|
xor ebx , ebx
|
|
jmp [ entry ]
|
|
|
|
|
|
trans_remapinner_loop:
|
|
// REPT not supported for inline asm. ST - 12/19/2018 6:11PM
|
|
//REPT 32
|
|
// Run out of registers so use ebp
|
|
push ebp //ST - 12/19/2018 6:11PM
|
|
mov ebp,32 //ST - 12/19/2018 6:11PM
|
|
rept_loop3:
|
|
mov bl , [ esi ]
|
|
test bl , bl
|
|
jz trans_pixel2
|
|
mov cl , [ eax + ebx ]
|
|
mov [ edi ] , cl
|
|
trans_pixel2:
|
|
add ecx , [ dx_frac ]
|
|
adc esi , edx
|
|
inc edi
|
|
|
|
dec ebp //ST - 12/19/2018 6:11PM
|
|
jnz rept_loop3 //ST - 12/19/2018 6:11PM
|
|
pop ebp //ST - 12/19/2018 6:11PM
|
|
|
|
//ENDM
|
|
|
|
trans_remapref_point:
|
|
dec [ remap_counter ]
|
|
jge trans_remapinner_loop
|
|
|
|
pop edi
|
|
pop esi
|
|
add edi , [ dst_win_width ]
|
|
add esi , [ dy_intr ]
|
|
|
|
mov ebx , [ dy_acc ]
|
|
add ebx , [ dy_frac ]
|
|
jle trans_remapskip_line
|
|
add esi , [ src_win_width ]
|
|
sub ebx , [ dst_height ]
|
|
trans_remapskip_line:
|
|
dec [ counter_y ]
|
|
mov [ dy_acc ] , ebx
|
|
jnz trans_remapoutter_loop
|
|
//ret
|
|
|
|
|
|
all_done:
|
|
}
|
|
}
|
|
|
|
|
|
#pragma warning (pop)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int LastIconset = 0;
|
|
unsigned int StampPtr = 0; // DD 0 ; Pointer to icon data.
|
|
|
|
unsigned int IsTrans = 0; // DD 0 ; Pointer to transparent icon flag table.
|
|
|
|
unsigned int MapPtr = 0; // DD 0 ; Pointer to icon map.
|
|
unsigned int IconWidth = 0; // DD 0 ; Width of icon in pixels.
|
|
unsigned int IconHeight = 0; // DD 0 ; Height of icon in pixels.
|
|
unsigned int IconSize = 0; // DD 0 ; Number of bytes for each icon data.
|
|
unsigned int IconCount = 0; // DD 0 ; Number of icons in the set.
|
|
|
|
|
|
|
|
#if (0)
|
|
LastIconset DD 0 ; Pointer to last iconset initialized.
|
|
StampPtr DD 0 ; Pointer to icon data.
|
|
|
|
IsTrans DD 0 ; Pointer to transparent icon flag table.
|
|
|
|
MapPtr DD 0 ; Pointer to icon map.
|
|
IconWidth DD 0 ; Width of icon in pixels.
|
|
IconHeight DD 0 ; Height of icon in pixels.
|
|
IconSize DD 0 ; Number of bytes for each icon data.
|
|
IconCount DD 0 ; Number of icons in the set.
|
|
|
|
|
|
GLOBAL C Buffer_Draw_Stamp:near
|
|
GLOBAL C Buffer_Draw_Stamp_Clip:near
|
|
|
|
; 256 color icon system.
|
|
#endif
|
|
|
|
|
|
/*
|
|
;***********************************************************
|
|
; INIT_STAMPS
|
|
;
|
|
; VOID cdecl Init_Stamps(VOID *icondata);
|
|
;
|
|
; This routine initializes the stamp data.
|
|
; Bounds Checking: NONE
|
|
;
|
|
;*
|
|
*/
|
|
extern "C" void __cdecl Init_Stamps(unsigned int icondata)
|
|
{
|
|
|
|
__asm {
|
|
pushad // ST - 12/20/2018 10:30AM
|
|
|
|
; Verify legality of parameter.
|
|
cmp [icondata],0
|
|
je short fini
|
|
|
|
; Don't initialize if already initialized to this set (speed reasons).
|
|
mov edi,[icondata]
|
|
cmp [LastIconset],edi
|
|
je short fini
|
|
mov [LastIconset],edi
|
|
|
|
; Record number of icons in set.
|
|
movzx eax,[edi]IControl_Type.Count
|
|
mov [IconCount],eax
|
|
|
|
; Record width of icon.
|
|
movzx eax,[edi]IControl_Type.Width
|
|
mov [IconWidth],eax
|
|
|
|
; Record height of icon.
|
|
movzx ebx,[edi]IControl_Type.Height
|
|
mov [IconHeight],ebx
|
|
|
|
; Record size of icon (in bytes).
|
|
mul ebx
|
|
mov [IconSize],eax
|
|
|
|
; Record hard pointer to icon map data.
|
|
mov eax,[edi]IControl_Type.Map
|
|
add eax,edi
|
|
mov [MapPtr],eax
|
|
|
|
//nomap:
|
|
; Record hard pointer to icon data.
|
|
mov eax,edi
|
|
add eax,[edi]IControl_Type.Icons
|
|
mov [StampPtr],eax
|
|
|
|
; Record the transparent table.
|
|
mov eax,edi
|
|
add eax,[edi]IControl_Type.TransFlag
|
|
mov [IsTrans],eax
|
|
|
|
fini:
|
|
popad // ST - 12/20/2018 10:30AM
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
;***********************************************************
|
|
|
|
;***********************************************************
|
|
; DRAW_STAMP
|
|
;
|
|
; VOID cdecl Buffer_Draw_Stamp(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap);
|
|
;
|
|
; This routine renders the icon at the given coordinate.
|
|
;
|
|
; The remap table is a 256 byte simple pixel translation table to use when
|
|
; drawing the icon. Transparency check is performed AFTER the remap so it is possible to
|
|
; remap valid colors to be invisible (for special effect reasons).
|
|
; This routine is fastest when no remap table is passed in.
|
|
;*
|
|
*/
|
|
|
|
void __cdecl Buffer_Draw_Stamp(void const *this_object, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap)
|
|
{
|
|
unsigned int modulo = 0;
|
|
unsigned int iwidth = 0;
|
|
unsigned char doremap = 0;
|
|
|
|
|
|
/*
|
|
PROC Buffer_Draw_Stamp C near
|
|
|
|
ARG this_object:DWORD ; this is a member function
|
|
ARG icondata:DWORD ; Pointer to icondata.
|
|
ARG icon:DWORD ; Icon number to draw.
|
|
ARG x_pixel:DWORD ; X coordinate of icon.
|
|
ARG y_pixel:DWORD ; Y coordinate of icon.
|
|
ARG remap:DWORD ; Remap table.
|
|
|
|
LOCAL modulo:DWORD ; Modulo to get to next row.
|
|
LOCAL iwidth:DWORD ; Icon width (here for speedy access).
|
|
LOCAL doremap:BYTE ; Should remapping occur?
|
|
*/
|
|
|
|
__asm {
|
|
|
|
pushad
|
|
cmp [icondata],0
|
|
je proc_out
|
|
|
|
; Initialize the stamp data if necessary.
|
|
mov eax,[icondata]
|
|
cmp [LastIconset],eax
|
|
je short noreset
|
|
push eax
|
|
call Init_Stamps
|
|
pop eax // Clean up stack. ST - 12/20/2018 10:42AM
|
|
noreset:
|
|
|
|
; Determine if the icon number requested is actually in the set.
|
|
; Perform the logical icon to actual icon number remap if necessary.
|
|
mov ebx,[icon]
|
|
cmp [MapPtr],0
|
|
je short notmap
|
|
mov edi,[MapPtr]
|
|
mov bl,[edi+ebx]
|
|
notmap:
|
|
cmp ebx,[IconCount]
|
|
jae proc_out
|
|
mov [icon],ebx ; Updated icon number.
|
|
|
|
; If the remap table pointer passed in is NULL, then flag this condition
|
|
; so that the faster (non-remapping) icon draw loop will be used.
|
|
cmp [remap],0
|
|
setne [doremap]
|
|
|
|
; Get pointer to position to render icon. EDI = ptr to destination page.
|
|
mov ebx,[this_object]
|
|
mov edi,[ebx]GraphicViewPortClass.Offset
|
|
mov eax,[ebx]GraphicViewPortClass.Width
|
|
add eax,[ebx]GraphicViewPortClass.XAdd
|
|
add eax,[ebx]GraphicViewPortClass.Pitch
|
|
push eax ; save viewport full width for lower
|
|
mul [y_pixel]
|
|
add edi,eax
|
|
add edi,[x_pixel]
|
|
|
|
; Determine row modulo for advancing to next line.
|
|
pop eax ; retrieve viewport width
|
|
sub eax,[IconWidth]
|
|
mov [modulo],eax
|
|
|
|
; Setup some working variables.
|
|
mov ecx,[IconHeight] ; Row counter.
|
|
mov eax,[IconWidth]
|
|
mov [iwidth],eax ; Stack copy of byte width for easy BP access.
|
|
|
|
; Fetch pointer to start of icon's data. ESI = ptr to icon data.
|
|
mov eax,[icon]
|
|
mul [IconSize]
|
|
mov esi,[StampPtr]
|
|
add esi,eax
|
|
|
|
; Determine whether simple icon draw is sufficient or whether the
|
|
; extra remapping icon draw is needed.
|
|
cmp [BYTE PTR doremap],0
|
|
je short istranscheck
|
|
|
|
;************************************************************
|
|
; Complex icon draw -- extended remap.
|
|
; EBX = Palette pointer (ready for XLAT instruction).
|
|
; EDI = Pointer to icon destination in page.
|
|
; ESI = Pointer to icon data.
|
|
; ECX = Number of pixel rows.
|
|
;;; mov edx,[remap]
|
|
mov ebx,[remap]
|
|
xor eax,eax
|
|
xrowloop:
|
|
push ecx
|
|
mov ecx,[iwidth]
|
|
|
|
xcolumnloop:
|
|
lodsb
|
|
;;; mov ebx,edx
|
|
;;; add ebx,eax
|
|
;;; mov al,[ebx] ; New real color to draw.
|
|
xlatb
|
|
or al,al
|
|
jz short xskip1 ; Transparency skip check.
|
|
mov [edi],al
|
|
xskip1:
|
|
inc edi
|
|
loop xcolumnloop
|
|
|
|
pop ecx
|
|
add edi,[modulo]
|
|
loop xrowloop
|
|
jmp short proc_out
|
|
|
|
|
|
;************************************************************
|
|
; Check to see if transparent or generic draw is necessary.
|
|
istranscheck:
|
|
mov ebx,[IsTrans]
|
|
add ebx,[icon]
|
|
cmp [BYTE PTR ebx],0
|
|
jne short rowloop
|
|
|
|
;************************************************************
|
|
; Fast non-transparent icon draw routine.
|
|
; ES:DI = Pointer to icon destination in page.
|
|
; DS:SI = Pointer to icon data.
|
|
; CX = Number of pixel rows.
|
|
mov ebx,ecx
|
|
shr ebx,2
|
|
mov edx,[modulo]
|
|
mov eax,[iwidth]
|
|
shr eax,2
|
|
loop1:
|
|
mov ecx,eax
|
|
rep movsd
|
|
add edi,edx
|
|
|
|
mov ecx,eax
|
|
rep movsd
|
|
add edi,edx
|
|
|
|
mov ecx,eax
|
|
rep movsd
|
|
add edi,edx
|
|
|
|
mov ecx,eax
|
|
rep movsd
|
|
add edi,edx
|
|
|
|
dec ebx
|
|
jnz loop1
|
|
jmp short proc_out
|
|
|
|
;************************************************************
|
|
; Transparent icon draw routine -- no extended remap.
|
|
; ES:DI = Pointer to icon destination in page.
|
|
; DS:SI = Pointer to icon data.
|
|
; CX = Number of pixel rows.
|
|
rowloop:
|
|
push ecx
|
|
mov ecx,[iwidth]
|
|
|
|
columnloop:
|
|
lodsb
|
|
or al,al
|
|
jz short skip1 ; Transparency check.
|
|
mov [edi],al
|
|
skip1:
|
|
inc edi
|
|
loop columnloop
|
|
|
|
pop ecx
|
|
add edi,[modulo]
|
|
loop rowloop
|
|
|
|
; Cleanup and exit icon drawing routine.
|
|
proc_out:
|
|
popad
|
|
//ret
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
;***********************************************************
|
|
; DRAW_STAMP_CLIP
|
|
;
|
|
; VOID cdecl MCGA_Draw_Stamp_Clip(VOID *icondata, WORD icon, WORD x_pixel, WORD y_pixel, VOID *remap, LONG min_x, LONG min_y, LONG max_x, LONG max_y);
|
|
;
|
|
; This routine renders the icon at the given coordinate.
|
|
;
|
|
; The remap table is a 256 byte simple pixel translation table to use when
|
|
; drawing the icon. Transparency check is performed AFTER the remap so it is possible to
|
|
; remap valid colors to be invisible (for special effect reasons).
|
|
; This routine is fastest when no remap table is passed in.
|
|
;*
|
|
*/
|
|
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)
|
|
{
|
|
|
|
|
|
unsigned int modulo = 0;
|
|
unsigned int iwidth = 0;
|
|
unsigned int skip = 0;
|
|
unsigned char doremap = 0;
|
|
|
|
|
|
/*
|
|
ARG this_object:DWORD ; this is a member function
|
|
ARG icondata:DWORD ; Pointer to icondata.
|
|
ARG icon:DWORD ; Icon number to draw.
|
|
ARG x_pixel:DWORD ; X coordinate of icon.
|
|
ARG y_pixel:DWORD ; Y coordinate of icon.
|
|
ARG remap:DWORD ; Remap table.
|
|
ARG min_x:DWORD ; Clipping rectangle boundary
|
|
ARG min_y:DWORD ; Clipping rectangle boundary
|
|
ARG max_x:DWORD ; Clipping rectangle boundary
|
|
ARG max_y:DWORD ; Clipping rectangle boundary
|
|
|
|
LOCAL modulo:DWORD ; Modulo to get to next row.
|
|
LOCAL iwidth:DWORD ; Icon width (here for speedy access).
|
|
LOCAL skip:DWORD ; amount to skip per row of icon data
|
|
LOCAL doremap:BYTE ; Should remapping occur?
|
|
*/
|
|
__asm {
|
|
pushad
|
|
cmp [icondata],0
|
|
je proc_out
|
|
|
|
; Initialize the stamp data if necessary.
|
|
mov eax,[icondata]
|
|
cmp [LastIconset],eax
|
|
je short noreset2
|
|
push eax
|
|
call Init_Stamps
|
|
pop eax // Clean up stack. ST - 12/20/2018 10:42AM
|
|
noreset2:
|
|
|
|
; Determine if the icon number requested is actually in the set.
|
|
; Perform the logical icon to actual icon number remap if necessary.
|
|
mov ebx,[icon]
|
|
cmp [MapPtr],0
|
|
je short notmap2
|
|
mov edi,[MapPtr]
|
|
mov bl,[edi+ebx]
|
|
notmap2:
|
|
cmp ebx,[IconCount]
|
|
jae proc_out
|
|
mov [icon],ebx ; Updated icon number.
|
|
|
|
; Setup some working variables.
|
|
mov ecx,[IconHeight] ; Row counter.
|
|
mov eax,[IconWidth]
|
|
mov [iwidth],eax ; Stack copy of byte width for easy BP access.
|
|
|
|
; Fetch pointer to start of icon's data. ESI = ptr to icon data.
|
|
mov eax,[icon]
|
|
mul [IconSize]
|
|
mov esi,[StampPtr]
|
|
add esi,eax
|
|
|
|
; Update the clipping window coordinates to be valid maxes instead of width & height
|
|
; , and change the coordinates to be window-relative
|
|
mov ebx,[min_x]
|
|
add [max_x],ebx
|
|
add [x_pixel],ebx ; make it window-relative
|
|
mov ebx,[min_y]
|
|
add [max_y],ebx
|
|
add [y_pixel],ebx ; make it window-relative
|
|
|
|
; See if the icon is within the clipping window
|
|
; First, verify that the icon position is less than the maximums
|
|
mov ebx,[x_pixel]
|
|
cmp ebx,[max_x]
|
|
jge proc_out
|
|
mov ebx,[y_pixel]
|
|
cmp ebx,[max_y]
|
|
jge proc_out
|
|
; Now verify that the icon position is >= the minimums
|
|
add ebx,[IconHeight]
|
|
cmp ebx,[min_y]
|
|
jle proc_out
|
|
mov ebx,[x_pixel]
|
|
add ebx,[IconWidth]
|
|
cmp ebx,[min_x]
|
|
jle proc_out
|
|
|
|
; Now, clip the x, y, width, and height variables to be within the
|
|
; clipping rectangle
|
|
mov ebx,[x_pixel]
|
|
cmp ebx,[min_x]
|
|
jge nominxclip
|
|
; x < minx, so must clip
|
|
mov ebx,[min_x]
|
|
sub ebx,[x_pixel]
|
|
add esi,ebx ; source ptr += (minx - x)
|
|
sub [iwidth],ebx ; icon width -= (minx - x)
|
|
mov ebx,[min_x]
|
|
mov [x_pixel],ebx
|
|
|
|
nominxclip:
|
|
mov eax,[IconWidth]
|
|
sub eax,[iwidth]
|
|
mov [skip],eax
|
|
|
|
; Check for x+width > max_x
|
|
mov eax,[x_pixel]
|
|
add eax,[iwidth]
|
|
cmp eax,[max_x]
|
|
jle nomaxxclip
|
|
; x+width is greater than max_x, so must clip width down
|
|
mov eax,[iwidth] ; eax = old width
|
|
mov ebx,[max_x]
|
|
sub ebx,[x_pixel]
|
|
mov [iwidth],ebx ; iwidth = max_x - xpixel
|
|
sub eax,ebx
|
|
add [skip],eax ; skip += (old width - iwidth)
|
|
nomaxxclip:
|
|
; check if y < miny
|
|
mov eax,[min_y]
|
|
cmp eax,[y_pixel] ; if(miny <= y_pixel), no clip needed
|
|
jle nominyclip
|
|
sub eax,[y_pixel]
|
|
sub ecx,eax ; height -= (miny - y)
|
|
mul [IconWidth]
|
|
add esi,eax ; icon source ptr += (width * (miny - y))
|
|
mov eax,[min_y]
|
|
mov [y_pixel],eax ; y = miny
|
|
nominyclip:
|
|
; check if (y+height) > max y
|
|
mov eax,[y_pixel]
|
|
add eax,ecx
|
|
cmp eax,[max_y] ; if (y + height <= max_y), no clip needed
|
|
jle nomaxyclip
|
|
mov ecx,[max_y] ; height = max_y - y_pixel
|
|
sub ecx,[y_pixel]
|
|
nomaxyclip:
|
|
|
|
; If the remap table pointer passed in is NULL, then flag this condition
|
|
; so that the faster (non-remapping) icon draw loop will be used.
|
|
cmp [remap],0
|
|
setne [doremap]
|
|
|
|
; Get pointer to position to render icon. EDI = ptr to destination page.
|
|
mov ebx,[this_object]
|
|
mov edi,[ebx]GraphicViewPortClass.Offset
|
|
mov eax,[ebx]GraphicViewPortClass.Width
|
|
add eax,[ebx]GraphicViewPortClass.XAdd
|
|
add eax,[ebx]GraphicViewPortClass.Pitch
|
|
push eax ; save viewport full width for lower
|
|
mul [y_pixel]
|
|
add edi,eax
|
|
add edi,[x_pixel]
|
|
|
|
; Determine row modulo for advancing to next line.
|
|
pop eax ; retrieve viewport width
|
|
sub eax,[iwidth]
|
|
mov [modulo],eax
|
|
|
|
; Determine whether simple icon draw is sufficient or whether the
|
|
; extra remapping icon draw is needed.
|
|
cmp [BYTE PTR doremap],0
|
|
je short istranscheck2
|
|
|
|
;************************************************************
|
|
; Complex icon draw -- extended remap.
|
|
; EBX = Palette pointer (ready for XLAT instruction).
|
|
; EDI = Pointer to icon destination in page.
|
|
; ESI = Pointer to icon data.
|
|
; ECX = Number of pixel rows.
|
|
mov ebx,[remap]
|
|
xor eax,eax
|
|
xrowloopc:
|
|
push ecx
|
|
mov ecx,[iwidth]
|
|
|
|
xcolumnloopc:
|
|
lodsb
|
|
xlatb
|
|
or al,al
|
|
jz short xskip1c ; Transparency skip check.
|
|
mov [edi],al
|
|
xskip1c:
|
|
inc edi
|
|
loop xcolumnloopc
|
|
|
|
pop ecx
|
|
add edi,[modulo]
|
|
add esi,[skip]
|
|
loop xrowloopc
|
|
jmp short proc_out
|
|
|
|
|
|
;************************************************************
|
|
; Check to see if transparent or generic draw is necessary.
|
|
istranscheck2:
|
|
mov ebx,[IsTrans]
|
|
add ebx,[icon]
|
|
cmp [BYTE PTR ebx],0
|
|
jne short rowloopc
|
|
|
|
;************************************************************
|
|
; Fast non-transparent icon draw routine.
|
|
; ES:DI = Pointer to icon destination in page.
|
|
; DS:SI = Pointer to icon data.
|
|
; CX = Number of pixel rows.
|
|
mov ebx,ecx
|
|
mov edx,[modulo]
|
|
mov eax,[iwidth]
|
|
|
|
;
|
|
; Optimise copy by dword aligning the destination
|
|
;
|
|
loop1c:
|
|
push eax
|
|
//rept 3 // No rept in inline asm. ST - 12/20/2018 10:43AM
|
|
test edi,3
|
|
jz aligned
|
|
movsb
|
|
dec eax
|
|
jz finishedit
|
|
|
|
test edi,3
|
|
jz aligned
|
|
movsb
|
|
dec eax
|
|
jz finishedit
|
|
|
|
test edi,3
|
|
jz aligned
|
|
movsb
|
|
dec eax
|
|
jz finishedit
|
|
|
|
//endm
|
|
aligned:
|
|
mov ecx,eax
|
|
shr ecx,2
|
|
rep movsd
|
|
mov ecx,eax
|
|
and ecx,3
|
|
rep movsb
|
|
|
|
finishedit:
|
|
add edi,edx
|
|
add esi,[skip]
|
|
pop eax
|
|
|
|
dec ebx
|
|
jnz loop1c
|
|
jmp short proc_out
|
|
|
|
;************************************************************
|
|
; Transparent icon draw routine -- no extended remap.
|
|
; ES:DI = Pointer to icon destination in page.
|
|
; DS:SI = Pointer to icon data.
|
|
; CX = Number of pixel rows.
|
|
rowloopc:
|
|
push ecx
|
|
mov ecx,[iwidth]
|
|
|
|
columnloopc:
|
|
lodsb
|
|
or al,al
|
|
jz short skip1c ; Transparency check.
|
|
mov [edi],al
|
|
skip1c:
|
|
inc edi
|
|
loop columnloopc
|
|
|
|
pop ecx
|
|
add edi,[modulo]
|
|
add esi,[skip]
|
|
loop rowloopc
|
|
|
|
; Cleanup and exit icon drawing routine.
|
|
proc_out:
|
|
popad
|
|
//ret
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID __cdecl Buffer_Draw_Line(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);
|
|
VOID __cdecl Buffer_Fill_Rect(void *thisptr, int sx, int sy, int dx, int dy, unsigned char color);
|
|
VOID __cdecl Buffer_Remap(void * thisptr, int sx, int sy, int width, int height, void *remap);
|
|
VOID __cdecl Buffer_Fill_Quad(void * thisptr, VOID *span_buff, int x0, int y0, int x1, int y1,
|
|
int x2, int y2, int x3, int y3, int color);
|
|
void __cdecl Buffer_Draw_Stamp(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap);
|
|
void __cdecl Buffer_Draw_Stamp_Clip(void const *thisptr, void const *icondata, int icon, int x_pixel, int y_pixel, void const *remap, int ,int,int,int);
|
|
void * __cdecl Get_Font_Palette_Ptr ( void );
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
|
|
;***************************************************************************
|
|
;* *
|
|
;* Project Name : Westwood 32 bit Library *
|
|
;* *
|
|
;* File Name : REMAP.ASM *
|
|
;* *
|
|
;* Programmer : Phil W. Gorrow *
|
|
;* *
|
|
;* Start Date : July 1, 1994 *
|
|
;* *
|
|
;* Last Update : July 1, 1994 [PWG] *
|
|
;* *
|
|
;*-------------------------------------------------------------------------*
|
|
;* Functions: *
|
|
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
|
*/
|
|
|
|
|
|
VOID __cdecl Buffer_Remap(void * this_object, int sx, int sy, int width, int height, void *remap)
|
|
{
|
|
/*
|
|
PROC Buffer_Remap C NEAR
|
|
USES eax,ebx,ecx,edx,esi,edi
|
|
|
|
;*===================================================================
|
|
;* Define the arguements that our function takes.
|
|
;*===================================================================
|
|
ARG this_object:DWORD
|
|
ARG x0_pixel:DWORD
|
|
ARG y0_pixel:DWORD
|
|
ARG region_width:DWORD
|
|
ARG region_height:DWORD
|
|
ARG remap :DWORD
|
|
|
|
;*===================================================================
|
|
; Define some locals so that we can handle things quickly
|
|
;*===================================================================
|
|
local x1_pixel : DWORD
|
|
local y1_pixel : DWORD
|
|
local win_width : dword
|
|
local counter_x : dword
|
|
*/
|
|
|
|
unsigned int x0_pixel = (unsigned int) sx;
|
|
unsigned int y0_pixel = (unsigned int) sy;
|
|
unsigned int region_width = (unsigned int) width;
|
|
unsigned int region_height = (unsigned int) height;
|
|
|
|
unsigned int x1_pixel = 0;
|
|
unsigned int y1_pixel = 0;
|
|
unsigned int win_width = 0;
|
|
unsigned int counter_x = 0;
|
|
|
|
__asm {
|
|
|
|
cmp [ remap ] , 0
|
|
jz real_out
|
|
|
|
; Clip Source Rectangle against source Window boundaries.
|
|
mov esi , [ this_object ] ; get ptr to src
|
|
xor ecx , ecx
|
|
xor edx , edx
|
|
mov edi , [esi]GraphicViewPortClass.Width ; get width into register
|
|
mov ebx , [ x0_pixel ]
|
|
mov eax , [ x0_pixel ]
|
|
add ebx , [ region_width ]
|
|
shld ecx , eax , 1
|
|
mov [ x1_pixel ] , ebx
|
|
inc edi
|
|
shld edx , ebx , 1
|
|
sub eax , edi
|
|
sub ebx , edi
|
|
shld ecx , eax , 1
|
|
shld edx , ebx , 1
|
|
|
|
mov edi,[esi]GraphicViewPortClass.Height ; get height into register
|
|
mov ebx , [ y0_pixel ]
|
|
mov eax , [ y0_pixel ]
|
|
add ebx , [ region_height ]
|
|
shld ecx , eax , 1
|
|
mov [ y1_pixel ] , ebx
|
|
inc edi
|
|
shld edx , ebx , 1
|
|
sub eax , edi
|
|
sub ebx , edi
|
|
shld ecx , eax , 1
|
|
shld edx , ebx , 1
|
|
|
|
xor cl , 5
|
|
xor dl , 5
|
|
mov al , cl
|
|
test dl , cl
|
|
jnz real_out
|
|
or al , dl
|
|
jz do_remap
|
|
|
|
test cl , 1000b
|
|
jz scr_left_ok
|
|
mov [ x0_pixel ] , 0
|
|
|
|
scr_left_ok:
|
|
test cl , 0010b
|
|
jz scr_bottom_ok
|
|
mov [ y0_pixel ] , 0
|
|
|
|
scr_bottom_ok:
|
|
test dl , 0100b
|
|
jz scr_right_ok
|
|
mov eax , [esi]GraphicViewPortClass.Width ; get width into register
|
|
mov [ x1_pixel ] , eax
|
|
scr_right_ok:
|
|
test dl , 0001b
|
|
jz do_remap
|
|
mov eax , [esi]GraphicViewPortClass.Height ; get width into register
|
|
mov [ y1_pixel ] , eax
|
|
|
|
|
|
do_remap:
|
|
cld
|
|
mov edi , [esi]GraphicViewPortClass.Offset
|
|
mov eax , [esi]GraphicViewPortClass.XAdd
|
|
mov ebx , [ x1_pixel ]
|
|
add eax , [esi]GraphicViewPortClass.Width
|
|
add eax , [esi]GraphicViewPortClass.Pitch
|
|
mov esi , eax
|
|
mul [ y0_pixel ]
|
|
add edi , [ x0_pixel ]
|
|
sub ebx , [ x0_pixel ]
|
|
jle real_out
|
|
add edi , eax
|
|
sub esi , ebx
|
|
|
|
mov ecx , [ y1_pixel ]
|
|
sub ecx , [ y0_pixel ]
|
|
jle real_out
|
|
mov eax , [ remap ]
|
|
mov [ counter_x ] , ebx
|
|
xor edx , edx
|
|
|
|
outer_loop:
|
|
mov ebx , [ counter_x ]
|
|
inner_loop:
|
|
mov dl , [ edi ]
|
|
mov dl , [ eax + edx ]
|
|
mov [ edi ] , dl
|
|
inc edi
|
|
dec ebx
|
|
jnz inner_loop
|
|
add edi , esi
|
|
dec ecx
|
|
jnz outer_loop
|
|
|
|
|
|
|
|
|
|
real_out:
|
|
// ret
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
; **************************************************************************
|
|
; ** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S *
|
|
; **************************************************************************
|
|
; * *
|
|
; * Project Name : WSA Support routines *
|
|
; * *
|
|
; * File Name : XORDELTA.ASM *
|
|
; * *
|
|
; * Programmer : Scott K. Bowen *
|
|
; * *
|
|
; * Last Update :May 23, 1994 [SKB] *
|
|
; * *
|
|
; *------------------------------------------------------------------------*
|
|
; * Functions: *
|
|
;* Apply_XOR_Delta -- Apply XOR delta data to a buffer. *
|
|
;* Apply_XOR_Delta_To_Page_Or_Viewport -- Calls the copy or the XOR funti*
|
|
;* Copy_Delta_buffer -- Copies XOR Delta Data to a section of a page. *
|
|
;* XOR_Delta_Buffer -- Xor's the data in a XOR Delta format to a page. *
|
|
; * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
|
|
|
|
IDEAL
|
|
P386
|
|
MODEL USE32 FLAT
|
|
*/
|
|
|
|
|
|
/*
|
|
LOCALS ??
|
|
|
|
; These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter. If
|
|
; These change, make sure and change their values in wsa.cpp.
|
|
DO_XOR equ 0
|
|
DO_COPY equ 1
|
|
TO_VIEWPORT equ 0
|
|
TO_PAGE equ 2
|
|
|
|
;
|
|
; Routines defined in this module
|
|
;
|
|
;
|
|
; UWORD Apply_XOR_Delta(UWORD page_seg, BYTE *delta_ptr);
|
|
; PUBLIC Apply_XOR_Delta_To_Page_Or_Viewport(UWORD page_seg, BYTE *delta_ptr, WORD width, WORD copy)
|
|
;
|
|
; PROC C XOR_Delta_Buffer
|
|
; PROC C Copy_Delta_Buffer
|
|
;
|
|
|
|
GLOBAL C Apply_XOR_Delta:NEAR
|
|
GLOBAL C Apply_XOR_Delta_To_Page_Or_Viewport:NEAR
|
|
*/
|
|
|
|
#define DO_XOR 0
|
|
#define DO_COPY 1
|
|
#define TO_VIEWPORT 0
|
|
#define TO_PAGE 2
|
|
|
|
void __cdecl XOR_Delta_Buffer(int nextrow);
|
|
void __cdecl Copy_Delta_Buffer(int nextrow);
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;* APPLY_XOR_DELTA -- Apply XOR delta data to a linear buffer. *
|
|
;* AN example of this in C is at the botton of the file commented out. *
|
|
;* *
|
|
;* INPUT: BYTE *target - destination buffer. *
|
|
;* BYTE *delta - xor data to be delta uncompress. *
|
|
;* *
|
|
;* OUTPUT: *
|
|
;* *
|
|
;* WARNINGS: *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 05/23/1994 SKB : Created. *
|
|
;*=========================================================================*
|
|
*/
|
|
unsigned int __cdecl Apply_XOR_Delta(char *target, char *delta)
|
|
{
|
|
/*
|
|
PROC Apply_XOR_Delta C near
|
|
USES ebx,ecx,edx,edi,esi
|
|
ARG target:DWORD ; pointers.
|
|
ARG delta:DWORD ; pointers.
|
|
*/
|
|
|
|
__asm {
|
|
|
|
; Optimized for 486/pentium by rearanging instructions.
|
|
mov edi,[target] ; get our pointers into offset registers.
|
|
mov esi,[delta]
|
|
|
|
cld ; make sure we go forward
|
|
xor ecx,ecx ; use cx for loop
|
|
|
|
top_loop:
|
|
xor eax,eax ; clear out eax.
|
|
mov al,[esi] ; get delta source byte
|
|
inc esi
|
|
|
|
test al,al ; check for a SHORTDUMP ; check al incase of sign value.
|
|
je short_run
|
|
js check_others
|
|
|
|
;
|
|
; SHORTDUMP
|
|
;
|
|
mov ecx,eax ; stick count in cx
|
|
|
|
dump_loop:
|
|
mov al,[esi] ;get delta XOR byte
|
|
xor [edi],al ; xor that byte on the dest
|
|
inc esi
|
|
inc edi
|
|
dec ecx
|
|
jnz dump_loop
|
|
jmp top_loop
|
|
|
|
;
|
|
; SHORTRUN
|
|
;
|
|
|
|
short_run:
|
|
mov cl,[esi] ; get count
|
|
inc esi ; inc delta source
|
|
|
|
do_run:
|
|
mov al,[esi] ; get XOR byte
|
|
inc esi
|
|
|
|
run_loop:
|
|
xor [edi],al ; xor that byte.
|
|
|
|
inc edi ; go to next dest pixel
|
|
dec ecx ; one less to go.
|
|
jnz run_loop
|
|
jmp top_loop
|
|
|
|
;
|
|
; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP
|
|
;
|
|
|
|
check_others:
|
|
sub eax,080h ; opcode -= 0x80
|
|
jnz do_skip ; if zero then get next word, otherwise use remainder.
|
|
|
|
mov ax,[esi]
|
|
lea esi,[esi+2] ; get word code in ax
|
|
test ax,ax ; set flags. (not 32bit register so neg flag works)
|
|
jle not_long_skip
|
|
|
|
;
|
|
; SHORTSKIP AND LONGSKIP
|
|
;
|
|
do_skip:
|
|
add edi,eax ; do the skip.
|
|
jmp top_loop
|
|
|
|
|
|
not_long_skip:
|
|
jz stop ; long count of zero means stop
|
|
sub eax,08000h ; opcode -= 0x8000
|
|
test eax,04000h ; is it a LONGRUN (code & 0x4000)?
|
|
je long_dump
|
|
|
|
;
|
|
; LONGRUN
|
|
;
|
|
sub eax,04000h ; opcode -= 0x4000
|
|
mov ecx,eax ; use cx as loop count
|
|
jmp do_run ; jump to run code.
|
|
|
|
|
|
;
|
|
; LONGDUMP
|
|
;
|
|
|
|
long_dump:
|
|
mov ecx,eax ; use cx as loop count
|
|
jmp dump_loop ; go to the dump loop.
|
|
|
|
stop:
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
;----------------------------------------------------------------------------
|
|
|
|
;***************************************************************************
|
|
;* APPLY_XOR_DELTA_To_Page_Or_Viewport -- Calls the copy or the XOR funtion. *
|
|
;* *
|
|
;* *
|
|
;* This funtion is call to either xor or copy XOR_Delta data onto a *
|
|
;* page instead of a buffer. The routine will set up the registers *
|
|
;* need for the actual routines that will perform the copy or xor. *
|
|
;* *
|
|
;* The registers are setup as follows : *
|
|
;* es:edi - destination segment:offset onto page. *
|
|
;* ds:esi - source buffer segment:offset of delta data. *
|
|
;* dx,cx,ax - are all zeroed out before entry. *
|
|
;* *
|
|
;* INPUT: *
|
|
;* *
|
|
;* OUTPUT: *
|
|
;* *
|
|
;* WARNINGS: *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 03/09/1992 SB : Created. *
|
|
;*=========================================================================*
|
|
*/
|
|
|
|
void __cdecl Apply_XOR_Delta_To_Page_Or_Viewport(void *target, void *delta, int width, int nextrow, int copy)
|
|
{
|
|
/*
|
|
USES ebx,ecx,edx,edi,esi
|
|
ARG target:DWORD ; pointer to the destination buffer.
|
|
ARG delta:DWORD ; pointer to the delta buffer.
|
|
ARG width:DWORD ; width of animation.
|
|
ARG nextrow:DWORD ; Page/Buffer width - anim width.
|
|
ARG copy:DWORD ; should it be copied or xor'd?
|
|
*/
|
|
|
|
__asm {
|
|
|
|
mov edi,[target] ; Get the target pointer.
|
|
mov esi,[delta] ; Get the destination pointer.
|
|
|
|
xor eax,eax ; clear eax, later put them into ecx and edx.
|
|
|
|
cld ; make sure we go forward
|
|
|
|
mov ebx,[nextrow] ; get the amount to add to get to next row from end. push it later...
|
|
|
|
mov ecx,eax ; use cx for loop
|
|
mov edx,eax ; use dx to count the relative column.
|
|
|
|
push ebx ; push nextrow onto the stack for Copy/XOR_Delta_Buffer.
|
|
mov ebx,[width] ; bx will hold the max column for speed compares
|
|
|
|
; At this point, all the registers have been set up. Now call the correct function
|
|
; to either copy or xor the data.
|
|
|
|
cmp [copy],DO_XOR ; Do we want to copy or XOR
|
|
je xorfunct ; Jump to XOR if not copy
|
|
call Copy_Delta_Buffer ; Call the function to copy the delta buffer.
|
|
jmp didcopy ; jump past XOR
|
|
xorfunct:
|
|
call XOR_Delta_Buffer ; Call funtion to XOR the deltat buffer.
|
|
didcopy:
|
|
pop ebx ; remove the push done to pass a value.
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
;----------------------------------------------------------------------------
|
|
|
|
|
|
;***************************************************************************
|
|
;* XOR_DELTA_BUFFER -- Xor's the data in a XOR Delta format to a page. *
|
|
;* This will only work right if the page has the previous data on it. *
|
|
;* This function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport. *
|
|
;* The registers must be setup as follows : *
|
|
;* *
|
|
;* INPUT: *
|
|
;* es:edi - destination segment:offset onto page. *
|
|
;* ds:esi - source buffer segment:offset of delta data. *
|
|
;* edx,ecx,eax - are all zeroed out before entry. *
|
|
;* *
|
|
;* OUTPUT: *
|
|
;* *
|
|
;* WARNINGS: *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 03/09/1992 SB : Created. *
|
|
;*=========================================================================*
|
|
*/
|
|
void __cdecl XOR_Delta_Buffer(int nextrow)
|
|
{
|
|
/*
|
|
ARG nextrow:DWORD
|
|
*/
|
|
|
|
__asm {
|
|
|
|
top_loop:
|
|
xor eax,eax ; clear out eax.
|
|
mov al,[esi] ; get delta source byte
|
|
inc esi
|
|
|
|
test al,al ; check for a SHORTDUMP ; check al incase of sign value.
|
|
je short_run
|
|
js check_others
|
|
|
|
;
|
|
; SHORTDUMP
|
|
;
|
|
mov ecx,eax ; stick count in cx
|
|
|
|
dump_loop:
|
|
mov al,[esi] ; get delta XOR byte
|
|
xor [edi],al ; xor that byte on the dest
|
|
inc esi
|
|
inc edx ; increment our count on current column
|
|
inc edi
|
|
cmp edx,ebx ; are we at the final column
|
|
jne end_col1 ; if not the jmp over the code
|
|
|
|
sub edi,edx ; get our column back to the beginning.
|
|
xor edx,edx ; zero out our column counter
|
|
add edi,[nextrow] ; jump to start of next row
|
|
end_col1:
|
|
|
|
dec ecx
|
|
jnz dump_loop
|
|
jmp top_loop
|
|
|
|
;
|
|
; SHORTRUN
|
|
;
|
|
|
|
short_run:
|
|
mov cl,[esi] ; get count
|
|
inc esi ; inc delta source
|
|
|
|
do_run:
|
|
mov al,[esi] ; get XOR byte
|
|
inc esi
|
|
|
|
run_loop:
|
|
xor [edi],al ; xor that byte.
|
|
|
|
inc edx ; increment our count on current column
|
|
inc edi ; go to next dest pixel
|
|
cmp edx,ebx ; are we at the final column
|
|
jne end_col2 ; if not the jmp over the code
|
|
|
|
sub edi,ebx ; get our column back to the beginning.
|
|
xor edx,edx ; zero out our column counter
|
|
add edi,[nextrow] ; jump to start of next row
|
|
end_col2:
|
|
|
|
|
|
dec ecx
|
|
jnz run_loop
|
|
jmp top_loop
|
|
|
|
;
|
|
; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP
|
|
;
|
|
|
|
check_others:
|
|
sub eax,080h ; opcode -= 0x80
|
|
jnz do_skip ; if zero then get next word, otherwise use remainder.
|
|
|
|
mov ax,[esi] ; get word code in ax
|
|
lea esi,[esi+2]
|
|
test ax,ax ; set flags. (not 32bit register so neg flag works)
|
|
jle not_long_skip
|
|
|
|
;
|
|
; SHORTSKIP AND LONGSKIP
|
|
;
|
|
do_skip:
|
|
sub edi,edx ; go back to beginning or row.
|
|
add edx,eax ; incriment our count on current row
|
|
recheck3:
|
|
cmp edx,ebx ; are we past the end of the row
|
|
jb end_col3 ; if not the jmp over the code
|
|
|
|
sub edx,ebx ; Subtract width from the col counter
|
|
add edi,[nextrow] ; jump to start of next row
|
|
jmp recheck3 ; jump up to see if we are at the right row
|
|
end_col3:
|
|
add edi,edx ; get to correct position in row.
|
|
jmp top_loop
|
|
|
|
|
|
not_long_skip:
|
|
jz stop ; long count of zero means stop
|
|
sub eax,08000h ; opcode -= 0x8000
|
|
test eax,04000h ; is it a LONGRUN (code & 0x4000)?
|
|
je long_dump
|
|
|
|
;
|
|
; LONGRUN
|
|
;
|
|
sub eax,04000h ; opcode -= 0x4000
|
|
mov ecx,eax ; use cx as loop count
|
|
jmp do_run ; jump to run code.
|
|
|
|
|
|
;
|
|
; LONGDUMP
|
|
;
|
|
|
|
long_dump:
|
|
mov ecx,eax ; use cx as loop count
|
|
jmp dump_loop ; go to the dump loop.
|
|
|
|
stop:
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
;----------------------------------------------------------------------------
|
|
|
|
|
|
;***************************************************************************
|
|
;* COPY_DELTA_BUFFER -- Copies XOR Delta Data to a section of a page. *
|
|
;* This function should only be called by XOR_Delta_Buffer_To_Page_Or_Viewport. *
|
|
;* The registers must be setup as follows : *
|
|
;* *
|
|
;* INPUT: *
|
|
;* es:edi - destination segment:offset onto page. *
|
|
;* ds:esi - source buffer segment:offset of delta data. *
|
|
;* dx,cx,ax - are all zeroed out before entry. *
|
|
;* *
|
|
;* OUTPUT: *
|
|
;* *
|
|
;* WARNINGS: *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 03/09/1992 SB : Created. *
|
|
;*=========================================================================*
|
|
*/
|
|
void __cdecl Copy_Delta_Buffer(int nextrow)
|
|
{
|
|
/*
|
|
ARG nextrow:DWORD
|
|
*/
|
|
|
|
__asm {
|
|
|
|
top_loop:
|
|
xor eax,eax ; clear out eax.
|
|
mov al,[esi] ; get delta source byte
|
|
inc esi
|
|
|
|
test al,al ; check for a SHORTDUMP ; check al incase of sign value.
|
|
je short_run
|
|
js check_others
|
|
|
|
;
|
|
; SHORTDUMP
|
|
;
|
|
mov ecx,eax ; stick count in cx
|
|
|
|
dump_loop:
|
|
mov al,[esi] ; get delta XOR byte
|
|
|
|
mov [edi],al ; store that byte on the dest
|
|
|
|
inc edx ; increment our count on current column
|
|
inc esi
|
|
inc edi
|
|
cmp edx,ebx ; are we at the final column
|
|
jne end_col1 ; if not the jmp over the code
|
|
|
|
sub edi,edx ; get our column back to the beginning.
|
|
xor edx,edx ; zero out our column counter
|
|
add edi,[nextrow] ; jump to start of next row
|
|
end_col1:
|
|
|
|
dec ecx
|
|
jnz dump_loop
|
|
jmp top_loop
|
|
|
|
;
|
|
; SHORTRUN
|
|
;
|
|
|
|
short_run:
|
|
mov cl,[esi] ; get count
|
|
inc esi ; inc delta source
|
|
|
|
do_run:
|
|
mov al,[esi] ; get XOR byte
|
|
inc esi
|
|
|
|
run_loop:
|
|
mov [edi],al ; store the byte (instead of XOR against current color)
|
|
|
|
inc edx ; increment our count on current column
|
|
inc edi ; go to next dest pixel
|
|
cmp edx,ebx ; are we at the final column
|
|
jne end_col2 ; if not the jmp over the code
|
|
|
|
sub edi,ebx ; get our column back to the beginning.
|
|
xor edx,edx ; zero out our column counter
|
|
add edi,[nextrow] ; jump to start of next row
|
|
end_col2:
|
|
|
|
|
|
dec ecx
|
|
jnz run_loop
|
|
jmp top_loop
|
|
|
|
;
|
|
; By now, we know it must be a LONGDUMP, SHORTSKIP, LONGRUN, or LONGSKIP
|
|
;
|
|
|
|
check_others:
|
|
sub eax,080h ; opcode -= 0x80
|
|
jnz do_skip ; if zero then get next word, otherwise use remainder.
|
|
|
|
mov ax,[esi] ; get word code in ax
|
|
lea esi,[esi+2]
|
|
test ax,ax ; set flags. (not 32bit register so neg flag works)
|
|
jle not_long_skip
|
|
|
|
;
|
|
; SHORTSKIP AND LONGSKIP
|
|
;
|
|
do_skip:
|
|
sub edi,edx ; go back to beginning or row.
|
|
add edx,eax ; incriment our count on current row
|
|
recheck3:
|
|
cmp edx,ebx ; are we past the end of the row
|
|
jb end_col3 ; if not the jmp over the code
|
|
|
|
sub edx,ebx ; Subtract width from the col counter
|
|
add edi,[nextrow] ; jump to start of next row
|
|
jmp recheck3 ; jump up to see if we are at the right row
|
|
end_col3:
|
|
add edi,edx ; get to correct position in row.
|
|
jmp top_loop
|
|
|
|
|
|
not_long_skip:
|
|
jz stop ; long count of zero means stop
|
|
sub eax,08000h ; opcode -= 0x8000
|
|
test eax,04000h ; is it a LONGRUN (code & 0x4000)?
|
|
je long_dump
|
|
|
|
;
|
|
; LONGRUN
|
|
;
|
|
sub eax,04000h ; opcode -= 0x4000
|
|
mov ecx,eax ; use cx as loop count
|
|
jmp do_run ; jump to run code.
|
|
|
|
|
|
;
|
|
; LONGDUMP
|
|
;
|
|
|
|
long_dump:
|
|
mov ecx,eax ; use cx as loop count
|
|
jmp dump_loop ; go to the dump loop.
|
|
|
|
stop:
|
|
|
|
}
|
|
}
|
|
/*
|
|
;----------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
|
;***************************************************************************
|
|
;* *
|
|
;* Project Name : Westwood Library *
|
|
;* *
|
|
;* File Name : FADING.ASM *
|
|
;* *
|
|
;* Programmer : Joe L. Bostic *
|
|
;* *
|
|
;* Start Date : August 20, 1993 *
|
|
;* *
|
|
;* Last Update : August 20, 1993 [JLB] *
|
|
;* *
|
|
;*-------------------------------------------------------------------------*
|
|
;* Functions: *
|
|
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
|
|
|
IDEAL
|
|
P386
|
|
MODEL USE32 FLAT
|
|
|
|
GLOBAL C Build_Fading_Table :NEAR
|
|
|
|
CODESEG
|
|
|
|
;***********************************************************
|
|
; BUILD_FADING_TABLE
|
|
;
|
|
; void *Build_Fading_Table(void *palette, void *dest, long int color, long int frac);
|
|
;
|
|
; This routine will create the fading effect table used to coerce colors
|
|
; from toward a common value. This table is used when Fading_Effect is
|
|
; active.
|
|
;
|
|
; Bounds Checking: None
|
|
;*
|
|
*/
|
|
void * __cdecl Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac)
|
|
{
|
|
/*
|
|
PROC Build_Fading_Table C near
|
|
USES ebx, ecx, edi, esi
|
|
ARG palette:DWORD
|
|
ARG dest:DWORD
|
|
ARG color:DWORD
|
|
ARG frac:DWORD
|
|
|
|
LOCAL matchvalue:DWORD ; Last recorded match value.
|
|
LOCAL targetred:BYTE ; Target gun red.
|
|
LOCAL targetgreen:BYTE ; Target gun green.
|
|
LOCAL targetblue:BYTE ; Target gun blue.
|
|
LOCAL idealred:BYTE
|
|
LOCAL idealgreen:BYTE
|
|
LOCAL idealblue:BYTE
|
|
LOCAL matchcolor:BYTE ; Tentative match color.
|
|
*/
|
|
|
|
int matchvalue = 0; //:DWORD ; Last recorded match value.
|
|
unsigned char targetred = 0; //BYTE ; Target gun red.
|
|
unsigned char targetgreen = 0; //BYTE ; Target gun green.
|
|
unsigned char targetblue = 0; //BYTE ; Target gun blue.
|
|
unsigned char idealred = 0; //BYTE
|
|
unsigned char idealgreen = 0; //BYTE
|
|
unsigned char idealblue = 0; //BYTE
|
|
unsigned char matchcolor = 0; //:BYTE ; Tentative match color.
|
|
|
|
__asm {
|
|
cld
|
|
|
|
; If the source palette is NULL, then just return with current fading table pointer.
|
|
cmp [palette],0
|
|
je fini
|
|
cmp [dest],0
|
|
je fini
|
|
|
|
; Fractions above 255 become 255.
|
|
mov eax,[frac]
|
|
cmp eax,0100h
|
|
jb short ok
|
|
mov [frac],0FFh
|
|
ok:
|
|
|
|
; Record the target gun values.
|
|
mov esi,[palette]
|
|
mov ebx,[color]
|
|
add esi,ebx
|
|
add esi,ebx
|
|
add esi,ebx
|
|
lodsb
|
|
mov [targetred],al
|
|
lodsb
|
|
mov [targetgreen],al
|
|
lodsb
|
|
mov [targetblue],al
|
|
|
|
; Main loop.
|
|
xor ebx,ebx ; Remap table index.
|
|
|
|
; Transparent black never gets remapped.
|
|
mov edi,[dest]
|
|
mov [edi],bl
|
|
inc edi
|
|
|
|
; EBX = source palette logical number (1..255).
|
|
; EDI = running pointer into dest remap table.
|
|
mainloop:
|
|
inc ebx
|
|
mov esi,[palette]
|
|
add esi,ebx
|
|
add esi,ebx
|
|
add esi,ebx
|
|
|
|
mov edx,[frac]
|
|
shr edx,1
|
|
; new = orig - ((orig-target) * fraction);
|
|
|
|
lodsb ; orig
|
|
mov dh,al ; preserve it for later.
|
|
sub al,[targetred] ; al = (orig-target)
|
|
imul dl ; ax = (orig-target)*fraction
|
|
shl ax,1
|
|
sub dh,ah ; dh = orig - ((orig-target) * fraction)
|
|
mov [idealred],dh ; preserve ideal color gun value.
|
|
|
|
lodsb ; orig
|
|
mov dh,al ; preserve it for later.
|
|
sub al,[targetgreen] ; al = (orig-target)
|
|
imul dl ; ax = (orig-target)*fraction
|
|
shl ax,1
|
|
sub dh,ah ; dh = orig - ((orig-target) * fraction)
|
|
mov [idealgreen],dh ; preserve ideal color gun value.
|
|
|
|
lodsb ; orig
|
|
mov dh,al ; preserve it for later.
|
|
sub al,[targetblue] ; al = (orig-target)
|
|
imul dl ; ax = (orig-target)*fraction
|
|
shl ax,1
|
|
sub dh,ah ; dh = orig - ((orig-target) * fraction)
|
|
mov [idealblue],dh ; preserve ideal color gun value.
|
|
|
|
; Sweep through the entire existing palette to find the closest
|
|
; matching color. Never matches with color 0.
|
|
|
|
mov eax,[color]
|
|
mov [matchcolor],al ; Default color (self).
|
|
mov [matchvalue],-1 ; Ridiculous match value init.
|
|
mov ecx,255
|
|
|
|
mov esi,[palette] ; Pointer to original palette.
|
|
add esi,3
|
|
|
|
; BH = color index.
|
|
mov bh,1
|
|
innerloop:
|
|
|
|
; Recursion through the fading table won't work if a color is allowed
|
|
; to remap to itself. Prevent this from occuring.
|
|
add esi,3
|
|
cmp bh,bl
|
|
je short notclose
|
|
sub esi,3
|
|
|
|
xor edx,edx ; Comparison value starts null.
|
|
mov eax,edx
|
|
; Build the comparison value based on the sum of the differences of the color
|
|
; guns squared.
|
|
lodsb
|
|
sub al,[idealred]
|
|
mov ah,al
|
|
imul ah
|
|
add edx,eax
|
|
|
|
lodsb
|
|
sub al,[idealgreen]
|
|
mov ah,al
|
|
imul ah
|
|
add edx,eax
|
|
|
|
lodsb
|
|
sub al,[idealblue]
|
|
mov ah,al
|
|
imul ah
|
|
add edx,eax
|
|
jz short perfect ; If perfect match found then quit early.
|
|
|
|
cmp edx,[matchvalue]
|
|
ja short notclose
|
|
mov [matchvalue],edx ; Record new possible color.
|
|
mov [matchcolor],bh
|
|
notclose:
|
|
inc bh ; Checking color index.
|
|
loop innerloop
|
|
mov bh,[matchcolor]
|
|
perfect:
|
|
mov [matchcolor],bh
|
|
xor bh,bh ; Make BX valid main index again.
|
|
|
|
; When the loop exits, we have found the closest match.
|
|
mov al,[matchcolor]
|
|
stosb
|
|
cmp ebx,255
|
|
jne mainloop
|
|
|
|
fini:
|
|
mov eax,[dest]
|
|
// ret
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
|
|
;***************************************************************************
|
|
;* *
|
|
;* Project Name : Westwood Library *
|
|
;* *
|
|
;* File Name : PAL.ASM *
|
|
;* *
|
|
;* Programmer : Joe L. Bostic *
|
|
;* *
|
|
;* Start Date : May 30, 1992 *
|
|
;* *
|
|
;* Last Update : April 27, 1994 [BR] *
|
|
;* *
|
|
;*-------------------------------------------------------------------------*
|
|
;* Functions: *
|
|
;* Set_Palette_Range -- Sets changed values in the palette. *
|
|
;* Bump_Color -- adjusts specified color in specified palette *
|
|
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
|
;********************** Model & Processor Directives ************************
|
|
IDEAL
|
|
P386
|
|
MODEL USE32 FLAT
|
|
|
|
|
|
;include "keyboard.inc"
|
|
FALSE = 0
|
|
TRUE = 1
|
|
|
|
;****************************** Declarations ********************************
|
|
GLOBAL C Set_Palette_Range:NEAR
|
|
GLOBAL C Bump_Color:NEAR
|
|
GLOBAL C CurrentPalette:BYTE:768
|
|
GLOBAL C PaletteTable:byte:1024
|
|
|
|
|
|
;********************************** Data ************************************
|
|
LOCALS ??
|
|
|
|
DATASEG
|
|
|
|
CurrentPalette DB 768 DUP(255) ; copy of current values of DAC regs
|
|
PaletteTable DB 1024 DUP(0)
|
|
|
|
IFNDEF LIB_EXTERNS_RESOLVED
|
|
VertBlank DW 0 ; !!!! this should go away
|
|
ENDIF
|
|
|
|
|
|
;********************************** Code ************************************
|
|
CODESEG
|
|
*/
|
|
|
|
extern "C" unsigned char CurrentPalette[768] = {255}; // DB 768 DUP(255) ; copy of current values of DAC regs
|
|
extern "C" unsigned char PaletteTable[1024] = {0}; // DB 1024 DUP(0)
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;* SET_PALETTE_RANGE -- Sets a palette range to the new pal *
|
|
;* *
|
|
;* INPUT: *
|
|
;* *
|
|
;* OUTPUT: *
|
|
;* *
|
|
;* PROTO: *
|
|
;* *
|
|
;* WARNINGS: This routine is optimized for changing a small number of *
|
|
;* colors in the palette.
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 03/07/1995 PWG : Created. *
|
|
;*=========================================================================*
|
|
*/
|
|
void __cdecl Set_Palette_Range(void *palette)
|
|
{
|
|
memcpy(CurrentPalette, palette, 768);
|
|
Set_DD_Palette(palette);
|
|
|
|
/*
|
|
PROC Set_Palette_Range C NEAR
|
|
ARG palette:DWORD
|
|
|
|
GLOBAL Set_DD_Palette_:near
|
|
GLOBAL Wait_Vert_Blank_:near
|
|
|
|
pushad
|
|
mov esi,[palette]
|
|
mov ecx,768/4
|
|
mov edi,offset CurrentPalette
|
|
cld
|
|
rep movsd
|
|
;call Wait_Vert_Blank_
|
|
mov eax,[palette]
|
|
push eax
|
|
call Set_DD_Palette_
|
|
pop eax
|
|
popad
|
|
ret
|
|
*/
|
|
}
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;* Bump_Color -- adjusts specified color in specified palette *
|
|
;* *
|
|
;* INPUT: *
|
|
;* VOID *palette - palette to modify *
|
|
;* WORD changable - color # to change *
|
|
;* WORD target - color to bend toward *
|
|
;* *
|
|
;* OUTPUT: *
|
|
;* *
|
|
;* WARNINGS: *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 04/27/1994 BR : Converted to 32-bit. *
|
|
;*=========================================================================*
|
|
; BOOL cdecl Bump_Color(VOID *palette, WORD changable, WORD target);
|
|
*/
|
|
BOOL __cdecl Bump_Color(void *pal, int color, int desired)
|
|
{
|
|
/*
|
|
PROC Bump_Color C NEAR
|
|
USES ebx,ecx,edi,esi
|
|
ARG pal:DWORD, color:WORD, desired:WORD
|
|
LOCAL changed:WORD ; Has palette changed?
|
|
*/
|
|
|
|
short short_color = (short) color;
|
|
short short_desired = (short) desired;
|
|
bool changed = false;
|
|
|
|
__asm {
|
|
mov edi,[pal] ; Original palette pointer.
|
|
mov esi,edi
|
|
mov eax,0
|
|
mov ax,[short_color]
|
|
add edi,eax
|
|
add edi,eax
|
|
add edi,eax ; Offset to changable color.
|
|
mov ax,[short_desired]
|
|
add esi,eax
|
|
add esi,eax
|
|
add esi,eax ; Offset to target color.
|
|
|
|
mov [changed],FALSE ; Presume no change.
|
|
mov ecx,3 ; Three color guns.
|
|
|
|
; Check the color gun.
|
|
colorloop:
|
|
mov al,[BYTE PTR esi]
|
|
sub al,[BYTE PTR edi] ; Carry flag is set if subtraction needed.
|
|
jz short gotit
|
|
mov [changed],TRUE
|
|
inc [BYTE PTR edi] ; Presume addition.
|
|
jnc short gotit ; oops, subtraction needed so dec twice.
|
|
dec [BYTE PTR edi]
|
|
dec [BYTE PTR edi]
|
|
gotit:
|
|
inc edi
|
|
inc esi
|
|
loop colorloop
|
|
|
|
movzx eax,[changed]
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
|
;***************************************************************************
|
|
;* *
|
|
;* Project Name : GraphicViewPortClass *
|
|
;* *
|
|
;* File Name : PUTPIXEL.ASM *
|
|
;* *
|
|
;* Programmer : Phil Gorrow *
|
|
;* *
|
|
;* Start Date : June 7, 1994 *
|
|
;* *
|
|
;* Last Update : June 8, 1994 [PWG] *
|
|
;* *
|
|
;*-------------------------------------------------------------------------*
|
|
;* Functions: *
|
|
;* VVPC::Put_Pixel -- Puts a pixel on a virtual viewport *
|
|
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
|
|
|
IDEAL
|
|
P386
|
|
MODEL USE32 FLAT
|
|
|
|
INCLUDE ".\drawbuff.inc"
|
|
INCLUDE ".\gbuffer.inc"
|
|
|
|
|
|
CODESEG
|
|
*/
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;* VVPC::PUT_PIXEL -- Puts a pixel on a virtual viewport *
|
|
;* *
|
|
;* INPUT: WORD the x position for the pixel relative to the upper *
|
|
;* left corner of the viewport *
|
|
;* WORD the y pos for the pixel relative to the upper left *
|
|
;* corner of the viewport *
|
|
;* UBYTE the color of the pixel to write *
|
|
;* *
|
|
;* OUTPUT: none *
|
|
;* *
|
|
;* WARNING: If pixel is to be placed outside of the viewport then *
|
|
;* this routine will abort. *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 06/08/1994 PWG : Created. *
|
|
;*=========================================================================*
|
|
PROC Buffer_Put_Pixel C near
|
|
USES eax,ebx,ecx,edx,edi
|
|
*/
|
|
|
|
void __cdecl Buffer_Put_Pixel(void * this_object, int x_pixel, int y_pixel, unsigned char color)
|
|
{
|
|
|
|
/*
|
|
ARG this_object:DWORD ; this is a member function
|
|
ARG x_pixel:DWORD ; x position of pixel to set
|
|
ARG y_pixel:DWORD ; y position of pixel to set
|
|
ARG color:BYTE ; what color should we clear to
|
|
*/
|
|
|
|
__asm {
|
|
|
|
|
|
;*===================================================================
|
|
; Get the viewport information and put bytes per row in ecx
|
|
;*===================================================================
|
|
mov ebx,[this_object] ; get a pointer to viewport
|
|
xor eax,eax
|
|
mov edi,[ebx]GraphicViewPortClass.Offset ; get the correct offset
|
|
mov ecx,[ebx]GraphicViewPortClass.Height ; edx = height of viewport
|
|
mov edx,[ebx]GraphicViewPortClass.Width ; ecx = width of viewport
|
|
|
|
;*===================================================================
|
|
; Verify that the X pixel offset if legal
|
|
;*===================================================================
|
|
mov eax,[x_pixel] ; find the x position
|
|
cmp eax,edx ; is it out of bounds
|
|
jae short done ; if so then get out
|
|
add edi,eax ; otherwise add in offset
|
|
|
|
;*===================================================================
|
|
; Verify that the Y pixel offset if legal
|
|
;*===================================================================
|
|
mov eax,[y_pixel] ; get the y position
|
|
cmp eax,ecx ; is it out of bounds
|
|
jae done ; if so then get out
|
|
add edx,[ebx]GraphicViewPortClass.XAdd ; otherwise find bytes per row
|
|
add edx,[ebx]GraphicViewPortClass.Pitch ; add in direct draw pitch
|
|
mul edx ; offset = bytes per row * y
|
|
add edi,eax ; add it into the offset
|
|
|
|
;*===================================================================
|
|
; Write the pixel to the screen
|
|
;*===================================================================
|
|
mov al,[color] ; read in color value
|
|
mov [edi],al ; write it to the screen
|
|
done:
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
|
|
;***************************************************************************
|
|
;* *
|
|
;* Project Name : Support Library *
|
|
;* *
|
|
;* File Name : cliprect.asm *
|
|
;* *
|
|
;* Programmer : Julio R Jerez *
|
|
;* *
|
|
;* Start Date : Mar, 2 1995 *
|
|
;* *
|
|
;* *
|
|
;*-------------------------------------------------------------------------*
|
|
;* Functions: *
|
|
;* int Clip_Rect ( int * x , int * y , int * dw , int * dh , *
|
|
;* int width , int height ) ; *
|
|
;* int Confine_Rect ( int * x , int * y , int * dw , int * dh , *
|
|
;* int width , int height ) ; *
|
|
;* *
|
|
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
|
|
|
|
|
IDEAL
|
|
P386
|
|
MODEL USE32 FLAT
|
|
|
|
GLOBAL C Clip_Rect :NEAR
|
|
GLOBAL C Confine_Rect :NEAR
|
|
|
|
CODESEG
|
|
|
|
;***************************************************************************
|
|
;* Clip_Rect -- clip a given rectangle against a given window *
|
|
;* *
|
|
;* INPUT: &x , &y , &w , &h -> Pointer to rectangle being clipped *
|
|
;* width , height -> dimension of clipping window *
|
|
;* *
|
|
;* OUTPUT: a) Zero if the rectangle is totally contained by the *
|
|
;* clipping window. *
|
|
;* b) A negative value if the rectangle is totally outside the *
|
|
;* the clipping window *
|
|
;* c) A positive value if the rectangle was clipped against the *
|
|
;* clipping window, also the values pointed by x, y, w, h will *
|
|
;* be modified to new clipped values *
|
|
;* *
|
|
;* 05/03/1995 JRJ : added comment *
|
|
;*=========================================================================*
|
|
; int Clip_Rect (int* x, int* y, int* dw, int* dh, int width, int height); *
|
|
*/
|
|
|
|
extern "C" int __cdecl Clip_Rect ( int * x , int * y , int * w , int * h , int width , int height )
|
|
{
|
|
|
|
/*
|
|
PROC Clip_Rect C near
|
|
uses ebx,ecx,edx,esi,edi
|
|
arg x:dword
|
|
arg y:dword
|
|
arg w:dword
|
|
arg h:dword
|
|
arg width:dword
|
|
arg height:dword
|
|
*/
|
|
|
|
__asm {
|
|
|
|
;This Clipping algorithm is a derivation of the very well known
|
|
;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency
|
|
;it is probably the most commontly implemented algorithm both in software
|
|
;and hardware for clipping lines, rectangles, and convex polygons against
|
|
;a rectagular clipping window. For reference see
|
|
;"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes
|
|
; pages 113 to 177".
|
|
; Briefly consist in computing the Sutherland code for both end point of
|
|
; the rectangle to find out if the rectangle is:
|
|
; - trivially accepted (no further clipping test, return the oroginal data)
|
|
; - trivially rejected (return with no action, return error code)
|
|
; - retangle must be iteratively clipped again edges of the clipping window
|
|
; and return the clipped rectangle
|
|
|
|
; get all four pointer into regisnters
|
|
mov esi,[x] ; esi = pointer to x
|
|
mov edi,[y] ; edi = pointer to x
|
|
mov eax,[w] ; eax = pointer to dw
|
|
mov ebx,[h] ; ebx = pointer to dh
|
|
|
|
; load the actual data into reg
|
|
mov esi,[esi] ; esi = x0
|
|
mov edi,[edi] ; edi = y0
|
|
mov eax,[eax] ; eax = dw
|
|
mov ebx,[ebx] ; ebx = dh
|
|
|
|
; create a wire frame of the type [x0,y0] , [x1,y1]
|
|
add eax,esi ; eax = x1 = x0 + dw
|
|
add ebx,edi ; ebx = y1 = y0 + dh
|
|
|
|
; we start we suthenland code0 and code1 set to zero
|
|
xor ecx,ecx ; cl = sutherland boolean code0
|
|
xor edx,edx ; dl = sutherland boolean code0
|
|
|
|
; now we start computing the to suthenland boolean code for x0 , x1
|
|
shld ecx,esi,1 ; bit3 of code0 = sign bit of (x0 - 0)
|
|
shld edx,eax,1 ; bit3 of code1 = sign bit of (x1 - 0)
|
|
sub esi,[width] ; get the difference (x0 - (width + 1))
|
|
sub eax,[width] ; get the difference (x1 - (width + 1))
|
|
dec esi
|
|
dec eax
|
|
shld ecx,esi,1 ; bit2 of code0 = sign bit of (x0 - (width + 1))
|
|
shld edx,eax,1 ; bit2 of code1 = sign bit of (x0 - (width + 1))
|
|
|
|
; now we start computing the to suthenland boolean code for y0 , y1
|
|
shld ecx,edi,1 ; bit1 of code0 = sign bit of (y0 - 0)
|
|
shld edx,ebx,1 ; bit1 of code1 = sign bit of (y0 - 0)
|
|
sub edi,[height] ; get the difference (y0 - (height + 1))
|
|
sub ebx,[height] ; get the difference (y1 - (height + 1))
|
|
dec edi
|
|
dec ebx
|
|
shld ecx,edi,1 ; bit0 of code0 = sign bit of (y0 - (height + 1))
|
|
shld edx,ebx,1 ; bit0 of code1 = sign bit of (y1 - (height + 1))
|
|
|
|
; Bit 2 and 0 of cl and bl are complemented
|
|
xor cl,5 ; reverse bit2 and bit0 in code0
|
|
xor dl,5 ; reverse bit2 and bit0 in code1
|
|
|
|
; now perform the rejection test
|
|
mov eax,-1 ; set return code to false
|
|
mov bl,cl ; save code0 for future use
|
|
test dl,cl ; if any two pair of bit in code0 and code1 is set
|
|
jnz clip_out ; then rectangle is outside the window
|
|
|
|
; now perform the aceptance test
|
|
xor eax,eax ; set return code to true
|
|
or bl,dl ; if all pair of bits in code0 and code1 are reset
|
|
jz clip_out ; then rectangle is insize the window. '
|
|
|
|
; we need to clip the rectangle iteratively
|
|
mov eax,-1 ; set return code to false
|
|
test cl,1000b ; if bit3 of code0 is set then the rectangle
|
|
jz left_ok ; spill out the left edge of the window
|
|
mov edi,[x] ; edi = a pointer to x0
|
|
mov ebx,[w] ; ebx = a pointer to dw
|
|
mov esi,[edi] ; esi = x0
|
|
mov [dword ptr edi],0 ; set x0 to 0 "this the left edge value"
|
|
add [ebx],esi ; adjust dw by x0, since x0 must be negative
|
|
|
|
left_ok:
|
|
test cl,0010b ; if bit1 of code0 is set then the rectangle
|
|
jz bottom_ok ; spill out the bottom edge of the window
|
|
mov edi,[y] ; edi = a pointer to y0
|
|
mov ebx,[h] ; ebx = a pointer to dh
|
|
mov esi,[edi] ; esi = y0
|
|
mov [dword ptr edi],0 ; set y0 to 0 "this the bottom edge value"
|
|
add [ebx],esi ; adjust dh by y0, since y0 must be negative
|
|
|
|
bottom_ok:
|
|
test dl,0100b ; if bit2 of code1 is set then the rectangle
|
|
jz right_ok ; spill out the right edge of the window
|
|
mov edi,[w] ; edi = a pointer to dw
|
|
mov esi,[x] ; esi = a pointer to x
|
|
mov ebx,[width] ; ebx = the width of the window
|
|
sub ebx,[esi] ; the new dw is the difference (width-x0)
|
|
mov [edi],ebx ; adjust dw to (width - x0)
|
|
jle clip_out ; if (width-x0) = 0 then the clipped retangle
|
|
; has no width we are done
|
|
right_ok:
|
|
test dl,0001b ; if bit0 of code1 is set then the rectangle
|
|
jz clip_ok ; spill out the top edge of the window
|
|
mov edi,[h] ; edi = a pointer to dh
|
|
mov esi,[y] ; esi = a pointer to y0
|
|
mov ebx,[height] ; ebx = the height of the window
|
|
sub ebx,[esi] ; the new dh is the difference (height-y0)
|
|
mov [edi],ebx ; adjust dh to (height-y0)
|
|
jle clip_out ; if (width-x0) = 0 then the clipped retangle
|
|
; has no width we are done
|
|
clip_ok:
|
|
mov eax,1 ; signal the calling program that the rectangle was modify
|
|
clip_out:
|
|
//ret
|
|
}
|
|
|
|
//ENDP Clip_Rect
|
|
}
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;* Confine_Rect -- clip a given rectangle against a given window *
|
|
;* *
|
|
;* INPUT: &x,&y,w,h -> Pointer to rectangle being clipped *
|
|
;* width,height -> dimension of clipping window *
|
|
;* *
|
|
;* OUTPUT: a) Zero if the rectangle is totally contained by the *
|
|
;* clipping window. *
|
|
;* c) A positive value if the rectangle was shifted in position *
|
|
;* to fix inside the clipping window, also the values pointed *
|
|
;* by x, y, will adjusted to a new values *
|
|
;* *
|
|
;* NOTE: this function make not attempt to verify if the rectangle is *
|
|
;* bigger than the clipping window and at the same time wrap around*
|
|
;* it. If that is the case the result is meaningless *
|
|
;*=========================================================================*
|
|
; int Confine_Rect (int* x, int* y, int dw, int dh, int width, int height); *
|
|
*/
|
|
|
|
extern "C" int __cdecl Confine_Rect ( int * x , int * y , int w , int h , int width , int height )
|
|
{
|
|
|
|
/*
|
|
PROC Confine_Rect C near
|
|
uses ebx, esi,edi
|
|
arg x:dword
|
|
arg y:dword
|
|
arg w:dword
|
|
arg h:dword
|
|
arg width :dword
|
|
arg height:dword
|
|
*/
|
|
__asm {
|
|
|
|
xor eax,eax
|
|
mov ebx,[x]
|
|
mov edi,[w]
|
|
|
|
mov esi,[ebx]
|
|
add edi,[ebx]
|
|
|
|
sub edi,[width]
|
|
neg esi
|
|
dec edi
|
|
|
|
test esi,edi
|
|
jl x_axix_ok
|
|
mov eax,1
|
|
|
|
test esi,esi
|
|
jl shift_right
|
|
mov [dword ptr ebx],0
|
|
jmp x_axix_ok
|
|
shift_right:
|
|
inc edi
|
|
sub [ebx],edi
|
|
x_axix_ok:
|
|
mov ebx,[y]
|
|
mov edi,[h]
|
|
|
|
mov esi,[ebx]
|
|
add edi,[ebx]
|
|
|
|
sub edi,[height]
|
|
neg esi
|
|
dec edi
|
|
|
|
test esi,edi
|
|
jl confi_out
|
|
mov eax,1
|
|
|
|
test esi,esi
|
|
jl shift_top
|
|
mov [dword ptr ebx],0
|
|
|
|
//ret
|
|
jmp confi_out
|
|
shift_top:
|
|
inc edi
|
|
sub [ebx],edi
|
|
confi_out:
|
|
//ret
|
|
|
|
//ENDP Confine_Rect
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
; $Header: //depot/Projects/Mobius/QA/Project/Run/SOURCECODE/REDALERT/WIN32LIB/DrawMisc.cpp#139 $
|
|
;***************************************************************************
|
|
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
|
|
;***************************************************************************
|
|
;* *
|
|
;* Project Name : Library routine *
|
|
;* *
|
|
;* File Name : UNCOMP.ASM *
|
|
;* *
|
|
;* Programmer : Christopher Yates *
|
|
;* *
|
|
;* Last Update : 20 August, 1990 [CY] *
|
|
;* *
|
|
;*-------------------------------------------------------------------------*
|
|
;* Functions: *
|
|
;* *
|
|
; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length); *
|
|
;* *
|
|
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
|
|
|
IDEAL
|
|
P386
|
|
MODEL USE32 FLAT
|
|
|
|
GLOBAL C LCW_Uncompress :NEAR
|
|
|
|
CODESEG
|
|
|
|
; ----------------------------------------------------------------
|
|
;
|
|
; Here are prototypes for the routines defined within this module:
|
|
;
|
|
; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length);
|
|
;
|
|
; ----------------------------------------------------------------
|
|
*/
|
|
#if (0)//ST 5/10/2019
|
|
extern "C" unsigned long __cdecl LCW_Uncompress(void *source, void *dest, unsigned long length_)
|
|
{
|
|
//PROC LCW_Uncompress C near
|
|
//
|
|
// USES ebx,ecx,edx,edi,esi
|
|
//
|
|
// ARG source:DWORD
|
|
// ARG dest:DWORD
|
|
// ARG length:DWORD
|
|
//;LOCALS
|
|
// LOCAL a1stdest:DWORD
|
|
// LOCAL maxlen:DWORD
|
|
// LOCAL lastbyte:DWORD
|
|
// LOCAL lastcom:DWORD
|
|
// LOCAL lastcom1:DWORD
|
|
|
|
unsigned long a1stdest;
|
|
unsigned long maxlen;
|
|
unsigned long lastbyte;
|
|
//unsigned long lastcom;
|
|
//unsigned long lastcom1;
|
|
|
|
__asm {
|
|
|
|
|
|
mov edi,[dest]
|
|
mov esi,[source]
|
|
mov edx,[length_]
|
|
|
|
;
|
|
;
|
|
; uncompress data to the following codes in the format b = byte, w = word
|
|
; n = byte code pulled from compressed data
|
|
; Bit field of n command description
|
|
; n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3
|
|
; n=10xxxxxx,n1,n2,...,nx+1 med length copy the next x+1 bytes
|
|
; n=11xxxxxx,w1 med run run x+3 bytes from offset w1
|
|
; n=11111111,w1,w2 long copy copy w1 bytes from offset w2
|
|
; n=11111110,w1,b1 long run run byte b1 for w1 bytes
|
|
; n=10000000 end end of data reached
|
|
;
|
|
|
|
mov [a1stdest],edi
|
|
add edx,edi
|
|
mov [lastbyte],edx
|
|
cld ; make sure all lod and sto are forward
|
|
mov ebx,esi ; save the source offset
|
|
|
|
loop_label:
|
|
mov eax,[lastbyte]
|
|
sub eax,edi ; get the remaining byte to uncomp
|
|
jz short out_label ; were done
|
|
|
|
mov [maxlen],eax ; save for string commands
|
|
mov esi,ebx ; mov in the source index
|
|
|
|
xor eax,eax
|
|
mov al,[esi]
|
|
inc esi
|
|
test al,al ; see if its a short run
|
|
js short notshort
|
|
|
|
mov ecx,eax ;put count nibble in cl
|
|
|
|
mov ah,al ; put rel offset high nibble in ah
|
|
and ah,0Fh ; only 4 bits count
|
|
|
|
shr cl,4 ; get run -3
|
|
add ecx,3 ; get actual run length
|
|
|
|
cmp ecx,[maxlen] ; is it too big to fit?
|
|
jbe short rsok ; if not, its ok
|
|
|
|
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
|
|
|
|
rsok:
|
|
mov al,[esi] ; get rel offset low byte
|
|
lea ebx,[esi+1] ; save the source offset
|
|
mov esi,edi ; get the current dest
|
|
sub esi,eax ; get relative offset
|
|
|
|
rep movsb
|
|
|
|
jmp loop_label
|
|
|
|
notshort:
|
|
test al,40h ; is it a length?
|
|
jne short notlength ; if not it could be med or long run
|
|
|
|
cmp al,80h ; is it the end?
|
|
je short out_label ; if so its over
|
|
|
|
mov cl,al ; put the byte in count register
|
|
and ecx,3Fh ; and off the extra bits
|
|
|
|
cmp ecx,[maxlen] ; is it too big to fit?
|
|
jbe short lenok ; if not, its ok
|
|
|
|
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
|
|
|
|
lenok:
|
|
rep movsb
|
|
|
|
mov ebx,esi ; save the source offset
|
|
jmp loop_label
|
|
|
|
out_label:
|
|
mov eax,edi
|
|
sub eax,[a1stdest]
|
|
jmp label_exit
|
|
|
|
notlength:
|
|
mov cl,al ; get the entire code
|
|
and ecx,3Fh ; and off all but the size -3
|
|
add ecx,3 ; add 3 for byte count
|
|
|
|
cmp al,0FEh
|
|
jne short notrunlength
|
|
|
|
xor ecx,ecx
|
|
mov cx,[esi]
|
|
|
|
xor eax,eax
|
|
mov al,[esi+2]
|
|
lea ebx,[esi+3] ;save the source offset
|
|
|
|
cmp ecx,[maxlen] ; is it too big to fit?
|
|
jbe short runlenok ; if not, its ok
|
|
|
|
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
|
|
|
|
runlenok:
|
|
test ecx,0ffe0h
|
|
jnz dont_use_stosb
|
|
rep stosb
|
|
jmp loop_label
|
|
|
|
|
|
dont_use_stosb:
|
|
mov ah,al
|
|
mov edx,eax
|
|
shl eax,16
|
|
or eax,edx
|
|
|
|
test edi,3
|
|
jz aligned
|
|
|
|
mov [edi],eax
|
|
mov edx,edi
|
|
and edi,0fffffffch
|
|
lea edi,[edi+4]
|
|
and edx,3
|
|
dec dl
|
|
xor dl,3
|
|
sub ecx,edx
|
|
|
|
aligned:
|
|
mov edx,ecx
|
|
shr ecx,2
|
|
rep stosd
|
|
|
|
and edx,3
|
|
jz loop_label
|
|
mov ecx,edx
|
|
rep stosb
|
|
jmp loop_label
|
|
|
|
|
|
|
|
|
|
|
|
|
|
notrunlength:
|
|
cmp al,0FFh ; is it a long run?
|
|
jne short notlong ; if not use the code as the size
|
|
|
|
xor ecx,ecx
|
|
xor eax,eax
|
|
mov cx,[esi] ; if so, get the size
|
|
lea esi,[esi+2]
|
|
|
|
notlong:
|
|
mov ax,[esi] ;get the real index
|
|
add eax,[a1stdest] ;add in the 1st index
|
|
lea ebx,[esi+2] ;save the source offset
|
|
cmp ecx,[maxlen] ;compare for overrun
|
|
mov esi,eax ;use eax as new source
|
|
jbe short runok ; if not, its ok
|
|
|
|
mov ecx,[maxlen] ; if so, max it out so it dosen't overrun
|
|
|
|
runok:
|
|
test ecx,0ffe0h
|
|
jnz dont_use_movsb
|
|
rep movsb
|
|
jmp loop_label
|
|
|
|
|
|
|
|
|
|
dont_use_movsb:
|
|
lea edx,[edi+0fffffffch]
|
|
cmp esi,edx
|
|
ja use_movsb
|
|
|
|
test edi,3
|
|
jz aligned2
|
|
|
|
mov eax,[esi]
|
|
mov [edi],eax
|
|
mov edx,edi
|
|
and edi,0fffffffch
|
|
lea edi,[edi+4]
|
|
and edx,3
|
|
dec dl
|
|
xor dl,3
|
|
sub ecx,edx
|
|
add esi,edx
|
|
|
|
aligned2:
|
|
mov edx,ecx
|
|
shr ecx,2
|
|
and edx,3
|
|
rep movsd
|
|
mov ecx,edx
|
|
use_movsb:
|
|
rep movsb
|
|
jmp loop_label
|
|
|
|
|
|
|
|
|
|
label_exit:
|
|
mov eax,edi
|
|
mov ebx,[dest]
|
|
sub eax,ebx
|
|
|
|
//ret
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
;***************************************************************************
|
|
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
|
|
;***************************************************************************
|
|
;* *
|
|
;* Project Name : Westwood 32 bit Library *
|
|
;* *
|
|
;* File Name : TOPAGE.ASM *
|
|
;* *
|
|
;* Programmer : Phil W. Gorrow *
|
|
;* *
|
|
;* Start Date : June 8, 1994 *
|
|
;* *
|
|
;* Last Update : June 15, 1994 [PWG] *
|
|
;* *
|
|
;*-------------------------------------------------------------------------*
|
|
;* Functions: *
|
|
;* Buffer_To_Page -- Copies a linear buffer to a virtual viewport *
|
|
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
|
|
|
IDEAL
|
|
P386
|
|
MODEL USE32 FLAT
|
|
|
|
TRANSP equ 0
|
|
|
|
|
|
INCLUDE ".\drawbuff.inc"
|
|
INCLUDE ".\gbuffer.inc"
|
|
|
|
CODESEG
|
|
|
|
;***************************************************************************
|
|
;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport *
|
|
;* *
|
|
;* INPUT: WORD x_pixel - x pixel on viewport to copy from *
|
|
;* WORD y_pixel - y pixel on viewport to copy from *
|
|
;* WORD pixel_width - the width of copy region *
|
|
;* WORD pixel_height - the height of copy region *
|
|
;* BYTE * src - buffer to copy from *
|
|
;* VVPC * dest - virtual viewport to copy to *
|
|
;* *
|
|
;* OUTPUT: none *
|
|
;* *
|
|
;* WARNINGS: Coordinates and dimensions will be adjusted if they exceed *
|
|
;* the boundaries. In the event that no adjustment is *
|
|
;* possible this routine will abort. If the size of the *
|
|
;* region to copy exceeds the size passed in for the buffer *
|
|
;* the routine will automatically abort. *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 06/15/1994 PWG : Created. *
|
|
;*=========================================================================*
|
|
*/
|
|
|
|
extern "C" long __cdecl Buffer_To_Page(int x_pixel, int y_pixel, int pixel_width, int pixel_height, void *src, void *dest)
|
|
{
|
|
|
|
/*
|
|
PROC Buffer_To_Page C near
|
|
USES eax,ebx,ecx,edx,esi,edi
|
|
|
|
;*===================================================================
|
|
;* define the arguements that our function takes.
|
|
;*===================================================================
|
|
ARG x_pixel :DWORD ; x pixel position in source
|
|
ARG y_pixel :DWORD ; y pixel position in source
|
|
ARG pixel_width :DWORD ; width of rectangle to blit
|
|
ARG pixel_height:DWORD ; height of rectangle to blit
|
|
ARG src :DWORD ; this is a member function
|
|
ARG dest :DWORD ; what are we blitting to
|
|
|
|
; ARG trans :DWORD ; do we deal with transparents?
|
|
|
|
;*===================================================================
|
|
; Define some locals so that we can handle things quickly
|
|
;*===================================================================
|
|
LOCAL x1_pixel :dword
|
|
LOCAL y1_pixel :dword
|
|
local scr_x : dword
|
|
local scr_y : dword
|
|
LOCAL dest_ajust_width:DWORD
|
|
LOCAL scr_ajust_width:DWORD
|
|
LOCAL dest_area : dword
|
|
*/
|
|
|
|
unsigned long x1_pixel;
|
|
unsigned long y1_pixel;
|
|
unsigned long scr_x;
|
|
unsigned long scr_y;
|
|
unsigned long dest_ajust_width;
|
|
unsigned long scr_ajust_width;
|
|
//unsigned long dest_area;
|
|
|
|
__asm {
|
|
|
|
cmp [ src ] , 0
|
|
jz real_out
|
|
|
|
|
|
; Clip dest Rectangle against source Window boundaries.
|
|
|
|
mov [ scr_x ] , 0
|
|
mov [ scr_y ] , 0
|
|
mov esi , [ dest ] ; get ptr to dest
|
|
xor ecx , ecx
|
|
xor edx , edx
|
|
mov edi , [esi]GraphicViewPortClass.Width ; get width into register
|
|
mov ebx , [ x_pixel ]
|
|
mov eax , [ x_pixel ]
|
|
add ebx , [ pixel_width ]
|
|
shld ecx , eax , 1
|
|
mov [ x1_pixel ] , ebx
|
|
inc edi
|
|
shld edx , ebx , 1
|
|
sub eax , edi
|
|
sub ebx , edi
|
|
shld ecx , eax , 1
|
|
shld edx , ebx , 1
|
|
|
|
mov edi, [esi]GraphicViewPortClass.Height ; get height into register
|
|
mov ebx , [ y_pixel ]
|
|
mov eax , [ y_pixel ]
|
|
add ebx , [ pixel_height ]
|
|
shld ecx , eax , 1
|
|
mov [ y1_pixel ] , ebx
|
|
inc edi
|
|
shld edx , ebx , 1
|
|
sub eax , edi
|
|
sub ebx , edi
|
|
shld ecx , eax , 1
|
|
shld edx , ebx , 1
|
|
|
|
xor cl , 5
|
|
xor dl , 5
|
|
mov al , cl
|
|
test dl , cl
|
|
jnz real_out
|
|
or al , dl
|
|
jz do_blit
|
|
|
|
test cl , 1000b
|
|
jz dest_left_ok
|
|
mov eax , [ x_pixel ]
|
|
neg eax
|
|
mov [ x_pixel ] , 0
|
|
mov [ scr_x ] , eax
|
|
|
|
dest_left_ok:
|
|
test cl , 0010b
|
|
jz dest_bottom_ok
|
|
mov eax , [ y_pixel ]
|
|
neg eax
|
|
mov [ y_pixel ] , 0
|
|
mov [ scr_y ] , eax
|
|
|
|
dest_bottom_ok:
|
|
test dl , 0100b
|
|
jz dest_right_ok
|
|
mov eax , [esi]GraphicViewPortClass.Width ; get width into register
|
|
mov [ x1_pixel ] , eax
|
|
dest_right_ok:
|
|
test dl , 0001b
|
|
jz do_blit
|
|
mov eax , [esi]GraphicViewPortClass.Height ; get width into register
|
|
mov [ y1_pixel ] , eax
|
|
|
|
do_blit:
|
|
|
|
cld
|
|
|
|
mov eax , [esi]GraphicViewPortClass.XAdd
|
|
add eax , [esi]GraphicViewPortClass.Width
|
|
add eax , [esi]GraphicViewPortClass.Pitch
|
|
mov edi , [esi]GraphicViewPortClass.Offset
|
|
|
|
mov ecx , eax
|
|
mul [ y_pixel ]
|
|
add edi , [ x_pixel ]
|
|
add edi , eax
|
|
|
|
add ecx , [ x_pixel ]
|
|
sub ecx , [ x1_pixel ]
|
|
mov [ dest_ajust_width ] , ecx
|
|
|
|
|
|
mov esi , [ src ]
|
|
mov eax , [ pixel_width ]
|
|
sub eax , [ x1_pixel ]
|
|
add eax , [ x_pixel ]
|
|
mov [ scr_ajust_width ] , eax
|
|
|
|
mov eax , [ scr_y ]
|
|
mul [ pixel_width ]
|
|
add eax , [ scr_x ]
|
|
add esi , eax
|
|
|
|
mov edx , [ y1_pixel ]
|
|
mov eax , [ x1_pixel ]
|
|
|
|
sub edx , [ y_pixel ]
|
|
jle real_out
|
|
sub eax , [ x_pixel ]
|
|
jle real_out
|
|
|
|
|
|
; ********************************************************************
|
|
; Forward bitblit only
|
|
|
|
//IF TRANSP
|
|
// test [ trans ] , 1
|
|
// jnz forward_Blit_trans
|
|
//ENDIF
|
|
|
|
|
|
; the inner loop is so efficient that
|
|
; the optimal consept no longer apply because
|
|
; the optimal byte have to by a number greather than 9 bytes
|
|
cmp eax , 10
|
|
jl forward_loop_bytes
|
|
|
|
forward_loop_dword:
|
|
mov ecx , edi
|
|
mov ebx , eax
|
|
neg ecx
|
|
and ecx , 3
|
|
sub ebx , ecx
|
|
rep movsb
|
|
mov ecx , ebx
|
|
shr ecx , 2
|
|
rep movsd
|
|
mov ecx , ebx
|
|
and ecx , 3
|
|
rep movsb
|
|
add esi , [ scr_ajust_width ]
|
|
add edi , [ dest_ajust_width ]
|
|
dec edx
|
|
jnz forward_loop_dword
|
|
jmp real_out //ret
|
|
|
|
forward_loop_bytes:
|
|
mov ecx , eax
|
|
rep movsb
|
|
add esi , [ scr_ajust_width ]
|
|
add edi , [ dest_ajust_width ]
|
|
dec edx ; decrement the height
|
|
jnz forward_loop_bytes
|
|
// ret
|
|
|
|
//IF TRANSP
|
|
//
|
|
//
|
|
//forward_Blit_trans:
|
|
//
|
|
//
|
|
// mov ecx , eax
|
|
// and ecx , 01fh
|
|
// lea ecx , [ ecx + ecx * 4 ]
|
|
// neg ecx
|
|
// shr eax , 5
|
|
// lea ecx , [ transp_reference + ecx * 2 ]
|
|
// mov [ y1_pixel ] , ecx
|
|
//
|
|
//
|
|
//forward_loop_trans:
|
|
// mov ecx , eax
|
|
// jmp [ y1_pixel ]
|
|
//forward_trans_line:
|
|
// REPT 32
|
|
// local transp_pixel
|
|
// mov bl , [ esi ]
|
|
// inc esi
|
|
// test bl , bl
|
|
// jz transp_pixel
|
|
// mov [ edi ] , bl
|
|
// transp_pixel:
|
|
// inc edi
|
|
// ENDM
|
|
// transp_reference:
|
|
// dec ecx
|
|
// jge forward_trans_line
|
|
// add esi , [ scr_ajust_width ]
|
|
// add edi , [ dest_ajust_width ]
|
|
// dec edx
|
|
// jnz forward_loop_trans
|
|
// ret
|
|
//ENDIF
|
|
|
|
real_out:
|
|
//ret
|
|
}
|
|
}
|
|
|
|
//ENDP Buffer_To_Page
|
|
//END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
;***************************************************************************
|
|
;* VVPC::GET_PIXEL -- Gets a pixel from the current view port *
|
|
;* *
|
|
;* INPUT: WORD the x pixel on the screen. *
|
|
;* WORD the y pixel on the screen. *
|
|
;* *
|
|
;* OUTPUT: UBYTE the pixel at the specified location *
|
|
;* *
|
|
;* WARNING: If pixel is to be placed outside of the viewport then *
|
|
;* this routine will abort. *
|
|
;* *
|
|
;* HISTORY: *
|
|
;* 06/07/1994 PWG : Created. *
|
|
;*=========================================================================*
|
|
PROC Buffer_Get_Pixel C near
|
|
USES ebx,ecx,edx,edi
|
|
|
|
ARG this_object:DWORD ; this is a member function
|
|
ARG x_pixel:DWORD ; x position of pixel to set
|
|
ARG y_pixel:DWORD ; y position of pixel to set
|
|
*/
|
|
|
|
extern "C" int __cdecl Buffer_Get_Pixel(void * this_object, int x_pixel, int y_pixel)
|
|
{
|
|
__asm {
|
|
|
|
;*===================================================================
|
|
; Get the viewport information and put bytes per row in ecx
|
|
;*===================================================================
|
|
mov ebx,[this_object] ; get a pointer to viewport
|
|
xor eax,eax
|
|
mov edi,[ebx]GraphicViewPortClass.Offset ; get the correct offset
|
|
mov ecx,[ebx]GraphicViewPortClass.Height ; edx = height of viewport
|
|
mov edx,[ebx]GraphicViewPortClass.Width ; ecx = width of viewport
|
|
|
|
;*===================================================================
|
|
; Verify that the X pixel offset if legal
|
|
;*===================================================================
|
|
mov eax,[x_pixel] ; find the x position
|
|
cmp eax,edx ; is it out of bounds
|
|
jae short exit_label ; if so then get out
|
|
add edi,eax ; otherwise add in offset
|
|
|
|
;*===================================================================
|
|
; Verify that the Y pixel offset if legal
|
|
;*===================================================================
|
|
mov eax,[y_pixel] ; get the y position
|
|
cmp eax,ecx ; is it out of bounds
|
|
jae exit_label ; if so then get out
|
|
add edx,[ebx]GraphicViewPortClass.XAdd ; otherwise find bytes per row
|
|
add edx,[ebx]GraphicViewPortClass.Pitch ; otherwise find bytes per row
|
|
mul edx ; offset = bytes per row * y
|
|
add edi,eax ; add it into the offset
|
|
|
|
;*===================================================================
|
|
; Write the pixel to the screen
|
|
;*===================================================================
|
|
xor eax,eax ; clear the word
|
|
mov al,[edi] ; read in the pixel
|
|
exit_label:
|
|
//ret
|
|
//ENDP Buffer_Get_Pixel
|
|
|
|
}
|
|
}
|
|
|
|
|