rnd-20100224-1-src
[rocksndiamonds.git] / src / game_sp / DDScrollBuffer.c
1 // ----------------------------------------------------------------------------
2 // DDScrollBuffer.c
3 // ----------------------------------------------------------------------------
4
5 #include "DDScrollBuffer.h"
6
7 #include <math.h>
8
9
10 // --- VERSION 1.0 CLASS
11 // --- BEGIN
12 // ---   MultiUse = -1  'True  // True
13 // ---   Persistable = 0  'NotPersistable  // NotPersistable
14 // ---   DataBindingBehavior = 0  'vbNone  // vbNone
15 // ---   DataSourceBehavior  = 0  'vbNone  // vbNone
16 // ---   MTSTransactionMode  = 0  'NotAnMTSObject  // NotAnMTSObject
17 // --- END
18
19 // static char *VB_Name = "DDScrollBuffer";
20 // static boolean VB_GlobalNameSpace = False;
21 // static boolean VB_Creatable = True;
22 // static boolean VB_PredeclaredId = False;
23 // static boolean VB_Exposed = False;
24
25 // --- Option Explicit
26
27 // needs reference to: DirectX7 for Visual Basic Type Library
28
29 DirectDrawSurface7 Buffer;
30 DirectDrawSurface7 mPrimary;
31 long mWidth, mHeight;
32 long mhWnd;
33 long mScrollX, mScrollY;
34 long mScrollX_last, mScrollY_last;
35 long mDestXOff, mDestYOff;
36
37 long ScreenBuffer[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
38 boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
39
40 int TEST_flag = 0;
41
42 void RestorePlayfield()
43 {
44   int x1 = mScrollX / TILEX - 2;
45   int y1 = mScrollY / TILEY - 2;
46   int x2 = mScrollX / TILEX + (SCR_FIELDX - 1) + 2;
47   int y2 = mScrollY / TILEY + (SCR_FIELDY - 1) + 2;
48   int x, y;
49
50   DrawFrameIfNeeded();
51
52   for (y = DisplayMinY; y <= DisplayMaxY; y++)
53   {
54     for (x = DisplayMinX; x <= DisplayMaxX; x++)
55     {
56       if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
57       {
58         DrawFieldNoAnimated(x, y);
59         DrawFieldAnimated(x, y);
60       }
61     }
62   }
63 }
64
65 static void ScrollPlayfield(int dx, int dy)
66 {
67   int x1 = mScrollX_last / TILEX - 2;
68   int y1 = mScrollY_last / TILEY - 2;
69   int x2 = mScrollX_last / TILEX + (SCR_FIELDX - 1) + 2;
70   int y2 = mScrollY_last / TILEY + (SCR_FIELDY - 1) + 2;
71   int x, y;
72
73   BlitBitmap(screenBitmap, screenBitmap,
74              TILEX * (dx == -1),
75              TILEY * (dy == -1),
76              (MAX_BUF_XSIZE * TILEX) - TILEX * (dx != 0),
77              (MAX_BUF_YSIZE * TILEY) - TILEY * (dy != 0),
78              TILEX * (dx == 1),
79              TILEY * (dy == 1));
80
81   /* when scrolling the whole playfield, do not redraw single tiles */
82   for (x = 0; x < MAX_BUF_XSIZE; x++)
83     for (y = 0; y < MAX_BUF_YSIZE; y++)
84       redraw[x][y] = FALSE;
85   redraw_tiles = 0;
86
87 #if 1
88   DrawFrameIfNeeded();
89 #endif
90
91   for (y = DisplayMinY; y <= DisplayMaxY; y++)
92   {
93     for (x = DisplayMinX; x <= DisplayMaxX; x++)
94     {
95       if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
96       {
97         int sx = x - x1;
98         int sy = y - y1;
99         int tsi = GetSI(x, y);
100         long id = ((PlayField16[tsi]) |
101                    (PlayField8[tsi] << 16) |
102                    (DisPlayField[tsi] << 24));
103
104 #if 0
105 #if 1
106         printf("::: [%d] %d [%d, %d] [%d]\n", dx, sx, x, y, buf_xsize);
107 #else
108         if (sx == 0 || sx == MAX_BUF_XSIZE - 1)
109           printf("::: %d, %d\n", dx, sx);
110 #endif
111 #endif
112
113         if ((dx == -1 && x == x2) ||
114             (dx == +1 && x == x1) ||
115             (dy == -1 && y == y2) ||
116             (dy == +1 && y == y1))
117         {
118 #if 0
119           printf("::: %d, %d\n", sx, sy);
120 #endif
121
122           TEST_flag = 1;
123
124           DrawFieldNoAnimated(x, y);
125           DrawFieldAnimated(x, y);
126
127           TEST_flag = 0;
128         }
129
130         ScreenBuffer[sx][sy] = id;
131       }
132     }
133   }
134 }
135
136 static void ScrollPlayfieldIfNeededExt(boolean reset)
137 {
138   if (reset)
139   {
140     mScrollX_last = -1;
141     mScrollY_last = -1;
142
143     return;
144   }
145
146   if (mScrollX_last == -1 || mScrollY_last == -1)
147   {
148     mScrollX_last = mScrollX;
149     mScrollY_last = mScrollY;
150
151     return;
152   }
153
154 #if 1
155
156   /* check if scrolling the playfield requires redrawing the viewport bitmap */
157   if ((mScrollX != mScrollX_last ||
158        mScrollY != mScrollY_last) &&
159       (ABS(mScrollX - mScrollX_last) >= TILEX ||
160        ABS(mScrollY - mScrollY_last) >= TILEY))
161   {
162     int dx = (ABS(mScrollX - mScrollX_last) < TILEX ? 0 :
163               mScrollX < mScrollX_last ? 1 : mScrollX > mScrollX_last ? -1 : 0);
164     int dy = (ABS(mScrollY - mScrollY_last) < TILEY ? 0 :
165               mScrollY < mScrollY_last ? 1 : mScrollY > mScrollY_last ? -1 : 0);
166
167     mScrollX_last -= dx * TILEX;
168     mScrollY_last -= dy * TILEY;
169
170     ScrollPlayfield(dx, dy);
171
172 #if 0
173     printf("::: %ld, %ld\n", mScrollX, mScrollY);
174 #endif
175   }
176
177 #else
178
179   /* check if scrolling the playfield reached the destination tile position */
180   if ((mScrollX != mScrollX_last || mScrollY != mScrollY_last) &&
181       mScrollX % TILEX == 0 && mScrollY % TILEY == 0)
182   {
183     int dx = (mScrollX < mScrollX_last ? 1 : mScrollX > mScrollX_last ? -1 : 0);
184     int dy = (mScrollY < mScrollY_last ? 1 : mScrollY > mScrollY_last ? -1 : 0);
185
186     mScrollX_last = mScrollX;
187     mScrollY_last = mScrollY;
188
189     ScrollPlayfield(dx, dy);
190
191 #if 0
192     printf("::: %ld, %ld\n", mScrollX, mScrollY);
193 #endif
194   }
195
196 #endif
197 }
198
199 static void ScrollPlayfieldIfNeeded()
200 {
201   ScrollPlayfieldIfNeededExt(FALSE);
202 }
203
204 void InitScrollPlayfield()
205 {
206   ScrollPlayfieldIfNeededExt(TRUE);
207 }
208
209 void UpdatePlayfield(boolean force_redraw)
210 {
211   int x, y;
212 #if 1
213   int num_redrawn = 0;
214 #endif
215
216   for (y = DisplayMinY; y <= DisplayMaxY; y++)
217   {
218     for (x = DisplayMinX; x <= DisplayMaxX; x++)
219     {
220       int element = LowByte(PlayField16[GetSI(x, y)]);
221       int graphic = GfxGraphic[x][y];
222       int sync_frame = GfxFrame[x][y];
223       boolean redraw = force_redraw;
224
225 #if 0
226       redraw = TRUE;    // !!! TEST ONLY -- ALWAYS REDRAW !!!
227 #endif
228
229       if (graphic < 0)
230       {
231         GfxGraphicLast[x][y] = GfxGraphic[x][y];
232
233         continue;
234       }
235
236       if (element != GfxElementLast[x][y] &&
237           graphic == GfxGraphicLast[x][y])
238       {
239         /* element changed, but not graphic => disable updating graphic */
240
241         GfxElementLast[x][y] = element;
242         GfxGraphicLast[x][y] = GfxGraphic[x][y] = -1;
243
244         continue;
245       }
246
247       if (graphic != GfxGraphicLast[x][y])                      // new graphic
248       {
249         redraw = TRUE;
250
251         GfxElementLast[x][y] = element;
252         GfxGraphicLast[x][y] = GfxGraphic[x][y];
253         sync_frame = GfxFrame[x][y] = 0;
254       }
255       else if (isNextAnimationFrame_SP(graphic, sync_frame))    // new frame
256       {
257         redraw = TRUE;
258       }
259
260       if (redraw)
261       {
262         int sx = x * StretchWidth;
263         int sy = y * StretchWidth;
264
265 #if 0
266         printf("::: REDRAW (%d, %d): %d, %d\n", x, y, graphic, sync_frame);
267 #endif
268
269         StretchedSprites.BltImg(sx, sy, graphic, sync_frame);
270
271 #if 1
272         num_redrawn++;
273 #endif
274       }
275     }
276   }
277
278 #if 0
279   printf("::: FRAME %d: %d redrawn\n", FrameCounter, num_redrawn);
280 #endif
281 }
282
283 void UpdatePlayfield_TMP()
284 {
285   int x1 = mScrollX_last / TILEX - 2;
286   int y1 = mScrollY_last / TILEY - 2;
287   int x2 = mScrollX_last / TILEX + (SCR_FIELDX - 1) + 2;
288   int y2 = mScrollY_last / TILEY + (SCR_FIELDY - 1) + 2;
289   int x, y;
290
291   for (y = DisplayMinY; y <= DisplayMaxY; y++)
292   {
293     for (x = DisplayMinX; x <= DisplayMaxX; x++)
294     {
295       if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
296       {
297         int sx = x - x1;
298         int sy = y - y1;
299         int tsi = GetSI(x, y);
300         long id = ((PlayField16[tsi]) |
301                    (PlayField8[tsi] << 16) |
302                    (DisPlayField[tsi] << 24));
303         boolean redraw_screen_tile = (ScreenBuffer[sx][sy] != id);
304
305 #if 0
306         if (LowByte(PlayField16[tsi]) == fiMurphy)
307           continue;
308 #endif
309
310         if (redraw_screen_tile)
311         {
312 #if 0
313           DrawFieldNoAnimated(x, y);
314           DrawFieldAnimated(x, y);
315 #endif
316
317           ScreenBuffer[sx][sy] = id;
318
319           redraw[sx][sy] = TRUE;
320           redraw_tiles++;
321         }
322       }
323     }
324   }
325 }
326
327 void OLD_UpdatePlayfield()
328 {
329   int x, y;
330   int left = mScrollX / TILEX;
331   int top  = mScrollY / TILEY;
332
333   for (y = top; y < top + MAX_BUF_YSIZE; y++)
334   {
335     for (x = left; x < left + MAX_BUF_XSIZE; x++)
336     {
337       int sx = x % MAX_BUF_XSIZE;
338       int sy = y % MAX_BUF_YSIZE;
339       int tsi = GetSI(x, y);
340       long id = ((PlayField16[tsi]) |
341                  (PlayField8[tsi] << 16) |
342                  (DisPlayField[tsi] << 24));
343       boolean redraw_screen_tile = (ScreenBuffer[sx][sy] != id);
344
345       if (redraw_screen_tile)
346       {
347         DrawFieldNoAnimated(x, y);
348         DrawFieldAnimated(x, y);
349
350         ScreenBuffer[sx][sy] = id;
351
352         redraw[sx][sy] = TRUE;
353         redraw_tiles++;
354       }
355     }
356   }
357 }
358
359 void DDScrollBuffer_Let_DestXOff(long NewVal)
360 {
361   mDestXOff = NewVal;
362 }
363
364 long DDScrollBuffer_Get_DestXOff()
365 {
366   long DestXOff;
367
368   DestXOff = mDestXOff;
369
370   return DestXOff;
371 }
372
373 void DDScrollBuffer_Let_DestYOff(long NewVal)
374 {
375   mDestYOff = NewVal;
376 }
377
378 long DDScrollBuffer_Get_DestYOff()
379 {
380   long DestYOff;
381
382   DestYOff = mDestYOff;
383
384   return DestYOff;
385 }
386
387 DirectDrawSurface7 DDScrollBuffer_Get_Surface()
388 {
389   DirectDrawSurface7 Surface;
390
391   Surface = Buffer;
392
393   return Surface;
394 }
395
396 long DDScrollBuffer_Get_Width()
397 {
398   long Width;
399
400   Width = mWidth;
401
402   return Width;
403 }
404
405 int DDScrollBuffer_Get_Height()
406 {
407   int Height;
408
409   Height = mHeight;
410
411   return Height;
412 }
413
414 #if 0
415
416 long DDScrollBuffer_CreateAtSize(long Width, long Height, long hWndViewPort)
417 {
418   long CreateAtSize;
419
420   DDSURFACEDESC2 SD;
421
422   CreateAtSize = 0;
423   mhWnd = hWndViewPort;
424   // Create ScrollBuffer:
425   {
426     SD.lFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
427     SD.ddsCaps.lCaps = DDSCAPS_VIDEOMEMORY;
428     // SD.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
429     SD.LWidth = Width;
430     SD.LHeight = Height;
431   }
432
433   // --- On Error Resume Next
434   Buffer = DDraw.CreateSurface(SD);
435   if (Err.Number != 0)
436     return CreateAtSize;
437
438   // --- On Error GoTo 0
439
440   mWidth = Width;
441   mHeight = Height;
442   mScrollX = 0;
443   mScrollY = 0;
444   CreateAtSize = -1;
445
446   return CreateAtSize;
447 }
448
449 void DDScrollBuffer_Cls(int BackColor)
450 {
451   RECT EmptyRect;
452
453   if (NoDisplayFlag)
454     return;
455
456   Buffer.BltColorFill(EmptyRect, BackColor);
457 }
458
459 #endif
460
461 /* copy the entire screen to the window at the scroll position */
462
463 void BlitScreenToBitmap_SP(Bitmap *target_bitmap)
464 {
465 #if 0
466   int px = 2 * TILEX + mScrollX % TILEX;
467   int py = 2 * TILEY + mScrollY % TILEY;
468 #else
469   int px = 2 * TILEX + (mScrollX - mScrollX_last) % TILEX;
470   int py = 2 * TILEY + (mScrollY - mScrollY_last) % TILEY;
471 #endif
472   int sx, sy, sxsize, sysize;
473
474 #if 0
475   if (mScrollX % TILEX != (mScrollX - mScrollX_last) % TILEX ||
476       mScrollY % TILEY != (mScrollY - mScrollY_last) % TILEY)
477     printf("::: %ld, %ld / %ld, %ld\n",
478            mScrollX, mScrollY, mScrollX_last, mScrollY_last);
479 #endif
480
481 #if 1
482   int xsize = SXSIZE;
483   int ysize = SYSIZE;
484   int full_xsize = (FieldWidth  - (menBorder.Checked ? 0 : 1)) * TILEX;
485   int full_ysize = (FieldHeight - (menBorder.Checked ? 0 : 1)) * TILEY;
486
487   sxsize = (full_xsize < xsize ? full_xsize : xsize);
488   sysize = (full_ysize < ysize ? full_ysize : ysize);
489   sx = SX + (full_xsize < xsize ? (xsize - full_xsize) / 2 : 0);
490   sy = SY + (full_ysize < ysize ? (ysize - full_ysize) / 2 : 0);
491 #endif
492
493 #if 0
494   {
495     static int mScrollX_tmp = -1;
496     static int mScrollY_tmp = -1;
497
498     if (mScrollX != mScrollX_tmp || mScrollY != mScrollY_tmp)
499     {
500       printf("::: %ld, %ld\n", mScrollX, mScrollY);
501
502       mScrollX_tmp = mScrollX;
503       mScrollY_tmp = mScrollY;
504     }
505   }
506 #endif
507
508 #if 0
509   {
510     static boolean x = 0;
511
512     if (x == 0)
513     {
514       printf("::: %d, %d (%d, %d) (%d, %d) [%ld, %ld] [%ld, %ld] \n",
515              sx, sy, xsize, ysize, full_xsize, full_ysize,
516              mScrollX, mScrollY, mScrollX_last, mScrollY_last);
517
518       x = 1;
519     }
520   }
521 #endif
522
523 #if 1
524   if (!menBorder.Checked)
525   {
526     px += TILEX / 2;
527     py += TILEY / 2;
528   }
529 #endif
530
531 #if 0
532   if (mScrollX >= 0 && mScrollX <= 16)
533   {
534     px -= mScrollX;
535   }
536 #if 0
537   else if (mScrollX >= 352 && mScrollX <= 368)
538   {
539     px -= mScrollX;
540   }
541 #endif
542   else if (mScrollX >= 16) // && mScrollX <= 352)
543   {
544     px -= TILEX / 2;
545   }
546 #endif
547
548 #if 0
549   /* !!! TEST ONLY !!! */
550   px = py = 0;
551   sx = sy = SX;
552 #endif
553
554   BlitBitmap(screenBitmap, target_bitmap, px, py, sxsize, sysize, sx, sy);
555 }
556
557 void OLD_BlitScreenToBitmap_SP(Bitmap *target_bitmap)
558 {
559   int x = mScrollX % (MAX_BUF_XSIZE * TILEX);
560   int y = mScrollY % (MAX_BUF_YSIZE * TILEY);
561
562   if (x < 2 * TILEX && y < 2 * TILEY)
563   {
564     BlitBitmap(screenBitmap, target_bitmap, x, y,
565                SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
566   }
567   else if (x < 2 * TILEX && y >= 2 * TILEY)
568   {
569     BlitBitmap(screenBitmap, target_bitmap, x, y,
570                SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
571                SX, SY);
572     BlitBitmap(screenBitmap, target_bitmap, x, 0,
573                SCR_FIELDX * TILEX, y - 2 * TILEY,
574                SX, SY + MAX_BUF_YSIZE * TILEY - y);
575   }
576   else if (x >= 2 * TILEX && y < 2 * TILEY)
577   {
578     BlitBitmap(screenBitmap, target_bitmap, x, y,
579                MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
580                SX, SY);
581     BlitBitmap(screenBitmap, target_bitmap, 0, y,
582                x - 2 * TILEX, SCR_FIELDY * TILEY,
583                SX + MAX_BUF_XSIZE * TILEX - x, SY);
584   }
585   else
586   {
587     BlitBitmap(screenBitmap, target_bitmap, x, y,
588                MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
589                SX, SY);
590     BlitBitmap(screenBitmap, target_bitmap, 0, y,
591                x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
592                SX + MAX_BUF_XSIZE * TILEX - x, SY);
593     BlitBitmap(screenBitmap, target_bitmap, x, 0,
594                MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
595                SX, SY + MAX_BUF_YSIZE * TILEY - y);
596     BlitBitmap(screenBitmap, target_bitmap, 0, 0,
597                x - 2 * TILEX, y - 2 * TILEY,
598                SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y);
599   }
600 }
601
602 void BackToFront_SP(void)
603 {
604   static boolean scrolling_last = FALSE;
605   int left = mScrollX / TILEX;
606   int top  = mScrollY / TILEY;
607   boolean scrolling = (mScrollX % TILEX != 0 || mScrollY % TILEY != 0);
608   int x, y;
609
610   SyncDisplay();
611
612   if (1 ||
613       redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last)
614   {
615 #if 1
616     BlitScreenToBitmap_SP(window);
617 #else
618     /* blit all (up to four) parts of the scroll buffer to the backbuffer */
619     BlitScreenToBitmap_SP(backbuffer);
620
621     /* blit the completely updated backbuffer to the window (in one blit) */
622     BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY);
623 #endif
624   }
625   else
626   {
627     for (x = 0; x < SCR_FIELDX; x++)
628     {
629       for (y = 0; y < SCR_FIELDY; y++)
630       {
631         int xx = (left + x) % MAX_BUF_XSIZE;
632         int yy = (top  + y) % MAX_BUF_YSIZE;
633
634         if (redraw[xx][yy])
635           BlitBitmap(screenBitmap, window,
636                      xx * TILEX, yy * TILEY, TILEX, TILEY,
637                      SX + x * TILEX, SY + y * TILEY);
638       }
639     }
640   }
641
642   FlushDisplay();
643
644   for (x = 0; x < MAX_BUF_XSIZE; x++)
645     for (y = 0; y < MAX_BUF_YSIZE; y++)
646       redraw[x][y] = FALSE;
647   redraw_tiles = 0;
648
649   scrolling_last = scrolling;
650 }
651
652
653 void DDScrollBuffer_Blt_Ext(Bitmap *target_bitmap)
654 {
655   MyRECT DR, SR;
656 #if 1
657   long tX, tY;
658 #else
659   long tX, tY, L;
660 #endif
661   int sX, sY;
662   // RECT ERect;
663   // long Restore;
664
665   if (NoDisplayFlag)
666     return;
667
668 #if 1
669   DR.left = 0;
670   DR.top = 0;
671   DR.right = SCR_FIELDX * TILEX;
672   DR.bottom = SCR_FIELDY * TILEY;
673 #else
674   // --- On Error GoTo BltEH
675   DirectX.GetWindowRect(mhWnd, DR);
676   // --- On Error GoTo 0
677 #endif
678
679   {
680     tX = (DR.right - DR.left) / Stretch;
681     tY = (DR.bottom - DR.top) / Stretch;
682   }
683
684   {
685     SR.left = mScrollX + mDestXOff;
686     SR.top = mScrollY + mDestYOff;
687
688     SR.right = SR.left + tX;
689     SR.bottom = SR.top + tY;
690
691     //    If mWidth < SR.right Then
692     //      SR.right = mWidth
693     //      DR.right = DR.left + Stretch * (SR.right - SR.left)
694     //    End If
695     //    If mHeight < SR.bottom Then
696     //      SR.bottom = mHeight
697     //      DR.bottom = DR.top + Stretch * (SR.bottom - SR.top)
698     //    End If
699     //    If (mScrollX + mDestXOff) < 0 Then
700     //      SR.left = 0
701     //      DR.left = DR.left - Stretch * (mScrollX + mDestXOff)
702     //    End If
703     //    If (mScrollY + mDestYOff) < 0 Then
704     //      SR.top = 0
705     //      DR.top = DR.top - Stretch * (mScrollY + mDestYOff)
706     //    End If
707   }
708
709 #if 1
710   SR.left = (SR.left < 0 ? 0 : SR.left);
711   SR.top  = (SR.top  < 0 ? 0 : SR.top);
712 #endif
713
714 #if 1
715   {
716     int full_xsize = (FieldWidth  - (menBorder.Checked ? 0 : 1)) * TILEX;
717     int full_ysize = (FieldHeight - (menBorder.Checked ? 0 : 1)) * TILEY;
718     int sxsize = SCR_FIELDX * TILEX;
719     int sysize = SCR_FIELDY * TILEY;
720
721     tX = (full_xsize < sxsize ? full_xsize : tX);
722     tY = (full_ysize < sysize ? full_ysize : tY);
723     sX = SX + (full_xsize < sxsize ? (sxsize - full_xsize) / 2 : 0);
724     sY = SY + (full_ysize < sysize ? (sysize - full_ysize) / 2 : 0);
725   }
726 #endif
727
728 #if 1
729   if (!menBorder.Checked)
730   {
731     SR.left += TILEX / 2;
732     SR.top  += TILEY / 2;
733   }
734 #endif
735
736 #if 1
737
738 #if 1
739   printf("::: DDScrollBuffer.c: DDScrollBuffer_Blt(): blit from %d, %d [%ld, %ld] [%ld, %ld] [%ld, %ld]\n",
740          SR.left, SR.top, mScrollX, mScrollY, mDestXOff, mDestYOff, tX, tY);
741 #endif
742
743 #if 0
744   /* !!! quick and dirty -- FIX THIS !!! */
745   if (tape.playing && tape.fast_forward &&
746       target_bitmap == window &&
747       (FrameCounter % 2) != 0)
748     printf("::: FrameCounter == %d\n", FrameCounter);
749 #endif
750
751 #if 1
752   SyncDisplay();
753 #endif
754
755 #if 1
756   BlitBitmap(screenBitmap, target_bitmap,
757              SR.left, SR.top, tX, tY, sX, sY);
758 #else
759   BlitBitmap(screenBitmap, target_bitmap,
760              SR.left, SR.top,
761              SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
762 #endif
763
764 #if 1
765   FlushDisplay();
766 #endif
767
768   return;
769
770 #endif
771
772   // DDraw.WaitForVerticalBlank DDWAITVB_BLOCKBEGIN, 0
773   if (IS_NOTHING(&Buffer, sizeof(Buffer)))
774     return;
775
776 #if 0
777   if (IS_NOTHING(&PrimarySurface, sizeof(PrimarySurface)))
778     return;
779 #endif
780
781 #if 0
782
783   L = PrimarySurface.Blt(DR, &Buffer, SR, DDBLT_WAIT);
784   if (L != DD_OK)
785   {
786     switch (L)
787     {
788 #if 0
789       case DDERR_GENERIC:
790         Debug.Assert(False);
791         break;
792
793       case DDERR_INVALIDCLIPLIST:
794         Debug.Assert(False);
795         break;
796
797       case DDERR_INVALIDOBJECT:
798         Debug.Assert(False);
799         break;
800
801       case DDERR_INVALIDPARAMS:
802         Debug.Assert(False);
803         break;
804
805       case DDERR_INVALIDRECT:
806         Debug.Assert(False);
807         break;
808
809       case DDERR_NOALPHAHW:
810         Debug.Assert(False);
811         break;
812
813       case DDERR_NOBLTHW:
814         Debug.Assert(False);
815         break;
816
817       case DDERR_NOCLIPLIST:
818         Debug.Assert(False);
819         break;
820
821       case DDERR_NODDROPSHW:
822         Debug.Assert(False);
823         break;
824
825       case DDERR_NOMIRRORHW:
826         Debug.Assert(False);
827         break;
828
829       case DDERR_NORASTEROPHW:
830         Debug.Assert(False);
831         break;
832
833       case DDERR_NOROTATIONHW:
834         Debug.Assert(False);
835         break;
836
837       case DDERR_NOSTRETCHHW:
838         Debug.Assert(False);
839         break;
840
841       case DDERR_NOZBUFFERHW:
842         Debug.Assert(False);
843         break;
844
845       case DDERR_SURFACEBUSY:
846         Debug.Assert(False);
847         break;
848 #endif
849
850 #if 0
851       case DDERR_SURFACELOST:
852         DDraw.RestoreAllSurfaces();
853         if (! PrimarySurface.isLost())
854         {
855           subDisplayLevel();
856           // Blt();
857         }
858
859         // RestorePrimarySurface
860         // ClipToWindow 0
861         break;
862 #endif
863
864 #if 0
865       case DDERR_UNSUPPORTED:
866         Debug.Assert(False);
867         break;
868
869       case DDERR_WASSTILLDRAWING:
870         Debug.Assert(False);
871         break;
872
873       default:
874         Debug.Assert(False);
875         break;
876 #endif
877     }
878   }
879
880 #endif
881
882 #if 0
883   //  Buffer.UpdateOverlay SR, PrimarySurface, DR, DDOVER_SHOW
884   if (EditFlag)
885     FMark.RefreshMarker();
886 #endif
887
888   // BltEH:
889 }
890
891 void DDScrollBuffer_Blt()
892 {
893 #if 1
894
895 #if 1
896   BackToFront_SP();
897 #else
898   /* !!! TEST ONLY !!! */
899   BlitBitmap(screenBitmap, window,
900              0, 0, SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
901 #endif
902
903 #else
904   DDScrollBuffer_Blt_Ext(window);
905 #endif
906 }
907
908 void DDScrollBuffer_ScrollTo(int X, int Y)
909 {
910   if (NoDisplayFlag)
911     return;
912
913   X = X / Stretch;
914   Y = Y / Stretch;
915   mScrollX = X;
916   mScrollY = Y;
917   ScrollX = mScrollX;
918   ScrollY = mScrollY;
919
920 #if 0
921   printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTo():  mScroll: %ld, %ld [%d, %d]\n",
922          mScrollX, mScrollY, X, Y);
923 #endif
924
925 #if 1
926   ScrollPlayfieldIfNeeded();
927 #endif
928 }
929
930 void DDScrollBuffer_ScrollTowards(int X, int Y, double Step)
931 {
932   double dx, dY, r;
933
934   if (NoDisplayFlag)
935     return;
936
937 #if 0
938   printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (1) mScroll: %ld, %ld [%d, %d, %f, %f]\n",
939          mScrollX, mScrollY, X, Y, Step, Stretch);
940 #endif
941
942   X = X / Stretch;
943   Y = Y / Stretch;
944   dx = X - mScrollX;
945   dY = Y - mScrollY;
946   r = Sqr(dx * dx + dY * dY);
947   if (r == 0) // we are there already
948     return;
949
950   if (Step < r)
951     r = Step / r;
952   else
953     r = 1;
954
955   mScrollX = mScrollX + dx * r;
956   mScrollY = mScrollY + dY * r;
957   ScrollX = mScrollX;
958   ScrollY = mScrollY;
959
960 #if 0
961   printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (2) mScroll: %ld, %ld [%d, %d, %f]\n",
962          mScrollX, mScrollY, X, Y, Step);
963 #endif
964
965 #if 1
966   ScrollPlayfieldIfNeeded();
967 #endif
968 }
969
970 void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS)
971 {
972   double dx, dY;
973 #if 0
974   TickCountObject Tick;
975 #endif
976   long dT, StepCount;
977   double T, tStep;
978   long oldX, oldY, maxD;
979   static boolean AlreadyRunning = False;
980
981 #if 0
982   printf(":a: %d, %d [%d, %d] [%d, %d] [%d, %d]\n",
983          mScrollX, mScrollY,
984          mScrollX_last, mScrollY_last,
985          ScreenScrollXPos, ScreenScrollYPos,
986          ScrollX, ScrollY);
987 #endif
988
989   if (NoDisplayFlag)
990     return;
991
992   if (AlreadyRunning)
993   {
994     return;
995   }
996
997   AlreadyRunning = True;
998   X = X / Stretch;
999   Y = Y / Stretch;
1000   dx = X - mScrollX;
1001   dY = Y - mScrollY;
1002   maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dx));
1003   StepCount = FPS * (TimeMS / (double)1000);
1004   if (StepCount > maxD)
1005     StepCount = maxD;
1006
1007   if (StepCount == 0)
1008     StepCount = 1;
1009
1010   dT = 1000 / FPS;
1011   tStep = (double)1 / StepCount;
1012   oldX = mScrollX;
1013   oldY = mScrollY;
1014   // R = Sqr(dX * dX + dY * dY)
1015   // If R = 0 Then Exit Sub 'we are there already
1016   for (T = (double)tStep; T <= (double)1; T += tStep)
1017   {
1018     if (UserDragFlag)
1019       goto SoftScrollEH;
1020
1021     // If Claim Then Exit For
1022
1023 #if 0
1024     Tick.DelayMS(dT, False);
1025 #endif
1026
1027     mScrollX = oldX + T * dx;
1028     mScrollY = oldY + T * dY;
1029     ScrollX = mScrollX;
1030     ScrollY = mScrollY;
1031
1032 #if 0
1033     Blt();
1034 #endif
1035   }
1036
1037 #if 0
1038   printf(":x: %d, %d [%d, %d] [%d, %d] [%d, %d]\n",
1039          mScrollX, mScrollY,
1040          mScrollX_last, mScrollY_last,
1041          ScreenScrollXPos, ScreenScrollYPos,
1042          ScrollX, ScrollY);
1043 #endif
1044
1045   if (UserDragFlag)
1046     goto SoftScrollEH;
1047
1048 #if 0
1049   Tick.DelayMS(dT, False);
1050 #endif
1051
1052   mScrollX = X;
1053   mScrollY = Y;
1054   ScrollX = mScrollX;
1055   ScrollY = mScrollY;
1056
1057 #if 0
1058   Blt();
1059 #endif
1060
1061 SoftScrollEH:
1062   AlreadyRunning = False;
1063
1064 #if 0
1065   printf("::: DDScrollBuffer.c: DDScrollBuffer_SoftScrollTo(): mScroll: %ld, %ld\n",
1066          mScrollX, mScrollY);
1067 #endif
1068
1069 #if 0
1070   printf(":y: %d, %d [%d, %d] [%d, %d] [%d, %d]\n",
1071          mScrollX, mScrollY,
1072          mScrollX_last, mScrollY_last,
1073          ScreenScrollXPos, ScreenScrollYPos,
1074          ScrollX, ScrollY);
1075 #endif
1076
1077 #if 1
1078   ScrollPlayfieldIfNeeded();
1079 #endif
1080
1081 #if 0
1082   printf(":z: %d, %d [%d, %d] [%d, %d] [%d, %d]\n",
1083          mScrollX, mScrollY,
1084          mScrollX_last, mScrollY_last,
1085          ScreenScrollXPos, ScreenScrollYPos,
1086          ScrollX, ScrollY);
1087 #endif
1088 }