Subversion Repositories spacemission

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 daniel-mar 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