diff --git a/AppleWinExpress2019.vcxproj b/AppleWinExpress2019.vcxproj index c11c061d..10c81acd 100644 --- a/AppleWinExpress2019.vcxproj +++ b/AppleWinExpress2019.vcxproj @@ -237,6 +237,8 @@ + + @@ -298,6 +300,7 @@ + diff --git a/AppleWinExpress2019.vcxproj.filters b/AppleWinExpress2019.vcxproj.filters index 1b9cfec1..066d108f 100644 --- a/AppleWinExpress2019.vcxproj.filters +++ b/AppleWinExpress2019.vcxproj.filters @@ -593,6 +593,9 @@ Resource Files + + Resource Files + @@ -652,6 +655,12 @@ Resource Files + + Resource Files + + + Resource Files + diff --git a/resource/Applewin.rc b/resource/Applewin.rc index 8422331a..381b336b 100644 --- a/resource/Applewin.rc +++ b/resource/Applewin.rc @@ -55,6 +55,7 @@ FULLSCR_BUTTON BITMAP "FULLSCR.BMP" RUN_BUTTON BITMAP "RUN.BMP" RUNP_BUTTON BITMAP "RUNP.BMP" RUN3000E_BUTTON BITMAP "RUN3000E.BMP" +RUNBASE64A_BUTTON BITMAP "RUNBASE64A.BMP" DEBUG_BUTTON BITMAP "DEBUG.BMP" DRIVE1_BUTTON BITMAP "DRIVE1.BMP" DRIVE2_BUTTON BITMAP "DRIVE2.BMP" @@ -332,6 +333,7 @@ IDR_PRAVETS_82_ROM ROM "Pravets82.rom" IDR_PRAVETS_8M_ROM ROM "Pravets8M.rom" IDR_PRAVETS_8C_ROM ROM "Pravets8C.rom" IDR_TK3000_2E_ROM ROM "TK3000e.rom" +IDR_BASE_64A_ROM ROM "Base64A.rom" IDR_FREEZES_F8_ROM ROM "FREEZES_NON-AUTOSTART_F8_ROM.rom" ///////////////////////////////////////////////////////////////////////////// @@ -340,6 +342,7 @@ IDR_FREEZES_F8_ROM ROM "FREEZES_NON-AUTOSTART_F8_ROM.ro // IDR_APPLE2_JPLUS_VIDEO_ROM ROM "Apple2_JPlus_Video.rom" +IDR_BASE64A_VIDEO_ROM ROM "Base64A_German_Video.rom" ///////////////////////////////////////////////////////////////////////////// // diff --git a/resource/Base64A.rom b/resource/Base64A.rom new file mode 100644 index 00000000..78e2054d Binary files /dev/null and b/resource/Base64A.rom differ diff --git a/resource/Base64A_German_Video.rom b/resource/Base64A_German_Video.rom new file mode 100644 index 00000000..dcc2972f Binary files /dev/null and b/resource/Base64A_German_Video.rom differ diff --git a/resource/RUNBASE64A.BMP b/resource/RUNBASE64A.BMP new file mode 100644 index 00000000..9c4c03b5 Binary files /dev/null and b/resource/RUNBASE64A.BMP differ diff --git a/resource/resource.h b/resource/resource.h index 932ac25d..3dfe6a3a 100644 --- a/resource/resource.h +++ b/resource/resource.h @@ -51,6 +51,8 @@ #define IDR_DISK2_16SECTOR_FW 150 #define IDR_APPLE2_JPLUS_ROM 151 #define IDR_APPLE2_JPLUS_VIDEO_ROM 152 +#define IDR_BASE_64A_ROM 153 +#define IDR_BASE64A_VIDEO_ROM 154 #define IDC_KEYB_BUFFER_ENABLE 1005 #define IDC_SAVESTATE 1006 #define IDC_SAVESTATE_ON_EXIT 1007 diff --git a/source/Common.h b/source/Common.h index f2c6516b..2fca260a 100644 --- a/source/Common.h +++ b/source/Common.h @@ -57,6 +57,7 @@ enum AppMode_e #define TITLE_PRAVETS_8M TEXT("Pravets 8M Emulator") #define TITLE_PRAVETS_8A TEXT("Pravets 8A Emulator") #define TITLE_TK3000_2E TEXT("TK3000 //e Emulator") +#define TITLE_BASE64A TEXT("Base64A Emulator") #define TITLE_PAUSED TEXT("* PAUSED *") #define TITLE_STEPPING TEXT("Stepping") @@ -180,6 +181,7 @@ enum eApple2Type { A2TYPE_CLONE=APPLECLONE_MASK, A2TYPE_PRAVETS8M, // Apple ][ clone A2TYPE_PRAVETS82, // Apple ][ clone + A2TYPE_BASE64A, // Apple ][ clone // (Gap for more Apple ][ clones) A2TYPE_CLONE_A2_MAX, diff --git a/source/Configuration/PageAdvanced.cpp b/source/Configuration/PageAdvanced.cpp index d82d4cc1..8ff9120f 100644 --- a/source/Configuration/PageAdvanced.cpp +++ b/source/Configuration/PageAdvanced.cpp @@ -33,12 +33,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA CPageAdvanced* CPageAdvanced::ms_this = 0; // reinit'd in ctor -enum CLONECHOICE {MENUITEM_CLONEMIN, MENUITEM_PRAVETS82=MENUITEM_CLONEMIN, MENUITEM_PRAVETS8M, MENUITEM_PRAVETS8A, MENUITEM_TK30002E, MENUITEM_CLONEMAX}; +enum CLONECHOICE {MENUITEM_CLONEMIN, MENUITEM_PRAVETS82=MENUITEM_CLONEMIN, MENUITEM_PRAVETS8M, MENUITEM_PRAVETS8A, MENUITEM_TK30002E, MENUITEM_BASE64A, MENUITEM_CLONEMAX}; const TCHAR CPageAdvanced::m_CloneChoices[] = TEXT("Pravets 82\0") // Bulgarian TEXT("Pravets 8M\0") // Bulgarian TEXT("Pravets 8A\0") // Bulgarian - TEXT("TK3000 //e\0"); // Brazilian + TEXT("TK3000 //e\0") // Brazilian + TEXT("Base 64A\0"); // Taiwanese + BOOL CALLBACK CPageAdvanced::DlgProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam) { @@ -223,6 +225,7 @@ eApple2Type CPageAdvanced::GetCloneType(DWORD NewMenuItem) case MENUITEM_PRAVETS8M: return A2TYPE_PRAVETS8M; case MENUITEM_PRAVETS8A: return A2TYPE_PRAVETS8A; case MENUITEM_TK30002E: return A2TYPE_TK30002E; + case MENUITEM_BASE64A: return A2TYPE_BASE64A; default: return A2TYPE_PRAVETS82; } } @@ -250,6 +253,7 @@ int CPageAdvanced::GetCloneMenuItem(void) case A2TYPE_PRAVETS8M: nMenuItem = MENUITEM_PRAVETS8M; break; case A2TYPE_PRAVETS8A: nMenuItem = MENUITEM_PRAVETS8A; break; case A2TYPE_TK30002E: nMenuItem = MENUITEM_TK30002E; break; + case A2TYPE_BASE64A: nMenuItem = MENUITEM_BASE64A; break; default: // New clone needs adding here? _ASSERT(0); } diff --git a/source/Configuration/PageConfig.cpp b/source/Configuration/PageConfig.cpp index ddba9ce3..929a6796 100644 --- a/source/Configuration/PageConfig.cpp +++ b/source/Configuration/PageConfig.cpp @@ -190,6 +190,7 @@ BOOL CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM case A2TYPE_PRAVETS8M: nCurrentChoice = MENUITEM_CLONE; break; case A2TYPE_PRAVETS8A: nCurrentChoice = MENUITEM_CLONE; break; case A2TYPE_TK30002E: nCurrentChoice = MENUITEM_CLONE; break; + case A2TYPE_BASE64A: nCurrentChoice = MENUITEM_CLONE; break; default: _ASSERT(0); break; } diff --git a/source/Frame.cpp b/source/Frame.cpp index f33ed21d..c8529e02 100644 --- a/source/Frame.cpp +++ b/source/Frame.cpp @@ -263,6 +263,7 @@ static void GetAppleWindowTitle() case A2TYPE_PRAVETS8M: g_pAppTitle = TITLE_PRAVETS_8M ; break; case A2TYPE_PRAVETS8A: g_pAppTitle = TITLE_PRAVETS_8A ; break; case A2TYPE_TK30002E: g_pAppTitle = TITLE_TK3000_2E ; break; + case A2TYPE_BASE64A: g_pAppTitle = TITLE_BASE64A ; break; } #if _DEBUG @@ -386,6 +387,9 @@ static void CreateGdiObjects(void) case A2TYPE_TK30002E: buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUN3000E_BUTTON")); break; + case A2TYPE_BASE64A: + buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUNBASE64A_BUTTON")); + break; default: buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUN_BUTTON")); break; @@ -1349,7 +1353,7 @@ LRESULT CALLBACK FrameWndProc ( } else if (wparam == VK_F10) { - if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED) + if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED || g_Apple2Type == A2TYPE_BASE64A) { SetVideoRomRockerSwitch( !GetVideoRomRockerSwitch() ); // F10: toggle rocker switch NTSC_VideoInitAppleType(); diff --git a/source/Memory.cpp b/source/Memory.cpp index 5a5a7db1..a3ab1e8d 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -77,6 +77,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define SW_INTCXROM (memmode & MF_INTCXROM) #define SW_WRITERAM (memmode & MF_WRITERAM) #define SW_IOUDIS (memmode & MF_IOUDIS) +#define SW_ALTROM0 (memmode & MF_ALTROM0) +#define SW_ALTROM1 (memmode & MF_ALTROM1) /* MEMORY MANAGEMENT SOFT SWITCHES @@ -210,6 +212,8 @@ static LPBYTE g_pMemMainLanguageCard = NULL; static DWORD memmode = LanguageCardUnit::kMemModeInitialState; static BOOL modechanging = 0; // An Optimisation: means delay calling UpdatePaging() for 1 instruction +static UINT memrompages = 1; + static CNoSlotClock* g_NoSlotClock = new CNoSlotClock; static LanguageCardUnit* g_pLanguageCard = NULL; // For all Apple II, //e and above @@ -233,6 +237,15 @@ static SS_CARDTYPE g_MemTypeAppleIIPlus = CT_LanguageCard; // Keep a copy so it' static SS_CARDTYPE g_MemTypeAppleIIe = CT_Extended80Col; // Keep a copy so it's not lost if machine type changes, eg: A//e -> A][ -> A//e static UINT g_uSaturnBanksFromCmdLine = 0; + +const UINT CxRomSize = 4 * 1024; +const UINT Apple2RomSize = 12 * 1024; +const UINT Apple2eRomSize = Apple2RomSize + CxRomSize; +//const UINT Pravets82RomSize = 12*1024; +//const UINT Pravets8ARomSize = Pravets82RomSize+CxRomSize; +const UINT MaxRomPages = 4; +const UINT Base64ARomSize = MaxRomPages * Apple2RomSize; + // Called from MemLoadSnapshot() static void ResetDefaultMachineMemTypes(void) { @@ -699,6 +712,11 @@ BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYT if (address >= 0xC05C && address <= 0xC05D && IsApple2JPlus(GetApple2Type())) NTSC_VideoInitAppleType(); // AN2 switches between Katakana & ASCII video rom chars (GH#773) + if (address >= 0xC058 && address <= 0xC05B && (g_Apple2Type == A2TYPE_BASE64A)) + { + MemSetPaging(programcounter, address, write, value, nExecutedCycles); + } + if (!write) return MemReadFloatingBus(nExecutedCycles); else @@ -1132,12 +1150,14 @@ static void UpdatePaging(BOOL initialize) : pCxRomInternal+uRomOffset; // C800..CFFF - Internal ROM } + int selectedrompage = (SW_ALTROM0 ? 1 : 0) | (SW_ALTROM1 ? 2 : 0); + int romoffset = (selectedrompage % memrompages) * Apple2RomSize; for (loop = 0xD0; loop < 0xE0; loop++) { int bankoffset = (SW_BANK2 ? 0 : 0x1000); memshadow[loop] = SW_HIGHRAM ? SW_ALTZP ? memaux+(loop << 8)-bankoffset : g_pMemMainLanguageCard+((loop-0xC0)<<8)-bankoffset - : memrom+((loop-0xD0) * 0x100); + : memrom+((loop-0xD0) * 0x100)+romoffset; memwrite[loop] = SW_WRITERAM ? SW_HIGHRAM ? mem+(loop << 8) : SW_ALTZP ? memaux+(loop << 8)-bankoffset @@ -1149,7 +1169,7 @@ static void UpdatePaging(BOOL initialize) { memshadow[loop] = SW_HIGHRAM ? SW_ALTZP ? memaux+(loop << 8) : g_pMemMainLanguageCard+((loop-0xC0)<<8) - : memrom+((loop-0xD0) * 0x100); + : memrom+((loop-0xD0) * 0x100)+romoffset; memwrite[loop] = SW_WRITERAM ? SW_HIGHRAM ? mem+(loop << 8) : SW_ALTZP ? memaux+(loop << 8) @@ -1429,19 +1449,13 @@ bool MemIsAddrCodeMemory(const USHORT addr) //=========================================================================== -const UINT CxRomSize = 4*1024; -const UINT Apple2RomSize = 12*1024; -const UINT Apple2eRomSize = Apple2RomSize+CxRomSize; -//const UINT Pravets82RomSize = 12*1024; -//const UINT Pravets8ARomSize = Pravets82RomSize+CxRomSize; - void MemInitialize() { // ALLOCATE MEMORY FOR THE APPLE MEMORY IMAGE AND ASSOCIATED DATA STRUCTURES memaux = (LPBYTE)VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE); memmain = (LPBYTE)VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE); memdirty = (LPBYTE)VirtualAlloc(NULL,0x100 ,MEM_COMMIT,PAGE_READWRITE); - memrom = (LPBYTE)VirtualAlloc(NULL,0x5000 ,MEM_COMMIT,PAGE_READWRITE); + memrom = (LPBYTE)VirtualAlloc(NULL,0x3000 * MaxRomPages ,MEM_COMMIT,PAGE_READWRITE); memimage = (LPBYTE)VirtualAlloc(NULL,_6502_MEM_END+1,MEM_RESERVE,PAGE_NOACCESS); pCxRomInternal = (LPBYTE) VirtualAlloc(NULL, CxRomSize, MEM_COMMIT, PAGE_READWRITE); @@ -1522,6 +1536,7 @@ void MemInitializeROM(void) case A2TYPE_PRAVETS8M: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_PRAVETS_8M_ROM ), "ROM"); ROM_SIZE = Apple2RomSize ; break; case A2TYPE_PRAVETS8A: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_PRAVETS_8C_ROM ), "ROM"); ROM_SIZE = Apple2eRomSize; break; case A2TYPE_TK30002E: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_TK3000_2E_ROM ), "ROM"); ROM_SIZE = Apple2eRomSize; break; + case A2TYPE_BASE64A: hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_BASE_64A_ROM ), "ROM"); ROM_SIZE = Base64ARomSize; break; } if (hResInfo == NULL) @@ -1538,6 +1553,7 @@ void MemInitializeROM(void) case A2TYPE_PRAVETS8M: _tcscpy(sRomFileName, TEXT("PRAVETS8M.ROM" )); break; case A2TYPE_PRAVETS8A: _tcscpy(sRomFileName, TEXT("PRAVETS8C.ROM" )); break; case A2TYPE_TK30002E: _tcscpy(sRomFileName, TEXT("TK3000e.ROM" )); break; + case A2TYPE_BASE64A: _tcscpy(sRomFileName, TEXT("BASE64A.ROM" )); break; default: { _tcscpy(sRomFileName, TEXT("Unknown type!")); @@ -1581,8 +1597,9 @@ void MemInitializeROM(void) ROM_SIZE -= CxRomSize; } - _ASSERT(ROM_SIZE == Apple2RomSize); - memcpy(memrom, pData, Apple2RomSize); // ROM at $D000...$FFFF + memrompages = MAX(MaxRomPages, ROM_SIZE / Apple2RomSize); + _ASSERT(ROM_SIZE % Apple2RomSize == 0); + memcpy(memrom, pData, ROM_SIZE); // ROM at $D000...$FFFF, one or several pages } void MemInitializeCustomF8ROM(void) @@ -2045,6 +2062,17 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE } } + if (g_Apple2Type == A2TYPE_BASE64A) + { + switch (address) + { + case 0x58: SetMemMode(memmode & ~MF_ALTROM0); break; + case 0x59: SetMemMode(memmode | MF_ALTROM0); break; + case 0x5A: SetMemMode(memmode & ~MF_ALTROM1); break; + case 0x5B: SetMemMode(memmode | MF_ALTROM1); break; + } + } + if (MemOptimizeForModeChanging(programcounter, address)) return write ? 0 : MemReadFloatingBus(nExecutedCycles); diff --git a/source/Memory.h b/source/Memory.h index 2e65ba18..81130c7f 100644 --- a/source/Memory.h +++ b/source/Memory.h @@ -13,6 +13,8 @@ #define MF_INTCXROM 0x00000200 #define MF_WRITERAM 0x00000400 // Language Card RAM is Write Enabled #define MF_IOUDIS 0x00000800 // Disable IOU access for addresses $C058 to $C05F; enable access to DHIRES switch (0=on) (Enhanced //e only) +#define MF_ALTROM0 0x00001000 // Use alternate ROM for $D000 to $FFFF. Two bits for up to 4 pages +#define MF_ALTROM1 0x00002000 // Use alternate ROM, second bit to have four pages #define MF_IMAGEMASK 0x000003F7 #define MF_LANGCARD_MASK (MF_WRITERAM|MF_HIGHRAM|MF_BANK2) diff --git a/source/NTSC.cpp b/source/NTSC.cpp index 12507f97..ee621cd9 100644 --- a/source/NTSC.cpp +++ b/source/NTSC.cpp @@ -457,6 +457,7 @@ static void set_csbits() case A2TYPE_PRAVETS8M: csbits = &csbits_pravets8M[0]; g_nVideoCharSet = 0; break; // Apple ][ clone case A2TYPE_PRAVETS8A: csbits = &csbits_pravets8C[0]; break; // Apple //e clone case A2TYPE_TK30002E: csbits = &csbits_enhanced2e[0]; break; // Enhanced Apple //e clone + case A2TYPE_BASE64A: csbits = &csbits_base64a[GetVideoRomRockerSwitch() ? 0 : 1]; g_nVideoCharSet = 0; break; // Apple ][ clone default: _ASSERT(0); csbits = &csbits_enhanced2e[0]; break; } } diff --git a/source/NTSC_CharSet.cpp b/source/NTSC_CharSet.cpp index 3ff4017c..092049da 100644 --- a/source/NTSC_CharSet.cpp +++ b/source/NTSC_CharSet.cpp @@ -34,6 +34,8 @@ unsigned char csbits_a2j[2][256][8]; // ][J-Plus unsigned char csbits_pravets82[1][256][8]; // Pravets 82 unsigned char csbits_pravets8M[1][256][8]; // Pravets 8M unsigned char csbits_pravets8C[2][256][8]; // Pravets 8A & 8C +unsigned char csbits_base64a[2][256][8]; // Base 64A + // @@ -179,15 +181,15 @@ static void userVideoRomForIIe(void) //------------------------------------- -static void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom, const bool isApple2JPlus=false, const int AN2=0); +static void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom, eApple2Type type = A2TYPE_APPLE2, const int AN2=0); -static void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom, const bool isApple2JPlus/*=false*/, const int AN2/*=0*/) +static void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom, const eApple2Type type /*= A2TYPE_APPLE2*/, const int AN2/*=0*/) { for (int i=0; i<256; i++) { int RA = i*8; // rom address - if (isApple2JPlus) + if (type == A2TYPE_APPLE2JPLUS) { // AN2=0: $00-3F, $00-3F; $80-BF, $80-BF => KKAA (Repeat Katakana) // AN2=1: $40-7F, $40-7F; $C0-FF, $C0-FF => AAAA (Repeat ASCII) @@ -202,16 +204,33 @@ static void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom, const bool is // UTAII:8-30 "Bit 7 of your EPROM fonts will control flashing in the lower 1024 bytes of the EPROM" // UTAII:8-31 "If you leave O7 (EPROM Output7) reset in these patterns, the resulting characters will be inversions..." // Apple II J-Plus: simplest logic is just invert if reading low 1K of video ROM + // Base64A: Bit 0 instead of bit 7 if (RA < 1024) { - if (!(n & 0x80) || isApple2JPlus) - n = n ^ 0x7f; + if (type == A2TYPE_BASE64A) + { + if (!(n & 0x01)) + n = n ^ 0xfe; + } + else + { + if (!(n & 0x80) || (type == A2TYPE_APPLE2JPLUS)) + n = n ^ 0x7f; + } } - // UTAII:8-30 "TEXT ROM pattern is ... reversed" BYTE d = 0; - for (BYTE j=0; j<7; j++, n >>= 1) // Just bits [0..6] - d = (d << 1) | (n & 1); + if (type == A2TYPE_BASE64A) + { + // On the Base 64A bits are ordered 1345672. + d = (n >> 2) | ((n & 2) >> 1) | ((n & 4) << 4); + } + else + { + // UTAII:8-30 "TEXT ROM pattern is ... reversed" + for (BYTE j = 0; j < 7; j++, n >>= 1) // Just bits [0..6] + d = (d << 1) | (n & 1); + } csbits[0][i][y] = d; } @@ -248,10 +267,33 @@ static void VideoRomForIIJPlus(void) if (pVideoRom == NULL) return; - userVideoRom2K(&csbits_a2j[0], pVideoRom, true, 0); - userVideoRom2K(&csbits_a2j[1], pVideoRom, true, 1); + userVideoRom2K(&csbits_a2j[0], pVideoRom, A2TYPE_APPLE2JPLUS, 0); + userVideoRom2K(&csbits_a2j[1], pVideoRom, A2TYPE_APPLE2JPLUS, 1); } +static void VideoRomForBase64A(void) +{ + HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_BASE64A_VIDEO_ROM), "ROM"); + if (hResInfo == NULL) + return; + + DWORD dwResSize = SizeofResource(NULL, hResInfo); + if (dwResSize != kVideoRomSize4K) + return; + + HGLOBAL hResData = LoadResource(NULL, hResInfo); + if (hResData == NULL) + return; + + BYTE* pVideoRom = (BYTE*)LockResource(hResData); // NB. Don't need to unlock resource + if (pVideoRom == NULL) + return; + + userVideoRom2K(&csbits_base64a[0], pVideoRom, A2TYPE_BASE64A, 0); + userVideoRom2K(&csbits_base64a[1], pVideoRom + kVideoRomSize2K, A2TYPE_BASE64A, 0); +} + + //------------------------------------- void make_csbits(void) @@ -269,6 +311,7 @@ void make_csbits(void) memcpy(&csbits_2e[1][64], &csbits_2e[0][64], 32*8); VideoRomForIIJPlus(); // GH#773 + VideoRomForBase64A(); // GH#806 // Try to use any user-provided video ROM for Original/Enhanced //e userVideoRomForIIe(); diff --git a/source/NTSC_CharSet.h b/source/NTSC_CharSet.h index e3d1d7fd..f8ce9370 100644 --- a/source/NTSC_CharSet.h +++ b/source/NTSC_CharSet.h @@ -8,6 +8,8 @@ extern unsigned char csbits_a2j[2][256][8]; // ][J-Plus extern unsigned char csbits_pravets82[1][256][8]; // Pravets 82 extern unsigned char csbits_pravets8M[1][256][8]; // Pravets 8M extern unsigned char csbits_pravets8C[2][256][8]; // Pravets 8A & 8C +extern unsigned char csbits_base64a[2][256][8]; // Base64A + void make_csbits(void); csbits_t Get2e_csbits(void); diff --git a/source/SaveState.cpp b/source/SaveState.cpp index 4bd044f7..87aa3dbc 100644 --- a/source/SaveState.cpp +++ b/source/SaveState.cpp @@ -155,6 +155,7 @@ static std::string GetSnapshotUnitMiscName(void) #define SS_YAML_VALUE_PRAVETS8M "Pravets8M" #define SS_YAML_VALUE_PRAVETS8A "Pravets8A" #define SS_YAML_VALUE_TK30002E "TK3000//e" +#define SS_YAML_VALUE_BASE64A "Base 64A" static eApple2Type ParseApple2Type(std::string type) { @@ -168,6 +169,7 @@ static eApple2Type ParseApple2Type(std::string type) else if (type == SS_YAML_VALUE_PRAVETS8M) return A2TYPE_PRAVETS8M; else if (type == SS_YAML_VALUE_PRAVETS8A) return A2TYPE_PRAVETS8A; else if (type == SS_YAML_VALUE_TK30002E) return A2TYPE_TK30002E; + else if (type == SS_YAML_VALUE_BASE64A) return A2TYPE_BASE64A; throw std::string("Load: Unknown Apple2 type"); } @@ -186,6 +188,7 @@ static std::string GetApple2TypeAsString(void) case A2TYPE_PRAVETS8M: return SS_YAML_VALUE_PRAVETS8M; case A2TYPE_PRAVETS8A: return SS_YAML_VALUE_PRAVETS8A; case A2TYPE_TK30002E: return SS_YAML_VALUE_TK30002E; + case A2TYPE_BASE64A: return SS_YAML_VALUE_BASE64A; default: throw std::string("Save: Unknown Apple2 type"); }