#include #include #include #include "ffeapi.h" #include "ffecfg.h" #include "win32api.h" static int fullscreen = 0; static int fswidth = 320; static int fsheight = 200; static int fsbpp = 16; static int fssoftscale = 0; static int fstriplebuf = 0; static int fsletterbox = 1; static int winwidth = 640; static int winheight = 400; static int winsoftscale = 0; static int winintermediatebuf = 1; static int nodraw = 0; static int vidInit = 0; static int active = 1; static int ptrEnabled = 1; static int error = 0; static int exclusive = 0; static int bpp = 16; static int softscale = 0; static int wndwidth; // window width/height including borders static int wndheight; static int curwidth; // width/height of front surface static int curheight; static RECT clrect; static RECT wndrect; static POINT cursorpos; static HWND hWnd = NULL; static HINSTANCE hInst = NULL; static UCHAR pBackBuf[320*200]; static LPDIRECTDRAW pDDraw = NULL; static LPDIRECTDRAWSURFACE pDDSurf = NULL; // writing surface static LPDIRECTDRAWSURFACE pDDSurf2 = NULL; // front surface static LPDIRECTDRAWSURFACE pDDSurf3 = NULL; // intermediate surface static LPDIRECTDRAWPALETTE pDDPal = NULL; static LPDIRECTDRAWCLIPPER pDDClip = NULL; static ULONG pWinPal16[256]; static ULONG pWinPal15[256]; static ULONG pWinPal32[256]; static FILE *pLog = NULL; extern "C" int asmmain (int argc, char **argv); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { hInst = hInstance; return asmmain(0, NULL); } void Win32MsgHandler (void) { while (1) { MSG msg; if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { SystemCleanup(); exit(0); } TranslateMessage (&msg); DispatchMessage (&msg); } else if (active) return; else WaitMessage(); } } HWND Win32GetWnd() { return hWnd; } HINSTANCE Win32GetInst() { return hInst; } extern "C" void InputMouseReadPos (long *pXPos, long *pYPos) { POINT p; if (!fullscreen) { GetCursorPos (&p); ScreenToClient (Win32GetWnd(), &p); *pXPos = (p.x * 320) / curwidth; *pYPos = (p.y * 200) / curheight; } else *pXPos = *pYPos = 0; } static void ConvPalette (PALETTEENTRY *pPal) { int i; for (i=0; i<256; i++) { pPal[i].peRed = (UCHAR)(pWinPal32[i] >> 16 & 0xfc); pPal[i].peGreen = (UCHAR)(pWinPal32[i] >> 8 & 0xfc); pPal[i].peBlue = (UCHAR)(pWinPal32[i] & 0xfc); } } char *ppFSError[] = { { "Unknown error\n" }, { "Failed on SetCooperativeLevel\n" }, { "Failed on SetDisplayMode\n" }, { "Failed on primary surface creation\n" }, { "Failed on backbuffer selection\n" }, { "Failed on intermediate surface creation\n" }, { "Failed on palette creation\n" }, { "Failed on palette attachment\n" } }; static int InitFullscreen (void) { DDSURFACEDESC ddsd; PALETTEENTRY pTempPal[256]; int rval; exclusive = 1; softscale = fssoftscale; if (fsheight <= (200*fswidth) / 320) fsletterbox = 0; curwidth = fswidth; curheight = fsheight; rval = pDDraw->SetCooperativeLevel (hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT | DDSCL_ALLOWMODEX); if (rval != DD_OK) { error = 1; return 0; } if (fsbpp != 8) { rval = pDDraw->SetDisplayMode (fswidth, fsheight, fsbpp); if (rval != DD_OK) { error = 2; return 0; } VideoPointerDisable(); Win32SetMouseExclusive(); memset (&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; rval = pDDraw->CreateSurface (&ddsd, &pDDSurf2, NULL); if (rval != DD_OK) { error = 3; return 0; } ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; if (!fssoftscale) { ddsd.dwHeight = 200; ddsd.dwWidth = 320; } else { ddsd.dwHeight = fsheight; ddsd.dwWidth = fswidth; } rval = pDDraw->CreateSurface (&ddsd, &pDDSurf, NULL); if (rval != DD_OK) { error = 4; return 0; } pDDSurf->GetSurfaceDesc (&ddsd); bpp = 32; if (ddsd.ddpfPixelFormat.dwRBitMask == 0xff0000 && ddsd.ddpfPixelFormat.dwRGBBitCount == 32) return 1; if (ddsd.ddpfPixelFormat.dwRGBBitCount == 24) { bpp = 24; return 1; } if (ddsd.ddpfPixelFormat.dwGBitMask == 0x07e0) { bpp = 16; return 1; } if (ddsd.ddpfPixelFormat.dwGBitMask == 0x03e0) { bpp = 15; return 1; } return 0; } LPDIRECTDRAW4 pDD4 = 0; rval = pDDraw->QueryInterface (IID_IDirectDraw4, (void **)&pDD4); if (rval != DD_OK) { error = 2; return 0; } rval = pDD4->SetDisplayMode (320, 200, 8, 0, DDSDM_STANDARDVGAMODE); pDD4->Release (); if (rval != DD_OK) { error = 2; return 0; } VideoPointerDisable(); Win32SetMouseExclusive(); if (!fstriplebuf) { memset (&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; rval = pDDraw->CreateSurface (&ddsd, &pDDSurf, NULL); if (rval != DD_OK) { error = 3; return 0; } } else { memset (&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; ddsd.dwBackBufferCount = 2; rval = pDDraw->CreateSurface (&ddsd, &pDDSurf2, NULL); if (rval != DD_OK) { error = 3; return 0; } ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; rval = pDDSurf2->GetAttachedSurface (&ddsd.ddsCaps, &pDDSurf); if (rval != DD_OK) { error = 4; return 0; } } ConvPalette (pTempPal); rval = pDDraw->CreatePalette (DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, pTempPal, &pDDPal, NULL); if (rval != DD_OK) { error = 6; return 0; } if (!fstriplebuf) rval = pDDSurf->SetPalette (pDDPal); else rval = pDDSurf2->SetPalette (pDDPal); if (rval != DD_OK) { error = 7; return 0; } bpp = 8; return 1; } char *ppWinError[] = { { "Unknown error\n" }, { "Failed on SetCooperativeLevel\n" }, { "Failed on primary surface creation\n" }, { "Failed on clipper creation\n" }, { "Failed on clipper window setting\n" }, { "Failed on clipper attachment\n" }, { "Failed on backbuffer creation\n" }, { "Failed on intermediate surface creation\n" }, { "Failed to find usable bit depth\n" }, }; static int InitWindowed (void) { DDSURFACEDESC ddsd; int rval; softscale = winsoftscale; curwidth = winwidth; curheight = winheight; rval = pDDraw->SetCooperativeLevel (hWnd, DDSCL_NORMAL); if (rval != DD_OK) { error = 1; return 0; } ShowWindow (hWnd, SW_SHOWNORMAL); SetWindowPos (hWnd, HWND_NOTOPMOST, wndrect.left, wndrect.top, wndrect.right-wndrect.left, wndrect.bottom-wndrect.top, 0); memset (&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; rval = pDDraw->CreateSurface (&ddsd, &pDDSurf2, NULL); if (rval != DD_OK) { error = 2; return 0; } rval = pDDraw->CreateClipper (0, &pDDClip, NULL); if (rval != DD_OK) { error = 3; return 0; } rval = pDDClip->SetHWnd(0, hWnd); if (rval != DD_OK) { error = 4; return 0; } rval = pDDSurf2->SetClipper(pDDClip); if (rval != DD_OK) { error = 5; return 0; } ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; if (!softscale) { ddsd.dwHeight = 200; ddsd.dwWidth = 320; } else { ddsd.dwHeight = winheight; ddsd.dwWidth = winwidth; } rval = pDDraw->CreateSurface (&ddsd, &pDDSurf, NULL); if (rval != DD_OK) { error = 6; return 0; } if (winintermediatebuf) { ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwHeight = winheight; ddsd.dwWidth = winwidth; rval = pDDraw->CreateSurface (&ddsd, &pDDSurf3, NULL); if (rval != DD_OK) { error = 7; return 0; } } pDDSurf->GetSurfaceDesc (&ddsd); bpp = 32; if (ddsd.ddpfPixelFormat.dwRBitMask == 0xff0000 && ddsd.ddpfPixelFormat.dwRGBBitCount == 32) return 1; if (ddsd.ddpfPixelFormat.dwRGBBitCount == 24) { bpp = 24; return 1; } if (ddsd.ddpfPixelFormat.dwGBitMask == 0x07e0) { bpp = 16; return 1; } if (ddsd.ddpfPixelFormat.dwGBitMask == 0x03e0) { bpp = 15; return 1; } error = 8; return 0; } static void DDrawCleanup() { if (pDDraw) { if (pDDPal) { pDDPal->Release(); pDDPal = NULL; } if (pDDClip) { pDDClip->Release(); pDDClip = NULL; } if (pDDSurf) { pDDSurf->Release(); pDDSurf = NULL; } if (pDDSurf2) { pDDSurf2->Release(); pDDSurf2 = NULL; } if (pDDSurf3) { pDDSurf3->Release(); pDDSurf3 = NULL; } pDDraw->RestoreDisplayMode(); pDDraw->SetCooperativeLevel (hWnd, DDSCL_NORMAL); exclusive = 0; Win32SetMouseNorm(); VideoPointerEnable(); } } static void ResetWindowParams() { POINT pos = { 0, 0 }; WINDOWPLACEMENT wp; if (exclusive) return; wp.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement (hWnd, &wp); if (wp.showCmd == SW_SHOWMINIMIZED) return; GetClientRect (hWnd, &clrect); ClientToScreen (hWnd, &pos); OffsetRect (&clrect, pos.x, pos.y); wndrect.left = clrect.left - GetSystemMetrics(SM_CXSIZEFRAME); wndrect.top = clrect.top - GetSystemMetrics(SM_CYSIZEFRAME) - GetSystemMetrics(SM_CYMENU); wndrect.right = clrect.right + GetSystemMetrics(SM_CXSIZEFRAME); wndrect.bottom = clrect.bottom + GetSystemMetrics(SM_CYSIZEFRAME); } static void VideoReset (void) { int rval; DDrawCleanup(); Win32SetMouseNorm(); while (1) { if (fullscreen) rval = InitFullscreen(); else rval = InitWindowed(); if (rval != 0) return; DDrawCleanup(); Win32SetMouseNorm(); if (!fullscreen) { rval = MessageBox (hWnd, ppWinError[error], "Windowed mode switching error", MB_RETRYCANCEL | MB_ICONWARNING); if (rval == 0 || rval == IDCANCEL) { SystemCleanup(); exit(0); } } else if (error == 2) { rval = MessageBox (hWnd, "Failed to set display mode\nTry compatibility mode?", "Fullscreen mode switching error", MB_YESNO | MB_ICONWARNING); if (rval == IDNO) fullscreen = 0; else if (rval == IDYES) { fswidth = 640; fsheight = 480; fsbpp = 16; fssoftscale = 0; fsletterbox = 0; } } else { rval = MessageBox (hWnd, ppFSError[error], "Fullscreen mode switching error", MB_RETRYCANCEL | MB_ICONWARNING); if (rval == 0 || rval == IDCANCEL) fullscreen = 0; } } } static void RestoreSurfaces() { int rv1, rv2, rv3; while (1) { rv1 = rv2 = rv3 = DD_OK; if (pDDSurf) rv1 = pDDSurf->Restore(); if (pDDSurf2) rv2 = pDDSurf2->Restore(); if (pDDSurf3) rv3 = pDDSurf3->Restore(); if (rv1 == DDERR_WRONGMODE) VideoReset(); if (rv1 == DD_OK && rv2 == DD_OK && rv3 == DD_OK) break; } } static LRESULT CALLBACK WndProc (HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch(msg) { case WM_LBUTTONDOWN: case WM_ACTIVATEAPP: case WM_ACTIVATE: Win32InputReacquire(); Win32SoundReacquire(); break; case WM_SIZE: if (SIZE_MAXHIDE==wparam || SIZE_MINIMIZED==wparam) { active = 0; TimerCleanup(); Win32SetMouseNorm(); } else { active = 1; TimerInit(); if (exclusive) Win32SetMouseExclusive(); ResetWindowParams(); } break; case WM_CLOSE: PostQuitMessage(0); return 0L; case WM_DESTROY: return 0L; case WM_GETMINMAXINFO: ((MINMAXINFO*)lparam)->ptMinTrackSize.x = wndwidth; ((MINMAXINFO*)lparam)->ptMinTrackSize.y = wndheight; ((MINMAXINFO*)lparam)->ptMaxTrackSize.x = wndwidth; ((MINMAXINFO*)lparam)->ptMaxTrackSize.y = wndheight; break; case WM_MOVE: ResetWindowParams (); break; case WM_KEYDOWN: if (!(GetAsyncKeyState(VK_CONTROL) & 0x8000)) break; if (wparam == VK_F11) { nodraw ^= 1; return 0L; } if (wparam == VK_F12) { fullscreen ^= 1; VideoReset(); return 0L; } case WM_SYSKEYDOWN: return 0L; } return DefWindowProc (wnd, msg, wparam, lparam); } static UCHAR pPalTable[3][64]; void VideoInit() { WNDCLASS wc; CfgStruct cfg; int pPalBase[3] = { 0, 0, 0 }; int step, i, j, col; int rval; if (vidInit != 0) return; memset (pWinPal15, 0, 256*4); memset (pWinPal16, 0, 256*4); memset (pWinPal32, 0, 256*4); CfgOpen (&cfg, __CONFIGFILE__); CfgFindSection (&cfg, "VIDEO"); CfgGetKeyVal (&cfg, "fullscreen", &fullscreen); CfgGetKeyVal (&cfg, "nodraw", &nodraw); CfgGetKeyVal (&cfg, "fswidth", &fswidth); CfgGetKeyVal (&cfg, "fsheight", &fsheight); CfgGetKeyVal (&cfg, "fsbpp", &fsbpp); CfgGetKeyVal (&cfg, "fssoftscale", &fssoftscale); CfgGetKeyVal (&cfg, "fsletterbox", &fsletterbox); CfgGetKeyVal (&cfg, "fstriplebuf", &fstriplebuf); CfgGetKeyVal (&cfg, "winwidth", &winwidth); CfgGetKeyVal (&cfg, "winheight", &winheight); CfgGetKeyVal (&cfg, "winsoftscale", &winsoftscale); CfgGetKeyVal (&cfg, "winintermediatebuf", &winintermediatebuf); CfgGetKeyVal (&cfg, "RedBase", pPalBase); CfgGetKeyVal (&cfg, "GreenBase", pPalBase+1); CfgGetKeyVal (&cfg, "BlueBase", pPalBase+2); CfgClose (&cfg); for (i=0; i<3; i++) { col = pPalBase[i] << 8; step = ((64<<8) - col) / 63; for (j=0; j<64; j++) { int tcol = col >> 8; if (tcol < 0) tcol = 0; pPalTable[i][j] = (UCHAR)tcol; col += step; } } wc.lpszClassName = "WIN32FFE"; wc.lpfnWndProc = WndProc; wc.style = CS_VREDRAW | CS_HREDRAW; wc.hInstance = hInst; wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.cbClsExtra = 0; wc.cbWndExtra = 0; rval = RegisterClass (&wc); if (rval == 0) { MessageBox (NULL, "Failed on class registration", "WinFFE startup error", MB_OK | MB_ICONWARNING); SystemCleanup(); exit(0); } if (winwidth < 160) winwidth = 160; if (winheight < 100) winheight = 100; wndwidth = winwidth + GetSystemMetrics(SM_CXSIZEFRAME)*2; wndheight = winheight + GetSystemMetrics(SM_CYSIZEFRAME)*2 + GetSystemMetrics(SM_CYMENU); hWnd = CreateWindow ("WIN32FFE", "FFE", WS_OVERLAPPEDWINDOW, 100, 100, wndwidth, wndheight, NULL, NULL, hInst, NULL); if (hWnd == 0) { MessageBox (NULL, "Failed on window creation", "WinFFE startup error", MB_OK | MB_ICONWARNING); SystemCleanup(); exit(0); } ShowWindow (hWnd, SW_SHOWNORMAL); UpdateWindow (hWnd); ResetWindowParams (); rval = DirectDrawCreate (NULL, &pDDraw, NULL); if (rval != DD_OK) { SystemCleanup(); exit (0); } VideoReset(); vidInit = 1; } void VideoCleanup() { if (pDDraw) { DDrawCleanup(); pDDraw->Release(); pDDraw = NULL; } if (hWnd) { DestroyWindow (hWnd); hWnd = NULL; } } extern "C" void VideoPointerEnable() { if (ptrEnabled == 0) { SetCursorPos (cursorpos.x, cursorpos.y); ClipCursor (NULL); ShowCursor (TRUE); ptrEnabled = 1; } } extern "C" void VideoPointerDisable() { if (ptrEnabled != 0) { GetCursorPos (&cursorpos); ShowCursor (FALSE); ClipCursor (&clrect); ptrEnabled = 0; } } extern "C" long VideoPointerExclusive() { return exclusive; } void Win32Stretch16 (void *pDest, int dw, int dh, int pitch, ULONG *pPal) { int xfrac, yfrac; int xpos, ypos, x, y; xfrac = 0x1400000 / dw; // 320 << 16 yfrac = 0xc80000 / dh; // 200 << 16 ypos = yfrac >> 1; for (y=0; y>16); USHORT *pDestL = (USHORT *)((UCHAR *)pDest + pitch*y); xpos = xfrac >> 1; for (x=0; x>16]]; } } } void Win32Stretch32 (void *pDest, int dw, int dh, int pitch, ULONG *pPal) { int xfrac, yfrac; int xpos, ypos, x, y; xfrac = 0x1400000 / dw; // 320 << 16 yfrac = 0xc80000 / dh; // 200 << 16 ypos = yfrac >> 1; for (y=0; y>16); ULONG *pDestL = (ULONG *)((UCHAR *)pDest + pitch*y); xpos = xfrac >> 1; for (x=0; x>16)]]; } } } void Win32ClearBoxEdges (int yoff, int w, int h) { DDBLTFX ddbltfx; ddbltfx.dwSize = sizeof (DDBLTFX); ddbltfx.dwFillColor = 0; RECT r1 = { 0, 0, w, yoff }; RECT r2 = { 0, yoff+h, w, h+yoff*2 }; int flags = DDBLT_COLORFILL | DDBLT_WAIT | DDBLT_ASYNC; pDDSurf2->Blt (&r1, NULL, NULL, flags, &ddbltfx); pDDSurf2->Blt (&r2, NULL, NULL, flags, &ddbltfx); } extern "C" void VideoBlit (UCHAR *pData, long x, long y, long w, long h, long jump) { if (nodraw) return; // copy to backbuffer... UCHAR *pBuf = pBackBuf + x + y*320; for (; h; --h, pData+=jump+w, pBuf+=320) memcpy (pBuf, pData, w); pBuf = pBackBuf; // If w=320, write and flip to rear surface if (w != 320) return; // One flip per frame DDSURFACEDESC ddsd; ddsd.dwSize=sizeof(ddsd); while (pDDSurf->Lock (NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK) RestoreSurfaces (); // Simple code for 8bpp if (bpp == 8) { int sw = ddsd.lPitch; UCHAR *pSurf = (UCHAR *)ddsd.lpSurface; for (h=200; h; --h, pBuf+=320, pSurf+=sw) memcpy (pSurf, pBuf, w); pDDSurf->Unlock (NULL); if (fstriplebuf) pDDSurf2->Flip (NULL, DDFLIP_WAIT); return; } // Check aspect ratio for letterbox int yoff = 0; RECT boxrect; w = curwidth; h = curheight; if (fsletterbox && exclusive) { h = (curwidth * 200) / 320; yoff = (curheight - h) >> 1; } boxrect.left = 0; boxrect.right = w; boxrect.top = yoff; boxrect.bottom = h+yoff; if (softscale) { // Scale straight to pDDSurf void *pSurf = (void *)((UCHAR *)ddsd.lpSurface + yoff*ddsd.lPitch); if (bpp==15) Win32Stretch16 (pSurf, w, h, ddsd.lPitch, pWinPal15); if (bpp==16) Win32Stretch16 (pSurf, w, h, ddsd.lPitch, pWinPal16); if (bpp==24) return; if (bpp==32) Win32Stretch32 (pSurf, w, h, ddsd.lPitch, pWinPal32); pDDSurf->Unlock (NULL); // Use fast blit? Nah... if (exclusive) pDDSurf2->BltFast (0, yoff, pDDSurf, &boxrect, DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT); else pDDSurf2->Blt (&clrect, pDDSurf, NULL, DDBLT_WAIT, NULL); if (yoff) Win32ClearBoxEdges (yoff, w, h); return; } // Copy unscaled straight to pDDSurf if (bpp==15) { int dJump = (ddsd.lPitch>>1) - 320; int cw, ch; USHORT *pSurf = (USHORT *)ddsd.lpSurface; for (ch=200; ch; --ch, pSurf+=dJump) for (cw=320; cw; --cw, ++pBuf, ++pSurf) *pSurf = (USHORT)pWinPal15[*pBuf]; } else if (bpp==16) { int dJump = (ddsd.lPitch>>1) - 320; int cw, ch; USHORT *pSurf = (USHORT *)ddsd.lpSurface; for (ch=200; ch; --ch, pSurf+=dJump) for (cw=320; cw; --cw, ++pBuf, ++pSurf) *pSurf = (USHORT)pWinPal16[*pBuf]; } else if (bpp==24) { int dJump = ddsd.lPitch - 320*3; int cw, ch; UCHAR *pSurf = (UCHAR *)ddsd.lpSurface; for (ch=200; ch; --ch, pSurf+=dJump) for (cw=320; cw; --cw, ++pBuf, pSurf+=3) { UCHAR *pSrc = (UCHAR *)&pWinPal32[*pBuf]; pSurf[0] = pSrc[0]; pSurf[1] = pSrc[1]; pSurf[2] = pSrc[2]; } } else if (bpp==32) { int dJump = (ddsd.lPitch>>2) - 320; int cw, ch; ULONG *pSurf = (ULONG *)ddsd.lpSurface; for (ch=200; ch; --ch, pSurf+=dJump) for (cw=320; cw; --cw, ++pBuf, ++pSurf) *pSurf = pWinPal32[*pBuf]; } pDDSurf->Unlock (NULL); // Scale with hardware if (exclusive) { if (yoff) { pDDSurf2->Blt (&boxrect, pDDSurf, NULL, DDBLT_WAIT, NULL); Win32ClearBoxEdges (yoff, w, h); } else pDDSurf2->Blt (NULL, pDDSurf, NULL, DDBLT_WAIT, NULL); } else if (winintermediatebuf) { pDDSurf3->Blt (NULL, pDDSurf, NULL, DDBLT_WAIT, NULL); pDDSurf2->Blt (&clrect, pDDSurf3, NULL, DDBLT_WAIT, NULL); } else pDDSurf2->Blt (&clrect, pDDSurf, NULL, DDBLT_WAIT, NULL); } extern "C" void VideoMaskedBlit (UCHAR *pData, long x, long y, long w, long h, long jump) { if (nodraw) return; // Copy to backbuffer int cw; int dJump = 320-w; UCHAR *pBuf = (UCHAR *)pBackBuf + x + 320*y; for (; h; --h, pData+=jump, pBuf+=dJump) for (cw=w; cw; --cw, ++pData, ++pBuf) if (*pData) *pBuf = *pData; } extern "C" void VideoReverseBlit (UCHAR *pData, long x, long y, long w, long h, long jump) { if (nodraw) return; // Copy from backbuffer... UCHAR *pBuf = pBackBuf + x + y*320; for (; h; --h, pData+=jump+w, pBuf+=320) memcpy (pData, pBuf, w); if (w != 320) return; // One flip per frame } extern "C" void VideoGetPalValue (long palindex, UCHAR *pVal) { ULONG col = pWinPal32[palindex]; pVal[0] = (UCHAR)(col >> 18 & 0x3f); pVal[1] = (UCHAR)(col >> 10 & 0x3f); pVal[2] = (UCHAR)(col >> 2 & 0x3f); } extern "C" void VideoSetPalValue (long palindex, UCHAR *pVal) { UCHAR pCol[4]; pCol[0] = pPalTable[0][pVal[0]]; pCol[1] = pPalTable[1][pVal[1]]; pCol[2] = pPalTable[2][pVal[2]]; if (bpp == 8) { PALETTEENTRY pe; pe.peRed = pCol[0] << 2; pe.peGreen = pCol[1] << 2; pe.peBlue = pCol[2] << 2; pDDPal->SetEntries (0, palindex, 1, &pe); } pWinPal15[palindex] = (ULONG)((pCol[0] << 9 & 0x7c00) + (pCol[1] << 4 & 0x03e0) + (pCol[2] >> 1)); pWinPal16[palindex] = (ULONG)((pCol[0] << 10 & 0xf800) + (pCol[1] << 5 & 0x07e0) + (pCol[2] >> 1)); pWinPal32[palindex] = (ULONG)((pCol[0] << 18 & 0xfc0000) + (pCol[1] << 10 & 0xfc00) + (pCol[2] << 2)); pWinPal15[palindex] |= pWinPal15[palindex] << 16; pWinPal16[palindex] |= pWinPal16[palindex] << 16; }