CnC_Remastered_Collection

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

JSHELL.CPP (30188B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/JSHELL.CPP 2     3/13/97 2:05p Steve_tall $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : JSHELL.CPP                                                   *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : April 2, 1994                                                *
     28  *                                                                                             *
     29  *                  Last Update : May 11, 1995 [JLB]                                           *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   Build_Translucent_Table -- Creates a translucent control table.                           *
     34  *   Conquer_Build_Translucent_Table -- Builds fading table for shadow colors only.            *
     35  *   Fatal -- General purpose fatal error handler.                                             *
     36  *   Load_Alloc_Data -- Allocates a buffer and loads the file into it.                         *
     37  *   Load_Uncompress -- Loads and uncompresses data to a buffer.                               *
     38  *   Set_Window -- Sets the window dimensions to that specified.                               *
     39  *   Small_Icon -- Create a small icon from a big one.                                         *
     40  *   Translucent_Table_Size -- Determines the size of a translucent table.                     *
     41  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     42 
     43 #include	"function.h"
     44 #include	"wwfile.h"
     45 
     46 
     47 /***********************************************************************************************
     48  * Small_Icon -- Create a small icon from a big one.                                           *
     49  *                                                                                             *
     50  *    This routine will extract the specified icon from the icon data file and convert that    *
     51  *    icon into a small (3x3) representation. Typical use of this mini-icon is for the radar   *
     52  *    map.                                                                                     *
     53  *                                                                                             *
     54  * INPUT:   iconptr  -- Pointer to the icon data file.                                         *
     55  *                                                                                             *
     56  *          iconnum  -- The embedded icon number to convert into a small image.                *
     57  *                                                                                             *
     58  * OUTPUT:  Returns with a pointer to the small icon imagery. This is exactly 9 bytes long.    *
     59  *                                                                                             *
     60  * WARNINGS:   none                                                                            *
     61  *                                                                                             *
     62  * HISTORY:                                                                                    *
     63  *   05/11/1995 JLB : Created.                                                                 *
     64  *=============================================================================================*/
     65 void * Small_Icon(void const * iconptr, int iconnum)
     66 {
     67 	static unsigned char _icon[9];
     68 	IControl_Type const * iptr = (IControl_Type const *)iconptr;
     69 	unsigned char * data;
     70 
     71 	if (iconptr) {
     72 		iconnum = ((char *)((char *)iptr + iptr->Map))[iconnum];
     73 		data = &((unsigned char *)((unsigned char *)iptr + iptr->Icons))[iconnum*(24*24)];
     74 //		data = &iptr->Icons[iconnum*(24*24)];
     75 
     76 		for (int index = 0; index < 9; index++) {
     77 			int _offsets[9] = {
     78 				4+4*24,
     79 				12+4*24,
     80 				20+4*24,
     81 				4+12*24,
     82 				12+12*24,
     83 				20+12*24,
     84 				4+20*24,
     85 				12+20*24,
     86 				20+20*24
     87 			};
     88 			_icon[index] = data[_offsets[index]];
     89 		}
     90 	}
     91 
     92 	return(_icon);
     93 }
     94 
     95 
     96 /***********************************************************************************************
     97  * Set_Window -- Sets the window dimensions to that specified.                                 *
     98  *                                                                                             *
     99  *    Use this routine to set the windows dimensions to the coordinates and dimensions         *
    100  *    specified.                                                                               *
    101  *                                                                                             *
    102  * INPUT:   x     -- Window X pixel position.                                                  *
    103  *                                                                                             *
    104  *          y     -- Window Y pixel position.                                                  *
    105  *                                                                                             *
    106  *          w     -- Window width in pixels.                                                   *
    107  *                                                                                             *
    108  *          h     -- Window height in pixels.                                                  *
    109  *                                                                                             *
    110  * OUTPUT:  none                                                                               *
    111  *                                                                                             *
    112  * WARNINGS:   The X and width values are truncated to an even 8 pixel boundary. This is       *
    113  *             the same as stripping off the lower 3 bits.                                     *
    114  *                                                                                             *
    115  * HISTORY:                                                                                    *
    116  *   01/15/1995 JLB : Created.                                                                 *
    117  *=============================================================================================*/
    118 void Set_Window(int window, int x, int y, int w, int h)
    119 {
    120 	WindowList[window][WINDOWWIDTH] = w;
    121 	WindowList[window][WINDOWHEIGHT] = h;
    122 	WindowList[window][WINDOWX] = x;
    123 	WindowList[window][WINDOWY] = y;
    124 }
    125 
    126 
    127 /***********************************************************************************************
    128  * Fatal -- General purpose fatal error handler.                                               *
    129  *                                                                                             *
    130  *    This is a very simple general purpose fatal error handler. It goes directly to text      *
    131  *    mode, prints the error, and then aborts with a failure code.                             *
    132  *                                                                                             *
    133  * INPUT:   message  -- The text message to display.                                           *
    134  *                                                                                             *
    135  *          ...      -- Any optional parameters that are used in formatting the message.       *
    136  *                                                                                             *
    137  * OUTPUT:  none                                                                               *
    138  *                                                                                             *
    139  * WARNINGS:   This routine never returns. The game exits immediately.                         *
    140  *                                                                                             *
    141  * HISTORY:                                                                                    *
    142  *   10/17/1994 JLB : Created.                                                                 *
    143  *=============================================================================================*/
    144 void Fatal(char const * message, ...)
    145 {
    146 	va_list	va;
    147 
    148 	va_start(va, message);
    149 	Prog_End(message, true);
    150 	vfprintf(stderr, message, va);
    151 	Mono_Printf(message);
    152 	if (!RunningAsDLL) {	//PG
    153 		Emergency_Exit(EXIT_FAILURE);
    154 	}
    155 }
    156 
    157 
    158 #ifdef NEVER
    159 void File_Fatal(char const * message)
    160 {
    161 	//Prog_End();
    162 	perror(message);
    163 	Emergency_Exit(EXIT_FAILURE);
    164 }
    165 #endif
    166 
    167 
    168 
    169 /***********************************************************************************************
    170  * Load_Uncompress -- Loads and uncompresses data to a buffer.                                 *
    171  *                                                                                             *
    172  *    This is the C++ counterpart to the Load_Uncompress function. It will load the file       *
    173  *    specified into the graphic buffer indicated and uncompress it.                           *
    174  *                                                                                             *
    175  * INPUT:   file     -- The file to load and uncompress.                                       *
    176  *                                                                                             *
    177  *          uncomp_buff -- The graphic buffer that initial loading will use.                   *
    178  *                                                                                             *
    179  *          dest_buff   -- The buffer that will hold the uncompressed data.                    *
    180  *                                                                                             *
    181  *          reserved_data  -- This is an optional pointer to a buffer that will hold any       *
    182  *                            reserved data the compressed file may contain. This is           *
    183  *                            typically a palette.                                             *
    184  *                                                                                             *
    185  * OUTPUT:  Returns with the size of the uncompressed data in the destination buffer.          *
    186  *                                                                                             *
    187  * WARNINGS:   none                                                                            *
    188  *                                                                                             *
    189  * HISTORY:                                                                                    *
    190  *   10/17/1994 JLB : Created.                                                                 *
    191  *=============================================================================================*/
    192 long Load_Uncompress(FileClass &file, BuffType &uncomp_buff, BuffType &dest_buff, void * reserved_data)
    193 {
    194 	unsigned short	size;
    195 	void	* sptr = uncomp_buff.Get_Buffer();
    196 	void	* dptr = dest_buff.Get_Buffer();
    197 	int	opened = false;
    198 	CompHeaderType	header;
    199 
    200 	/*
    201 	**	The file must be opened in order to be read from. If the file
    202 	**	isn't opened, then open it. Record this fact so that it can be
    203 	**	restored to its closed state at the end.
    204 	*/
    205 	if (!file.Is_Open()) {
    206 		if (!file.Open()) {
    207 			return(0);
    208 		}
    209 		opened = true;
    210 	}
    211 
    212 	/*
    213 	**	Read in the size of the file (supposedly).
    214 	*/
    215 	file.Read(&size, sizeof(size));
    216 
    217 	/*
    218 	**	Read in the header block. This block contains the compression type
    219 	**	and skip data (among other things).
    220 	*/
    221 	file.Read(&header, sizeof(header));
    222 	size -= sizeof(header);
    223 
    224 	/*
    225 	**	If there are skip bytes then they must be processed. Either read
    226 	**	them into the buffer provided or skip past them. No check is made
    227 	**	to ensure that the reserved data buffer is big enough (watch out!).
    228 	*/
    229 	if (header.Skip) {
    230 		size -= header.Skip;
    231 		if (reserved_data) {
    232 			file.Read(reserved_data, header.Skip);
    233 		} else {
    234 			file.Seek(header.Skip, SEEK_CUR);
    235 		}
    236 		header.Skip = 0;
    237 	}
    238 
    239 	/*
    240 	**	Determine where is the proper place to load the data. If both buffers
    241 	**	specified are identical, then the data should be loaded at the end of
    242 	**	the buffer and decompressed at the beginning.
    243 	*/
    244 	if (uncomp_buff.Get_Buffer() == dest_buff.Get_Buffer()) {
    245 		sptr = (char *)sptr + uncomp_buff.Get_Size()-(size+sizeof(header));
    246 	}
    247 
    248 	/*
    249 	**	Read in the bulk of the data.
    250 	*/
    251 	Mem_Copy(&header, sptr, sizeof(header));
    252 	file.Read((char *)sptr + sizeof(header), size);
    253 
    254 	/*
    255 	**	Decompress the data.
    256 	*/
    257 	size = (unsigned int) Uncompress_Data(sptr, dptr);
    258 
    259 	/*
    260 	**	Close the file if necessary.
    261 	*/
    262 	if (opened) {
    263 		file.Close();
    264 	}
    265 	return((long)size);
    266 }
    267 
    268 
    269 int Load_Picture(char const * filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char * palette, PicturePlaneType )
    270 {
    271 	return(Load_Uncompress(CCFileClass(filename), scratchbuf, destbuf,  palette ) / 8000);
    272 }
    273 
    274 
    275 /***********************************************************************************************
    276  * Load_Alloc_Data -- Allocates a buffer and loads the file into it.                           *
    277  *                                                                                             *
    278  *    This is the C++ replacement for the Load_Alloc_Data function. It will allocate the       *
    279  *    memory big enough to hold the file and then read the file into it.                       *
    280  *                                                                                             *
    281  * INPUT:   file  -- The file to read.                                                         *
    282  *                                                                                             *
    283  *          mem   -- The memory system to use for allocation.                                  *
    284  *                                                                                             *
    285  * OUTPUT:  Returns with a pointer to the allocated and filled memory block.                   *
    286  *                                                                                             *
    287  * WARNINGS:   none                                                                            *
    288  *                                                                                             *
    289  * HISTORY:                                                                                    *
    290  *   10/17/1994 JLB : Created.                                                                 *
    291  *=============================================================================================*/
    292 void * Load_Alloc_Data(FileClass &file)
    293 {
    294 	void * ptr = 0;
    295 	long size = file.Size();
    296 
    297 	ptr = new char [size];
    298 	if (ptr) {
    299 		file.Read(ptr, size);
    300 	}
    301 	return(ptr);
    302 }
    303 
    304 
    305 /***********************************************************************************************
    306  * Translucent_Table_Size -- Determines the size of a translucent table.                       *
    307  *                                                                                             *
    308  *    Use this routine to determine how big the translucent table needs                        *
    309  *    to be given the specified number of colors. This value is typically                      *
    310  *    used when allocating the buffer for the translucent table.                               *
    311  *                                                                                             *
    312  * INPUT:   count -- The number of colors that are translucent.                                *
    313  *                                                                                             *
    314  * OUTPUT:  Returns the size of the translucent table.                                         *
    315  *                                                                                             *
    316  * WARNINGS:   none                                                                            *
    317  *                                                                                             *
    318  * HISTORY:                                                                                    *
    319  *   04/02/1994 JLB : Created.                                                                 *
    320  *=============================================================================================*/
    321 long Translucent_Table_Size(int count)
    322 {
    323 	return(256L + (256L * count));
    324 }
    325 
    326 
    327 /***********************************************************************************************
    328  * Build_Translucent_Table -- Creates a translucent control table.                             *
    329  *                                                                                             *
    330  *    The table created by this routine is used by Draw_Shape (GHOST) to                       *
    331  *    achieve a translucent affect. The original color of the shape will                       *
    332  *    show through. This differs from the fading effect, since that                            *
    333  *    affect only alters the background color toward a single destination                      *
    334  *    color.                                                                                   *
    335  *                                                                                             *
    336  * INPUT:   palette  -- Pointer to the control palette.                                        *
    337  *                                                                                             *
    338  *          control  -- Pointer to array of structures that control how                        *
    339  *                      the translucent table will be built.                                   *
    340  *                                                                                             *
    341  *          count    -- The number of entries in the control array.                            *
    342  *                                                                                             *
    343  *          buffer   -- Pointer to buffer to place the translucent table.                      *
    344  *                      If NULL is passed in, then the buffer will be                          *
    345  *                      allocated.                                                             *
    346  *                                                                                             *
    347  * OUTPUT:  Returns with pointer to the translucent table.                                     *
    348  *                                                                                             *
    349  * WARNINGS:   This routine is exceedingly slow. Use sparingly.                                *
    350  *                                                                                             *
    351  * HISTORY:                                                                                    *
    352  *   04/02/1994 JLB : Created.                                                                 *
    353  *=============================================================================================*/
    354 void * Build_Translucent_Table(PaletteClass const & palette, TLucentType const * control, int count, void * buffer)
    355 {
    356 	unsigned char	const *table;		// Remap table pointer.
    357 	int			index;		// Working color index.
    358 
    359 	if (count && control/* && palette*/) {		// palette can't be NULL... ST - 5/9/2019
    360 		if (!buffer) {
    361 			buffer = new char [Translucent_Table_Size(count)];
    362 		}
    363 
    364 		if (buffer) {
    365 			memset(buffer, -1, 256);
    366 			table = (unsigned char*)buffer + 256;
    367 
    368 			/*
    369 			**	Build the individual remap tables for each translucent color.
    370 			*/
    371 			for (index = 0; index < count; index++) {
    372 				((unsigned char*)buffer)[control[index].SourceColor] = index;
    373 				Build_Fading_Table(palette.Get_Data(), (void*)table, control[index].DestColor, control[index].Fading);
    374 				table = (unsigned char*)table + 256;
    375 			}
    376 		}
    377 	}
    378 	return(buffer);
    379 }
    380 
    381 
    382 /***********************************************************************************************
    383  * Conquer_Build_Translucent_Table -- Builds fading table for shadow colors only.              *
    384  *                                                                                             *
    385  *    This routine will build a translucent (fading) table to remap colors into the shadow     *
    386  *    color region of the palette. Shadow colors are not affected by this translucent table.   *
    387  *    This means that a shape can be overlapped any number of times and the imagery will       *
    388  *    remain deterministic (and constant).                                                     *
    389  *                                                                                             *
    390  * INPUT:   palette  -- Pointer to the palette to base the translucent process on.             *
    391  *                                                                                             *
    392  *          control  -- Pointer to special control structure that specifies the                *
    393  *                      target color, and percentage of fade.                                  *
    394  *                                                                                             *
    395  *          count    -- The number of colors to be remapped (entries in the control array).    *
    396  *                                                                                             *
    397  *          buffer   -- Pointer to the staging buffer that will hold the translucent table     *
    398  *                      data. If this parameter is NULL, then an appropriate sized table       *
    399  *                      will be allocated.                                                     *
    400  *                                                                                             *
    401  * OUTPUT:  Returns with a pointer to the translucent table data.                              *
    402  *                                                                                             *
    403  * WARNINGS:   none                                                                            *
    404  *                                                                                             *
    405  * HISTORY:                                                                                    *
    406  *   06/27/1994 JLB : Created.                                                                 *
    407  *=============================================================================================*/
    408 void * Conquer_Build_Translucent_Table(PaletteClass const & palette, TLucentType const * control, int count, void * buffer)
    409 {
    410 	unsigned char	const *table;		// Remap table pointer.
    411 
    412 	if (count && control) {
    413 		if (!buffer) {
    414 			buffer = new char [Translucent_Table_Size(count)];
    415 		}
    416 
    417 		if (buffer) {
    418 			memset(buffer, -1, 256);
    419 			table = (unsigned char*)buffer + 256;
    420 
    421 			/*
    422 			**	Build the individual remap tables for each translucent color.
    423 			*/
    424 			for (int index = 0; index < count; index++) {
    425 				((unsigned char*)buffer)[control[index].SourceColor] = index;
    426 				Conquer_Build_Fading_Table(palette, (void*)table, control[index].DestColor, control[index].Fading);
    427 				table = (unsigned char*)table + 256;
    428 			}
    429 		}
    430 	}
    431 	return(buffer);
    432 }
    433 
    434 
    435 void * Make_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac)
    436 {
    437 	if (dest) {
    438 		unsigned char * ptr = (unsigned char *)dest;
    439 
    440 		/*
    441 		**	Find an appropriate remap color index for every color in the palette.
    442 		**	There are certain exceptions to this, but they are trapped within the
    443 		**	loop.
    444 		*/
    445 		for (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {
    446 
    447 			/*
    448 			**	Find the color that, ideally, the working color should be remapped
    449 			**	to in the special remap range.
    450 			*/
    451 			RGBClass trycolor = palette[index];
    452 			trycolor.Adjust(frac, palette[color]);			// Try to match this color.
    453 
    454 			/*
    455 			**	Search through the remap range to find the color that should be remapped
    456 			**	to. This special range is used for shadows or other effects that are
    457 			**	not compounded if additively applied.
    458 			*/
    459 			*ptr++ = palette.Closest_Color(trycolor);
    460 		}
    461 	}
    462 	return(dest);
    463 }
    464 
    465 
    466 void * Conquer_Build_Fading_Table(PaletteClass const & palette, void * dest, int color, int frac)
    467 {
    468 	if (dest) {
    469 		unsigned char * ptr = (unsigned char *)dest;
    470 //		HSVClass desthsv = palette[color];
    471 
    472 		/*
    473 		**	Find an appropriate remap color index for every color in the palette.
    474 		**	There are certain exceptions to this, but they are trapped within the
    475 		**	loop.
    476 		*/
    477 		for (int index = 0; index < PaletteClass::COLOR_COUNT; index++) {
    478 
    479 			/*
    480 			**	If this color should not be remapped, then it will be stored as a remap
    481 			**	to itself. This is effectively no remap.
    482 			*/
    483 			if (index > PaletteClass::COLOR_COUNT-16 || index == 0) {
    484 				*ptr++ = index;
    485 			} else {
    486 
    487 				/*
    488 				**	Find the color that, ideally, the working color should be remapped
    489 				**	to in the special remap range.
    490 				*/
    491 				RGBClass trycolor = palette[index];
    492 				trycolor.Adjust(frac, palette[color]);			// Try to match this color.
    493 
    494 				/*
    495 				**	Search through the remap range to find the color that should be remapped
    496 				**	to. This special range is used for shadows or other effects that are
    497 				**	not compounded if additively applied.
    498 				*/
    499 				int best = -1;
    500 				int bvalue = 0;
    501 				for (int id = PaletteClass::COLOR_COUNT-16; id < PaletteClass::COLOR_COUNT-1; id++) {
    502 					int diff = palette[id].Difference(trycolor);
    503 					if (best == -1 || diff < bvalue) {
    504 						best = id;
    505 						bvalue = diff;
    506 					}
    507 				}
    508 				*ptr++ = best;
    509 			}
    510 		}
    511 	}
    512 	return(dest);
    513 }
    514 
    515 
    516 #ifdef OBSOLETE
    517 //int Desired_Facing8(int x1, int y1, int x2, int y2)
    518 DirType xDesired_Facing8(int x1, int y1, int x2, int y2)
    519 {
    520 	int index = 0;				// Facing composite value.
    521 
    522 	/*
    523 	**	Figure the absolute X difference. This determines
    524 	**	if the facing is leftward or not.
    525 	*/
    526 	int xdiff = x2-x1;
    527 	if (xdiff < 0) {
    528 		index |= 0x00C0;
    529 		xdiff = -xdiff;
    530 	}
    531 
    532 	/*
    533 	**	Figure the absolute Y difference. This determines
    534 	**	if the facing is downward or not. This also clarifies
    535 	**	exactly which quadrant the facing lies.
    536 	*/
    537 	int ydiff = y1-y2;
    538 	if (ydiff < 0) {
    539 		index ^= 0x0040;
    540 		ydiff = -ydiff;
    541 	}
    542 
    543 	/*
    544 	**	Determine which of the two direction offsets it bigger. The
    545 	**	offset direction that is bigger (X or Y) will indicate which
    546 	**	orthogonal direction the facing is closer to.
    547 	*/
    548 	unsigned bigger;
    549 	unsigned smaller;
    550 	if (xdiff < ydiff) {
    551 		smaller = xdiff;
    552 		bigger = ydiff;
    553 	} else {
    554 		smaller = ydiff;
    555 		bigger = xdiff;
    556 	}
    557 
    558 	/*
    559 	**	If on the diagonal, then incorporate this into the facing
    560 	**	and then bail. The facing is known.
    561 	*/
    562 	if (((bigger+1)/2) <= smaller) {
    563 		index += 0x0020;
    564 		return(DirType(index));
    565 	}
    566 
    567 	/*
    568 	**	Determine if the facing is closer to the Y axis or
    569 	**	the X axis.
    570 	*/
    571 	int adder = (index & 0x0040);
    572 	if (xdiff == bigger) {
    573 		adder ^= 0x0040;
    574 	}
    575 	index += adder;
    576 
    577 	return(DirType(index));
    578 }
    579 
    580 
    581 //int Desired_Facing256(int srcx, int srcy, int dstx, int dsty)
    582 DirType xDesired_Facing256(int srcx, int srcy, int dstx, int dsty)
    583 {
    584 	int composite=0;		// Facing built from intermediate calculations.
    585 
    586 	/*
    587 	**	Fetch the absolute X difference. This also gives a clue as
    588 	**	to which hemisphere the direction lies.
    589 	*/
    590 	int xdiff = dstx - srcx;
    591 	if (xdiff < 0) {
    592 		composite |= 0x00C0;
    593 		xdiff = -xdiff;
    594 	}
    595 
    596 	/*
    597 	**	Fetch the absolute Y difference. This clarifies the exact
    598 	**	quadrant that the direction lies.
    599 	*/
    600 	int ydiff = srcy - dsty;
    601 	if (ydiff < 0) {
    602 		composite ^= 0x0040;
    603 		ydiff = -ydiff;
    604 	}
    605 
    606 	/*
    607 	**	Bail early if the coordinates are the same. This check also
    608 	**	has the added bonus of ensuring that checking for division
    609 	**	by zero is not needed in the following section.
    610 	*/
    611 	if (xdiff == 0 && ydiff == 0) return(DirType(0xFF));
    612 
    613 	/*
    614 	**	Determine which of the two direction offsets it bigger. The
    615 	**	offset direction that is bigger (X or Y) will indicate which
    616 	**	orthogonal direction the facing is closer to.
    617 	*/
    618 	unsigned bigger;
    619 	unsigned smaller;
    620 	if (xdiff < ydiff) {
    621 		smaller = xdiff;
    622 		bigger = ydiff;
    623 	} else {
    624 		smaller = ydiff;
    625 		bigger = xdiff;
    626 	}
    627 
    628 	/*
    629 	**	Now that the quadrant is known, we need to determine how far
    630 	**	from the orthogonal directions, the facing lies. This value
    631 	**	is calculated as a ratio from 0 (matches orthogonal) to 31
    632 	**	(matches diagonal).
    633 	*/
    634 	int frac = (smaller * 32U) / bigger;
    635 
    636 	/*
    637 	**	Given the quadrant and knowing whether the facing is closer
    638 	**	to the X or Y axis, we must make an adjustment toward the
    639 	**	subsequent quadrant if necessary.
    640 	*/
    641 	int adder = (composite & 0x0040);
    642 	if (xdiff > ydiff) {
    643 		adder ^= 0x0040;
    644 	}
    645 	if (adder) {
    646 		frac = (adder - frac)-1;
    647 	}
    648 
    649 	/*
    650 	**	Integrate the fraction value into the quadrant.
    651 	*/
    652 	composite += frac;
    653 
    654 	/*
    655 	**	Return with the final facing value.
    656 	*/
    657 	return(DirType(composite & 0x00FF));
    658 }
    659 #endif