diff --git a/AppleWinExpress2019.vcxproj b/AppleWinExpress2019.vcxproj
index 6e8a483d4..eb8544b90 100644
--- a/AppleWinExpress2019.vcxproj
+++ b/AppleWinExpress2019.vcxproj
@@ -121,6 +121,7 @@
+
@@ -247,6 +248,7 @@
+
diff --git a/AppleWinExpress2019.vcxproj.filters b/AppleWinExpress2019.vcxproj.filters
index 49c6034d5..26c96c5dd 100644
--- a/AppleWinExpress2019.vcxproj.filters
+++ b/AppleWinExpress2019.vcxproj.filters
@@ -241,6 +241,9 @@
Source Files\Emulator
+
+ Source Files\Video
+
@@ -555,6 +558,9 @@
Source Files\Emulator
+
+ Source Files\Video
+
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index 968fa3f81..dc7c5687a 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -84,7 +84,7 @@ IDB_DEBUG_FONT_7X8 BITMAP "Debug_Font.bmp"
// Dialog
//
-IDD_PROPPAGE_CONFIG DIALOGEX 0, 0, 210, 209
+IDD_PROPPAGE_CONFIG DIALOGEX 0, 0, 210, 240
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_CAPTION | WS_SYSMENU
CAPTION "Configuration"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
@@ -92,30 +92,32 @@ BEGIN
LTEXT "&Model:",IDC_STATIC,5,7,40,8
COMBOBOX IDC_COMPUTER,45,5,91,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Confirm reboot",IDC_CHECK_CONFIRM_REBOOT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,142,8,62,10
- GROUPBOX "Video",IDC_STATIC,5,22,200,56
+ GROUPBOX "Video",IDC_STATIC,5,22,200,74
LTEXT "Mo&de:",IDC_STATIC,12,33,33,8
COMBOBOX IDC_VIDEOTYPE,33,30,103,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Monochrome &Color...",IDC_MONOCOLOR,12,46,80,14
CONTROL "50% Scan lines",IDC_CHECK_HALF_SCAN_LINES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,142,33,62,10
CONTROL "Vertical blend",IDC_CHECK_VERTICAL_BLEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,142,48,62,10
- CONTROL "Full-Screen: Show drive/keyboard status",IDC_CHECK_FS_SHOW_SUBUNIT_STATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,64,140,10
- LTEXT "&Serial Port:",IDC_STATIC,5,89,40,8
- COMBOBOX IDC_SERIALPORT,45,87,90,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- PUSHBUTTON "&Ethernet Settings...",IDC_ETHERNET,4,105,80,14
- GROUPBOX "Emulation Speed Control",IDC_STATIC,5,130,200,85
+ CONTROL "Full-Screen: Show drive/keyboard status",IDC_CHECK_FS_SHOW_SUBUNIT_STATUS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,64,140,10
+ CONTROL "VidHD in slot 3",IDC_CHECK_VIDHD_IN_SLOT3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,78,140,10
+ LTEXT "&Serial Port:",IDC_STATIC,5,108,40,8
+ COMBOBOX IDC_SERIALPORT,45,106,90,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Ethernet Settings...",IDC_ETHERNET,4,124,80,14
+ GROUPBOX "Emulation Speed Control",IDC_STATIC,5,149,200,85
CONTROL "Use &Authentic Machine Speed",IDC_AUTHENTIC_SPEED,
- "Button",BS_AUTORADIOBUTTON,15,141,115,10
- CONTROL "Select C&ustom Speed (in MHz)",IDC_CUSTOM_SPEED,"Button",BS_AUTORADIOBUTTON,15,153,115,10
- CONTROL "Generic2",IDC_SLIDER_CPU_SPEED,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,25,164,160,15
- CTEXT "0.5",IDC_0_5_MHz,23,180,20,10
- CTEXT "1.0",IDC_1_0_MHz,59,180,20,10
- 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
+ "Button",BS_AUTORADIOBUTTON,15,160,115,10
+ CONTROL "Select C&ustom Speed (in MHz)",IDC_CUSTOM_SPEED,"Button",BS_AUTORADIOBUTTON,15,172,115,10
+ CONTROL "Generic2",IDC_SLIDER_CPU_SPEED,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,25,183,160,15
+ CTEXT "0.5",IDC_0_5_MHz,23,199,20,10
+ CTEXT "1.0",IDC_1_0_MHz,59,199,20,10
+ CTEXT "2.0",IDC_2_0_MHz,96,199,20,10
+ RTEXT "Fastest",IDC_MAX_MHz,150,199,29,10
+ PUSHBUTTON "&Benchmark Emulator",IDC_BENCHMARK,15,213,85,15
+ CONTROL "50Hz video",IDC_CHECK_50HZ_VIDEO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,142,160,51,10
END
-IDD_PROPPAGE_INPUT DIALOGEX 0, 0, 211, 240
+IDD_PROPPAGE_INPUT DIALOGEX 0, 0, 210, 240
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_CAPTION | WS_SYSMENU
CAPTION "Input"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
@@ -172,7 +174,7 @@ BEGIN
CONTROL "No sound cards",IDC_SOUNDCARD_DISABLE,"Button",BS_AUTORADIOBUTTON,10,175,78,10
END
-IDD_PROPPAGE_DISK DIALOGEX 0, 0, 211, 188
+IDD_PROPPAGE_DISK DIALOGEX 0, 0, 210, 240
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_CAPTION | WS_SYSMENU
CAPTION "Disk"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
diff --git a/resource/resource.h b/resource/resource.h
index ae5a2158b..819b10115 100644
--- a/resource/resource.h
+++ b/resource/resource.h
@@ -70,7 +70,6 @@
#define IDC_PHASOR_ENABLE 1029
#define IDC_SAM_ENABLE 1030
#define IDC_SOUNDCARD_DISABLE 1031
-
#define IDC_TFE_SETTINGS_ENABLE_T 1032
#define IDC_TFE_SETTINGS_ENABLE 1033
#define IDC_TFE_SETTINGS_INTERFACE_T 1034
@@ -99,7 +98,6 @@
#define IDC_PRINTER_FILTER_UNPRINTABLE 1057
#define IDC_PRINTER_APPEND 1058
#define IDC_SPIN_PRINTER_IDLE 1059
-
#define IDC_CHECK_HALF_SCAN_LINES 1060
#define IDC_GPL_TEXT 1061
#define IDC_GPL_BORDER 1063
@@ -120,6 +118,7 @@
#define IDC_COMBO_DISK2_SLOT5 1086
#define IDC_FOURPLAY_CONFIG 1087
#define IDC_SNESMAX_CONFIG 1088
+#define IDC_CHECK_VIDHD_IN_SLOT3 1089
#define IDM_EXIT 40001
#define IDM_HELP 40002
#define IDM_ABOUT 40003
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 34bed4c64..c1c35200f 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -47,6 +47,7 @@ set(SOURCE_FILES
Debugger/Debugger_Commands.cpp
Debugger/Util_MemoryTextFile.cpp
+ VidHD.cpp
SSI263.cpp
Speaker.cpp
SoundCore.cpp
@@ -115,6 +116,7 @@ set(SOURCE_FILES
)
set(HEADER_FILES
+ VidHD.cpp
SSI263.h
SSI263Phonemes.h
Speaker.h
diff --git a/source/Card.h b/source/Card.h
index aae57cf0a..225ba8047 100644
--- a/source/Card.h
+++ b/source/Card.h
@@ -23,6 +23,7 @@ enum SS_CARDTYPE
CT_Saturn128K, // Saturn 128K (but may be populated with less RAM, in multiples of 16K)
CT_FourPlay, // 4 port Atari 2600 style digital joystick card
CT_SNESMAX, // 2 port Nintendo NES/SNES controller serial interface card
+ CT_VidHD,
CT_Uthernet2,
};
diff --git a/source/CardManager.cpp b/source/CardManager.cpp
index f250f1fe2..65c9f3257 100644
--- a/source/CardManager.cpp
+++ b/source/CardManager.cpp
@@ -40,6 +40,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SAM.h"
#include "SerialComms.h"
#include "SNESMAX.h"
+#include "VidHD.h"
+#include "linux/network/uthernet2.h"
void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type)
{
@@ -91,7 +93,7 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type)
m_slot[slot] = new DummyCard(type, slot);
break;
case CT_Uthernet2:
- m_slot[slot] = new DummyCard(type, slot);
+ m_slot[slot] = new Uthernet2(slot);
break;
case CT_FourPlay:
m_slot[slot] = new FourPlayCard(slot);
@@ -99,6 +101,9 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type)
case CT_SNESMAX:
m_slot[slot] = new SNESMAXCard(slot);
break;
+ case CT_VidHD:
+ m_slot[slot] = new VidHDCard(slot);
+ break;
case CT_LanguageCard:
case CT_Saturn128K:
diff --git a/source/CmdLine.cpp b/source/CmdLine.cpp
index 2dbccffe0..acfdca31c 100644
--- a/source/CmdLine.cpp
+++ b/source/CmdLine.cpp
@@ -169,6 +169,13 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
g_cmdLine.bSlotEmpty[slot] = true;
if (strcmp(lpCmdLine, "diskii") == 0)
g_cmdLine.slotInsert[slot] = CT_Disk2;
+ if (strcmp(lpCmdLine, "vidhd") == 0)
+ {
+ if (slot == SLOT3)
+ g_cmdLine.slotInsert[slot] = CT_VidHD;
+ else
+ LogFileOutput("VidHD currently only supported in slot 3\n");
+ }
}
else if (lpCmdLine[3] == 'd' && (lpCmdLine[4] == '1' || lpCmdLine[4] == '2')) // -s[1..7]d[1|2]
{
@@ -208,6 +215,19 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
{
g_cmdLine.setFullScreen = 0;
}
+#define CMD_FS_WIDTH "-fs-width="
+ else if (strncmp(lpCmdLine, CMD_FS_WIDTH, sizeof(CMD_FS_WIDTH)-1) == 0)
+ {
+ if (g_cmdLine.setFullScreen < 0) // Not yet been specified on cmd line?
+ g_cmdLine.setFullScreen = 1; // Implicity set full-screen. NB. Can be overridden by "-no-full-screen"
+
+ LPSTR lpTmp = lpCmdLine + sizeof(CMD_FS_WIDTH)-1;
+ {
+ g_cmdLine.userSpecifiedWidth = atoi(lpTmp);
+ if (!g_cmdLine.userSpecifiedWidth)
+ LogFileOutput("Invalid cmd-line parameter for -fs-width=x switch\n");
+ }
+ }
#define CMD_FS_HEIGHT "-fs-height="
else if (strncmp(lpCmdLine, CMD_FS_HEIGHT, sizeof(CMD_FS_HEIGHT)-1) == 0)
{
@@ -215,24 +235,16 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
g_cmdLine.setFullScreen = 1; // Implicity set full-screen. NB. Can be overridden by "-no-full-screen"
LPSTR lpTmp = lpCmdLine + sizeof(CMD_FS_HEIGHT)-1;
- bool bRes = false;
- UINT bestWidth=0, bestHeight=0;
if (strcmp(lpTmp, "best") == 0)
{
- bRes = GetFrame().GetBestDisplayResolutionForFullScreen(bestWidth, bestHeight);
+ g_cmdLine.bestFullScreenResolution = true;
}
else
{
- UINT userSpecifiedHeight = atoi(lpTmp);
- if (userSpecifiedHeight)
- bRes = GetFrame().GetBestDisplayResolutionForFullScreen(bestWidth, bestHeight, userSpecifiedHeight);
- else
+ g_cmdLine.userSpecifiedHeight = atoi(lpTmp);
+ if (!g_cmdLine.userSpecifiedHeight)
LogFileOutput("Invalid cmd-line parameter for -fs-height=x switch\n");
}
- if (bRes)
- LogFileOutput("Best resolution for -fs-height=x switch: Width=%d, Height=%d\n", bestWidth, bestHeight);
- else
- LogFileOutput("Failed to set parameter for -fs-height=x switch\n");
}
else if (strcmp(lpCmdLine, "-no-di") == 0)
{
diff --git a/source/CmdLine.h b/source/CmdLine.h
index 2e1034cd8..b76dd0f4a 100644
--- a/source/CmdLine.h
+++ b/source/CmdLine.h
@@ -35,6 +35,9 @@ struct CmdLine
rgbCard = RGB_Videocard_e::Apple;
rgbCardForegroundColor = 15;
rgbCardBackgroundColor = 0;
+ bestFullScreenResolution = false;
+ userSpecifiedWidth = 0;
+ userSpecifiedHeight = 0;
for (UINT i = 0; i < NUM_SLOTS; i++)
{
@@ -74,6 +77,9 @@ struct CmdLine
int rgbCardForegroundColor;
int rgbCardBackgroundColor;
std::string strCurrentDir;
+ bool bestFullScreenResolution;
+ UINT userSpecifiedWidth;
+ UINT userSpecifiedHeight;
};
bool ProcessCmdLine(LPSTR lpCmdLine);
diff --git a/source/Configuration/PageConfig.cpp b/source/Configuration/PageConfig.cpp
index 4db1efa83..996c56fe0 100644
--- a/source/Configuration/PageConfig.cpp
+++ b/source/Configuration/PageConfig.cpp
@@ -89,18 +89,18 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
switch (LOWORD(wparam))
{
case IDC_AUTHENTIC_SPEED: // Authentic Machine Speed
- SendDlgItemMessage(hWnd,IDC_SLIDER_CPU_SPEED,TBM_SETPOS,1,SPEED_NORMAL);
- EnableTrackbar(hWnd,0);
+ SendDlgItemMessage(hWnd, IDC_SLIDER_CPU_SPEED, TBM_SETPOS, 1, SPEED_NORMAL);
+ EnableTrackbar(hWnd, 0);
break;
case IDC_CUSTOM_SPEED: // Select Custom Speed
- SetFocus(GetDlgItem(hWnd,IDC_SLIDER_CPU_SPEED));
- EnableTrackbar(hWnd,1);
+ SetFocus(GetDlgItem(hWnd, IDC_SLIDER_CPU_SPEED));
+ EnableTrackbar(hWnd, 1);
break;
case IDC_SLIDER_CPU_SPEED: // CPU speed slider
- CheckRadioButton(hWnd,IDC_AUTHENTIC_SPEED,IDC_CUSTOM_SPEED,IDC_CUSTOM_SPEED);
- EnableTrackbar(hWnd,1);
+ CheckRadioButton(hWnd, IDC_AUTHENTIC_SPEED, IDC_CUSTOM_SPEED, IDC_CUSTOM_SPEED);
+ EnableTrackbar(hWnd, 1);
break;
case IDC_BENCHMARK:
@@ -113,6 +113,7 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
case IDC_ETHERNET:
ui_tfe_settings_dialog(hWnd);
m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT3] = m_PageConfigTfe.m_tfe_enabled ? CT_Uthernet : CT_Empty;
+ InitOptions(hWnd);
break;
case IDC_MONOCOLOR:
@@ -127,6 +128,14 @@ INT_PTR CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPA
// Checked in DlgOK()
break;
+ case IDC_CHECK_VIDHD_IN_SLOT3:
+ {
+ const UINT newState = IsDlgButtonChecked(hWnd, IDC_CHECK_VIDHD_IN_SLOT3) ? 1 : 0;
+ m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT3] = newState ? CT_VidHD : CT_Empty;
+ InitOptions(hWnd);
+ }
+ break;
+
case IDC_COMPUTER:
if(HIWORD(wparam) == CBN_SELCHANGE)
{
@@ -374,6 +383,11 @@ void CPageConfig::InitOptions(HWND hWnd)
const SS_CARDTYPE slot3 = m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT3];
const BOOL enableUthernetDialog = slot3 == CT_Empty || slot3 == CT_Uthernet;
EnableWindow(GetDlgItem(hWnd, IDC_ETHERNET), enableUthernetDialog);
+
+ const bool bIsSlot3VidHD = slot3 == CT_VidHD;
+ CheckDlgButton(hWnd, IDC_CHECK_VIDHD_IN_SLOT3, bIsSlot3VidHD ? BST_CHECKED : BST_UNCHECKED);
+ const BOOL enableVidHD = slot3 == CT_Empty || bIsSlot3VidHD;
+ EnableWindow(GetDlgItem(hWnd, IDC_CHECK_VIDHD_IN_SLOT3), enableVidHD);
}
// Config->Computer: Menu item to eApple2Type
diff --git a/source/Configuration/PropertySheetHelper.cpp b/source/Configuration/PropertySheetHelper.cpp
index 217d79d3e..426c05973 100644
--- a/source/Configuration/PropertySheetHelper.cpp
+++ b/source/Configuration/PropertySheetHelper.cpp
@@ -548,6 +548,8 @@ std::string CPropertySheetHelper::GetCardName(const SS_CARDTYPE CardType)
return "4Play";
case CT_SNESMAX:
return "SNES MAX";
+ case CT_VidHD:
+ return "VidHD";
default:
return "Unknown";
}
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index 3e68efabc..6acb242b9 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -6545,6 +6545,11 @@ Update_t _ViewOutput( ViewVideoPage_t iPage, int bVideoModeFlags )
{
return _ViewOutput( VIEW_PAGE_2, VF_HIRES | VF_DHIRES | VF_80COL );
}
+// Super Hi-Res
+ Update_t CmdViewOutput_SHR(int nArgs)
+ {
+ return _ViewOutput( VIEW_PAGE_1, VF_SHR );
+ }
// Watches ________________________________________________________________________________________
@@ -8744,6 +8749,9 @@ void DebuggerProcessKey( int keycode )
// Normally any key press takes us out of "Viewing Apple Output" g_nAppMode
// VK_F# are already processed, so we can't use them to cycle next video g_nAppMode
// if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG))
+
+ GetVideo().ClearSHRResidue(); // Clear the framebuffer to remove any SHR residue in the borders
+
DebugVideoMode::Instance().Reset();
UpdateDisplay( UPDATE_ALL ); // 1
return;
diff --git a/source/Debugger/Debugger_Commands.cpp b/source/Debugger/Debugger_Commands.cpp
index ac056080f..c19675129 100644
--- a/source/Debugger/Debugger_Commands.cpp
+++ b/source/Debugger/Debugger_Commands.cpp
@@ -267,6 +267,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{TEXT("DHGR") , CmdViewOutput_DHGRX , CMD_VIEW_DHGRX , "View Double Hi-res (current page)" },
{TEXT("DHGR1") , CmdViewOutput_DHGR1 , CMD_VIEW_DHGR1 , "View Double Hi-res Page 1" },
{TEXT("DHGR2") , CmdViewOutput_DHGR2 , CMD_VIEW_DHGR2 , "View Double Hi-res Page 2" },
+ {TEXT("SHR") , CmdViewOutput_SHR , CMD_VIEW_SHR , "View Super Hi-res" },
// Watch
{TEXT("W") , CmdWatch , CMD_WATCH , "Alias for WA (Watch Add)" },
{TEXT("WA") , CmdWatchAdd , CMD_WATCH_ADD , "Add/Update address or symbol to watch" },
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index 70d7a9ec3..9e118b459 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -639,8 +639,8 @@ void StretchBltMemToFrameDC(void)
int nViewportCX, nViewportCY;
win32Frame.GetViewportCXCY(nViewportCX, nViewportCY);
- int xdest = win32Frame.IsFullScreen() ? win32Frame.GetFullScreenOffsetX() : 0;
- int ydest = win32Frame.IsFullScreen() ? win32Frame.GetFullScreenOffsetY() : 0;
+ int xdest = win32Frame.IsFullScreen() ? win32Frame.GetFullScreenOffsetX() : GetVideo().GetFrameBufferCentringOffsetX() * win32Frame.GetViewportScale();
+ int ydest = win32Frame.IsFullScreen() ? win32Frame.GetFullScreenOffsetY() : GetVideo().GetFrameBufferCentringOffsetY() * win32Frame.GetViewportScale();
int wdest = nViewportCX;
int hdest = nViewportCY;
@@ -738,6 +738,7 @@ static void PrintGlyph( const int xDst, const int yDst, const int glyph )
// Manual print of character. A lot faster than BitBlt, which must be avoided.
int index_src = (CONSOLE_FONT_BITMAP_HEIGHT - 1 - ySrc) * CONSOLE_FONT_NUM_CHARS_PER_ROW * CONSOLE_FONT_GRID_X + xSrc; // font bitmap
int index_dst = (DISPLAY_HEIGHT - 1 - yDst) * DEBUG_VIRTUAL_TEXT_WIDTH * CONSOLE_FONT_GRID_X + xDst; // debugger bitmap
+
for (int yy = 0; yy < CONSOLE_FONT_GRID_Y; yy++)
{
for (int xx = 0; xx < CONSOLE_FONT_GRID_X; xx++)
diff --git a/source/Debugger/Debugger_Types.h b/source/Debugger/Debugger_Types.h
index 8ac67eb2f..63141dbd9 100644
--- a/source/Debugger/Debugger_Types.h
+++ b/source/Debugger/Debugger_Types.h
@@ -509,6 +509,7 @@
, CMD_VIEW_DHGRX
, CMD_VIEW_DHGR1
, CMD_VIEW_DHGR2
+ , CMD_VIEW_SHR
// Watch
, CMD_WATCH // TODO: Deprecated ?
, CMD_WATCH_ADD
@@ -770,6 +771,7 @@
Update_t CmdViewOutput_DHGRX (int nArgs);
Update_t CmdViewOutput_DHGR1 (int nArgs);
Update_t CmdViewOutput_DHGR2 (int nArgs);
+ Update_t CmdViewOutput_SHR (int nArgs);
// Watch
Update_t CmdWatch (int nArgs);
Update_t CmdWatchAdd (int nArgs);
diff --git a/source/FrameBase.h b/source/FrameBase.h
index bcf267ef3..1850cc592 100644
--- a/source/FrameBase.h
+++ b/source/FrameBase.h
@@ -15,7 +15,7 @@ class FrameBase
BOOL g_bMultiMon;
bool g_bFreshReset;
- virtual void Initialize(void) = 0;
+ virtual void Initialize(bool resetVideoState) = 0;
virtual void Destroy(void) = 0;
virtual void FrameDrawDiskLEDS() = 0;
@@ -26,13 +26,14 @@ class FrameBase
virtual void FrameSetCursorPosByMousePos() = 0;
virtual void SetFullScreenShowSubunitStatus(bool bShow) = 0;
- virtual bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedHeight = 0) = 0;
+ virtual bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedWidth=0, UINT userSpecifiedHeight=0) = 0;
virtual int SetViewportScale(int nNewScale, bool bForce = false) = 0;
virtual void SetAltEnterToggleFullScreen(bool mode) = 0;
virtual void SetLoadedSaveStateFlag(const bool bFlag) = 0;
virtual void VideoPresentScreen(void) = 0;
+ virtual void ResizeWindow(void) = 0;
// this function has the same interface as MessageBox in windows.h
virtual int FrameMessageBox(LPCSTR lpText, LPCSTR lpCaption, UINT uType) = 0;
diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp
index b46e124cc..01651dbb6 100644
--- a/source/Harddisk.cpp
+++ b/source/Harddisk.cpp
@@ -518,6 +518,11 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY
{
memdirty[dstAddr >> 8] = 0xFF;
LPBYTE page = memwrite[dstAddr >> 8];
+ if (!page)
+ {
+ _ASSERT(0);
+ break;
+ }
// handle both page-aligned & non-page aligned destinations
UINT size = PAGE_SIZE - (dstAddr & 0xff);
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 21ffc2d00..48af597f3 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -122,6 +122,10 @@ VIDEO SOFT SWITCHES
$C00D W 80COLON Turn on 80 column display
$C00E W ALTCHARSETOFF Turn off alternate characters
$C00F W ALTCHARSETON Turn on alternate characters
+ $C022 R/W SCREENCOLOR [IIgs] text foreground and background colors (also VidHD)
+ $C029 R/W NEWVIDEO [IIgs] Select new video modes (also VidHD)
+ $C034 R/W BORDERCOLOR [IIgs] b3:0 are border color (also VidHD)
+ $C035 R/W SHADOW [IIgs] auxmem-to-bank-E1 shadowing (also VidHD)
$C050 R/W TEXTOFF Select graphics mode
$C051 R/W TEXTON Select text mode
$C052 R/W MIXEDOFF Use full screen for graphics
@@ -470,6 +474,12 @@ static BYTE __stdcall IORead_C02x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
static BYTE __stdcall IOWrite_C02x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
{
+ if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD)
+ {
+ if (addr == 0xC022 || addr == 0xC029)
+ GetVideo().VideoSetMode(pc, addr, bWrite, d, nExecutedCycles);
+ }
+
return TapeWrite(pc, addr, bWrite, d, nExecutedCycles); // $C020 TAPEOUT
}
@@ -482,6 +492,13 @@ static BYTE __stdcall IORead_C03x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
static BYTE __stdcall IOWrite_C03x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
{
+ if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD)
+ {
+ // NB. Writes to $C03x addresses will still toggle the speaker, even with a VidHD present
+ if (addr == 0xC034 || addr == 0xC035)
+ GetVideo().VideoSetMode(pc, addr, bWrite, d, nExecutedCycles);
+ }
+
return SpkrToggle(pc, addr, bWrite, d, nExecutedCycles);
}
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index 0eaccfeba..a8691a50c 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Memory.h" // MemGetMainPtr(), MemGetAuxPtr(), MemGetAnnunciator()
#include "Interface.h" // GetFrameBuffer()
#include "RGBMonitor.h"
+ #include "VidHD.h"
#include "NTSC_CharSet.h"
@@ -100,11 +101,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define VIDEO_SCANNER_HORZ_START 25 // first displayable horz scanner index
#define VIDEO_SCANNER_Y_MIXED 160 // num scanlins for mixed graphics + text
#define VIDEO_SCANNER_Y_DISPLAY 192 // max displayable scanlines
+ #define VIDEO_SCANNER_Y_DISPLAY_IIGS 200
- // these are initialized in NTSC_VideoInit
+ // These 3 vars are initialized in NTSC_VideoInit()
static bgra_t* g_pVideoAddress = 0;
- static bgra_t *g_pScanLines[VIDEO_SCANNER_Y_DISPLAY*2]; // To maintain the 280x192 aspect ratio for 560px width, we double every scan line -> 560x384
- static UINT g_kFrameBufferWidth;
+ // To maintain the 280x192 aspect ratio for 560px width, we double every scan line -> 560x384
+ // NB. For IIgs SHR, the 320x200 is again doubled (to 640x400), but this gives a ~16:9 ratio, when 4:3 is probably required (ie. stretch height from 200 to 240)
+ static bgra_t* g_pScanLines[VIDEO_SCANNER_Y_DISPLAY_IIGS * 2];
+ static UINT g_kFrameBufferWidth = 0;
static unsigned short (*g_pHorzClockOffset)[VIDEO_SCANNER_MAX_HORZ] = 0;
@@ -348,6 +352,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
static void updateScreenText80RGB ( long cycles6502 );
static void updateScreenDoubleHires80Simplified(long cycles6502);
static void updateScreenDoubleHires80RGB(long cycles6502);
+ static void updateScreenSHR(long cycles6502);
//===========================================================================
static void set_csbits()
@@ -712,13 +717,37 @@ inline void updateVideoScannerHorzEOL()
}
}
+inline void updateVideoScannerHorzEOL_SHR()
+{
+ if (VIDEO_SCANNER_MAX_HORZ == ++g_nVideoClockHorz)
+ {
+ g_nVideoClockHorz = 0;
+
+ if (++g_nVideoClockVert == g_videoScannerMaxVert)
+ {
+ g_nVideoClockVert = 0;
+ }
+
+ if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY_IIGS)
+ {
+ updateVideoScannerAddress();
+ }
+ }
+}
+
//===========================================================================
inline void updateVideoScannerAddress()
{
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED && GetVideo().GetVideoRefreshRate() == VR_50HZ) // GH#763
g_nColorBurstPixels = 0; // instantaneously kill color-burst!
- g_pVideoAddress = g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY ? g_pScanLines[2*g_nVideoClockVert] : g_pScanLines[0];
+ if (g_pFuncUpdateGraphicsScreen == updateScreenSHR)
+ {
+ g_pVideoAddress = g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY_IIGS ? g_pScanLines[2 * g_nVideoClockVert] : g_pScanLines[0];
+ return;
+ }
+
+ g_pVideoAddress = g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY ? g_pScanLines[2 * g_nVideoClockVert] : g_pScanLines[0];
// Adjust, as these video styles have 2x 14M pixels of pre-render
// NB. For VT_COLOR_MONITOR_NTSC, also check color-burst so that TEXT and MIXED(HGR+TEXT) render the TEXT at the same offset (GH#341)
@@ -740,6 +769,9 @@ inline void updateVideoScannerAddress()
g_pVideoAddress -= 1;
}
+ // Centre the older //e video modes when running with a VidHD
+ g_pVideoAddress += GetVideo().GetFrameBufferCentringValue();
+
g_nColorPhaseNTSC = INITIAL_COLOR_PHASE;
g_nLastColumnPixelNTSC = 0;
g_nSignalBitsNTSC = 0;
@@ -760,7 +792,6 @@ INLINE uint16_t getVideoScannerAddressHGR()
APPLE_IIE_HORZ_CLOCK_OFFSET[g_nVideoClockVert/64][g_nVideoClockHorz] + (g_nHiresPage * 0x2000));
}
-
// Non-Inline _________________________________________________________
// Build the 4 phase chroma lookup table
@@ -1709,6 +1740,42 @@ void updateScreenText80RGB(long cycles6502)
}
}
+//===========================================================================
+void updateScreenSHR(long cycles6502)
+{
+ for (; cycles6502 > 0; --cycles6502)
+ {
+ // 2 pixels per byte in 320-pixel mode = 160 bytes/scanline
+ // 4 pixels per byte in 640-pixel mode = 160 bytes/scanline
+ const UINT kBytesPerScanline = 160;
+ const UINT kBytesPerCycle = 4;
+ uint16_t addr = 0x2000 + kBytesPerScanline * g_nVideoClockVert + kBytesPerCycle * (g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START);
+
+ if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY_IIGS)
+ {
+ if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
+ {
+ uint32_t* pAux = (uint32_t*) MemGetAuxPtr(addr); // 8 pixels (320 mode) / 16 pixels (640 mode)
+ uint32_t a = pAux[0];
+
+ uint8_t* pControl = MemGetAuxPtr(0x9D00 + g_nVideoClockVert); // scan-line control byte
+ uint8_t c = pControl[0];
+
+ bool is640Mode = c & 0x80;
+ bool isColorFillMode = c & 0x20;
+ UINT paletteSelectCode = c & 0xf;
+ const UINT kColorsPerPalette = 16;
+ const UINT kColorSize = 2;
+ uint16_t addrPalette = 0x9E00 + paletteSelectCode * kColorsPerPalette * kColorSize;
+
+ VidHDCard::UpdateSHRCell(is640Mode, isColorFillMode, addrPalette, g_pVideoAddress, a);
+ g_pVideoAddress += 16;
+ }
+ }
+ updateVideoScannerHorzEOL_SHR();
+ }
+}
+
// Functions (Public) _____________________________________________________________________________
//===========================================================================
@@ -1803,6 +1870,19 @@ void NTSC_SetVideoTextMode( int cols )
//===========================================================================
void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
{
+ if (uVideoModeFlags & VF_SHR)
+ {
+ g_pFuncUpdateGraphicsScreen = updateScreenSHR;
+ g_pFuncUpdateTextScreen = updateScreenSHR;
+ return;
+ }
+
+ if (g_pFuncUpdateGraphicsScreen == updateScreenSHR && !(uVideoModeFlags & VF_SHR))
+ {
+ // Was SHR mode, so clear the framebuffer to remove any SHR residue in the borders
+ GetVideo().ClearFrameBuffer();
+ }
+
if (bDelay && !g_bFullSpeed)
{
// (GH#670) NB. if g_bFullSpeed then NTSC_VideoUpdateCycles() won't be called on the next 6502 opcode.
@@ -1812,7 +1892,6 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
return;
}
-
g_nVideoMixed = uVideoModeFlags & VF_MIXED;
g_nVideoCharSet = GetVideo().VideoGetSWAltCharSet() ? 1 : 0;
@@ -2104,7 +2183,7 @@ void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit
g_kFrameBufferWidth = GetVideo().GetFrameBufferWidth();
- for (int y = 0; y < (VIDEO_SCANNER_Y_DISPLAY*2); y++)
+ for (int y = 0; y < (VIDEO_SCANNER_Y_DISPLAY_IIGS*2); y++)
{
uint32_t offset = sizeof(bgra_t) * GetVideo().GetFrameBufferWidth()
* ((GetVideo().GetFrameBufferHeight() - 1) - y - GetVideo().GetFrameBufferBorderHeight())
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index d1bda6d32..0c4b12e50 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -50,6 +50,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SNESMAX.h"
#include "Speaker.h"
#include "Speech.h"
+#include "VidHD.h"
#include "z80emu.h"
#include "Configuration/Config.h"
@@ -288,10 +289,6 @@ static void ParseUnitApple2(YamlLoadHelper& yamlLoadHelper, UINT version)
SpkrLoadSnapshot(yamlLoadHelper);
GetVideo().VideoLoadSnapshot(yamlLoadHelper, version);
MemLoadSnapshot(yamlLoadHelper, version);
-
- // g_Apple2Type may've changed: so redraw frame (title, buttons, leds, etc)
- GetVideo().VideoReinitialize(true); // g_CharsetType changed
- GetFrame().FrameUpdateApple2Type(); // Calls VideoRedrawScreen() before the aux mem has been loaded (so if DHGR is enabled, then aux mem will be zeros at this stage)
}
//---
@@ -381,6 +378,10 @@ static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT unitVersion)
{
type = CT_SNESMAX;
}
+ else if (card == VidHDCard::GetSnapshotCardName())
+ {
+ type = CT_VidHD;
+ }
else
{
throw std::string("Slots: Unknown card: " + card); // todo: don't throw - just ignore & continue
@@ -482,6 +483,7 @@ static void Snapshot_LoadState_v2(void)
GetPravets().Reset();
KeybReset();
+ GetVideo().SetVidHD(false); // Set true later only if VidHDCard is instantiated
GetVideo().VideoResetState();
GetVideo().SetVideoRefreshRate(VR_60HZ); // Default to 60Hz as older save-states won't contain refresh rate
MB_InitializeForLoadingSnapshot(); // GH#609
@@ -520,6 +522,12 @@ static void Snapshot_LoadState_v2(void)
DebugReset();
if (g_nAppMode == MODE_DEBUG)
DebugDisplay(TRUE);
+
+ frame.Initialize(false); // don't reset the video state
+ frame.ResizeWindow();
+
+ // g_Apple2Type may've changed: so reload button bitmaps & redraw frame (title, buttons, leds, etc)
+ frame.FrameUpdateApple2Type(); // NB. Calls VideoRedrawScreen()
}
catch(std::string szMessage)
{
diff --git a/source/Utilities.cpp b/source/Utilities.cpp
index ff1bcbd26..ffd6ad225 100644
--- a/source/Utilities.cpp
+++ b/source/Utilities.cpp
@@ -543,6 +543,8 @@ void ResetMachineState()
GetCardMgr().GetDisk2CardMgr().Reset(true);
if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
GetCardMgr().GetRef(SLOT7).Reset(true);
+ if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD)
+ GetCardMgr().GetRef(SLOT3).Reset(true);
g_bFullSpeed = 0; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted
MemReset(); // calls CpuInitialize(), CNoSlotClock.Reset()
@@ -597,7 +599,9 @@ void CtrlReset()
GetPravets().Reset();
GetCardMgr().GetDisk2CardMgr().Reset();
if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
- GetCardMgr().GetRef(SLOT7).Reset(true);
+ GetCardMgr().GetRef(SLOT7).Reset(false);
+ if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD)
+ GetCardMgr().GetRef(SLOT3).Reset(false);
KeybReset();
if (GetCardMgr().IsSSCInstalled())
GetCardMgr().GetSSC()->CommReset();
diff --git a/source/VidHD.cpp b/source/VidHD.cpp
new file mode 100644
index 000000000..88a27c38c
--- /dev/null
+++ b/source/VidHD.cpp
@@ -0,0 +1,190 @@
+/*
+ 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-2021, Tom Charlesworth, Michael Pohoreski
+
+ 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
+*/
+/*
+ Emulate a VidHD card (Blue Shift Inc)
+
+ Allows any Apple II to support the IIgs' 320x200 and 640x200 256-colour Super High-Res video modes.
+ Currently only a //e with 64K aux memory supports SHR mode.
+
+ NB. The extended text modes 80x45, 120x67, 240x135 (and setting FG/BG colours) are not supported yet.
+*/
+
+#include "StdAfx.h"
+
+#include "Memory.h"
+#include "NTSC.h"
+#include "Video.h"
+#include "VidHD.h"
+#include "YamlHelper.h"
+
+void VidHDCard::Reset(const bool powerCycle)
+{
+ m_NEWVIDEO = 0;
+ GetVideo().SetVideoMode(GetVideo().GetVideoMode() & ~VF_SHR);
+}
+
+void VidHDCard::InitializeIO(LPBYTE pCxRomPeripheral)
+{
+ RegisterIoHandler(m_slot, IO_Null, IO_Null, &VidHDCard::IORead, IO_Null, this, NULL);
+}
+
+BYTE __stdcall VidHDCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles)
+{
+ // Return magic bytes (from the VidHD firmware) for VidHD detection
+ switch (addr & 0xff)
+ {
+ case 0: return 0x24;
+ case 1: return 0xEA;
+ case 2: return 0x4C;
+ }
+ return IO_Null(pc, addr, bWrite, value, nExecutedCycles);
+}
+
+// NB. VidHD has no support for reading the IIgs video registers (from an earlier Apple II)
+void VidHDCard::VideoIOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles)
+{
+ switch (addr & 0xff)
+ {
+ case 0x22: // SCREENCOLOR
+ m_SCREENCOLOR = value;
+ break;
+ case 0x29: // NEWVIDEO
+ m_NEWVIDEO = value;
+ break;
+ case 0x34: // BORDERCOLOR
+ m_BORDERCOLOR = value;
+ break;
+ case 0x35: // SHADOW
+ m_SHADOW = value;
+ break;
+ default:
+ _ASSERT(0);
+ }
+}
+
+//===========================================================================
+
+#pragma pack(push)
+#pragma pack(1) // Ensure struct is packed
+struct Color
+{
+ USHORT blue : 4;
+ USHORT green : 4;
+ USHORT red : 4;
+ USHORT reserved : 4;
+};
+#pragma pack(pop)
+
+bgra_t ConvertIIgs2RGB(Color color)
+{
+ bgra_t rgb = { 0 };
+ rgb.r = color.red * 16;
+ rgb.g = color.green * 16;
+ rgb.b = color.blue * 16;
+ rgb.a = ALPHA;
+ return rgb;
+}
+
+void VidHDCard::UpdateSHRCell(bool is640Mode, bool isColorFillMode, uint16_t addrPalette, bgra_t* pVideoAddress, uint32_t a)
+{
+ _ASSERT(!is640Mode); // to do: test this mode
+
+ Color* palette = (Color*) MemGetAuxPtr(addrPalette);
+
+ for (UINT i = 0; i < 4; i++)
+ {
+ if (!is640Mode) // 320 mode
+ {
+ BYTE pixel1 = (a >> 4) & 0xf;
+ bgra_t color1 = ConvertIIgs2RGB(palette[pixel1]);
+ if (isColorFillMode && pixel1 == 0) color1 = *(pVideoAddress - 1);
+ *pVideoAddress++ = color1;
+ *pVideoAddress++ = color1;
+
+ BYTE pixel2 = a & 0xf;
+ bgra_t color2 = ConvertIIgs2RGB(palette[pixel2]);
+ if (isColorFillMode && pixel2 == 0) color2 = color1;
+ *pVideoAddress++ = color2;
+ *pVideoAddress++ = color2;
+ }
+ else // 640 mode - see IIgs Hardware Ref, Pg.96, Table4-21 'Color Selection in 640 mode'
+ {
+ BYTE pixel1 = (a >> 6) & 0x3;
+ bgra_t color1 = ConvertIIgs2RGB(palette[0x8 + pixel1]);
+ *pVideoAddress++ = color1;
+
+ BYTE pixel2 = (a >> 4) & 0x3;
+ bgra_t color2 = ConvertIIgs2RGB(palette[0xC + pixel2]);
+ *pVideoAddress++ = color2;
+
+ BYTE pixel3 = (a >> 2) & 0x3;
+ bgra_t color3 = ConvertIIgs2RGB(palette[0x0 + pixel3]);
+ *pVideoAddress++ = color3;
+
+ BYTE pixel4 = a & 0x3;
+ bgra_t color4 = ConvertIIgs2RGB(palette[0x4 + pixel4]);
+ *pVideoAddress++ = color4;
+ }
+
+ a >>= 8;
+ }
+}
+
+//===========================================================================
+
+static const UINT kUNIT_VERSION = 1;
+
+#define SS_YAML_KEY_SCREEN_COLOR "Screen Color"
+#define SS_YAML_KEY_NEW_VIDEO "New Video"
+#define SS_YAML_KEY_BORDER_COLOR "Border Color"
+#define SS_YAML_KEY_SHADOW "Shadow"
+
+std::string VidHDCard::GetSnapshotCardName(void)
+{
+ static const std::string name("VidHD");
+ return name;
+}
+
+void VidHDCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ YamlSaveHelper::Slot slot(yamlSaveHelper, GetSnapshotCardName(), m_slot, kUNIT_VERSION);
+
+ YamlSaveHelper::Label unit(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SCREEN_COLOR, m_SCREENCOLOR);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_NEW_VIDEO, m_NEWVIDEO);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_BORDER_COLOR, m_BORDERCOLOR);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SHADOW, m_SHADOW);
+}
+
+bool VidHDCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
+{
+ if (version < 1 || version > kUNIT_VERSION)
+ throw std::string("Card: wrong version");
+
+ m_SCREENCOLOR = yamlLoadHelper.LoadUint(SS_YAML_KEY_SCREEN_COLOR);
+ m_NEWVIDEO = yamlLoadHelper.LoadUint(SS_YAML_KEY_NEW_VIDEO);
+ m_BORDERCOLOR = yamlLoadHelper.LoadUint(SS_YAML_KEY_BORDER_COLOR);
+ m_SHADOW = yamlLoadHelper.LoadUint(SS_YAML_KEY_SHADOW);
+
+ return true;
+}
diff --git a/source/VidHD.h b/source/VidHD.h
new file mode 100644
index 000000000..8652c2787
--- /dev/null
+++ b/source/VidHD.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "Card.h"
+#include "Interface.h"
+
+class VidHDCard : public Card
+{
+public:
+ VidHDCard(UINT slot) :
+ Card(CT_VidHD, slot)
+ {
+ m_SCREENCOLOR = 0;
+ m_NEWVIDEO = 0;
+ m_BORDERCOLOR = 0;
+ m_SHADOW = 0;
+
+ GetVideo().SetVidHD(true);
+ }
+ virtual ~VidHDCard(void) {}
+
+ virtual void Init(void) {}
+ virtual void Reset(const bool powerCycle);
+ virtual void Update(const ULONG nExecutedCycles) {}
+ virtual void InitializeIO(LPBYTE pCxRomPeripheral);
+
+ static BYTE __stdcall IORead(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles);
+
+ void VideoIOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG nExecutedCycles);
+
+ bool IsSHR(void) { return (m_NEWVIDEO & 0xC0) == 0xC0; } // 11000001 = Enable SHR(b7) | Linearize SHR video memory(b6)
+ bool IsDHGRBlackAndWhite(void) { return (m_NEWVIDEO & (1 << 5)) ? true : false; }
+
+ static void UpdateSHRCell(bool is640Mode, bool isColorFillMode, uint16_t addrPalette, bgra_t* pVideoAddress, uint32_t a);
+
+ static std::string GetSnapshotCardName(void);
+ virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
+ virtual bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
+
+private:
+ BYTE m_SCREENCOLOR;
+ BYTE m_NEWVIDEO;
+ BYTE m_BORDERCOLOR;
+ BYTE m_SHADOW;
+};
diff --git a/source/Video.cpp b/source/Video.cpp
index f096cd31e..569afe176 100644
--- a/source/Video.cpp
+++ b/source/Video.cpp
@@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Video.h"
+#include "CardManager.h"
#include "Core.h"
#include "CPU.h"
#include "Log.h"
@@ -36,6 +37,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Registry.h"
#include "NTSC.h"
#include "RGBMonitor.h"
+#include "VidHD.h"
#include "YamlHelper.h"
#define SW_80COL (g_uVideoMode & VF_80COL)
@@ -45,6 +47,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define SW_MIXED (g_uVideoMode & VF_MIXED)
#define SW_PAGE2 (g_uVideoMode & VF_PAGE2)
#define SW_TEXT (g_uVideoMode & VF_TEXT)
+#define SW_SHR (g_uVideoMode & VF_SHR)
//-------------------------------------
@@ -91,14 +94,12 @@ const char* const Video::g_apVideoModeDesc[NUM_VIDEO_MODES] =
UINT Video::GetFrameBufferBorderlessWidth(void)
{
- static const UINT uFrameBufferBorderlessW = 560; // 560 = Double Hi-Res
- return uFrameBufferBorderlessW;
+ return HasVidHD() ? kVideoWidthIIgs : kVideoWidthII;
}
UINT Video::GetFrameBufferBorderlessHeight(void)
{
- static const UINT uFrameBufferBorderlessH = 384; // 384 = Double Scan Line
- return uFrameBufferBorderlessH;
+ return HasVidHD() ? kVideoHeightIIgs : kVideoHeightII;
}
// NB. These border areas are not visible (... and these border areas are unrelated to the 3D border below)
@@ -124,6 +125,29 @@ UINT Video::GetFrameBufferHeight(void)
return GetFrameBufferBorderlessHeight() + 2 * GetFrameBufferBorderHeight();
}
+UINT Video::GetFrameBufferCentringOffsetX(void)
+{
+ return HasVidHD() ? ((kVideoWidthIIgs - kVideoWidthII) / 2) : 0;
+}
+
+UINT Video::GetFrameBufferCentringOffsetY(void)
+{
+ return HasVidHD() ? ((kVideoHeightIIgs - kVideoHeightII) / 2) : 0;
+}
+
+int Video::GetFrameBufferCentringValue(void)
+{
+ int value = 0;
+
+ if (HasVidHD())
+ {
+ value -= GetFrameBufferCentringOffsetY() * GetFrameBufferWidth();
+ value += GetFrameBufferCentringOffsetX();
+ }
+
+ return value;
+}
+
//===========================================================================
void Video::VideoReinitialize(bool bInitVideoScannerAddress)
@@ -151,12 +175,15 @@ void Video::VideoResetState(void)
//===========================================================================
-BYTE Video::VideoSetMode(WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles)
+BYTE Video::VideoSetMode(WORD pc, WORD address, BYTE write, BYTE d, ULONG uExecutedCycles)
{
- address &= 0xFF;
-
const uint32_t oldVideoMode = g_uVideoMode;
+ VidHDCard* vidHD = NULL;
+ if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD)
+ vidHD = dynamic_cast(GetCardMgr().GetObj(SLOT3));
+
+ address &= 0xFF;
switch (address)
{
case 0x00: g_uVideoMode &= ~VF_80STORE; break;
@@ -165,6 +192,10 @@ BYTE Video::VideoSetMode(WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCy
case 0x0D: if (!IS_APPLE2){g_uVideoMode |= VF_80COL; NTSC_SetVideoTextMode(80);}; break;
case 0x0E: if (!IS_APPLE2) g_nAltCharSetOffset = 0; break; // Alternate char set off
case 0x0F: if (!IS_APPLE2) g_nAltCharSetOffset = 256; break; // Alternate char set on
+ case 0x22: if (vidHD) vidHD->VideoIOWrite(pc, address, write, d, uExecutedCycles); break; // VidHD IIgs video mode register
+ case 0x29: if (vidHD) vidHD->VideoIOWrite(pc, address, write, d, uExecutedCycles); break; // VidHD IIgs video mode register
+ case 0x34: if (vidHD) vidHD->VideoIOWrite(pc, address, write, d, uExecutedCycles); break; // VidHD IIgs video mode register
+ case 0x35: if (vidHD) vidHD->VideoIOWrite(pc, address, write, d, uExecutedCycles); break; // VidHD IIgs video mode register
case 0x50: g_uVideoMode &= ~VF_TEXT; break;
case 0x51: g_uVideoMode |= VF_TEXT; break;
case 0x52: g_uVideoMode &= ~VF_MIXED; break;
@@ -177,6 +208,11 @@ BYTE Video::VideoSetMode(WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCy
case 0x5F: if (!IS_APPLE2) g_uVideoMode &= ~VF_DHIRES; break;
}
+ if (vidHD && vidHD->IsSHR())
+ g_uVideoMode |= VF_SHR;
+ else
+ g_uVideoMode &= ~VF_SHR;
+
if (!IS_APPLE2)
RGB_SetVideoMode(address);
@@ -185,7 +221,7 @@ BYTE Video::VideoSetMode(WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCy
if ((oldVideoMode ^ g_uVideoMode) & (VF_TEXT|VF_MIXED))
delay = true;
- NTSC_SetVideoMode( g_uVideoMode, delay );
+ NTSC_SetVideoMode(g_uVideoMode, delay);
return MemReadFloatingBus(uExecutedCycles);
}
@@ -754,16 +790,18 @@ const char* Video::VideoGetAppWindowTitle(void)
return apVideoMonitorModeDesc[ GetVideoRefreshRate() == VR_60HZ ? 0 : 1 ]; // NTSC or PAL
}
-
-void Video::Initialize(uint8_t* frameBuffer)
+void Video::Initialize(uint8_t* frameBuffer, bool resetState)
{
SetFrameBuffer(frameBuffer);
- // RESET THE VIDEO MODE SWITCHES AND THE CHARACTER SET OFFSET
- VideoResetState();
+ if (resetState)
+ {
+ // RESET THE VIDEO MODE SWITCHES AND THE CHARACTER SET OFFSET
+ VideoResetState();
+ }
// DRAW THE SOURCE IMAGE INTO THE SOURCE BIT BUFFER
- memset(GetFrameBuffer(), 0, GetFrameBufferWidth() * GetFrameBufferHeight() * sizeof(bgra_t));
+ ClearFrameBuffer();
// CREATE THE OFFSET TABLE FOR EACH SCAN LINE IN THE FRAME BUFFER
NTSC_VideoInit(GetFrameBuffer());
@@ -796,3 +834,16 @@ void Video::VideoRefreshBuffer(uint32_t uRedrawWholeScreenVideoMode, bool bRedra
NTSC_VideoRedrawWholeScreen();
}
}
+
+void Video::ClearFrameBuffer(void)
+{
+ UINT32* frameBuffer = (UINT32*)GetFrameBuffer();
+ std::fill(frameBuffer, frameBuffer + GetFrameBufferWidth() * GetFrameBufferHeight(), OPAQUE_BLACK);
+}
+
+// Called when entering debugger, and after viewing Apple II video screen from debugger
+void Video::ClearSHRResidue(void)
+{
+ ClearFrameBuffer();
+ GetFrame().VideoPresentScreen();
+}
diff --git a/source/Video.h b/source/Video.h
index acde39156..e28da3a31 100644
--- a/source/Video.h
+++ b/source/Video.h
@@ -55,7 +55,8 @@ enum VideoFlag_e
VF_80STORE= 0x00000008,
VF_MIXED = 0x00000010,
VF_PAGE2 = 0x00000020,
- VF_TEXT = 0x00000040
+ VF_TEXT = 0x00000040,
+ VF_SHR = 0x00000080 // For VidHD's support for IIgs SHR video modes
};
enum AppleFont_e
@@ -193,9 +194,12 @@ class Video
g_nMonochromeRGB = RGB(0xC0,0xC0,0xC0);
g_videoRomSize = 0;
g_videoRomRockerSwitch = false;
+ m_hasVidHD = false;
}
- void Initialize(uint8_t* frameBuffer); // Do not call directly. Call FrameBase::Initialize()
+ ~Video(void){}
+
+ void Initialize(uint8_t* frameBuffer, bool resetState); // Do not call directly. Call FrameBase::Initialize()
void Destroy(void); // Call FrameBase::Destroy()
uint8_t* GetFrameBuffer(void) { return g_pFramebufferbits; }
@@ -207,6 +211,9 @@ class Video
UINT GetFrameBufferBorderHeight(void);
UINT GetFrameBufferWidth(void);
UINT GetFrameBufferHeight(void);
+ UINT GetFrameBufferCentringOffsetX(void);
+ UINT GetFrameBufferCentringOffsetY(void);
+ int GetFrameBufferCentringValue(void);
COLORREF GetMonochromeRGB(void) { return g_nMonochromeRGB; }
void SetMonochromeRGB(COLORREF colorRef) { g_nMonochromeRGB = colorRef; }
@@ -214,6 +221,8 @@ class Video
void VideoReinitialize(bool bInitVideoScannerAddress);
void VideoResetState(void);
void VideoRefreshBuffer(uint32_t uRedrawWholeScreenVideoMode, bool bRedrawWholeScreen);
+ void ClearFrameBuffer(void);
+ void ClearSHRResidue(void);
enum VideoScanner_e {VS_FullAddr, VS_PartialAddrV, VS_PartialAddrH};
WORD VideoGetScannerAddress(DWORD nCycles, VideoScanner_e videoScannerAddr = VS_FullAddr);
@@ -268,6 +277,9 @@ class Video
const char* VideoGetAppWindowTitle(void);
const char* GetVideoChoices(void) { return g_aVideoChoices; }
+ bool HasVidHD(void) { return m_hasVidHD; }
+ void SetVidHD(bool hasVidHD) { m_hasVidHD = hasVidHD; }
+
static const UINT kVideoRomSize2K = 1024*2;
static const UINT kVideoRomSize4K = kVideoRomSize2K*2;
@@ -275,7 +287,6 @@ class Video
uint8_t *g_pFramebufferbits;
private:
-
void SetFrameBuffer(uint8_t* frameBuffer) { g_pFramebufferbits = frameBuffer; }
std::string VideoGetSnapshotStructName(void);
@@ -285,6 +296,7 @@ class Video
VideoStyle_e g_eVideoStyle;
bool g_bVideoScannerNTSC; // NTSC video scanning (or PAL)
COLORREF g_nMonochromeRGB; // saved to Registry
+ bool m_hasVidHD;
WinBmpHeader_t g_tBmpHeader;
@@ -309,4 +321,10 @@ class Video
static const char m_szModeDesc7[];
static const char m_szModeDesc8[];
static const char* const g_apVideoModeDesc[NUM_VIDEO_MODES];
+
+ static const UINT kVideoHeightII = 192*2;
+ static const UINT kVideoHeightIIgs = 200*2;
+
+ static const UINT kVideoWidthII = 280*2;
+ static const UINT kVideoWidthIIgs = 320*2;
};
diff --git a/source/Windows/AppleWin.cpp b/source/Windows/AppleWin.cpp
index ccc9f913b..65f683fdb 100644
--- a/source/Windows/AppleWin.cpp
+++ b/source/Windows/AppleWin.cpp
@@ -667,6 +667,7 @@ static void OneTimeInitialization(HINSTANCE passinstance)
// DO INITIALIZATION THAT MUST BE REPEATED FOR A RESTART
static void RepeatInitialization(void)
{
+ GetVideo().SetVidHD(false); // Set true later only if VidHDCard is instantiated
ResetToLogoMode();
// NB. g_OldAppleWinVersion needed by LoadConfiguration() -> Config_Load_Video()
@@ -731,13 +732,6 @@ static void RepeatInitialization(void)
JoyInitialize();
LogFileOutput("Main: JoyInitialize()\n");
- GetFrame().Initialize(); // g_pFramebufferinfo been created now & COM init'ed
- LogFileOutput("Main: VideoInitialize()\n");
-
- LogFileOutput("Main: FrameCreateWindow() - pre\n");
- Win32Frame::GetWin32Frame().FrameCreateWindow(); // GetFrame().g_hFrameWindow is now valid
- LogFileOutput("Main: FrameCreateWindow() - post\n");
-
// Init palette color
VideoSwitchVideocardPalette(RGB_GetVideocard(), GetVideo().GetVideoType());
@@ -753,6 +747,11 @@ static void RepeatInitialization(void)
if (g_cmdLine.bSlotEmpty[SLOT6])
GetCardMgr().Remove(SLOT6);
+ if (g_cmdLine.slotInsert[SLOT3] != CT_Empty && g_cmdLine.slotInsert[SLOT3] == CT_VidHD) // For now just support VidHD in slot 3
+ {
+ GetCardMgr().Insert(SLOT3, g_cmdLine.slotInsert[SLOT3]);
+ }
+
if (g_cmdLine.slotInsert[SLOT5] != CT_Empty)
{
if (GetCardMgr().QuerySlot(SLOT4) == CT_MockingboardC && g_cmdLine.slotInsert[SLOT5] != CT_MockingboardC) // Currently MB occupies slot4+5 when enabled
@@ -764,6 +763,35 @@ static void RepeatInitialization(void)
GetCardMgr().Insert(SLOT5, g_cmdLine.slotInsert[SLOT5]);
}
+ // Create window after inserting/removing VidHD card (as it affects width & height)
+ {
+ Win32Frame::GetWin32Frame().SetViewportScale(Win32Frame::GetWin32Frame().GetViewportScale(), true);
+
+ GetFrame().Initialize(true); // g_pFramebufferinfo been created now & COM init'ed
+ LogFileOutput("Main: VideoInitialize()\n");
+
+ LogFileOutput("Main: FrameCreateWindow() - pre\n");
+ Win32Frame::GetWin32Frame().FrameCreateWindow(); // GetFrame().g_hFrameWindow is now valid
+ LogFileOutput("Main: FrameCreateWindow() - post\n");
+ }
+
+ // Set best W,H resolution after inserting/removing VidHD card
+ if (g_cmdLine.bestFullScreenResolution || g_cmdLine.userSpecifiedWidth || g_cmdLine.userSpecifiedHeight)
+ {
+ bool res = false;
+ UINT bestWidth = 0, bestHeight = 0;
+
+ if (g_cmdLine.bestFullScreenResolution)
+ res = GetFrame().GetBestDisplayResolutionForFullScreen(bestWidth, bestHeight);
+ else
+ res = GetFrame().GetBestDisplayResolutionForFullScreen(bestWidth, bestHeight, g_cmdLine.userSpecifiedWidth, g_cmdLine.userSpecifiedHeight);
+
+ if (res)
+ LogFileOutput("Best resolution for -fs-height/height=x switch(es): Width=%d, Height=%d\n", bestWidth, bestHeight);
+ else
+ LogFileOutput("Failed to set parameter for -fs-width/height=x switch(es)\n");
+ }
+
// Pre: may need g_hFrameWindow for MessageBox errors
// Post: may enable HDD, required for MemInitialize()->MemInitializeIO()
{
diff --git a/source/Windows/Win32Frame.cpp b/source/Windows/Win32Frame.cpp
index f78ce3322..06beb8f0b 100644
--- a/source/Windows/Win32Frame.cpp
+++ b/source/Windows/Win32Frame.cpp
@@ -33,16 +33,12 @@ Win32Frame::Win32Frame()
g_bFrameActive = false;
g_windowMinimized = false;
g_bFullScreen_ShowSubunitStatus = true;
- g_win_fullscreen_scale = 1;
g_win_fullscreen_offsetx = 0;
g_win_fullscreen_offsety = 0;
m_bestWidthForFullScreen = 0;
m_bestHeightForFullScreen = 0;
m_changedDisplaySettings = false;
- g_nViewportCX = GetVideo().GetFrameBufferBorderlessWidth() * kDEFAULT_VIEWPORT_SCALE;
- g_nViewportCY = GetVideo().GetFrameBufferBorderlessHeight() * kDEFAULT_VIEWPORT_SCALE;
- g_nViewportScale = kDEFAULT_VIEWPORT_SCALE; // saved REGSAVE
g_nMaxViewportScale = kDEFAULT_VIEWPORT_SCALE; // Max scale in Windowed mode with borders, buttons etc (full-screen may be +1)
btnfacebrush = (HBRUSH)0;
@@ -52,8 +48,6 @@ Win32Frame::Win32Frame()
buttonactive = -1;
buttondown = -1;
buttonover = -1;
- buttonx = BUTTONX; // NB. macro uses g_nViewportCX
- buttony = BUTTONY;
g_hFrameDC = (HDC)0;
memset(&framerect, 0, sizeof(framerect));
@@ -76,9 +70,12 @@ Win32Frame::Win32Frame()
g_eStatusDrive1 = DISK_STATUS_OFF;
g_eStatusDrive2 = DISK_STATUS_OFF;
+
+ // Set g_nViewportScale, g_nViewportCX, g_nViewportCY & buttonx, buttony
+ SetViewportScale(kDEFAULT_VIEWPORT_SCALE, true);
}
-void Win32Frame::videoCreateDIBSection(Video & video)
+void Win32Frame::VideoCreateDIBSection(bool resetVideoState)
{
// CREATE THE DEVICE CONTEXT
HWND window = GetDesktopWindow();
@@ -91,7 +88,10 @@ void Win32Frame::videoCreateDIBSection(Video & video)
// CREATE THE FRAME BUFFER DIB SECTION
if (g_hDeviceBitmap)
+ {
DeleteObject(g_hDeviceBitmap);
+ GetVideo().Destroy();
+ }
uint8_t* pFramebufferbits;
@@ -102,29 +102,33 @@ void Win32Frame::videoCreateDIBSection(Video & video)
(LPVOID*)&pFramebufferbits, 0, 0
);
SelectObject(g_hDeviceDC, g_hDeviceBitmap);
- video.Initialize(pFramebufferbits);
+ GetVideo().Initialize(pFramebufferbits, resetVideoState);
}
-void Win32Frame::Initialize(void)
+void Win32Frame::Initialize(bool resetVideoState)
{
- // LOAD THE LOGO
- g_hLogoBitmap = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_APPLEWIN));
+ if (g_hLogoBitmap == NULL)
+ {
+ // LOAD THE LOGO
+ g_hLogoBitmap = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_APPLEWIN));
+ }
+
+ if (g_pFramebufferinfo)
+ delete[] g_pFramebufferinfo;
// CREATE A BITMAPINFO STRUCTURE FOR THE FRAME BUFFER
g_pFramebufferinfo = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
- Video & video = GetVideo();
-
memset(g_pFramebufferinfo, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
g_pFramebufferinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- g_pFramebufferinfo->bmiHeader.biWidth = video.GetFrameBufferWidth();
- g_pFramebufferinfo->bmiHeader.biHeight = video.GetFrameBufferHeight();
+ g_pFramebufferinfo->bmiHeader.biWidth = GetVideo().GetFrameBufferWidth();
+ g_pFramebufferinfo->bmiHeader.biHeight = GetVideo().GetFrameBufferHeight();
g_pFramebufferinfo->bmiHeader.biPlanes = 1;
g_pFramebufferinfo->bmiHeader.biBitCount = 32;
g_pFramebufferinfo->bmiHeader.biCompression = BI_RGB;
g_pFramebufferinfo->bmiHeader.biClrUsed = 0;
- videoCreateDIBSection(video);
+ VideoCreateDIBSection(resetVideoState);
#if 0
DDInit(); // For WaitForVerticalBlank()
diff --git a/source/Windows/Win32Frame.h b/source/Windows/Win32Frame.h
index cbce057ed..75fd89265 100644
--- a/source/Windows/Win32Frame.h
+++ b/source/Windows/Win32Frame.h
@@ -25,7 +25,8 @@ class Video;
class Win32Frame : public FrameBase
{
public:
- Win32Frame();
+ Win32Frame(void);
+ virtual ~Win32Frame(void){}
static Win32Frame& GetWin32Frame();
static LRESULT CALLBACK FrameWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
@@ -38,15 +39,16 @@ class Win32Frame : public FrameBase
virtual void FrameSetCursorPosByMousePos();
virtual void SetFullScreenShowSubunitStatus(bool bShow);
- virtual bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedHeight = 0);
+ virtual bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedWidth=0, UINT userSpecifiedHeight=0);
virtual int SetViewportScale(int nNewScale, bool bForce = false);
virtual void SetAltEnterToggleFullScreen(bool mode);
virtual void SetLoadedSaveStateFlag(const bool bFlag);
- virtual void Initialize(void);
+ virtual void Initialize(bool resetVideoState);
virtual void Destroy(void);
virtual void VideoPresentScreen(void);
+ virtual void ResizeWindow(void);
virtual int FrameMessageBox(LPCSTR lpText, LPCSTR lpCaption, UINT uType);
virtual void GetBitmap(LPCSTR lpBitmapName, LONG cb, LPVOID lpvBits);
@@ -64,6 +66,7 @@ class Win32Frame : public FrameBase
UINT Get3DBorderHeight(void);
int GetViewportScale(void);
void GetViewportCXCY(int& nViewportCX, int& nViewportCY);
+ void SetFullScreenViewportScale(int nNewXScale, int nNewYScale);
void ApplyVideoModeChange(void);
@@ -76,7 +79,7 @@ class Win32Frame : public FrameBase
static BOOL CALLBACK DDEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext);
LRESULT WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
- void videoCreateDIBSection(Video& video);
+ void VideoCreateDIBSection(bool resetVideoState);
void VideoDrawLogoBitmap(HDC hDstDC, int xoff, int yoff, int srcw, int srch, int scale);
bool DDInit(void);
void DDUninit(void);
@@ -129,7 +132,6 @@ class Win32Frame : public FrameBase
bool g_windowMinimized;
std::string driveTooltip;
bool g_bFullScreen_ShowSubunitStatus;
- FULLSCREEN_SCALE_TYPE g_win_fullscreen_scale;
int g_win_fullscreen_offsetx;
int g_win_fullscreen_offsety;
UINT m_bestWidthForFullScreen;
diff --git a/source/Windows/WinFrame.cpp b/source/Windows/WinFrame.cpp
index 8c3c2a40a..e78abbea7 100644
--- a/source/Windows/WinFrame.cpp
+++ b/source/Windows/WinFrame.cpp
@@ -463,11 +463,20 @@ void Win32Frame::DrawFrameWindow (bool bPaintingWindow/*=false*/)
DrawButton(dc,iButton);
}
- if (g_nViewportScale == 2)
+ if (g_nViewportScale == 2 || GetVideo().HasVidHD())
{
- int x = buttonx + 1;
- int y = buttony + BUTTONS*BUTTONCY + 36; // 36 = height of StatusArea
- RECT rect = {x, y, x+45, y+BUTTONS*BUTTONCY+22};
+ const int x = buttonx + 1;
+ const int y = buttony + BUTTONS * BUTTONCY + 36; // 36 = height of StatusArea
+ RECT rect = { x, y, x + BUTTONCX, y + BUTTONS * BUTTONCY + 22 };
+
+ if (GetVideo().HasVidHD())
+ {
+ if (g_nViewportScale == 1)
+ rect.bottom += 14;
+ else
+ rect.bottom += 32;
+ }
+
int res = FillRect(dc, &rect, btnfacebrush);
}
}
@@ -1933,6 +1942,7 @@ void Win32Frame::ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
}
else // MODE_RUNNING, MODE_LOGO, MODE_PAUSED
{
+ GetVideo().ClearSHRResidue(); // Clear the framebuffer to remove any SHR residue in the borders
DebugBegin();
}
break;
@@ -2149,13 +2159,14 @@ void Win32Frame::SetFullScreenMode(void)
scalex = width / GetVideo().GetFrameBufferBorderlessWidth();
scaley = height / GetVideo().GetFrameBufferBorderlessHeight();
- g_win_fullscreen_scale = (scalex <= scaley) ? scalex : scaley;
- g_win_fullscreen_offsetx = ((int)width - (int)(g_win_fullscreen_scale * GetVideo().GetFrameBufferBorderlessWidth())) / 2;
- g_win_fullscreen_offsety = ((int)height - (int)(g_win_fullscreen_scale * GetVideo().GetFrameBufferBorderlessHeight())) / 2;
+ // NB. Separate x,y scaling is OK in full-screen mode
+ // . eg. SHR 640x400 (scalex=2, scaley=3) => 1280x1200, which roughly gives a 4:3 aspect ratio for a resolution of 1600x1200
+ g_win_fullscreen_offsetx = ((int)width - (int)(scalex * GetVideo().GetFrameBufferBorderlessWidth())) / 2;
+ g_win_fullscreen_offsety = ((int)height - (int)(scaley * GetVideo().GetFrameBufferBorderlessHeight())) / 2;
SetWindowPos(g_hFrameWindow, NULL, left, top, (int)width, (int)height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
g_bIsFullScreen = true;
- SetViewportScale(g_win_fullscreen_scale, true);
+ SetFullScreenViewportScale(scalex, scaley);
buttonx = GetFullScreenOffsetX() + g_nViewportCX + VIEWPORTX*2;
buttony = GetFullScreenOffsetY();
@@ -2187,7 +2198,6 @@ void Win32Frame::SetNormalMode(void)
g_win_fullscreen_offsetx = 0;
g_win_fullscreen_offsety = 0;
- g_win_fullscreen_scale = 1;
SetWindowLong(g_hFrameWindow, GWL_STYLE, g_main_window_saved_style);
SetWindowLong(g_hFrameWindow, GWL_EXSTYLE, g_main_window_saved_exstyle);
SetWindowPos(g_hFrameWindow, NULL,
@@ -2249,9 +2259,22 @@ int Win32Frame::SetViewportScale(int nNewScale, bool bForce /*=false*/)
g_nViewportCX = g_nViewportScale * GetVideo().GetFrameBufferBorderlessWidth();
g_nViewportCY = g_nViewportScale * GetVideo().GetFrameBufferBorderlessHeight();
+ buttonx = BUTTONX; // NB. macro uses g_nViewportCX
+ buttony = BUTTONY;
+
return nNewScale;
}
+void Win32Frame::SetFullScreenViewportScale(int nNewXScale, int nNewYScale)
+{
+ g_nViewportScale = MIN(nNewXScale, nNewYScale); // Not needed in FS mode
+ g_nViewportCX = nNewXScale * GetVideo().GetFrameBufferBorderlessWidth();
+ g_nViewportCY = nNewYScale * GetVideo().GetFrameBufferBorderlessHeight();
+
+ buttonx = BUTTONX; // NB. macro uses g_nViewportCX
+ buttony = BUTTONY;
+}
+
void Win32Frame::SetupTooltipControls(void)
{
TOOLINFO toolinfo;
@@ -2303,6 +2326,12 @@ void Win32Frame::GetWidthHeight(int& nWidth, int& nHeight)
#endif
}
+// Window frame's border size has changed (eg. VidHD added/removed)
+void Win32Frame::ResizeWindow(void)
+{
+ FrameResizeWindow(GetViewportScale());
+}
+
void Win32Frame::FrameResizeWindow(int nNewScale)
{
int nOldWidth, nOldHeight;
@@ -2314,11 +2343,6 @@ void Win32Frame::FrameResizeWindow(int nNewScale)
int nXPos = framerect.left;
int nYPos = framerect.top;
- //
-
- buttonx = g_nViewportCX + VIEWPORTX*2;
- buttony = 0;
-
// Invalidate old rect region
{
RECT irect;
@@ -2697,7 +2721,7 @@ void Win32Frame::FrameUpdateApple2Type(void)
DrawFrameWindow();
}
-bool Win32Frame::GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedHeight /*= 0*/)
+bool Win32Frame::GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedWidth/*=0*/, UINT userSpecifiedHeight/*=0*/)
{
m_bestWidthForFullScreen = 0;
m_bestHeightForFullScreen = 0;
@@ -2734,10 +2758,17 @@ bool Win32Frame::GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& be
if (vecDisplayResolutions.size() == 0)
return false;
- // Pick least width (such that it's wide enough to scale)
+ // Pick user-specific width if it exists
+ // Else pick least width (such that it's wide enough to scale)
UINT width = (UINT)-1;
for (VEC_PAIR::iterator it = vecDisplayResolutions.begin(); it!= vecDisplayResolutions.end(); ++it)
{
+ if (it->first == userSpecifiedWidth)
+ {
+ width = userSpecifiedWidth;
+ break;
+ }
+
if (width > it->first)
{
UINT scaleFactor = it->second / GetVideo().GetFrameBufferBorderlessHeight();
diff --git a/source/frontends/common2/commonframe.cpp b/source/frontends/common2/commonframe.cpp
index 3917a7246..94e42ceec 100644
--- a/source/frontends/common2/commonframe.cpp
+++ b/source/frontends/common2/commonframe.cpp
@@ -2,6 +2,7 @@
#include "frontends/common2/commonframe.h"
#include "frontends/common2/utils.h"
#include "linux/resources.h"
+#include "linux/context.h"
#include
#include
@@ -77,25 +78,6 @@ namespace common2
g_sProgramDir = getResourcePath("/bin/");
}
- void CommonFrame::Initialize()
- {
- InitialiseEmulator();
- LinuxFrame::Initialize();
- }
-
- void CommonFrame::Destroy()
- {
- LinuxFrame::Destroy();
- myResource.clear();
- DestroyEmulator();
- }
-
- void CommonFrame::Restart()
- {
- Destroy();
- Initialize();
- }
-
BYTE* CommonFrame::GetResource(WORD id, LPCSTR lpType, DWORD expectedSize)
{
myResource.clear();
diff --git a/source/frontends/common2/commonframe.h b/source/frontends/common2/commonframe.h
index 102391df7..44a0f785f 100644
--- a/source/frontends/common2/commonframe.h
+++ b/source/frontends/common2/commonframe.h
@@ -12,10 +12,6 @@ namespace common2
public:
CommonFrame();
- void Initialize() override;
- void Destroy() override;
- void Restart() override;
-
BYTE* GetResource(WORD id, LPCSTR lpType, DWORD expectedSize) override;
protected:
diff --git a/source/frontends/common2/utils.cpp b/source/frontends/common2/utils.cpp
index 7c7d62c4b..2f2fc7f91 100644
--- a/source/frontends/common2/utils.cpp
+++ b/source/frontends/common2/utils.cpp
@@ -1,35 +1,8 @@
#include "StdAfx.h"
-#include "frontends/common2/utils.h"
#include "frontends/common2/programoptions.h"
-#include "linux/network/uthernet2.h"
-
-#include "SaveState.h"
-
-#include "Common.h"
-#include "CardManager.h"
-#include "Core.h"
-#include "Disk.h"
-#include "Mockingboard.h"
-#include "SoundCore.h"
-#include "Harddisk.h"
-#include "Speaker.h"
-#include "Log.h"
-#include "CPU.h"
-#include "Memory.h"
-#include "LanguageCard.h"
-#include "MouseInterface.h"
-#include "ParallelPrinter.h"
-#include "Video.h"
-#include "NTSC.h"
#include "SaveState.h"
-#include "RGBMonitor.h"
-#include "Riff.h"
#include "Registry.h"
-#include "Utilities.h"
-#include "Interface.h"
-#include "Debugger/Debug.h"
-#include "Tfe/tfe.h"
#include
#include
@@ -62,90 +35,6 @@ namespace common2
}
}
- void LoadUthernet2()
- {
- CardManager & cardManager = GetCardMgr();
- for (UINT slot = SLOT1; slot < NUM_SLOTS; slot++)
- {
- if (cardManager.QuerySlot(slot) == CT_Uthernet2)
- {
- // AppleWin does not know anything about this
- registerUthernet2(slot);
- break;
- }
- }
- }
-
- void InitialiseEmulator()
- {
-#ifdef RIFF_SPKR
- RiffInitWriteFile("/tmp/Spkr.wav", SPKR_SAMPLE_RATE, 1);
-#endif
-#ifdef RIFF_MB
- RiffInitWriteFile("/tmp/Mockingboard.wav", 44100, 2);
-#endif
-
- g_nAppMode = MODE_RUNNING;
- LogFileOutput("Initialisation\n");
-
- g_bFullSpeed = false;
-
- LoadConfiguration();
- LoadUthernet2();
- SetCurrentCLK6502();
- GetAppleWindowTitle();
- GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES | DRAW_DISK_STATUS);
-
- DSInit();
- MB_Initialize();
- SpkrInitialize();
-
- MemInitialize();
-
- CardManager & cardManager = GetCardMgr();
- cardManager.GetDisk2CardMgr().Reset();
- if (cardManager.QuerySlot(SLOT7) == CT_GenericHDD)
- {
- dynamic_cast(cardManager.GetRef(SLOT7)).Reset(true);
- }
-
- Snapshot_Startup();
-
- DebugInitialize();
- }
-
- void DestroyEmulator()
- {
- CardManager & cardManager = GetCardMgr();
-
- Snapshot_Shutdown();
- CMouseInterface* pMouseCard = cardManager.GetMouseCard();
- if (pMouseCard)
- {
- pMouseCard->Reset();
- }
- MemDestroy();
-
- SpkrDestroy();
- MB_Destroy();
- DSUninit();
-
- unRegisterUthernet2();
- tfe_shutdown();
-
- if (cardManager.QuerySlot(SLOT7) == CT_GenericHDD)
- {
- dynamic_cast(cardManager.GetRef(SLOT7)).Destroy();
- }
-
- PrintDestroy();
- CpuDestroy();
- DebugDestroy();
-
- GetCardMgr().GetDisk2CardMgr().Destroy();
- RiffFinishWriteFile();
- }
-
void loadGeometryFromRegistry(const std::string §ion, Geometry & geometry)
{
if (geometry.empty) // otherwise it was user provided
diff --git a/source/frontends/common2/utils.h b/source/frontends/common2/utils.h
index 5986d9d9d..40b840940 100644
--- a/source/frontends/common2/utils.h
+++ b/source/frontends/common2/utils.h
@@ -8,10 +8,6 @@ namespace common2
void setSnapshotFilename(const std::string & filename, const bool load);
- // Do not call directly. Used in CommonFrame
- void InitialiseEmulator();
- void DestroyEmulator();
-
void loadGeometryFromRegistry(const std::string §ion, Geometry & geometry);
void saveGeometryToRegistry(const std::string §ion, const Geometry & geometry);
}
diff --git a/source/frontends/libretro/game.cpp b/source/frontends/libretro/game.cpp
index a5fc8445b..bff837b95 100644
--- a/source/frontends/libretro/game.cpp
+++ b/source/frontends/libretro/game.cpp
@@ -36,7 +36,7 @@ namespace ra2
myFrame.reset(new ra2::RetroFrame());
SetFrame(myFrame);
- myFrame->Initialize();
+ myFrame->Begin();
Video & video = GetVideo();
// should the user be allowed to tweak 0.75
@@ -46,7 +46,7 @@ namespace ra2
Game::~Game()
{
- myFrame->Destroy();
+ myFrame->End();
myFrame.reset();
SetFrame(myFrame);
}
diff --git a/source/frontends/libretro/retroframe.cpp b/source/frontends/libretro/retroframe.cpp
index 3b857387a..9c9c4c3c2 100644
--- a/source/frontends/libretro/retroframe.cpp
+++ b/source/frontends/libretro/retroframe.cpp
@@ -106,9 +106,9 @@ namespace ra2
video_cb(myVideoBuffer.data() + myOffset, myBorderlessWidth, myBorderlessHeight, myPitch);
}
- void RetroFrame::Initialize()
+ void RetroFrame::Initialize(bool resetVideoState)
{
- CommonFrame::Initialize();
+ CommonFrame::Initialize(resetVideoState);
FrameRefreshStatus(DRAW_TITLE);
Video & video = GetVideo();
diff --git a/source/frontends/libretro/retroframe.h b/source/frontends/libretro/retroframe.h
index 376dd34b0..7df2f3a81 100644
--- a/source/frontends/libretro/retroframe.h
+++ b/source/frontends/libretro/retroframe.h
@@ -15,7 +15,7 @@ namespace ra2
void VideoPresentScreen() override;
void FrameRefreshStatus(int drawflags) override;
- void Initialize() override;
+ void Initialize(bool resetVideoState) override;
void Destroy() override;
int FrameMessageBox(LPCSTR lpText, LPCSTR lpCaption, UINT uType) override;
void GetBitmap(LPCSTR lpBitmapName, LONG cb, LPVOID lpvBits) override;
diff --git a/source/frontends/ncurses/main.cpp b/source/frontends/ncurses/main.cpp
index 56e078e1d..51b0b6774 100644
--- a/source/frontends/ncurses/main.cpp
+++ b/source/frontends/ncurses/main.cpp
@@ -152,7 +152,7 @@ namespace
const Initialisation init(frame, paddle);
applyOptions(options);
- frame->Initialize();
+ frame->Begin();
na2::SetCtrlCHandler(options.headless);
@@ -165,6 +165,7 @@ namespace
{
EnterMessageLoop(options, frame);
}
+ frame->End();
return 0;
}
diff --git a/source/frontends/ncurses/nframe.cpp b/source/frontends/ncurses/nframe.cpp
index c2231a9f9..b7417b2a8 100644
--- a/source/frontends/ncurses/nframe.cpp
+++ b/source/frontends/ncurses/nframe.cpp
@@ -47,9 +47,9 @@ namespace na2
// so we can run headless
}
- void NFrame::Initialize()
+ void NFrame::Initialize(bool resetVideoState)
{
- CommonFrame::Initialize();
+ CommonFrame::Initialize(resetVideoState);
myTextFlashCounter = 0;
myTextFlashState = 0;
myAsciiArt.reset(new ASCIIArt());
diff --git a/source/frontends/ncurses/nframe.h b/source/frontends/ncurses/nframe.h
index fdfb912cb..533fd3078 100644
--- a/source/frontends/ncurses/nframe.h
+++ b/source/frontends/ncurses/nframe.h
@@ -21,7 +21,7 @@ namespace na2
WINDOW * GetWindow();
WINDOW * GetStatus();
- void Initialize() override;
+ void Initialize(bool resetVideoState) override;
void Destroy() override;
void VideoPresentScreen() override;
int FrameMessageBox(LPCSTR lpText, LPCSTR lpCaption, UINT uType) override;
diff --git a/source/frontends/qt/qapple.cpp b/source/frontends/qt/qapple.cpp
index 557e00ace..9de150572 100644
--- a/source/frontends/qt/qapple.cpp
+++ b/source/frontends/qt/qapple.cpp
@@ -10,19 +10,13 @@
#include "Harddisk.h"
#include "Log.h"
#include "CPU.h"
-#include "Memory.h"
#include "LanguageCard.h"
-#include "Mockingboard.h"
-#include "MouseInterface.h"
-#include "ParallelPrinter.h"
#include "Video.h"
-#include "SoundCore.h"
#include "NTSC.h"
#include "SaveState.h"
#include "Speaker.h"
#include "Riff.h"
#include "RGBMonitor.h"
-#include "Utilities.h"
#include "linux/benchmark.h"
#include "linux/version.h"
@@ -76,72 +70,6 @@ namespace
*
*/
- void loadEmulator(const std::shared_ptr & frame, const GlobalOptions & options)
- {
- LoadConfiguration();
-
- // ResetDefaultMachineMemTypes();
-
- switch (options.slot0Card) {
- case 1: // Language Card
- SetExpansionMemType(CT_LanguageCard);
- break;
- case 2: // Saturn 64
- SetSaturnMemorySize(Saturn128K::kMaxSaturnBanks / 2);
- SetExpansionMemType(CT_Saturn128K);
- break;
- case 3: // Saturn 128
- SetSaturnMemorySize(Saturn128K::kMaxSaturnBanks);
- SetExpansionMemType(CT_Saturn128K);
- break;
- case 4: // RamWorks
- SetRamWorksMemorySize(options.ramWorksMemorySize);
- SetExpansionMemType(CT_RamWorksIII);
- break;
- }
-
- DSInit();
- MB_Initialize();
- SpkrInitialize();
- MemInitialize();
- frame->Initialize();
-
- CardManager & cardManager = GetCardMgr();
- cardManager.GetDisk2CardMgr().Reset();
- if (cardManager.QuerySlot(SLOT7) == CT_GenericHDD)
- {
- dynamic_cast(cardManager.GetRef(SLOT7)).Reset(true);
- }
- }
-
- void unloadEmulator(const std::shared_ptr & frame)
- {
- CardManager & cardManager = GetCardMgr();
-
- CMouseInterface* pMouseCard = cardManager.GetMouseCard();
- if (pMouseCard)
- {
- pMouseCard->Reset();
- }
- if (cardManager.QuerySlot(SLOT7) == CT_GenericHDD)
- {
- dynamic_cast(cardManager.GetRef(SLOT7)).Destroy();
- }
- PrintDestroy();
- MemDestroy();
- SpkrDestroy();
- frame->Destroy();
- MB_Destroy();
- DSUninit();
- CpuDestroy();
-
- cardManager.GetDisk2CardMgr().Destroy();
- LogDone();
- RiffFinishWriteFile();
-
- QDirectSound::stop();
- }
-
qint64 emulatorTimeInMS()
{
const double timeInSeconds = g_nCumulativeCycles / g_fCurrentCLK6502;
@@ -206,7 +134,7 @@ QApple::QApple(QWidget *parent) :
on_actionPause_triggered();
initialiseEmulator();
- loadEmulator(myFrame, myOptions);
+ myFrame->Begin();
setAcceptDrops(true);
}
@@ -219,7 +147,8 @@ QApple::~QApple()
void QApple::closeEvent(QCloseEvent * event)
{
stopTimer();
- unloadEmulator(myFrame);
+ myFrame->End();
+ QDirectSound::stop();
QSettings settings;
settings.setValue("QApple/window/geometry", saveGeometry().toBase64());
@@ -367,8 +296,7 @@ void QApple::on_actionReboot_triggered()
emit endEmulator();
mySaveStateLabel->clear();
- unloadEmulator(myFrame);
- loadEmulator(myFrame, myOptions);
+ myFrame->Restart();
myFrame->VideoPresentScreen();
}
diff --git a/source/frontends/qt/qtframe.cpp b/source/frontends/qt/qtframe.cpp
index 305de1b9c..f6d8fec86 100644
--- a/source/frontends/qt/qtframe.cpp
+++ b/source/frontends/qt/qtframe.cpp
@@ -36,9 +36,9 @@ void QtFrame::FrameRefreshStatus(int drawflags)
}
}
-void QtFrame::Initialize()
+void QtFrame::Initialize(bool resetVideoState)
{
- LinuxFrame::Initialize();
+ LinuxFrame::Initialize(resetVideoState);
FrameRefreshStatus(DRAW_TITLE);
myEmulator->loadVideoSettings();
myEmulator->displayLogo();
diff --git a/source/frontends/qt/qtframe.h b/source/frontends/qt/qtframe.h
index d0c5cf1a7..2a0aa163b 100644
--- a/source/frontends/qt/qtframe.h
+++ b/source/frontends/qt/qtframe.h
@@ -16,7 +16,7 @@ class QtFrame : public LinuxFrame
void VideoPresentScreen() override;
void FrameRefreshStatus(int drawflags) override;
- void Initialize() override;
+ void Initialize(bool resetVideoState) override;
void Destroy() override;
int FrameMessageBox(LPCSTR lpText, LPCSTR lpCaption, UINT uType) override;
diff --git a/source/frontends/sdl/imgui/sdlimguiframe.cpp b/source/frontends/sdl/imgui/sdlimguiframe.cpp
index d0462ab2a..ec0827a52 100644
--- a/source/frontends/sdl/imgui/sdlimguiframe.cpp
+++ b/source/frontends/sdl/imgui/sdlimguiframe.cpp
@@ -96,9 +96,25 @@ namespace sa2
ImGui::StyleColorsDark();
ImGui_ImplSDL2_InitForOpenGL(myWindow.get(), myGLContext);
-
ImGui_ImplOpenGL3_Init();
+ myDeadTopZone = 0;
+ myTexture = 0;
+ }
+
+ SDLImGuiFrame::~SDLImGuiFrame()
+ {
+ glDeleteTextures(1, &myTexture);
+ ImGui_ImplOpenGL3_Shutdown();
+ ImGui_ImplSDL2_Shutdown();
+ ImGui::DestroyContext();
+ SDL_GL_DeleteContext(myGLContext);
+ }
+
+ void SDLImGuiFrame::Initialize(bool resetVideoState)
+ {
+ SDLFrame::Initialize(resetVideoState);
+ glDeleteTextures(1, &myTexture);
glGenTextures(1, &myTexture);
Video & video = GetVideo();
@@ -114,17 +130,6 @@ namespace sa2
myOffset = (width * borderHeight + borderWidth) * sizeof(bgra_t);
allocateTexture(myTexture, myBorderlessWidth, myBorderlessHeight);
-
- myDeadTopZone = 0;
- }
-
- SDLImGuiFrame::~SDLImGuiFrame()
- {
- glDeleteTextures(1, &myTexture);
- ImGui_ImplOpenGL3_Shutdown();
- ImGui_ImplSDL2_Shutdown();
- ImGui::DestroyContext();
- SDL_GL_DeleteContext(myGLContext);
}
void SDLImGuiFrame::UpdateTexture()
diff --git a/source/frontends/sdl/imgui/sdlimguiframe.h b/source/frontends/sdl/imgui/sdlimguiframe.h
index b18472f59..41bc6a920 100644
--- a/source/frontends/sdl/imgui/sdlimguiframe.h
+++ b/source/frontends/sdl/imgui/sdlimguiframe.h
@@ -21,6 +21,7 @@ namespace sa2
void VideoPresentScreen() override;
void ResetSpeed() override;
+ void Initialize(bool resetVideoState) override;
protected:
diff --git a/source/frontends/sdl/imgui/sdlsettings.cpp b/source/frontends/sdl/imgui/sdlsettings.cpp
index 131ecefa9..824244648 100644
--- a/source/frontends/sdl/imgui/sdlsettings.cpp
+++ b/source/frontends/sdl/imgui/sdlsettings.cpp
@@ -306,7 +306,7 @@ namespace sa2
const bool isSelected = card == current;
if (ImGui::Selectable(getCardName(card).c_str(), isSelected))
{
- insertCard(slot, card);
+ insertCard(slot, card, frame);
}
if (isSelected)
{
@@ -330,7 +330,7 @@ namespace sa2
const bool isSelected = card == expansion;
if (ImGui::Selectable(getCardName(card).c_str(), isSelected))
{
- SetExpansionMemType(card);
+ setExpansionCard(card);
}
if (isSelected)
{
diff --git a/source/frontends/sdl/imgui/settingshelper.cpp b/source/frontends/sdl/imgui/settingshelper.cpp
index df42e7333..e6e688fd5 100644
--- a/source/frontends/sdl/imgui/settingshelper.cpp
+++ b/source/frontends/sdl/imgui/settingshelper.cpp
@@ -3,6 +3,8 @@
#include "Registry.h"
#include "Harddisk.h"
#include "Core.h"
+#include "Memory.h"
+#include "Interface.h"
#include "Debugger/Debug.h"
#include "Tfe/tfe.h"
@@ -16,60 +18,61 @@ namespace
{
const std::map cards =
{
- {CT_Empty, "CT_Empty"},
- {CT_Disk2, "CT_Disk2"},
- {CT_SSC, "CT_SSC"},
- {CT_MockingboardC, "CT_MockingboardC"},
- {CT_GenericPrinter, "CT_GenericPrinter"},
- {CT_GenericHDD, "CT_GenericHDD"},
- {CT_GenericClock, "CT_GenericClock"},
- {CT_MouseInterface, "CT_MouseInterface"},
- {CT_Z80, "CT_Z80"},
- {CT_Phasor, "CT_Phasor"},
- {CT_Echo, "CT_Echo"},
- {CT_SAM, "CT_SAM"},
- {CT_80Col, "CT_80Col"},
- {CT_Extended80Col, "CT_Extended80Col"},
- {CT_RamWorksIII, "CT_RamWorksIII"},
- {CT_Uthernet, "CT_Uthernet"},
- {CT_LanguageCard, "CT_LanguageCard"},
- {CT_LanguageCardIIe, "CT_LanguageCardIIe"},
- {CT_Saturn128K, "CT_Saturn128K"},
- {CT_FourPlay, "CT_FourPlay"},
- {CT_SNESMAX, "CT_SNESMAX"},
- {CT_Uthernet2, "CT_Uthernet2"},
+ {CT_Empty, "Empty"},
+ {CT_Disk2, "Disk2"},
+ {CT_SSC, "SSC"},
+ {CT_MockingboardC, "MockingboardC"},
+ {CT_GenericPrinter, "GenericPrinter"},
+ {CT_GenericHDD, "GenericHDD"},
+ {CT_GenericClock, "GenericClock"},
+ {CT_MouseInterface, "MouseInterface"},
+ {CT_Z80, "Z80"},
+ {CT_Phasor, "Phasor"},
+ {CT_Echo, "Echo"},
+ {CT_SAM, "SAM"},
+ {CT_80Col, "80Col"},
+ {CT_Extended80Col, "Extended80Col"},
+ {CT_RamWorksIII, "RamWorksIII"},
+ {CT_Uthernet, "Uthernet"},
+ {CT_LanguageCard, "LanguageCard"},
+ {CT_LanguageCardIIe, "LanguageCardIIe"},
+ {CT_Saturn128K, "Saturn128K"},
+ {CT_FourPlay, "FourPlay"},
+ {CT_SNESMAX, "SNESMAX"},
+ {CT_VidHD, "VidHD"},
+ {CT_Uthernet2, "Uthernet2"},
};
const std::map apple2Types =
{
- {A2TYPE_APPLE2, "A2TYPE_APPLE2"},
- {A2TYPE_APPLE2PLUS, "A2TYPE_APPLE2PLUS"},
- {A2TYPE_APPLE2JPLUS, "A2TYPE_APPLE2JPLUS"},
- {A2TYPE_APPLE2E, "A2TYPE_APPLE2E"},
- {A2TYPE_APPLE2EENHANCED, "A2TYPE_APPLE2EENHANCED"},
- {A2TYPE_APPLE2C, "A2TYPE_APPLE2C"},
- {A2TYPE_PRAVETS8M, "A2TYPE_PRAVETS8M"},
- {A2TYPE_PRAVETS82, "A2TYPE_PRAVETS82"},
- {A2TYPE_BASE64A, "A2TYPE_BASE64A"},
- {A2TYPE_PRAVETS8A, "A2TYPE_PRAVETS8A"},
- {A2TYPE_TK30002E, "A2TYPE_TK30002E"},
+ {A2TYPE_APPLE2, "APPLE2"},
+ {A2TYPE_APPLE2PLUS, "APPLE2PLUS"},
+ {A2TYPE_APPLE2JPLUS, "APPLE2JPLUS"},
+ {A2TYPE_APPLE2E, "APPLE2E"},
+ {A2TYPE_APPLE2EENHANCED, "APPLE2EENHANCED"},
+ {A2TYPE_APPLE2C, "APPLE2C"},
+ {A2TYPE_PRAVETS8M, "PRAVETS8M"},
+ {A2TYPE_PRAVETS82, "PRAVETS82"},
+ {A2TYPE_BASE64A, "BASE64A"},
+ {A2TYPE_PRAVETS8A, "PRAVETS8A"},
+ {A2TYPE_TK30002E, "TK30002E"},
};
const std::map cpuTypes =
{
- {CPU_6502, "CPU_6502"},
- {CPU_65C02, "CPU_65C02"},
- {CPU_Z80, "CPU_Z80"},
+ {CPU_6502, "6502"},
+ {CPU_65C02, "65C02"},
+ {CPU_Z80, "Z80"},
};
const std::map appModes =
{
- {MODE_LOGO, "MODE_LOGO"},
- {MODE_PAUSED, "MODE_PAUSED"},
- {MODE_RUNNING, "MODE_RUNNING"},
- {MODE_DEBUG, "MODE_DEBUG"},
- {MODE_STEPPING, "MODE_STEPPING"},
- {MODE_BENCHMARK, "MODE_BENCHMARCK"},
+ {MODE_LOGO, "LOGO"},
+ {MODE_PAUSED, "PAUSED"},
+ {MODE_RUNNING, "RUNNING"},
+ {MODE_DEBUG, "DEBUG"},
+ {MODE_STEPPING, "STEPPING"},
+ {MODE_BENCHMARK, "BENCHMARCK"},
};
const std::map statuses =
@@ -98,11 +101,11 @@ namespace
{0, {CT_Empty, CT_LanguageCard, CT_Saturn128K}},
{1, {CT_Empty, CT_GenericPrinter, CT_Uthernet2}},
{2, {CT_Empty, CT_SSC, CT_Uthernet2}},
- {3, {CT_Empty, CT_Uthernet, CT_Uthernet2}},
+ {3, {CT_Empty, CT_Uthernet, CT_Uthernet2, CT_VidHD}},
{4, {CT_Empty, CT_MockingboardC, CT_MouseInterface, CT_Phasor, CT_Uthernet2}},
{5, {CT_Empty, CT_MockingboardC, CT_Z80, CT_SAM, CT_Disk2, CT_FourPlay, CT_SNESMAX, CT_Uthernet2}},
- {6, {CT_Empty, CT_Disk2}},
- {7, {CT_Empty, CT_GenericHDD}},
+ {6, {CT_Empty, CT_Disk2, CT_Uthernet2}},
+ {7, {CT_Empty, CT_GenericHDD, CT_Uthernet2}},
};
const std::vector expansionCards =
@@ -158,11 +161,23 @@ namespace sa2
return statuses.at(status);
}
- void insertCard(size_t slot, SS_CARDTYPE card)
+ void insertCard(size_t slot, SS_CARDTYPE card, FrameBase * frame)
{
CardManager & cardManager = GetCardMgr();
+ Video & video = GetVideo();
+ const bool oldHasVid = video.HasVidHD();
switch (slot)
{
+ case 3:
+ {
+ if (cardManager.QuerySlot(slot) == CT_VidHD)
+ {
+ // the old card was a VidHD, which will be removed
+ // reset it
+ video.SetVidHD(false);
+ }
+ break;
+ }
case 4:
case 5:
{
@@ -172,7 +187,6 @@ namespace sa2
}
else
{
- CardManager & cardManager = GetCardMgr();
if (cardManager.QuerySlot(slot) == CT_MockingboardC)
{
cardManager.Insert(9 - slot, CT_Empty); // the other
@@ -182,19 +196,24 @@ namespace sa2
}
};
- if (card == CT_Uthernet2)
+ cardManager.Insert(slot, card);
+
+ // keep everything consistent
+ // a bit of a heavy call, but nothing simpler is available now
+ MemInitializeIO();
+
+ if (oldHasVid != video.HasVidHD())
{
- // only 1 Uthernet2 allowed
- for (size_t s = SLOT1; s < NUM_SLOTS; ++s)
- {
- if (cardManager.QuerySlot(s) == card)
- {
- cardManager.Insert(s, CT_Empty);
- }
- }
+ frame->Destroy();
+ frame->Initialize(true);
}
+ }
- cardManager.Insert(slot, card);
+ void setExpansionCard(SS_CARDTYPE card)
+ {
+ SetExpansionMemType(card);
+ CreateLanguageCard();
+ MemInitializeIO();
}
void setVideoStyle(Video & video, const VideoStyle_e style, const bool enabled)
diff --git a/source/frontends/sdl/imgui/settingshelper.h b/source/frontends/sdl/imgui/settingshelper.h
index 694d5c393..646d4a4f6 100644
--- a/source/frontends/sdl/imgui/settingshelper.h
+++ b/source/frontends/sdl/imgui/settingshelper.h
@@ -10,6 +10,8 @@
#include
#include