rnd-20091112-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 mDestXOff, mDestYOff;
35
36 long ScreenBuffer[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
37 boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
38
39
40 void UpdatePlayfield()
41 {
42   int x, y;
43   int sx1 = mScrollX - TILEX;
44   int sy1 = mScrollY - TILEY;
45   int sx2 = mScrollX + SXSIZE + TILEX;
46   int sy2 = mScrollY + SYSIZE + TILEY;
47   int x1 = sx1 / TILEX;
48   int y1 = sy1 / TILEY;
49   int x2 = sx2 / TILEX;
50   int y2 = sy2 / TILEY;
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         int sx = x - x1;
59         int sy = y - y1;
60         int tsi = GetSI(x, y);
61         long id = ((PlayField16[tsi]) |
62                    (PlayField8[tsi] << 16) |
63                    (DisPlayField[tsi] << 24));
64         boolean redraw_screen_tile = (ScreenBuffer[sx][sy] != id);
65
66         if (redraw_screen_tile)
67         {
68           DrawFieldNoAnimated(x, y);
69           DrawFieldAnimated(x, y);
70
71           ScreenBuffer[sx][sy] = id;
72
73           redraw[sx][sy] = TRUE;
74           redraw_tiles++;
75         }
76       }
77     }
78   }
79 }
80
81 void OLD_UpdatePlayfield()
82 {
83   int x, y;
84   int left = mScrollX / TILEX;
85   int top  = mScrollY / TILEY;
86
87   for (y = top; y < top + MAX_BUF_YSIZE; y++)
88   {
89     for (x = left; x < left + MAX_BUF_XSIZE; x++)
90     {
91       int sx = x % MAX_BUF_XSIZE;
92       int sy = y % MAX_BUF_YSIZE;
93       int tsi = GetSI(x, y);
94       long id = ((PlayField16[tsi]) |
95                  (PlayField8[tsi] << 16) |
96                  (DisPlayField[tsi] << 24));
97       boolean redraw_screen_tile = (ScreenBuffer[sx][sy] != id);
98
99       if (redraw_screen_tile)
100       {
101         DrawFieldNoAnimated(x, y);
102         DrawFieldAnimated(x, y);
103
104         ScreenBuffer[sx][sy] = id;
105
106         redraw[sx][sy] = TRUE;
107         redraw_tiles++;
108       }
109     }
110   }
111 }
112
113 void DDScrollBuffer_Let_DestXOff(long NewVal)
114 {
115   mDestXOff = NewVal;
116 }
117
118 long DDScrollBuffer_Get_DestXOff()
119 {
120   long DestXOff;
121
122   DestXOff = mDestXOff;
123
124   return DestXOff;
125 }
126
127 void DDScrollBuffer_Let_DestYOff(long NewVal)
128 {
129   mDestYOff = NewVal;
130 }
131
132 long DDScrollBuffer_Get_DestYOff()
133 {
134   long DestYOff;
135
136   DestYOff = mDestYOff;
137
138   return DestYOff;
139 }
140
141 DirectDrawSurface7 DDScrollBuffer_Get_Surface()
142 {
143   DirectDrawSurface7 Surface;
144
145   Surface = Buffer;
146
147   return Surface;
148 }
149
150 long DDScrollBuffer_Get_Width()
151 {
152   long Width;
153
154   Width = mWidth;
155
156   return Width;
157 }
158
159 int DDScrollBuffer_Get_Height()
160 {
161   int Height;
162
163   Height = mHeight;
164
165   return Height;
166 }
167
168 long DDScrollBuffer_CreateAtSize(long Width, long Height, long hWndViewPort)
169 {
170   long CreateAtSize;
171
172   DDSURFACEDESC2 SD;
173
174   CreateAtSize = 0;
175   mhWnd = hWndViewPort;
176   // Create ScrollBuffer:
177   {
178     SD.lFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
179     SD.ddsCaps.lCaps = DDSCAPS_VIDEOMEMORY;
180     // SD.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
181     SD.LWidth = Width;
182     SD.LHeight = Height;
183   }
184
185   // --- On Error Resume Next
186   Buffer = DDraw.CreateSurface(SD);
187   if (Err.Number != 0)
188     return CreateAtSize;
189
190   // --- On Error GoTo 0
191
192   mWidth = Width;
193   mHeight = Height;
194   mScrollX = 0;
195   mScrollY = 0;
196   CreateAtSize = -1;
197
198   return CreateAtSize;
199 }
200
201 void DDScrollBuffer_Cls(int BackColor)
202 {
203   RECT EmptyRect;
204
205   if (NoDisplayFlag)
206     return;
207
208   Buffer.BltColorFill(EmptyRect, BackColor);
209 }
210
211
212 /* copy the entire screen to the window at the scroll position */
213
214 void BlitScreenToBitmap_SP(Bitmap *target_bitmap)
215 {
216   int sx = TILEX + mScrollX % TILEX;
217   int sy = TILEY + mScrollY % TILEY;
218
219   BlitBitmap(screenBitmap, target_bitmap, sx, sy,
220              SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
221 }
222
223 void OLD_BlitScreenToBitmap_SP(Bitmap *target_bitmap)
224 {
225   int x = mScrollX % (MAX_BUF_XSIZE * TILEX);
226   int y = mScrollY % (MAX_BUF_YSIZE * TILEY);
227
228   if (x < 2 * TILEX && y < 2 * TILEY)
229   {
230     BlitBitmap(screenBitmap, target_bitmap, x, y,
231                SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
232   }
233   else if (x < 2 * TILEX && y >= 2 * TILEY)
234   {
235     BlitBitmap(screenBitmap, target_bitmap, x, y,
236                SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
237                SX, SY);
238     BlitBitmap(screenBitmap, target_bitmap, x, 0,
239                SCR_FIELDX * TILEX, y - 2 * TILEY,
240                SX, SY + MAX_BUF_YSIZE * TILEY - y);
241   }
242   else if (x >= 2 * TILEX && y < 2 * TILEY)
243   {
244     BlitBitmap(screenBitmap, target_bitmap, x, y,
245                MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
246                SX, SY);
247     BlitBitmap(screenBitmap, target_bitmap, 0, y,
248                x - 2 * TILEX, SCR_FIELDY * TILEY,
249                SX + MAX_BUF_XSIZE * TILEX - x, SY);
250   }
251   else
252   {
253     BlitBitmap(screenBitmap, target_bitmap, x, y,
254                MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
255                SX, SY);
256     BlitBitmap(screenBitmap, target_bitmap, 0, y,
257                x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
258                SX + MAX_BUF_XSIZE * TILEX - x, SY);
259     BlitBitmap(screenBitmap, target_bitmap, x, 0,
260                MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
261                SX, SY + MAX_BUF_YSIZE * TILEY - y);
262     BlitBitmap(screenBitmap, target_bitmap, 0, 0,
263                x - 2 * TILEX, y - 2 * TILEY,
264                SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y);
265   }
266 }
267
268 void BackToFront_SP(void)
269 {
270   static boolean scrolling_last = FALSE;
271   int left = mScrollX / TILEX;
272   int top  = mScrollY / TILEY;
273   boolean scrolling = (mScrollX % TILEX != 0 || mScrollY % TILEY != 0);
274   int x, y;
275
276   SyncDisplay();
277
278   if (1 ||
279       redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last)
280   {
281     /* blit all (up to four) parts of the scroll buffer to the backbuffer */
282     BlitScreenToBitmap_SP(backbuffer);
283
284     /* blit the completely updated backbuffer to the window (in one blit) */
285     BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY);
286   }
287   else
288   {
289     for (x = 0; x < SCR_FIELDX; x++)
290     {
291       for (y = 0; y < SCR_FIELDY; y++)
292       {
293         int xx = (left + x) % MAX_BUF_XSIZE;
294         int yy = (top  + y) % MAX_BUF_YSIZE;
295
296         if (redraw[xx][yy])
297           BlitBitmap(screenBitmap, window,
298                      xx * TILEX, yy * TILEY, TILEX, TILEY,
299                      SX + x * TILEX, SY + y * TILEY);
300       }
301     }
302   }
303
304   FlushDisplay();
305
306   for (x = 0; x < MAX_BUF_XSIZE; x++)
307     for (y = 0; y < MAX_BUF_YSIZE; y++)
308       redraw[x][y] = FALSE;
309   redraw_tiles = 0;
310
311   scrolling_last = scrolling;
312 }
313
314
315 void DDScrollBuffer_Blt_Ext(Bitmap *target_bitmap)
316 {
317   RECT DR, SR;
318   long tX, tY, L;
319   int sX, sY;
320   // RECT ERect;
321   // long Restore;
322
323   if (NoDisplayFlag)
324     return;
325
326 #if 1
327   DR.left = 0;
328   DR.top = 0;
329   DR.right = SCR_FIELDX * TILEX;
330   DR.bottom = SCR_FIELDY * TILEY;
331 #else
332   // --- On Error GoTo BltEH
333   DirectX.GetWindowRect(mhWnd, DR);
334   // --- On Error GoTo 0
335 #endif
336
337   {
338     tX = (DR.right - DR.left) / Stretch;
339     tY = (DR.bottom - DR.top) / Stretch;
340   }
341
342   {
343     SR.left = mScrollX + mDestXOff;
344     SR.top = mScrollY + mDestYOff;
345
346     SR.right = SR.left + tX;
347     SR.bottom = SR.top + tY;
348
349     //    If mWidth < SR.right Then
350     //      SR.right = mWidth
351     //      DR.right = DR.left + Stretch * (SR.right - SR.left)
352     //    End If
353     //    If mHeight < SR.bottom Then
354     //      SR.bottom = mHeight
355     //      DR.bottom = DR.top + Stretch * (SR.bottom - SR.top)
356     //    End If
357     //    If (mScrollX + mDestXOff) < 0 Then
358     //      SR.left = 0
359     //      DR.left = DR.left - Stretch * (mScrollX + mDestXOff)
360     //    End If
361     //    If (mScrollY + mDestYOff) < 0 Then
362     //      SR.top = 0
363     //      DR.top = DR.top - Stretch * (mScrollY + mDestYOff)
364     //    End If
365   }
366
367 #if 1
368   SR.left = (SR.left < 0 ? 0 : SR.left);
369   SR.top  = (SR.top  < 0 ? 0 : SR.top);
370 #endif
371
372 #if 1
373   {
374     int full_xsize = (FieldWidth  - (menBorder.Checked ? 0 : 1)) * TILEX;
375     int full_ysize = (FieldHeight - (menBorder.Checked ? 0 : 1)) * TILEY;
376     int sxsize = SCR_FIELDX * TILEX;
377     int sysize = SCR_FIELDY * TILEY;
378
379     tX = (full_xsize < sxsize ? full_xsize : tX);
380     tY = (full_ysize < sysize ? full_ysize : tY);
381     sX = SX + (full_xsize < sxsize ? (sxsize - full_xsize) / 2 : 0);
382     sY = SY + (full_ysize < sysize ? (sysize - full_ysize) / 2 : 0);
383   }
384 #endif
385
386 #if 1
387   if (!menBorder.Checked)
388   {
389     SR.left += 16;
390     SR.top  += 16;
391   }
392 #endif
393
394 #if 1
395
396 #if 1
397   printf("::: DDScrollBuffer.c: DDScrollBuffer_Blt(): blit from %d, %d [%ld, %ld] [%ld, %ld] [%ld, %ld]\n",
398          SR.left, SR.top, mScrollX, mScrollY, mDestXOff, mDestYOff, tX, tY);
399 #endif
400
401 #if 0
402   /* !!! quick and dirty -- FIX THIS !!! */
403   if (tape.playing && tape.fast_forward &&
404       target_bitmap == window &&
405       (FrameCounter % 2) != 0)
406     printf("::: FrameCounter == %d\n", FrameCounter);
407 #endif
408
409 #if 1
410   SyncDisplay();
411 #endif
412
413 #if 1
414   BlitBitmap(screenBitmap, target_bitmap,
415              SR.left, SR.top, tX, tY, sX, sY);
416 #else
417   BlitBitmap(screenBitmap, target_bitmap,
418              SR.left, SR.top,
419              SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
420 #endif
421
422 #if 1
423   FlushDisplay();
424 #endif
425
426   return;
427
428 #endif
429
430   // DDraw.WaitForVerticalBlank DDWAITVB_BLOCKBEGIN, 0
431   if (IS_NOTHING(&Buffer, sizeof(Buffer)))
432     return;
433
434   if (IS_NOTHING(&PrimarySurface, sizeof(PrimarySurface)))
435     return;
436
437   L = PrimarySurface.Blt(DR, &Buffer, SR, DDBLT_WAIT);
438   if (L != DD_OK)
439   {
440     switch (L)
441     {
442 #if 0
443       case DDERR_GENERIC:
444         Debug.Assert(False);
445         break;
446
447       case DDERR_INVALIDCLIPLIST:
448         Debug.Assert(False);
449         break;
450
451       case DDERR_INVALIDOBJECT:
452         Debug.Assert(False);
453         break;
454
455       case DDERR_INVALIDPARAMS:
456         Debug.Assert(False);
457         break;
458
459       case DDERR_INVALIDRECT:
460         Debug.Assert(False);
461         break;
462
463       case DDERR_NOALPHAHW:
464         Debug.Assert(False);
465         break;
466
467       case DDERR_NOBLTHW:
468         Debug.Assert(False);
469         break;
470
471       case DDERR_NOCLIPLIST:
472         Debug.Assert(False);
473         break;
474
475       case DDERR_NODDROPSHW:
476         Debug.Assert(False);
477         break;
478
479       case DDERR_NOMIRRORHW:
480         Debug.Assert(False);
481         break;
482
483       case DDERR_NORASTEROPHW:
484         Debug.Assert(False);
485         break;
486
487       case DDERR_NOROTATIONHW:
488         Debug.Assert(False);
489         break;
490
491       case DDERR_NOSTRETCHHW:
492         Debug.Assert(False);
493         break;
494
495       case DDERR_NOZBUFFERHW:
496         Debug.Assert(False);
497         break;
498
499       case DDERR_SURFACEBUSY:
500         Debug.Assert(False);
501         break;
502 #endif
503
504       case DDERR_SURFACELOST:
505         DDraw.RestoreAllSurfaces();
506         if (! PrimarySurface.isLost())
507         {
508           subDisplayLevel();
509           // Blt();
510         }
511
512         // RestorePrimarySurface
513         // ClipToWindow 0
514         break;
515
516 #if 0
517       case DDERR_UNSUPPORTED:
518         Debug.Assert(False);
519         break;
520
521       case DDERR_WASSTILLDRAWING:
522         Debug.Assert(False);
523         break;
524
525       default:
526         Debug.Assert(False);
527         break;
528 #endif
529     }
530   }
531
532 #if 0
533   //  Buffer.UpdateOverlay SR, PrimarySurface, DR, DDOVER_SHOW
534   if (EditFlag)
535     FMark.RefreshMarker();
536 #endif
537
538   // BltEH:
539 }
540
541 void DDScrollBuffer_Blt()
542 {
543 #if 1
544
545 #if 1
546   BackToFront_SP();
547 #else
548   /* !!! TEST ONLY !!! */
549   BlitBitmap(screenBitmap, window,
550              0, 0, SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
551 #endif
552
553 #else
554   DDScrollBuffer_Blt_Ext(window);
555 #endif
556 }
557
558 void DDScrollBuffer_ScrollTo(int X, int Y)
559 {
560   if (NoDisplayFlag)
561     return;
562
563   X = X / Stretch;
564   Y = Y / Stretch;
565   mScrollX = X;
566   mScrollY = Y;
567   ScrollX = mScrollX;
568   ScrollY = mScrollY;
569
570 #if 0
571   printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTo():  mScroll: %ld, %ld [%d, %d]\n",
572          mScrollX, mScrollY, X, Y);
573 #endif
574 }
575
576 void DDScrollBuffer_ScrollTowards(int X, int Y, double Step)
577 {
578   double dx, dY, r;
579
580   if (NoDisplayFlag)
581     return;
582
583 #if 0
584   printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (1) mScroll: %ld, %ld [%d, %d, %f]\n",
585          mScrollX, mScrollY, X, Y, Step);
586 #endif
587
588   X = X / Stretch;
589   Y = Y / Stretch;
590   dx = X - mScrollX;
591   dY = Y - mScrollY;
592   r = Sqr(dx * dx + dY * dY);
593   if (r == 0) // we are there already
594     return;
595
596   if (Step < r)
597     r = Step / r;
598   else
599     r = 1;
600
601   mScrollX = mScrollX + dx * r;
602   mScrollY = mScrollY + dY * r;
603   ScrollX = mScrollX;
604   ScrollY = mScrollY;
605
606 #if 0
607   printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (2) mScroll: %ld, %ld [%d, %d, %f]\n",
608          mScrollX, mScrollY, X, Y, Step);
609 #endif
610 }
611
612 void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS)
613 {
614   double dx, dY;
615 #if 0
616   TickCountObject Tick;
617 #endif
618   long dT, StepCount;
619   double T, tStep;
620   long oldX, oldY, maxD;
621   static boolean AlreadyRunning = False;
622
623   if (NoDisplayFlag)
624     return;
625
626   if (AlreadyRunning)
627   {
628     return;
629   }
630
631   AlreadyRunning = True;
632   X = X / Stretch;
633   Y = Y / Stretch;
634   dx = X - mScrollX;
635   dY = Y - mScrollY;
636   maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dx));
637   StepCount = FPS * (TimeMS / (double)1000);
638   if (StepCount > maxD)
639     StepCount = maxD;
640
641   if (StepCount == 0)
642     StepCount = 1;
643
644   dT = 1000 / FPS;
645   tStep = (double)1 / StepCount;
646   oldX = mScrollX;
647   oldY = mScrollY;
648   // R = Sqr(dX * dX + dY * dY)
649   // If R = 0 Then Exit Sub 'we are there already
650   for (T = (double)tStep; T <= (double)1; T += tStep)
651   {
652     if (UserDragFlag)
653       goto SoftScrollEH;
654
655     // If Claim Then Exit For
656
657 #if 0
658     Tick.DelayMS(dT, False);
659 #endif
660
661     mScrollX = oldX + T * dx;
662     mScrollY = oldY + T * dY;
663     ScrollX = mScrollX;
664     ScrollY = mScrollY;
665     // Blt();
666   }
667
668   if (UserDragFlag)
669     goto SoftScrollEH;
670
671 #if 0
672   Tick.DelayMS(dT, False);
673 #endif
674
675   mScrollX = X;
676   mScrollY = Y;
677   ScrollX = mScrollX;
678   ScrollY = mScrollY;
679   // Blt();
680
681 SoftScrollEH:
682   AlreadyRunning = False;
683
684 #if 0
685   printf("::: DDScrollBuffer.c: DDScrollBuffer_SoftScrollTo(): mScroll: %ld, %ld\n",
686          mScrollX, mScrollY);
687 #endif
688 }