mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-12-23 00:30:17 +00:00
- Added Configuration GUI to include checkbox for "50Hz" - Implicitly use PAL or NTSC base 6502 clocks depending on video refresh rate - Added new -50hz and -60hz command line switches - Updated save-state for video refresh rate 1.28.8.0: Updated version & history.txt
This commit is contained in:
parent
dbcb789442
commit
bd86088c59
@ -369,6 +369,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -8,10 +8,17 @@ https://github.com/AppleWin/AppleWin/issues/new
|
||||
|
||||
Tom Charlesworth
|
||||
|
||||
1.28.8.0 - 28 Jun 2019
|
||||
----------------------
|
||||
. [Change #648] Support 50Hz(PAL) video refresh rate and implicitly PAL 1.018MHz.
|
||||
- NB. TV video modes still use NTSC rendering.
|
||||
. [Bug #656] Fix for PAGE1/2 ($C054/55) not having a 1 cycle delay.
|
||||
|
||||
|
||||
1.28.7.0 - 15 Jun 2019
|
||||
----------------------
|
||||
. [Bug #654] Fix for Sather's "Little Text Window" not rendering correctly.
|
||||
. [Bug #654] Fix for 6522 TIMER1's period to be N+2 cycles.
|
||||
. [Bug #652] Fix for 6522 TIMER1's period to be N+2 cycles.
|
||||
|
||||
|
||||
1.28.6.0 - 2 Jun 2019
|
||||
|
@ -111,6 +111,7 @@ BEGIN
|
||||
CTEXT "2.0",IDC_2_0_MHz,96,180,20,10
|
||||
RTEXT "Fastest",IDC_MAX_MHz,150,180,29,10
|
||||
PUSHBUTTON "&Benchmark Emulator",IDC_BENCHMARK,15,194,85,15
|
||||
CONTROL "50Hz video",IDC_CHECK_50HZ_VIDEO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,142,141,51,10
|
||||
END
|
||||
|
||||
IDD_PROPPAGE_INPUT DIALOGEX 0, 0, 210, 215
|
||||
|
@ -116,6 +116,7 @@
|
||||
#define IDC_COMBO_DISK2 1081
|
||||
#define IDC_CHECK_FS_SHOW_SUBUNIT_STATUS 1082
|
||||
#define IDC_CHECK_VERTICAL_BLEND 1083
|
||||
#define IDC_CHECK_50HZ_VIDEO 1084
|
||||
#define IDM_EXIT 40001
|
||||
#define IDM_HELP 40002
|
||||
#define IDM_ABOUT 40003
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define APPLEWIN_VERSION 1,28,7,0
|
||||
#define APPLEWIN_VERSION 1,28,8,0
|
||||
|
||||
#define xstr(a) str(a)
|
||||
#define str(a) #a
|
||||
|
@ -91,7 +91,7 @@ bool g_bRestart = false;
|
||||
bool g_bRestartFullScreen = false;
|
||||
|
||||
DWORD g_dwSpeed = SPEED_NORMAL; // Affected by Config dialog's speed slider bar
|
||||
double g_fCurrentCLK6502 = CLK_6502; // Affected by Config dialog's speed slider bar
|
||||
double g_fCurrentCLK6502 = CLK_6502_NTSC; // Affected by Config dialog's speed slider bar
|
||||
static double g_fMHz = 1.0; // Affected by Config dialog's speed slider bar
|
||||
|
||||
int g_nCpuCyclesFeedback = 0;
|
||||
@ -345,6 +345,7 @@ static void ContinueExecution(void)
|
||||
|
||||
//
|
||||
|
||||
const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame();
|
||||
if (g_dwCyclesThisFrame >= dwClksPerFrame)
|
||||
{
|
||||
g_dwCyclesThisFrame -= dwClksPerFrame;
|
||||
@ -376,14 +377,21 @@ void SingleStep(bool bReinit)
|
||||
|
||||
//===========================================================================
|
||||
|
||||
double Get6502BaseClock(void)
|
||||
{
|
||||
return (GetVideoRefreshRate() == VR_50HZ) ? CLK_6502_PAL : CLK_6502_NTSC;
|
||||
}
|
||||
|
||||
void SetCurrentCLK6502(void)
|
||||
{
|
||||
static DWORD dwPrevSpeed = (DWORD) -1;
|
||||
static VideoRefreshRate_e prevVideoRefreshRate = VR_NONE;
|
||||
|
||||
if(dwPrevSpeed == g_dwSpeed)
|
||||
if (dwPrevSpeed == g_dwSpeed && GetVideoRefreshRate() == prevVideoRefreshRate)
|
||||
return;
|
||||
|
||||
dwPrevSpeed = g_dwSpeed;
|
||||
prevVideoRefreshRate = GetVideoRefreshRate();
|
||||
|
||||
// SPEED_MIN = 0 = 0.50 MHz
|
||||
// SPEED_NORMAL = 10 = 1.00 MHz
|
||||
@ -396,7 +404,7 @@ void SetCurrentCLK6502(void)
|
||||
else
|
||||
g_fMHz = (double)g_dwSpeed / 10.0;
|
||||
|
||||
g_fCurrentCLK6502 = CLK_6502 * g_fMHz;
|
||||
g_fCurrentCLK6502 = Get6502BaseClock() * g_fMHz;
|
||||
|
||||
//
|
||||
// Now re-init modules that are dependent on /g_fCurrentCLK6502/
|
||||
@ -622,17 +630,15 @@ void LoadConfiguration(void)
|
||||
}
|
||||
|
||||
REGLOAD(TEXT(REGVALUE_EMULATION_SPEED) ,&g_dwSpeed);
|
||||
Config_Load_Video();
|
||||
SetCurrentCLK6502(); // Pre: g_dwSpeed && Config_Load_Video()->SetVideoRefreshRate()
|
||||
|
||||
DWORD dwEnhanceDisk;
|
||||
REGLOAD(TEXT(REGVALUE_ENHANCE_DISK_SPEED), &dwEnhanceDisk);
|
||||
sg_Disk2Card.SetEnhanceDisk(dwEnhanceDisk ? true : false);
|
||||
|
||||
Config_Load_Video();
|
||||
|
||||
REGLOAD(TEXT("Uthernet Active") ,(DWORD *)&tfe_enabled);
|
||||
|
||||
SetCurrentCLK6502();
|
||||
|
||||
//
|
||||
|
||||
DWORD dwTmp;
|
||||
@ -1181,6 +1187,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||
int newVideoType = -1;
|
||||
int newVideoStyleEnableMask = 0;
|
||||
int newVideoStyleDisableMask = 0;
|
||||
VideoRefreshRate_e newVideoRefreshRate = VR_NONE;
|
||||
LPSTR szScreenshotFilename = NULL;
|
||||
|
||||
while (*lpCmdLine)
|
||||
@ -1427,6 +1434,14 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||
szScreenshotFilename = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
}
|
||||
else if (_stricmp(lpCmdLine, "-50hz") == 0) // (case-insensitive)
|
||||
{
|
||||
newVideoRefreshRate = VR_50HZ;
|
||||
}
|
||||
else if (_stricmp(lpCmdLine, "-60hz") == 0) // (case-insensitive)
|
||||
{
|
||||
newVideoRefreshRate = VR_60HZ;
|
||||
}
|
||||
else // unsupported
|
||||
{
|
||||
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
|
||||
@ -1537,9 +1552,19 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||
LogFileOutput("Main: LoadConfiguration()\n");
|
||||
|
||||
if (newVideoType >= 0)
|
||||
{
|
||||
SetVideoType( (VideoType_e)newVideoType );
|
||||
newVideoType = -1; // Don't reapply after a restart
|
||||
}
|
||||
SetVideoStyle( (VideoStyle_e) ((GetVideoStyle() | newVideoStyleEnableMask) & ~newVideoStyleDisableMask) );
|
||||
|
||||
if (newVideoRefreshRate != VR_NONE)
|
||||
{
|
||||
SetVideoRefreshRate(newVideoRefreshRate);
|
||||
newVideoRefreshRate = VR_NONE; // Don't reapply after a restart
|
||||
SetCurrentCLK6502();
|
||||
}
|
||||
|
||||
// Apply the memory expansion switches after loading the Apple II machine type
|
||||
#ifdef RAMWORKS
|
||||
if (uRamWorksExPages)
|
||||
|
@ -6,7 +6,6 @@
|
||||
void LogFileTimeUntilFirstKeyReadReset(void);
|
||||
void LogFileTimeUntilFirstKeyRead(void);
|
||||
|
||||
void SetCurrentCLK6502();
|
||||
bool SetCurrentImageDir(const char* pszImageDir);
|
||||
|
||||
extern const UINT16* GetOldAppleWinVersion(void);
|
||||
@ -18,6 +17,9 @@ extern eApple2Type g_Apple2Type;
|
||||
eApple2Type GetApple2Type(void);
|
||||
void SetApple2Type(eApple2Type type);
|
||||
|
||||
double Get6502BaseClock(void);
|
||||
void SetCurrentCLK6502(void);
|
||||
|
||||
void SingleStep(bool bReinit);
|
||||
|
||||
extern bool g_bFullSpeed;
|
||||
|
@ -1,19 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
const double _M14 = (157500000.0 / 11.0); // 14.3181818... * 10^6
|
||||
const double CLK_6502 = ((_M14 * 65.0) / 912.0); // 65 cycles per 912 14M clocks
|
||||
const double _14M_NTSC = (157500000.0 / 11.0); // 14.3181818... * 10^6
|
||||
const double _14M_PAL = 14.25045e6; // UTAIIe:3-17
|
||||
const double CLK_6502_NTSC = ((_14M_NTSC * 65.0) / 912.0); // 65 cycles per 912 14M clocks
|
||||
const double CLK_6502_PAL = _14M_PAL / 14.0;
|
||||
//const double CLK_6502 = 23 * 44100; // 1014300
|
||||
|
||||
// The effective Z-80 clock rate is 2.041MHz
|
||||
// See: http://www.apple2info.net/hardware/softcard/SC-SWHW_a2in.pdf
|
||||
const double CLK_Z80 = (CLK_6502 * 2);
|
||||
|
||||
// TODO: Clean up from Common.h, Video.cpp, and NTSC.h !!!
|
||||
const UINT uCyclesPerLine = 65; // 25 cycles of HBL & 40 cycles of HBL'
|
||||
const UINT uVisibleLinesPerFrame = 64*3; // 192
|
||||
const UINT uLinesPerFrame = 262; // 64 in each third of the screen & 70 in VBL
|
||||
const DWORD dwClksPerFrame = uCyclesPerLine * uLinesPerFrame; // 17030
|
||||
|
||||
#define NUM_SLOTS 8
|
||||
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
@ -107,6 +99,7 @@ enum AppMode_e
|
||||
#define REGVALUE_VIDEO_STYLE "Video Style" // GH#616: Added at 1.28.2
|
||||
#define REGVALUE_VIDEO_HALF_SCAN_LINES "Half Scan Lines" // GH#616: Deprecated from 1.28.2
|
||||
#define REGVALUE_VIDEO_MONO_COLOR "Monochrome Color"
|
||||
#define REGVALUE_VIDEO_REFRESH_RATE "Video Refresh Rate"
|
||||
#define REGVALUE_SERIAL_PORT_NAME "Serial Port Name"
|
||||
#define REGVALUE_ENHANCE_DISK_SPEED "Enhance Disk Speed"
|
||||
#define REGVALUE_CUSTOM_SPEED "Custom Speed"
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "../CPU.h"
|
||||
#include "../DiskImage.h" // Disk_Status_e
|
||||
#include "../Harddisk.h" // HD_CardIsEnabled()
|
||||
#include "../Video.h" // VideoRefreshRate_e, GetVideoRefreshRate()
|
||||
|
||||
class CConfigNeedingRestart
|
||||
{
|
||||
@ -11,7 +12,8 @@ public:
|
||||
CConfigNeedingRestart(UINT bEnableTheFreezesF8Rom = false) :
|
||||
m_Apple2Type( GetApple2Type() ),
|
||||
m_CpuType( GetMainCpu() ),
|
||||
m_uSaveLoadStateMsg(0)
|
||||
m_uSaveLoadStateMsg(0),
|
||||
m_videoRefreshRate( GetVideoRefreshRate() )
|
||||
{
|
||||
m_bEnableHDD = HD_CardIsEnabled();
|
||||
m_bEnableTheFreezesF8Rom = bEnableTheFreezesF8Rom;
|
||||
@ -29,17 +31,19 @@ public:
|
||||
m_bEnableHDD = other.m_bEnableHDD;
|
||||
m_bEnableTheFreezesF8Rom = other.m_bEnableTheFreezesF8Rom;
|
||||
m_uSaveLoadStateMsg = other.m_uSaveLoadStateMsg;
|
||||
m_videoRefreshRate = other.m_videoRefreshRate;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator== (const CConfigNeedingRestart& other) const
|
||||
{
|
||||
return m_Apple2Type == other.m_Apple2Type &&
|
||||
m_CpuType == other.m_CpuType &&
|
||||
memcmp(m_Slot, other.m_Slot, sizeof(m_Slot)) == 0 &&
|
||||
m_bEnableHDD == other.m_bEnableHDD &&
|
||||
m_bEnableTheFreezesF8Rom == other.m_bEnableTheFreezesF8Rom &&
|
||||
m_uSaveLoadStateMsg == other.m_uSaveLoadStateMsg;
|
||||
m_CpuType == other.m_CpuType &&
|
||||
memcmp(m_Slot, other.m_Slot, sizeof(m_Slot)) == 0 &&
|
||||
m_bEnableHDD == other.m_bEnableHDD &&
|
||||
m_bEnableTheFreezesF8Rom == other.m_bEnableTheFreezesF8Rom &&
|
||||
m_uSaveLoadStateMsg == other.m_uSaveLoadStateMsg &&
|
||||
m_videoRefreshRate == other.m_videoRefreshRate;
|
||||
}
|
||||
|
||||
bool operator!= (const CConfigNeedingRestart& other) const
|
||||
@ -54,4 +58,5 @@ public:
|
||||
bool m_bEnableHDD;
|
||||
UINT m_bEnableTheFreezesF8Rom;
|
||||
UINT m_uSaveLoadStateMsg;
|
||||
VideoRefreshRate_e m_videoRefreshRate;
|
||||
};
|
||||
|
@ -121,6 +121,7 @@ BOOL CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM
|
||||
case IDC_CHECK_HALF_SCAN_LINES:
|
||||
case IDC_CHECK_VERTICAL_BLEND:
|
||||
case IDC_CHECK_FS_SHOW_SUBUNIT_STATUS:
|
||||
case IDC_CHECK_50HZ_VIDEO:
|
||||
// Checked in DlgOK()
|
||||
break;
|
||||
|
||||
@ -205,6 +206,8 @@ BOOL CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM
|
||||
m_PropertySheetHelper.FillComboBox(hWnd,IDC_SERIALPORT, sg_SSC.GetSerialPortChoices(), sg_SSC.GetSerialPort());
|
||||
EnableWindow(GetDlgItem(hWnd, IDC_SERIALPORT), !sg_SSC.IsActive() ? TRUE : FALSE);
|
||||
|
||||
CheckDlgButton(hWnd, IDC_CHECK_50HZ_VIDEO, (GetVideoRefreshRate() == VR_50HZ) ? BST_CHECKED : BST_UNCHECKED);
|
||||
|
||||
SendDlgItemMessage(hWnd,IDC_SLIDER_CPU_SPEED,TBM_SETRANGE,1,MAKELONG(0,40));
|
||||
SendDlgItemMessage(hWnd,IDC_SLIDER_CPU_SPEED,TBM_SETPAGESIZE,0,5);
|
||||
SendDlgItemMessage(hWnd,IDC_SLIDER_CPU_SPEED,TBM_SETTICFREQ,10,0);
|
||||
@ -286,6 +289,13 @@ void CPageConfig::DlgOK(HWND hWnd)
|
||||
bVideoReinit = true;
|
||||
}
|
||||
|
||||
const bool isNewVideoRate50Hz = IsDlgButtonChecked(hWnd, IDC_CHECK_50HZ_VIDEO) != 0;
|
||||
const bool isCurrentVideoRate50Hz = GetVideoRefreshRate() == VR_50HZ;
|
||||
if (isCurrentVideoRate50Hz != isNewVideoRate50Hz)
|
||||
{
|
||||
m_PropertySheetHelper.GetConfigNew().m_videoRefreshRate = isNewVideoRate50Hz ? VR_50HZ : VR_60HZ;
|
||||
}
|
||||
|
||||
if (bVideoReinit)
|
||||
{
|
||||
Config_Save_Video();
|
||||
|
@ -407,6 +407,11 @@ void CPropertySheetHelper::ApplyNewConfig(const CConfigNeedingRestart& ConfigNew
|
||||
{
|
||||
REGSAVE(TEXT(REGVALUE_THE_FREEZES_F8_ROM), ConfigNew.m_bEnableTheFreezesF8Rom);
|
||||
}
|
||||
|
||||
if (CONFIG_CHANGED_LOCAL(m_videoRefreshRate))
|
||||
{
|
||||
REGSAVE(TEXT(REGVALUE_VIDEO_REFRESH_RATE), ConfigNew.m_videoRefreshRate);
|
||||
}
|
||||
}
|
||||
|
||||
void CPropertySheetHelper::ApplyNewConfig(void)
|
||||
@ -423,6 +428,7 @@ void CPropertySheetHelper::SaveCurrentConfig(void)
|
||||
m_ConfigOld.m_Slot[5] = g_Slot5;
|
||||
m_ConfigOld.m_bEnableHDD = HD_CardIsEnabled();
|
||||
m_ConfigOld.m_bEnableTheFreezesF8Rom = sg_PropertySheet.GetTheFreezesF8Rom();
|
||||
m_ConfigOld.m_videoRefreshRate = GetVideoRefreshRate();
|
||||
|
||||
// Reset flags each time:
|
||||
m_ConfigOld.m_uSaveLoadStateMsg = 0;
|
||||
@ -441,6 +447,7 @@ void CPropertySheetHelper::RestoreCurrentConfig(void)
|
||||
g_Slot5 = m_ConfigOld.m_Slot[5];
|
||||
HD_SetEnabled(m_ConfigOld.m_bEnableHDD);
|
||||
sg_PropertySheet.SetTheFreezesF8Rom(m_ConfigOld.m_bEnableTheFreezesF8Rom);
|
||||
SetVideoRefreshRate(m_ConfigOld.m_videoRefreshRate);
|
||||
}
|
||||
|
||||
bool CPropertySheetHelper::IsOkToSaveLoadState(HWND hWnd, const bool bConfigChanged)
|
||||
@ -491,6 +498,9 @@ bool CPropertySheetHelper::HardwareConfigChanged(HWND hWnd)
|
||||
if (CONFIG_CHANGED(m_CpuType))
|
||||
strMsgMain += ". Emulated main CPU has changed\n";
|
||||
|
||||
if (CONFIG_CHANGED(m_videoRefreshRate))
|
||||
strMsgMain += ". Video refresh rate has changed\n";
|
||||
|
||||
if (CONFIG_CHANGED(m_Slot[4]))
|
||||
strMsgMain += GetSlot(4);
|
||||
|
||||
|
@ -2202,7 +2202,7 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT unitVersion)
|
||||
SetLastRamWrite( yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTRAMWRITE) ? TRUE : FALSE ); // NB. This is set later for II,II+ by slot-0 LC or Saturn
|
||||
}
|
||||
|
||||
if (unitVersion == 3)
|
||||
if (unitVersion >= 3)
|
||||
{
|
||||
for (UINT i=0; i<kNumAnnunciators; i++)
|
||||
{
|
||||
|
@ -205,7 +205,8 @@ static HANDLE g_hSSI263Event[g_nNumEvents] = {NULL}; // 1: Phoneme finished play
|
||||
static DWORD g_dwMaxPhonemeLen = 0;
|
||||
|
||||
// When 6522 IRQ is *not* active use 60Hz update freq for MB voices
|
||||
static const double g_f6522TimerPeriod_NoIRQ = CLK_6502 / 60.0; // Constant whatever the CLK is set to
|
||||
// NB. Not important if NTSC or PAL - just need to pick a sensible period
|
||||
static const double g_f6522TimerPeriod_NoIRQ = CLK_6502_NTSC / 60.0; // Constant whatever the CLK is set to
|
||||
|
||||
static bool g_bCritSectionValid = false; // Deleting CritialSection when not valid causes crash on Win98
|
||||
static CRITICAL_SECTION g_CriticalSection; // To guard 6522's IFR
|
||||
@ -1627,7 +1628,7 @@ static BYTE __stdcall PhasorIO(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, UL
|
||||
|
||||
g_PhasorClockScaleFactor = (nAddr & 4) ? 2 : 1;
|
||||
|
||||
AY8910_InitClock((int)(CLK_6502 * g_PhasorClockScaleFactor));
|
||||
AY8910_InitClock((int)(Get6502BaseClock() * g_PhasorClockScaleFactor));
|
||||
|
||||
return MemReadFloatingBus(nExecutedCycles);
|
||||
}
|
||||
@ -2189,7 +2190,7 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
|
||||
pMB++;
|
||||
}
|
||||
|
||||
AY8910_InitClock((int)CLK_6502);
|
||||
AY8910_InitClock((int)Get6502BaseClock());
|
||||
|
||||
// NB. g_SoundcardType & g_bPhasorEnable setup in MB_InitializeIO() -> MB_SetSoundcardType()
|
||||
|
||||
@ -2312,7 +2313,7 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version
|
||||
pMB++;
|
||||
}
|
||||
|
||||
AY8910_InitClock((int)(CLK_6502 * g_PhasorClockScaleFactor));
|
||||
AY8910_InitClock((int)(Get6502BaseClock() * g_PhasorClockScaleFactor));
|
||||
|
||||
// NB. g_SoundcardType & g_bPhasorEnable setup in MB_InitializeIO() -> MB_SetSoundcardType()
|
||||
|
||||
|
119
source/NTSC.cpp
119
source/NTSC.cpp
@ -134,7 +134,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// "There are exactly 17030 (65 x 262) 6502 cycles in every television scan of an American Apple."
|
||||
#define VIDEO_SCANNER_MAX_HORZ 65 // TODO: use Video.cpp: kHClocks
|
||||
#define VIDEO_SCANNER_MAX_VERT 262 // TODO: use Video.cpp: kNTSCScanLines
|
||||
static const int VIDEO_SCANNER_6502_CYCLES = VIDEO_SCANNER_MAX_HORZ * VIDEO_SCANNER_MAX_VERT;
|
||||
static const UINT VIDEO_SCANNER_6502_CYCLES = VIDEO_SCANNER_MAX_HORZ * VIDEO_SCANNER_MAX_VERT;
|
||||
|
||||
#define VIDEO_SCANNER_MAX_VERT_PAL 312
|
||||
static const UINT VIDEO_SCANNER_6502_CYCLES_PAL = VIDEO_SCANNER_MAX_HORZ * VIDEO_SCANNER_MAX_VERT_PAL;
|
||||
|
||||
static UINT g_videoScannerMaxVert = VIDEO_SCANNER_MAX_VERT; // default to NTSC
|
||||
static UINT g_videoScanner6502Cycles = VIDEO_SCANNER_6502_CYCLES; // default to NTSC
|
||||
|
||||
#define VIDEO_SCANNER_HORZ_COLORBURST_BEG 12
|
||||
#define VIDEO_SCANNER_HORZ_COLORBURST_END 16
|
||||
@ -212,9 +218,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
// Tables
|
||||
// Video scanner tables are now runtime-generated using UTAIIe logic
|
||||
static unsigned short g_aClockVertOffsetsHGR[VIDEO_SCANNER_MAX_VERT];
|
||||
static unsigned short g_aClockVertOffsetsTXT[33];
|
||||
static unsigned short APPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
|
||||
static unsigned short g_aClockVertOffsetsHGR[VIDEO_SCANNER_MAX_VERT_PAL];
|
||||
static unsigned short g_aClockVertOffsetsTXT[VIDEO_SCANNER_MAX_VERT_PAL/8];
|
||||
static unsigned short APPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ]; // 5 = CEILING(312/64) = CEILING(262/64)
|
||||
static unsigned short APPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
|
||||
|
||||
#ifdef _DEBUG
|
||||
@ -243,7 +249,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
0x0B80,0x0F80,0x1380,0x1780,0x1B80,0x1F80
|
||||
};
|
||||
|
||||
static unsigned short g_kClockVertOffsetsTXT[33] =
|
||||
static unsigned short g_kClockVertOffsetsTXT[33] = // 33 = CEILING(262/8)
|
||||
{
|
||||
0x0000,0x0080,0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,
|
||||
0x0000,0x0080,0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,
|
||||
@ -768,7 +774,7 @@ inline void updateVideoScannerHorzEOLSimple()
|
||||
{
|
||||
g_nVideoClockHorz = 0;
|
||||
|
||||
if (++g_nVideoClockVert == VIDEO_SCANNER_MAX_VERT)
|
||||
if (++g_nVideoClockVert == g_videoScannerMaxVert)
|
||||
{
|
||||
g_nVideoClockVert = 0;
|
||||
|
||||
@ -807,7 +813,7 @@ inline void updateVideoScannerHorzEOL()
|
||||
|
||||
g_nVideoClockHorz = 0;
|
||||
|
||||
if (++g_nVideoClockVert == VIDEO_SCANNER_MAX_VERT)
|
||||
if (++g_nVideoClockVert == g_videoScannerMaxVert)
|
||||
{
|
||||
g_nVideoClockVert = 0;
|
||||
|
||||
@ -851,7 +857,7 @@ inline void updateVideoScannerHorzEOL_14M()
|
||||
|
||||
g_nVideoClockHorz = 0;
|
||||
|
||||
if (++g_nVideoClockVert == VIDEO_SCANNER_MAX_VERT)
|
||||
if (++g_nVideoClockVert == g_videoScannerMaxVert)
|
||||
{
|
||||
g_nVideoClockVert = 0;
|
||||
|
||||
@ -897,7 +903,7 @@ inline void updateVideoScannerHorzEOL()
|
||||
|
||||
g_nVideoClockHorz = 0;
|
||||
|
||||
if (++g_nVideoClockVert == VIDEO_SCANNER_MAX_VERT)
|
||||
if (++g_nVideoClockVert == g_videoScannerMaxVert)
|
||||
{
|
||||
g_nVideoClockVert = 0;
|
||||
|
||||
@ -1838,8 +1844,8 @@ uint32_t*NTSC_VideoGetChromaTable( bool bHueTypeMonochrome, bool bMonitorTypeCol
|
||||
//===========================================================================
|
||||
void NTSC_VideoClockResync(const DWORD dwCyclesThisFrame)
|
||||
{
|
||||
g_nVideoClockVert = (uint16_t) (dwCyclesThisFrame / VIDEO_SCANNER_MAX_HORZ) % VIDEO_SCANNER_MAX_VERT;
|
||||
g_nVideoClockHorz = (uint16_t) (dwCyclesThisFrame % VIDEO_SCANNER_MAX_HORZ);
|
||||
g_nVideoClockVert = (uint16_t)(dwCyclesThisFrame / VIDEO_SCANNER_MAX_HORZ) % g_videoScannerMaxVert;
|
||||
g_nVideoClockHorz = (uint16_t)(dwCyclesThisFrame % VIDEO_SCANNER_MAX_HORZ);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@ -1861,7 +1867,7 @@ uint16_t NTSC_VideoGetScannerAddress ( const ULONG uExecutedCycles )
|
||||
g_nVideoClockHorz += VIDEO_SCANNER_MAX_HORZ;
|
||||
g_nVideoClockVert -= 1;
|
||||
if ((SHORT)g_nVideoClockVert < 0)
|
||||
g_nVideoClockVert = VIDEO_SCANNER_MAX_VERT-1;
|
||||
g_nVideoClockVert = g_videoScannerMaxVert-1;
|
||||
}
|
||||
|
||||
uint16_t addr;
|
||||
@ -2154,8 +2160,8 @@ void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit
|
||||
//===========================================================================
|
||||
void NTSC_VideoReinitialize( DWORD cyclesThisFrame, bool bInitVideoScannerAddress )
|
||||
{
|
||||
_ASSERT(cyclesThisFrame < VIDEO_SCANNER_6502_CYCLES);
|
||||
if (cyclesThisFrame >= VIDEO_SCANNER_6502_CYCLES) cyclesThisFrame = 0; // error
|
||||
_ASSERT(cyclesThisFrame < g_videoScanner6502Cycles);
|
||||
if (cyclesThisFrame >= g_videoScanner6502Cycles) cyclesThisFrame = 0; // error
|
||||
g_nVideoClockVert = (uint16_t) (cyclesThisFrame / VIDEO_SCANNER_MAX_HORZ);
|
||||
g_nVideoClockHorz = cyclesThisFrame % VIDEO_SCANNER_MAX_HORZ;
|
||||
|
||||
@ -2193,7 +2199,7 @@ void NTSC_VideoInitChroma()
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// Pre: cyclesLeftToUpdate = [0...VIDEO_SCANNER_6502_CYCLES]
|
||||
// Pre: cyclesLeftToUpdate = [0...g_videoScanner6502Cycles]
|
||||
// . 2-14: After one emulated 6502/65C02 opcode (optionally with IRQ)
|
||||
// . ~1000: After 1ms of Z80 emulation
|
||||
// . 17030: From NTSC_VideoRedrawWholeScreen()
|
||||
@ -2208,7 +2214,7 @@ static void VideoUpdateCycles( int cyclesLeftToUpdate )
|
||||
g_pFuncUpdateGraphicsScreen(cycles); // lines [currV...159]
|
||||
cyclesLeftToUpdate -= cycles;
|
||||
|
||||
const int cyclesFromLine160ToLine261 = VIDEO_SCANNER_6502_CYCLES - (VIDEO_SCANNER_MAX_HORZ * VIDEO_SCANNER_Y_MIXED);
|
||||
const int cyclesFromLine160ToLine261 = g_videoScanner6502Cycles - (VIDEO_SCANNER_MAX_HORZ * VIDEO_SCANNER_Y_MIXED);
|
||||
cycles = cyclesLeftToUpdate < cyclesFromLine160ToLine261 ? cyclesLeftToUpdate : cyclesFromLine160ToLine261;
|
||||
g_pFuncUpdateGraphicsScreen(cycles); // lines [160..191..261]
|
||||
cyclesLeftToUpdate -= cycles;
|
||||
@ -2217,7 +2223,7 @@ static void VideoUpdateCycles( int cyclesLeftToUpdate )
|
||||
}
|
||||
else
|
||||
{
|
||||
const int cyclesToLine262 = VIDEO_SCANNER_MAX_HORZ * (VIDEO_SCANNER_MAX_VERT - g_nVideoClockVert - 1) + cyclesToEndOfLine;
|
||||
const int cyclesToLine262 = VIDEO_SCANNER_MAX_HORZ * (g_videoScannerMaxVert - g_nVideoClockVert - 1) + cyclesToEndOfLine;
|
||||
int cycles = cyclesLeftToUpdate < cyclesToLine262 ? cyclesLeftToUpdate : cyclesToLine262;
|
||||
g_pFuncUpdateGraphicsScreen(cycles); // lines [currV...261]
|
||||
cyclesLeftToUpdate -= cycles;
|
||||
@ -2235,9 +2241,9 @@ static void VideoUpdateCycles( int cyclesLeftToUpdate )
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void NTSC_VideoUpdateCycles( long cycles6502 )
|
||||
void NTSC_VideoUpdateCycles( UINT cycles6502 )
|
||||
{
|
||||
_ASSERT(cycles6502 && cycles6502 < VIDEO_SCANNER_6502_CYCLES); // Use NTSC_VideoRedrawWholeScreen() instead
|
||||
_ASSERT(cycles6502 && cycles6502 < g_videoScanner6502Cycles); // Use NTSC_VideoRedrawWholeScreen() instead
|
||||
|
||||
if (g_bDelayVideoMode)
|
||||
{
|
||||
@ -2269,7 +2275,7 @@ void NTSC_VideoRedrawWholeScreen( void )
|
||||
g_nVideoClockHorz = 0;
|
||||
updateVideoScannerAddress();
|
||||
|
||||
VideoUpdateCycles(VIDEO_SCANNER_6502_CYCLES);
|
||||
VideoUpdateCycles(g_videoScanner6502Cycles);
|
||||
|
||||
VideoUpdateCycles(horz); // Finally update to get to correct H-pos
|
||||
|
||||
@ -2324,19 +2330,37 @@ static void CheckVideoTables( void )
|
||||
CheckVideoTables2(A2TYPE_APPLE2E, VF_TEXT);
|
||||
}
|
||||
|
||||
static bool IsNTSC(void)
|
||||
{
|
||||
return g_videoScannerMaxVert == VIDEO_SCANNER_MAX_VERT;
|
||||
}
|
||||
|
||||
static void GenerateVideoTables( void )
|
||||
{
|
||||
eApple2Type currentApple2Type = GetApple2Type();
|
||||
uint32_t currentVideoMode = g_uVideoMode;
|
||||
int currentHiresPage = g_nHiresPage;
|
||||
int currentTextPage = g_nTextPage;
|
||||
|
||||
g_nHiresPage = g_nTextPage = 1;
|
||||
|
||||
//
|
||||
// g_aClockVertOffsetsHGR[]
|
||||
//
|
||||
|
||||
g_uVideoMode = VF_HIRES;
|
||||
for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i<VIDEO_SCANNER_MAX_VERT; i++, cycle+=VIDEO_SCANNER_MAX_HORZ)
|
||||
{
|
||||
g_aClockVertOffsetsHGR[i] = VideoGetScannerAddress(cycle, VS_PartialAddrV);
|
||||
_ASSERT(g_aClockVertOffsetsHGR[i] == g_kClockVertOffsetsHGR[i]);
|
||||
UINT i = 0, cycle = VIDEO_SCANNER_HORZ_START;
|
||||
for (; i < VIDEO_SCANNER_MAX_VERT; i++, cycle += VIDEO_SCANNER_MAX_HORZ)
|
||||
{
|
||||
g_aClockVertOffsetsHGR[i] = VideoGetScannerAddress(cycle, VS_PartialAddrV);
|
||||
if (IsNTSC()) _ASSERT(g_aClockVertOffsetsHGR[i] == g_kClockVertOffsetsHGR[i]);
|
||||
}
|
||||
if (!IsNTSC())
|
||||
{
|
||||
for (; i < VIDEO_SCANNER_MAX_VERT_PAL; i++, cycle += VIDEO_SCANNER_MAX_HORZ)
|
||||
g_aClockVertOffsetsHGR[i] = VideoGetScannerAddress(cycle, VS_PartialAddrV);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -2344,10 +2368,18 @@ static void GenerateVideoTables( void )
|
||||
//
|
||||
|
||||
g_uVideoMode = VF_TEXT;
|
||||
for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i<(256+8)/8; i++, cycle+=VIDEO_SCANNER_MAX_HORZ*8)
|
||||
{
|
||||
g_aClockVertOffsetsTXT[i] = VideoGetScannerAddress(cycle, VS_PartialAddrV);
|
||||
_ASSERT(g_aClockVertOffsetsTXT[i] == g_kClockVertOffsetsTXT[i]);
|
||||
UINT i = 0, cycle = VIDEO_SCANNER_HORZ_START;
|
||||
for (; i < (256 + 8) / 8; i++, cycle += VIDEO_SCANNER_MAX_HORZ * 8)
|
||||
{
|
||||
g_aClockVertOffsetsTXT[i] = VideoGetScannerAddress(cycle, VS_PartialAddrV);
|
||||
if (IsNTSC()) _ASSERT(g_aClockVertOffsetsTXT[i] == g_kClockVertOffsetsTXT[i]);
|
||||
}
|
||||
if (!IsNTSC())
|
||||
{
|
||||
for (; i < VIDEO_SCANNER_MAX_VERT_PAL / 8; i++, cycle += VIDEO_SCANNER_MAX_HORZ * 8)
|
||||
g_aClockVertOffsetsTXT[i] = VideoGetScannerAddress(cycle, VS_PartialAddrV);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -2361,7 +2393,7 @@ static void GenerateVideoTables( void )
|
||||
for (UINT i=0, cycle=j*64*VIDEO_SCANNER_MAX_HORZ; i<VIDEO_SCANNER_MAX_HORZ; i++, cycle++)
|
||||
{
|
||||
APPLE_IIP_HORZ_CLOCK_OFFSET[j][i] = VideoGetScannerAddress(cycle, VS_PartialAddrH);
|
||||
_ASSERT(APPLE_IIP_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIP_HORZ_CLOCK_OFFSET[j][i]);
|
||||
if (IsNTSC()) _ASSERT(APPLE_IIP_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIP_HORZ_CLOCK_OFFSET[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2376,7 +2408,7 @@ static void GenerateVideoTables( void )
|
||||
for (UINT i=0, cycle=j*64*VIDEO_SCANNER_MAX_HORZ; i<VIDEO_SCANNER_MAX_HORZ; i++, cycle++)
|
||||
{
|
||||
APPLE_IIE_HORZ_CLOCK_OFFSET[j][i] = VideoGetScannerAddress(cycle, VS_PartialAddrH);
|
||||
_ASSERT(APPLE_IIE_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIE_HORZ_CLOCK_OFFSET[j][i]);
|
||||
if (IsNTSC()) _ASSERT(APPLE_IIE_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIE_HORZ_CLOCK_OFFSET[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2384,11 +2416,15 @@ static void GenerateVideoTables( void )
|
||||
|
||||
CheckVideoTables();
|
||||
|
||||
VideoResetState();
|
||||
// VideoResetState();
|
||||
|
||||
SetApple2Type(currentApple2Type);
|
||||
g_uVideoMode = currentVideoMode;
|
||||
g_nHiresPage = currentHiresPage;
|
||||
g_nTextPage = currentTextPage;
|
||||
}
|
||||
|
||||
void GenerateBaseColors(baseColors_t pBaseNtscColors)
|
||||
static void GenerateBaseColors(baseColors_t pBaseNtscColors)
|
||||
{
|
||||
for (UINT i=0; i<16; i++)
|
||||
{
|
||||
@ -2415,3 +2451,26 @@ void GenerateBaseColors(baseColors_t pBaseNtscColors)
|
||||
(*pBaseNtscColors)[i] = * (bgra_t*) &color;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void NTSC_SetRefreshRate(VideoRefreshRate_e rate)
|
||||
{
|
||||
if (rate == VR_50HZ)
|
||||
{
|
||||
g_videoScannerMaxVert = VIDEO_SCANNER_MAX_VERT_PAL;
|
||||
g_videoScanner6502Cycles = VIDEO_SCANNER_6502_CYCLES_PAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_videoScannerMaxVert = VIDEO_SCANNER_MAX_VERT;
|
||||
g_videoScanner6502Cycles = VIDEO_SCANNER_6502_CYCLES;
|
||||
}
|
||||
|
||||
GenerateVideoTables();
|
||||
}
|
||||
|
||||
UINT NTSC_GetCyclesPerFrame(void)
|
||||
{
|
||||
return g_videoScanner6502Cycles;
|
||||
}
|
||||
|
@ -14,6 +14,10 @@
|
||||
extern void NTSC_VideoReinitialize( DWORD cyclesThisFrame, bool bInitVideoScannerAddress );
|
||||
extern void NTSC_VideoInitAppleType();
|
||||
extern void NTSC_VideoInitChroma();
|
||||
extern void NTSC_VideoUpdateCycles( long cycles6502 );
|
||||
extern void NTSC_VideoUpdateCycles( UINT cycles6502 );
|
||||
extern void NTSC_VideoRedrawWholeScreen( void );
|
||||
extern UINT NTSC_GetFrameBufferBorderlessWidth( void );
|
||||
|
||||
enum VideoRefreshRate_e;
|
||||
void NTSC_SetRefreshRate(VideoRefreshRate_e rate);
|
||||
UINT NTSC_GetCyclesPerFrame(void);
|
||||
|
@ -67,7 +67,8 @@ static YamlHelper yamlHelper;
|
||||
// Unit version history:
|
||||
// v2: Extended: keyboard (added 'Key Waiting'), memory (LC mem type for II/II+, inverted MF_INTCXROM bit)
|
||||
// v3: Extended: memory (added 'AnnunciatorN')
|
||||
#define UNIT_APPLE2_VER 3
|
||||
// v4: Extended: video (added 'Video Refresh Rate')
|
||||
#define UNIT_APPLE2_VER 4
|
||||
|
||||
#define UNIT_SLOTS_VER 1
|
||||
|
||||
@ -219,7 +220,7 @@ static void ParseUnitApple2(YamlLoadHelper& yamlLoadHelper, UINT version)
|
||||
JoyLoadSnapshot(yamlLoadHelper);
|
||||
KeybLoadSnapshot(yamlLoadHelper, version);
|
||||
SpkrLoadSnapshot(yamlLoadHelper);
|
||||
VideoLoadSnapshot(yamlLoadHelper);
|
||||
VideoLoadSnapshot(yamlLoadHelper, version);
|
||||
MemLoadSnapshot(yamlLoadHelper, version);
|
||||
|
||||
// g_Apple2Type may've changed: so redraw frame (title, buttons, leds, etc)
|
||||
@ -395,6 +396,7 @@ static void Snapshot_LoadState_v2(void)
|
||||
HD_Reset();
|
||||
KeybReset();
|
||||
VideoResetState();
|
||||
SetVideoRefreshRate(VR_60HZ); // Default to 60Hz as older save-states won't contain refresh rate
|
||||
MB_InitializeForLoadingSnapshot(); // GH#609
|
||||
sg_SSC.CommReset();
|
||||
#ifdef USE_SPEECH_API
|
||||
@ -420,7 +422,7 @@ static void Snapshot_LoadState_v2(void)
|
||||
// . A change in h/w via loading a save-state avoids this VM restart
|
||||
// The latter is the desired approach (as the former needs a "power-on" / F2 to start things again)
|
||||
|
||||
sg_PropertySheet.ApplyNewConfig(m_ConfigNew, ConfigOld);
|
||||
sg_PropertySheet.ApplyNewConfig(m_ConfigNew, ConfigOld); // Mainly just saves (some) new state to Registry
|
||||
|
||||
MemInitializeROM();
|
||||
MemInitializeCustomF8ROM();
|
||||
|
@ -91,7 +91,7 @@ uint32_t g_uVideoMode = VF_TEXT; // Current Video Mode (this is the last se
|
||||
DWORD g_eVideoType = VT_DEFAULT;
|
||||
static VideoStyle_e g_eVideoStyle = VS_HALF_SCANLINES;
|
||||
|
||||
static const bool g_bVideoScannerNTSC = true; // NTSC video scanning (or PAL)
|
||||
static bool g_bVideoScannerNTSC = true; // NTSC video scanning (or PAL)
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
@ -542,6 +542,9 @@ void VideoRedrawScreenDuringFullSpeed(DWORD dwCyclesThisFrame, bool bInit /*=fal
|
||||
|
||||
void VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame)
|
||||
{
|
||||
#if 1
|
||||
NTSC_VideoClockResync(dwCyclesThisFrame);
|
||||
#else
|
||||
if (g_bVideoScannerNTSC)
|
||||
{
|
||||
NTSC_VideoClockResync(dwCyclesThisFrame);
|
||||
@ -552,6 +555,7 @@ void VideoRedrawScreenAfterFullSpeed(DWORD dwCyclesThisFrame)
|
||||
g_nVideoClockVert = (uint16_t) (dwCyclesThisFrame / kHClocks) % kPALScanLines;
|
||||
g_nVideoClockHorz = (uint16_t) (dwCyclesThisFrame % kHClocks);
|
||||
}
|
||||
#endif
|
||||
|
||||
VideoRedrawScreen(); // Better (no flicker) than using: NTSC_VideoReinitialize() or VideoReinitialize()
|
||||
}
|
||||
@ -730,9 +734,10 @@ bool VideoGetSWAltCharSet(void)
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define SS_YAML_KEY_ALTCHARSET "Alt Char Set"
|
||||
#define SS_YAML_KEY_VIDEOMODE "Video Mode"
|
||||
#define SS_YAML_KEY_CYCLESTHISFRAME "Cycles This Frame"
|
||||
#define SS_YAML_KEY_ALT_CHARSET "Alt Char Set"
|
||||
#define SS_YAML_KEY_VIDEO_MODE "Video Mode"
|
||||
#define SS_YAML_KEY_CYCLES_THIS_FRAME "Cycles This Frame"
|
||||
#define SS_YAML_KEY_VIDEO_REFRESH_RATE "Video Refresh Rate"
|
||||
|
||||
static std::string VideoGetSnapshotStructName(void)
|
||||
{
|
||||
@ -743,19 +748,27 @@ static std::string VideoGetSnapshotStructName(void)
|
||||
void VideoSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
|
||||
{
|
||||
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", VideoGetSnapshotStructName().c_str());
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_ALTCHARSET, g_nAltCharSetOffset ? true : false);
|
||||
yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_VIDEOMODE, g_uVideoMode);
|
||||
yamlSaveHelper.SaveUint(SS_YAML_KEY_CYCLESTHISFRAME, g_dwCyclesThisFrame);
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_ALT_CHARSET, g_nAltCharSetOffset ? true : false);
|
||||
yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_VIDEO_MODE, g_uVideoMode);
|
||||
yamlSaveHelper.SaveUint(SS_YAML_KEY_CYCLES_THIS_FRAME, g_dwCyclesThisFrame);
|
||||
yamlSaveHelper.SaveUint(SS_YAML_KEY_VIDEO_REFRESH_RATE, (UINT)GetVideoRefreshRate());
|
||||
}
|
||||
|
||||
void VideoLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
|
||||
void VideoLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
|
||||
{
|
||||
if (!yamlLoadHelper.GetSubMap(VideoGetSnapshotStructName()))
|
||||
return;
|
||||
|
||||
g_nAltCharSetOffset = yamlLoadHelper.LoadBool(SS_YAML_KEY_ALTCHARSET) ? 256 : 0;
|
||||
g_uVideoMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_VIDEOMODE);
|
||||
g_dwCyclesThisFrame = yamlLoadHelper.LoadUint(SS_YAML_KEY_CYCLESTHISFRAME);
|
||||
if (version >= 4)
|
||||
{
|
||||
VideoRefreshRate_e rate = (VideoRefreshRate_e)yamlLoadHelper.LoadUint(SS_YAML_KEY_VIDEO_REFRESH_RATE);
|
||||
SetVideoRefreshRate(rate); // Trashes: g_dwCyclesThisFrame
|
||||
SetCurrentCLK6502();
|
||||
}
|
||||
|
||||
g_nAltCharSetOffset = yamlLoadHelper.LoadBool(SS_YAML_KEY_ALT_CHARSET) ? 256 : 0;
|
||||
g_uVideoMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_VIDEO_MODE);
|
||||
g_dwCyclesThisFrame = yamlLoadHelper.LoadUint(SS_YAML_KEY_CYCLES_THIS_FRAME);
|
||||
|
||||
yamlLoadHelper.PopMap();
|
||||
}
|
||||
@ -777,7 +790,7 @@ WORD VideoGetScannerAddress(DWORD nCycles, VideoScanner_e videoScannerAddr /*= V
|
||||
//
|
||||
const int kScanLines = g_bVideoScannerNTSC ? kNTSCScanLines : kPALScanLines;
|
||||
const int kScanCycles = kScanLines * kHClocks;
|
||||
_ASSERT(nCycles < kScanCycles);
|
||||
_ASSERT(nCycles < (UINT)kScanCycles);
|
||||
nCycles %= kScanCycles;
|
||||
|
||||
// calculate horizontal scanning state
|
||||
@ -795,7 +808,7 @@ WORD VideoGetScannerAddress(DWORD nCycles, VideoScanner_e videoScannerAddr /*= V
|
||||
int h_4 = (nHState >> 4) & 1;
|
||||
int h_5 = (nHState >> 5) & 1;
|
||||
|
||||
// calculate vertical scanning state
|
||||
// calculate vertical scanning state (UTAIIe:3-15,T3.2)
|
||||
//
|
||||
int nVLine = nCycles / kHClocks; // which vertical scanning line
|
||||
int nVState = kVLine0State + nVLine; // V state bits
|
||||
@ -868,7 +881,7 @@ WORD VideoGetScannerAddress(DWORD nCycles, VideoScanner_e videoScannerAddr /*= V
|
||||
nAddressP |= p2b << 11; // a11
|
||||
}
|
||||
|
||||
// VBL' = v_4' | v_3' = (v_4 & v_3)' (UTAIIe:5-10,#3)
|
||||
// VBL' = v_4' | v_3' = (v_4 & v_3)' (UTAIIe:5-10,#3), (UTAIIe:3-15,T3.2)
|
||||
|
||||
if (videoScannerAddr == VS_PartialAddrH)
|
||||
return nAddressH;
|
||||
@ -1231,6 +1244,10 @@ void Config_Load_Video()
|
||||
REGLOAD(TEXT(REGVALUE_VIDEO_STYLE) ,(DWORD*)&g_eVideoStyle);
|
||||
REGLOAD(TEXT(REGVALUE_VIDEO_MONO_COLOR),&g_nMonochromeRGB);
|
||||
|
||||
DWORD rate = VR_60HZ;
|
||||
REGLOAD(TEXT(REGVALUE_VIDEO_REFRESH_RATE), &rate);
|
||||
SetVideoRefreshRate((VideoRefreshRate_e)rate);
|
||||
|
||||
//
|
||||
|
||||
const UINT16* pOldVersion = GetOldAppleWinVersion();
|
||||
@ -1275,6 +1292,7 @@ void Config_Save_Video()
|
||||
REGSAVE(TEXT(REGVALUE_VIDEO_MODE) ,g_eVideoType);
|
||||
REGSAVE(TEXT(REGVALUE_VIDEO_STYLE) ,g_eVideoStyle);
|
||||
REGSAVE(TEXT(REGVALUE_VIDEO_MONO_COLOR),g_nMonochromeRGB);
|
||||
REGSAVE(TEXT(REGVALUE_VIDEO_REFRESH_RATE), GetVideoRefreshRate());
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@ -1305,6 +1323,22 @@ bool IsVideoStyle(VideoStyle_e mask)
|
||||
return (g_eVideoStyle & mask) != 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
VideoRefreshRate_e GetVideoRefreshRate(void)
|
||||
{
|
||||
return (g_bVideoScannerNTSC == false) ? VR_50HZ : VR_60HZ;
|
||||
}
|
||||
|
||||
void SetVideoRefreshRate(VideoRefreshRate_e rate)
|
||||
{
|
||||
if (rate != VR_50HZ)
|
||||
rate = VR_60HZ;
|
||||
|
||||
g_bVideoScannerNTSC = (rate == VR_60HZ);
|
||||
NTSC_SetRefreshRate(rate);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
static void videoCreateDIBSection()
|
||||
{
|
||||
|
@ -29,6 +29,13 @@
|
||||
// VS_TEXT_OPTIMIZED=4,
|
||||
};
|
||||
|
||||
enum VideoRefreshRate_e
|
||||
{
|
||||
VR_NONE,
|
||||
VR_50HZ,
|
||||
VR_60HZ
|
||||
};
|
||||
|
||||
enum VideoFlag_e
|
||||
{
|
||||
VF_80COL = 0x00000001,
|
||||
@ -193,7 +200,7 @@ bool VideoGetSWTEXT(void);
|
||||
bool VideoGetSWAltCharSet(void);
|
||||
|
||||
void VideoSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void VideoLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
|
||||
void VideoLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version);
|
||||
|
||||
extern bool g_bDisplayPrintScreenFileName;
|
||||
extern bool g_bShowPrintScreenWarningDialog;
|
||||
@ -226,3 +233,6 @@ void SetVideoType(VideoType_e newVideoType);
|
||||
VideoStyle_e GetVideoStyle(void);
|
||||
void SetVideoStyle(VideoStyle_e newVideoStyle);
|
||||
bool IsVideoStyle(VideoStyle_e mask);
|
||||
|
||||
VideoRefreshRate_e GetVideoRefreshRate(void);
|
||||
void SetVideoRefreshRate(VideoRefreshRate_e rate);
|
||||
|
@ -5510,7 +5510,10 @@ static void opcode_fd(BYTE ip1, BYTE ip2, BYTE ip3, WORD ip12, WORD ip23)
|
||||
|
||||
/* Z80 mainloop. */
|
||||
|
||||
static const double uZ80ClockMultiplier = CLK_Z80 / CLK_6502;
|
||||
// The effective Z-80 clock rate is 2.041MHz
|
||||
// See: http://www.apple2info.net/hardware/softcard/SC-SWHW_a2in.pdf
|
||||
static const double uZ80ClockMultiplier = 2;
|
||||
|
||||
inline static ULONG ConvertZ80TStatesTo6502Cycles(UINT uTStates)
|
||||
{
|
||||
return (uTStates < 0) ? 0 : (ULONG) ((double)uTStates / uZ80ClockMultiplier);
|
||||
|
Loading…
Reference in New Issue
Block a user