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];
42 void RestorePlayfield()
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;
52 for (y = DisplayMinY; y <= DisplayMaxY; y++)
54 for (x = DisplayMinX; x <= DisplayMaxX; x++)
56 if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
58 DrawFieldNoAnimated(x, y);
59 DrawFieldAnimated(x, y);
65 static void ScrollPlayfield(int dx, int dy)
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;
73 BlitBitmap(screenBitmap, screenBitmap,
76 (MAX_BUF_XSIZE * TILEX) - TILEX * (dx != 0),
77 (MAX_BUF_YSIZE * TILEY) - TILEY * (dy != 0),
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++)
91 for (y = DisplayMinY; y <= DisplayMaxY; y++)
93 for (x = DisplayMinX; x <= DisplayMaxX; x++)
95 if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
99 int tsi = GetSI(x, y);
100 long id = ((PlayField16[tsi]) |
101 (PlayField8[tsi] << 16) |
102 (DisPlayField[tsi] << 24));
106 printf("::: [%d] %d [%d, %d] [%d]\n", dx, sx, x, y, buf_xsize);
108 if (sx == 0 || sx == MAX_BUF_XSIZE - 1)
109 printf("::: %d, %d\n", dx, sx);
113 if ((dx == -1 && x == x2) ||
114 (dx == +1 && x == x1) ||
115 (dy == -1 && y == y2) ||
116 (dy == +1 && y == y1))
119 printf("::: %d, %d\n", sx, sy);
124 DrawFieldNoAnimated(x, y);
125 DrawFieldAnimated(x, y);
130 ScreenBuffer[sx][sy] = id;
136 static void ScrollPlayfieldIfNeededExt(boolean reset)
146 if (mScrollX_last == -1 || mScrollY_last == -1)
148 mScrollX_last = mScrollX;
149 mScrollY_last = mScrollY;
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))
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);
167 mScrollX_last -= dx * TILEX;
168 mScrollY_last -= dy * TILEY;
170 ScrollPlayfield(dx, dy);
173 printf("::: %ld, %ld\n", mScrollX, mScrollY);
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)
183 int dx = (mScrollX < mScrollX_last ? 1 : mScrollX > mScrollX_last ? -1 : 0);
184 int dy = (mScrollY < mScrollY_last ? 1 : mScrollY > mScrollY_last ? -1 : 0);
186 mScrollX_last = mScrollX;
187 mScrollY_last = mScrollY;
189 ScrollPlayfield(dx, dy);
192 printf("::: %ld, %ld\n", mScrollX, mScrollY);
199 static void ScrollPlayfieldIfNeeded()
201 ScrollPlayfieldIfNeededExt(FALSE);
204 void InitScrollPlayfield()
206 ScrollPlayfieldIfNeededExt(TRUE);
209 void UpdatePlayfield(boolean force_redraw)
216 for (y = DisplayMinY; y <= DisplayMaxY; y++)
218 for (x = DisplayMinX; x <= DisplayMaxX; x++)
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;
226 redraw = TRUE; // !!! TEST ONLY -- ALWAYS REDRAW !!!
231 GfxGraphicLast[x][y] = GfxGraphic[x][y];
236 if (element != GfxElementLast[x][y] &&
237 graphic == GfxGraphicLast[x][y])
239 /* element changed, but not graphic => disable updating graphic */
241 GfxElementLast[x][y] = element;
242 GfxGraphicLast[x][y] = GfxGraphic[x][y] = -1;
247 if (graphic != GfxGraphicLast[x][y]) // new graphic
251 GfxElementLast[x][y] = element;
252 GfxGraphicLast[x][y] = GfxGraphic[x][y];
253 sync_frame = GfxFrame[x][y] = 0;
255 else if (isNextAnimationFrame_SP(graphic, sync_frame)) // new frame
262 int sx = x * StretchWidth;
263 int sy = y * StretchWidth;
266 printf("::: REDRAW (%d, %d): %d, %d\n", x, y, graphic, sync_frame);
269 StretchedSprites.BltImg(sx, sy, graphic, sync_frame);
279 printf("::: FRAME %d: %d redrawn\n", FrameCounter, num_redrawn);
283 void UpdatePlayfield_TMP()
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;
291 for (y = DisplayMinY; y <= DisplayMaxY; y++)
293 for (x = DisplayMinX; x <= DisplayMaxX; x++)
295 if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
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);
306 if (LowByte(PlayField16[tsi]) == fiMurphy)
310 if (redraw_screen_tile)
313 DrawFieldNoAnimated(x, y);
314 DrawFieldAnimated(x, y);
317 ScreenBuffer[sx][sy] = id;
319 redraw[sx][sy] = TRUE;
327 void OLD_UpdatePlayfield()
330 int left = mScrollX / TILEX;
331 int top = mScrollY / TILEY;
333 for (y = top; y < top + MAX_BUF_YSIZE; y++)
335 for (x = left; x < left + MAX_BUF_XSIZE; x++)
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);
345 if (redraw_screen_tile)
347 DrawFieldNoAnimated(x, y);
348 DrawFieldAnimated(x, y);
350 ScreenBuffer[sx][sy] = id;
352 redraw[sx][sy] = TRUE;
359 void DDScrollBuffer_Let_DestXOff(long NewVal)
364 long DDScrollBuffer_Get_DestXOff()
368 DestXOff = mDestXOff;
373 void DDScrollBuffer_Let_DestYOff(long NewVal)
378 long DDScrollBuffer_Get_DestYOff()
382 DestYOff = mDestYOff;
387 DirectDrawSurface7 DDScrollBuffer_Get_Surface()
389 DirectDrawSurface7 Surface;
396 long DDScrollBuffer_Get_Width()
405 int DDScrollBuffer_Get_Height()
416 long DDScrollBuffer_CreateAtSize(long Width, long Height, long hWndViewPort)
423 mhWnd = hWndViewPort;
424 // Create ScrollBuffer:
426 SD.lFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
427 SD.ddsCaps.lCaps = DDSCAPS_VIDEOMEMORY;
428 // SD.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
433 // --- On Error Resume Next
434 Buffer = DDraw.CreateSurface(SD);
438 // --- On Error GoTo 0
449 void DDScrollBuffer_Cls(int BackColor)
456 Buffer.BltColorFill(EmptyRect, BackColor);
461 /* copy the entire screen to the window at the scroll position */
463 void BlitScreenToBitmap_SP(Bitmap *target_bitmap)
466 int px = 2 * TILEX + mScrollX % TILEX;
467 int py = 2 * TILEY + mScrollY % TILEY;
469 int px = 2 * TILEX + (mScrollX - mScrollX_last) % TILEX;
470 int py = 2 * TILEY + (mScrollY - mScrollY_last) % TILEY;
472 int sx, sy, sxsize, sysize;
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);
484 int full_xsize = (FieldWidth - (menBorder.Checked ? 0 : 1)) * TILEX;
485 int full_ysize = (FieldHeight - (menBorder.Checked ? 0 : 1)) * TILEY;
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);
495 static int mScrollX_tmp = -1;
496 static int mScrollY_tmp = -1;
498 if (mScrollX != mScrollX_tmp || mScrollY != mScrollY_tmp)
500 printf("::: %ld, %ld\n", mScrollX, mScrollY);
502 mScrollX_tmp = mScrollX;
503 mScrollY_tmp = mScrollY;
510 static boolean x = 0;
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);
524 if (!menBorder.Checked)
532 if (mScrollX >= 0 && mScrollX <= 16)
537 else if (mScrollX >= 352 && mScrollX <= 368)
542 else if (mScrollX >= 16) // && mScrollX <= 352)
549 /* !!! TEST ONLY !!! */
554 BlitBitmap(screenBitmap, target_bitmap, px, py, sxsize, sysize, sx, sy);
557 void OLD_BlitScreenToBitmap_SP(Bitmap *target_bitmap)
559 int x = mScrollX % (MAX_BUF_XSIZE * TILEX);
560 int y = mScrollY % (MAX_BUF_YSIZE * TILEY);
562 if (x < 2 * TILEX && y < 2 * TILEY)
564 BlitBitmap(screenBitmap, target_bitmap, x, y,
565 SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
567 else if (x < 2 * TILEX && y >= 2 * TILEY)
569 BlitBitmap(screenBitmap, target_bitmap, x, y,
570 SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
572 BlitBitmap(screenBitmap, target_bitmap, x, 0,
573 SCR_FIELDX * TILEX, y - 2 * TILEY,
574 SX, SY + MAX_BUF_YSIZE * TILEY - y);
576 else if (x >= 2 * TILEX && y < 2 * TILEY)
578 BlitBitmap(screenBitmap, target_bitmap, x, y,
579 MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
581 BlitBitmap(screenBitmap, target_bitmap, 0, y,
582 x - 2 * TILEX, SCR_FIELDY * TILEY,
583 SX + MAX_BUF_XSIZE * TILEX - x, SY);
587 BlitBitmap(screenBitmap, target_bitmap, x, y,
588 MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
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);
602 void BackToFront_SP(void)
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);
613 redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last)
616 BlitScreenToBitmap_SP(window);
618 /* blit all (up to four) parts of the scroll buffer to the backbuffer */
619 BlitScreenToBitmap_SP(backbuffer);
621 /* blit the completely updated backbuffer to the window (in one blit) */
622 BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY);
627 for (x = 0; x < SCR_FIELDX; x++)
629 for (y = 0; y < SCR_FIELDY; y++)
631 int xx = (left + x) % MAX_BUF_XSIZE;
632 int yy = (top + y) % MAX_BUF_YSIZE;
635 BlitBitmap(screenBitmap, window,
636 xx * TILEX, yy * TILEY, TILEX, TILEY,
637 SX + x * TILEX, SY + y * TILEY);
644 for (x = 0; x < MAX_BUF_XSIZE; x++)
645 for (y = 0; y < MAX_BUF_YSIZE; y++)
646 redraw[x][y] = FALSE;
649 scrolling_last = scrolling;
653 void DDScrollBuffer_Blt_Ext(Bitmap *target_bitmap)
671 DR.right = SCR_FIELDX * TILEX;
672 DR.bottom = SCR_FIELDY * TILEY;
674 // --- On Error GoTo BltEH
675 DirectX.GetWindowRect(mhWnd, DR);
676 // --- On Error GoTo 0
680 tX = (DR.right - DR.left) / Stretch;
681 tY = (DR.bottom - DR.top) / Stretch;
685 SR.left = mScrollX + mDestXOff;
686 SR.top = mScrollY + mDestYOff;
688 SR.right = SR.left + tX;
689 SR.bottom = SR.top + tY;
691 // If mWidth < SR.right Then
693 // DR.right = DR.left + Stretch * (SR.right - SR.left)
695 // If mHeight < SR.bottom Then
696 // SR.bottom = mHeight
697 // DR.bottom = DR.top + Stretch * (SR.bottom - SR.top)
699 // If (mScrollX + mDestXOff) < 0 Then
701 // DR.left = DR.left - Stretch * (mScrollX + mDestXOff)
703 // If (mScrollY + mDestYOff) < 0 Then
705 // DR.top = DR.top - Stretch * (mScrollY + mDestYOff)
710 SR.left = (SR.left < 0 ? 0 : SR.left);
711 SR.top = (SR.top < 0 ? 0 : SR.top);
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;
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);
729 if (!menBorder.Checked)
731 SR.left += TILEX / 2;
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);
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);
756 BlitBitmap(screenBitmap, target_bitmap,
757 SR.left, SR.top, tX, tY, sX, sY);
759 BlitBitmap(screenBitmap, target_bitmap,
761 SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
772 // DDraw.WaitForVerticalBlank DDWAITVB_BLOCKBEGIN, 0
773 if (IS_NOTHING(&Buffer, sizeof(Buffer)))
777 if (IS_NOTHING(&PrimarySurface, sizeof(PrimarySurface)))
783 L = PrimarySurface.Blt(DR, &Buffer, SR, DDBLT_WAIT);
793 case DDERR_INVALIDCLIPLIST:
797 case DDERR_INVALIDOBJECT:
801 case DDERR_INVALIDPARAMS:
805 case DDERR_INVALIDRECT:
809 case DDERR_NOALPHAHW:
817 case DDERR_NOCLIPLIST:
821 case DDERR_NODDROPSHW:
825 case DDERR_NOMIRRORHW:
829 case DDERR_NORASTEROPHW:
833 case DDERR_NOROTATIONHW:
837 case DDERR_NOSTRETCHHW:
841 case DDERR_NOZBUFFERHW:
845 case DDERR_SURFACEBUSY:
851 case DDERR_SURFACELOST:
852 DDraw.RestoreAllSurfaces();
853 if (! PrimarySurface.isLost())
859 // RestorePrimarySurface
865 case DDERR_UNSUPPORTED:
869 case DDERR_WASSTILLDRAWING:
883 // Buffer.UpdateOverlay SR, PrimarySurface, DR, DDOVER_SHOW
885 FMark.RefreshMarker();
891 void DDScrollBuffer_Blt()
898 /* !!! TEST ONLY !!! */
899 BlitBitmap(screenBitmap, window,
900 0, 0, SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
904 DDScrollBuffer_Blt_Ext(window);
908 void DDScrollBuffer_ScrollTo(int X, int Y)
921 printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTo(): mScroll: %ld, %ld [%d, %d]\n",
922 mScrollX, mScrollY, X, Y);
926 ScrollPlayfieldIfNeeded();
930 void DDScrollBuffer_ScrollTowards(int X, int Y, double Step)
938 printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (1) mScroll: %ld, %ld [%d, %d, %f, %f]\n",
939 mScrollX, mScrollY, X, Y, Step, Stretch);
946 r = Sqr(dx * dx + dY * dY);
947 if (r == 0) // we are there already
955 mScrollX = mScrollX + dx * r;
956 mScrollY = mScrollY + dY * r;
961 printf("::: DDScrollBuffer.c: DDScrollBuffer_ScrollTowards(): (2) mScroll: %ld, %ld [%d, %d, %f]\n",
962 mScrollX, mScrollY, X, Y, Step);
966 ScrollPlayfieldIfNeeded();
970 void DDScrollBuffer_SoftScrollTo(int X, int Y, long TimeMS, int FPS)
974 TickCountObject Tick;
978 long oldX, oldY, maxD;
979 static boolean AlreadyRunning = False;
982 printf(":a: %d, %d [%d, %d] [%d, %d] [%d, %d]\n",
984 mScrollX_last, mScrollY_last,
985 ScreenScrollXPos, ScreenScrollYPos,
997 AlreadyRunning = True;
1002 maxD = (Abs(dx) < Abs(dY) ? Abs(dY) : Abs(dx));
1003 StepCount = FPS * (TimeMS / (double)1000);
1004 if (StepCount > maxD)
1011 tStep = (double)1 / StepCount;
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)
1021 // If Claim Then Exit For
1024 Tick.DelayMS(dT, False);
1027 mScrollX = oldX + T * dx;
1028 mScrollY = oldY + T * dY;
1038 printf(":x: %d, %d [%d, %d] [%d, %d] [%d, %d]\n",
1040 mScrollX_last, mScrollY_last,
1041 ScreenScrollXPos, ScreenScrollYPos,
1049 Tick.DelayMS(dT, False);
1062 AlreadyRunning = False;
1065 printf("::: DDScrollBuffer.c: DDScrollBuffer_SoftScrollTo(): mScroll: %ld, %ld\n",
1066 mScrollX, mScrollY);
1070 printf(":y: %d, %d [%d, %d] [%d, %d] [%d, %d]\n",
1072 mScrollX_last, mScrollY_last,
1073 ScreenScrollXPos, ScreenScrollYPos,
1078 ScrollPlayfieldIfNeeded();
1082 printf(":z: %d, %d [%d, %d] [%d, %d] [%d, %d]\n",
1084 mScrollX_last, mScrollY_last,
1085 ScreenScrollXPos, ScreenScrollYPos,