diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index ee219fd..d89d1ba 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -725,3 +725,4 @@ add_executable(RedAlert ${src_io} ${src_win32lib} ${src_redalert} ${src_external set_target_properties(RedAlert PROPERTIES OUTPUT_NAME "RedAlert" LINK_FLAGS "/PDB:\"RedAlert.pdb\" /SUBSYSTEM:WINDOWS" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/../" ) target_include_directories(RedAlert PRIVATE ./external/xml/;./external/devil/;./external/;./redalert/win32lib;./external/lua/;./external/imgui;./external/dxsdk/Include;./external/ffmpeg-win32/include;./external/sdl2/include;./win32lib;./external/openal/include) target_link_libraries(RedAlert "opengl32.lib" "winmm.lib" "Ws2_32.lib" "${CMAKE_SOURCE_DIR}/external/devil/ilu.lib" "${CMAKE_SOURCE_DIR}/external/devil/DevIL.lib" "${CMAKE_SOURCE_DIR}/external/sdl2/lib/x86/SDL2.lib" "${CMAKE_SOURCE_DIR}/external/openal/out/build/x86-Release/OpenAL32.lib") + \ No newline at end of file diff --git a/code/REDALERT/COORD.CPP b/code/REDALERT/COORD.CPP index 73a1786..14937ce 100644 --- a/code/REDALERT/COORD.CPP +++ b/code/REDALERT/COORD.CPP @@ -437,129 +437,50 @@ void Move_Point(short& x, short& y, register DirType dir, unsigned short distanc y += -( sinTable[dir] * distance ) / SHRT_MAX; } -int __cdecl calcx(signed short param1, short distance) -{ - __asm { - - //#pragma aux calcx parm [ax] [bx] \ - - movzx eax, [param1] - mov bx, [distance] - imul bx - shl ax, 1 - rcl dx, 1 - mov al, ah - mov ah, dl - cwd - } -} - - -int __cdecl calcy(signed short param1, short distance) -{ - __asm { - - //#pragma aux calcy parm [ax] [bx] \ - - movzx eax, [param1] - mov bx, [distance] - imul bx - shl ax, 1 - rcl dx, 1 - mov al, ah - mov ah, dl - cwd - neg eax - } -} - - +// This is from Coord.cpp from chronoshift. void Normal_Move_Point(short& x, short& y, register DirType dir, unsigned short distance) { - static unsigned char const CosTable[256] = { - 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15, - 0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d, - 0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43, - 0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57, - 0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67, - 0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74, - 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b, - 0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e, - - 0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d, - 0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76, - 0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b, - 0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b, - 0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49, - 0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33, - 0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b, - 0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03, - - 0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb, - 0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3, - 0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd, - 0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9, - 0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99, - 0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c, - 0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85, - 0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82, - - 0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83, - 0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a, - 0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95, - 0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5, - 0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7, - 0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd, - 0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5, - 0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd, + // These tables are 7bit fixed point lookup tables representing the values of sine and cosine radian values. + static const int8_t _cosinetable[256] = { + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, + 48, 51, 54, 57, 59, 62, 65, 67, 70, 73, 75, 78, 80, 82, 85, 87, + 89, 91, 94, 96, 98, 100, 101, 103, 105, 107, 108, 110, 111, 113, 114, 116, + 117, 118, 119, 120, 121, 122, 123, 123, 124, 125, 125, 126, 126, 126, 126, 126, + 127, 126, 126, 126, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119, 118, + 117, 116, 114, 113, 112, 110, 108, 107, 105, 103, 102, 100, 98, 96, 94, 91, + 89, 87, 85, 82, 80, 78, 75, 73, 70, 67, 65, 62, 59, 57, 54, 51, + 48, 45, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, + 0, -3, -6, -9, -12, -15, -18, -21, -24, -27, -30, -33, -36, -39, -42, -45, + -48, -51, -54, -57, -59, -62, -65, -67, -70, -73, -75, -78, -80, -82, -85, -87, + -89, -91, -94, -96, -98, -100, -102, -103, -105, -107, -108, -110, -111, -113, -114, -116, + -117, -118, -119, -120, -121, -122, -123, -123, -124, -125, -125, -126, -126, -126, -126, -126, + -126, -126, -126, -126, -126, -126, -125, -125, -124, -123, -123, -122, -121, -120, -119, -118, + -117, -116, -114, -113, -112, -110, -108, -107, -105, -103, -102, -100, -98, -96, -94, -91, + -89, -87, -85, -82, -80, -78, -75, -73, -70, -67, -65, -62, -59, -57, -54, -51, + -48, -45, -42, -39, -36, -33, -30, -27, -24, -21, -18, -15, -12, -9, -6, -3 }; - static unsigned char const SinTable[256] = { - 0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d, - 0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76, - 0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b, - 0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b, - 0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49, - 0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33, - 0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b, - 0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03, - - 0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb, - 0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3, - 0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd, - 0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9, - 0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99, - 0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c, - 0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85, - 0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82, - - 0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83, - 0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a, - 0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95, - 0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5, - 0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7, - 0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd, - 0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5, - 0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd, - - 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15, - 0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d, - 0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43, - 0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57, - 0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67, - 0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74, - 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b, - 0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e, + static const int8_t _sintable[256] = { + 127, 126, 126, 126, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119, 118, + 117, 116, 114, 113, 112, 110, 108, 107, 105, 103, 102, 100, 98, 96, 94, 91, + 89, 87, 85, 82, 80, 78, 75, 73, 70, 67, 65, 62, 59, 57, 54, 51, + 48, 45, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3, + 0, -3, -6, -9, -12, -15, -18, -21, -24, -27, -30, -33, -36, -39, -42, -45, + -48, -51, -54, -57, -59, -62, -65, -67, -70, -73, -75, -78, -80, -82, -85, -87, + -89, -91, -94, -96, -98, -100, -102, -103, -105, -107, -108, -110, -111, -113, -114, -116, + -117, -118, -119, -120, -121, -122, -123, -123, -124, -125, -125, -126, -126, -126, -126, -126, + -126, -126, -126, -126, -126, -126, -125, -125, -124, -123, -123, -122, -121, -120, -119, -118, + -117, -116, -114, -113, -112, -110, -108, -107, -105, -103, -102, -100, -98, -96, -94, -91, + -89, -87, -85, -82, -80, -78, -75, -73, -70, -67, -65, -62, -59, -57, -54, -51, + -48, -45, -42, -39, -36, -33, -30, -27, -24, -21, -18, -15, -12, -9, -6, -3, + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, + 48, 51, 54, 57, 59, 62, 65, 67, 70, 73, 75, 78, 80, 82, 85, 87, + 89, 91, 94, 96, 98, 100, 101, 103, 105, 107, 108, 110, 111, 113, 114, 116, + 117, 118, 119, 120, 121, 122, 123, 123, 124, 125, 125, 126, 126, 126, 126, 126 }; - distance = distance; // Keep LINT quiet. - // - // Have to declare table as unsigned otherwise MSVC complains, but we need to treat the actual values as signed. - // - static const char* _sin_table = (char*)&SinTable[0]; - static const char* _cos_table = (char*)&CosTable[0]; - - x += calcx(_cos_table[dir], distance); - - y += calcy(_sin_table[dir] / 2, distance); + // The division by 128 is for a shift of 7 bits for a fixed point chop to int. + // Note that this function uses 7 bit accuracy, not 8 bit like the fixed class. + x += (_cosinetable[dir] * distance) / 128; + y -= (_sintable[dir] * distance) / 128; } \ No newline at end of file diff --git a/code/REDALERT/JSHELL.H b/code/REDALERT/JSHELL.H index b215b52..53b44f2 100644 --- a/code/REDALERT/JSHELL.H +++ b/code/REDALERT/JSHELL.H @@ -206,8 +206,8 @@ inline ShapeFlags_Type operator ~(ShapeFlags_Type); void __cdecl Set_Bit(void * array, int bit, int value); int __cdecl Get_Bit(void const * array, int bit); -int __cdecl First_True_Bit(void const * array); -int __cdecl First_False_Bit(void const * array); +int __cdecl First_True_Bit(void const * array, int size); +int __cdecl First_False_Bit(void const * array, int size); int __cdecl Bound(int original, int min, int max); #if (0) diff --git a/code/REDALERT/MEMCHECK.H b/code/REDALERT/MEMCHECK.H index 5a1b537..54ce603 100644 --- a/code/REDALERT/MEMCHECK.H +++ b/code/REDALERT/MEMCHECK.H @@ -1561,7 +1561,9 @@ extern int _MCAPI mc_in_source (void); extern int _MCAPI mc_is_active (void); extern MCSL _MCAPI mc_line (void); extern char * _MCAPI mc_location_text (void); -#define mc_load_debugger() _asm int 3 +// jmarshall - added debug break. +#define mc_load_debugger() __debugbreak() +// jmarshall end extern unsigned long _MCAPI mc_memory_leaked (void); extern char * _MCAPI mc_memrec_text (MEMRECP); extern MEMRECP _MCAPI mc_memrec (void); diff --git a/code/REDALERT/MiscAsm.cpp b/code/REDALERT/MiscAsm.cpp index cd8e639..44b1b78 100644 --- a/code/REDALERT/MiscAsm.cpp +++ b/code/REDALERT/MiscAsm.cpp @@ -18,8 +18,8 @@ ** ** Misc. assembly code moved from headers ** -** -** +** jmarshall: This file heavily uses Chronoshift code to replace inline assembly functions +** https://github.com/TheAssemblyArmada/Chronoshift ** ** */ @@ -33,151 +33,6 @@ extern "C" void __cdecl Mem_Copy(void const *source, void *dest, unsigned long b memcpy(dest, source, bytes_to_copy); } - -/*********************************************************************************************** - * Distance -- Determines the lepton distance between two coordinates. * - * * - * This routine is used to determine the distance between two coordinates. It uses the * - * Dragon Strike method of distance determination and thus it is very fast. * - * * - * INPUT: coord1 -- First coordinate. * - * * - * coord2 -- Second coordinate. * - * * - * OUTPUT: Returns the lepton distance between the two coordinates. * - * * - * WARNINGS: none * - * * - * HISTORY: * - * 05/27/1994 JLB : Created. * - *=============================================================================================*/ -int Distance_Coord(COORDINATE coord1, COORDINATE coord2) -{ - __asm { - mov eax,[coord1] - mov ebx,[coord2] - mov dx,ax - sub dx,bx - jg okx - neg dx - okx: - shr eax,16 - shr ebx,16 - sub ax,bx - jg oky - neg ax -oky: - cmp ax,dx - jg ok - xchg ax,dx -ok: - shr dx,1 - add ax,dx - } -} - - - - -/* -;*************************************************************************** -;* DESIRED_FACING16 -- Converts coordinates into a facing number. * -;* * -;* This converts coordinates into a desired facing number that ranges * -;* from 0 to 15 (0 equals North and going clockwise). * -;* * -;* INPUT: x1,y1 -- Position of origin point. * -;* * -;* x2,y2 -- Position of target. * -;* * -;* OUTPUT: Returns desired facing as a number from 0 to 255 but * -;* accurate to 22.5 degree increments. * -;* * -;* WARNINGS: If the two coordinates are the same, then -1 will be * -;* returned. It is up to you to handle this case. * -;* * -;* HISTORY: * -;* 08/14/1991 JLB : Created. * -;*=========================================================================* -*/ - -long __cdecl Desired_Facing16(long x1, long y1, long x2, long y2) -{ - static const char _new_facing16[] = { - 3, 2, 4,-1, 1, 2,0,-1, - 13,14,12,-1,15,14,0,-1, - 5, 6, 4,-1, 7, 6,8,-1, - 11,10,12,-1, 9,10,8,-1 - }; - - - __asm { - xor ebx,ebx //; Index byte (built). - - //; Determine Y axis difference. - mov edx,[y1] - mov ecx,[y2] - sub edx,ecx //; DX = Y axis (signed). - jns short absy - inc ebx //; Set the signed bit. - neg edx //; ABS(y) -absy: - - //; Determine X axis difference. - shl ebx,1 - mov eax,[x1] - mov ecx,[x2] - sub ecx,eax //; CX = X axis (signed). - jns short absx - inc ebx //; Set the signed bit. - neg ecx //; ABS(x) -absx: - - //; Determine the greater axis. - cmp ecx,edx - jb short dxisbig - xchg ecx,edx -dxisbig: - rcl ebx,1 //; Y > X flag bit. - - //; Determine the closeness or farness of lesser axis. - mov eax,edx - inc eax //; Round up. - shr eax,1 - inc eax //; Round up. - shr eax,1 //; 1/4 of greater axis. - - cmp ecx,eax - rcl ebx,1 //; Very close to major axis bit. - - sub edx,eax - cmp edx,ecx - rcl ebx,1 //; Very far from major axis bit. - - xor eax,eax - mov al,[_new_facing16+ebx] - - //; Normalize to 0..FF range. - shl eax,4 - -// ret - } -} - - - - - - - - - - - - - - - /* ;*************************************************************************** ;* Desired_Facing256 -- Desired facing algorithm 0..255 resolution. * @@ -201,92 +56,52 @@ dxisbig: ;* 12/24/1991 JLB : Adapted. * ;*=========================================================================*/ -int __cdecl Desired_Facing256(LONG srcx, LONG srcy, LONG dstx, LONG dsty) +int __cdecl Desired_Facing256(LONG x1, LONG y1, LONG x2, LONG y2) { - - __asm { - xor ebx,ebx //; Facing number. + int8_t unk1 = 0; - ////; Determine absolute X delta and left/right direction. - mov ecx,[dstx] - sub ecx,[srcx] - jge short xnotneg - neg ecx - mov ebx,11000000b //; Set bit 7 and 6 for leftward. -xnotneg: + int x_diff = x2 - x1; - //; Determine absolute Y delta and top/bottom direction. - mov eax,[srcy] - sub eax,[dsty] - jge short ynotneg - xor ebx,01000000b //; Complement bit 6 for downward. - neg eax -ynotneg: - - //; Set DX=64 for quadrants 0 and 2. - mov edx,ebx - and edx,01000000b - xor edx,01000000b - - //; Determine if the direction is closer to the Y axis and make sure that - //; CX holds the larger of the two deltas. This is in preparation for the - //; divide. - cmp eax,ecx - jb short gotaxis - xchg eax,ecx - xor edx,01000000b //; Closer to Y axis so make DX=64 for quad 0 and 2. -gotaxis: - - //; If closer to the X axis then add 64 for quadrants 0 and 2. If - //; closer to the Y axis then add 64 for quadrants 1 and 3. Determined - //; add value is in DX and save on stack. - push edx - - //; Make sure that the division won't overflow. Reduce precision until - //; the larger number is less than 256 if it appears that an overflow - //; will occur. If the high byte of the divisor is not zero, then this - //; guarantees no overflow, so just abort shift operation. - test eax,0FFFFFF00h - jnz short nooverflow -again: - test ecx,0FFFFFF00h - jz short nooverflow - shr ecx,1 - shr eax,1 - jmp short again -nooverflow: - - //; Make sure that the division won't underflow (divide by zero). If - //; this would occur, then set the quotient to $FF and skip divide. - or ecx,ecx - jnz short nounderflow - mov eax,0FFFFFFFFh - jmp short divcomplete - - //; Derive a pseudo angle number for the octant. The angle is based - //; on $00 = angle matches long axis, $00 = angle matches $FF degrees. -nounderflow: - xor edx,edx - shld edx,eax,8 //; shift high byte of eax into dl - shl eax,8 - div ecx -divcomplete: - - //; Integrate the 5 most significant bits into the angle index. If DX - //; is not zero, then it is 64. This means that the dividend must be negated - //; before it is added into the final angle value. - shr eax,3 - pop edx - or edx,edx - je short noneg - dec edx - neg eax -noneg: - add eax,edx - add eax,ebx - and eax,0FFH -// ret + if (x_diff < 0) { + x_diff = -x_diff; + unk1 = -64; } + + int y_diff = y1 - y2; + + if (y_diff < 0) { + unk1 ^= 64; + y_diff = -y_diff; + } + + int s_diff; + unsigned l_diff; + + if (x_diff != 0 || y_diff != 0) { + if (x_diff >= y_diff) { + s_diff = y_diff; + l_diff = x_diff; + } + else { + s_diff = x_diff; + l_diff = y_diff; + } + + unsigned unk2 = 32 * s_diff / l_diff; + int ranged_dir = unk1 & 64; + + if (x_diff > y_diff) { + ranged_dir = ranged_dir ^ 64; + } + + if (ranged_dir != 0) { + unk2 = ranged_dir - unk2 - 1; + } + + return (DirType)((unk2 + unk1) & 255); + } + + return 255; } @@ -371,255 +186,48 @@ GLOBAL C Desired_Facing8 :NEAR int __cdecl Desired_Facing8(long x1, long y1, long x2, long y2) { - static const char _new_facing8[] = {1,2,1,0,7,6,7,0,3,2,3,4,5,6,5,4}; - - __asm { - - xor ebx,ebx //; Index byte (built). + int xdiff = 0; + int ydiff = 0; + char dirtype = 0; - //; Determine Y axis difference. - mov edx,[y1] - mov ecx,[y2] - sub edx,ecx //; DX = Y axis (signed). - jns short absy - inc ebx //; Set the signed bit. - neg edx //; ABS(y) -absy: - - //; Determine X axis difference. - shl ebx,1 - mov eax,[x1] - mov ecx,[x2] - sub ecx,eax //; CX = X axis (signed). - jns short absx - inc ebx //; Set the signed bit. - neg ecx //; ABS(x) -absx: - - //; Determine the greater axis. - cmp ecx,edx - jb short dxisbig - xchg ecx,edx -dxisbig: - rcl ebx,1 //; Y > X flag bit. - - //; Determine the closeness or farness of lesser axis. - mov eax,edx - inc eax //; Round up. - shr eax,1 - - cmp ecx,eax - rcl ebx,1 //; Close to major axis bit. - - xor eax,eax - mov al,[_new_facing8+ebx] - - //; Normalize to 0..FF range. - shl eax,5 - -// ret + xdiff = x2 - x1; + if (xdiff < 0) { + dirtype = -64; + xdiff = -xdiff; } - -} + ydiff = y1 - y2; - -#if (0) - -/* - ; $Header: //depot/Projects/Mobius/QA/Project/Run/SOURCECODE/REDALERT/MiscAsm.cpp#33 $ -;*************************************************************************** -;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** -;*************************************************************************** -;* * -;* Project Name : Support Library * -;* * -;* File Name : FACING16.ASM * -;* * -;* Programmer : Joe L. Bostic * -;* * -;* Start Date : May 8, 1991 * -;* * -;* Last Update : February 6, 1995 [BWG] * -;* * -;*-------------------------------------------------------------------------* -;* Functions: * -;* Desired_Facing16 -- Converts coordinates into a facing number. * -;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - -IDEAL -P386 -MODEL USE32 FLAT - -GLOBAL C Desired_Facing16 :NEAR -; INCLUDE "wwlib.i" - - DATASEG - -; 16 direction desired facing lookup table. Build the index according -; to the following bits: -; -; bit 4 = Is y2 < y1? -; bit 3 = Is x2 < x1? -; bit 2 = Is the ABS(x2-x1) < ABS(y2-y1)? -; bit 1 = Is the lesser absolute difference very close to zero? -; bit 0 = Is the lesser absolute difference very close to the greater dist? -NewFacing16 DB 3, 2, 4,-1, 1, 2,0,-1 - DB 13,14,12,-1,15,14,0,-1 - DB 5, 6, 4,-1, 7, 6,8,-1 - DB 11,10,12,-1, 9,10,8,-1 - - CODESEG - -;*************************************************************************** -;* DESIRED_FACING16 -- Converts coordinates into a facing number. * -;* * -;* This converts coordinates into a desired facing number that ranges * -;* from 0 to 15 (0 equals North and going clockwise). * -;* * -;* INPUT: x1,y1 -- Position of origin point. * -;* * -;* x2,y2 -- Position of target. * -;* * -;* OUTPUT: Returns desired facing as a number from 0 to 255 but * -;* accurate to 22.5 degree increments. * -;* * -;* WARNINGS: If the two coordinates are the same, then -1 will be * -;* returned. It is up to you to handle this case. * -;* * -;* HISTORY: * -;* 08/14/1991 JLB : Created. * -;*=========================================================================* -*/ -long __cdecl Desired_Facing16(long x1, long y1, long x2, long y2) -{ - - __asm { - xor ebx,ebx ; Index byte (built). - - ; Determine Y axis difference. - mov edx,[y1] - mov ecx,[y2] - sub edx,ecx //; DX = Y axis (signed). - jns short absy - inc ebx //; Set the signed bit. - neg edx //; ABS(y) -absy: - - //; Determine X axis difference. - shl ebx,1 - mov eax,[x1] - mov ecx,[x2] - sub ecx,eax //; CX = X axis (signed). - jns short absx - inc ebx //; Set the signed bit. - neg ecx //; ABS(x) -absx: - - //; Determine the greater axis. - cmp ecx,edx - jb short dxisbig - xchg ecx,edx -dxisbig: - rcl ebx,1 //; Y > X flag bit. - - //; Determine the closeness or farness of lesser axis. - mov eax,edx - inc eax //; Round up. - shr eax,1 - inc eax //; Round up. - shr eax,1 //; 1/4 of greater axis. - - cmp ecx,eax - rcl ebx,1 //; Very close to major axis bit. - - sub edx,eax - cmp edx,ecx - rcl ebx,1 //; Very far from major axis bit. - - xor eax,eax - mov al,[NewFacing16+ebx] - - //; Normalize to 0..FF range. - shl eax,4 - -// ret + if (ydiff < 0) { + dirtype ^= 0x40; + ydiff = -ydiff; } + + unsigned int lower_diff; + + if (xdiff >= ydiff) { + lower_diff = ydiff; + ydiff = xdiff; + } + else { + lower_diff = xdiff; + } + + char ranged_dir; + + if (((unsigned)(ydiff + 1) >> 1) > lower_diff) { + ranged_dir = ((unsigned)dirtype) & 64; + + if (xdiff == ydiff) { + ranged_dir ^= 64; + } + + return (DirType)(dirtype + ranged_dir); + } + + return (DirType)(dirtype + 32); } - - - - -#if (0) - PROC Desired_Facing16 C near - USES ebx, ecx, edx - - ARG x1:DWORD - ARG y1:DWORD - ARG x2:DWORD - ARG y2:DWORD - - xor ebx,ebx ; Index byte (built). - - ; Determine Y axis difference. - mov edx,[y1] - mov ecx,[y2] - sub edx,ecx ; DX = Y axis (signed). - jns short ??absy - inc ebx ; Set the signed bit. - neg edx ; ABS(y) -??absy: - - ; Determine X axis difference. - shl ebx,1 - mov eax,[x1] - mov ecx,[x2] - sub ecx,eax ; CX = X axis (signed). - jns short ??absx - inc ebx ; Set the signed bit. - neg ecx ; ABS(x) -??absx: - - ; Determine the greater axis. - cmp ecx,edx - jb short ??dxisbig - xchg ecx,edx -??dxisbig: - rcl ebx,1 ; Y > X flag bit. - - ; Determine the closeness or farness of lesser axis. - mov eax,edx - inc eax ; Round up. - shr eax,1 - inc eax ; Round up. - shr eax,1 ; 1/4 of greater axis. - - cmp ecx,eax - rcl ebx,1 ; Very close to major axis bit. - - sub edx,eax - cmp edx,ecx - rcl ebx,1 ; Very far from major axis bit. - - xor eax,eax - mov al,[NewFacing16+ebx] - - ; Normalize to 0..FF range. - shl eax,4 - - ret - - ENDP Desired_Facing16 - - END -#endif -#endif - - - - @@ -660,24 +268,13 @@ dxisbig: unsigned int __cdecl Cardinal_To_Fixed(unsigned base, unsigned cardinal) { - __asm { - - mov eax, 0FFFFFFFFh //; establish default return value + // jmarshall: this is from me, hope this is right. + unsigned int result; // eax - mov ebx,[base] - or ebx, ebx - jz retneg1 //; if base==0, return 4294967295 - - mov eax,[cardinal] //; otherwise, return (cardinal*65536)/base - shl eax,16 - xor edx,edx - div ebx - -retneg1: - //ret - - - } + result = -1; + if (base) + result = (cardinal << 16) / base; + return result; } #if (0) @@ -724,138 +321,123 @@ retneg1: unsigned int __cdecl Fixed_To_Cardinal(unsigned base, unsigned fixed) { -// PROC Fixed_To_Cardinal C near -// USES edx - -// ARG base:DWORD -// ARG fixed:DWORD - - __asm { - mov eax,[base] - mul [fixed] - add eax,08000h //; eax = (base * fixed) + 0x8000 - - shr eax,16 //; return eax/65536 - //ret - } - - -#if (0) - mov eax,[base] - mul [fixed] - add eax,080h ; eax = (base * fixed) + 0x80 - - test eax,0FF000000h ; if high byte set, return FFFF - jnz ??rneg1 - shr eax,8 ; else, return eax/256 - ret -??rneg1 : - mov eax,0FFFFh ; establish default return value - ret - - ENDP Fixed_To_Cardinal - - END -#endif - - + // jmarshall: this one is from me I hope its right. + return (fixed * base + 0x8000) >> 16; } - - - - - - - - - - - - - - +// jmarshall: this is from chronoshift void __cdecl Set_Bit(void * array, int bit, int value) { - __asm { - mov ecx, [bit] - mov eax, [value] - mov esi, [array] - mov ebx,ecx - shr ebx,5 - and ecx,01Fh - btr [esi+ebx*4],ecx - or eax,eax - jz ok - bts [esi+ebx*4],ecx -ok: + // Don't try and handle a negative value + if (bit < 0) { + return; + } + + uint8_t* byte_array = (uint8_t*)array; + + if (value) { + byte_array[bit / 8] |= 1 << (bit % 8); + } + else { + byte_array[bit / 8] &= ~(1 << (bit % 8)); } } int __cdecl Get_Bit(void const * array, int bit) { - __asm { - mov eax, [bit] - mov esi, [array] - mov ebx,eax - shr ebx,5 - and eax,01Fh - bt [esi+ebx*4],eax - setc al + // If negative it is out of range so can't be set + if (bit < 0) { + return false; } + + const uint8_t* byte_array = (const uint8_t*)array; + + return byte_array[bit / 8] & (1 << (bit % 8)) ? true : false; } -int __cdecl First_True_Bit(void const * array) +/** + * @brief Scans through the data and returns the position of the first set bit found. + */ +int First_True_Bit(const void* array, int size) { - __asm { - mov esi, [array] - mov eax,-32 -again: - add eax,32 - mov ebx,[esi] - add esi,4 - bsf ebx,ebx - jz again - add eax,ebx + const uint8_t* byte_array = (const uint8_t*)array; + + int bytenum = 0; + int bitnum = 0; + + // Find the first none zero byte as it must contain the first bit. + for (bytenum = 0; bytenum < size; ++bytenum) { + if (byte_array[bytenum] != 0) { + break; + } } + + if (bytenum >= size) { + return 8 * bytenum; + } + + // Scan through the bits of the byte until we find the first set bit. + for (bitnum = 0; bitnum < 8; ++bitnum) { + if (Get_Bit(&byte_array[bytenum], bitnum)) { + break; + } + } + + return 8 * bytenum + bitnum; } - -int __cdecl First_False_Bit(void const * array) +/** + * @brief Scans through the data and returns the position of the first clear bit found. + */ +int First_False_Bit(const void* array, int size) { - __asm { - - mov esi, [array] - mov eax,-32 -again: - add eax,32 - mov ebx,[esi] - not ebx - add esi,4 - bsf ebx,ebx - jz again - add eax,ebx + const uint8_t* byte_array = (const uint8_t*)array; + + int bytenum = 0; + int bitnum = 0; + + // Find the first byte with an unset bit as it must contain the first bit. + for (bytenum = 0; bytenum < size; ++bytenum) { + if (byte_array[bytenum] != 0xFF) { + break; + } } + + if (bytenum >= size) { + return 8 * bytenum; + } + + // Scan through the bits until we find one that isn't set. + for (bitnum = 0; bitnum < 8; ++bitnum) { + if (!Get_Bit(&byte_array[bytenum], bitnum)) { + break; + } + } + + return 8 * bytenum + bitnum; } int __cdecl Bound(int original, int min, int max) { - __asm { - mov eax,[original] - mov ebx,[min] - mov ecx,[max] - cmp ebx,ecx - jl okorder - xchg ebx,ecx -okorder: cmp eax,ebx - jg okmin - mov eax,ebx -okmin: cmp eax,ecx - jl okmax - mov eax,ecx -okmax: + // jmarshall: this is just a clamp, todo simplify me! + int result; // eax + int v4; // ebx + int v5; // ecx + + result = original; + v4 = min; + v5 = max; + if (min >= max) + { + v4 = max; + v5 = min; } + if (original <= v4) + result = v4; + if (result >= v5) + result = v5; + return result; } @@ -1069,189 +651,40 @@ GLOBAL C Shake_Screen :NEAR ;* 10/07/1992 JLB : Created. * ;*=========================================================================*/ -void * __cdecl Conquer_Build_Fading_Table(void const *palette, void *dest, int color, int frac) +// This function is from Chronoshift. +void * __cdecl Conquer_Build_Fading_Table(void const *paletteptr, void *fade_table, int color, int frac) { - /* - global C Conquer_Build_Fading_Table : NEAR - PROC Conquer_Build_Fading_Table C near - USES ebx, ecx, edi, esi + const PaletteClass& palette = *((const PaletteClass*)paletteptr); + if (fade_table) { + uint8_t* dst = static_cast(fade_table); + RGBClass const* target_col = &palette[color]; - ARG palette:DWORD - ARG dest:DWORD - ARG color:DWORD - ARG frac:DWORD + for (int i = 0; i < 256; ++i) { + if (i <= 240 && i) { + RGBClass tmp = palette[i]; + tmp.Adjust(frac, *target_col); - 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. - -ALLOWED_COUNT EQU 16 -ALLOWED_START EQU 256-ALLOWED_COUNT - */ + int index = 0; + int prevdiff = -1; -#define ALLOWED_COUNT 16 -#define ALLOWED_START 256-ALLOWED_COUNT + for (int j = 240; j < 255; ++j) { + int difference = palette[j].Difference(tmp); - 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. + if (prevdiff == -1 || difference < prevdiff) { + index = j; + prevdiff = difference; + } + } - __asm { - - cld - - ; If the source palette is NULL, then just return with current fading table pointer. - cmp [palette],0 - je fini1 - cmp [dest],0 - je fini1 - - ; 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 eax,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 eax,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 eax,1 - sub dh,ah ; dh = orig - ((orig-target) * fraction) - mov [idealblue],dh ; preserve ideal color gun value. - - ; Sweep through a limited set of existing colors to find the closest - ; matching color. - - mov eax,[color] - mov [matchcolor],al ; Default color (self). - mov [matchvalue],-1 ; Ridiculous match value init. - mov ecx,ALLOWED_COUNT - - mov esi,[palette] ; Pointer to original palette. - add esi,(ALLOWED_START)*3 - - ; BH = color index. - mov bh,ALLOWED_START - innerloop: - - xor edx,edx ; Comparison value starts null. - - ; 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] - jae 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,ALLOWED_START-1 - jne mainloop - - ; Fill the remainder of the remap table with values - ; that will remap the color to itself. - mov ecx,ALLOWED_COUNT - fillerloop: - inc bl - mov al,bl - stosb - loop fillerloop - - fini1: - mov esi,[dest] - mov eax,esi - - //ret + dst[i] = index; + } + else { + dst[i] = i; + } + } } + + return fade_table; } @@ -1261,31 +694,46 @@ ALLOWED_START EQU 256-ALLOWED_COUNT extern "C" long __cdecl Reverse_Long(long number) { +#if 0 // jmarshall __asm { mov eax,dword ptr [number] xchg al,ah ror eax,16 xchg al,ah } +#else + assert("Reverse_Long not implmeneted"); + return number; +#endif } extern "C" short __cdecl Reverse_Short(short number) { +#if 0 // jmarshall __asm { mov ax,[number] xchg ah,al } +#else + assert("Reverse_Short not implmeneted"); + return number; +#endif } extern "C" long __cdecl Swap_Long(long number) { +#if 0 // jmarshall __asm { mov eax,dword ptr [number] ror eax,16 } +#else + assert("Reverse_Short not implmeneted"); + return number; +#endif } @@ -1324,43 +772,35 @@ extern "C" long __cdecl Swap_Long(long number) */ void __cdecl strtrim(char *buffer) { - __asm { - cmp [buffer],0 - je short fini + char* v1; // esi + char v2; // al + char* v3; // edi + char v4; // al + char* v5; // edi - ; Prepare for string scanning by loading pointers. - cld - mov esi,[buffer] - mov edi,esi - - ; Strip white space from the start of the string. - looper: - lodsb - cmp al,20h ; Space - je short looper - cmp al,9 ; TAB - je short looper - stosb - - ; Copy the rest of the string. - gruntloop: - lodsb - stosb - or al,al - jnz short gruntloop - dec edi - ; Strip the white space from the end of the string. - looper2: - mov [edi],al - dec edi - mov ah,[edi] - cmp ah,20h - je short looper2 - cmp ah,9 - je short looper2 - - fini: - //ret + if (buffer) + { + v1 = buffer; + do + { + do + v2 = *v1++; + while (v2 == 32); + } while (v2 == 9); + *buffer = v2; + v3 = buffer + 1; + do + { + v4 = *v1++; + *v3++ = v4; + } while (v4); + v5 = v3 - 1; + do + { + do + *v5-- = 0; + while (*v5 == 32); + } while (*v5 == 9); } } @@ -1403,50 +843,7 @@ void __cdecl strtrim(char *buffer) void __cdecl Fat_Put_Pixel(int x, int y, int color, int siz, GraphicViewPortClass &gpage) { - __asm { - - cmp [siz],0 - je short exit_label - ; Set EDI to point to start of logical page memory. - ;*=================================================================== - ; Get the viewport information and put bytes per row in ecx - ;*=================================================================== - mov ebx,[gpage] ; get a pointer to viewport - mov edi,[ebx]GraphicViewPortClass.Offset ; get the correct offset - - ; Verify the the Y pixel offset is legal. - mov eax,[y] - cmp eax,[ebx]GraphicViewPortClass.Height ;YPIXEL_MAX - jae short exit_label - mov ecx,[ebx]GraphicViewPortClass.Width - add ecx,[ebx]GraphicViewPortClass.XAdd - add ecx,[ebx]GraphicViewPortClass.Pitch - mul ecx - add edi,eax - - ; Verify the the X pixel offset is legal. - - mov edx,[ebx]GraphicViewPortClass.Width - cmp edx,[x] - mov edx,ecx - jbe short exit_label - add edi,[x] - - ; Write the pixel to the screen. - mov ebx,[siz] ; Copy of pixel size. - sub edx,ebx ; Modulo to reach start of next row. - mov eax,[color] - again: - mov ecx,ebx - rep stosb - add edi,edx ; EDI points to start of next row. - dec [siz] - jnz short again - - exit_label: - //ret - } } diff --git a/code/REDALERT/VECTOR.H b/code/REDALERT/VECTOR.H index 5b5fe77..fb8e5a8 100644 --- a/code/REDALERT/VECTOR.H +++ b/code/REDALERT/VECTOR.H @@ -361,7 +361,7 @@ class BooleanVectorClass int First_False(void) const { if (LastIndex != -1) Fixup(-1); - int retval = First_False_Bit(&BitArray[0]); + int retval = First_False_Bit(&BitArray[0], BitArray.Length()); if (retval < BitCount) return(retval); /* @@ -375,7 +375,7 @@ class BooleanVectorClass int First_True(void) const { if (LastIndex != -1) Fixup(-1); - int retval = First_True_Bit(&BitArray[0]); + int retval = First_True_Bit(&BitArray[0], BitArray.Length()); if (retval < BitCount) return(retval); /* diff --git a/code/REDALERT/WIN32LIB/DrawMisc.cpp b/code/REDALERT/WIN32LIB/DrawMisc.cpp index ad65e30..441f75f 100644 --- a/code/REDALERT/WIN32LIB/DrawMisc.cpp +++ b/code/REDALERT/WIN32LIB/DrawMisc.cpp @@ -105,455 +105,8 @@ extern int UnCachedIconsDrawn; 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; +void __cdecl Buffer_Draw_Line(void *this_object, int sx, int sy, int dx, int dy, unsigned char color) { - 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: - } } @@ -1421,55 +974,7 @@ GLOBAL C Buffer_Draw_Stamp_Clip:near 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 - - } + } @@ -1506,144 +1011,7 @@ fini: 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 - } } @@ -1739,112 +1107,318 @@ void __cdecl Copy_Delta_Buffer(int nextrow); */ 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] + int8_t* putp = (int8_t*)(target); + int8_t* getp = (int8_t*)(delta); + uint16_t count = 0; + int8_t value = 0; + int8_t cmd = 0; - cld ; make sure we go forward - xor ecx,ecx ; use cx for loop + while (true) { + // captainslog_debug("XOR_Delta Put pos: %u, Get pos: %u.... ", putp - static_cast(dest), getp - + // static_cast(source)); + cmd = *getp++; + count = cmd; + bool xorval = false; - top_loop: - xor eax,eax ; clear out eax. - mov al,[esi] ; get delta source byte - inc esi + if (cmd >= 0) { + // 0b00000000 + if (cmd == 0) { + count = *getp++ & 0xFF; + value = *getp++; + xorval = true; + // captainslog_debug("0b00000000 Val Count %d ", count); + // 0b0??????? + } + else { + // captainslog_debug("0b0??????? XOR Count %d ", count); + } + } + else { + // 0b1??????? remove most significant bit + count &= 0x7F; + if (count != 0) { + putp += count; + // captainslog_debug("0b1??????? Skip Count %d", count); + continue; + } - test al,al ; check for a SHORTDUMP ; check al incase of sign value. - je short_run - js check_others + count = (*getp & 0xFF) + (*(getp + 1) << 8); + getp += 2; - ; - ; SHORTDUMP - ; - mov ecx,eax ; stick count in cx + // captainslog_debug("Eval %u ", count); - 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 + // 0b10000000 0 0 + if (count == 0) { + // captainslog_debug("0b10000000 Count %d to end delta", count); + return 0; + } - ; - ; SHORTRUN - ; + // 0b100000000 0? + if ((count & 0x8000) == 0) { + putp += count; + // captainslog_debug("0b100000000 0? Skip Count %d", count); + continue; + } + else { + // 0b10000000 11 + if (count & 0x4000) { + count &= 0x3FFF; + value = *getp++; + // captainslog_debug("0b10000000 11 Val Count %d ", count); + xorval = true; + // 0b10000000 10 + } + else { + count &= 0x3FFF; + // captainslog_debug("0b10000000 10 XOR Count %d ", count); + } + } + } - 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 + if (xorval) { + // captainslog_debug("XOR Val %d", value); + for (; count > 0; --count) { + *putp++ ^= value; + } + } + else { + // captainslog_debug("XOR Source to Dest"); + for (; count > 0; --count) { + *putp++ ^= *getp++; + } + } + } + return 0; +} - 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 +void Copy_Delta_Buffer(int width, void* offset, void* delta, int pitch) +{ + int8_t* putp = static_cast(offset); + int8_t* getp = static_cast(delta); + int8_t value = 0; + int8_t cmd = 0; + int length = 0; + int count = 0; - ; - ; LONGRUN - ; - sub eax,04000h ; opcode -= 0x4000 - mov ecx,eax ; use cx as loop count - jmp do_run ; jump to run code. + while (true) { + // captainslog_debug("XOR_Delta Put pos: %u, Get pos: %u.... ", putp - static_cast(dest), getp - + // static_cast(source)); + cmd = *getp++; + count = cmd; + bool xorval = false; + if (cmd >= 0) { + // 0b00000000 + if (cmd == 0) { + count = *getp++ & 0xFF; + value = *getp++; + xorval = true; + // captainslog_debug("0b00000000 Val Count %d ", count); + // 0b0??????? + } + else { + // captainslog_debug("0b0??????? XOR Count %d ", count); + } + } + else { + // 0b1??????? remove most significant bit + count &= 0x7F; + if (count != 0) { + putp -= length; + length += count; - ; - ; LONGDUMP - ; + while (length >= width) { + length -= width; + putp += pitch; + } - long_dump: - mov ecx,eax ; use cx as loop count - jmp dump_loop ; go to the dump loop. + putp += length; + // captainslog_debug("0b1??????? Skip Count %d", count); + continue; + } - stop: + count = (*getp & 0xFF) + (*(getp + 1) << 8); + getp += 2; + + // captainslog_debug("Eval %u ", count); + + // 0b10000000 0 0 + if (count == 0) { + // captainslog_debug("0b10000000 Count %d to end delta", count); + return; + } + + // 0b100000000 0? + if ((count & 0x8000) == 0) { + putp -= length; + length += count; + + while (length >= width) { + length -= width; + putp += pitch; + } + + putp += length; + // captainslog_debug("0b100000000 0? Skip Count %d", count); + continue; + } + else { + // 0b10000000 11 + if (count & 0x4000) { + count &= 0x3FFF; + value = *getp++; + // captainslog_debug("0b10000000 11 Val Count %d ", count); + xorval = true; + // 0b10000000 10 + } + else { + count &= 0x3FFF; + // captainslog_debug("0b10000000 10 XOR Count %d ", count); + } + } + } + + if (xorval) { + // captainslog_debug("XOR Val %d", value); + for (; count > 0; --count) { + *putp++ = value; + ++length; + + if (length == width) { + length = 0; + putp += pitch - width; + } + } + } + else { + // captainslog_debug("XOR Source to Dest"); + for (; count > 0; --count) { + *putp++ = *getp++; + ++length; + + if (length == width) { + length = 0; + putp += pitch - width; + } + } + } } } +void XOR_Delta_Buffer(int width, void* offset, void* delta, int pitch) +{ + int8_t* putp = static_cast(offset); + int8_t* getp = static_cast(delta); + int8_t value = 0; + int8_t cmd = 0; + int length = 0; + int count = 0; + + while (true) { + // captainslog_debug("XOR_Delta Put pos: %u, Get pos: %u.... ", putp - static_cast(dest), getp - + // static_cast(source)); + cmd = *getp++; + count = cmd; + bool xorval = false; + + if (cmd >= 0) { + // 0b00000000 + if (cmd == 0) { + count = *getp++ & 0xFF; + value = *getp++; + xorval = true; + // captainslog_debug("0b00000000 Val Count %d ", count); + // 0b0??????? + } + else { + // captainslog_debug("0b0??????? XOR Count %d ", count); + } + } + else { + // 0b1??????? remove most significant bit + count &= 0x7F; + if (count != 0) { + putp -= length; + length += count; + + while (length >= width) { + length -= width; + putp += pitch; + } + + putp += length; + // captainslog_debug("0b1??????? Skip Count %d", count); + continue; + } + + count = (*getp & 0xFF) + (*(getp + 1) << 8); + getp += 2; + + // captainslog_debug("Eval %u ", count); + + // 0b10000000 0 0 + if (count == 0) { + // captainslog_debug("0b10000000 Count %d to end delta", count); + return; + } + + // 0b100000000 0? + if ((count & 0x8000) == 0) { + putp -= length; + length += count; + + while (length >= width) { + length -= width; + putp += pitch; + } + + putp += length; + // captainslog_debug("0b100000000 0? Skip Count %d", count); + continue; + } + else { + // 0b10000000 11 + if (count & 0x4000) { + count &= 0x3FFF; + value = *getp++; + // captainslog_debug("0b10000000 11 Val Count %d ", count); + xorval = true; + // 0b10000000 10 + } + else { + count &= 0x3FFF; + // captainslog_debug("0b10000000 10 XOR Count %d ", count); + } + } + } + + if (xorval) { + // captainslog_debug("XOR Val %d", value); + for (; count > 0; --count) { + *putp++ ^= value; + ++length; + + if (length == width) { + length = 0; + putp += pitch - width; + } + } + } + else { + // captainslog_debug("XOR Source to Dest"); + for (; count > 0; --count) { + *putp++ ^= *getp++; + ++length; + + if (length == width) { + length = 0; + putp += pitch - width; + } + } + } + } +} /* ;---------------------------------------------------------------------------- @@ -1873,359 +1447,17 @@ PROC Apply_XOR_Delta C near ;*=========================================================================* */ -void __cdecl Apply_XOR_Delta_To_Page_Or_Viewport(void *target, void *delta, int width, int nextrow, int copy) +void __cdecl Apply_XOR_Delta_To_Page_Or_Viewport(void *offset, void *delta, int width, int pitch, 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. + if (copy) { + Copy_Delta_Buffer(width, offset, delta, pitch); + } + else { + XOR_Delta_Buffer(width, offset, delta, pitch); } } -/* -;---------------------------------------------------------------------------- - - -;*************************************************************************** -;* 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: - - } -} -/* -;---------------------------------------------------------------------------- -*/ - - - - @@ -2283,178 +1515,55 @@ GLOBAL C Build_Fading_Table :NEAR ; Bounds Checking: None ;* */ -void * __cdecl Build_Fading_Table(void const *palette, void const *dest, long int color, long int frac) +void * __cdecl Build_Fading_Table(void const *palette, void const * fade_table, 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 - - + if (fade_table == nullptr) { + return nullptr; } + + uint8_t* table = (uint8_t*)(fade_table); + uint8_t const* pal = reinterpret_cast(&palette); + + // First entry always maps to itself for transparency + *table++ = 0; + + for (int i = 1; i < 256; i++) { + // Create adjusted versions of the palette entries based on reference + // colour and fraction to adjust by. + uint8_t red = pal[3 * i + 0] - (((pal[3 * i + 0] - pal[3 * color + 0]) * (frac / 2)) >> 7); + uint8_t grn = pal[3 * i + 1] - (((pal[3 * i + 1] - pal[3 * color + 1]) * (frac / 2)) >> 7); + uint8_t blu = pal[3 * i + 2] - (((pal[3 * i + 2] - pal[3 * color + 2]) * (frac / 2)) >> 7); + uint8_t closest = color; + unsigned min_diff = 0xFFFFFFFF; + + // For each palette entry calculate difference from adjusted version of + // target color and find closest colour to use from palette. + for (int j = 1; j < 256; ++j) { + if (j == i) { + continue; + } + + unsigned diff = 0; + + diff += (pal[3 * j + 0] - red) * (pal[3 * j + 0] - red); + diff += (pal[3 * j + 1] - grn) * (pal[3 * j + 1] - grn); + diff += (pal[3 * j + 2] - blu) * (pal[3 * j + 2] - blu); + + if (!diff) { + closest = j; + break; + } + + if (diff <= min_diff) { + min_diff = diff; + closest = j; + } + } + + *table++ = closest; + } + + return (void *)fade_table; } @@ -2584,77 +1693,6 @@ void __cdecl Set_Palette_Range(void *palette) } -/* -;*************************************************************************** -;* 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] - } -} - - - - - - @@ -2719,52 +1757,7 @@ CODESEG 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: - } + } @@ -2826,137 +1819,45 @@ CODESEG ; 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 ) +extern "C" int __cdecl Clip_Rect ( int * x , int * y , int * w , int * h , int clip_w, int clip_h) { + int xstart = *x; + int ystart = *y; + int yend = *y + *h - 1; + int xend = *x + *w - 1; + int result = 0; -/* - 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 + // If we aren't drawing within bounds, return -1 + if (xstart >= clip_w || ystart >= clip_h || xend < 0 || yend < 0) { + return -1; } - //ENDP Clip_Rect + if (xstart < 0) { + xstart = 0; + result = 1; + } + + if (ystart < 0) { + ystart = 0; + result = 1; + } + + if (xend >= clip_w - 1) { + xend = clip_w - 1; + result = 1; + } + + if (yend >= clip_h - 1) { + yend = clip_h - 1; + result = 1; + } + + *x = xstart; + *y = ystart; + *w = xend - xstart + 1; + *h = yend - ystart + 1; + + return result; } /* @@ -2979,374 +1880,34 @@ extern "C" int __cdecl Clip_Rect ( int * x , int * y , int * w , int * h , int w ; 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 ) +extern "C" int __cdecl Confine_Rect ( int * x_pos , int * y_pos , int x , int y , int w , int h ) { - -/* - 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] + BOOL confined = false; - mov esi,[ebx] - add edi,[ebx] + if ((-*x_pos & (*x_pos + x - w - 1)) >= 0) { + if (*x_pos > 0) { + *x_pos -= *x_pos + x - w; + } + else { + *x_pos = 0; + } - 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 + confined = true; } -} + if ((-*y_pos & (*y_pos + y - h - 1)) >= 0) { + if (*y_pos > 0) { + *y_pos -= *y_pos + y - h; + } + else { + *y_pos = 0; + } - - - - - - - -/* -; $Header: //depot/Projects/Mobius/QA/Project/Run/SOURCECODE/REDALERT/WIN32LIB/DrawMisc.cpp#33 $ -;*************************************************************************** -;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** -;*************************************************************************** -;* * -;* Project Name : Library routine * -;* * -;* File Name : UNCOMP.ASM * -;* * -;* Programmer : Christopher Yates * -;* * -;* Last Update : 20 August, 1990 [CY] * -;* * -;*-------------------------------------------------------------------------* -;* Functions: * -;* * -; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length); * -;* * -;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - -IDEAL -P386 -MODEL USE32 FLAT - -GLOBAL C LCW_Uncompress :NEAR - -CODESEG - -; ---------------------------------------------------------------- -; -; Here are prototypes for the routines defined within this module: -; -; ULONG LCW_Uncompress(BYTE *source, BYTE *dest, ULONG length); -; -; ---------------------------------------------------------------- -*/ -#if (0)//ST 5/10/2019 -extern "C" unsigned long __cdecl LCW_Uncompress(void *source, void *dest, unsigned long length_) -{ -//PROC LCW_Uncompress C near -// -// USES ebx,ecx,edx,edi,esi -// -// ARG source:DWORD -// ARG dest:DWORD -// ARG length:DWORD -//;LOCALS -// LOCAL a1stdest:DWORD -// LOCAL maxlen:DWORD -// LOCAL lastbyte:DWORD -// LOCAL lastcom:DWORD -// LOCAL lastcom1:DWORD - - unsigned long a1stdest; - unsigned long maxlen; - unsigned long lastbyte; - //unsigned long lastcom; - //unsigned long lastcom1; - - __asm { - - - mov edi,[dest] - mov esi,[source] - mov edx,[length_] - - ; - ; - ; uncompress data to the following codes in the format b = byte, w = word - ; n = byte code pulled from compressed data - ; Bit field of n command description - ; n=0xxxyyyy,yyyyyyyy short run back y bytes and run x+3 - ; n=10xxxxxx,n1,n2,...,nx+1 med length copy the next x+1 bytes - ; n=11xxxxxx,w1 med run run x+3 bytes from offset w1 - ; n=11111111,w1,w2 long copy copy w1 bytes from offset w2 - ; n=11111110,w1,b1 long run run byte b1 for w1 bytes - ; n=10000000 end end of data reached - ; - - mov [a1stdest],edi - add edx,edi - mov [lastbyte],edx - cld ; make sure all lod and sto are forward - mov ebx,esi ; save the source offset - - loop_label: - mov eax,[lastbyte] - sub eax,edi ; get the remaining byte to uncomp - jz short out_label ; were done - - mov [maxlen],eax ; save for string commands - mov esi,ebx ; mov in the source index - - xor eax,eax - mov al,[esi] - inc esi - test al,al ; see if its a short run - js short notshort - - mov ecx,eax ;put count nibble in cl - - mov ah,al ; put rel offset high nibble in ah - and ah,0Fh ; only 4 bits count - - shr cl,4 ; get run -3 - add ecx,3 ; get actual run length - - cmp ecx,[maxlen] ; is it too big to fit? - jbe short rsok ; if not, its ok - - mov ecx,[maxlen] ; if so, max it out so it dosen't overrun - - rsok: - mov al,[esi] ; get rel offset low byte - lea ebx,[esi+1] ; save the source offset - mov esi,edi ; get the current dest - sub esi,eax ; get relative offset - - rep movsb - - jmp loop_label - - notshort: - test al,40h ; is it a length? - jne short notlength ; if not it could be med or long run - - cmp al,80h ; is it the end? - je short out_label ; if so its over - - mov cl,al ; put the byte in count register - and ecx,3Fh ; and off the extra bits - - cmp ecx,[maxlen] ; is it too big to fit? - jbe short lenok ; if not, its ok - - mov ecx,[maxlen] ; if so, max it out so it dosen't overrun - - lenok: - rep movsb - - mov ebx,esi ; save the source offset - jmp loop_label - - out_label: - mov eax,edi - sub eax,[a1stdest] - jmp label_exit - - notlength: - mov cl,al ; get the entire code - and ecx,3Fh ; and off all but the size -3 - add ecx,3 ; add 3 for byte count - - cmp al,0FEh - jne short notrunlength - - xor ecx,ecx - mov cx,[esi] - - xor eax,eax - mov al,[esi+2] - lea ebx,[esi+3] ;save the source offset - - cmp ecx,[maxlen] ; is it too big to fit? - jbe short runlenok ; if not, its ok - - mov ecx,[maxlen] ; if so, max it out so it dosen't overrun - - runlenok: - test ecx,0ffe0h - jnz dont_use_stosb - rep stosb - jmp loop_label - - - dont_use_stosb: - mov ah,al - mov edx,eax - shl eax,16 - or eax,edx - - test edi,3 - jz aligned - - mov [edi],eax - mov edx,edi - and edi,0fffffffch - lea edi,[edi+4] - and edx,3 - dec dl - xor dl,3 - sub ecx,edx - - aligned: - mov edx,ecx - shr ecx,2 - rep stosd - - and edx,3 - jz loop_label - mov ecx,edx - rep stosb - jmp loop_label - - - - - - - notrunlength: - cmp al,0FFh ; is it a long run? - jne short notlong ; if not use the code as the size - - xor ecx,ecx - xor eax,eax - mov cx,[esi] ; if so, get the size - lea esi,[esi+2] - - notlong: - mov ax,[esi] ;get the real index - add eax,[a1stdest] ;add in the 1st index - lea ebx,[esi+2] ;save the source offset - cmp ecx,[maxlen] ;compare for overrun - mov esi,eax ;use eax as new source - jbe short runok ; if not, its ok - - mov ecx,[maxlen] ; if so, max it out so it dosen't overrun - - runok: - test ecx,0ffe0h - jnz dont_use_movsb - rep movsb - jmp loop_label - - - - - dont_use_movsb: - lea edx,[edi+0fffffffch] - cmp esi,edx - ja use_movsb - - test edi,3 - jz aligned2 - - mov eax,[esi] - mov [edi],eax - mov edx,edi - and edi,0fffffffch - lea edi,[edi+4] - and edx,3 - dec dl - xor dl,3 - sub ecx,edx - add esi,edx - - aligned2: - mov edx,ecx - shr ecx,2 - and edx,3 - rep movsd - mov ecx,edx - use_movsb: - rep movsb - jmp loop_label - - - - - label_exit: - mov eax,edi - mov ebx,[dest] - sub eax,ebx - - //ret - + confined = true; } + + return confined; } -#endif - - - - - - - - - - - - /* ;*************************************************************************** @@ -3486,47 +2047,11 @@ extern "C" long __cdecl Buffer_To_Page(int x, int y, int w, int h, void *buffer, 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) +extern "C" int __cdecl Buffer_Get_Pixel(void * this_object, int x, int y) { - __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 - + GraphicViewPortClass& vp = *((GraphicViewPortClass *)this_object); + if (x < (unsigned)vp.Get_Width() && y < (unsigned)vp.Get_Height()) { + return *((uint8_t*)(vp.Get_Offset()) + x + y * vp.Get_Full_Pitch()); } } diff --git a/code/REDALERT/WIN32LIB/IRANDOM.CPP b/code/REDALERT/WIN32LIB/IRANDOM.CPP index 03b0bd0..805b550 100644 --- a/code/REDALERT/WIN32LIB/IRANDOM.CPP +++ b/code/REDALERT/WIN32LIB/IRANDOM.CPP @@ -32,6 +32,7 @@ #include #include #include "misc.h" +#include @@ -50,6 +51,7 @@ extern "C" unsigned long RandNumb = 0x12349876; int IRandom(int minval, int maxval) { +#if 0 // jmarshall - not used. int num,mask; // Keep minval and maxval straight. @@ -63,12 +65,17 @@ int IRandom(int minval, int maxval) while( (num = (rand() & mask) + minval) > maxval ) ; return(num); +#else + assert(!"Random function not implmented!"); + return 0; +#endif } unsigned char Random(void) { +#if 0 // jmarshall - not used. __asm { lea esi, [RandNumb] //; get offset in segment of RandNumb xor eax,eax @@ -84,22 +91,29 @@ unsigned char Random(void) mov al,[esi] //; reload byte 1 of RandNumb xor al,[esi+1] //; xor with byte 2 of RandNumb } +#else + assert(!"Random function not implmented!"); + return 0; +#endif } int Get_Random_Mask(int maxval) { - __asm { - - bsr ecx,[maxval] // ; put bit position of highest bit in ecx - mov eax, 1 // ; set one bit on in eax - jz invalid // ; if BSR shows maxval==0, return eax=1 - inc ecx // ; get one bit higher than count showed - shl eax,cl // ; move our EAX bit into position - dec eax // ; dec it to create the mask. -invalid: - } +#if 0 // jmarshall - not used. + bool v1; // zf + DWORD v2; // ecx + int result; // eax + + v1 = !_BitScanReverse((DWORD*)&v2, maxval); + result = 1; + if (!v1) + result = (1 << (v2 + 1)) - 1; + return result; +#else + return 0; +#endif } diff --git a/code/TIBERIANDAWN/JSHELL.H b/code/TIBERIANDAWN/JSHELL.H index 09f0126..b4d98c4 100644 --- a/code/TIBERIANDAWN/JSHELL.H +++ b/code/TIBERIANDAWN/JSHELL.H @@ -126,10 +126,10 @@ void __cdecl Set_Bit(void * array, int bit, int value); int __cdecl Get_Bit(void const * array, int bit); //#pragma aux First_True_Bit parm [esi] -int __cdecl First_True_Bit(void const * array); +int __cdecl First_True_Bit(void const * array, int size); //#pragma aux First_False_Bit parm [esi] -int __cdecl First_False_Bit(void const * array); +int __cdecl First_False_Bit(void const * array, int size); //#pragma aux Bound parm [eax] [ebx] [ecx] int __cdecl Bound(int original, int min, int max); diff --git a/code/TIBERIANDAWN/REAL.H b/code/TIBERIANDAWN/REAL.H index 70dfda0..39265bf 100644 --- a/code/TIBERIANDAWN/REAL.H +++ b/code/TIBERIANDAWN/REAL.H @@ -833,31 +833,8 @@ extern int Load_Interpolated_Palettes(char const *filename, BOOL add=FALSE); * HISTORY: * * 05/27/1994 JLB : Created. * *=============================================================================================*/ -int Distance_Coord(COORDINATE coord1, COORDINATE coord2); -#pragma aux Distance_Coord parm [eax] [ebx] \ - modify [edx ebx] \ - value [eax] = \ - "mov dx,ax" \ - "sub dx,bx" \ - "jg okx" \ - "neg dx" \ - "okx:" \ - "shr eax,16" \ - "shr ebx,16" \ - "sub ax,bx" \ - "jg oky" \ - "neg ax" \ - "oky:" \ - "cmp ax,dx" \ - "jg ok" \ - "xchg ax,dx" \ - "ok:" \ - "shr dx,1" \ - "add ax,dx" - inline int Distance(COORDINATE coord1, COORDINATE coord2) { -#ifdef NEVER int diff1, diff2; diff1 = Coord_Y(coord1) - Coord_Y(coord2); @@ -868,9 +845,6 @@ inline int Distance(COORDINATE coord1, COORDINATE coord2) return(diff1 + (diff2>>1)); } return(diff2 + (diff1>>1)); -#else - return(Distance_Coord(coord1, coord2)); -#endif } diff --git a/code/TIBERIANDAWN/VECTOR.H b/code/TIBERIANDAWN/VECTOR.H index 830f8b6..9268299 100644 --- a/code/TIBERIANDAWN/VECTOR.H +++ b/code/TIBERIANDAWN/VECTOR.H @@ -372,7 +372,7 @@ class BooleanVectorClass int First_False(void) const { if (LastIndex != -1) Fixup(-1); - int retval = First_False_Bit(&BitArray[0]); + int retval = First_False_Bit(&BitArray[0], BitArray.Length()); if (retval < BitCount) return(retval); /* @@ -386,7 +386,7 @@ class BooleanVectorClass int First_True(void) const { if (LastIndex != -1) Fixup(-1); - int retval = First_True_Bit(&BitArray[0]); + int retval = First_True_Bit(&BitArray[0], BitArray.Length()); if (retval < BitCount) return(retval); /*