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(int dx, int dy)
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;
51 BlitBitmap(screenBitmap, screenBitmap,
54 (MAX_BUF_XSIZE * TILEX) - TILEX * (dx != 0),
55 (MAX_BUF_YSIZE * TILEY) - TILEY * (dy != 0),
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++)
69 for (y = DisplayMinY; y <= DisplayMaxY; y++)
71 for (x = DisplayMinX; x <= DisplayMaxX; x++)
73 if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
77 int tsi = GetSI(x, y);
78 long id = ((PlayField16[tsi]) |
79 (PlayField8[tsi] << 16) |
80 (DisPlayField[tsi] << 24));
84 printf("::: [%d] %d [%d, %d] [%d]\n", dx, sx, x, y, buf_xsize);
86 if (sx == 0 || sx == MAX_BUF_XSIZE - 1)
87 printf("::: %d, %d\n", dx, sx);
91 if ((dx == -1 && x == x2) ||
92 (dx == +1 && x == x1) ||
93 (dy == -1 && y == y2) ||
94 (dy == +1 && y == y1))
97 printf("::: %d, %d\n", sx, sy);
102 DrawFieldNoAnimated(x, y);
103 DrawFieldAnimated(x, y);
108 ScreenBuffer[sx][sy] = id;
114 static void ScrollPlayfieldIfNeededExt(boolean reset)
124 if (mScrollX_last == -1 || mScrollY_last == -1)
126 mScrollX_last = mScrollX;
127 mScrollY_last = mScrollY;
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))
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);
145 mScrollX_last -= dx * TILEX;
146 mScrollY_last -= dy * TILEY;
148 ScrollPlayfield(dx, dy);
151 printf("::: %ld, %ld\n", mScrollX, mScrollY);
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)
161 int dx = (mScrollX < mScrollX_last ? 1 : mScrollX > mScrollX_last ? -1 : 0);
162 int dy = (mScrollY < mScrollY_last ? 1 : mScrollY > mScrollY_last ? -1 : 0);
164 mScrollX_last = mScrollX;
165 mScrollY_last = mScrollY;
167 ScrollPlayfield(dx, dy);
170 printf("::: %ld, %ld\n", mScrollX, mScrollY);
177 static void ScrollPlayfieldIfNeeded()
179 ScrollPlayfieldIfNeededExt(FALSE);
182 void InitScrollPlayfield()
184 ScrollPlayfieldIfNeededExt(TRUE);
187 void UpdatePlayfield()
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;
195 for (y = DisplayMinY; y <= DisplayMaxY; y++)
197 for (x = DisplayMinX; x <= DisplayMaxX; x++)
199 if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
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);
210 if (LowByte(PlayField16[tsi]) == fiMurphy)
214 if (redraw_screen_tile)
217 DrawFieldNoAnimated(x, y);
218 DrawFieldAnimated(x, y);
221 ScreenBuffer[sx][sy] = id;
223 redraw[sx][sy] = TRUE;
231 void OLD_UpdatePlayfield()
234 int left = mScrollX / TILEX;
235 int top = mScrollY / TILEY;
237 for (y = top; y < top + MAX_BUF_YSIZE; y++)
239 for (x = left; x < left + MAX_BUF_XSIZE; x++)
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);
249 if (redraw_screen_tile)
251 DrawFieldNoAnimated(x, y);
252 DrawFieldAnimated(x, y);
254 ScreenBuffer[sx][sy] = id;
256 redraw[sx][sy] = TRUE;
263 void DDScrollBuffer_Let_DestXOff(long NewVal)
268 long DDScrollBuffer_Get_DestXOff()
272 DestXOff = mDestXOff;
277 void DDScrollBuffer_Let_DestYOff(long NewVal)
282 long DDScrollBuffer_Get_DestYOff()
286 DestYOff = mDestYOff;
291 DirectDrawSurface7 DDScrollBuffer_Get_Surface()
293 DirectDrawSurface7 Surface;
300 long DDScrollBuffer_Get_Width()
309 int DDScrollBuffer_Get_Height()
318 long DDScrollBuffer_CreateAtSize(long Width, long Height, long hWndViewPort)
325 mhWnd = hWndViewPort;
326 // Create ScrollBuffer:
328 SD.lFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
329 SD.ddsCaps.lCaps = DDSCAPS_VIDEOMEMORY;
330 // SD.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
335 // --- On Error Resume Next
336 Buffer = DDraw.CreateSurface(SD);
340 // --- On Error GoTo 0
351 void DDScrollBuffer_Cls(int BackColor)
358 Buffer.BltColorFill(EmptyRect, BackColor);
362 /* copy the entire screen to the window at the scroll position */
364 void BlitScreenToBitmap_SP(Bitmap *target_bitmap)
367 int px = 2 * TILEX + mScrollX % TILEX;
368 int py = 2 * TILEY + mScrollY % TILEY;
370 int px = 2 * TILEX + (mScrollX - mScrollX_last) % TILEX;
371 int py = 2 * TILEY + (mScrollY - mScrollY_last) % TILEY;
373 int sx, sy, sxsize, sysize;
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);
385 int full_xsize = (FieldWidth - (menBorder.Checked ? 0 : 1)) * TILEX;
386 int full_ysize = (FieldHeight - (menBorder.Checked ? 0 : 1)) * TILEY;
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);
396 static int mScrollX_tmp = -1;
397 static int mScrollY_tmp = -1;
399 if (mScrollX != mScrollX_tmp || mScrollY != mScrollY_tmp)
401 printf("::: %ld, %ld\n", mScrollX, mScrollY);
403 mScrollX_tmp = mScrollX;
404 mScrollY_tmp = mScrollY;
411 static boolean x = 0;
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);
425 if (!menBorder.Checked)
433 if (mScrollX >= 0 && mScrollX <= 16)
438 else if (mScrollX >= 352 && mScrollX <= 368)
443 else if (mScrollX >= 16) // && mScrollX <= 352)
450 /* !!! TEST ONLY !!! */
455 BlitBitmap(screenBitmap, target_bitmap, px, py, sxsize, sysize, sx, sy);
458 void OLD_BlitScreenToBitmap_SP(Bitmap *target_bitmap)
460 int x = mScrollX % (MAX_BUF_XSIZE * TILEX);
461 int y = mScrollY % (MAX_BUF_YSIZE * TILEY);
463 if (x < 2 * TILEX && y < 2 * TILEY)
465 BlitBitmap(screenBitmap, target_bitmap, x, y,
466 SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
468 else if (x < 2 * TILEX && y >= 2 * TILEY)
470 BlitBitmap(screenBitmap, target_bitmap, x, y,
471 SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
473 BlitBitmap(screenBitmap, target_bitmap, x, 0,
474 SCR_FIELDX * TILEX, y - 2 * TILEY,
475 SX, SY + MAX_BUF_YSIZE * TILEY - y);
477 else if (x >= 2 * TILEX && y < 2 * TILEY)
479 BlitBitmap(screenBitmap, target_bitmap, x, y,
480 MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
482 BlitBitmap(screenBitmap, target_bitmap, 0, y,
483 x - 2 * TILEX, SCR_FIELDY * TILEY,
484 SX + MAX_BUF_XSIZE * TILEX - x, SY);
488 BlitBitmap(screenBitmap, target_bitmap, x, y,
489 MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
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);
503 void BackToFront_SP(void)
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);
514 redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last)
517 BlitScreenToBitmap_SP(window);
519 /* blit all (up to four) parts of the scroll buffer to the backbuffer */
520 BlitScreenToBitmap_SP(backbuffer);
522 /* blit the completely updated backbuffer to the window (in one blit) */
523 BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY);
528 for (x = 0; x < SCR_FIELDX; x++)
530 for (y = 0; y < SCR_FIELDY; y++)
532 int xx = (left + x) % MAX_BUF_XSIZE;
533 int yy = (top + y) % MAX_BUF_YSIZE;
536 BlitBitmap(screenBitmap, window,
537 xx * TILEX, yy * TILEY, TILEX, TILEY,
538 SX + x * TILEX, SY + y * TILEY);
545 for (x = 0; x < MAX_BUF_XSIZE; x++)
546 for (y = 0; y < MAX_BUF_YSIZE; y++)
547 redraw[x][y] = FALSE;
550 scrolling_last = scrolling;
554 void DDScrollBuffer_Blt_Ext(Bitmap *target_bitmap)
568 DR.right = SCR_FIELDX * TILEX;
569 DR.bottom = SCR_FIELDY * TILEY;
571 // --- On Error GoTo BltEH
572 DirectX.GetWindowRect(mhWnd, DR);
573 // --- On Error GoTo 0
577 tX = (DR.right - DR.left) / Stretch;
578 tY = (DR.bottom - DR.top) / Stretch;
582 SR.left = mScrollX + mDestXOff;
583 SR.top = mScrollY + mDestYOff;
585 SR.right = SR.left + tX;
586 SR.bottom = SR.top + tY;
588 // If mWidth < SR.right Then
590 // DR.right = DR.left + Stretch * (SR.right - SR.left)
592 // If mHeight < SR.bottom Then
593 // SR.bottom = mHeight
594 // DR.bottom = DR.top + Stretch * (SR.bottom - SR.top)
596 // If (mScrollX + mDestXOff) < 0 Then
598 // DR.left = DR.left - Stretch * (mScrollX + mDestXOff)
600 // If (mScrollY + mDestYOff) < 0 Then
602 // DR.top = DR.top - Stretch * (mScrollY + mDestYOff)
607 SR.left = (SR.left < 0 ? 0 : SR.left);
608 SR.top = (SR.top < 0 ? 0 : SR.top);
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;
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);
626 if (!menBorder.Checked)
628 SR.left += TILEX / 2;
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);
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);
653 BlitBitmap(screenBitmap, target_bitmap,
654 SR.left, SR.top, tX, tY, sX, sY);
656 BlitBitmap(screenBitmap, target_bitmap,
658 SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
669 // DDraw.WaitForVerticalBlank DDWAITVB_BLOCKBEGIN, 0
670 if (IS_NOTHING(&Buffer, sizeof(Buffer)))
673 if (IS_NOTHING(&PrimarySurface, sizeof(PrimarySurface)))
676 L = PrimarySurface.Blt(DR, &Buffer, SR, DDBLT_WAIT);
686 case DDERR_INVALIDCLIPLIST:
690 case DDERR_INVALIDOBJECT:
694 case DDERR_INVALIDPARAMS:
698 case DDERR_INVALIDRECT:
702 case DDERR_NOALPHAHW:
710 case DDERR_NOCLIPLIST:
714 case DDERR_NODDROPSHW:
718 case DDERR_NOMIRRORHW:
722 case DDERR_NORASTEROPHW:
726 case DDERR_NOROTATIONHW:
730 case DDERR_NOSTRETCHHW:
734 case DDERR_NOZBUFFERHW:
738 case DDERR_SURFACEBUSY:
743 case DDERR_SURFACELOST:
744 DDraw.RestoreAllSurfaces();
745 if (! PrimarySurface.isLost())
751 // RestorePrimarySurface
756 case DDERR_UNSUPPORTED:
760 case DDERR_WASSTILLDRAWING:
772 // Buffer.UpdateOverlay SR, PrimarySurface, DR, DDOVER_SHOW
774 FMark.RefreshMarker();
780 void DDScrollBuffer_Blt()
787 /* !!! TEST ONLY !!! */
788 BlitBitmap(screenBitmap, window,
789 0, 0, SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
793 DDScrollBuffer_Blt_Ext(window);
797 void DDScrollBuffer_ScrollTo(int X, int Y)
810 printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTo(): mScroll: %ld, %ld [%d, %d]\n",
811 mScrollX, mScrollY, X, Y);
815 ScrollPlayfieldIfNeeded();
819 void DDScrollBuffer_ScrollTowards(int X, int Y, double Step)
827 printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (1) mScroll: %ld, %ld [%d, %d, %f, %f]\n",
828 mScrollX, mScrollY, X, Y, Step, Stretch);
835 r = Sqr(dx * dx + dY * dY);
836 if (r == 0) // we are there already
844 mScrollX = mScrollX + dx * r;
845 mScrollY = mScrollY + dY * r;
850 printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (2) mScroll: %ld, %ld [%d, %d, %f]\n",
851 mScrollX, mScrollY, X, Y, Step);
855 ScrollPlayfieldIfNeeded();
859 void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS)
863 TickCountObject Tick;
867 long oldX, oldY, maxD;
868 static boolean AlreadyRunning = False;
878 AlreadyRunning = True;
883 maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dx));
884 StepCount = FPS * (TimeMS / (double)1000);
885 if (StepCount > maxD)
892 tStep = (double)1 / StepCount;
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)
902 // If Claim Then Exit For
905 Tick.DelayMS(dT, False);
908 mScrollX = oldX + T * dx;
909 mScrollY = oldY + T * dY;
919 Tick.DelayMS(dT, False);
929 AlreadyRunning = False;
932 printf("::: DDScrollBuffer.c: DDScrollBuffer_SoftScrollTo(): mScroll: %ld, %ld\n",
937 ScrollPlayfieldIfNeeded();