Subversion Repositories spacemission

Rev

Blame | Last modification | View Log | RSS feed

  1. unit turbopixels;
  2.  
  3. // turboPixels 1.2
  4. // for use with DelphiX DirectX Headers and Components
  5.  
  6. // (c) 2000 Michael Wilson -- no.2 games
  7. // www.no2games.com & turbo.gamedev.net
  8. // wilson@no2games.com
  9.  
  10. // 1.2 Features:
  11. // DelphiX 7 support
  12. // Powered by PixelCore release
  13. // PixelCore ASM routines by Henri Hakl aka A-Lore
  14. // Updated WinAmp font routine
  15.  
  16. // 1.1 Features:
  17. // Incorporated ASM conversion by LifePower
  18. // Incorporated ASM putpixels by JerK
  19. // Added non-RGB versions of 8/16/24 PutPixels
  20. // Faster clipping and no surface passing
  21. // Auto 565 and 555 detection that works!!!
  22. // Re-oganized demo for more speed and FPS counter
  23.  
  24. // 1.0 Inital release
  25.  
  26. // [ Credits and thanks... ]
  27. // Based on FastPixels v0.2 for DelphiX -- but faster ;)
  28. // 24-bit put loosely based on Erik Englund's Setpixel.pas
  29. // Thanks to Tim Baumgarten for some bit shifting ideas
  30. // Thanks to John Hebert for teaching me AlphaBlending
  31. // Thanks to Hugo for introducing me to Wu
  32. // ASM conversion routines by LifePower (faster...)
  33. // ASM put routines by JerK (jdelauney@free.fr)
  34. // PixelCore ASM routines by Henri Hakl aka A-Lore
  35. // Font from a WinAmp skin
  36. // Windows SDK help for confusing me about RGB values
  37.  
  38. // [ Legal ]
  39. // THIS SOFTWARE AND THE ACCOMPANYING FILES
  40. // ARE WITHOUT WARRANTIES AS TO PERFORMANCE
  41. // OR MERCHANTABILITY OR ANY OTHER WARRANTIES
  42. // WHETHER EXPRESSED OR IMPLIED.
  43. // Because of the various hardware and software
  44. // environments into which turboPixels may be put,
  45. // NO WARRANTY OF FITNESS FOR A PARTICULAR
  46. // PURPOSE IS OFFERED.
  47.  
  48.  
  49. interface
  50. {$INCLUDE DelphiXcfg.inc}
  51. uses
  52.   Windows, Messages, SysUtils, Classes, Graphics,
  53.   DXDraws, DXClass,
  54. {$IfDef StandardDX}
  55.    DirectDraw;
  56. {$Else}
  57.    DirectX;
  58. {$EndIf}
  59.  
  60. const
  61.   alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ"at  0123456789<>=()-''!_+\/{}^&%.=$#ÅÖÄ?*';
  62.   numbers = '0123456789-';
  63.  
  64. // *** locking functions ***
  65.  
  66. function turboLock(DxDrawSurface: TDirectDrawSurface): Boolean;
  67. procedure turboUnlock;
  68.  
  69. // *** pixel manipulation ***
  70.  
  71. procedure turboSetPixel8(const X, Y: Integer; color: byte);
  72. procedure turboSetPixel8A(const X, Y: Integer; color: Integer);
  73. procedure turboSetPixel8PC(x, y, color: integer);
  74. procedure turboSetPixel16RGB(const X, Y: Integer; R, G, B: byte);
  75. procedure turboSetPixel24RGB(const X, Y: Integer; R, G, B: byte);
  76. procedure turboSetPixel16(const X, Y: integer; color: cardinal);
  77. procedure turboSetPixel16A(X, Y: Integer; color: cardinal);
  78. procedure turboSetPixel16PC(x, y, color: integer);
  79. procedure turboSetPixel32PC(x, y, color: integer);
  80. procedure turboSetPixel24(const X, Y: integer; color: cardinal);
  81. procedure turboSetPixel24A(X, Y: Integer; Color: cardinal);
  82. procedure turboSetPixel24PC(x, y, color: integer);
  83. function turboGetPixel8(const X, Y: Integer): byte;
  84. function turboGetPixel8PC(x, y: integer): integer;
  85. function turboGetPixel16(const x, y: Integer): cardinal;
  86. function turboGetPixel16PC(x, y: integer): integer;
  87. function r16(color: cardinal): byte;
  88. function g16(color: cardinal): byte;
  89. function b16(color: cardinal): byte;
  90. function turboGetPixel24(const x, y: Integer): dword;
  91. function turboGetPixel24PC(x, y: integer): integer;
  92. function r24(color: cardinal): byte;
  93. function g24(color: cardinal): byte;
  94. function b24(color: cardinal): byte;
  95. function turboGetPixel32PC(x, y: integer): integer;
  96. procedure turboSetPixelAlpha16(const X, Y: Integer; color: cardinal; A: byte);
  97. procedure turboSetPixelAlpha24(const X, Y: Integer; color: cardinal; A: byte);
  98. procedure turboSetPixelAlpha16RGB(const X, Y: Integer; R, G, B, A: byte);
  99. procedure turboSetPixelAlpha24RGB(const X, Y: Integer; R, G, B, A: byte);
  100. function Conv15to24(Color: Word): Integer; register;
  101. function Conv16to24(Color: Word): Integer; register;
  102. function Conv24to15(Color: Integer): Word; register;
  103. function Conv24to16(Color: Integer): Word; register;
  104.  
  105. // *** graphic primitives ***
  106.  
  107. procedure turboLine16(x1, y1, x2, y2: Integer; R, G, B: byte);
  108. procedure turboLine24(x1, y1, x2, y2: Integer; R, G, B: byte);
  109. procedure turboWuLine16(x1, y1, x2, y2: Integer; R, G, B: byte);
  110. procedure turboWuLine24(x1, y1, x2, y2: Integer; R, G, B: byte);
  111. procedure turboWrite(DxDrawSurface: TDirectDrawSurface; Imagelist: TDXImageList; font, text: string; x, y: integer);
  112. procedure turboWriteD(DxDrawSurface: TDirectDrawSurface; Imagelist: TDXImageList; font, text: string; x, y: integer);
  113.  
  114. implementation
  115.  
  116. var
  117.   LockedSurface: {$IFDEF D3D_deprecated}IDirectDrawSurface4{$ELSE}IDirectDrawSurface7{$ENDIF};
  118.   LockedSurfaceDesc: TDDSurfaceDesc2;
  119.   LockedRect: TRect;
  120.   bitfix: cardinal; // for 555 or 565
  121.   xmax, ymax: integer; // clipping
  122.  
  123. function turboLock(DxDrawSurface: TDirectDrawSurface): Boolean;
  124. begin
  125.   LockedSurface := DxDrawSurface.{$IFDEF D3D_deprecated}ISurface4{$ELSE}ISurface7{$ENDIF};
  126.   LockedSurfaceDesc.dwSize := SizeOf(TDDSurfaceDesc);
  127.   LockedRect := Rect(0, 0, LockedSurfaceDesc.dwWidth,
  128.     LockedSurfaceDesc.dwHeight);
  129.   if LockedSurface.Lock(@LockedRect, // do the lock
  130.     LockedSurfaceDesc,
  131.     DDLOCK_SURFACEMEMORYPTR + DDLOCK_WAIT,
  132.     0) <> DD_OK
  133.     then Result := False
  134.   else Result := True;
  135.   xmax := DxDrawSurface.Width - 1; // Max X clip
  136.   ymax := DxDrawSurface.Height - 1; // Max Y clip
  137.   if LockedSurfaceDesc.ddpfPixelFormat.dwGBitMask = 2016 // if there are 6 bits
  138.     then bitfix := 0 else bitfix := 1; // of GREEN were looking at 565
  139. end;
  140.  
  141. procedure turboUnlock;
  142. begin
  143.   LockedSurface.Unlock(@LockedRect);
  144.   LockedSurface := nil; // free locked surface
  145. end;
  146.  
  147. procedure turboSetPixel8(const X, Y: Integer; color: byte);
  148. begin
  149.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  150.     (Y < 0) or (Y > ymax) then Exit;
  151.   pbyte(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
  152.     y * LockedSurfaceDesc.lpitch + x)^ := color; // offset for 1 byte pixel
  153. end;
  154.  
  155. procedure turboSetPixel8A(const X, Y: Integer; color: Integer); assembler;
  156. begin
  157.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  158.     (Y < 0) or (Y > ymax) then Exit;
  159.   asm
  160.     push ebx  // ASM put routines by JerK (jdelauney@free.fr)
  161.     push esi  // Don't seem much faster
  162.     push edi
  163.     mov esi,LockedSurfaceDesc.lpSurface
  164.     mov eax,[LockedSurfaceDesc.lpitch]
  165.     mul [Y]
  166.     add esi,eax
  167.     mov ebx,[X]
  168.     add esi,ebx
  169.     mov ebx,[Color]
  170.     mov ds:[esi],ebx
  171.     pop edi
  172.     pop esi
  173.     pop ebx
  174.   end;
  175. end;
  176.  
  177. procedure turboSetPixel16RGB(const X, Y: Integer; R, G, B: byte);
  178. begin
  179.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  180.     (Y < 0) or (Y > ymax) then Exit;
  181.   pword(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
  182.     y * LockedSurfaceDesc.lpitch + x * 2)^ := // offset for *2* byte pixel
  183.     ((R shr 3) shl (11 - bitfix)) or // r value shifted
  184.     ((G shr (2 + bitfix)) shl 5) or // g value shifted
  185.     (B shr 3); // add blue
  186. end;
  187.  
  188. procedure turboSetPixel24RGB(const X, Y: Integer; R, G, B: byte);
  189. begin
  190.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  191.     (Y < 0) or (Y > ymax) then Exit;
  192.   pdword(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
  193.     y * LockedSurfaceDesc.lpitch + x * 3)^ :=
  194.     (r shl 16) or (g shl 8) or b; // Could use RGB(r,g,b)
  195. end;
  196.  
  197. procedure turboSetPixel16(const X, Y: integer; color: cardinal);
  198. begin
  199.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  200.     (Y < 0) or (Y > ymax) then Exit;
  201.   if bitfix = 0 then
  202.     pword(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
  203.       y * LockedSurfaceDesc.lpitch + x * 2)^ := // offset for *2* byte pixel
  204.       Conv24to16(color)
  205.   else
  206.     pword(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
  207.       y * LockedSurfaceDesc.lpitch + x * 2)^ := // offset for *2* byte pixel
  208.       Conv24to15(color);
  209. //    ((R16(color) shr 3) shl (11 - bitfix)) or // r value shifted
  210. //    ((G16(color) shr (2 + bitfix)) shl 5) or // g value shifted
  211. //    (B16(color) shr 3); // add blue
  212. end;
  213.  
  214. procedure turboSetPixel16A(X, Y: Integer; Color: cardinal); assembler;
  215. var
  216.   convertedcolor: integer;
  217. begin
  218.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  219.     (Y < 0) or (Y > ymax) then Exit;
  220.   if bitfix = 0 then
  221.     convertedcolor := Conv24to16(color)
  222.   else
  223.     convertedcolor := Conv24to15(color);
  224.   asm
  225.     push ebx  // ASM put routines by JerK (jdelauney@free.fr)
  226.     push esi
  227.     push edi
  228.     mov esi,LockedSurfaceDesc.lpSurface
  229.     mov eax,[LockedSurfaceDesc.lpitch]
  230.     mul [Y]
  231.     add esi,eax
  232.     mov ebx,[X]
  233.     shl ebx,1
  234.     add esi,ebx
  235.     mov ebx,[convertedcolor]
  236.     mov ds:[esi],ebx
  237.     pop edi
  238.     pop esi
  239.     pop ebx
  240.   end;
  241. end;
  242.  
  243. procedure turboSetPixel24(const X, Y: Integer; color: cardinal);
  244. begin
  245.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  246.     (Y < 0) or (Y > ymax) then Exit;
  247.   pdword(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
  248.     y * LockedSurfaceDesc.lpitch + x * 3)^ :=
  249.     color;
  250. end;
  251.  
  252. procedure turboSetPixel24A(X, Y: Integer; Color: cardinal); assembler;
  253. begin
  254.   asm
  255.     push ebx  // ASM put routines by JerK (jdelauney@free.fr)
  256.     push esi
  257.     push edi
  258.     mov esi,LockedSurfaceDesc.lpSurface
  259.     mov eax,[LockedSurfaceDesc.lpitch]
  260.     mul [Y]
  261.     add esi,eax
  262.     mov ebx,[X]
  263.     imul ebx,3
  264.     add esi,ebx
  265.     mov ebx,[Color]
  266.     mov ds:[esi],ebx
  267.     pop edi
  268.     pop esi
  269.     pop ebx
  270.   end;
  271. end;
  272.  
  273. function turboGetPixel8(const X, Y: Integer): byte;
  274. begin
  275.   result := 0;
  276.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  277.     (Y < 0) or (Y > ymax) then Exit;
  278.   result := pbyte(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
  279.     y * LockedSurfaceDesc.lpitch + x)^; // offset for 1 byte pixel
  280. end;
  281.  
  282. function turboGetPixel16(const x, y: Integer): cardinal;
  283. begin
  284.   result := 0;
  285.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  286.     (Y < 0) or (Y > ymax) then Exit;
  287.   result := pword(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
  288.     y * LockedSurfaceDesc.lpitch + x * 2)^;
  289. end;
  290.  
  291. function r16(color: cardinal): byte;
  292. begin;
  293.   result := (color shr (11 - bitfix)) shl 3;
  294. end;
  295.  
  296. function g16(color: cardinal): byte;
  297. begin;
  298.   if bitfix = 0 then
  299.     result := ((color and 2016) shr 5) shl 2
  300.   else
  301.     result := ((color and 992) shr 5) shl 3;
  302. end;
  303.  
  304. function b16(color: cardinal): byte;
  305. begin;
  306.   result := (color and 31) shl 3;
  307. end;
  308.  
  309. function turboGetPixel24(const x, y: Integer): dword;
  310. begin
  311.   result := 0;
  312.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  313.     (Y < 0) or (Y > ymax) then Exit;
  314.   result := pdword(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
  315.     y * LockedSurfaceDesc.lpitch + x * 3)^;
  316. end;
  317.  
  318. function r24(color: cardinal): byte;
  319. begin;
  320.   result := (color shr 16) and 255; // or GetRValue(color);
  321. end;
  322.  
  323. function g24(color: cardinal): byte;
  324. begin;
  325.   result := (color shr 8) and 255; // or GetGValue(color);
  326. end;
  327.  
  328. function b24(color: cardinal): byte;
  329. begin;
  330. // Some video boards may return a blue value in the first byte
  331. // i.e. result := color and 255;
  332.   result := (color shr 24) and 255; // or GetBValue(color);
  333. end;
  334.  
  335. procedure turboSetPixelAlpha16RGB(const X, Y: Integer; R, G, B, A: byte);
  336. var color: integer;
  337. begin
  338. // This function could use a lot of speed work, but it's faster than
  339. // alpha blending Canvas.Pixels ;) but Hori's FillRectAdd is faster
  340. // for large areas
  341.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  342.     (Y < 0) or (Y > ymax) then Exit;
  343.   color := turboGetPixel16(x, y); // get "color"
  344.   turboSetPixel16RGB(X, Y, // set new pixel
  345.     (A * (R - r16(color)) shr 8) + r16(color), // R alpha
  346.     (A * (G - g16(color)) shr 8) + g16(color), // G alpha
  347.     (A * (B - b16(color)) shr 8) + b16(color)); // B alpha
  348. end;
  349.  
  350. procedure turboSetPixelAlpha24RGB(const X, Y: Integer; R, G, B, A: byte);
  351. var color: dword;
  352. begin
  353. // This function could use a lot of speed work, but it's faster than
  354. // alpha blending Canvas.Pixels ;) but Hori's FillRectAdd is faster
  355. // for large areas
  356.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  357.     (Y < 0) or (Y > ymax) then Exit;
  358.   color := turboGetPixel24(x, y); // get "color"
  359.   turboSetPixel24RGB(X, Y, // set new pixel
  360.     (A * (R - r24(color)) shr 8) + r24(color), // R alpha
  361.     (A * (G - g24(color)) shr 8) + g24(color), // G alpha
  362.     (A * (B - b24(color)) shr 8) + b24(color)); // B alpha
  363. end;
  364.  
  365.  
  366. procedure turboSetPixelAlpha16(const X, Y: Integer; color: cardinal; A: byte);
  367. var oldcolor: integer;
  368. begin
  369. // This function could use a lot of speed work, but it's faster than
  370. // alpha blending Canvas.Pixels ;) but Hori's FillRectAdd is faster
  371. // for large areas
  372.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  373.     (Y < 0) or (Y > ymax) then Exit;
  374.   oldcolor := turboGetPixel16(x, y); // get old color
  375.   turboSetPixel16RGB(X, Y, // set new pixel
  376.     (A * (r16(color) - r16(oldcolor)) shr 8) + r16(oldcolor), // R alpha
  377.     (A * (g16(color) - g16(oldcolor)) shr 8) + g16(oldcolor), // G alpha
  378.     (A * (b16(color) - b16(oldcolor)) shr 8) + b16(oldcolor)); // B alpha
  379. end;
  380.  
  381. procedure turboSetPixelAlpha24(const X, Y: Integer; color: cardinal; A: byte);
  382. var oldcolor: dword;
  383. begin
  384. // This function could use a lot of speed work, but it's faster than
  385. // alpha blending Canvas.Pixels ;) but Hori's FillRectAdd is faster
  386. // for large areas
  387.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  388.     (Y < 0) or (Y > ymax) then Exit;
  389.   oldcolor := turboGetPixel24(x, y); // get "color"
  390.   turboSetPixel24RGB(X, Y, // set new pixel
  391.     (A * (r24(color) - r24(oldcolor)) shr 8) + r24(oldcolor), // R alpha
  392.     (A * (g24(color) - g24(oldcolor)) shr 8) + g24(oldcolor), // G alpha
  393.     (A * (b24(color) - b24(oldcolor)) shr 8) + b24(oldcolor)); // B alpha
  394. end;
  395.  
  396. // *** ASM pixel routines straight from PixelCore by Henri Hakl aka A-Lore ***
  397. // *** Surface clipping added by Michael Wilson 09/07/2000
  398.  
  399. procedure turboSetPixel8PC(x, y, color: integer);
  400. { on entry:  x = eax,   y = edx,   color = ecx }
  401. begin
  402.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  403.     (Y < 0) or (Y > ymax) then Exit;
  404.   asm
  405.    push esi                              // must maintain esi
  406.    mov esi,LockedSurfaceDesc.lpSurface      // set to surface
  407.    add esi,eax                           // add x
  408.    mov eax,[LockedSurfaceDesc.lpitch]       // eax = pitch
  409.    mul edx                               // eax = pitch * y
  410.    add esi,eax                           // esi = pixel offset
  411.    mov ds:[esi],cl                       // set pixel (lo byte of ecx)
  412.    pop esi                               // restore esi
  413.    ret                                   // return
  414.   end;
  415. end;
  416.  
  417. procedure turboSetPixel16PC(x, y, color: integer);
  418. { on entry:  x = eax,   y = edx,   color = ecx }
  419. begin
  420.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  421.     (Y < 0) or (Y > ymax) then Exit;
  422.   asm
  423.    push esi
  424.    mov esi,LockedSurfaceDesc.lpSurface
  425.    shl eax,1
  426.    add esi,eax                           // description similar to PutPixel8
  427.    mov eax,[LockedSurfaceDesc.lpitch]
  428.    mul edx
  429.    add esi,eax
  430.    mov ds:[esi],cx
  431.    pop esi
  432.    ret
  433.   end;
  434. end;
  435.  
  436. procedure turboSetPixel24PC(x, y, color: integer);
  437. { on entry:  x = eax,   y = edx,   color = ecx }
  438. begin
  439.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  440.     (Y < 0) or (Y > ymax) then Exit;
  441.   asm
  442.    push esi
  443.    mov esi,LockedSurfaceDesc.lpSurface
  444.    imul eax,3
  445.    add esi,eax                           // description similar to PutPixel8
  446.    mov eax,[LockedSurfaceDesc.lpitch]
  447.    mul edx
  448.    add esi,eax
  449.    mov eax,ds:[esi]       // the idea is to get the current pixel
  450.    and eax,$ff000000      // and the top 8 bits of next pixel (red component)
  451.    or  ecx,eax            // then bitwise OR that component to the current color
  452.    mov ds:[esi+1],ecx     // to ensure the prior bitmap isn't incorrectly manipulated
  453.    pop esi                // can't test if it works... so hope and pray
  454.    ret
  455.   end;
  456. end;
  457.  
  458. procedure turboSetPixel32PC(x, y, color: integer);
  459. { on entry:  x = eax,   y = edx,   color = ecx }
  460. begin
  461.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  462.     (Y < 0) or (Y > ymax) then Exit;
  463.   asm
  464.    push esi
  465.    mov esi,LockedSurfaceDesc.lpSurface
  466.    shl eax,2
  467.    add esi,eax                           // description similar to PutPixel8
  468.    mov eax,[LockedSurfaceDesc.lpitch]
  469.    mul edx
  470.    add esi,eax
  471.    mov ds:[esi],ecx
  472.    pop esi
  473.    ret
  474.   end;
  475. end;
  476.  
  477. function turboGetPixel8PC(x, y: integer): integer;
  478. { on entry:  x = eax,   y = edx }
  479. begin
  480.   Result := -1;
  481.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  482.     (Y < 0) or (Y > ymax) then Exit;
  483.   asm
  484.    push esi                              // myst maintain esi
  485.    mov esi,LockedSurfaceDesc.lpSurface      // set to surface
  486.    add esi,eax                           // add x
  487.    mov eax,[LockedSurfaceDesc.lpitch]       // eax = pitch
  488.    mul edx                               // eax = pitch * y
  489.    add esi,eax                           // esi = pixel offset
  490.    mov eax,ds:[esi]                      // eax = color
  491.    and eax,$ff                           // map into 8bit
  492.    pop esi                               // restore esi
  493.    ret                                   // return
  494.   end;
  495. end;
  496.  
  497. function turboGetPixel16PC(x, y: integer): integer;
  498. { on entry:  x = eax,   y = edx }
  499. begin
  500.   Result := -1;
  501.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  502.     (Y < 0) or (Y > ymax) then Exit;
  503.   asm
  504.    push esi
  505.    mov esi,LockedSurfaceDesc.lpSurface
  506.    shl eax,1
  507.    add esi,eax                           // description similar to GetPixel8
  508.    mov eax,[LockedSurfaceDesc.lpitch]
  509.    mul edx
  510.    add esi,eax
  511.    mov eax,ds:[esi]
  512.    and eax,$ffff                         // map into 16bit
  513.    pop esi
  514.    ret
  515.   end;
  516. end;
  517.  
  518. function turboGetPixel24PC(x, y: integer): integer;
  519. { on entry:  x = eax,   y = edx }
  520. begin
  521.   Result := -1;
  522.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  523.     (Y < 0) or (Y > ymax) then Exit;
  524.   asm
  525.    push esi
  526.    mov esi,LockedSurfaceDesc.lpSurface
  527.    imul eax,3
  528.    add esi,ebx                           // description similar to GetPixel8
  529.    mov eax,[LockedSurfaceDesc.lpitch]
  530.    mul edx
  531.    add esi,eax
  532.    mov eax,ds:[esi]
  533.    and eax,$ffffff                       // map into 24bit
  534.    pop esi
  535.    ret
  536.   end;
  537. end;
  538.  
  539. function turboGetPixel32PC(x, y: integer): integer;
  540. { on entry:  x = eax,   y = edx }
  541. begin
  542.   Result := -1;
  543.   if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
  544.     (Y < 0) or (Y > ymax) then Exit;
  545.   asm
  546.    push esi
  547.    mov esi,LockedSurfaceDesc.lpSurface
  548.    shl eax,2
  549.    add esi,eax                           // description similar to GetPixel8
  550.    mov eax,[LockedSurfaceDesc.lpitch]
  551.    mul edx
  552.    add esi,eax
  553.    mov eax,ds:[esi]
  554.    pop esi
  555.    ret
  556.   end;
  557. end;
  558.  
  559. // *** end of Pixel Core routines
  560.  
  561. procedure turboLine16(x1, y1, x2, y2: Integer; R, G, B: byte);
  562. var
  563.   i, deltax, deltay, numpixels,
  564.     d, dinc1, dinc2, x, xinc1, xinc2,
  565.     y, yinc1, yinc2: integer;
  566. begin
  567.   deltax := abs(x2 - x1); // Calculate deltax and deltay for initialisation
  568.   deltay := abs(y2 - y1);
  569.   if deltax >= deltay then // Initialize all vars based on which is the independent variable
  570.   begin
  571.     numpixels := deltax + 1; // x is independent variable
  572.     d := (2 * deltay) - deltax;
  573.     dinc1 := deltay shl 1;
  574.     dinc2 := (deltay - deltax) shl 1;
  575.     xinc1 := 1;
  576.     xinc2 := 1;
  577.     yinc1 := 0;
  578.     yinc2 := 1;
  579.   end
  580.   else
  581.   begin
  582.     numpixels := deltay + 1; // y is independent variable
  583.     d := (2 * deltax) - deltay;
  584.     dinc1 := deltax shl 1;
  585.     dinc2 := (deltax - deltay) shl 1;
  586.     xinc1 := 0;
  587.     xinc2 := 1;
  588.     yinc1 := 1;
  589.     yinc2 := 1;
  590.   end;
  591.   if x1 > x2 then // Make sure x and y move in the right directions
  592.   begin
  593.     xinc1 := -xinc1;
  594.     xinc2 := -xinc2;
  595.   end;
  596.   if y1 > y2 then
  597.   begin
  598.     yinc1 := -yinc1;
  599.     yinc2 := -yinc2;
  600.   end;
  601.   x := x1; // Start drawing at <x1, y1>
  602.   y := y1;
  603.   for i := 1 to numpixels do // Draw the pixels
  604.   begin
  605.     turboSetPixel16RGB(X, Y, R, G, B);
  606.     if d < 0 then
  607.     begin
  608.       d := d + dinc1;
  609.       x := x + xinc1;
  610.       y := y + yinc1;
  611.     end
  612.     else
  613.     begin
  614.       d := d + dinc2;
  615.       x := x + xinc2;
  616.       y := y + yinc2;
  617.     end;
  618.   end;
  619. end;
  620.  
  621. procedure turboLine24(x1, y1, x2, y2: Integer; R, G, B: byte);
  622. var
  623.   i, deltax, deltay, numpixels,
  624.     d, dinc1, dinc2, x, xinc1, xinc2,
  625.     y, yinc1, yinc2: integer;
  626. begin
  627.   deltax := abs(x2 - x1); // Calculate deltax and deltay for initialisation
  628.   deltay := abs(y2 - y1);
  629.   if deltax >= deltay then // Initialize all vars based on which is the independent variable
  630.   begin
  631.     numpixels := deltax + 1; // x is independent variable
  632.     d := (2 * deltay) - deltax;
  633.     dinc1 := deltay shl 1;
  634.     dinc2 := (deltay - deltax) shl 1;
  635.     xinc1 := 1;
  636.     xinc2 := 1;
  637.     yinc1 := 0;
  638.     yinc2 := 1;
  639.   end
  640.   else
  641.   begin
  642.     numpixels := deltay + 1; // y is independent variable
  643.     d := (2 * deltax) - deltay;
  644.     dinc1 := deltax shl 1;
  645.     dinc2 := (deltax - deltay) shl 1;
  646.     xinc1 := 0;
  647.     xinc2 := 1;
  648.     yinc1 := 1;
  649.     yinc2 := 1;
  650.   end;
  651.   if x1 > x2 then // Make sure x and y move in the right directions
  652.   begin
  653.     xinc1 := -xinc1;
  654.     xinc2 := -xinc2;
  655.   end;
  656.   if y1 > y2 then
  657.   begin
  658.     yinc1 := -yinc1;
  659.     yinc2 := -yinc2;
  660.   end;
  661.   x := x1; // Start drawing at <x1, y1>
  662.   y := y1;
  663.   for i := 1 to numpixels do // Draw the pixels
  664.   begin
  665.     turboSetPixel24RGB(X, Y, R, G, B);
  666.     if d < 0 then
  667.     begin
  668.       d := d + dinc1;
  669.       x := x + xinc1;
  670.       y := y + yinc1;
  671.     end
  672.     else
  673.     begin
  674.       d := d + dinc2;
  675.       x := x + xinc2;
  676.       y := y + yinc2;
  677.     end;
  678.   end;
  679. end;
  680.  
  681. procedure turboWuLine16(x1, y1, x2, y2: Integer; R, G, B: byte);
  682. var
  683.   deltax, deltay, loop, start, finish: integer;
  684.   dx, dy, dydx: single; // fractional parts
  685. begin
  686.   deltax := abs(x2 - x1); // Calculate deltax and deltay for initialisation
  687.   deltay := abs(y2 - y1);
  688.   if (deltax = 0) or (deltay = 0) then begin // straight lines
  689.     turboLine16(x1, y1, x2, y2, R, G, B);
  690.     exit;
  691.   end;
  692.   if deltax > deltay then // horizontal or verticle
  693.   begin
  694.     if y2 > y1 then // determine rise and run
  695.       dydx := -(deltay / deltax)
  696.     else
  697.       dydx := deltay / deltax;
  698.     if x2 < x1 then
  699.     begin
  700.       start := x2; // right to left
  701.       finish := x1;
  702.       dy := y2;
  703.     end
  704.     else
  705.     begin
  706.       start := x1; // left to right
  707.       finish := x2;
  708.       dy := y1;
  709.       dydx := -dydx; // inverse slope
  710.     end;
  711.     for loop := start to finish do begin
  712.       turboSetPixelAlpha16RGB(loop, trunc(dy), R, G, B,
  713.         trunc((1 - frac(dy)) * 255)); // plot main point
  714.       turboSetPixelAlpha16RGB(loop, trunc(dy) + 1, R, G, B,
  715.         trunc(frac(dy) * 255)); // plot fractional difference
  716.       dy := dy + dydx; // next point
  717.     end;
  718.   end
  719.   else
  720.   begin
  721.     if x2 > x1 then // determine rise and run
  722.       dydx := -(deltax / deltay)
  723.     else
  724.       dydx := deltax / deltay;
  725.     if y2 < y1 then
  726.     begin
  727.       start := y2; // right to left
  728.       finish := y1;
  729.       dx := x2;
  730.     end
  731.     else
  732.     begin
  733.       start := y1; // left to right
  734.       finish := y2;
  735.       dx := x1;
  736.       dydx := -dydx; // inverse slope
  737.     end;
  738.     for loop := start to finish do begin
  739.       turboSetPixelAlpha16RGB(trunc(dx), loop, R, G, B,
  740.         trunc((1 - frac(dx)) * 255)); // plot main point
  741.       turboSetPixelAlpha16RGB(trunc(dx) + 1, loop, R, G, B,
  742.         trunc(frac(dx) * 255)); // plot fractional difference
  743.       dx := dx + dydx; // next point
  744.     end;
  745.   end;
  746. end;
  747.  
  748. procedure turboWuLine24(x1, y1, x2, y2: Integer; R, G, B: byte);
  749. var
  750.   deltax, deltay, loop, start, finish: integer;
  751.   dx, dy, dydx: single; // fractional parts
  752. begin
  753.   deltax := abs(x2 - x1); // Calculate deltax and deltay for initialisation
  754.   deltay := abs(y2 - y1);
  755.   if (deltax = 0) or (deltay = 0) then begin // straight lines
  756.     turboLine24(x1, y1, x2, y2, R, G, B);
  757.     exit;
  758.   end;
  759.   if deltax > deltay then // horizontal or verticle
  760.   begin
  761.     if y2 > y1 then // determine rise and run
  762.       dydx := -(deltay / deltax)
  763.     else
  764.       dydx := deltay / deltax;
  765.     if x2 < x1 then
  766.     begin
  767.       start := x2; // right to left
  768.       finish := x1;
  769.       dy := y2;
  770.     end
  771.     else
  772.     begin
  773.       start := x1; // left to right
  774.       finish := x2;
  775.       dy := y1;
  776.       dydx := -dydx; // inverse slope
  777.     end;
  778.     for loop := start to finish do begin
  779.       turboSetPixelAlpha24RGB(loop, trunc(dy), R, G, B,
  780.         trunc((1 - frac(dy)) * 255)); // plot main point
  781.       turboSetPixelAlpha24RGB(loop, trunc(dy) + 1, R, G, B,
  782.         trunc(frac(dy) * 255)); // plot fractional difference
  783.       dy := dy + dydx; // next point
  784.     end;
  785.   end
  786.   else
  787.   begin
  788.     if x2 > x1 then // determine rise and run
  789.       dydx := -(deltax / deltay)
  790.     else
  791.       dydx := deltax / deltay;
  792.     if y2 < y1 then
  793.     begin
  794.       start := y2; // right to left
  795.       finish := y1;
  796.       dx := x2;
  797.     end
  798.     else
  799.     begin
  800.       start := y1; // left to right
  801.       finish := y2;
  802.       dx := x1;
  803.       dydx := -dydx; // inverse slope
  804.     end;
  805.     for loop := start to finish do begin
  806.       turboSetPixelAlpha24RGB(trunc(dx), loop, R, G, B,
  807.         trunc((1 - frac(dx)) * 255)); // plot main point
  808.       turboSetPixelAlpha24RGB(trunc(dx) + 1, loop, R, G, B,
  809.         trunc(frac(dx) * 255)); // plot fractional difference
  810.       dx := dx + dydx; // next point
  811.     end;
  812.   end;
  813. end;
  814.  
  815. // *** ASM conversion routines by LifePower ***
  816.  
  817. function Conv15to24(Color: Word): Integer; register;
  818. asm
  819.  xor edx,edx   // not used in LIB
  820.  mov dx,ax     // ASM code by LifePower
  821.  mov eax,edx
  822.  shl eax,27
  823.  shr eax,8
  824.  mov ecx,edx
  825.  shr ecx,5
  826.  shl ecx,27
  827.  shr ecx,16
  828.  or eax,ecx
  829.  mov ecx,edx
  830.  shr ecx,10
  831.  shl ecx,27
  832.  shr ecx,24
  833.  or eax,ecx
  834. end;
  835.  
  836. function Conv16to24(Color: Word): Integer; register;
  837. asm
  838.  xor edx,edx   // not used in LIB
  839.  mov dx,ax     // ASM code by LifePower
  840.  mov eax,edx
  841.  shl eax,27
  842.  shr eax,8
  843.  mov ecx,edx
  844.  shr ecx,5
  845.  shl ecx,26
  846.  shr ecx,16
  847.  or eax,ecx
  848.  mov ecx,edx
  849.  shr ecx,11
  850.  shl ecx,27
  851.  shr ecx,24
  852.  or eax,ecx
  853. end;
  854.  
  855. function Conv24to15(Color: Integer): Word; register;
  856. asm
  857.  mov ecx,eax   // ASM code by LifePower
  858.  shl eax,24
  859.  shr eax,27
  860.  shl eax,10
  861.  mov edx,ecx
  862.  shl edx,16
  863.  shr edx,27
  864.  shl edx,5
  865.  or eax,edx
  866.  mov edx,ecx
  867.  shl edx,8
  868.  shr edx,27
  869.  or eax,edx
  870. end;
  871.  
  872. function Conv24to16(Color: Integer): Word; register;
  873. asm
  874.  mov ecx,eax   // ASM code by LifePower
  875.  shl eax,24
  876.  shr eax,27
  877.  shl eax,11
  878.  mov edx,ecx
  879.  shl edx,16
  880.  shr edx,26
  881.  shl edx,5
  882.  or eax,edx
  883.  mov edx,ecx
  884.  shl edx,8
  885.  shr edx,27
  886.  or eax,edx
  887. end;
  888.  
  889. procedure turboWrite(DxDrawSurface: TDirectDrawSurface; Imagelist: TDXImageList; font, text: string; x, y: integer);
  890. var
  891.   loop, line, letter, offset, i: integer;
  892. begin
  893.   i := Imagelist.items.IndexOf(font); // find font once
  894.   offset := Imagelist.items[i].patternwidth;
  895.   line := 1;
  896.   for loop := 1 to Length(text) do
  897.   begin { each letter }
  898.     if text[loop] = '|' then // fake a <P>
  899.     begin
  900.       inc(y, Imagelist.items[i].patternheight + 1);
  901.       line := 1;
  902.     end
  903.     else begin
  904.       letter := pos(uppercase(text[loop]), alphabet) - 1;
  905.       if letter < 0 then letter := 30;
  906.       Imagelist.items[i].draw(DxDrawSurface, x + (offset * line), y, letter);
  907.       inc(line);
  908.     end;
  909.   end; { loop }
  910. end; { graphics write }
  911.  
  912. procedure turboWriteD(DxDrawSurface: TDirectDrawSurface; Imagelist: TDXImageList; font, text: string; x, y: integer);
  913. var
  914.   loop, line, letter, offset, i: integer;
  915. begin
  916.   i := Imagelist.items.IndexOf(font); // find font once
  917.   offset := Imagelist.items[i].patternwidth;
  918.   line := 1;
  919.   for loop := 1 to Length(text) do
  920.   begin { each letter }
  921.     if text[loop] = '|' then // fake a <P>
  922.     begin
  923.       inc(y, Imagelist.items[i].patternheight + 1);
  924.       line := 1;
  925.     end
  926.     else begin
  927.       letter := pos(uppercase(text[loop]), numbers) - 1;
  928.       if letter < 0 then letter := 30;
  929.       Imagelist.items[i].draw(DxDrawSurface, x + (offset * line), y, letter);
  930.       inc(line);
  931.     end;
  932.   end; { loop }
  933. end; { graphics write digits }
  934.  
  935. end.
  936.  
  937.