Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
78200c7a2c
18 changed files with 713 additions and 644 deletions
|
@ -621,14 +621,6 @@
|
|||
RelativePath=".\source\CardManager.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\DirectInput.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\DirectInput.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Joystick.cpp"
|
||||
>
|
||||
|
@ -958,6 +950,26 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Windows"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\source\Windows\DirectInput.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Windows\DirectInput.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Windows\WinVideo.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Windows\WinVideo.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Configuration"
|
||||
>
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
<ClInclude Include="source\Debugger\Debugger_Types.h" />
|
||||
<ClInclude Include="source\Debugger\Util_MemoryTextFile.h" />
|
||||
<ClInclude Include="source\Debugger\Util_Text.h" />
|
||||
<ClInclude Include="source\DirectInput.h" />
|
||||
<ClInclude Include="source\Disk.h" />
|
||||
<ClInclude Include="source\Disk2CardManager.h" />
|
||||
<ClInclude Include="source\DiskDefs.h" />
|
||||
|
@ -109,6 +108,8 @@
|
|||
<ClInclude Include="source\Tfe\Tfesupp.h" />
|
||||
<ClInclude Include="source\Tfe\Uilib.h" />
|
||||
<ClInclude Include="source\Video.h" />
|
||||
<ClInclude Include="source\Windows\DirectInput.h" />
|
||||
<ClInclude Include="source\Windows\WinVideo.h" />
|
||||
<ClInclude Include="source\YamlHelper.h" />
|
||||
<ClInclude Include="source\z80emu.h" />
|
||||
<ClInclude Include="source\Z80VICE\daa.h" />
|
||||
|
@ -140,7 +141,6 @@
|
|||
<ClCompile Include="source\Configuration\PropertySheet.cpp" />
|
||||
<ClCompile Include="source\Configuration\PropertySheetHelper.cpp" />
|
||||
<ClCompile Include="source\CPU.cpp" />
|
||||
<ClCompile Include="source\DirectInput.cpp" />
|
||||
<ClCompile Include="source\Disk2CardManager.cpp" />
|
||||
<ClCompile Include="source\RGBMonitor.cpp" />
|
||||
<ClCompile Include="source\SAM.cpp" />
|
||||
|
@ -214,6 +214,8 @@
|
|||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release NoDX|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\Video.cpp" />
|
||||
<ClCompile Include="source\Windows\DirectInput.cpp" />
|
||||
<ClCompile Include="source\Windows\WinVideo.cpp" />
|
||||
<ClCompile Include="source\YamlHelper.cpp" />
|
||||
<ClCompile Include="source\z80emu.cpp" />
|
||||
<ClCompile Include="source\Z80VICE\daa.cpp">
|
||||
|
|
|
@ -202,8 +202,11 @@
|
|||
<ClCompile Include="source\SynchronousEventManager.cpp">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\DirectInput.cpp">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
<ClCompile Include="source\Windows\DirectInput.cpp">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\Windows\WinVideo.cpp">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -492,8 +495,11 @@
|
|||
<ClInclude Include="source\SynchronousEventManager.h">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\DirectInput.h">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
<ClInclude Include="source\Windows\DirectInput.h">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\Windows\WinVideo.h">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -735,6 +741,9 @@
|
|||
<Filter Include="Source Files\Model">
|
||||
<UniqueIdentifier>{15b450e4-f89f-4d80-9c44-48b32f33f3e3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Windows">
|
||||
<UniqueIdentifier>{95d0abc3-4007-4eb0-8222-4579b565de23}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="resource\Applewin.rc">
|
||||
|
|
|
@ -54,7 +54,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "Speech.h"
|
||||
#endif
|
||||
#include "SynchronousEventManager.h"
|
||||
#include "Video.h"
|
||||
#include "Windows/WinVideo.h"
|
||||
#include "RGBMonitor.h"
|
||||
#include "NTSC.h"
|
||||
|
||||
|
@ -2064,7 +2064,7 @@ static void RepeatInitialization(void)
|
|||
JoyInitialize();
|
||||
LogFileOutput("Main: JoyInitialize()\n");
|
||||
|
||||
VideoInitialize(); // g_pFramebufferinfo been created now
|
||||
WinVideoInitialize(); // g_pFramebufferinfo been created now
|
||||
LogFileOutput("Main: VideoInitialize()\n");
|
||||
|
||||
LogFileOutput("Main: FrameCreateWindow() - pre\n");
|
||||
|
|
|
@ -89,7 +89,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "CPU.h"
|
||||
#include "AppleWin.h"
|
||||
#include "CardManager.h"
|
||||
#include "Frame.h"
|
||||
#include "Memory.h"
|
||||
#include "Mockingboard.h"
|
||||
#include "MouseInterface.h"
|
||||
|
|
|
@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "../Frame.h"
|
||||
#include "../Registry.h"
|
||||
#include "../SerialComms.h"
|
||||
#include "../Video.h"
|
||||
#include "../Windows/WinVideo.h"
|
||||
#include "../resource/resource.h"
|
||||
|
||||
CPageConfig* CPageConfig::ms_this = 0; // reinit'd in ctor
|
||||
|
|
|
@ -43,6 +43,7 @@ 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 "../Video.h"
|
||||
|
||||
// #define DEBUG_COMMAND_HELP 1
|
||||
|
|
|
@ -43,6 +43,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "Registry.h"
|
||||
#include "SaveState.h"
|
||||
#include "Video.h"
|
||||
#include "Windows/WinVideo.h"
|
||||
#include "YamlHelper.h"
|
||||
|
||||
#include "../resource/resource.h"
|
||||
|
|
|
@ -40,7 +40,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "Memory.h"
|
||||
#include "Mockingboard.h"
|
||||
#include "MouseInterface.h"
|
||||
#include "DirectInput.h"
|
||||
#include "Windows/DirectInput.h"
|
||||
#include "NTSC.h"
|
||||
#include "ParallelPrinter.h"
|
||||
#include "Pravets.h"
|
||||
|
@ -52,7 +52,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#ifdef USE_SPEECH_API
|
||||
#include "Speech.h"
|
||||
#endif
|
||||
#include "Video.h"
|
||||
#include "Windows/WinVideo.h"
|
||||
|
||||
#include "../resource/resource.h"
|
||||
#include "Configuration/PropertySheet.h"
|
||||
|
@ -1162,7 +1162,7 @@ LRESULT CALLBACK FrameWndProc (
|
|||
CpuDestroy();
|
||||
MemDestroy();
|
||||
SpkrDestroy();
|
||||
VideoDestroy();
|
||||
WinVideoDestroy();
|
||||
MB_Destroy();
|
||||
DeleteGdiObjects();
|
||||
DIMouse::DirectInputUninit(window); // NB. do before window is destroyed
|
||||
|
|
|
@ -507,7 +507,7 @@ static void DoAutofire(UINT uButton, BOOL& pressed)
|
|||
BOOL nowPressed = pressed;
|
||||
if (sg_PropertySheet.GetAutofire(uButton) && pressed)
|
||||
{
|
||||
toggle[uButton] = (!lastPressed[uButton]) ? TRUE : toggle[uButton] = !toggle[uButton];
|
||||
toggle[uButton] = (!lastPressed[uButton]) ? TRUE : !toggle[uButton];
|
||||
pressed = pressed && toggle[uButton];
|
||||
}
|
||||
lastPressed[uButton] = nowPressed;
|
||||
|
|
|
@ -34,7 +34,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "Pravets.h"
|
||||
#include "Tape.h"
|
||||
#include "YamlHelper.h"
|
||||
#include "Video.h" // Needed by TK3000 //e, to refresh the frame at each |Mode| change
|
||||
#include "Windows/WinVideo.h" // Needed by TK3000 //e, to refresh the frame at each |Mode| change
|
||||
#include "Log.h"
|
||||
|
||||
static BYTE asciicode[2][10] = {
|
||||
|
|
|
@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "Log.h"
|
||||
#include "Memory.h"
|
||||
#include "SoundCore.h"
|
||||
#include "Video.h" // VideoRedrawScreen()
|
||||
#include "Windows/WinVideo.h" // VideoRedrawScreen()
|
||||
#include "YamlHelper.h"
|
||||
#include "Riff.h"
|
||||
|
||||
|
|
611
source/Video.cpp
611
source/Video.cpp
|
@ -31,17 +31,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include "Video.h"
|
||||
#include "AppleWin.h"
|
||||
#include "CPU.h"
|
||||
#include "Disk.h" // DiskUpdateDriveState()
|
||||
#include "Frame.h"
|
||||
#include "Keyboard.h"
|
||||
#include "Log.h"
|
||||
#include "Memory.h"
|
||||
#include "Registry.h"
|
||||
#include "NTSC.h"
|
||||
#include "RGBMonitor.h"
|
||||
|
||||
#include "../resource/resource.h"
|
||||
#include "Configuration/PropertySheet.h"
|
||||
#include "YamlHelper.h"
|
||||
|
||||
#define SW_80COL (g_uVideoMode & VF_80COL)
|
||||
|
@ -54,7 +50,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
// Globals (Public)
|
||||
|
||||
uint8_t *g_pFramebufferbits = NULL; // last drawn frame
|
||||
uint8_t *g_pFramebufferbits = NULL; // last drawn frame (initialized in WinVideoInitialize)
|
||||
int g_nAltCharSetOffset = 0; // alternate character set
|
||||
|
||||
// Globals (Private)
|
||||
|
@ -77,14 +73,6 @@ int const kVPresetLine = 256; // line when V state presets
|
|||
int const kVSyncLines = 4; // lines per VSync duration
|
||||
int const kVDisplayableScanLines = 192; // max displayable scanlines
|
||||
|
||||
static COLORREF customcolors[256]; // MONOCHROME is last custom color
|
||||
|
||||
static HBITMAP g_hDeviceBitmap;
|
||||
static HDC g_hDeviceDC;
|
||||
static LPBITMAPINFO g_pFramebufferinfo = NULL;
|
||||
|
||||
HBITMAP g_hLogoBitmap;
|
||||
|
||||
COLORREF g_nMonochromeRGB = RGB(0xC0,0xC0,0xC0);
|
||||
|
||||
uint32_t g_uVideoMode = VF_TEXT; // Current Video Mode (this is the last set one as it may change mid-scan line!)
|
||||
|
@ -94,8 +82,6 @@ static VideoStyle_e g_eVideoStyle = VS_HALF_SCANLINES;
|
|||
|
||||
static bool g_bVideoScannerNTSC = true; // NTSC video scanning (or PAL)
|
||||
|
||||
static LPDIRECTDRAW g_lpDD = NULL;
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
// NOTE: KEEP IN SYNC: VideoType_e g_aVideoChoices g_apVideoModeDesc
|
||||
|
@ -130,39 +116,10 @@ static LPDIRECTDRAW g_lpDD = NULL;
|
|||
|
||||
bool g_bDisplayPrintScreenFileName = false;
|
||||
bool g_bShowPrintScreenWarningDialog = true;
|
||||
void Util_MakeScreenShotFileName( TCHAR *pFinalFileName_, DWORD chars );
|
||||
bool Util_TestScreenShotFileName( const TCHAR *pFileName );
|
||||
void Video_SaveScreenShot( const VideoScreenShot_e ScreenShotType, const TCHAR *pScreenShotFileName );
|
||||
void Video_MakeScreenShot( FILE *pFile, const VideoScreenShot_e ScreenShotType );
|
||||
void videoCreateDIBSection();
|
||||
|
||||
//===========================================================================
|
||||
void VideoInitialize ()
|
||||
{
|
||||
// RESET THE VIDEO MODE SWITCHES AND THE CHARACTER SET OFFSET
|
||||
VideoResetState();
|
||||
|
||||
// LOAD THE LOGO
|
||||
g_hLogoBitmap = LoadBitmap( g_hInstance, MAKEINTRESOURCE(IDB_APPLEWIN) );
|
||||
|
||||
// CREATE A BITMAPINFO STRUCTURE FOR THE FRAME BUFFER
|
||||
g_pFramebufferinfo = (LPBITMAPINFO)VirtualAlloc(
|
||||
NULL,
|
||||
sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD),
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
|
||||
ZeroMemory(g_pFramebufferinfo,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();
|
||||
}
|
||||
static void Util_MakeScreenShotFileName( TCHAR *pFinalFileName_, DWORD chars );
|
||||
static bool Util_TestScreenShotFileName( const TCHAR *pFileName );
|
||||
static void Video_MakeScreenShot( FILE *pFile, const VideoScreenShot_e ScreenShotType );
|
||||
static void videoCreateDIBSection();
|
||||
|
||||
//===========================================================================
|
||||
|
||||
|
@ -170,448 +127,6 @@ void VideoInitialize ()
|
|||
// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
|
||||
//
|
||||
|
||||
//===========================================================================
|
||||
void VideoBenchmark () {
|
||||
_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;
|
||||
|
||||
g_uVideoMode = VF_TEXT;
|
||||
FillMemory(mem+0x400,0x400,0x14);
|
||||
VideoRedrawScreen();
|
||||
DWORD milliseconds = GetTickCount();
|
||||
while (GetTickCount() == milliseconds) ;
|
||||
milliseconds = GetTickCount();
|
||||
DWORD cycle = 0;
|
||||
do {
|
||||
if (cycle & 1)
|
||||
FillMemory(mem+0x400,0x400,0x14);
|
||||
else
|
||||
CopyMemory(mem+0x400,mem+((cycle & 2) ? 0x4000 : 0x6000),0x400);
|
||||
VideoRefreshScreen();
|
||||
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;
|
||||
g_uVideoMode = VF_HIRES;
|
||||
FillMemory(mem+0x2000,0x2000,0x14);
|
||||
VideoRedrawScreen();
|
||||
milliseconds = GetTickCount();
|
||||
while (GetTickCount() == milliseconds) ;
|
||||
milliseconds = GetTickCount();
|
||||
cycle = 0;
|
||||
do {
|
||||
if (cycle & 1)
|
||||
FillMemory(mem+0x2000,0x2000,0x14);
|
||||
else
|
||||
CopyMemory(mem+0x2000,mem+((cycle & 2) ? 0x4000 : 0x6000),0x2000);
|
||||
VideoRefreshScreen();
|
||||
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;
|
||||
FillMemory(mem+0x2000,0x2000,0xAA);
|
||||
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)
|
||||
FillMemory(mem+0x2000,0x2000,0xAA);
|
||||
else
|
||||
CopyMemory(mem+0x2000,mem+((cycle & 2) ? 0x4000 : 0x6000),0x2000);
|
||||
VideoRedrawScreen();
|
||||
if (cycle++ >= 3)
|
||||
cycle = 0;
|
||||
realisticfps++;
|
||||
} while (GetTickCount() - milliseconds < 1000);
|
||||
|
||||
// DISPLAY THE RESULTS
|
||||
VideoDisplayLogo();
|
||||
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 VideoChooseMonochromeColor ()
|
||||
{
|
||||
CHOOSECOLOR cc;
|
||||
ZeroMemory(&cc,sizeof(CHOOSECOLOR));
|
||||
cc.lStructSize = sizeof(CHOOSECOLOR);
|
||||
cc.hwndOwner = g_hFrameWindow;
|
||||
cc.rgbResult = g_nMonochromeRGB;
|
||||
cc.lpCustColors = customcolors + 1;
|
||||
cc.Flags = CC_RGBINIT | CC_SOLIDCOLOR;
|
||||
if (ChooseColor(&cc))
|
||||
{
|
||||
g_nMonochromeRGB = cc.rgbResult;
|
||||
VideoReinitialize();
|
||||
if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG))
|
||||
{
|
||||
VideoRedrawScreen();
|
||||
}
|
||||
Config_Save_Video();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void VideoDestroy () {
|
||||
|
||||
// DESTROY BUFFERS
|
||||
VirtualFree(g_pFramebufferinfo,0,MEM_RELEASE);
|
||||
g_pFramebufferinfo = NULL;
|
||||
|
||||
// DESTROY FRAME BUFFER
|
||||
DeleteDC(g_hDeviceDC);
|
||||
DeleteObject(g_hDeviceBitmap);
|
||||
g_hDeviceDC = (HDC)0;
|
||||
g_hDeviceBitmap = (HBITMAP)0;
|
||||
|
||||
// DESTROY LOGO
|
||||
if (g_hLogoBitmap) {
|
||||
DeleteObject(g_hLogoBitmap);
|
||||
g_hLogoBitmap = (HBITMAP)0;
|
||||
}
|
||||
|
||||
NTSC_Destroy();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static void 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 VideoDisplayLogo ()
|
||||
{
|
||||
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 VideoRedrawScreenDuringFullSpeed(DWORD dwCyclesThisFrame, bool bInit /*=false*/)
|
||||
{
|
||||
static DWORD dwFullSpeedStartTime = 0;
|
||||
// static bool bValid = false;
|
||||
|
||||
if (bInit)
|
||||
{
|
||||
// Just entered full-speed mode
|
||||
// bValid = false;
|
||||
dwFullSpeedStartTime = GetTickCount();
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD dwFullSpeedDuration = GetTickCount() - dwFullSpeedStartTime;
|
||||
if (dwFullSpeedDuration <= 16) // Only update after every realtime ~17ms of *continuous* full-speed
|
||||
return;
|
||||
|
||||
dwFullSpeedStartTime += dwFullSpeedDuration;
|
||||
|
||||
//
|
||||
|
||||
#if 0
|
||||
static BYTE text_main[1024*2] = {0}; // page1 & 2
|
||||
static BYTE text_aux[1024*2] = {0}; // page1 & 2
|
||||
static BYTE hgr_main[8192*2] = {0}; // page1 & 2
|
||||
static BYTE hgr_aux[8192*2] = {0}; // page1 & 2
|
||||
|
||||
bool bRedraw = true; // Always redraw for bValid==false (ie. just entered full-speed mode)
|
||||
|
||||
if (bValid)
|
||||
{
|
||||
if ((g_uVideoMode&(VF_DHIRES|VF_HIRES|VF_TEXT|VF_MIXED)) == VF_HIRES)
|
||||
{
|
||||
// HIRES (not MIXED) - eg. AZTEC.DSK
|
||||
if ((g_uVideoMode&VF_PAGE2) == 0)
|
||||
bRedraw = memcmp(&hgr_main[0x0000], MemGetMainPtr(0x2000), 8192) != 0;
|
||||
else
|
||||
bRedraw = memcmp(&hgr_main[0x2000], MemGetMainPtr(0x4000), 8192) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bRedraw =
|
||||
(memcmp(text_main, MemGetMainPtr(0x400), sizeof(text_main)) != 0) ||
|
||||
(memcmp(text_aux, MemGetAuxPtr(0x400), sizeof(text_aux)) != 0) ||
|
||||
(memcmp(hgr_main, MemGetMainPtr(0x2000), sizeof(hgr_main)) != 0) ||
|
||||
(memcmp(hgr_aux, MemGetAuxPtr(0x2000), sizeof(hgr_aux)) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (bRedraw)
|
||||
VideoRedrawScreenAfterFullSpeed(dwCyclesThisFrame);
|
||||
|
||||
// Copy all video memory (+ screen holes)
|
||||
memcpy(text_main, MemGetMainPtr(0x400), sizeof(text_main));
|
||||
memcpy(text_aux, MemGetAuxPtr(0x400), sizeof(text_aux));
|
||||
memcpy(hgr_main, MemGetMainPtr(0x2000), sizeof(hgr_main));
|
||||
memcpy(hgr_aux, MemGetAuxPtr(0x2000), sizeof(hgr_aux));
|
||||
|
||||
bValid = true;
|
||||
#else
|
||||
VideoRedrawScreenAfterFullSpeed(dwCyclesThisFrame);
|
||||
#endif
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame)
|
||||
{
|
||||
NTSC_VideoClockResync(dwCyclesThisFrame);
|
||||
VideoRedrawScreen(); // Better (no flicker) than using: NTSC_VideoReinitialize() or VideoReinitialize()
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void 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( g_uVideoMode, true );
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void VideoRefreshScreen ( uint32_t uRedrawWholeScreenVideoMode /* =0*/, bool bRedrawWholeScreen /* =false*/ )
|
||||
{
|
||||
if (bRedrawWholeScreen || g_nAppMode == MODE_PAUSED)
|
||||
{
|
||||
// uVideoModeForWholeScreen set if:
|
||||
// . MODE_DEBUG : always
|
||||
// . MODE_RUNNING : called from VideoRedrawScreen(), eg. during full-speed
|
||||
if (bRedrawWholeScreen)
|
||||
NTSC_SetVideoMode( uRedrawWholeScreenVideoMode );
|
||||
NTSC_VideoRedrawWholeScreen();
|
||||
|
||||
// MODE_DEBUG|PAUSED: Need to refresh a 2nd time if changing video-type, otherwise could have residue from prev image!
|
||||
// . eg. Amber -> B&W TV
|
||||
if (g_nAppMode == MODE_DEBUG || g_nAppMode == MODE_PAUSED)
|
||||
NTSC_VideoRedrawWholeScreen();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void VideoReinitialize (bool bInitVideoScannerAddress /*= true*/)
|
||||
{
|
||||
|
@ -903,80 +418,6 @@ bool VideoGetVblBar(const DWORD uExecutedCycles)
|
|||
|
||||
return g_nVideoClockVert < kVDisplayableScanLines;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define MAX_DRAW_DEVICES 10
|
||||
|
||||
static char *draw_devices[MAX_DRAW_DEVICES];
|
||||
static GUID draw_device_guid[MAX_DRAW_DEVICES];
|
||||
static int num_draw_devices = 0;
|
||||
|
||||
static BOOL CALLBACK DDEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext)
|
||||
{
|
||||
int i = num_draw_devices;
|
||||
if (i == MAX_DRAW_DEVICES)
|
||||
return TRUE;
|
||||
if (lpGUID != NULL)
|
||||
memcpy(&draw_device_guid[i], lpGUID, sizeof (GUID));
|
||||
draw_devices[i] = _strdup(lpszDesc);
|
||||
|
||||
if (g_fh) fprintf(g_fh, "%d: %s - %s\n",i,lpszDesc,lpszDrvName);
|
||||
|
||||
num_draw_devices++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool DDInit(void)
|
||||
{
|
||||
#ifdef NO_DIRECT_X
|
||||
|
||||
return false;
|
||||
|
||||
#else
|
||||
HRESULT hr = DirectDrawEnumerate((LPDDENUMCALLBACK)DDEnumProc, NULL);
|
||||
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 DDUninit(void)
|
||||
{
|
||||
SAFE_RELEASE(g_lpDD);
|
||||
}
|
||||
|
||||
#undef SAFE_RELEASE
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define SCREENSHOT_BMP 1
|
||||
|
@ -1052,16 +493,6 @@ void Video_TakeScreenShot( const VideoScreenShot_e ScreenShotType )
|
|||
g_nLastScreenShot++;
|
||||
}
|
||||
|
||||
void Video_RedrawAndTakeScreenShot( const TCHAR* pScreenshotFilename )
|
||||
{
|
||||
_ASSERT(pScreenshotFilename);
|
||||
if (!pScreenshotFilename)
|
||||
return;
|
||||
|
||||
VideoRedrawScreen();
|
||||
Video_SaveScreenShot( SCREENSHOT_560x384, pScreenshotFilename );
|
||||
}
|
||||
|
||||
WinBmpHeader_t g_tBmpHeader;
|
||||
|
||||
#if SCREENSHOT_TGA
|
||||
|
@ -1218,7 +649,7 @@ static void Video_MakeScreenShot(FILE *pFile, const VideoScreenShot_e ScreenShot
|
|||
}
|
||||
|
||||
//===========================================================================
|
||||
static void Video_SaveScreenShot( const VideoScreenShot_e ScreenShotType, const TCHAR *pScreenShotFileName )
|
||||
void Video_SaveScreenShot( const VideoScreenShot_e ScreenShotType, const TCHAR *pScreenShotFileName )
|
||||
{
|
||||
FILE *pFile = fopen( pScreenShotFileName, "wb" );
|
||||
if( pFile )
|
||||
|
@ -1413,36 +844,6 @@ void SetVideoRefreshRate(VideoRefreshRate_e rate)
|
|||
NTSC_SetRefreshRate(rate);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
static void videoCreateDIBSection()
|
||||
{
|
||||
// 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
|
||||
ZeroMemory( g_pFramebufferbits, GetFrameBufferWidth()*GetFrameBufferHeight()*sizeof(bgra_t) );
|
||||
|
||||
// CREATE THE OFFSET TABLE FOR EACH SCAN LINE IN THE FRAME BUFFER
|
||||
NTSC_VideoInit( g_pFramebufferbits );
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
const char* VideoGetAppWindowTitle(void)
|
||||
|
|
|
@ -168,7 +168,6 @@ struct WinBmpHeader4_t
|
|||
#endif
|
||||
|
||||
// Globals __________________________________________________________
|
||||
|
||||
extern COLORREF g_nMonochromeRGB; // saved to Registry
|
||||
extern uint32_t g_uVideoMode;
|
||||
extern DWORD g_eVideoType; // saved to Registry
|
||||
|
@ -176,15 +175,6 @@ extern uint8_t *g_pFramebufferbits;
|
|||
|
||||
// Prototypes _______________________________________________________
|
||||
|
||||
void VideoBenchmark ();
|
||||
void VideoChooseMonochromeColor (); // FIXME: Should be moved to PageConfig and call VideoSetMonochromeColor()
|
||||
void VideoDestroy ();
|
||||
void VideoDisplayLogo ();
|
||||
void VideoInitialize ();
|
||||
void VideoRedrawScreenDuringFullSpeed(DWORD dwCyclesThisFrame, bool bInit = false);
|
||||
void VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame);
|
||||
void VideoRedrawScreen (void);
|
||||
void VideoRefreshScreen (uint32_t uRedrawWholeScreenVideoMode = 0, bool bRedrawWholeScreen = false);
|
||||
void VideoReinitialize (bool bInitVideoScannerAddress = true);
|
||||
void VideoResetState ();
|
||||
enum VideoScanner_e {VS_FullAddr, VS_PartialAddrV, VS_PartialAddrH};
|
||||
|
@ -214,8 +204,8 @@ enum VideoScreenShot_e
|
|||
SCREENSHOT_280x192
|
||||
};
|
||||
void Video_TakeScreenShot( VideoScreenShot_e ScreenShotType );
|
||||
void Video_RedrawAndTakeScreenShot( const char* pScreenshotFilename );
|
||||
void Video_SetBitmapHeader( WinBmpHeader_t *pBmp, int nWidth, int nHeight, int nBitsPerPixel );
|
||||
void Video_SaveScreenShot(const VideoScreenShot_e ScreenShotType, const TCHAR* pScreenShotFileName);
|
||||
|
||||
BYTE VideoSetMode(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
|
||||
|
||||
|
@ -239,7 +229,4 @@ bool IsVideoStyle(VideoStyle_e mask);
|
|||
VideoRefreshRate_e GetVideoRefreshRate(void);
|
||||
void SetVideoRefreshRate(VideoRefreshRate_e rate);
|
||||
|
||||
bool DDInit(void);
|
||||
void DDUninit(void);
|
||||
|
||||
const char* VideoGetAppWindowTitle(void);
|
||||
|
|
|
@ -34,7 +34,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
//#define STRICT
|
||||
|
||||
#include "DirectInput.h"
|
||||
#include "Windows/DirectInput.h"
|
||||
#include "SoundCore.h" // SAFE_RELEASE()
|
||||
#include "Log.h"
|
||||
#include "Common.h"
|
638
source/Windows/WinVideo.cpp
Normal file
638
source/Windows/WinVideo.cpp
Normal file
|
@ -0,0 +1,638 @@
|
|||
/*
|
||||
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 "AppleWin.h"
|
||||
#include "Video.h"
|
||||
#include "CPU.h"
|
||||
#include "Joystick.h"
|
||||
#include "Frame.h"
|
||||
#include "Log.h"
|
||||
#include "Memory.h"
|
||||
#include "CardManager.h"
|
||||
#include "NTSC.h"
|
||||
|
||||
#include "../resource/resource.h"
|
||||
|
||||
static COLORREF customcolors[256]; // MONOCHROME is last custom color
|
||||
static HBITMAP g_hLogoBitmap;
|
||||
static HBITMAP g_hDeviceBitmap;
|
||||
static HDC g_hDeviceDC;
|
||||
static LPBITMAPINFO g_pFramebufferinfo = NULL;
|
||||
|
||||
static void videoCreateDIBSection()
|
||||
{
|
||||
// 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
|
||||
ZeroMemory(g_pFramebufferbits, GetFrameBufferWidth() * GetFrameBufferHeight() * sizeof(bgra_t));
|
||||
|
||||
// CREATE THE OFFSET TABLE FOR EACH SCAN LINE IN THE FRAME BUFFER
|
||||
NTSC_VideoInit(g_pFramebufferbits);
|
||||
}
|
||||
|
||||
//
|
||||
// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
|
||||
//
|
||||
|
||||
void WinVideoInitialize()
|
||||
{
|
||||
// RESET THE VIDEO MODE SWITCHES AND THE CHARACTER SET OFFSET
|
||||
VideoResetState();
|
||||
|
||||
// LOAD THE LOGO
|
||||
g_hLogoBitmap = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_APPLEWIN));
|
||||
|
||||
// CREATE A BITMAPINFO STRUCTURE FOR THE FRAME BUFFER
|
||||
g_pFramebufferinfo = (LPBITMAPINFO)VirtualAlloc(
|
||||
NULL,
|
||||
sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD),
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
|
||||
ZeroMemory(g_pFramebufferinfo, 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();
|
||||
}
|
||||
|
||||
void WinVideoDestroy()
|
||||
{
|
||||
|
||||
// DESTROY BUFFERS
|
||||
VirtualFree(g_pFramebufferinfo, 0, MEM_RELEASE);
|
||||
g_pFramebufferinfo = NULL;
|
||||
|
||||
// DESTROY FRAME BUFFER
|
||||
DeleteDC(g_hDeviceDC);
|
||||
DeleteObject(g_hDeviceBitmap);
|
||||
g_hDeviceDC = (HDC)0;
|
||||
g_hDeviceBitmap = (HBITMAP)0;
|
||||
g_pFramebufferbits = NULL;
|
||||
|
||||
// DESTROY LOGO
|
||||
if (g_hLogoBitmap) {
|
||||
DeleteObject(g_hLogoBitmap);
|
||||
g_hLogoBitmap = (HBITMAP)0;
|
||||
}
|
||||
|
||||
NTSC_Destroy();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void VideoBenchmark () {
|
||||
_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;
|
||||
|
||||
g_uVideoMode = VF_TEXT;
|
||||
FillMemory(mem+0x400,0x400,0x14);
|
||||
VideoRedrawScreen();
|
||||
DWORD milliseconds = GetTickCount();
|
||||
while (GetTickCount() == milliseconds) ;
|
||||
milliseconds = GetTickCount();
|
||||
DWORD cycle = 0;
|
||||
do {
|
||||
if (cycle & 1)
|
||||
FillMemory(mem+0x400,0x400,0x14);
|
||||
else
|
||||
CopyMemory(mem+0x400,mem+((cycle & 2) ? 0x4000 : 0x6000),0x400);
|
||||
VideoRefreshScreen();
|
||||
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;
|
||||
g_uVideoMode = VF_HIRES;
|
||||
FillMemory(mem+0x2000,0x2000,0x14);
|
||||
VideoRedrawScreen();
|
||||
milliseconds = GetTickCount();
|
||||
while (GetTickCount() == milliseconds) ;
|
||||
milliseconds = GetTickCount();
|
||||
cycle = 0;
|
||||
do {
|
||||
if (cycle & 1)
|
||||
FillMemory(mem+0x2000,0x2000,0x14);
|
||||
else
|
||||
CopyMemory(mem+0x2000,mem+((cycle & 2) ? 0x4000 : 0x6000),0x2000);
|
||||
VideoRefreshScreen();
|
||||
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;
|
||||
FillMemory(mem+0x2000,0x2000,0xAA);
|
||||
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)
|
||||
FillMemory(mem+0x2000,0x2000,0xAA);
|
||||
else
|
||||
CopyMemory(mem+0x2000,mem+((cycle & 2) ? 0x4000 : 0x6000),0x2000);
|
||||
VideoRedrawScreen();
|
||||
if (cycle++ >= 3)
|
||||
cycle = 0;
|
||||
realisticfps++;
|
||||
} while (GetTickCount() - milliseconds < 1000);
|
||||
|
||||
// DISPLAY THE RESULTS
|
||||
VideoDisplayLogo();
|
||||
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 VideoChooseMonochromeColor ()
|
||||
{
|
||||
CHOOSECOLOR cc;
|
||||
ZeroMemory(&cc,sizeof(CHOOSECOLOR));
|
||||
cc.lStructSize = sizeof(CHOOSECOLOR);
|
||||
cc.hwndOwner = g_hFrameWindow;
|
||||
cc.rgbResult = g_nMonochromeRGB;
|
||||
cc.lpCustColors = customcolors + 1;
|
||||
cc.Flags = CC_RGBINIT | CC_SOLIDCOLOR;
|
||||
if (ChooseColor(&cc))
|
||||
{
|
||||
g_nMonochromeRGB = cc.rgbResult;
|
||||
VideoReinitialize();
|
||||
if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG))
|
||||
{
|
||||
VideoRedrawScreen();
|
||||
}
|
||||
Config_Save_Video();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static void 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 VideoDisplayLogo ()
|
||||
{
|
||||
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 VideoRedrawScreenDuringFullSpeed(DWORD dwCyclesThisFrame, bool bInit /*=false*/)
|
||||
{
|
||||
static DWORD dwFullSpeedStartTime = 0;
|
||||
// static bool bValid = false;
|
||||
|
||||
if (bInit)
|
||||
{
|
||||
// Just entered full-speed mode
|
||||
// bValid = false;
|
||||
dwFullSpeedStartTime = GetTickCount();
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD dwFullSpeedDuration = GetTickCount() - dwFullSpeedStartTime;
|
||||
if (dwFullSpeedDuration <= 16) // Only update after every realtime ~17ms of *continuous* full-speed
|
||||
return;
|
||||
|
||||
dwFullSpeedStartTime += dwFullSpeedDuration;
|
||||
|
||||
//
|
||||
|
||||
#if 0
|
||||
static BYTE text_main[1024*2] = {0}; // page1 & 2
|
||||
static BYTE text_aux[1024*2] = {0}; // page1 & 2
|
||||
static BYTE hgr_main[8192*2] = {0}; // page1 & 2
|
||||
static BYTE hgr_aux[8192*2] = {0}; // page1 & 2
|
||||
|
||||
bool bRedraw = true; // Always redraw for bValid==false (ie. just entered full-speed mode)
|
||||
|
||||
if (bValid)
|
||||
{
|
||||
if ((g_uVideoMode&(VF_DHIRES|VF_HIRES|VF_TEXT|VF_MIXED)) == VF_HIRES)
|
||||
{
|
||||
// HIRES (not MIXED) - eg. AZTEC.DSK
|
||||
if ((g_uVideoMode&VF_PAGE2) == 0)
|
||||
bRedraw = memcmp(&hgr_main[0x0000], MemGetMainPtr(0x2000), 8192) != 0;
|
||||
else
|
||||
bRedraw = memcmp(&hgr_main[0x2000], MemGetMainPtr(0x4000), 8192) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bRedraw =
|
||||
(memcmp(text_main, MemGetMainPtr(0x400), sizeof(text_main)) != 0) ||
|
||||
(memcmp(text_aux, MemGetAuxPtr(0x400), sizeof(text_aux)) != 0) ||
|
||||
(memcmp(hgr_main, MemGetMainPtr(0x2000), sizeof(hgr_main)) != 0) ||
|
||||
(memcmp(hgr_aux, MemGetAuxPtr(0x2000), sizeof(hgr_aux)) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (bRedraw)
|
||||
VideoRedrawScreenAfterFullSpeed(dwCyclesThisFrame);
|
||||
|
||||
// Copy all video memory (+ screen holes)
|
||||
memcpy(text_main, MemGetMainPtr(0x400), sizeof(text_main));
|
||||
memcpy(text_aux, MemGetAuxPtr(0x400), sizeof(text_aux));
|
||||
memcpy(hgr_main, MemGetMainPtr(0x2000), sizeof(hgr_main));
|
||||
memcpy(hgr_aux, MemGetAuxPtr(0x2000), sizeof(hgr_aux));
|
||||
|
||||
bValid = true;
|
||||
#else
|
||||
VideoRedrawScreenAfterFullSpeed(dwCyclesThisFrame);
|
||||
#endif
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame)
|
||||
{
|
||||
NTSC_VideoClockResync(dwCyclesThisFrame);
|
||||
VideoRedrawScreen(); // Better (no flicker) than using: NTSC_VideoReinitialize() or VideoReinitialize()
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void 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( g_uVideoMode, true );
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void VideoRefreshScreen ( uint32_t uRedrawWholeScreenVideoMode /* =0*/, bool bRedrawWholeScreen /* =false*/ )
|
||||
{
|
||||
if (bRedrawWholeScreen || g_nAppMode == MODE_PAUSED)
|
||||
{
|
||||
// uVideoModeForWholeScreen set if:
|
||||
// . MODE_DEBUG : always
|
||||
// . MODE_RUNNING : called from VideoRedrawScreen(), eg. during full-speed
|
||||
if (bRedrawWholeScreen)
|
||||
NTSC_SetVideoMode( uRedrawWholeScreenVideoMode );
|
||||
NTSC_VideoRedrawWholeScreen();
|
||||
|
||||
// MODE_DEBUG|PAUSED: Need to refresh a 2nd time if changing video-type, otherwise could have residue from prev image!
|
||||
// . eg. Amber -> B&W TV
|
||||
if (g_nAppMode == MODE_DEBUG || g_nAppMode == MODE_PAUSED)
|
||||
NTSC_VideoRedrawWholeScreen();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define MAX_DRAW_DEVICES 10
|
||||
|
||||
static char *draw_devices[MAX_DRAW_DEVICES];
|
||||
static GUID draw_device_guid[MAX_DRAW_DEVICES];
|
||||
static int num_draw_devices = 0;
|
||||
static LPDIRECTDRAW g_lpDD = NULL;
|
||||
|
||||
static BOOL CALLBACK DDEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext)
|
||||
{
|
||||
int i = num_draw_devices;
|
||||
if (i == MAX_DRAW_DEVICES)
|
||||
return TRUE;
|
||||
if (lpGUID != NULL)
|
||||
memcpy(&draw_device_guid[i], lpGUID, sizeof (GUID));
|
||||
draw_devices[i] = _strdup(lpszDesc);
|
||||
|
||||
if (g_fh) fprintf(g_fh, "%d: %s - %s\n",i,lpszDesc,lpszDrvName);
|
||||
|
||||
num_draw_devices++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool DDInit(void)
|
||||
{
|
||||
#ifdef NO_DIRECT_X
|
||||
|
||||
return false;
|
||||
|
||||
#else
|
||||
HRESULT hr = DirectDrawEnumerate((LPDDENUMCALLBACK)DDEnumProc, NULL);
|
||||
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 DDUninit(void)
|
||||
{
|
||||
SAFE_RELEASE(g_lpDD);
|
||||
}
|
||||
|
||||
#undef SAFE_RELEASE
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void Video_RedrawAndTakeScreenShot(const char* pScreenshotFilename)
|
||||
{
|
||||
_ASSERT(pScreenshotFilename);
|
||||
if (!pScreenshotFilename)
|
||||
return;
|
||||
|
||||
VideoRedrawScreen();
|
||||
Video_SaveScreenShot(SCREENSHOT_560x384, pScreenshotFilename);
|
||||
}
|
19
source/Windows/WinVideo.h
Normal file
19
source/Windows/WinVideo.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
// Prototypes _______________________________________________________
|
||||
|
||||
void WinVideoInitialize();
|
||||
void WinVideoDestroy();
|
||||
|
||||
void VideoBenchmark ();
|
||||
void VideoChooseMonochromeColor (); // FIXME: Should be moved to PageConfig and call VideoSetMonochromeColor()
|
||||
void VideoDisplayLogo ();
|
||||
void VideoRedrawScreenDuringFullSpeed(DWORD dwCyclesThisFrame, bool bInit = false);
|
||||
void VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame);
|
||||
void VideoRedrawScreen (void);
|
||||
void VideoRefreshScreen (uint32_t uRedrawWholeScreenVideoMode = 0, bool bRedrawWholeScreen = false);
|
||||
|
||||
void Video_RedrawAndTakeScreenShot(const char* pScreenshotFilename);
|
||||
|
||||
bool DDInit(void);
|
||||
void DDUninit(void);
|
Loading…
Add table
Reference in a new issue