OLDSCALE.C (15341B)
1 // WL_SCALE.C 2 3 #include "WL_DEF.H" 4 #pragma hdrstop 5 6 #define OP_RETF 0xcb 7 8 /* 9 ============================================================================= 10 11 GLOBALS 12 13 ============================================================================= 14 */ 15 16 t_compscale _seg *scaledirectory[MAXSCALEHEIGHT+1]; 17 long fullscalefarcall[MAXSCALEHEIGHT+1]; 18 19 int maxscale,maxscaleshl2; 20 21 /* 22 ============================================================================= 23 24 LOCALS 25 26 ============================================================================= 27 */ 28 29 t_compscale _seg *work; 30 unsigned BuildCompScale (int height, memptr *finalspot); 31 32 int stepbytwo; 33 34 //=========================================================================== 35 36 /* 37 ============== 38 = 39 = BadScale 40 = 41 ============== 42 */ 43 44 void far BadScale (void) 45 { 46 Quit ("BadScale called!"); 47 } 48 49 50 /* 51 ========================== 52 = 53 = SetupScaling 54 = 55 ========================== 56 */ 57 58 void SetupScaling (int maxscaleheight) 59 { 60 int i,x,y; 61 byte far *dest; 62 63 maxscaleheight/=2; // one scaler every two pixels 64 65 maxscale = maxscaleheight-1; 66 maxscaleshl2 = maxscale<<2; 67 68 // 69 // free up old scalers 70 // 71 for (i=1;i<MAXSCALEHEIGHT;i++) 72 { 73 if (scaledirectory[i]) 74 MM_FreePtr (&(memptr)scaledirectory[i]); 75 if (i>=stepbytwo) 76 i += 2; 77 } 78 memset (scaledirectory,0,sizeof(scaledirectory)); 79 80 MM_SortMem (); 81 82 // 83 // build the compiled scalers 84 // 85 stepbytwo = viewheight/2; // save space by double stepping 86 MM_GetPtr (&(memptr)work,20000); 87 if (mmerror) 88 return; 89 90 for (i=1;i<=maxscaleheight;i++) 91 { 92 BuildCompScale (i*2,&(memptr)scaledirectory[i]); 93 if (mmerror) 94 { 95 MM_FreePtr (&(memptr)work); 96 return; 97 } 98 if (i>=stepbytwo) 99 i+= 2; 100 } 101 MM_FreePtr (&(memptr)work); 102 103 // 104 // compact memory and lock down scalers 105 // 106 MM_SortMem (); 107 for (i=1;i<=maxscaleheight;i++) 108 { 109 MM_SetLock (&(memptr)scaledirectory[i],true); 110 fullscalefarcall[i] = (unsigned)scaledirectory[i]; 111 fullscalefarcall[i] <<=16; 112 fullscalefarcall[i] += scaledirectory[i]->codeofs[0]; 113 if (i>=stepbytwo) 114 { 115 scaledirectory[i+1] = scaledirectory[i]; 116 fullscalefarcall[i+1] = fullscalefarcall[i]; 117 scaledirectory[i+2] = scaledirectory[i]; 118 fullscalefarcall[i+2] = fullscalefarcall[i]; 119 i+=2; 120 } 121 } 122 scaledirectory[0] = scaledirectory[1]; 123 fullscalefarcall[0] = fullscalefarcall[1]; 124 125 // 126 // check for oversize wall drawing 127 // 128 for (i=maxscaleheight;i<MAXSCALEHEIGHT;i++) 129 fullscalefarcall[i] = (long)BadScale; 130 131 } 132 133 //=========================================================================== 134 135 /* 136 ======================== 137 = 138 = BuildCompScale 139 = 140 = Builds a compiled scaler object that will scale a 64 tall object to 141 = the given height (centered vertically on the screen) 142 = 143 = height should be even 144 = 145 = Call with 146 = --------- 147 = DS:SI Source for scale 148 = ES:DI Dest for scale 149 = 150 = Calling the compiled scaler only destroys AL 151 = 152 ======================== 153 */ 154 155 unsigned BuildCompScale (int height, memptr *finalspot) 156 { 157 byte far *code; 158 159 int i; 160 long fix,step; 161 unsigned src,totalscaled,totalsize; 162 int startpix,endpix,toppix; 163 164 165 step = ((long)height<<16) / 64; 166 code = &work->code[0]; 167 toppix = (viewheight-height)/2; 168 fix = 0; 169 170 for (src=0;src<=64;src++) 171 { 172 startpix = fix>>16; 173 fix += step; 174 endpix = fix>>16; 175 176 if (endpix>startpix) 177 work->width[src] = endpix-startpix; 178 else 179 work->width[src] = 0; 180 181 // 182 // mark the start of the code 183 // 184 work->codeofs[src] = FP_OFF(code); 185 186 // 187 // compile some code if the source pixel generates any screen pixels 188 // 189 startpix+=toppix; 190 endpix+=toppix; 191 192 if (startpix == endpix || endpix < 0 || startpix >= viewheight || src == 64) 193 continue; 194 195 // 196 // mov al,[si+src] 197 // 198 *code++ = 0x8a; 199 *code++ = 0x44; 200 *code++ = src; 201 202 for (;startpix<endpix;startpix++) 203 { 204 if (startpix >= viewheight) 205 break; // off the bottom of the view area 206 if (startpix < 0) 207 continue; // not into the view area 208 209 // 210 // mov [es:di+heightofs],al 211 // 212 *code++ = 0x26; 213 *code++ = 0x88; 214 *code++ = 0x85; 215 *((unsigned far *)code)++ = startpix*SCREENBWIDE; 216 } 217 218 } 219 220 // 221 // retf 222 // 223 *code++ = 0xcb; 224 225 totalsize = FP_OFF(code); 226 MM_GetPtr (finalspot,totalsize); 227 if (mmerror) 228 return 0; 229 _fmemcpy ((byte _seg *)(*finalspot),(byte _seg *)work,totalsize); 230 231 return totalsize; 232 } 233 234 235 /* 236 ======================= 237 = 238 = ScaleLine 239 = 240 = linescale should have the high word set to the segment of the scaler 241 = 242 ======================= 243 */ 244 245 extern int slinex,slinewidth; 246 extern unsigned far *linecmds; 247 extern long linescale; 248 extern unsigned maskword; 249 250 byte mask1,mask2,mask3; 251 252 253 void near ScaleLine (void) 254 { 255 asm mov cx,WORD PTR [linescale+2] 256 asm mov es,cx // segment of scaler 257 258 asm mov bp,WORD PTR [linecmds] 259 asm mov dx,SC_INDEX+1 // to set SC_MAPMASK 260 261 asm mov bx,[slinex] 262 asm mov di,bx 263 asm shr di,2 // X in bytes 264 asm add di,[bufferofs] 265 asm and bx,3 266 asm shl bx,3 267 asm add bx,[slinewidth] // bx = (pixel*8+pixwidth) 268 asm mov al,BYTE [mapmasks3-1+bx] // -1 because pixwidth of 1 is first 269 asm mov ds,WORD PTR [linecmds+2] 270 asm or al,al 271 asm jz notthreebyte // scale across three bytes 272 asm jmp threebyte 273 notthreebyte: 274 asm mov al,BYTE PTR ss:[mapmasks2-1+bx] // -1 because pixwidth of 1 is first 275 asm or al,al 276 asm jnz twobyte // scale across two bytes 277 278 // 279 // one byte scaling 280 // 281 asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first 282 asm out dx,al // set map mask register 283 284 scalesingle: 285 286 asm mov bx,[ds:bp] // table location of rtl to patch 287 asm or bx,bx 288 asm jz linedone // 0 signals end of segment list 289 asm mov bx,[es:bx] 290 asm mov dl,[es:bx] // save old value 291 asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in 292 asm mov si,[ds:bp+4] // table location of entry spot 293 asm mov ax,[es:si] 294 asm mov WORD PTR ss:[linescale],ax // call here to start scaling 295 asm mov si,[ds:bp+2] // corrected top of shape for this segment 296 asm add bp,6 // next segment list 297 298 asm mov ax,SCREENSEG 299 asm mov es,ax 300 asm call ss:[linescale] // scale the segment of pixels 301 302 asm mov es,cx // segment of scaler 303 asm mov BYTE PTR es:[bx],dl // unpatch the RETF 304 asm jmp scalesingle // do the next segment 305 306 307 // 308 // done 309 // 310 linedone: 311 asm mov ax,ss 312 asm mov ds,ax 313 return; 314 315 // 316 // two byte scaling 317 // 318 twobyte: 319 asm mov ss:[mask2],al 320 asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first 321 asm mov ss:[mask1],al 322 323 scaledouble: 324 325 asm mov bx,[ds:bp] // table location of rtl to patch 326 asm or bx,bx 327 asm jz linedone // 0 signals end of segment list 328 asm mov bx,[es:bx] 329 asm mov cl,[es:bx] // save old value 330 asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in 331 asm mov si,[ds:bp+4] // table location of entry spot 332 asm mov ax,[es:si] 333 asm mov WORD PTR ss:[linescale],ax // call here to start scaling 334 asm mov si,[ds:bp+2] // corrected top of shape for this segment 335 asm add bp,6 // next segment list 336 337 asm mov ax,SCREENSEG 338 asm mov es,ax 339 asm mov al,ss:[mask1] 340 asm out dx,al // set map mask register 341 asm call ss:[linescale] // scale the segment of pixels 342 asm inc di 343 asm mov al,ss:[mask2] 344 asm out dx,al // set map mask register 345 asm call ss:[linescale] // scale the segment of pixels 346 asm dec di 347 348 asm mov es,WORD PTR ss:[linescale+2] // segment of scaler 349 asm mov BYTE PTR es:[bx],cl // unpatch the RETF 350 asm jmp scaledouble // do the next segment 351 352 353 // 354 // three byte scaling 355 // 356 threebyte: 357 asm mov ss:[mask3],al 358 asm mov al,BYTE PTR ss:[mapmasks2-1+bx] // -1 because pixwidth of 1 is first 359 asm mov ss:[mask2],al 360 asm mov al,BYTE PTR ss:[mapmasks1-1+bx] // -1 because pixwidth of 1 is first 361 asm mov ss:[mask1],al 362 363 scaletriple: 364 365 asm mov bx,[ds:bp] // table location of rtl to patch 366 asm or bx,bx 367 asm jz linedone // 0 signals end of segment list 368 asm mov bx,[es:bx] 369 asm mov cl,[es:bx] // save old value 370 asm mov BYTE PTR es:[bx],OP_RETF // patch a RETF in 371 asm mov si,[ds:bp+4] // table location of entry spot 372 asm mov ax,[es:si] 373 asm mov WORD PTR ss:[linescale],ax // call here to start scaling 374 asm mov si,[ds:bp+2] // corrected top of shape for this segment 375 asm add bp,6 // next segment list 376 377 asm mov ax,SCREENSEG 378 asm mov es,ax 379 asm mov al,ss:[mask1] 380 asm out dx,al // set map mask register 381 asm call ss:[linescale] // scale the segment of pixels 382 asm inc di 383 asm mov al,ss:[mask2] 384 asm out dx,al // set map mask register 385 asm call ss:[linescale] // scale the segment of pixels 386 asm inc di 387 asm mov al,ss:[mask3] 388 asm out dx,al // set map mask register 389 asm call ss:[linescale] // scale the segment of pixels 390 asm dec di 391 asm dec di 392 393 asm mov es,WORD PTR ss:[linescale+2] // segment of scaler 394 asm mov BYTE PTR es:[bx],cl // unpatch the RETF 395 asm jmp scaletriple // do the next segment 396 397 398 } 399 400 401 /* 402 ======================= 403 = 404 = ScaleShape 405 = 406 = Draws a compiled shape at [scale] pixels high 407 = 408 = each vertical line of the shape has a pointer to segment data: 409 = end of segment pixel*2 (0 terminates line) used to patch rtl in scaler 410 = top of virtual line with segment in proper place 411 = start of segment pixel*2, used to jsl into compiled scaler 412 = <repeat> 413 = 414 = Setup for call 415 = -------------- 416 = GC_MODE read mode 1, write mode 2 417 = GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff 418 = GC_INDEX pointing at GC_BITMASK 419 = 420 ======================= 421 */ 422 423 static long longtemp; 424 425 void ScaleShape (int xcenter, int shapenum, unsigned height) 426 { 427 t_compshape _seg *shape; 428 t_compscale _seg *comptable; 429 unsigned scale,srcx,stopx,tempx; 430 int t; 431 unsigned far *cmdptr; 432 boolean leftvis,rightvis; 433 434 435 shape = PM_GetSpritePage (shapenum); 436 437 scale = height>>3; // low three bits are fractional 438 if (!scale || scale>maxscale) 439 return; // too close or far away 440 comptable = scaledirectory[scale]; 441 442 *(((unsigned *)&linescale)+1)=(unsigned)comptable; // seg of far call 443 *(((unsigned *)&linecmds)+1)=(unsigned)shape; // seg of shape 444 445 // 446 // scale to the left (from pixel 31 to shape->leftpix) 447 // 448 srcx = 32; 449 slinex = xcenter; 450 stopx = shape->leftpix; 451 cmdptr = &shape->dataofs[31-stopx]; 452 453 while ( --srcx >=stopx && slinex>0) 454 { 455 (unsigned)linecmds = *cmdptr--; 456 if ( !(slinewidth = comptable->width[srcx]) ) 457 continue; 458 459 if (slinewidth == 1) 460 { 461 slinex--; 462 if (slinex<viewwidth) 463 { 464 if (wallheight[slinex] >= height) 465 continue; // obscured by closer wall 466 ScaleLine (); 467 } 468 continue; 469 } 470 471 // 472 // handle multi pixel lines 473 // 474 if (slinex>viewwidth) 475 { 476 slinex -= slinewidth; 477 slinewidth = viewwidth-slinex; 478 if (slinewidth<1) 479 continue; // still off the right side 480 } 481 else 482 { 483 if (slinewidth>slinex) 484 slinewidth = slinex; 485 slinex -= slinewidth; 486 } 487 488 489 leftvis = (wallheight[slinex] < height); 490 rightvis = (wallheight[slinex+slinewidth-1] < height); 491 492 if (leftvis) 493 { 494 if (rightvis) 495 ScaleLine (); 496 else 497 { 498 while (wallheight[slinex+slinewidth-1] >= height) 499 slinewidth--; 500 ScaleLine (); 501 } 502 } 503 else 504 { 505 if (!rightvis) 506 continue; // totally obscured 507 508 while (wallheight[slinex] >= height) 509 { 510 slinex++; 511 slinewidth--; 512 } 513 ScaleLine (); 514 break; // the rest of the shape is gone 515 } 516 } 517 518 519 // 520 // scale to the right 521 // 522 slinex = xcenter; 523 stopx = shape->rightpix; 524 if (shape->leftpix<31) 525 { 526 srcx = 31; 527 cmdptr = &shape->dataofs[32-shape->leftpix]; 528 } 529 else 530 { 531 srcx = shape->leftpix-1; 532 cmdptr = &shape->dataofs[0]; 533 } 534 slinewidth = 0; 535 536 while ( ++srcx <= stopx && (slinex+=slinewidth)<viewwidth) 537 { 538 (unsigned)linecmds = *cmdptr++; 539 if ( !(slinewidth = comptable->width[srcx]) ) 540 continue; 541 542 if (slinewidth == 1) 543 { 544 if (slinex>=0 && wallheight[slinex] < height) 545 { 546 ScaleLine (); 547 } 548 continue; 549 } 550 551 // 552 // handle multi pixel lines 553 // 554 if (slinex<0) 555 { 556 if (slinewidth <= -slinex) 557 continue; // still off the left edge 558 559 slinewidth += slinex; 560 slinex = 0; 561 } 562 else 563 { 564 if (slinex + slinewidth > viewwidth) 565 slinewidth = viewwidth-slinex; 566 } 567 568 569 leftvis = (wallheight[slinex] < height); 570 rightvis = (wallheight[slinex+slinewidth-1] < height); 571 572 if (leftvis) 573 { 574 if (rightvis) 575 { 576 ScaleLine (); 577 } 578 else 579 { 580 while (wallheight[slinex+slinewidth-1] >= height) 581 slinewidth--; 582 ScaleLine (); 583 break; // the rest of the shape is gone 584 } 585 } 586 else 587 { 588 if (rightvis) 589 { 590 while (wallheight[slinex] >= height) 591 { 592 slinex++; 593 slinewidth--; 594 } 595 ScaleLine (); 596 } 597 else 598 continue; // totally obscured 599 } 600 } 601 } 602 603 604 605 /* 606 ======================= 607 = 608 = SimpleScaleShape 609 = 610 = NO CLIPPING, height in pixels 611 = 612 = Draws a compiled shape at [scale] pixels high 613 = 614 = each vertical line of the shape has a pointer to segment data: 615 = end of segment pixel*2 (0 terminates line) used to patch rtl in scaler 616 = top of virtual line with segment in proper place 617 = start of segment pixel*2, used to jsl into compiled scaler 618 = <repeat> 619 = 620 = Setup for call 621 = -------------- 622 = GC_MODE read mode 1, write mode 2 623 = GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff 624 = GC_INDEX pointing at GC_BITMASK 625 = 626 ======================= 627 */ 628 629 void SimpleScaleShape (int xcenter, int shapenum, unsigned height) 630 { 631 t_compshape _seg *shape; 632 t_compscale _seg *comptable; 633 unsigned scale,srcx,stopx,tempx; 634 int t; 635 unsigned far *cmdptr; 636 boolean leftvis,rightvis; 637 638 639 shape = PM_GetSpritePage (shapenum); 640 641 scale = height>>1; 642 comptable = scaledirectory[scale]; 643 644 *(((unsigned *)&linescale)+1)=(unsigned)comptable; // seg of far call 645 *(((unsigned *)&linecmds)+1)=(unsigned)shape; // seg of shape 646 647 // 648 // scale to the left (from pixel 31 to shape->leftpix) 649 // 650 srcx = 32; 651 slinex = xcenter; 652 stopx = shape->leftpix; 653 cmdptr = &shape->dataofs[31-stopx]; 654 655 while ( --srcx >=stopx ) 656 { 657 (unsigned)linecmds = *cmdptr--; 658 if ( !(slinewidth = comptable->width[srcx]) ) 659 continue; 660 661 slinex -= slinewidth; 662 ScaleLine (); 663 } 664 665 666 // 667 // scale to the right 668 // 669 slinex = xcenter; 670 stopx = shape->rightpix; 671 if (shape->leftpix<31) 672 { 673 srcx = 31; 674 cmdptr = &shape->dataofs[32-shape->leftpix]; 675 } 676 else 677 { 678 srcx = shape->leftpix-1; 679 cmdptr = &shape->dataofs[0]; 680 } 681 slinewidth = 0; 682 683 while ( ++srcx <= stopx ) 684 { 685 (unsigned)linecmds = *cmdptr++; 686 if ( !(slinewidth = comptable->width[srcx]) ) 687 continue; 688 689 ScaleLine (); 690 slinex+=slinewidth; 691 } 692 } 693 694 695 696 697 // 698 // bit mask tables for drawing scaled strips up to eight pixels wide 699 // 700 // down here so the STUPID inline assembler doesn't get confused! 701 // 702 703 704 byte mapmasks1[4][8] = { 705 {1 ,3 ,7 ,15,15,15,15,15}, 706 {2 ,6 ,14,14,14,14,14,14}, 707 {4 ,12,12,12,12,12,12,12}, 708 {8 ,8 ,8 ,8 ,8 ,8 ,8 ,8} }; 709 710 byte mapmasks2[4][8] = { 711 {0 ,0 ,0 ,0 ,1 ,3 ,7 ,15}, 712 {0 ,0 ,0 ,1 ,3 ,7 ,15,15}, 713 {0 ,0 ,1 ,3 ,7 ,15,15,15}, 714 {0 ,1 ,3 ,7 ,15,15,15,15} }; 715 716 byte mapmasks3[4][8] = { 717 {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}, 718 {0 ,0 ,0 ,0 ,0 ,0 ,0 ,1}, 719 {0 ,0 ,0 ,0 ,0 ,0 ,1 ,3}, 720 {0 ,0 ,0 ,0 ,0 ,1 ,3 ,7} }; 721 722 723 unsigned wordmasks[8][8] = { 724 {0x0080,0x00c0,0x00e0,0x00f0,0x00f8,0x00fc,0x00fe,0x00ff}, 725 {0x0040,0x0060,0x0070,0x0078,0x007c,0x007e,0x007f,0x807f}, 726 {0x0020,0x0030,0x0038,0x003c,0x003e,0x003f,0x803f,0xc03f}, 727 {0x0010,0x0018,0x001c,0x001e,0x001f,0x801f,0xc01f,0xe01f}, 728 {0x0008,0x000c,0x000e,0x000f,0x800f,0xc00f,0xe00f,0xf00f}, 729 {0x0004,0x0006,0x0007,0x8007,0xc007,0xe007,0xf007,0xf807}, 730 {0x0002,0x0003,0x8003,0xc003,0xe003,0xf003,0xf803,0xfc03}, 731 {0x0001,0x8001,0xc001,0xe001,0xf001,0xf801,0xfc01,0xfe01} }; 732 733 int slinex,slinewidth; 734 unsigned far *linecmds; 735 long linescale; 736 unsigned maskword; 737