COORD.CPP (34622B)
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/COORD.CPP 1 3/03/97 10:24a Joe_bostic $ */ 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 : COORD.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : September 10, 1993 * 28 * * 29 * Last Update : July 22, 1996 [JLB] * 30 * * 31 * Support code to handle the coordinate system is located in this module. * 32 * Routines here will be called QUITE frequently during play and must be * 33 * as efficient as possible. * 34 * * 35 *---------------------------------------------------------------------------------------------* 36 * Functions: * 37 * Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number. * 38 * Coord_Cell -- Convert a coordinate into a cell number. * 39 * Coord_Move -- Moves a coordinate an arbitrary direction for an arbitrary distance * 40 * Coord_Scatter -- Determines a random coordinate from an anchor point. * 41 * Coord_Spillage_List -- Calculate a spillage list for the dirty rectangle specified. * 42 * Coord_Spillage_List -- Determines the offset list for cell spillage/occupation. * 43 * Distance -- Determines the cell distance between two cells. * 44 * Distance -- Determines the lepton distance between two coordinates. * 45 * Distance -- Fetch distance between two target values. * 46 * Fixed_To_Cardinal -- Converts a fixed point number into a cardinal number. * 47 * Normal_Move_Point -- Moves point with tilt compensation. * 48 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 49 50 #include "function.h" 51 52 53 /*********************************************************************************************** 54 * Coord_Cell -- Convert a coordinate into a cell number. * 55 * * 56 * This routine will convert the specified coordinate value into a cell number. This is * 57 * useful to determine the map index number into the cell array that corresponds to a * 58 * particular coordinate. * 59 * * 60 * INPUT: coord -- The coordinate to convert into a cell number. * 61 * * 62 * OUTPUT: Returns with the cell number that corresponds to the coordinate specified. * 63 * * 64 * WARNINGS: none * 65 * * 66 * HISTORY: * 67 * 06/17/1996 JLB : Created. * 68 *=============================================================================================*/ 69 CELL Coord_Cell(COORDINATE coord) 70 { 71 CELL_COMPOSITE cell; 72 cell.Cell = 0; 73 cell.Sub.X = ((COORD_COMPOSITE &)coord).Sub.X.Sub.Cell; 74 cell.Sub.Y = ((COORD_COMPOSITE &)coord).Sub.Y.Sub.Cell; 75 return(cell.Cell); 76 // return(XY_Cell(((COORD_COMPOSITE)coord).Sub.X, ((COORD_COMPOSITE)composite).Sub.Y)); 77 } 78 79 80 /*********************************************************************************************** 81 * Distance -- Fetch distance between two target values. * 82 * * 83 * This routine will determine the lepton distance between the two specified target * 84 * values. * 85 * * 86 * INPUT: target1 -- First target value. * 87 * * 88 * target2 -- Second target value. * 89 * * 90 * OUTPUT: Returns with the lepton distance between the two target values. * 91 * * 92 * WARNINGS: Be sure that the targets are legal before calling this routine. Otherwise, the * 93 * return value is meaningless. * 94 * * 95 * HISTORY: * 96 * 06/17/1996 JLB : Created. * 97 *=============================================================================================*/ 98 int Distance(TARGET target1, TARGET target2) 99 { 100 return(Distance(As_Coord(target1), As_Coord(target2))); 101 } 102 103 104 /*********************************************************************************************** 105 * Distance -- Determines the lepton distance between two coordinates. * 106 * * 107 * This routine is used to determine the distance between two coordinates. It uses the * 108 * Dragon Strike method of distance determination and thus it is very fast. * 109 * * 110 * INPUT: coord1 -- First coordinate. * 111 * * 112 * coord2 -- Second coordinate. * 113 * * 114 * OUTPUT: Returns the lepton distance between the two coordinates. * 115 * * 116 * WARNINGS: none * 117 * * 118 * HISTORY: * 119 * 05/27/1994 JLB : Created. * 120 *=============================================================================================*/ 121 int Distance(COORDINATE coord1, COORDINATE coord2) 122 { 123 int diff1, diff2; 124 125 diff1 = Coord_Y(coord1) - Coord_Y(coord2); 126 if (diff1 < 0) diff1 = -diff1; 127 diff2 = Coord_X(coord1) - Coord_X(coord2); 128 if (diff2 < 0) diff2 = -diff2; 129 if (diff1 > diff2) { 130 return(diff1 + ((unsigned)diff2 / 2)); 131 } 132 return(diff2 + ((unsigned)diff1 / 2)); 133 } 134 135 136 /*********************************************************************************************** 137 * Coord_Spillage_List -- Determines the offset list for cell spillage/occupation. * 138 * * 139 * This routine will take an arbitrary position and object size and return with a list of * 140 * cell offsets from the current cell for all cells that are overlapped by the object. The * 141 * first cell offset is always zero, so to just get the adjacent spill cell list, add one * 142 * to the return pointer. * 143 * * 144 * INPUT: coord -- The coordinate to examine. * 145 * * 146 * maxsize -- The maximum width/height of the object (pixels). * 147 * * 148 * OUTPUT: Returns with a pointer to a spillage list. * 149 * * 150 * WARNINGS: The algorithm is limited to working with a maxsize of 48 or less. Larger values * 151 * will generate an incomplete overlap list. * 152 * * 153 * HISTORY: * 154 * 11/06/1993 JLB : Created. * 155 * 03/25/1994 JLB : Added width optimization. * 156 * 04/29/1994 JLB : Converted to C. * 157 * 06/03/1994 JLB : Converted to general purpose spillage functionality. * 158 * 01/07/1995 JLB : Manually calculates spillage list for large objects. * 159 *=============================================================================================*/ 160 short const * Coord_Spillage_List(COORDINATE coord, int maxsize) 161 { 162 static short const _MoveSpillage[(int)FACING_COUNT+1][5] = { 163 {0, -MAP_CELL_W, REFRESH_EOL, 0, 0}, // N 164 {0, -MAP_CELL_W, 1, -(MAP_CELL_W-1), REFRESH_EOL}, // NE 165 {0, 1, REFRESH_EOL, 0, 0}, // E 166 {0, 1, MAP_CELL_W, MAP_CELL_W+1, REFRESH_EOL}, // SE 167 {0, MAP_CELL_W, REFRESH_EOL, 0, 0}, // S 168 {0, -1, MAP_CELL_W, MAP_CELL_W-1, REFRESH_EOL}, // SW 169 {0, -1, REFRESH_EOL, 0, 0}, // W 170 {0, -1, -MAP_CELL_W, -(MAP_CELL_W+1), REFRESH_EOL}, // NW 171 {0, REFRESH_EOL, 0, 0, 0} // non-moving. 172 }; 173 static short _manual[10]; 174 //; 00 = on axis 175 //; 01 = below axis 176 //; 10 = above axis 177 //; 11 = undefined 178 static signed char const _SpillTable[16] = {8,6,2,-1,0,7,1,-1,4,5,3,-1,-1,-1,-1,-1}; 179 int index=0; 180 int x,y; 181 182 /* 183 ** For mondo-enourmo-gigundo objects, use a prebuilt mammoth table 184 ** that covers a 5x5 square region. 185 */ 186 if (maxsize > ICON_PIXEL_W * 2) { 187 static short const _gigundo[] = { 188 -((2*MAP_CELL_W)-2),-((2*MAP_CELL_W)-1),-((2*MAP_CELL_W)),-((2*MAP_CELL_W)+1),-((2*MAP_CELL_W)+2), 189 -((1*MAP_CELL_W)-2),-((1*MAP_CELL_W)-1),-((1*MAP_CELL_W)),-((1*MAP_CELL_W)+1),-((1*MAP_CELL_W)+2), 190 -((0*MAP_CELL_W)-2),-((0*MAP_CELL_W)-1),-((0*MAP_CELL_W)),-((0*MAP_CELL_W)+1),-((0*MAP_CELL_W)+2), 191 ((1*MAP_CELL_W)-2),((1*MAP_CELL_W)-1),((1*MAP_CELL_W)),((1*MAP_CELL_W)+1),((1*MAP_CELL_W)+2), 192 +((2*MAP_CELL_W)-2),+((2*MAP_CELL_W)-1),+((2*MAP_CELL_W)),+((2*MAP_CELL_W)+1),+((2*MAP_CELL_W)+2), 193 REFRESH_EOL 194 }; 195 return(&_gigundo[0]); 196 } 197 198 /* 199 ** For very large objects, build the overlap list by hand. This is time consuming, but 200 ** not nearly as time consuming as drawing even a single cell unnecessarily. 201 */ 202 if (maxsize > ICON_PIXEL_W) { 203 maxsize = min(maxsize, (ICON_PIXEL_W*2))/2; 204 205 x = (ICON_PIXEL_W * Coord_XLepton(coord)) / ICON_LEPTON_W; 206 y = (ICON_PIXEL_H * Coord_YLepton(coord)) / ICON_LEPTON_H; 207 int left = x-maxsize; 208 int right = x+maxsize; 209 int top = y-maxsize; 210 int bottom = y+maxsize; 211 212 _manual[index++] = 0; 213 if (left < 0) _manual[index++] = -1; 214 if (right >= ICON_PIXEL_W) _manual[index++] = 1; 215 if (top < 0) _manual[index++] = -MAP_CELL_W; 216 if (bottom >= ICON_PIXEL_H) _manual[index++] = MAP_CELL_W; 217 if (left < 0 && top < 0) _manual[index++] = -(MAP_CELL_W+1); 218 if (right >= ICON_PIXEL_W && bottom >= ICON_PIXEL_H) _manual[index++] = MAP_CELL_W+1; 219 if (left < 0 && bottom >= ICON_PIXEL_H) _manual[index++] = MAP_CELL_W-1; 220 if (right >= ICON_PIXEL_H && top < 0) _manual[index++] = -(MAP_CELL_W-1); 221 _manual[index] = REFRESH_EOL; 222 return(&_manual[0]); 223 } 224 225 /* 226 ** Determine the number of leptons "leeway" allowed this unit. 227 */ 228 int posval = Pixel2Lepton[(ICON_PIXEL_W-maxsize)/2]; 229 230 x = Coord_XLepton(coord) - 0x0080; 231 y = Coord_YLepton(coord) - 0x0080; 232 if (y > posval) index |= 0x08; // Spilling South. 233 if (y < -posval) index |= 0x04; // Spilling North. 234 if (x > posval) index |= 0x02; // Spilling East. 235 if (x < -posval) index |= 0x01; // Spilling West. 236 237 return(&_MoveSpillage[_SpillTable[index]][0]); 238 } 239 240 241 /*********************************************************************************************** 242 * Coord_Spillage_List -- Calculate a spillage list for the dirty rectangle specified. * 243 * * 244 * Given a center coordinate and a dirty rectangle, calcuate a cell offset list for * 245 * determining such things as overlap and redraw logic. Optionally, the center cell * 246 * location will not be part of the list. * 247 * * 248 * INPUT: coord -- The center coordinate that the dirty rectangle is based off of. * 249 * * 250 * rect -- Reference to the dirty rectangle. * 251 * * 252 * nocenter -- If true, then the center cell offset will not be part of the spillage * 253 * list returned. This is handy when the center cell is known to be * 254 * processed by some other method and it can be safely and efficiently * 255 * ignored by the list generated. * 256 * * 257 * OUTPUT: Returns with a pointer to the spillage list that corresponds to the data * 258 * specified. This is a pointer to a static buffer and as such it will only be valid * 259 * until the next time that this routine is called. * 260 * * 261 * WARNINGS: none * 262 * * 263 * HISTORY: * 264 * 07/22/1996 JLB : Created. * 265 *=============================================================================================*/ 266 short const * Coord_Spillage_List(COORDINATE coord, Rect const & rect, bool nocenter) 267 { 268 if (!rect.Is_Valid()) { 269 static short const _list[] = {REFRESH_EOL}; 270 return(_list); 271 } 272 273 CELL coordcell = Coord_Cell(coord); 274 LEPTON x = Coord_X(coord); 275 LEPTON y = Coord_Y(coord); 276 277 /* 278 ** Add the rectangle values to the coordinate in order to normalize the start and end 279 ** corners of the rectangle. The values are now absolute to the real game world rather 280 ** than relative to the coordinate. 281 */ 282 LEPTON_COMPOSITE startx; 283 LEPTON_COMPOSITE starty; 284 LEPTON_COMPOSITE endx; 285 LEPTON_COMPOSITE endy; 286 startx.Raw = (int)x + (short)Pixel_To_Lepton(rect.X); 287 starty.Raw = (int)y + (short)Pixel_To_Lepton(rect.Y); 288 endx.Raw = startx.Raw + Pixel_To_Lepton(rect.Width-1); 289 endy.Raw = starty.Raw + Pixel_To_Lepton(rect.Height-1); 290 291 /* 292 ** Determine the upper left and lower right cell indexes. This is a simple conversion from 293 ** their lepton counterpart. These cells values are used to form the bounding box for the 294 ** map offset list. 295 */ 296 int cellx = startx.Sub.Cell; 297 int cellx2 = endx.Sub.Cell; 298 int celly = starty.Sub.Cell; 299 int celly2 = endy.Sub.Cell; 300 301 /* 302 ** Generate the spillage list by counting off the rows and colums of the cells 303 ** that are affected. This is easy since the upper left and lower right corner cells 304 ** are known. 305 */ 306 int count = 0; 307 static short _spillagelist[128]; 308 short * ptr = _spillagelist; 309 for (int yy = celly; yy <= celly2; yy++) { 310 for (int xx = cellx; xx <= cellx2; xx++) { 311 short offset = (XY_Cell(xx, yy) - coordcell); 312 if (!nocenter || offset != 0) { 313 *ptr++ = offset; 314 count++; 315 if (count+2 >= ARRAY_SIZE(_spillagelist)) break; 316 } 317 } 318 if (count+2 >= ARRAY_SIZE(_spillagelist)) break; 319 } 320 321 /* 322 ** Cap the list with the end of list marker and then return a pointer 323 ** to the completed list. 324 */ 325 *ptr = REFRESH_EOL; 326 return(_spillagelist); 327 } 328 329 330 /*********************************************************************************************** 331 * Coord_Move -- Moves a coordinate an arbitrary direction for an arbitrary distance * 332 * * 333 * This function will move a coordinate in a using SIN and COS arithmetic. * 334 * * 335 * INPUT: start -- The starting coordinate. * 336 * * 337 * dir -- The direction to move the coordinate. * 338 * * 339 * distance -- The distance to move the coordinate position (in leptons). * 340 * * 341 * OUTPUT: Returns the new coordinate position. * 342 * * 343 * WARNINGS: This routine uses multiplies -- use with caution. * 344 * * 345 * HISTORY: * 346 * 05/27/1994 JLB : Created. * 347 *=============================================================================================*/ 348 COORDINATE Coord_Move(COORDINATE start, register DirType dir, unsigned short distance) 349 { 350 #ifdef NEVER 351 short x = Coord_X(start); 352 short y = Coord_Y(start); 353 354 Move_Point(x, y, dir, distance); 355 return(XY_Coord(x,y)); 356 #endif 357 358 Move_Point(*(short *)&start, *(((short *)&start)+1), dir, distance); 359 return(start); 360 } 361 362 363 /*********************************************************************************************** 364 * Coord_Scatter -- Determines a random coordinate from an anchor point. * 365 * * 366 * This routine will perform a scatter algorithm on the specified * 367 * anchor point in order to return with another coordinate that is * 368 * randomly nearby the original. Typical use of this would be for * 369 * missile targeting. * 370 * * 371 * INPUT: coord -- This is the anchor coordinate. * 372 * * 373 * distance -- This is the distance in pixels that the scatter * 374 * should fall within. * 375 * * 376 * lock -- bool; Convert the new coordinate into a center * 377 * cell based coordinate? * 378 * * 379 * OUTPUT: Returns with a new coordinate that is nearby the original. * 380 * * 381 * WARNINGS: Maximum pixel scatter distance is 255. * 382 * * 383 * HISTORY: * 384 * 02/01/1992 JLB : Created. * 385 * 05/13/1992 JLB : Only uses Random(). * 386 *=============================================================================================*/ 387 COORDINATE Coord_Scatter(COORDINATE coord, unsigned distance, bool lock) 388 { 389 COORDINATE newcoord; 390 391 newcoord = Coord_Move(coord, Random_Pick(DIR_N, DIR_MAX), distance); 392 393 if (newcoord & HIGH_COORD_MASK) newcoord = coord; 394 395 if (lock) { 396 newcoord = Coord_Snap(newcoord); 397 } 398 399 return(newcoord); 400 } 401 402 403 int __cdecl calcx(signed short param1, short distance) 404 { 405 __asm { 406 407 //#pragma aux calcx parm [ax] [bx] \ 408 409 movzx eax, [param1] 410 mov bx, [distance] 411 imul bx 412 shl ax, 1 413 rcl dx, 1 414 mov al, ah 415 mov ah, dl 416 cwd 417 } 418 } 419 420 421 int __cdecl calcy(signed short param1, short distance) 422 { 423 __asm { 424 425 //#pragma aux calcy parm [ax] [bx] \ 426 427 movzx eax, [param1] 428 mov bx, [distance] 429 imul bx 430 shl ax, 1 431 rcl dx, 1 432 mov al, ah 433 mov ah, dl 434 cwd 435 neg eax 436 } 437 } 438 439 440 #if (0) 441 extern int calcx(signed short, short distance); 442 #pragma aux calcx parm [ax] [bx] \ 443 modify [eax dx] \ 444 value [eax] = \ 445 "imul bx" \ 446 "shl ax,1" \ 447 "rcl dx,1" \ 448 "mov al,ah" \ 449 "mov ah,dl" \ 450 "cwd" \ 451 // "and eax,0FFFFh"; 452 453 extern int calcy(signed short, short distance); 454 #pragma aux calcy parm [ax] [bx] \ 455 modify [eax dx] \ 456 value [eax] = \ 457 "imul bx" \ 458 "shl ax,1" \ 459 "rcl dx,1" \ 460 "mov al,ah" \ 461 "mov ah,dl" \ 462 "cwd" \ 463 "neg eax"; 464 // "and eax,0FFFFh" \ 465 466 #endif 467 468 void Move_Point(short &x, short &y, register DirType dir, unsigned short distance) 469 { 470 static unsigned char const CosTable[256] = { 471 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15, 472 0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d, 473 0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43, 474 0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57, 475 0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67, 476 0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74, 477 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b, 478 0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e, 479 480 0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d, 481 0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76, 482 0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b, 483 0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b, 484 0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49, 485 0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33, 486 0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b, 487 0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03, 488 489 0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb, 490 0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3, 491 0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd, 492 0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9, 493 0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99, 494 0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c, 495 0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85, 496 0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82, 497 498 0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83, 499 0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a, 500 0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95, 501 0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5, 502 0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7, 503 0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd, 504 0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5, 505 0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd, 506 }; 507 508 static unsigned char const SinTable[256] = { 509 0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d, 510 0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76, 511 0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b, 512 0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b, 513 0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49, 514 0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33, 515 0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b, 516 0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03, 517 518 0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb, 519 0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3, 520 0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd, 521 0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9, 522 0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99, 523 0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c, 524 0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85, 525 0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82, 526 527 0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83, 528 0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a, 529 0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95, 530 0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5, 531 0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7, 532 0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd, 533 0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5, 534 0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd, 535 536 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15, 537 0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d, 538 0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43, 539 0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57, 540 0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67, 541 0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74, 542 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b, 543 0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e, 544 }; 545 distance = distance; // Keep LINT quiet. 546 547 #ifdef OBSOLETE 548 /* 549 ** Calculate and add in the X component of the move. 550 */ 551 _AX = CosTable[dir]; 552 asm imul word ptr distance 553 asm shl ax,1 554 asm rcl dx,1 555 asm mov al,ah 556 asm mov ah,dl 557 _DX = _AX; 558 x += _DX; 559 #else 560 // 561 // Have to declare table as unsigned otherwise MSVC complains, but we need to treat the actual values as signed. 562 // 563 static const char *_cos_table = (char*)&CosTable[0]; 564 x += calcx(_cos_table[dir], distance); 565 #endif 566 // asm add [word ptr start],ax 567 568 #ifdef OBSOLETE 569 /* 570 ** Calculate and add in the Y component of the move. 571 */ 572 _AX = SinTable[dir]; 573 asm imul word ptr distance 574 asm shl ax,1 575 asm rcl dx,1 576 asm mov al,ah 577 asm mov ah,dl 578 asm neg ax // Subtraction needed because of inverted sine table. 579 _DX = _AX; 580 y += _DX; 581 #else 582 // 583 // Have to declare table as unsigned otherwise MSVC complains, but we need to treat the actual values as signed. 584 // 585 static const char *_sin_table = (char*)&SinTable[0]; 586 y += calcy(_sin_table[dir], distance); 587 #endif 588 // asm add [word ptr start+2],ax 589 590 } 591 592 593 /*********************************************************************************************** 594 * Normal_Move_Point -- Moves point with tilt compensation. * 595 * * 596 * This routine will move the point in the direction and distance specified but it will * 597 * take into account the tilt of the playing field. Typical use of this routine is to * 598 * determine positioning as it relates to the playfield. Turrets are a good example of * 599 * this. * 600 * * 601 * INPUT: x,y -- References to the coordinates to adjust. * 602 * * 603 * dir -- The direction of the desired movement. * 604 * * 605 * distance -- The distance (in coordinate units) to move the point. * 606 * * 607 * OUTPUT: none * 608 * * 609 * WARNINGS: none * 610 * * 611 * HISTORY: * 612 * 12/19/1995 JLB : Created. * 613 *=============================================================================================*/ 614 // Loss of precision in initializations (8 bits to 7 bits) warning. Hmmm.. can this be fixed? 615 //lint -e569 616 void Normal_Move_Point(short &x, short &y, register DirType dir, unsigned short distance) 617 { 618 static unsigned char const CosTable[256] = { 619 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15, 620 0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d, 621 0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43, 622 0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57, 623 0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67, 624 0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74, 625 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b, 626 0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e, 627 628 0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d, 629 0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76, 630 0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b, 631 0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b, 632 0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49, 633 0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33, 634 0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b, 635 0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03, 636 637 0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb, 638 0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3, 639 0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd, 640 0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9, 641 0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99, 642 0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c, 643 0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85, 644 0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82, 645 646 0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83, 647 0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a, 648 0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95, 649 0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5, 650 0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7, 651 0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd, 652 0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5, 653 0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd, 654 }; 655 656 static unsigned char const SinTable[256] = { 657 0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d,0x7d, 658 0x7c,0x7b,0x7b,0x7a,0x79,0x78,0x77,0x76, 659 0x75,0x74,0x72,0x71,0x70,0x6e,0x6c,0x6b, 660 0x69,0x67,0x66,0x64,0x62,0x60,0x5e,0x5b, 661 0x59,0x57,0x55,0x52,0x50,0x4e,0x4b,0x49, 662 0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33, 663 0x30,0x2d,0x2a,0x27,0x24,0x21,0x1e,0x1b, 664 0x18,0x15,0x12,0x0f,0x0c,0x09,0x06,0x03, 665 666 0x00,0xfd,0xfa,0xf7,0xf4,0xf1,0xee,0xeb, 667 0xe8,0xe5,0xe2,0xdf,0xdc,0xd9,0xd6,0xd3, 668 0xd0,0xcd,0xca,0xc7,0xc5,0xc2,0xbf,0xbd, 669 0xba,0xb7,0xb5,0xb2,0xb0,0xae,0xab,0xa9, 670 0xa7,0xa5,0xa2,0xa0,0x9e,0x9c,0x9a,0x99, 671 0x97,0x95,0x94,0x92,0x91,0x8f,0x8e,0x8c, 672 0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x85, 673 0x84,0x83,0x83,0x82,0x82,0x82,0x82,0x82, 674 675 0x82,0x82,0x82,0x82,0x82,0x82,0x83,0x83, 676 0x84,0x85,0x85,0x86,0x87,0x88,0x89,0x8a, 677 0x8b,0x8c,0x8e,0x8f,0x90,0x92,0x94,0x95, 678 0x97,0x99,0x9a,0x9c,0x9e,0xa0,0xa2,0xa5, 679 0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7, 680 0xba,0xbd,0xbf,0xc2,0xc5,0xc7,0xca,0xcd, 681 0xd0,0xd3,0xd6,0xd9,0xdc,0xdf,0xe2,0xe5, 682 0xe8,0xeb,0xee,0xf1,0xf4,0xf7,0xfa,0xfd, 683 684 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x15, 685 0x18,0x1b,0x1e,0x21,0x24,0x27,0x2a,0x2d, 686 0x30,0x33,0x36,0x39,0x3b,0x3e,0x41,0x43, 687 0x46,0x49,0x4b,0x4e,0x50,0x52,0x55,0x57, 688 0x59,0x5b,0x5e,0x60,0x62,0x64,0x65,0x67, 689 0x69,0x6b,0x6c,0x6e,0x6f,0x71,0x72,0x74, 690 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7b, 691 0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7e, 692 }; 693 distance = distance; // Keep LINT quiet. 694 695 // 696 // Have to declare table as unsigned otherwise MSVC complains, but we need to treat the actual values as signed. 697 // 698 static const char *_sin_table = (char*)&SinTable[0]; 699 static const char *_cos_table = (char*)&CosTable[0]; 700 701 x += calcx(_cos_table[dir], distance); 702 703 y += calcy(_sin_table[dir] / 2, distance); 704 }