Video & FrameBase: better split (PR #908)

* Video / FrameBase: move arch specific code to FrameBase.
* Video::Initialize & SetFrameBuffer.
Ensure initialization and SetBuffer can only happen in the right order.
* Video: move virtual functions to FrameBase.
With these changes all the virtual functions are in FrameBase and Video gets closer to be (only) the Apple ][ Video device.
* Move a few more functions from Video to FrameBase (snapshot related)
Now, the inclusion is one way with Video *not* including FrameBase.
* FrameBase::VideoRefreshScreen move Video related code to Video.
And only leave management to FrameBase.
This commit is contained in:
Andrea 2021-01-03 16:21:24 +00:00 committed by GitHub
parent 0139878dd7
commit 159cde7d64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 751 additions and 781 deletions

View File

@ -1001,14 +1001,6 @@
RelativePath=".\source\Windows\WinFrame.h"
>
</File>
<File
RelativePath=".\source\Windows\WinVideo.cpp"
>
</File>
<File
RelativePath=".\source\Windows\WinVideo.h"
>
</File>
</Filter>
<Filter
Name="Configuration"

View File

@ -122,7 +122,6 @@
<ClInclude Include="source\Windows\DirectInput.h" />
<ClInclude Include="source\Windows\Win32Frame.h" />
<ClInclude Include="source\Windows\WinFrame.h" />
<ClInclude Include="source\Windows\WinVideo.h" />
<ClInclude Include="source\YamlHelper.h" />
<ClInclude Include="source\z80emu.h" />
<ClInclude Include="source\Z80VICE\daa.h" />
@ -243,7 +242,6 @@
<ClCompile Include="source\Windows\DirectInput.cpp" />
<ClCompile Include="source\Windows\Win32Frame.cpp" />
<ClCompile Include="source\Windows\WinFrame.cpp" />
<ClCompile Include="source\Windows\WinVideo.cpp" />
<ClCompile Include="source\YamlHelper.cpp" />
<ClCompile Include="source\z80emu.cpp" />
<ClCompile Include="source\Z80VICE\daa.cpp">

View File

@ -199,9 +199,6 @@
<ClCompile Include="source\Windows\DirectInput.cpp">
<Filter>Source Files\Windows</Filter>
</ClCompile>
<ClCompile Include="source\Windows\WinVideo.cpp">
<Filter>Source Files\Windows</Filter>
</ClCompile>
<ClCompile Include="source\Windows\WinFrame.cpp">
<Filter>Source Files\Windows</Filter>
</ClCompile>
@ -504,9 +501,6 @@
<ClInclude Include="source\Windows\DirectInput.h">
<Filter>Source Files\Windows</Filter>
</ClInclude>
<ClInclude Include="source\Windows\WinVideo.h">
<Filter>Source Files\Windows</Filter>
</ClInclude>
<ClInclude Include="source\Windows\WinFrame.h">
<Filter>Source Files\Windows</Filter>
</ClInclude>

View File

@ -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
{

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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()

View File

@ -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."),

View File

@ -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);
}

View File

@ -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[];

View File

@ -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;
}

View File

@ -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

View File

@ -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;
};

View File

@ -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:

View File

@ -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; 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 WinVideo::DDUninit(void)
{
SAFE_RELEASE(g_lpDD);
}
#undef SAFE_RELEASE
//===========================================================================

View File

@ -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;
};