mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-02-03 04:30:35 +00:00
Add support for PAL/European or custom 8K video ROMs (#596)
Added new cmd-line switch: -videorom <file> to replace the video ROM for the Enhanced //e. - Support video ROM sizes of 4K, 8K and 16K (top 8K only). - NB. The rocker switch is set to European video ROM. F10 (for //e or Enhanced //e models) emulates the PAL //e's rocker switch (under the keyboard) to toggle between European or US video ROM. Other: - Fixed debugger's view of the AltCharSet soft-switch (it was showing the opposite state).
This commit is contained in:
parent
14e0bb7b71
commit
aa59c71847
@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,27,10,0
|
||||
PRODUCTVERSION 1,27,10,0
|
||||
FILEVERSION 1,27,11,0
|
||||
PRODUCTVERSION 1,27,11,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -271,12 +271,12 @@ BEGIN
|
||||
VALUE "Comments", "https://github.com/AppleWin"
|
||||
VALUE "CompanyName", "AppleWin"
|
||||
VALUE "FileDescription", "Apple //e Emulator for Windows"
|
||||
VALUE "FileVersion", "1, 27, 10, 0"
|
||||
VALUE "FileVersion", "1, 27, 11, 0"
|
||||
VALUE "InternalName", "APPLEWIN"
|
||||
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
|
||||
VALUE "OriginalFilename", "APPLEWIN.EXE"
|
||||
VALUE "ProductName", "Apple //e Emulator"
|
||||
VALUE "ProductVersion", "1, 27, 10, 0"
|
||||
VALUE "ProductVersion", "1, 27, 11, 0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -1289,6 +1289,22 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||
if ((g_hCustomRomF8 == INVALID_HANDLE_VALUE) || (GetFileSize(g_hCustomRomF8, NULL) != 0x800))
|
||||
g_bCustomRomF8Failed = true;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-videorom") == 0) // Use 4K,8K or 16K video ROM for Enhanced //e
|
||||
{
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
|
||||
if (!ReadVideoRomFile(lpCmdLine))
|
||||
{
|
||||
std::string msg = "Failed to load video rom (not found or not exactly 4/8/16KiB)";
|
||||
LogFileOutput("%s", msg.c_str());
|
||||
MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVideoRomRockerSwitch(true); // Use PAL char set
|
||||
}
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-printscreen") == 0) // Turn on display of the last filename print screen was saved to
|
||||
{
|
||||
g_bDisplayPrintScreenFileName = true;
|
||||
@ -1553,7 +1569,9 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
||||
|
||||
if (g_bCustomRomF8Failed)
|
||||
{
|
||||
MessageBox(g_hFrameWindow, "Failed to load custom F8 rom (not found or not exactly 2KB)", TEXT("AppleWin Error"), MB_OK);
|
||||
std::string msg = "Failed to load custom F8 rom (not found or not exactly 2KiB)";
|
||||
LogFileOutput("%s", msg.c_str());
|
||||
MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
|
||||
bShutdown = true;
|
||||
}
|
||||
|
||||
|
@ -3089,7 +3089,7 @@ void DrawSoftSwitches( int iSoftSwitch )
|
||||
_DrawSoftSwitch( rect, 0xC00C, bSet, "Col", "40", "80", NULL, bgMemory );
|
||||
|
||||
// C00E = off, C00F = on
|
||||
bSet = VideoGetSWAltCharSet();
|
||||
bSet = !VideoGetSWAltCharSet();
|
||||
_DrawSoftSwitch( rect, 0xC00E, bSet, NULL, "ASC", "MOUS", NULL, bgMemory ); // ASCII/MouseText
|
||||
|
||||
#if SOFTSWITCH_LANGCARD
|
||||
|
@ -1316,14 +1316,19 @@ LRESULT CALLBACK FrameWndProc (
|
||||
}
|
||||
else if (wparam == VK_F10)
|
||||
{
|
||||
if (g_Apple2Type == A2TYPE_PRAVETS8A && !KeybGetCtrlStatus())
|
||||
{
|
||||
KeybToggleP8ACapsLock (); // F10: Toggles P8 Capslock
|
||||
}
|
||||
else
|
||||
if (KeybGetCtrlStatus())
|
||||
{
|
||||
SetUsingCursor(FALSE); // Ctrl+F10
|
||||
}
|
||||
else if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED)
|
||||
{
|
||||
SetVideoRomRockerSwitch( !GetVideoRomRockerSwitch() ); // F10: toggle rocker switch
|
||||
NTSC_VideoInitAppleType();
|
||||
}
|
||||
else if (g_Apple2Type == A2TYPE_PRAVETS8A)
|
||||
{
|
||||
KeybToggleP8ACapsLock (); // F10: Toggles Pravets8A Capslock
|
||||
}
|
||||
}
|
||||
else if (wparam == VK_F11 && !KeybGetCtrlStatus()) // Save state (F11)
|
||||
{
|
||||
@ -1758,7 +1763,6 @@ LRESULT CALLBACK FrameWndProc (
|
||||
KeybUpdateCtrlShiftStatus();
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/gg153546(v=vs.85).aspx
|
||||
// v1.25.0: Alt-Return Alt-Enter toggle fullscreen
|
||||
if (g_bAltEnter_ToggleFullScreen && KeybGetAltStatus() && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
|
||||
return 0; // NOP -- eat key
|
||||
|
||||
@ -1772,7 +1776,10 @@ LRESULT CALLBACK FrameWndProc (
|
||||
case WM_SYSKEYUP:
|
||||
KeybUpdateCtrlShiftStatus();
|
||||
|
||||
// v1.25.0: Alt-Return Alt-Enter toggle fullscreen
|
||||
// F10: no WM_KEYUP handler for VK_F10. Don't allow WM_KEYUP to pass to default handler which will show the app window's "menu" (and lose focus)
|
||||
if (wparam == VK_F10)
|
||||
return 0;
|
||||
|
||||
if (g_bAltEnter_ToggleFullScreen && KeybGetAltStatus() && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
|
||||
ScreenWindowResize(false);
|
||||
else
|
||||
|
@ -471,7 +471,7 @@ static void set_csbits()
|
||||
case A2TYPE_APPLE2: csbits = &csbits_a2[0]; g_nVideoCharSet = 0; break;
|
||||
case A2TYPE_APPLE2PLUS: csbits = &csbits_a2[0]; g_nVideoCharSet = 0; break;
|
||||
case A2TYPE_APPLE2E: csbits = &csbits_2e[0]; break;
|
||||
case A2TYPE_APPLE2EENHANCED:csbits = &csbits_enhanced2e[0]; break;
|
||||
case A2TYPE_APPLE2EENHANCED:csbits = GetEnhanced2e_csbits(); break;
|
||||
case A2TYPE_PRAVETS82: csbits = &csbits_pravets82[0]; g_nVideoCharSet = 0; break; // Apple ][ clone
|
||||
case A2TYPE_PRAVETS8M: csbits = &csbits_pravets8M[0]; g_nVideoCharSet = 0; break; // Apple ][ clone
|
||||
case A2TYPE_PRAVETS8A: csbits = &csbits_pravets8C[0]; break; // Apple //e clone
|
||||
|
@ -21,10 +21,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "Applewin.h"
|
||||
#include "Video.h"
|
||||
|
||||
#include "NTSC_CharSet.h"
|
||||
|
||||
unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e
|
||||
unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e (2732 4K video ROM)
|
||||
static unsigned char csbits_enhanced2e_pal[2][256][8]; // PAL Enhanced //e (2764 8K video ROM - top 4K) via rocker switch under keyboard
|
||||
unsigned char csbits_2e[2][256][8]; // Original //e (no mousetext)
|
||||
unsigned char csbits_a2[1][256][8]; // ][ and ][+
|
||||
unsigned char csbits_pravets82[1][256][8]; // Pravets 82
|
||||
@ -86,6 +88,91 @@ static void get_csbits(csbits_t csbits, const char* resourceName, const UINT cy0
|
||||
delete [] pBuffer;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
// ROM address (RA):
|
||||
// -----------------
|
||||
// . RA10,..,RA3;SEGC,SEGB,SEGA => [2^8][2^3] => 256 chars of 8 lines (total = 2KiB)
|
||||
// . VID7,..,VID0 is the 8-bit video character (eg. from TEXT/$400 memory)
|
||||
//
|
||||
// UTAIIe:8-13, Table 8.2:
|
||||
//
|
||||
// ALTCHRSET | RA10 | RA9
|
||||
//------------------------------------------
|
||||
// 0 | VID7 + VID6.FLASH | VID6.VID7
|
||||
// 1 | VID7 | VID6
|
||||
//
|
||||
// FLASH toggles every 16 VBLs, so alternates between selecting NORMAL control/special and INVERSE control/special
|
||||
//
|
||||
|
||||
void userVideoRom4K(csbits_t csbits, const BYTE* pVideoRom)
|
||||
{
|
||||
int RA = 0; // rom address
|
||||
int i = 0;
|
||||
|
||||
// regular char set
|
||||
|
||||
for (; i<64; i++, RA+=8) // [00..3F] INVERSE / [40..7F] FLASH
|
||||
{
|
||||
for (int y=0; y<8; y++)
|
||||
{
|
||||
csbits[0][i][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-11 "dot patterns in the video ROM are inverted..."
|
||||
csbits[0][i+64][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-14 (Table 8.3) we use FLASH=0, so RA=00ccccccsss
|
||||
}
|
||||
}
|
||||
|
||||
RA = (1<<10 | 0<<9); // UTAIIe:8-14 (Table 8.3)
|
||||
|
||||
for (i=128; i<256; i++, RA+=8) // [80..BF] NORMAL
|
||||
{
|
||||
for (int y=0; y<8; y++)
|
||||
{
|
||||
csbits[0][i][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-11 "dot patterns in the video ROM are inverted..."
|
||||
}
|
||||
}
|
||||
|
||||
RA = (1<<10 | 1<<9); // UTAIIe:8-14 (Table 8.3)
|
||||
|
||||
for (i=192; i<256; i++, RA+=8) // [C0..FF] NORMAL
|
||||
{
|
||||
for (int y=0; y<8; y++)
|
||||
{
|
||||
csbits[0][i][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-11 "dot patterns in the video ROM are inverted..."
|
||||
}
|
||||
}
|
||||
|
||||
// alt char set
|
||||
|
||||
RA = 0;
|
||||
|
||||
for (i=0; i<256; i++, RA+=8) // [00..7F] INVERSE / [80..FF] NORMAL
|
||||
{
|
||||
for (int y=0; y<8; y++)
|
||||
{
|
||||
csbits[1][i][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-11 "dot patterns in the video ROM are inverted..."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void userVideoRom(void)
|
||||
{
|
||||
const BYTE* pVideoRom;
|
||||
UINT size = GetVideoRom(pVideoRom); // 4K or 8K
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
if (size == kVideoRomSize4K)
|
||||
{
|
||||
userVideoRom4K(&csbits_enhanced2e[0], pVideoRom);
|
||||
return;
|
||||
}
|
||||
|
||||
userVideoRom4K(&csbits_enhanced2e_pal[0], pVideoRom);
|
||||
userVideoRom4K(&csbits_enhanced2e[0], &pVideoRom[4*1024]);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
void make_csbits(void)
|
||||
{
|
||||
get_csbits(&csbits_enhanced2e[0], TEXT("CHARSET40"), 0); // Enhanced //e: Alt char set off
|
||||
@ -99,4 +186,15 @@ void make_csbits(void)
|
||||
// Original //e is just Enhanced //e with the 32 mousetext chars [0x40..0x5F] replaced by the non-alt charset chars [0x40..0x5F]
|
||||
memcpy(csbits_2e, csbits_enhanced2e, sizeof(csbits_enhanced2e));
|
||||
memcpy(&csbits_2e[1][64], &csbits_2e[0][64], 32*8);
|
||||
|
||||
// Try to use any user-provided video ROM for Enhanced //e
|
||||
userVideoRom();
|
||||
}
|
||||
|
||||
csbits_t GetEnhanced2e_csbits(void)
|
||||
{
|
||||
if (IsVideoRom4K())
|
||||
return csbits_enhanced2e;
|
||||
|
||||
return GetVideoRomRockerSwitch() == false ? csbits_enhanced2e : csbits_enhanced2e_pal;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
typedef unsigned char (*csbits_t)[256][8];
|
||||
|
||||
extern unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e
|
||||
extern unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e (2732 4K video ROM)
|
||||
extern unsigned char csbits_2e[2][256][8]; // Original //e (no mousetext)
|
||||
extern unsigned char csbits_a2[1][256][8]; // ][ and ][+
|
||||
extern unsigned char csbits_pravets82[1][256][8]; // Pravets 82
|
||||
@ -10,3 +10,4 @@ extern unsigned char csbits_pravets8M[1][256][8]; // Pravets 8M
|
||||
extern unsigned char csbits_pravets8C[2][256][8]; // Pravets 8A & 8C
|
||||
|
||||
void make_csbits(void);
|
||||
csbits_t GetEnhanced2e_csbits(void);
|
||||
|
@ -647,7 +647,7 @@ void VideoResetState ()
|
||||
|
||||
//===========================================================================
|
||||
|
||||
BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles)
|
||||
BYTE VideoSetMode(WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles)
|
||||
{
|
||||
address &= 0xFF;
|
||||
|
||||
@ -1141,6 +1141,65 @@ static void Video_SaveScreenShot( const char *pScreenShotFileName, const VideoSc
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static const UINT kVideoRomSize8K = kVideoRomSize4K*2;
|
||||
static const UINT kVideoRomSize16K = kVideoRomSize8K*2;
|
||||
static const UINT kVideoRomSizeMax = kVideoRomSize16K;
|
||||
static BYTE g_videoRom[kVideoRomSizeMax];
|
||||
static UINT g_videoRomSize = 0;
|
||||
static bool g_videoRomRockerSwitch = false;
|
||||
|
||||
bool ReadVideoRomFile(const char* pRomFile)
|
||||
{
|
||||
g_videoRomSize = 0;
|
||||
|
||||
HANDLE h = CreateFile(pRomFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
const ULONG size = GetFileSize(h, NULL);
|
||||
if (size == kVideoRomSize4K || size == kVideoRomSize8K || size == kVideoRomSize16K)
|
||||
{
|
||||
DWORD bytesRead;
|
||||
if (ReadFile(h, g_videoRom, size, &bytesRead, NULL) && bytesRead == size)
|
||||
g_videoRomSize = size;
|
||||
}
|
||||
|
||||
if (g_videoRomSize == kVideoRomSize16K)
|
||||
{
|
||||
// Use top 8K (assume bottom 8K is all 0xFF's)
|
||||
memcpy(&g_videoRom[0], &g_videoRom[kVideoRomSize8K], kVideoRomSize8K);
|
||||
g_videoRomSize = kVideoRomSize8K;
|
||||
}
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
return g_videoRomSize != 0;
|
||||
}
|
||||
|
||||
UINT GetVideoRom(const BYTE*& pVideoRom)
|
||||
{
|
||||
pVideoRom = &g_videoRom[0];
|
||||
return g_videoRomSize;
|
||||
}
|
||||
|
||||
bool GetVideoRomRockerSwitch(void)
|
||||
{
|
||||
return g_videoRomRockerSwitch;
|
||||
}
|
||||
|
||||
void SetVideoRomRockerSwitch(bool state)
|
||||
{
|
||||
g_videoRomRockerSwitch = state;
|
||||
}
|
||||
|
||||
bool IsVideoRom4K(void)
|
||||
{
|
||||
return g_videoRomSize == 0 || g_videoRomSize == kVideoRomSize4K;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void Config_Load_Video()
|
||||
@ -1160,8 +1219,6 @@ void Config_Save_Video()
|
||||
REGSAVE(TEXT(REGVALUE_VIDEO_MONO_COLOR ),g_nMonochromeRGB);
|
||||
}
|
||||
|
||||
// ____________________________________________________________________
|
||||
|
||||
//===========================================================================
|
||||
static void videoCreateDIBSection()
|
||||
{
|
||||
|
@ -198,7 +198,14 @@ enum VideoScreenShot_e
|
||||
void Video_TakeScreenShot( VideoScreenShot_e iScreenShotType );
|
||||
void Video_SetBitmapHeader( WinBmpHeader_t *pBmp, int nWidth, int nHeight, int nBitsPerPixel );
|
||||
|
||||
BYTE VideoSetMode (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
|
||||
BYTE VideoSetMode(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
|
||||
|
||||
const UINT kVideoRomSize4K = 4*1024;
|
||||
bool ReadVideoRomFile(const char* pRomFile);
|
||||
UINT GetVideoRom(const BYTE*& pVideoRom);
|
||||
bool GetVideoRomRockerSwitch(void);
|
||||
void SetVideoRomRockerSwitch(bool state);
|
||||
bool IsVideoRom4K(void);
|
||||
|
||||
void Config_Load_Video(void);
|
||||
void Config_Save_Video(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user