1 // ----------------------------------------------------------------------------
3 // ----------------------------------------------------------------------------
5 #include "DDScrollBuffer.h"
10 // --- VERSION 1.0 CLASS
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
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;
25 // --- Option Explicit
27 // needs reference to: DirectX7 for Visual Basic Type Library
29 DirectDrawSurface7 Buffer;
30 DirectDrawSurface7 mPrimary;
33 long mScrollX, mScrollY;
34 long mScrollX_last, mScrollY_last;
35 long mDestXOff, mDestYOff;
37 long ScreenBuffer[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
38 boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
43 static void ScrollPlayfield()
45 int sx_last = mScrollX_last / TILEX;
46 int sy_last = mScrollY_last / TILEY;
47 int sx = mScrollX / TILEX;
48 int sy = mScrollY / TILEY;
49 int dx = (sx < sx_last ? +1 : sx > sx_last ? -1 : 0);
50 int dy = (sy < sy_last ? +1 : sy > sy_last ? -1 : 0);
52 int sx1 = mScrollX - TILEX;
53 int sy1 = mScrollY - TILEY;
54 int sx2 = mScrollX + SXSIZE + TILEX;
55 int sy2 = mScrollY + SYSIZE + TILEY;
61 int buf_xsize = SCR_FIELDX + 2;
62 int buf_ysize = SCR_FIELDY + 2;
64 int buf_xsize = MAX_BUF_XSIZE;
65 int buf_ysize = MAX_BUF_YSIZE;
68 BlitBitmap(screenBitmap, screenBitmap,
71 (MAX_BUF_XSIZE * TILEX) - TILEX * (dx != 0),
72 (MAX_BUF_YSIZE * TILEY) - TILEY * (dy != 0),
76 /* when scrolling the whole playfield, do not redraw single tiles */
77 for (x = 0; x < MAX_BUF_XSIZE; x++)
78 for (y = 0; y < MAX_BUF_YSIZE; y++)
82 for (y = DisplayMinY; y <= DisplayMaxY; y++)
84 for (x = DisplayMinX; x <= DisplayMaxX; x++)
86 if (x >= x1 && x < x2 && y >= y1 && y < y2)
90 int tsi = GetSI(x, y);
91 long id = ((PlayField16[tsi]) |
92 (PlayField8[tsi] << 16) |
93 (DisPlayField[tsi] << 24));
97 printf("::: [%d] %d [%d, %d] [%d]\n", dx, sx, x, y, buf_xsize);
99 if (sx == 0 || sx == MAX_BUF_XSIZE - 1)
100 printf("::: %d, %d\n", dx, sx);
104 if ((dx == -1 && sx == buf_xsize - 1) ||
105 (dx == +1 && sx == 0) ||
106 (dy == -1 && sy == buf_ysize - 1) ||
107 (dy == +1 && sy == 0))
109 printf("::: %d, %d\n", sx, sy);
113 DrawFieldNoAnimated(x, y);
114 DrawFieldAnimated(x, y);
119 ScreenBuffer[sx][sy] = id;
125 static void ScrollPlayfieldIfNeededExt(boolean reset)
127 int sx_last = mScrollX_last / TILEX;
128 int sy_last = mScrollY_last / TILEY;
129 int sx = mScrollX / TILEX;
130 int sy = mScrollY / TILEY;
131 boolean initialized = (mScrollX_last != -1 && mScrollY_last != -1);
142 if (mScrollX_last == -1 || mScrollY_last == -1)
144 mScrollX_last = mScrollX;
145 mScrollY_last = mScrollY;
151 if (initialized && (sx != sx_last || sy != sy_last))
154 mScrollX_last = mScrollX;
155 mScrollY_last = mScrollY;
158 static void ScrollPlayfieldIfNeeded()
160 ScrollPlayfieldIfNeededExt(FALSE);
163 void InitScrollPlayfield()
165 ScrollPlayfieldIfNeededExt(TRUE);
168 void UpdatePlayfield()
171 int sx1 = mScrollX - TILEX;
172 int sy1 = mScrollY - TILEY;
173 int sx2 = mScrollX + SXSIZE + TILEX;
174 int sy2 = mScrollY + SYSIZE + TILEY;
175 int x1 = sx1 / TILEX;
176 int y1 = sy1 / TILEY;
177 int x2 = sx2 / TILEX;
178 int y2 = sy2 / TILEY;
180 for (y = DisplayMinY; y <= DisplayMaxY; y++)
182 for (x = DisplayMinX; x <= DisplayMaxX; x++)
184 if (x >= x1 && x < x2 && y >= y1 && y < y2)
188 int tsi = GetSI(x, y);
189 long id = ((PlayField16[tsi]) |
190 (PlayField8[tsi] << 16) |
191 (DisPlayField[tsi] << 24));
192 boolean redraw_screen_tile = (ScreenBuffer[sx][sy] != id);
195 if (LowByte(PlayField16[tsi]) == fiMurphy)
199 if (redraw_screen_tile)
202 DrawFieldNoAnimated(x, y);
203 DrawFieldAnimated(x, y);
206 ScreenBuffer[sx][sy] = id;
208 redraw[sx][sy] = TRUE;
216 void OLD_UpdatePlayfield()
219 int left = mScrollX / TILEX;
220 int top = mScrollY / TILEY;
222 for (y = top; y < top + MAX_BUF_YSIZE; y++)
224 for (x = left; x < left + MAX_BUF_XSIZE; x++)
226 int sx = x % MAX_BUF_XSIZE;
227 int sy = y % MAX_BUF_YSIZE;
228 int tsi = GetSI(x, y);
229 long id = ((PlayField16[tsi]) |
230 (PlayField8[tsi] << 16) |
231 (DisPlayField[tsi] << 24));
232 boolean redraw_screen_tile = (ScreenBuffer[sx][sy] != id);
234 if (redraw_screen_tile)
236 DrawFieldNoAnimated(x, y);
237 DrawFieldAnimated(x, y);
239 ScreenBuffer[sx][sy] = id;
241 redraw[sx][sy] = TRUE;
248 void DDScrollBuffer_Let_DestXOff(long NewVal)
253 long DDScrollBuffer_Get_DestXOff()
257 DestXOff = mDestXOff;
262 void DDScrollBuffer_Let_DestYOff(long NewVal)
267 long DDScrollBuffer_Get_DestYOff()
271 DestYOff = mDestYOff;
276 DirectDrawSurface7 DDScrollBuffer_Get_Surface()
278 DirectDrawSurface7 Surface;
285 long DDScrollBuffer_Get_Width()
294 int DDScrollBuffer_Get_Height()
303 long DDScrollBuffer_CreateAtSize(long Width, long Height, long hWndViewPort)
310 mhWnd = hWndViewPort;
311 // Create ScrollBuffer:
313 SD.lFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
314 SD.ddsCaps.lCaps = DDSCAPS_VIDEOMEMORY;
315 // SD.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
320 // --- On Error Resume Next
321 Buffer = DDraw.CreateSurface(SD);
325 // --- On Error GoTo 0
336 void DDScrollBuffer_Cls(int BackColor)
343 Buffer.BltColorFill(EmptyRect, BackColor);
347 /* copy the entire screen to the window at the scroll position */
349 void BlitScreenToBitmap_SP(Bitmap *target_bitmap)
351 int sx = TILEX + mScrollX % TILEX;
352 int sy = TILEY + mScrollY % TILEY;
354 BlitBitmap(screenBitmap, target_bitmap, sx, sy,
355 SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
358 void OLD_BlitScreenToBitmap_SP(Bitmap *target_bitmap)
360 int x = mScrollX % (MAX_BUF_XSIZE * TILEX);
361 int y = mScrollY % (MAX_BUF_YSIZE * TILEY);
363 if (x < 2 * TILEX && y < 2 * TILEY)
365 BlitBitmap(screenBitmap, target_bitmap, x, y,
366 SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
368 else if (x < 2 * TILEX && y >= 2 * TILEY)
370 BlitBitmap(screenBitmap, target_bitmap, x, y,
371 SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
373 BlitBitmap(screenBitmap, target_bitmap, x, 0,
374 SCR_FIELDX * TILEX, y - 2 * TILEY,
375 SX, SY + MAX_BUF_YSIZE * TILEY - y);
377 else if (x >= 2 * TILEX && y < 2 * TILEY)
379 BlitBitmap(screenBitmap, target_bitmap, x, y,
380 MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
382 BlitBitmap(screenBitmap, target_bitmap, 0, y,
383 x - 2 * TILEX, SCR_FIELDY * TILEY,
384 SX + MAX_BUF_XSIZE * TILEX - x, SY);
388 BlitBitmap(screenBitmap, target_bitmap, x, y,
389 MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
391 BlitBitmap(screenBitmap, target_bitmap, 0, y,
392 x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
393 SX + MAX_BUF_XSIZE * TILEX - x, SY);
394 BlitBitmap(screenBitmap, target_bitmap, x, 0,
395 MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
396 SX, SY + MAX_BUF_YSIZE * TILEY - y);
397 BlitBitmap(screenBitmap, target_bitmap, 0, 0,
398 x - 2 * TILEX, y - 2 * TILEY,
399 SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y);
403 void BackToFront_SP(void)
405 static boolean scrolling_last = FALSE;
406 int left = mScrollX / TILEX;
407 int top = mScrollY / TILEY;
408 boolean scrolling = (mScrollX % TILEX != 0 || mScrollY % TILEY != 0);
414 redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last)
416 /* blit all (up to four) parts of the scroll buffer to the backbuffer */
417 BlitScreenToBitmap_SP(backbuffer);
419 /* blit the completely updated backbuffer to the window (in one blit) */
420 BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY);
424 for (x = 0; x < SCR_FIELDX; x++)
426 for (y = 0; y < SCR_FIELDY; y++)
428 int xx = (left + x) % MAX_BUF_XSIZE;
429 int yy = (top + y) % MAX_BUF_YSIZE;
432 BlitBitmap(screenBitmap, window,
433 xx * TILEX, yy * TILEY, TILEX, TILEY,
434 SX + x * TILEX, SY + y * TILEY);
441 for (x = 0; x < MAX_BUF_XSIZE; x++)
442 for (y = 0; y < MAX_BUF_YSIZE; y++)
443 redraw[x][y] = FALSE;
446 scrolling_last = scrolling;
450 void DDScrollBuffer_Blt_Ext(Bitmap *target_bitmap)
464 DR.right = SCR_FIELDX * TILEX;
465 DR.bottom = SCR_FIELDY * TILEY;
467 // --- On Error GoTo BltEH
468 DirectX.GetWindowRect(mhWnd, DR);
469 // --- On Error GoTo 0
473 tX = (DR.right - DR.left) / Stretch;
474 tY = (DR.bottom - DR.top) / Stretch;
478 SR.left = mScrollX + mDestXOff;
479 SR.top = mScrollY + mDestYOff;
481 SR.right = SR.left + tX;
482 SR.bottom = SR.top + tY;
484 // If mWidth < SR.right Then
486 // DR.right = DR.left + Stretch * (SR.right - SR.left)
488 // If mHeight < SR.bottom Then
489 // SR.bottom = mHeight
490 // DR.bottom = DR.top + Stretch * (SR.bottom - SR.top)
492 // If (mScrollX + mDestXOff) < 0 Then
494 // DR.left = DR.left - Stretch * (mScrollX + mDestXOff)
496 // If (mScrollY + mDestYOff) < 0 Then
498 // DR.top = DR.top - Stretch * (mScrollY + mDestYOff)
503 SR.left = (SR.left < 0 ? 0 : SR.left);
504 SR.top = (SR.top < 0 ? 0 : SR.top);
509 int full_xsize = (FieldWidth - (menBorder.Checked ? 0 : 1)) * TILEX;
510 int full_ysize = (FieldHeight - (menBorder.Checked ? 0 : 1)) * TILEY;
511 int sxsize = SCR_FIELDX * TILEX;
512 int sysize = SCR_FIELDY * TILEY;
514 tX = (full_xsize < sxsize ? full_xsize : tX);
515 tY = (full_ysize < sysize ? full_ysize : tY);
516 sX = SX + (full_xsize < sxsize ? (sxsize - full_xsize) / 2 : 0);
517 sY = SY + (full_ysize < sysize ? (sysize - full_ysize) / 2 : 0);
522 if (!menBorder.Checked)
532 printf("::: DDScrollBuffer.c: DDScrollBuffer_Blt(): blit from %d, %d [%ld, %ld] [%ld, %ld] [%ld, %ld]\n",
533 SR.left, SR.top, mScrollX, mScrollY, mDestXOff, mDestYOff, tX, tY);
537 /* !!! quick and dirty -- FIX THIS !!! */
538 if (tape.playing && tape.fast_forward &&
539 target_bitmap == window &&
540 (FrameCounter % 2) != 0)
541 printf("::: FrameCounter == %d\n", FrameCounter);
549 BlitBitmap(screenBitmap, target_bitmap,
550 SR.left, SR.top, tX, tY, sX, sY);
552 BlitBitmap(screenBitmap, target_bitmap,
554 SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
565 // DDraw.WaitForVerticalBlank DDWAITVB_BLOCKBEGIN, 0
566 if (IS_NOTHING(&Buffer, sizeof(Buffer)))
569 if (IS_NOTHING(&PrimarySurface, sizeof(PrimarySurface)))
572 L = PrimarySurface.Blt(DR, &Buffer, SR, DDBLT_WAIT);
582 case DDERR_INVALIDCLIPLIST:
586 case DDERR_INVALIDOBJECT:
590 case DDERR_INVALIDPARAMS:
594 case DDERR_INVALIDRECT:
598 case DDERR_NOALPHAHW:
606 case DDERR_NOCLIPLIST:
610 case DDERR_NODDROPSHW:
614 case DDERR_NOMIRRORHW:
618 case DDERR_NORASTEROPHW:
622 case DDERR_NOROTATIONHW:
626 case DDERR_NOSTRETCHHW:
630 case DDERR_NOZBUFFERHW:
634 case DDERR_SURFACEBUSY:
639 case DDERR_SURFACELOST:
640 DDraw.RestoreAllSurfaces();
641 if (! PrimarySurface.isLost())
647 // RestorePrimarySurface
652 case DDERR_UNSUPPORTED:
656 case DDERR_WASSTILLDRAWING:
668 // Buffer.UpdateOverlay SR, PrimarySurface, DR, DDOVER_SHOW
670 FMark.RefreshMarker();
676 void DDScrollBuffer_Blt()
683 /* !!! TEST ONLY !!! */
684 BlitBitmap(screenBitmap, window,
685 0, 0, SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
689 DDScrollBuffer_Blt_Ext(window);
693 void DDScrollBuffer_ScrollTo(int X, int Y)
706 printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTo(): mScroll: %ld, %ld [%d, %d]\n",
707 mScrollX, mScrollY, X, Y);
711 ScrollPlayfieldIfNeeded();
715 void DDScrollBuffer_ScrollTowards(int X, int Y, double Step)
723 printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (1) mScroll: %ld, %ld [%d, %d, %f]\n",
724 mScrollX, mScrollY, X, Y, Step);
731 r = Sqr(dx * dx + dY * dY);
732 if (r == 0) // we are there already
740 mScrollX = mScrollX + dx * r;
741 mScrollY = mScrollY + dY * r;
746 printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (2) mScroll: %ld, %ld [%d, %d, %f]\n",
747 mScrollX, mScrollY, X, Y, Step);
751 ScrollPlayfieldIfNeeded();
755 void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS)
759 TickCountObject Tick;
763 long oldX, oldY, maxD;
764 static boolean AlreadyRunning = False;
774 AlreadyRunning = True;
779 maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dx));
780 StepCount = FPS * (TimeMS / (double)1000);
781 if (StepCount > maxD)
788 tStep = (double)1 / StepCount;
791 // R = Sqr(dX * dX + dY * dY)
792 // If R = 0 Then Exit Sub 'we are there already
793 for (T = (double)tStep; T <= (double)1; T += tStep)
798 // If Claim Then Exit For
801 Tick.DelayMS(dT, False);
804 mScrollX = oldX + T * dx;
805 mScrollY = oldY + T * dY;
815 Tick.DelayMS(dT, False);
825 AlreadyRunning = False;
828 printf("::: DDScrollBuffer.c: DDScrollBuffer_SoftScrollTo(): mScroll: %ld, %ld\n",
833 ScrollPlayfieldIfNeeded();