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