mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-12-28 17:30:02 +00:00
Support VidHD in slot 3 (via Config GUI or '-s3 vidhd') for SHR video modes only. - AppleWin window is slightly enlarged when VidHD card is inserted. Support IIgs 320x200 (and fill mode) and 640x200 video modes. Debugger: add 'shr' command to view video CUI: Allow user to specify width & height (for full-screen); and allow separate x,y scaling in full-screen mode.
This commit is contained in:
parent
0b2104cc89
commit
443545b0f6
@ -121,6 +121,7 @@
|
||||
<ClInclude Include="source\Tfe\Uilib.h" />
|
||||
<ClInclude Include="source\Utilities.h" />
|
||||
<ClInclude Include="source\Video.h" />
|
||||
<ClInclude Include="Source\VidHD.h" />
|
||||
<ClInclude Include="source\Windows\AppleWin.h" />
|
||||
<ClInclude Include="source\Windows\DirectInput.h" />
|
||||
<ClInclude Include="source\Windows\HookFilter.h" />
|
||||
@ -247,6 +248,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\Utilities.cpp" />
|
||||
<ClCompile Include="source\Video.cpp" />
|
||||
<ClCompile Include="Source\VidHD.cpp" />
|
||||
<ClCompile Include="source\Windows\AppleWin.cpp" />
|
||||
<ClCompile Include="source\Windows\DirectInput.cpp" />
|
||||
<ClCompile Include="source\Windows\HookFilter.cpp" />
|
||||
|
@ -241,6 +241,9 @@
|
||||
<ClCompile Include="source\Card.cpp">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Source\VidHD.cpp">
|
||||
<Filter>Source Files\Video</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="source\CommonVICE\6510core.h">
|
||||
@ -555,6 +558,9 @@
|
||||
<ClInclude Include="source\SNESMAX.h">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Source\VidHD.h">
|
||||
<Filter>Source Files\Video</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="resource\Applewin.bmp">
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
enum SLOTS { SLOT0=0, SLOT1, SLOT2, SLOT3, SLOT4, SLOT5, SLOT6, SLOT7, NUM_SLOTS, SLOT_AUX };
|
||||
|
@ -40,6 +40,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "SAM.h"
|
||||
#include "SerialComms.h"
|
||||
#include "SNESMAX.h"
|
||||
#include "VidHD.h"
|
||||
|
||||
void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type)
|
||||
{
|
||||
@ -96,6 +97,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:
|
||||
|
@ -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] <dsk-image>
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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" },
|
||||
|
@ -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++)
|
||||
|
@ -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);
|
||||
|
@ -15,7 +15,7 @@ public:
|
||||
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 @@ public:
|
||||
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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -541,6 +541,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()
|
||||
@ -595,7 +597,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();
|
||||
|
189
source/VidHD.cpp
Normal file
189
source/VidHD.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
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;
|
||||
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;
|
||||
}
|
44
source/VidHD.h
Normal file
44
source/VidHD.h
Normal file
@ -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;
|
||||
};
|
@ -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<VidHDCard*>(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,15 @@ void Video::VideoRefreshBuffer(uint32_t uRedrawWholeScreenVideoMode, bool bRedra
|
||||
NTSC_VideoRedrawWholeScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void Video::ClearFrameBuffer(void)
|
||||
{
|
||||
memset(GetFrameBuffer(), 0, GetFrameBufferWidth() * GetFrameBufferHeight() * sizeof(bgra_t));
|
||||
}
|
||||
|
||||
// Called when entering debugger, and after viewing Apple II video screen from debugger
|
||||
void Video::ClearSHRResidue(void)
|
||||
{
|
||||
ClearFrameBuffer();
|
||||
GetFrame().VideoPresentScreen();
|
||||
}
|
||||
|
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ protected:
|
||||
uint8_t *g_pFramebufferbits;
|
||||
|
||||
private:
|
||||
|
||||
void SetFrameBuffer(uint8_t* frameBuffer) { g_pFramebufferbits = frameBuffer; }
|
||||
std::string VideoGetSnapshotStructName(void);
|
||||
|
||||
@ -285,6 +296,7 @@ private:
|
||||
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 @@ private:
|
||||
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;
|
||||
};
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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()
|
||||
|
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
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;
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user