diff --git a/AppleWinExpress2008.vcproj b/AppleWinExpress2008.vcproj index 5ea3a7ca..bd3930cc 100644 --- a/AppleWinExpress2008.vcproj +++ b/AppleWinExpress2008.vcproj @@ -1001,14 +1001,6 @@ RelativePath=".\source\Windows\WinFrame.h" > - - - - - @@ -243,7 +242,6 @@ - diff --git a/AppleWinExpress2019.vcxproj.filters b/AppleWinExpress2019.vcxproj.filters index 8a06c6c0..ccb2cd1a 100644 --- a/AppleWinExpress2019.vcxproj.filters +++ b/AppleWinExpress2019.vcxproj.filters @@ -199,9 +199,6 @@ Source Files\Windows - - Source Files\Windows - Source Files\Windows @@ -504,9 +501,6 @@ Source Files\Windows - - Source Files\Windows - Source Files\Windows diff --git a/source/CmdLine.cpp b/source/CmdLine.cpp index 29dea833..348232ee 100644 --- a/source/CmdLine.cpp +++ b/source/CmdLine.cpp @@ -319,7 +319,7 @@ bool ProcessCmdLine(LPSTR lpCmdLine) } else if (strcmp(lpCmdLine, "-printscreen") == 0) // Turn on display of the last filename print screen was saved to { - GetVideo().SetDisplayPrintScreenFileName(true); + GetFrame().SetDisplayPrintScreenFileName(true); } else if (strcmp(lpCmdLine, "-no-printscreen-key") == 0) // Don't try to capture PrintScreen key GH#469 { @@ -327,7 +327,7 @@ bool ProcessCmdLine(LPSTR lpCmdLine) } else if (strcmp(lpCmdLine, "-no-printscreen-dlg") == 0) // Turn off the PrintScreen warning message dialog (if PrintScreen key can't be grabbed) { - GetVideo().SetShowPrintScreenWarningDialog(false); + GetFrame().SetShowPrintScreenWarningDialog(false); } else if (strcmp(lpCmdLine, "-no-hook-system-key") == 0) // Don't hook the System keys (eg. Left-ALT+ESC/SPACE/TAB) GH#556 { diff --git a/source/Configuration/PageConfig.cpp b/source/Configuration/PageConfig.cpp index 8ff37e1b..b5026ab6 100644 --- a/source/Configuration/PageConfig.cpp +++ b/source/Configuration/PageConfig.cpp @@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../Windows/WinFrame.h" #include "../Registry.h" #include "../SerialComms.h" -#include "../Windows/WinVideo.h" #include "../resource/resource.h" CPageConfig* CPageConfig::ms_this = 0; // reinit'd in ctor @@ -116,7 +115,7 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA break; case IDC_MONOCOLOR: - GetVideo().ChooseMonochromeColor(); + GetFrame().ChooseMonochromeColor(); break; case IDC_CHECK_CONFIRM_REBOOT: @@ -318,7 +317,7 @@ void CPageConfig::DlgOK(HWND hWnd) GetVideo().VideoReinitialize(); if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG)) { - GetVideo().VideoRedrawScreen(); + GetFrame().VideoRedrawScreen(); } } diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp index e27d9172..b9159a2e 100644 --- a/source/Debugger/Debug.cpp +++ b/source/Debugger/Debug.cpp @@ -44,7 +44,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../Memory.h" #include "../NTSC.h" #include "../SoundCore.h" // SoundCore_SetFade() -#include "../Windows/WinVideo.h" #include "../Windows/WinFrame.h" // #define DEBUG_COMMAND_HELP 1 @@ -754,7 +753,7 @@ Update_t CmdBenchmarkStop (int nArgs) DebugEnd(); GetFrame().FrameRefreshStatus(DRAW_TITLE); - GetVideo().VideoRedrawScreen(); + GetFrame().VideoRedrawScreen(); DWORD currtime = GetTickCount(); while ((extbench = GetTickCount()) != currtime) ; // intentional busy-waiting @@ -6896,7 +6895,7 @@ Update_t _ViewOutput( ViewVideoPage_t iPage, int bVideoModeFlags ) } DebugVideoMode::Instance().Set(bVideoModeFlags); - GetVideo().VideoRefreshScreen( bVideoModeFlags, true ); + GetFrame().VideoRefreshScreen( bVideoModeFlags, true ); return UPDATE_NOTHING; // intentional } @@ -7447,7 +7446,7 @@ Update_t CmdWindowViewData (int nArgs) //=========================================================================== Update_t CmdWindowViewOutput (int nArgs) { - GetVideo().VideoRedrawScreen(); + GetFrame().VideoRedrawScreen(); DebugVideoMode::Instance().Set( GetVideo().GetVideoMode() ); @@ -9583,7 +9582,7 @@ void DebugDisplay( BOOL bInitDisasm/*=FALSE*/ ) { uint32_t mode = 0; DebugVideoMode::Instance().Get(&mode); - GetVideo().VideoRefreshScreen(mode, true); + GetFrame().VideoRefreshScreen(mode, true); return; } diff --git a/source/Disk.cpp b/source/Disk.cpp index 250e8e27..ee9a7e89 100644 --- a/source/Disk.cpp +++ b/source/Disk.cpp @@ -351,7 +351,7 @@ void Disk2InterfaceCard::EjectDisk(const int drive) Snapshot_UpdatePath(); SaveLastDiskImage(drive); - GetVideo().Video_ResetScreenshotCounter(""); + GetFrame().Video_ResetScreenshotCounter(""); } void Disk2InterfaceCard::UnplugDrive(const int drive) @@ -709,14 +709,14 @@ ImageError_e Disk2InterfaceCard::InsertDisk(const int drive, LPCTSTR pszImageFil GetImageTitle(pszImageFilename, pFloppy->m_imagename, pFloppy->m_fullname); Snapshot_UpdatePath(); - GetVideo().Video_ResetScreenshotCounter(pFloppy->m_imagename); + GetFrame().Video_ResetScreenshotCounter(pFloppy->m_imagename); if (g_nAppMode == MODE_LOGO) InitFirmware(GetCxRomPeripheral()); } else { - GetVideo().Video_ResetScreenshotCounter(""); + GetFrame().Video_ResetScreenshotCounter(""); } SaveLastDiskImage(drive); diff --git a/source/FrameBase.cpp b/source/FrameBase.cpp index 1c4722be..ea41ea20 100644 --- a/source/FrameBase.cpp +++ b/source/FrameBase.cpp @@ -1,6 +1,9 @@ #include "StdAfx.h" #include "FrameBase.h" +#include "Interface.h" +#include "Core.h" +#include "NTSC.h" FrameBase::FrameBase() { @@ -9,9 +12,135 @@ FrameBase::FrameBase() g_bMultiMon = 0; // OFF = load window position & clamp initial frame to screen, ON = use window position as is g_bFreshReset = false; g_hInstance = (HINSTANCE)0; + g_bDisplayPrintScreenFileName = false; + g_bShowPrintScreenWarningDialog = true; } FrameBase::~FrameBase() { } + +void FrameBase::VideoRefreshScreen(uint32_t uRedrawWholeScreenVideoMode, bool bRedrawWholeScreen) +{ + // regenerate video buffer if needed + GetVideo().VideoRefreshBuffer(uRedrawWholeScreenVideoMode, bRedrawWholeScreen); + + // actually draw it on screen + VideoPresentScreen(); +} + +void FrameBase::VideoRedrawScreen(void) +{ + // NB. Can't rely on g_uVideoMode being non-zero (ie. so it can double up as a flag) since 'GR,PAGE1,non-mixed' mode == 0x00. + VideoRefreshScreen(GetVideo().GetVideoMode(), true); +} + +//=========================================================================== +void FrameBase::VideoRedrawScreenDuringFullSpeed(DWORD dwCyclesThisFrame, bool bInit /*=false*/) +{ + if (bInit) + { + // Just entered full-speed mode + dwFullSpeedStartTime = GetTickCount(); + return; + } + + DWORD dwFullSpeedDuration = GetTickCount() - dwFullSpeedStartTime; + if (dwFullSpeedDuration <= 16) // Only update after every realtime ~17ms of *continuous* full-speed + return; + + dwFullSpeedStartTime += dwFullSpeedDuration; + + VideoRedrawScreenAfterFullSpeed(dwCyclesThisFrame); +} + +void FrameBase::VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame) +{ + NTSC_VideoClockResync(dwCyclesThisFrame); + VideoRedrawScreen(); // Better (no flicker) than using: NTSC_VideoReinitialize() or VideoReinitialize() +} + +void FrameBase::Video_RedrawAndTakeScreenShot(const char* pScreenshotFilename) +{ + _ASSERT(pScreenshotFilename); + if (!pScreenshotFilename) + return; + + VideoRedrawScreen(); + Video_SaveScreenShot(Video::SCREENSHOT_560x384, pScreenshotFilename); +} + +void FrameBase::Video_TakeScreenShot(const Video::VideoScreenShot_e ScreenShotType) +{ + TCHAR sScreenShotFileName[MAX_PATH]; + + // find last screenshot filename so we don't overwrite the existing user ones + bool bExists = true; + while (bExists) + { + if (g_nLastScreenShot > nMaxScreenShot) // Holy Crap! User has maxed the number of screenshots!? + { + TCHAR msg[512]; + StringCbPrintf(msg, 512, "You have more then %d screenshot filenames! They will no longer be saved.\n\nEither move some of your screenshots or increase the maximum in video.cpp\n", nMaxScreenShot); + MessageBox(GetFrame().g_hFrameWindow, msg, "Warning", MB_OK); + g_nLastScreenShot = 0; + return; + } + + Util_MakeScreenShotFileName(sScreenShotFileName, MAX_PATH); + bExists = Util_TestScreenShotFileName(sScreenShotFileName); + if (!bExists) + { + break; + } + g_nLastScreenShot++; + } + + Video_SaveScreenShot(ScreenShotType, sScreenShotFileName); + g_nLastScreenShot++; +} + +//=========================================================================== + +void FrameBase::Video_SaveScreenShot(const Video::VideoScreenShot_e ScreenShotType, const TCHAR* pScreenShotFileName) +{ + FILE* pFile = fopen(pScreenShotFileName, "wb"); + if (pFile) + { + GetVideo().Video_MakeScreenShot(pFile, ScreenShotType); + fclose(pFile); + } + + if (g_bDisplayPrintScreenFileName) + { + MessageBox(GetFrame().g_hFrameWindow, pScreenShotFileName, "Screen Captured", MB_OK); + } +} + +void FrameBase::Util_MakeScreenShotFileName(TCHAR* pFinalFileName_, DWORD chars) +{ + const std::string sPrefixScreenShotFileName = "AppleWin_ScreenShot"; + // TODO: g_sScreenshotDir + const std::string pPrefixFileName = !g_pLastDiskImageName.empty() ? g_pLastDiskImageName : sPrefixScreenShotFileName; + StringCbPrintf(pFinalFileName_, chars, TEXT("%s_%09d.bmp"), pPrefixFileName.c_str(), g_nLastScreenShot); +} + +// Returns TRUE if file exists, else FALSE +bool FrameBase::Util_TestScreenShotFileName(const TCHAR* pFileName) +{ + bool bFileExists = false; + FILE* pFile = fopen(pFileName, "rt"); + if (pFile) + { + fclose(pFile); + bFileExists = true; + } + return bFileExists; +} + +void FrameBase::Video_ResetScreenshotCounter(const std::string& pImageName) +{ + g_nLastScreenShot = 0; + g_pLastDiskImageName = pImageName; +} diff --git a/source/FrameBase.h b/source/FrameBase.h index 8f123642..315999e4 100644 --- a/source/FrameBase.h +++ b/source/FrameBase.h @@ -1,5 +1,7 @@ #pragma once +#include "Video.h" + class FrameBase { public: @@ -13,6 +15,9 @@ public: BOOL g_bMultiMon; bool g_bFreshReset; + virtual void Initialize(void) = 0; + virtual void Destroy(void) = 0; + virtual void FrameDrawDiskLEDS(HDC hdc) = 0; virtual void FrameDrawDiskStatus(HDC hdc) = 0; virtual void FrameRefreshStatus(int, bool bUpdateDiskStatus = true) = 0; @@ -25,4 +30,36 @@ public: virtual void SetAltEnterToggleFullScreen(bool mode) = 0; virtual void SetLoadedSaveStateFlag(const bool bFlag) = 0; + + virtual void VideoPresentScreen(void) = 0; + virtual void ChooseMonochromeColor(void) = 0; + virtual void Benchmark(void) = 0; + virtual void DisplayLogo(void) = 0; + + void VideoRefreshScreen(uint32_t uRedrawWholeScreenVideoMode, bool bRedrawWholeScreen); + void VideoRedrawScreen(void); + void VideoRedrawScreenDuringFullSpeed(DWORD dwCyclesThisFrame, bool bInit = false); + void VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame); + void Video_RedrawAndTakeScreenShot(const char* pScreenshotFilename); + + void Video_TakeScreenShot(const Video::VideoScreenShot_e ScreenShotType); + void Video_SaveScreenShot(const Video::VideoScreenShot_e ScreenShotType, const TCHAR* pScreenShotFileName); + void SetDisplayPrintScreenFileName(bool state) { g_bDisplayPrintScreenFileName = state; } + void Video_ResetScreenshotCounter(const std::string& pDiskImageFileName); + + bool GetShowPrintScreenWarningDialog(void) { return g_bShowPrintScreenWarningDialog; } + void SetShowPrintScreenWarningDialog(bool state) { g_bShowPrintScreenWarningDialog = state; } + +private: + void Util_MakeScreenShotFileName(TCHAR* pFinalFileName_, DWORD chars); + bool Util_TestScreenShotFileName(const TCHAR* pFileName); + + bool g_bShowPrintScreenWarningDialog; + + DWORD dwFullSpeedStartTime; + bool g_bDisplayPrintScreenFileName; + + int g_nLastScreenShot; + std::string g_pLastDiskImageName; + static const int nMaxScreenShot = 999999999; }; diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp index e6eb34b6..6d43aa8a 100644 --- a/source/Keyboard.cpp +++ b/source/Keyboard.cpp @@ -36,7 +36,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "Pravets.h" #include "Tape.h" #include "YamlHelper.h" -#include "Windows/WinVideo.h" // Needed by TK3000 //e, to refresh the frame at each |Mode| change #include "Log.h" static BYTE asciicode[2][10] = { @@ -303,7 +302,7 @@ void KeybQueueKeypress (WPARAM key, Keystroke_e bASCII) { g_bTK3KModeKey = (GetKeyState(VK_SCROLL) & 1) ? true : false; // Sync with the Scroll Lock status GetFrame().FrameRefreshStatus(DRAW_LEDS); // TODO: Implement |Mode| LED in the UI; make it appear only when in TK3000 mode - GetVideo().VideoRedrawScreen(); // TODO: Still need to implement page mode switching and 'whatnot' + GetFrame().VideoRedrawScreen(); // TODO: Still need to implement page mode switching and 'whatnot' } return; } diff --git a/source/NTSC.cpp b/source/NTSC.cpp index e4c7c55e..45bafa9f 100644 --- a/source/NTSC.cpp +++ b/source/NTSC.cpp @@ -101,10 +101,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define VIDEO_SCANNER_Y_MIXED 160 // num scanlins for mixed graphics + text #define VIDEO_SCANNER_Y_DISPLAY 192 // max displayable scanlines - static bgra_t *g_pVideoAddress = 0; + // these are initialized in NTSC_VideoInit + static bgra_t* g_pVideoAddress = 0; static bgra_t *g_pScanLines[VIDEO_SCANNER_Y_DISPLAY*2]; // To maintain the 280x192 aspect ratio for 560px width, we double every scan line -> 560x384 - - static const UINT g_kFrameBufferWidth = GetVideo().GetFrameBufferWidth(); + static UINT g_kFrameBufferWidth; static unsigned short (*g_pHorzClockOffset)[VIDEO_SCANNER_MAX_HORZ] = 0; @@ -2090,6 +2090,8 @@ void NTSC_Destroy(void) // After a VM restart, this will point to an old FrameBuffer // - if it's now unmapped then this can cause a crash in NTSC_SetVideoMode()! g_pVideoAddress = 0; + g_kFrameBufferWidth = 0; + memset(g_pScanLines, 0, sizeof(g_pScanLines)); } void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit @@ -2100,6 +2102,8 @@ void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit initChromaPhaseTables(); updateMonochromeTables( 0xFF, 0xFF, 0xFF ); + g_kFrameBufferWidth = GetVideo().GetFrameBufferWidth(); + for (int y = 0; y < (VIDEO_SCANNER_Y_DISPLAY*2); y++) { uint32_t offset = sizeof(bgra_t) * GetVideo().GetFrameBufferWidth() diff --git a/source/Speaker.cpp b/source/Speaker.cpp index 7db89dbd..ef68e96e 100644 --- a/source/Speaker.cpp +++ b/source/Speaker.cpp @@ -97,7 +97,7 @@ static void Spkr_DSUninit(); static void DisplayBenchmarkResults () { DWORD totaltime = GetTickCount()-extbench; - GetVideo().VideoRedrawScreen(); + GetFrame().VideoRedrawScreen(); TCHAR buffer[64]; wsprintf(buffer, TEXT("This benchmark took %u.%02u seconds."), diff --git a/source/Video.cpp b/source/Video.cpp index 18dcc16f..7b47c426 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -31,7 +31,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "Video.h" #include "Core.h" #include "CPU.h" -#include "Interface.h" #include "Log.h" #include "Memory.h" #include "Registry.h" @@ -437,65 +436,6 @@ bool Video::VideoGetVblBar(const DWORD uExecutedCycles) //=========================================================================== -void Video::Video_ResetScreenshotCounter(const std::string& pImageName) -{ - g_nLastScreenShot = 0; - g_pLastDiskImageName = pImageName; -} - -void Video::Util_MakeScreenShotFileName(TCHAR *pFinalFileName_, DWORD chars) -{ - const std::string sPrefixScreenShotFileName = "AppleWin_ScreenShot"; - // TODO: g_sScreenshotDir - const std::string pPrefixFileName = !g_pLastDiskImageName.empty() ? g_pLastDiskImageName : sPrefixScreenShotFileName; - StringCbPrintf( pFinalFileName_, chars, TEXT("%s_%09d.bmp"), pPrefixFileName.c_str(), g_nLastScreenShot ); -} - -// Returns TRUE if file exists, else FALSE -bool Video::Util_TestScreenShotFileName(const TCHAR *pFileName) -{ - bool bFileExists = false; - FILE *pFile = fopen( pFileName, "rt" ); - if (pFile) - { - fclose( pFile ); - bFileExists = true; - } - return bFileExists; -} - -//=========================================================================== - -void Video::Video_TakeScreenShot(const VideoScreenShot_e ScreenShotType) -{ - TCHAR sScreenShotFileName[ MAX_PATH ]; - - // find last screenshot filename so we don't overwrite the existing user ones - bool bExists = true; - while( bExists ) - { - if (g_nLastScreenShot > nMaxScreenShot) // Holy Crap! User has maxed the number of screenshots!? - { - TCHAR msg[512]; - StringCbPrintf( msg, 512, "You have more then %d screenshot filenames! They will no longer be saved.\n\nEither move some of your screenshots or increase the maximum in video.cpp\n", nMaxScreenShot ); - MessageBox( GetFrame().g_hFrameWindow, msg, "Warning", MB_OK ); - g_nLastScreenShot = 0; - return; - } - - Util_MakeScreenShotFileName(sScreenShotFileName, MAX_PATH); - bExists = Util_TestScreenShotFileName(sScreenShotFileName); - if( !bExists ) - { - break; - } - g_nLastScreenShot++; - } - - Video_SaveScreenShot(ScreenShotType, sScreenShotFileName); - g_nLastScreenShot++; -} - void Video::Video_SetBitmapHeader(WinBmpHeader_t *pBmp, int nWidth, int nHeight, int nBitsPerPixel) { pBmp->nCookie[ 0 ] = 'B'; // 0x42 @@ -603,23 +543,6 @@ void Video::Video_MakeScreenShot(FILE *pFile, const VideoScreenShot_e ScreenShot //=========================================================================== -void Video::Video_SaveScreenShot(const VideoScreenShot_e ScreenShotType, const TCHAR *pScreenShotFileName) -{ - FILE *pFile = fopen( pScreenShotFileName, "wb" ); - if( pFile ) - { - Video_MakeScreenShot( pFile, ScreenShotType ); - fclose( pFile ); - } - - if( g_bDisplayPrintScreenFileName ) - { - MessageBox( GetFrame().g_hFrameWindow, pScreenShotFileName, "Screen Captured", MB_OK ); - } -} - -//=========================================================================== - bool Video::ReadVideoRomFile(const char* pRomFile) { g_videoRomSize = 0; @@ -831,41 +754,32 @@ const char* Video::VideoGetAppWindowTitle(void) return apVideoMonitorModeDesc[ GetVideoRefreshRate() == VR_60HZ ? 0 : 1 ]; // NTSC or PAL } -void Video::VideoRedrawScreenDuringFullSpeed(DWORD dwCyclesThisFrame, bool bInit /*=false*/) + +void Video::Initialize(uint8_t* frameBuffer) { - if (bInit) - { - // Just entered full-speed mode - dwFullSpeedStartTime = GetTickCount(); - return; - } + SetFrameBuffer(frameBuffer); - DWORD dwFullSpeedDuration = GetTickCount() - dwFullSpeedStartTime; - if (dwFullSpeedDuration <= 16) // Only update after every realtime ~17ms of *continuous* full-speed - return; + // RESET THE VIDEO MODE SWITCHES AND THE CHARACTER SET OFFSET + VideoResetState(); - dwFullSpeedStartTime += dwFullSpeedDuration; + // DRAW THE SOURCE IMAGE INTO THE SOURCE BIT BUFFER + memset(GetFrameBuffer(), 0, GetFrameBufferWidth() * GetFrameBufferHeight() * sizeof(bgra_t)); - VideoRedrawScreenAfterFullSpeed(dwCyclesThisFrame); + // CREATE THE OFFSET TABLE FOR EACH SCAN LINE IN THE FRAME BUFFER + NTSC_VideoInit(GetFrameBuffer()); + +#if 0 + DDInit(); // For WaitForVerticalBlank() +#endif } -void Video::VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame) +void Video::Destroy(void) { - NTSC_VideoClockResync(dwCyclesThisFrame); - VideoRedrawScreen(); // Better (no flicker) than using: NTSC_VideoReinitialize() or VideoReinitialize() + SetFrameBuffer(NULL); + NTSC_Destroy(); } -void Video::Video_RedrawAndTakeScreenShot(const char* pScreenshotFilename) -{ - _ASSERT(pScreenshotFilename); - if (!pScreenshotFilename) - return; - - VideoRedrawScreen(); - Video_SaveScreenShot(SCREENSHOT_560x384, pScreenshotFilename); -} - -void Video::VideoRefreshScreen(uint32_t uRedrawWholeScreenVideoMode, bool bRedrawWholeScreen) +void Video::VideoRefreshBuffer(uint32_t uRedrawWholeScreenVideoMode, bool bRedrawWholeScreen) { if (bRedrawWholeScreen || g_nAppMode == MODE_PAUSED) { @@ -881,12 +795,4 @@ void Video::VideoRefreshScreen(uint32_t uRedrawWholeScreenVideoMode, bool bRedra if (g_nAppMode == MODE_DEBUG || g_nAppMode == MODE_PAUSED) NTSC_VideoRedrawWholeScreen(); } - - VideoPresentScreen(); -} - -void Video::VideoRedrawScreen(void) -{ - // NB. Can't rely on g_uVideoMode being non-zero (ie. so it can double up as a flag) since 'GR,PAGE1,non-mixed' mode == 0x00. - VideoRefreshScreen(GetVideoMode(), true); } diff --git a/source/Video.h b/source/Video.h index 51b1fa4c..72bef838 100644 --- a/source/Video.h +++ b/source/Video.h @@ -191,38 +191,14 @@ public: g_eVideoStyle = VS_HALF_SCANLINES; g_bVideoScannerNTSC = true; g_nMonochromeRGB = RGB(0xC0,0xC0,0xC0); - g_bDisplayPrintScreenFileName = false; - g_bShowPrintScreenWarningDialog = true; - g_nLastScreenShot = 0; g_videoRomSize = 0; g_videoRomRockerSwitch = false; } - virtual ~Video(void) - { - } - - virtual void Initialize(void) - { - } - - virtual void Destroy(void) - { - } - - virtual void VideoPresentScreen(void) = 0; - virtual void ChooseMonochromeColor(void) = 0; - virtual void Benchmark(void) = 0; - virtual void DisplayLogo(void) = 0; - - void VideoRefreshScreen(uint32_t uRedrawWholeScreenVideoMode, bool bRedrawWholeScreen); - void VideoRedrawScreenDuringFullSpeed(DWORD dwCyclesThisFrame, bool bInit = false); - void VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame); - void Video_RedrawAndTakeScreenShot(const char* pScreenshotFilename); - void VideoRedrawScreen(void); + void Initialize(uint8_t* frameBuffer); // Do not call directly. Call FrameBase::Initialize() + void Destroy(void); // Call FrameBase::Destroy() uint8_t* GetFrameBuffer(void) { return g_pFramebufferbits; } - void SetFrameBuffer(uint8_t* frameBuffer) { g_pFramebufferbits = frameBuffer; } // size of the video buffer stored in g_pFramebufferbits UINT GetFrameBufferBorderlessWidth(void); @@ -237,6 +213,7 @@ public: void VideoReinitialize(bool bInitVideoScannerAddress = true); void VideoResetState(void); + void VideoRefreshBuffer(uint32_t uRedrawWholeScreenVideoMode, bool bRedrawWholeScreen); enum VideoScanner_e {VS_FullAddr, VS_PartialAddrV, VS_PartialAddrH}; WORD VideoGetScannerAddress(DWORD nCycles, VideoScanner_e videoScannerAddr = VS_FullAddr); @@ -255,19 +232,14 @@ public: void VideoSaveSnapshot(class YamlSaveHelper& yamlSaveHelper); void VideoLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version); - void Video_ResetScreenshotCounter(const std::string & pDiskImageFileName); enum VideoScreenShot_e { SCREENSHOT_560x384 = 0, SCREENSHOT_280x192 }; - void Video_TakeScreenShot(VideoScreenShot_e ScreenShotType); void Video_SetBitmapHeader(WinBmpHeader_t *pBmp, int nWidth, int nHeight, int nBitsPerPixel); - void Video_SaveScreenShot(const VideoScreenShot_e ScreenShotType, const TCHAR* pScreenShotFileName); - void SetDisplayPrintScreenFileName(bool state) { g_bDisplayPrintScreenFileName = state; } - bool GetShowPrintScreenWarningDialog(void) { return g_bShowPrintScreenWarningDialog; } - void SetShowPrintScreenWarningDialog(bool state) { g_bShowPrintScreenWarningDialog = state; } + void Video_MakeScreenShot(FILE* pFile, const VideoScreenShot_e ScreenShotType); BYTE VideoSetMode(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles); @@ -303,10 +275,8 @@ protected: uint8_t *g_pFramebufferbits; private: - void Util_MakeScreenShotFileName(TCHAR *pFinalFileName_, DWORD chars); - bool Util_TestScreenShotFileName(const TCHAR *pFileName); - void Video_MakeScreenShot(FILE *pFile, const VideoScreenShot_e ScreenShotType); + void SetFrameBuffer(uint8_t* frameBuffer) { g_pFramebufferbits = frameBuffer; } std::string VideoGetSnapshotStructName(void); int g_nAltCharSetOffset; @@ -318,13 +288,6 @@ private: WinBmpHeader_t g_tBmpHeader; - bool g_bDisplayPrintScreenFileName; - bool g_bShowPrintScreenWarningDialog; - - int g_nLastScreenShot; - static const int nMaxScreenShot = 999999999; - std::string g_pLastDiskImageName; - static const int kVDisplayableScanLines = 192; // max displayable scanlines static const UINT kVideoRomSize8K = kVideoRomSize4K*2; @@ -334,8 +297,6 @@ private: UINT g_videoRomSize; bool g_videoRomRockerSwitch; - DWORD dwFullSpeedStartTime; - static const char g_aVideoChoices[]; static const char m_szModeDesc0[]; diff --git a/source/Windows/AppleWin.cpp b/source/Windows/AppleWin.cpp index 70cd5efb..f20a6d6e 100644 --- a/source/Windows/AppleWin.cpp +++ b/source/Windows/AppleWin.cpp @@ -46,7 +46,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifdef USE_SPEECH_API #include "Speech.h" #endif -#include "Windows/WinVideo.h" #include "Windows/Win32Frame.h" #include "Windows/WinFrame.h" #include "RGBMonitor.h" @@ -172,7 +171,7 @@ static void ContinueExecution(void) if (g_bFullSpeed) { if (!bWasFullSpeed) - GetVideo().VideoRedrawScreenDuringFullSpeed(0, true); // Init for full-speed mode + GetFrame().VideoRedrawScreenDuringFullSpeed(0, true); // Init for full-speed mode // Don't call Spkr_Mute() - will get speaker clicks MB_Mute(); @@ -190,7 +189,7 @@ static void ContinueExecution(void) else { if (bWasFullSpeed) - GetVideo().VideoRedrawScreenAfterFullSpeed(g_dwCyclesThisFrame); + GetFrame().VideoRedrawScreenAfterFullSpeed(g_dwCyclesThisFrame); // Don't call Spkr_Demute() MB_Demute(); @@ -251,9 +250,9 @@ static void ContinueExecution(void) g_dwCyclesThisFrame -= dwClksPerFrame; if (g_bFullSpeed) - GetVideo().VideoRedrawScreenDuringFullSpeed(g_dwCyclesThisFrame); + GetFrame().VideoRedrawScreenDuringFullSpeed(g_dwCyclesThisFrame); else - GetVideo().VideoPresentScreen(); // Just copy the output of our Apple framebuffer to the system Back Buffer + GetFrame().VideoPresentScreen(); // Just copy the output of our Apple framebuffer to the system Back Buffer } #ifdef LOG_PERF_TIMINGS @@ -482,7 +481,7 @@ static void RegisterHotKeys(void) if (!bStatus[2]) msg += "\n. Ctrl+PrintScreen"; - if (GetVideo().GetShowPrintScreenWarningDialog()) + if (GetFrame().GetShowPrintScreenWarningDialog()) SHMessageBoxCheck( GetFrame().g_hFrameWindow, msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK, MB_OK, "AppleWin-75097740-8e59-444c-bc94-2d4915132599" ); msg += "\n"; @@ -840,7 +839,7 @@ static void RepeatInitialization(void) JoyInitialize(); LogFileOutput("Main: JoyInitialize()\n"); - GetVideo().Initialize(); // g_pFramebufferinfo been created now & COM init'ed + GetFrame().Initialize(); // g_pFramebufferinfo been created now & COM init'ed LogFileOutput("Main: VideoInitialize()\n"); LogFileOutput("Main: FrameCreateWindow() - pre\n"); @@ -975,7 +974,7 @@ static void RepeatInitialization(void) if (g_cmdLine.szScreenshotFilename) { - GetVideo().Video_RedrawAndTakeScreenShot(g_cmdLine.szScreenshotFilename); + GetFrame().Video_RedrawAndTakeScreenShot(g_cmdLine.szScreenshotFilename); g_cmdLine.bShutdown = true; } @@ -1058,6 +1057,6 @@ FrameBase& GetFrame(void) Video& GetVideo(void) { - static WinVideo video; + static Video video; return video; } diff --git a/source/Windows/Win32Frame.cpp b/source/Windows/Win32Frame.cpp index 0545b7af..bb7a8893 100644 --- a/source/Windows/Win32Frame.cpp +++ b/source/Windows/Win32Frame.cpp @@ -1,6 +1,501 @@ #include "StdAfx.h" #include "Windows/Win32Frame.h" +#include "Windows/WinFrame.h" +#include "Interface.h" +#include "Core.h" +#include "CPU.h" +#include "Joystick.h" +#include "Log.h" +#include "Memory.h" +#include "CardManager.h" +#include "../resource/resource.h" // Win32Frame methods are implemented in AppleWin, WinFrame and WinVideo. // in time they should be brought together and more freestanding functions added to Win32Frame. + +Win32Frame::Win32Frame() +{ + g_pFramebufferinfo = NULL; + num_draw_devices = 0; + g_lpDD = NULL; + g_hLogoBitmap = (HBITMAP)0; + g_hDeviceBitmap = (HBITMAP)0; + g_hDeviceDC = (HDC)0; +} + +void Win32Frame::videoCreateDIBSection(Video & video) +{ + // CREATE THE DEVICE CONTEXT + HWND window = GetDesktopWindow(); + HDC dc = GetDC(window); + if (g_hDeviceDC) + { + DeleteDC(g_hDeviceDC); + } + g_hDeviceDC = CreateCompatibleDC(dc); + + // CREATE THE FRAME BUFFER DIB SECTION + if (g_hDeviceBitmap) + DeleteObject(g_hDeviceBitmap); + + uint8_t* pFramebufferbits; + + g_hDeviceBitmap = CreateDIBSection( + dc, + g_pFramebufferinfo, + DIB_RGB_COLORS, + (LPVOID*)&pFramebufferbits, 0, 0 + ); + SelectObject(g_hDeviceDC, g_hDeviceBitmap); + video.Initialize(pFramebufferbits); +} + +void Win32Frame::Initialize(void) +{ + // LOAD THE LOGO + g_hLogoBitmap = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_APPLEWIN)); + + // CREATE A BITMAPINFO STRUCTURE FOR THE FRAME BUFFER + g_pFramebufferinfo = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)]; + + Video & video = GetVideo(); + + memset(g_pFramebufferinfo, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + g_pFramebufferinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + g_pFramebufferinfo->bmiHeader.biWidth = video.GetFrameBufferWidth(); + g_pFramebufferinfo->bmiHeader.biHeight = video.GetFrameBufferHeight(); + g_pFramebufferinfo->bmiHeader.biPlanes = 1; + g_pFramebufferinfo->bmiHeader.biBitCount = 32; + g_pFramebufferinfo->bmiHeader.biCompression = BI_RGB; + g_pFramebufferinfo->bmiHeader.biClrUsed = 0; + + videoCreateDIBSection(video); + +#if 0 + DDInit(); // For WaitForVerticalBlank() +#endif +} + +void Win32Frame::Destroy(void) +{ + // DESTROY BUFFERS + delete[] g_pFramebufferinfo; + g_pFramebufferinfo = NULL; + + // DESTROY FRAME BUFFER + DeleteDC(g_hDeviceDC); + g_hDeviceDC = (HDC)0; + + DeleteObject(g_hDeviceBitmap); // this invalidates the Video's FrameBuffer pointer + GetVideo().Destroy(); // this resets the Video's FrameBuffer pointer + g_hDeviceBitmap = (HBITMAP)0; + + // DESTROY LOGO + if (g_hLogoBitmap) { + DeleteObject(g_hLogoBitmap); + g_hLogoBitmap = (HBITMAP)0; + } + + DDUninit(); +} + +//=========================================================================== +void Win32Frame::Benchmark(void) +{ + _ASSERT(g_nAppMode == MODE_BENCHMARK); + Sleep(500); + Video& video = GetVideo(); + + // PREPARE TWO DIFFERENT FRAME BUFFERS, EACH OF WHICH HAVE HALF OF THE + // BYTES SET TO 0x14 AND THE OTHER HALF SET TO 0xAA + int loop; + LPDWORD mem32 = (LPDWORD)mem; + for (loop = 4096; loop < 6144; loop++) + *(mem32 + loop) = ((loop & 1) ^ ((loop & 0x40) >> 6)) ? 0x14141414 + : 0xAAAAAAAA; + for (loop = 6144; loop < 8192; loop++) + *(mem32 + loop) = ((loop & 1) ^ ((loop & 0x40) >> 6)) ? 0xAAAAAAAA + : 0x14141414; + + // SEE HOW MANY TEXT FRAMES PER SECOND WE CAN PRODUCE WITH NOTHING ELSE + // GOING ON, CHANGING HALF OF THE BYTES IN THE VIDEO BUFFER EACH FRAME TO + // SIMULATE THE ACTIVITY OF AN AVERAGE GAME + DWORD totaltextfps = 0; + + video.SetVideoMode(VF_TEXT); + memset(mem + 0x400, 0x14, 0x400); + VideoRedrawScreen(); + DWORD milliseconds = GetTickCount(); + while (GetTickCount() == milliseconds); + milliseconds = GetTickCount(); + DWORD cycle = 0; + do { + if (cycle & 1) + memset(mem + 0x400, 0x14, 0x400); + else + memcpy(mem + 0x400, mem + ((cycle & 2) ? 0x4000 : 0x6000), 0x400); + VideoPresentScreen(); + if (cycle++ >= 3) + cycle = 0; + totaltextfps++; + } while (GetTickCount() - milliseconds < 1000); + + // SEE HOW MANY HIRES FRAMES PER SECOND WE CAN PRODUCE WITH NOTHING ELSE + // GOING ON, CHANGING HALF OF THE BYTES IN THE VIDEO BUFFER EACH FRAME TO + // SIMULATE THE ACTIVITY OF AN AVERAGE GAME + DWORD totalhiresfps = 0; + video.SetVideoMode(VF_HIRES); + memset(mem + 0x2000, 0x14, 0x2000); + VideoRedrawScreen(); + milliseconds = GetTickCount(); + while (GetTickCount() == milliseconds); + milliseconds = GetTickCount(); + cycle = 0; + do { + if (cycle & 1) + memset(mem + 0x2000, 0x14, 0x2000); + else + memcpy(mem + 0x2000, mem + ((cycle & 2) ? 0x4000 : 0x6000), 0x2000); + VideoPresentScreen(); + if (cycle++ >= 3) + cycle = 0; + totalhiresfps++; + } while (GetTickCount() - milliseconds < 1000); + + // DETERMINE HOW MANY 65C02 CLOCK CYCLES WE CAN EMULATE PER SECOND WITH + // NOTHING ELSE GOING ON + DWORD totalmhz10[2] = { 0,0 }; // bVideoUpdate & !bVideoUpdate + for (UINT i = 0; i < 2; i++) + { + CpuSetupBenchmark(); + milliseconds = GetTickCount(); + while (GetTickCount() == milliseconds); + milliseconds = GetTickCount(); + do { + CpuExecute(100000, i == 0 ? true : false); + totalmhz10[i]++; + } while (GetTickCount() - milliseconds < 1000); + } + + // IF THE PROGRAM COUNTER IS NOT IN THE EXPECTED RANGE AT THE END OF THE + // CPU BENCHMARK, REPORT AN ERROR AND OPTIONALLY TRACK IT DOWN + if ((regs.pc < 0x300) || (regs.pc > 0x400)) + if (MessageBox(g_hFrameWindow, + TEXT("The emulator has detected a problem while running ") + TEXT("the CPU benchmark. Would you like to gather more ") + TEXT("information?"), + TEXT("Benchmarks"), + MB_ICONQUESTION | MB_YESNO | MB_SETFOREGROUND) == IDYES) { + BOOL error = 0; + WORD lastpc = 0x300; + int loop = 0; + while ((loop < 10000) && !error) { + CpuSetupBenchmark(); + CpuExecute(loop, true); + if ((regs.pc < 0x300) || (regs.pc > 0x400)) + error = 1; + else { + lastpc = regs.pc; + ++loop; + } + } + if (error) { + TCHAR outstr[256]; + wsprintf(outstr, + TEXT("The emulator experienced an error %u clock cycles ") + TEXT("into the CPU benchmark. Prior to the error, the ") + TEXT("program counter was at $%04X. After the error, it ") + TEXT("had jumped to $%04X."), + (unsigned)loop, + (unsigned)lastpc, + (unsigned)regs.pc); + MessageBox(g_hFrameWindow, + outstr, + TEXT("Benchmarks"), + MB_ICONINFORMATION | MB_SETFOREGROUND); + } + else + MessageBox(g_hFrameWindow, + TEXT("The emulator was unable to locate the exact ") + TEXT("point of the error. This probably means that ") + TEXT("the problem is external to the emulator, ") + TEXT("happening asynchronously, such as a problem in ") + TEXT("a timer interrupt handler."), + TEXT("Benchmarks"), + MB_ICONINFORMATION | MB_SETFOREGROUND); + } + + // DO A REALISTIC TEST OF HOW MANY FRAMES PER SECOND WE CAN PRODUCE + // WITH FULL EMULATION OF THE CPU, JOYSTICK, AND DISK HAPPENING AT + // THE SAME TIME + DWORD realisticfps = 0; + memset(mem + 0x2000, 0xAA, 0x2000); + VideoRedrawScreen(); + milliseconds = GetTickCount(); + while (GetTickCount() == milliseconds); + milliseconds = GetTickCount(); + cycle = 0; + do { + if (realisticfps < 10) { + int cycles = 100000; + while (cycles > 0) { + DWORD executedcycles = CpuExecute(103, true); + cycles -= executedcycles; + GetCardMgr().GetDisk2CardMgr().UpdateDriveState(executedcycles); + JoyUpdateButtonLatch(executedcycles); + } + } + if (cycle & 1) + memset(mem + 0x2000, 0xAA, 0x2000); + else + memcpy(mem + 0x2000, mem + ((cycle & 2) ? 0x4000 : 0x6000), 0x2000); + VideoRedrawScreen(); + if (cycle++ >= 3) + cycle = 0; + realisticfps++; + } while (GetTickCount() - milliseconds < 1000); + + // DISPLAY THE RESULTS + DisplayLogo(); + TCHAR outstr[256]; + wsprintf(outstr, + TEXT("Pure Video FPS:\t%u hires, %u text\n") + TEXT("Pure CPU MHz:\t%u.%u%s (video update)\n") + TEXT("Pure CPU MHz:\t%u.%u%s (full-speed)\n\n") + TEXT("EXPECTED AVERAGE VIDEO GAME\n") + TEXT("PERFORMANCE: %u FPS"), + (unsigned)totalhiresfps, + (unsigned)totaltextfps, + (unsigned)(totalmhz10[0] / 10), (unsigned)(totalmhz10[0] % 10), (LPCTSTR)(IS_APPLE2 ? TEXT(" (6502)") : TEXT("")), + (unsigned)(totalmhz10[1] / 10), (unsigned)(totalmhz10[1] % 10), (LPCTSTR)(IS_APPLE2 ? TEXT(" (6502)") : TEXT("")), + (unsigned)realisticfps); + MessageBox(g_hFrameWindow, + outstr, + TEXT("Benchmarks"), + MB_ICONINFORMATION | MB_SETFOREGROUND); +} + +//=========================================================================== + +// This is called from PageConfig +void Win32Frame::ChooseMonochromeColor(void) +{ + Video& video = GetVideo(); + CHOOSECOLOR cc; + memset(&cc, 0, sizeof(CHOOSECOLOR)); + cc.lStructSize = sizeof(CHOOSECOLOR); + cc.hwndOwner = g_hFrameWindow; + cc.rgbResult = video.GetMonochromeRGB(); + cc.lpCustColors = customcolors + 1; + cc.Flags = CC_RGBINIT | CC_SOLIDCOLOR; + if (ChooseColor(&cc)) + { + video.SetMonochromeRGB(cc.rgbResult); + video.VideoReinitialize(); + if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG)) + { + VideoRedrawScreen(); + } + video.Config_Save_Video(); + } +} + +//=========================================================================== + +void Win32Frame::VideoDrawLogoBitmap(HDC hDstDC, int xoff, int yoff, int srcw, int srch, int scale) +{ + HDC hSrcDC = CreateCompatibleDC(hDstDC); + SelectObject(hSrcDC, g_hLogoBitmap); + StretchBlt( + hDstDC, // hdcDest + xoff, yoff, // nXDest, nYDest + scale * srcw, scale * srch, // nWidth, nHeight + hSrcDC, // hdcSrc + 0, 0, // nXSrc, nYSrc + srcw, srch, + SRCCOPY // dwRop + ); + + DeleteObject(hSrcDC); +} + +//=========================================================================== + +void Win32Frame::DisplayLogo(void) +{ + Video& video = GetVideo(); + int nLogoX = 0, nLogoY = 0; + int scale = GetViewportScale(); + + HDC hFrameDC = FrameGetDC(); + + // DRAW THE LOGO + SelectObject(hFrameDC, GetStockObject(NULL_PEN)); + + if (g_hLogoBitmap) + { + BITMAP bm; + if (GetObject(g_hLogoBitmap, sizeof(bm), &bm)) + { + nLogoX = (g_nViewportCX - scale * bm.bmWidth) / 2; + nLogoY = (g_nViewportCY - scale * bm.bmHeight) / 2; + + if (IsFullScreen()) + { + nLogoX += GetFullScreenOffsetX(); + nLogoY += GetFullScreenOffsetY(); + } + + VideoDrawLogoBitmap(hFrameDC, nLogoX, nLogoY, bm.bmWidth, bm.bmHeight, scale); + } + } + + // DRAW THE VERSION NUMBER + TCHAR sFontName[] = TEXT("Arial"); + HFONT font = CreateFont(-20, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + VARIABLE_PITCH | 4 | FF_SWISS, + sFontName); + SelectObject(hFrameDC, font); + SetTextAlign(hFrameDC, TA_RIGHT | TA_TOP); + SetBkMode(hFrameDC, TRANSPARENT); + + TCHAR szVersion[64]; + StringCbPrintf(szVersion, 64, "Version %s", VERSIONSTRING); + int xoff = GetFullScreenOffsetX(), yoff = GetFullScreenOffsetY(); + +#define DRAWVERSION(x,y,c) \ + SetTextColor(hFrameDC,c); \ + TextOut(hFrameDC, \ + scale*540+x+xoff,scale*358+y+yoff, \ + szVersion, \ + strlen(szVersion)); + + if (GetDeviceCaps(hFrameDC, PLANES) * GetDeviceCaps(hFrameDC, BITSPIXEL) <= 4) { + DRAWVERSION(2, 2, RGB(0x00, 0x00, 0x00)); + DRAWVERSION(1, 1, RGB(0x00, 0x00, 0x00)); + DRAWVERSION(0, 0, RGB(0xFF, 0x00, 0xFF)); + } + else { + DRAWVERSION(1, 1, PALETTERGB(0x30, 0x30, 0x70)); + DRAWVERSION(-1, -1, PALETTERGB(0xC0, 0x70, 0xE0)); + DRAWVERSION(0, 0, PALETTERGB(0x70, 0x30, 0xE0)); + } + +#if _DEBUG + StringCbPrintf(szVersion, 64, "DEBUG"); + DRAWVERSION(2, -358 * scale, RGB(0x00, 0x00, 0x00)); + DRAWVERSION(1, -357 * scale, RGB(0x00, 0x00, 0x00)); + DRAWVERSION(0, -356 * scale, RGB(0xFF, 0x00, 0xFF)); +#endif + +#undef DRAWVERSION + + DeleteObject(font); +} + +//=========================================================================== + +void Win32Frame::VideoPresentScreen(void) +{ + HDC hFrameDC = FrameGetDC(); + + if (hFrameDC) + { + Video& video = GetVideo(); + int xSrc = video.GetFrameBufferBorderWidth(); + int ySrc = video.GetFrameBufferBorderHeight(); + + int xdest = IsFullScreen() ? GetFullScreenOffsetX() : 0; + int ydest = IsFullScreen() ? GetFullScreenOffsetY() : 0; + int wdest = g_nViewportCX; + int hdest = g_nViewportCY; + + SetStretchBltMode(hFrameDC, COLORONCOLOR); + StretchBlt( + hFrameDC, + xdest, ydest, + wdest, hdest, + g_hDeviceDC, + xSrc, ySrc, + video.GetFrameBufferBorderlessWidth(), video.GetFrameBufferBorderlessHeight(), + SRCCOPY); + } + +#ifdef NO_DIRECT_X +#else + //if (g_lpDD) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL); +#endif // NO_DIRECT_X + + GdiFlush(); +} + +//=========================================================================== + +BOOL CALLBACK Win32Frame::DDEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext) +{ + Win32Frame* obj = (Win32Frame*)lpContext; + + int i = obj->num_draw_devices; + if (i == MAX_DRAW_DEVICES) + return TRUE; + if (lpGUID != NULL) + memcpy(&(obj->draw_device_guid[i]), lpGUID, sizeof(GUID)); + obj->draw_devices[i] = _strdup(lpszDesc); + + if (g_fh) fprintf(g_fh, "%d: %s - %s\n", i, lpszDesc, lpszDrvName); + + (obj->num_draw_devices)++; + return TRUE; +} + +bool Win32Frame::DDInit(void) +{ +#ifdef NO_DIRECT_X + + return false; + +#else + HRESULT hr = DirectDrawEnumerate((LPDDENUMCALLBACK)DDEnumProc, this); + if (FAILED(hr)) + { + LogFileOutput("DSEnumerate failed (%08X)\n", hr); + return false; + } + + LogFileOutput("Number of draw devices = %d\n", num_draw_devices); + + bool bCreatedOK = false; + for (int x = 0; x < num_draw_devices; x++) + { + hr = DirectDrawCreate(&draw_device_guid[x], &g_lpDD, NULL); + if (SUCCEEDED(hr)) + { + LogFileOutput("DSCreate succeeded for draw device #%d\n", x); + bCreatedOK = true; + break; + } + + LogFileOutput("DSCreate failed for draw device #%d (%08X)\n", x, hr); + } + + if (!bCreatedOK) + { + LogFileOutput("DSCreate failed for all draw devices\n"); + return false; + } + + return true; +#endif // NO_DIRECT_X +} + +// From SoundCore.h +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + +void Win32Frame::DDUninit(void) +{ + SAFE_RELEASE(g_lpDD); +} + +#undef SAFE_RELEASE diff --git a/source/Windows/Win32Frame.h b/source/Windows/Win32Frame.h index c7002aa8..e095474b 100644 --- a/source/Windows/Win32Frame.h +++ b/source/Windows/Win32Frame.h @@ -2,9 +2,13 @@ #include "FrameBase.h" +class Video; + class Win32Frame : public FrameBase { public: + Win32Frame(); + virtual void FrameDrawDiskLEDS(HDC hdc); virtual void FrameDrawDiskStatus(HDC hdc); virtual void FrameRefreshStatus(int, bool bUpdateDiskStatus = true); @@ -17,4 +21,29 @@ public: virtual void SetAltEnterToggleFullScreen(bool mode); virtual void SetLoadedSaveStateFlag(const bool bFlag); + + virtual void Initialize(void); + virtual void Destroy(void); + virtual void VideoPresentScreen(void); + virtual void ChooseMonochromeColor(void); + virtual void Benchmark(void); + virtual void DisplayLogo(void); +private: + void videoCreateDIBSection(Video& video); + void VideoDrawLogoBitmap(HDC hDstDC, int xoff, int yoff, int srcw, int srch, int scale); + static BOOL CALLBACK DDEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext); + bool DDInit(void); + void DDUninit(void); + + COLORREF customcolors[256]; // MONOCHROME is last custom color + HBITMAP g_hLogoBitmap; + HBITMAP g_hDeviceBitmap; + HDC g_hDeviceDC; + LPBITMAPINFO g_pFramebufferinfo; + + static const UINT MAX_DRAW_DEVICES = 10; + char* draw_devices[MAX_DRAW_DEVICES]; + GUID draw_device_guid[MAX_DRAW_DEVICES]; + int num_draw_devices; + LPDIRECTDRAW g_lpDD; }; diff --git a/source/Windows/WinFrame.cpp b/source/Windows/WinFrame.cpp index 98c0a1c6..bb613f55 100644 --- a/source/Windows/WinFrame.cpp +++ b/source/Windows/WinFrame.cpp @@ -46,7 +46,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "SoundCore.h" #include "Speaker.h" #include "Utilities.h" -#include "Windows/WinVideo.h" #include "../resource/resource.h" #include "Configuration/PropertySheet.h" #include "Debugger/Debug.h" @@ -585,11 +584,11 @@ static void DrawFrameWindow (bool bPaintingWindow/*=false*/) // DRAW THE CONTENTS OF THE EMULATED SCREEN if (g_nAppMode == MODE_LOGO) - GetVideo().DisplayLogo(); + GetFrame().DisplayLogo(); else if (g_nAppMode == MODE_DEBUG) DebugDisplay(); else - GetVideo().VideoRedrawScreen(); + GetFrame().VideoRedrawScreen(); if (bPaintingWindow) EndPaint(GetFrame().g_hFrameWindow,&ps); @@ -1064,7 +1063,7 @@ LRESULT CALLBACK FrameWndProc ( CpuDestroy(); MemDestroy(); SpkrDestroy(); - GetVideo().Destroy(); + GetFrame().Destroy(); MB_Destroy(); DeleteGdiObjects(); DIMouse::DirectInputUninit(window); // NB. do before window is destroyed @@ -1186,12 +1185,12 @@ LRESULT CALLBACK FrameWndProc ( // lparam = modifiers: shift, ctrl, alt, win if (wparam == VK_SNAPSHOT_560) { - GetVideo().Video_TakeScreenShot( Video::SCREENSHOT_560x384 ); + GetFrame().Video_TakeScreenShot( Video::SCREENSHOT_560x384 ); } else if (wparam == VK_SNAPSHOT_280) // ( lparam & MOD_SHIFT ) { - GetVideo().Video_TakeScreenShot( Video::SCREENSHOT_280x192 ); + GetFrame().Video_TakeScreenShot( Video::SCREENSHOT_280x192 ); } else if (wparam == VK_SNAPSHOT_TEXT) // ( lparam & MOD_CONTROL ) @@ -1254,13 +1253,13 @@ LRESULT CALLBACK FrameWndProc ( { UINT debugVideoMode; if ( DebugGetVideoMode(&debugVideoMode) ) - GetVideo().VideoRefreshScreen(debugVideoMode, true); + GetFrame().VideoRefreshScreen(debugVideoMode, true); else - GetVideo().VideoPresentScreen(); + GetFrame().VideoPresentScreen(); } else { - GetVideo().VideoPresentScreen(); + GetFrame().VideoPresentScreen(); } } @@ -1322,7 +1321,7 @@ LRESULT CALLBACK FrameWndProc ( } DrawStatusArea((HDC)0,DRAW_TITLE); if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG)) - GetVideo().VideoRedrawScreen(); + GetFrame().VideoRedrawScreen(); } else if ((wparam == VK_SCROLL) && GetPropertySheet().GetScrollLockToggle()) { @@ -1809,7 +1808,7 @@ LRESULT CALLBACK FrameWndProc ( DrawStatusArea((HDC)0,DRAW_TITLE); HCURSOR oldcursor = SetCursor(LoadCursor(0,IDC_WAIT)); g_nAppMode = MODE_BENCHMARK; - GetVideo().Benchmark(); + GetFrame().Benchmark(); g_nAppMode = MODE_LOGO; ResetMachineState(); SetCursor(oldcursor); @@ -2005,7 +2004,7 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/) } DrawStatusArea((HDC)0,DRAW_TITLE); - GetVideo().VideoRedrawScreen(); + GetFrame().VideoRedrawScreen(); break; case BTN_DRIVE1: diff --git a/source/Windows/WinVideo.cpp b/source/Windows/WinVideo.cpp deleted file mode 100644 index 2d919068..00000000 --- a/source/Windows/WinVideo.cpp +++ /dev/null @@ -1,525 +0,0 @@ -/* -AppleWin : An Apple //e emulator for Windows - -Copyright (C) 1994-1996, Michael O'Brien -Copyright (C) 1999-2001, Oliver Schmidt -Copyright (C) 2002-2005, Tom Charlesworth -Copyright (C) 2006-2010, Tom Charlesworth, Michael Pohoreski, Nick Westgate - -AppleWin is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -AppleWin is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with AppleWin; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Description: Emulation of video modes - * - * Author: Various - */ - -#include "StdAfx.h" - -#include "Windows/WinVideo.h" -#include "Windows/WinFrame.h" -#include "Windows/AppleWin.h" -#include "Interface.h" -#include "Core.h" -#include "CPU.h" -#include "Joystick.h" -#include "Log.h" -#include "Memory.h" -#include "CardManager.h" -#include "NTSC.h" - -#include "../resource/resource.h" - -void WinVideo::videoCreateDIBSection(void) -{ - // CREATE THE DEVICE CONTEXT - HWND window = GetDesktopWindow(); - HDC dc = GetDC(window); - if (g_hDeviceDC) - { - DeleteDC(g_hDeviceDC); - } - g_hDeviceDC = CreateCompatibleDC(dc); - - // CREATE THE FRAME BUFFER DIB SECTION - if (g_hDeviceBitmap) - DeleteObject(g_hDeviceBitmap); - - g_hDeviceBitmap = CreateDIBSection( - dc, - g_pFramebufferinfo, - DIB_RGB_COLORS, - (LPVOID*)&g_pFramebufferbits, 0, 0 - ); - SelectObject(g_hDeviceDC, g_hDeviceBitmap); - - // DRAW THE SOURCE IMAGE INTO THE SOURCE BIT BUFFER - memset(GetFrameBuffer(), 0, GetFrameBufferWidth() * GetFrameBufferHeight() * sizeof(bgra_t)); - - // CREATE THE OFFSET TABLE FOR EACH SCAN LINE IN THE FRAME BUFFER - NTSC_VideoInit(GetFrameBuffer()); -} - -void WinVideo::Initialize(void) -{ - Video::Initialize(); - - // RESET THE VIDEO MODE SWITCHES AND THE CHARACTER SET OFFSET - VideoResetState(); - - // LOAD THE LOGO - g_hLogoBitmap = LoadBitmap(GetFrame().g_hInstance, MAKEINTRESOURCE(IDB_APPLEWIN)); - - // CREATE A BITMAPINFO STRUCTURE FOR THE FRAME BUFFER - g_pFramebufferinfo = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)]; - - memset(g_pFramebufferinfo, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); - g_pFramebufferinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - g_pFramebufferinfo->bmiHeader.biWidth = GetFrameBufferWidth(); - g_pFramebufferinfo->bmiHeader.biHeight = GetFrameBufferHeight(); - g_pFramebufferinfo->bmiHeader.biPlanes = 1; - g_pFramebufferinfo->bmiHeader.biBitCount = 32; - g_pFramebufferinfo->bmiHeader.biCompression = BI_RGB; - g_pFramebufferinfo->bmiHeader.biClrUsed = 0; - - videoCreateDIBSection(); - -#if 0 - DDInit(); // For WaitForVerticalBlank() -#endif -} - -void WinVideo::Destroy(void) -{ - // DESTROY BUFFERS - delete [] g_pFramebufferinfo; - g_pFramebufferinfo = NULL; - - // DESTROY FRAME BUFFER - DeleteDC(g_hDeviceDC); - DeleteObject(g_hDeviceBitmap); - g_hDeviceDC = (HDC)0; - g_hDeviceBitmap = (HBITMAP)0; - SetFrameBuffer(NULL); - - // DESTROY LOGO - if (g_hLogoBitmap) { - DeleteObject(g_hLogoBitmap); - g_hLogoBitmap = (HBITMAP)0; - } - - NTSC_Destroy(); - - DDUninit(); - - Video::Destroy(); -} - -//=========================================================================== -void WinVideo::Benchmark(void) -{ - _ASSERT(g_nAppMode == MODE_BENCHMARK); - Sleep(500); - - // PREPARE TWO DIFFERENT FRAME BUFFERS, EACH OF WHICH HAVE HALF OF THE - // BYTES SET TO 0x14 AND THE OTHER HALF SET TO 0xAA - int loop; - LPDWORD mem32 = (LPDWORD)mem; - for (loop = 4096; loop < 6144; loop++) - *(mem32+loop) = ((loop & 1) ^ ((loop & 0x40) >> 6)) ? 0x14141414 - : 0xAAAAAAAA; - for (loop = 6144; loop < 8192; loop++) - *(mem32+loop) = ((loop & 1) ^ ((loop & 0x40) >> 6)) ? 0xAAAAAAAA - : 0x14141414; - - // SEE HOW MANY TEXT FRAMES PER SECOND WE CAN PRODUCE WITH NOTHING ELSE - // GOING ON, CHANGING HALF OF THE BYTES IN THE VIDEO BUFFER EACH FRAME TO - // SIMULATE THE ACTIVITY OF AN AVERAGE GAME - DWORD totaltextfps = 0; - - SetVideoMode(VF_TEXT); - memset(mem+0x400,0x14,0x400); - VideoRedrawScreen(); - DWORD milliseconds = GetTickCount(); - while (GetTickCount() == milliseconds) ; - milliseconds = GetTickCount(); - DWORD cycle = 0; - do { - if (cycle & 1) - memset(mem+0x400,0x14,0x400); - else - memcpy(mem+0x400,mem+((cycle & 2) ? 0x4000 : 0x6000),0x400); - VideoPresentScreen(); - if (cycle++ >= 3) - cycle = 0; - totaltextfps++; - } while (GetTickCount() - milliseconds < 1000); - - // SEE HOW MANY HIRES FRAMES PER SECOND WE CAN PRODUCE WITH NOTHING ELSE - // GOING ON, CHANGING HALF OF THE BYTES IN THE VIDEO BUFFER EACH FRAME TO - // SIMULATE THE ACTIVITY OF AN AVERAGE GAME - DWORD totalhiresfps = 0; - SetVideoMode(VF_HIRES); - memset(mem+0x2000,0x14,0x2000); - VideoRedrawScreen(); - milliseconds = GetTickCount(); - while (GetTickCount() == milliseconds) ; - milliseconds = GetTickCount(); - cycle = 0; - do { - if (cycle & 1) - memset(mem+0x2000,0x14,0x2000); - else - memcpy(mem+0x2000,mem+((cycle & 2) ? 0x4000 : 0x6000),0x2000); - VideoPresentScreen(); - if (cycle++ >= 3) - cycle = 0; - totalhiresfps++; - } while (GetTickCount() - milliseconds < 1000); - - // DETERMINE HOW MANY 65C02 CLOCK CYCLES WE CAN EMULATE PER SECOND WITH - // NOTHING ELSE GOING ON - DWORD totalmhz10[2] = {0,0}; // bVideoUpdate & !bVideoUpdate - for (UINT i=0; i<2; i++) - { - CpuSetupBenchmark(); - milliseconds = GetTickCount(); - while (GetTickCount() == milliseconds) ; - milliseconds = GetTickCount(); - do { - CpuExecute(100000, i==0 ? true : false); - totalmhz10[i]++; - } while (GetTickCount() - milliseconds < 1000); - } - - // IF THE PROGRAM COUNTER IS NOT IN THE EXPECTED RANGE AT THE END OF THE - // CPU BENCHMARK, REPORT AN ERROR AND OPTIONALLY TRACK IT DOWN - if ((regs.pc < 0x300) || (regs.pc > 0x400)) - if (MessageBox(GetFrame().g_hFrameWindow, - TEXT("The emulator has detected a problem while running ") - TEXT("the CPU benchmark. Would you like to gather more ") - TEXT("information?"), - TEXT("Benchmarks"), - MB_ICONQUESTION | MB_YESNO | MB_SETFOREGROUND) == IDYES) { - BOOL error = 0; - WORD lastpc = 0x300; - int loop = 0; - while ((loop < 10000) && !error) { - CpuSetupBenchmark(); - CpuExecute(loop, true); - if ((regs.pc < 0x300) || (regs.pc > 0x400)) - error = 1; - else { - lastpc = regs.pc; - ++loop; - } - } - if (error) { - TCHAR outstr[256]; - wsprintf(outstr, - TEXT("The emulator experienced an error %u clock cycles ") - TEXT("into the CPU benchmark. Prior to the error, the ") - TEXT("program counter was at $%04X. After the error, it ") - TEXT("had jumped to $%04X."), - (unsigned)loop, - (unsigned)lastpc, - (unsigned)regs.pc); - MessageBox(GetFrame().g_hFrameWindow, - outstr, - TEXT("Benchmarks"), - MB_ICONINFORMATION | MB_SETFOREGROUND); - } - else - MessageBox(GetFrame().g_hFrameWindow, - TEXT("The emulator was unable to locate the exact ") - TEXT("point of the error. This probably means that ") - TEXT("the problem is external to the emulator, ") - TEXT("happening asynchronously, such as a problem in ") - TEXT("a timer interrupt handler."), - TEXT("Benchmarks"), - MB_ICONINFORMATION | MB_SETFOREGROUND); - } - - // DO A REALISTIC TEST OF HOW MANY FRAMES PER SECOND WE CAN PRODUCE - // WITH FULL EMULATION OF THE CPU, JOYSTICK, AND DISK HAPPENING AT - // THE SAME TIME - DWORD realisticfps = 0; - memset(mem+0x2000,0xAA,0x2000); - VideoRedrawScreen(); - milliseconds = GetTickCount(); - while (GetTickCount() == milliseconds) ; - milliseconds = GetTickCount(); - cycle = 0; - do { - if (realisticfps < 10) { - int cycles = 100000; - while (cycles > 0) { - DWORD executedcycles = CpuExecute(103, true); - cycles -= executedcycles; - GetCardMgr().GetDisk2CardMgr().UpdateDriveState(executedcycles); - JoyUpdateButtonLatch(executedcycles); - } - } - if (cycle & 1) - memset(mem+0x2000,0xAA,0x2000); - else - memcpy(mem+0x2000,mem+((cycle & 2) ? 0x4000 : 0x6000),0x2000); - VideoRedrawScreen(); - if (cycle++ >= 3) - cycle = 0; - realisticfps++; - } while (GetTickCount() - milliseconds < 1000); - - // DISPLAY THE RESULTS - DisplayLogo(); - TCHAR outstr[256]; - wsprintf(outstr, - TEXT("Pure Video FPS:\t%u hires, %u text\n") - TEXT("Pure CPU MHz:\t%u.%u%s (video update)\n") - TEXT("Pure CPU MHz:\t%u.%u%s (full-speed)\n\n") - TEXT("EXPECTED AVERAGE VIDEO GAME\n") - TEXT("PERFORMANCE: %u FPS"), - (unsigned)totalhiresfps, - (unsigned)totaltextfps, - (unsigned)(totalmhz10[0] / 10), (unsigned)(totalmhz10[0] % 10), (LPCTSTR)(IS_APPLE2 ? TEXT(" (6502)") : TEXT("")), - (unsigned)(totalmhz10[1] / 10), (unsigned)(totalmhz10[1] % 10), (LPCTSTR)(IS_APPLE2 ? TEXT(" (6502)") : TEXT("")), - (unsigned)realisticfps); - MessageBox(GetFrame().g_hFrameWindow, - outstr, - TEXT("Benchmarks"), - MB_ICONINFORMATION | MB_SETFOREGROUND); -} - -//=========================================================================== - -// This is called from PageConfig -void WinVideo::ChooseMonochromeColor(void) -{ - CHOOSECOLOR cc; - memset(&cc, 0, sizeof(CHOOSECOLOR)); - cc.lStructSize = sizeof(CHOOSECOLOR); - cc.hwndOwner = GetFrame().g_hFrameWindow; - cc.rgbResult = GetMonochromeRGB(); - cc.lpCustColors = customcolors + 1; - cc.Flags = CC_RGBINIT | CC_SOLIDCOLOR; - if (ChooseColor(&cc)) - { - SetMonochromeRGB(cc.rgbResult); - VideoReinitialize(); - if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG)) - { - VideoRedrawScreen(); - } - Config_Save_Video(); - } -} - -//=========================================================================== - -void WinVideo::VideoDrawLogoBitmap(HDC hDstDC, int xoff, int yoff, int srcw, int srch, int scale) -{ - HDC hSrcDC = CreateCompatibleDC( hDstDC ); - SelectObject( hSrcDC, g_hLogoBitmap ); - StretchBlt( - hDstDC, // hdcDest - xoff, yoff, // nXDest, nYDest - scale * srcw, scale * srch, // nWidth, nHeight - hSrcDC, // hdcSrc - 0, 0, // nXSrc, nYSrc - srcw, srch, - SRCCOPY // dwRop - ); - - DeleteObject( hSrcDC ); -} - -//=========================================================================== - -void WinVideo::DisplayLogo(void) -{ - int nLogoX = 0, nLogoY = 0; - int scale = GetViewportScale(); - - HDC hFrameDC = FrameGetDC(); - - // DRAW THE LOGO - SelectObject(hFrameDC, GetStockObject(NULL_PEN)); - - if (g_hLogoBitmap) - { - BITMAP bm; - if (GetObject(g_hLogoBitmap, sizeof(bm), &bm)) - { - nLogoX = (g_nViewportCX - scale*bm.bmWidth )/2; - nLogoY = (g_nViewportCY - scale*bm.bmHeight)/2; - - if( IsFullScreen() ) - { - nLogoX += GetFullScreenOffsetX(); - nLogoY += GetFullScreenOffsetY(); - } - - VideoDrawLogoBitmap( hFrameDC, nLogoX, nLogoY, bm.bmWidth, bm.bmHeight, scale ); - } - } - - // DRAW THE VERSION NUMBER - TCHAR sFontName[] = TEXT("Arial"); - HFONT font = CreateFont(-20,0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET, - OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, - VARIABLE_PITCH | 4 | FF_SWISS, - sFontName ); - SelectObject(hFrameDC,font); - SetTextAlign(hFrameDC,TA_RIGHT | TA_TOP); - SetBkMode(hFrameDC,TRANSPARENT); - - TCHAR szVersion[ 64 ]; - StringCbPrintf(szVersion, 64, "Version %s", VERSIONSTRING); - int xoff = GetFullScreenOffsetX(), yoff = GetFullScreenOffsetY(); - -#define DRAWVERSION(x,y,c) \ - SetTextColor(hFrameDC,c); \ - TextOut(hFrameDC, \ - scale*540+x+xoff,scale*358+y+yoff, \ - szVersion, \ - strlen(szVersion)); - - if (GetDeviceCaps(hFrameDC,PLANES) * GetDeviceCaps(hFrameDC,BITSPIXEL) <= 4) { - DRAWVERSION( 2, 2,RGB(0x00,0x00,0x00)); - DRAWVERSION( 1, 1,RGB(0x00,0x00,0x00)); - DRAWVERSION( 0, 0,RGB(0xFF,0x00,0xFF)); - } else { - DRAWVERSION( 1, 1,PALETTERGB(0x30,0x30,0x70)); - DRAWVERSION(-1,-1,PALETTERGB(0xC0,0x70,0xE0)); - DRAWVERSION( 0, 0,PALETTERGB(0x70,0x30,0xE0)); - } - -#if _DEBUG - StringCbPrintf(szVersion, 64, "DEBUG"); - DRAWVERSION( 2, -358*scale,RGB(0x00,0x00,0x00)); - DRAWVERSION( 1, -357*scale,RGB(0x00,0x00,0x00)); - DRAWVERSION( 0, -356*scale,RGB(0xFF,0x00,0xFF)); -#endif - -#undef DRAWVERSION - - DeleteObject(font); -} - -//=========================================================================== - -void WinVideo::VideoPresentScreen(void) -{ - HDC hFrameDC = FrameGetDC(); - - if (hFrameDC) - { - int xSrc = GetFrameBufferBorderWidth(); - int ySrc = GetFrameBufferBorderHeight(); - - int xdest = IsFullScreen() ? GetFullScreenOffsetX() : 0; - int ydest = IsFullScreen() ? GetFullScreenOffsetY() : 0; - int wdest = g_nViewportCX; - int hdest = g_nViewportCY; - - SetStretchBltMode(hFrameDC, COLORONCOLOR); - StretchBlt( - hFrameDC, - xdest, ydest, - wdest, hdest, - g_hDeviceDC, - xSrc, ySrc, - GetFrameBufferBorderlessWidth(), GetFrameBufferBorderlessHeight(), - SRCCOPY); - } - -#ifdef NO_DIRECT_X -#else - //if (g_lpDD) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL); -#endif // NO_DIRECT_X - - GdiFlush(); -} - -//=========================================================================== - -BOOL CALLBACK WinVideo::DDEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext) -{ - WinVideo* obj = (WinVideo*)lpContext; - - int i = obj->num_draw_devices; - if (i == MAX_DRAW_DEVICES) - return TRUE; - if (lpGUID != NULL) - memcpy(&(obj->draw_device_guid[i]), lpGUID, sizeof (GUID)); - obj->draw_devices[i] = _strdup(lpszDesc); - - if (g_fh) fprintf(g_fh, "%d: %s - %s\n",i,lpszDesc,lpszDrvName); - - (obj->num_draw_devices)++; - return TRUE; -} - -bool WinVideo::DDInit(void) -{ -#ifdef NO_DIRECT_X - - return false; - -#else - HRESULT hr = DirectDrawEnumerate((LPDDENUMCALLBACK)DDEnumProc, this); - if (FAILED(hr)) - { - LogFileOutput("DSEnumerate failed (%08X)\n", hr); - return false; - } - - LogFileOutput("Number of draw devices = %d\n", num_draw_devices); - - bool bCreatedOK = false; - for (int x=0; xRelease(); (p)=NULL; } } - -void WinVideo::DDUninit(void) -{ - SAFE_RELEASE(g_lpDD); -} - -#undef SAFE_RELEASE - -//=========================================================================== diff --git a/source/Windows/WinVideo.h b/source/Windows/WinVideo.h deleted file mode 100644 index e1761aa8..00000000 --- a/source/Windows/WinVideo.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "Video.h" - -class WinVideo : public Video -{ -public: - WinVideo() - { - g_pFramebufferinfo = NULL; - num_draw_devices = 0; - g_lpDD = NULL; - } - - virtual ~WinVideo() - { - } - - virtual void Initialize(void); - virtual void Destroy(void); - - virtual void VideoPresentScreen(void); - virtual void ChooseMonochromeColor(void); - virtual void Benchmark(void); - virtual void DisplayLogo(void); - -private: - void videoCreateDIBSection(void); - void VideoDrawLogoBitmap(HDC hDstDC, int xoff, int yoff, int srcw, int srch, int scale); - static BOOL CALLBACK DDEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext); - bool DDInit(void); - void DDUninit(void); - - COLORREF customcolors[256]; // MONOCHROME is last custom color - HBITMAP g_hLogoBitmap; - HBITMAP g_hDeviceBitmap; - HDC g_hDeviceDC; - LPBITMAPINFO g_pFramebufferinfo; - - static const UINT MAX_DRAW_DEVICES = 10; - char *draw_devices[MAX_DRAW_DEVICES]; - GUID draw_device_guid[MAX_DRAW_DEVICES]; - int num_draw_devices; - LPDIRECTDRAW g_lpDD; -};