From 36e318e344683c4a3c72fb6df3425abb979b5377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Izaguirre?= Date: Mon, 6 Jul 2020 21:24:16 +0200 Subject: [PATCH] Support 'Copam Base 64A' - a Taiwanese Apple II clone (#806) (PR #807) . It's an Apple II plus clone. . The 48K bank-switched Rom is controlled with AN0 and AN1. . The character generation video Rom has two full character sets: English and German (F10 to switch). NB. At the prompt, "TEST" runs the ROM self-test. --- AppleWinExpress2019.vcxproj | 3 ++ AppleWinExpress2019.vcxproj.filters | 9 ++++ resource/Applewin.rc | 3 ++ resource/Base64A.rom | Bin 0 -> 49152 bytes resource/Base64A_German_Video.rom | Bin 0 -> 4096 bytes resource/RUNBASE64A.BMP | Bin 0 -> 2884 bytes resource/resource.h | 2 + source/Common.h | 2 + source/Configuration/PageAdvanced.cpp | 8 +++- source/Configuration/PageConfig.cpp | 1 + source/Frame.cpp | 6 ++- source/Memory.cpp | 50 +++++++++++++++----- source/Memory.h | 2 + source/NTSC.cpp | 1 + source/NTSC_CharSet.cpp | 63 ++++++++++++++++++++++---- source/NTSC_CharSet.h | 2 + source/SaveState.cpp | 3 ++ 17 files changed, 131 insertions(+), 24 deletions(-) create mode 100644 resource/Base64A.rom create mode 100644 resource/Base64A_German_Video.rom create mode 100644 resource/RUNBASE64A.BMP 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 0000000000000000000000000000000000000000..78e2054d9007f57dbb0e98a0afc9ae7c52df44a7 GIT binary patch literal 49152 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 xQ={349 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"); }