mirror of
https://github.com/AppleWin/AppleWin.git
synced 2026-04-20 00:17:16 +00:00
Add new command line switch: -aux <empty|std80|ext80|rw3> Add 6502/65C02 x normal/debugger alt read support for CPU emulation (#1353). Fix bug in MemReadFloatingBus() reading from mem[] - no good, if MF_AUXREAD is set. Support odd 80-col text video mode when aux slot is empty: . add a new videoMode flag for VF_80COL_AUX_EMPTY. Correctly support 80COL & DHIRES soft-switches when aux slot is empty or with std80 card. Support VidHD's SHR with -aux <empty|std80>. Save-state: support aux slot empty or with std80 card.
This commit is contained in:
+73
-1
@@ -462,6 +462,7 @@ static __forceinline bool IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn,
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// 6502 & no debugger
|
||||
#define READ _READ_WITH_IO_F8xx
|
||||
#define WRITE(value) _WRITE_WITH_IO_F8xx(value)
|
||||
#define HEATMAP_X(address)
|
||||
@@ -473,20 +474,47 @@ static __forceinline bool IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn,
|
||||
|
||||
//-------
|
||||
|
||||
// 6502 & no debugger & alt read/write support
|
||||
#define READ _READ_ALT
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu6502 Cpu6502_altRW
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
#undef Cpu6502
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
|
||||
//-------
|
||||
|
||||
// 65C02 & no debugger
|
||||
#define READ _READ
|
||||
#define WRITE(value) _WRITE(value)
|
||||
|
||||
#include "CPU/cpu65C02.h" // WDC 65C02
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
|
||||
//-------
|
||||
|
||||
// 65C02 & no debugger & alt read/write support
|
||||
#define READ _READ_ALT
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu65C02 Cpu65C02_altRW
|
||||
#include "CPU/cpu65C02.h" // WDC 65C02
|
||||
#undef Cpu65C02
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef HEATMAP_X
|
||||
|
||||
//-----------------
|
||||
|
||||
// 6502 & debugger
|
||||
#define READ Heatmap_ReadByte_With_IO_F8xx(addr, uExecutedCycles)
|
||||
#define WRITE(value) Heatmap_WriteByte_With_IO_F8xx(addr, value, uExecutedCycles);
|
||||
|
||||
#define HEATMAP_X(address) Heatmap_X(address)
|
||||
|
||||
#include "CPU/cpu_heatmap.inl"
|
||||
@@ -500,6 +528,20 @@ static __forceinline bool IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn,
|
||||
|
||||
//-------
|
||||
|
||||
// 6502 & debugger & alt read/write support
|
||||
#define READ _READ_ALT
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu6502 Cpu6502_debug_altRW
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
#undef Cpu6502
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
|
||||
//-------
|
||||
|
||||
// 65C02 & debugger
|
||||
#define READ Heatmap_ReadByte(addr, uExecutedCycles)
|
||||
#define WRITE(value) Heatmap_WriteByte(addr, value, uExecutedCycles);
|
||||
|
||||
@@ -507,6 +549,19 @@ static __forceinline bool IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn,
|
||||
#include "CPU/cpu65C02.h" // WDC 65C02
|
||||
#undef Cpu65C02
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
|
||||
//-------
|
||||
|
||||
// 65C02 & debugger & alt read/write support
|
||||
#define READ _READ_ALT
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu65C02 Cpu65C02_debug_altRW
|
||||
#include "CPU/cpu65C02.h" // WDC 65C02
|
||||
#undef Cpu65C02
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef HEATMAP_X
|
||||
@@ -517,6 +572,14 @@ static uint32_t InternalCpuExecute(const uint32_t uTotalCycles, const bool bVide
|
||||
{
|
||||
if (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_BENCHMARK)
|
||||
{
|
||||
if (IsAppleIIe(GetApple2Type()) && (GetCardMgr().QueryAux() == CT_Empty || GetCardMgr().QueryAux() == CT_80Col))
|
||||
{
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
return Cpu6502_altRW(uTotalCycles, bVideoUpdate); // Apple //e
|
||||
else
|
||||
return Cpu65C02_altRW(uTotalCycles, bVideoUpdate); // Enhanced Apple //e
|
||||
}
|
||||
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
return Cpu6502(uTotalCycles, bVideoUpdate); // Apple ][, ][+, //e, Clones
|
||||
else
|
||||
@@ -525,6 +588,15 @@ static uint32_t InternalCpuExecute(const uint32_t uTotalCycles, const bool bVide
|
||||
else
|
||||
{
|
||||
_ASSERT(g_nAppMode == MODE_STEPPING || g_nAppMode == MODE_DEBUG);
|
||||
|
||||
if (IsAppleIIe(GetApple2Type()) && (GetCardMgr().QueryAux() == CT_Empty || GetCardMgr().QueryAux() == CT_80Col))
|
||||
{
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
return Cpu6502_debug_altRW(uTotalCycles, bVideoUpdate); // Apple //e
|
||||
else
|
||||
return Cpu65C02_debug_altRW(uTotalCycles, bVideoUpdate); // Enhanced Apple //e
|
||||
}
|
||||
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
return Cpu6502_debug(uTotalCycles, bVideoUpdate); // Apple ][, ][+, //e, Clones
|
||||
else
|
||||
|
||||
@@ -59,6 +59,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
? IORead[(addr>>4) & 0xFF](regs.pc,addr,0,0,uExecutedCycles) \
|
||||
: *(mem+addr) \
|
||||
)
|
||||
#define _READ_ALT ( \
|
||||
(memreadPageType[addr >> 8] == MEM_Normal) \
|
||||
? *(mem+addr) \
|
||||
: (memreadPageType[addr >> 8] == MEM_Aux1K) \
|
||||
? *(mem+TEXT_PAGE1_BEGIN+(addr&(TEXT_PAGE1_SIZE-1))) \
|
||||
: (memreadPageType[addr >> 8] == MEM_IORead) \
|
||||
? IORead[(addr >> 4) & 0xFF](regs.pc, addr, 0, 0, uExecutedCycles) \
|
||||
: MemReadFloatingBus(uExecutedCycles) \
|
||||
)
|
||||
#define _READ_WITH_IO_F8xx ( /* GH#827 */\
|
||||
((addr & 0xF000) == 0xC000) \
|
||||
? IORead[(addr>>4) & 0xFF](regs.pc,addr,0,0,uExecutedCycles) \
|
||||
@@ -81,6 +90,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
IOWrite[(addr>>4) & 0xFF](regs.pc,addr,1,(BYTE)(a),uExecutedCycles);\
|
||||
} \
|
||||
}
|
||||
#define _WRITE_ALT(a) { \
|
||||
{ \
|
||||
memdirty[memwriteDirtyPage[addr >> 8]] = 0xFF; \
|
||||
LPBYTE page = memwrite[addr >> 8]; \
|
||||
if (page) { \
|
||||
*(page+(addr & 0xFF)) = (BYTE)(a); \
|
||||
if (memVidHD) /* GH#997 */\
|
||||
*(memVidHD + addr) = (BYTE)(a); \
|
||||
} \
|
||||
else if ((addr & 0xF000) == 0xC000) \
|
||||
IOWrite[(addr>>4) & 0xFF](regs.pc,addr,1,(BYTE)(a),uExecutedCycles);\
|
||||
} \
|
||||
}
|
||||
#define _WRITE_WITH_IO_F8xx(a) { /* GH#827 */\
|
||||
if (addr >= 0xF800) \
|
||||
IO_F8xx(regs.pc,addr,1,(BYTE)(a),uExecutedCycles); \
|
||||
|
||||
+47
-14
@@ -178,76 +178,84 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
if (strcmp(lpCmdLine, "empty") == 0)
|
||||
{
|
||||
g_cmdLine.bSlotEmpty[slot] = true;
|
||||
if (strcmp(lpCmdLine, "diskii") == 0)
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "diskii") == 0)
|
||||
{
|
||||
g_cmdLine.slotInsert[slot] = CT_Disk2;
|
||||
if (strcmp(lpCmdLine, "diskii13") == 0)
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "diskii13") == 0)
|
||||
{
|
||||
g_cmdLine.slotInsert[slot] = CT_Disk2;
|
||||
g_cmdLine.slotInfo[slot].isDiskII13 = true;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "hdc") == 0)
|
||||
else if (strcmp(lpCmdLine, "hdc") == 0)
|
||||
{
|
||||
g_cmdLine.slotInsert[slot] = CT_GenericHDD;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "hdc-sp") == 0)
|
||||
else if (strcmp(lpCmdLine, "hdc-sp") == 0)
|
||||
{
|
||||
g_cmdLine.slotInsert[slot] = CT_GenericHDD;
|
||||
g_cmdLine.slotInfo[slot].useHdcFirmwareMode = HdcSmartPort;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "hdc-bm2") == 0)
|
||||
else if (strcmp(lpCmdLine, "hdc-bm2") == 0)
|
||||
{
|
||||
g_cmdLine.slotInsert[slot] = CT_GenericHDD;
|
||||
g_cmdLine.slotInfo[slot].useHdcFirmwareMode = HdcBlockMode2Devices;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "hdc-bm4") == 0)
|
||||
else if (strcmp(lpCmdLine, "hdc-bm4") == 0)
|
||||
{
|
||||
g_cmdLine.slotInsert[slot] = CT_GenericHDD;
|
||||
g_cmdLine.slotInfo[slot].useHdcFirmwareMode = HdcBlockMode4Devices;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0) // Support Saturn128 card in slot 1-7 too (GH#1279)
|
||||
else if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0) // Support Saturn128 card in slot 1-7 too (GH#1279)
|
||||
{
|
||||
g_cmdLine.slotInsert[slot] = CT_Saturn128K;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "megaaudio") == 0)
|
||||
else if (strcmp(lpCmdLine, "megaaudio") == 0)
|
||||
{
|
||||
g_cmdLine.slotInsert[slot] = CT_MegaAudio;
|
||||
g_cmdLine.supportExtraMBCardTypes = true;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "sdmusic") == 0)
|
||||
else if (strcmp(lpCmdLine, "sdmusic") == 0)
|
||||
{
|
||||
g_cmdLine.slotInsert[slot] = CT_SDMusic;
|
||||
g_cmdLine.supportExtraMBCardTypes = true;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "6522a-bad") == 0)
|
||||
else if (strcmp(lpCmdLine, "6522a-bad") == 0)
|
||||
{
|
||||
g_cmdLine.slotInfo[slot].useBad6522A = true;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "6522b-bad") == 0)
|
||||
else if (strcmp(lpCmdLine, "6522b-bad") == 0)
|
||||
{
|
||||
g_cmdLine.slotInfo[slot].useBad6522B = true;
|
||||
}
|
||||
if (strcmp(lpCmdLine, "parallel") == 0)
|
||||
else if (strcmp(lpCmdLine, "parallel") == 0)
|
||||
{
|
||||
if (slot == SLOT1)
|
||||
g_cmdLine.slotInsert[slot] = CT_GenericPrinter;
|
||||
else
|
||||
LogFileOutput("Parallel Printer card currently only supported in slot 1\n");
|
||||
}
|
||||
if (strcmp(lpCmdLine, "ssc") == 0)
|
||||
else if (strcmp(lpCmdLine, "ssc") == 0)
|
||||
{
|
||||
if (slot == SLOT2)
|
||||
g_cmdLine.slotInsert[slot] = CT_SSC;
|
||||
else
|
||||
LogFileOutput("SSC currently only supported in slot 2\n");
|
||||
}
|
||||
if (strcmp(lpCmdLine, "vidhd") == 0)
|
||||
else 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
|
||||
{
|
||||
LogFileOutput("Unsupported slot-%d card: %s\n", slot, lpCmdLine);
|
||||
}
|
||||
}
|
||||
else if (lpCmdLine[3] == 'd' && (lpCmdLine[4] == '1' || lpCmdLine[4] == '2')) // -s[1..7]d[1|2] <dsk-image>
|
||||
{
|
||||
@@ -289,6 +297,31 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
|
||||
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
|
||||
}
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-aux") == 0)
|
||||
{
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
if (strcmp(lpCmdLine, "empty") == 0)
|
||||
{
|
||||
g_cmdLine.auxSlotEmpty = true;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "std80") == 0)
|
||||
{
|
||||
g_cmdLine.auxSlotInsert = CT_80Col;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "ext80") == 0)
|
||||
{
|
||||
g_cmdLine.auxSlotInsert = CT_Extended80Col;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "rw3") == 0)
|
||||
{
|
||||
g_cmdLine.auxSlotInsert = CT_RamWorksIII;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFileOutput("Unsupported aux slot card: %s\n", lpCmdLine);
|
||||
}
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-harddisknumblocks") == 0) // number of blocks to report for ProDOS
|
||||
{
|
||||
lpCmdLine = GetCurrArg(lpNextArg);
|
||||
|
||||
@@ -60,6 +60,8 @@ struct CmdLine
|
||||
bestFullScreenResolution = false;
|
||||
userSpecifiedWidth = 0;
|
||||
userSpecifiedHeight = 0;
|
||||
auxSlotEmpty = false;
|
||||
auxSlotInsert = CT_Empty;
|
||||
|
||||
for (UINT i = 0; i < NUM_SLOTS; i++)
|
||||
{
|
||||
@@ -115,6 +117,8 @@ struct CmdLine
|
||||
UINT userSpecifiedHeight;
|
||||
std::string wavFileSpeaker;
|
||||
std::string wavFileMockingboard;
|
||||
bool auxSlotEmpty;
|
||||
SS_CARDTYPE auxSlotInsert;
|
||||
};
|
||||
|
||||
bool ProcessCmdLine(LPSTR lpCmdLine);
|
||||
|
||||
@@ -219,6 +219,11 @@ inline bool IsApple2PlusOrClone(eApple2Type type) // Apple ][,][+,][J-Plus or cl
|
||||
return (type & (APPLE2E_MASK|APPLE2C_MASK)) == 0;
|
||||
}
|
||||
|
||||
inline bool IsAppleIIe(eApple2Type type) // Apple //e,Enhanced//e or clone //e,Enhanced//e
|
||||
{
|
||||
return type & APPLE2E_MASK;
|
||||
}
|
||||
|
||||
inline bool IsAppleIIeOrAbove(eApple2Type type) // Apple //e,Enhanced//e,//c or clone //e,Enhanced//e
|
||||
{
|
||||
return !IsApple2PlusOrClone(type);
|
||||
|
||||
@@ -6811,13 +6811,13 @@ enum ViewVideoPage_t
|
||||
VIEW_PAGE_5 // Pseudo
|
||||
};
|
||||
|
||||
Update_t _ViewOutput ( ViewVideoPage_t iPage, int bVideoModeFlags )
|
||||
static Update_t _ViewOutput ( ViewVideoPage_t iPage, UINT bVideoModeFlags )
|
||||
{
|
||||
switch ( iPage )
|
||||
{
|
||||
case VIEW_PAGE_X:
|
||||
bVideoModeFlags |= !GetVideo().VideoGetSWPAGE2() ? 0 : VF_PAGE2;
|
||||
bVideoModeFlags |= !GetVideo().VideoGetSWMIXED() ? 0 : VF_MIXED;
|
||||
bVideoModeFlags |= GetVideo().VideoGetSWPAGE2() ? VF_PAGE2 : 0;
|
||||
bVideoModeFlags |= GetVideo().VideoGetSWMIXED() ? VF_MIXED : 0;
|
||||
break; // Page Current & current MIXED state
|
||||
case VIEW_PAGE_0: bVideoModeFlags |= VF_PAGE0; break; // Pseudo Page 0 ($0000)
|
||||
case VIEW_PAGE_1: bVideoModeFlags |= 0 ; break; // Hardware Page 1 ($2000), NOTE: VF_HIRES will be passed in
|
||||
@@ -6830,6 +6830,8 @@ Update_t _ViewOutput ( ViewVideoPage_t iPage, int bVideoModeFlags )
|
||||
break;
|
||||
}
|
||||
|
||||
bVideoModeFlags |= GetVideo().VideoGet80COLAUXEMPTY() ? VF_80COL_AUX_EMPTY : 0; // Preserve this flag
|
||||
|
||||
DebugVideoMode::Instance().Set(bVideoModeFlags);
|
||||
GetFrame().VideoRefreshScreen( bVideoModeFlags, true );
|
||||
return UPDATE_NOTHING; // intentional
|
||||
|
||||
+322
-69
@@ -200,9 +200,32 @@ SOFT SWITCH STATUS FLAGS
|
||||
// . memshadow[0] = &memaux[0x0000]
|
||||
// . memshadow[1] = &memaux[0x0100]
|
||||
//
|
||||
// memreadPageType (used by _READ_ALT for CPU emulation)
|
||||
// - 1 byte entry per 256-byte page
|
||||
// - Required specifically for when:
|
||||
// . the aux slot is empty, so that it can return floating-bus
|
||||
// . the aux slot has an 80-col(1KiB) card, so reads are restricted to this mem space
|
||||
//
|
||||
// memwriteDirtyPage (used by _WRITE_ALT for CPU emulation)
|
||||
// - 1 byte entry per 256-byte page
|
||||
// - Required specifically for the 80-Col(1KiB) card so that writes *outside* the 1KiB area only set dirty pages *inside* the 1KiB area!
|
||||
//
|
||||
// Apple //e 64K (aux slot is empty or has 80-Col(1KiB) card) - GH#1341
|
||||
// . MMU still supports RAMRDOFF/RAMRDON/RAMWRTOFF/RAMWRTON/ALTZPOFF/ALTZPON
|
||||
// . DHIRESON: no affect, as the Ext 80-col card enables this (so no DHGR or DGR - although a full VidHD would support this)
|
||||
// . NB. With a VidHD card, then SHR video works correctly to HDMI-out
|
||||
// . Apple //e 64K (aux slot is empty)
|
||||
// . aux writes still get written to memaux (write-only memory! Used by VidHD card)
|
||||
// . aux reads are from floating bus
|
||||
// . Apple //e 64K (w/ 80-Col(1KiB) card in aux slot)
|
||||
// . aux reads & writes are to the 1KiB of aux mem
|
||||
// . aux writes outside of the aux TEXT1 get written to memaux (if there's a VidHD card)
|
||||
//
|
||||
|
||||
static LPBYTE memshadow[0x100];
|
||||
LPBYTE memwrite[0x100];
|
||||
static LPBYTE memshadow[0x100];
|
||||
LPBYTE memwrite[0x100];
|
||||
BYTE memreadPageType[0x100];
|
||||
BYTE memwriteDirtyPage[0x100];
|
||||
|
||||
iofunction IORead[256];
|
||||
iofunction IOWrite[256];
|
||||
@@ -320,7 +343,7 @@ void SetExpansionMemType(const SS_CARDTYPE type)
|
||||
else
|
||||
newSlot0Card = CT_Empty; // NB. No slot0 for //e
|
||||
}
|
||||
else if (type == CT_RamWorksIII)
|
||||
else if (type == CT_80Col || type == CT_Extended80Col || type == CT_RamWorksIII)
|
||||
{
|
||||
g_MemTypeAppleIIe = type;
|
||||
if (IsApple2PlusOrClone(GetApple2Type()))
|
||||
@@ -328,6 +351,20 @@ void SetExpansionMemType(const SS_CARDTYPE type)
|
||||
else
|
||||
newSlotAuxCard = type;
|
||||
}
|
||||
else if (type == CT_Empty) // NB. This sets global state depending on machine type
|
||||
{
|
||||
if (IsApple2PlusOrClone(GetApple2Type()))
|
||||
{
|
||||
g_MemTypeAppleII = CT_Empty;
|
||||
g_MemTypeAppleIIPlus = CT_Empty;
|
||||
newSlot0Card = CT_Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_MemTypeAppleIIe = CT_Empty;
|
||||
newSlotAuxCard = CT_Empty;
|
||||
}
|
||||
}
|
||||
|
||||
GetCardMgr().Insert(SLOT0, newSlot0Card);
|
||||
GetCardMgr().InsertAux(newSlotAuxCard);
|
||||
@@ -1155,6 +1192,8 @@ static void ResetPaging(BOOL initialize)
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static void UpdatePagingForAltRW(void);
|
||||
|
||||
void MemUpdatePaging(BOOL initialize)
|
||||
{
|
||||
UpdatePaging(initialize);
|
||||
@@ -1181,7 +1220,12 @@ static void UpdatePaging(BOOL initialize)
|
||||
}
|
||||
|
||||
for (loop = 0x00; loop < 0x02; loop++)
|
||||
memshadow[loop] = SW_ALTZP ? memaux+(loop << 8) : memmain+(loop << 8);
|
||||
{
|
||||
memshadow[loop] = SW_ALTZP ? memaux + (loop << 8) : memmain + (loop << 8);
|
||||
|
||||
// re-init this, since for //e aux slot 80-col(1KiB) card, this can change
|
||||
memwrite[loop] = mem + (loop << 8);
|
||||
}
|
||||
|
||||
for (loop = 0x02; loop < 0xC0; loop++)
|
||||
{
|
||||
@@ -1289,6 +1333,106 @@ static void UpdatePaging(BOOL initialize)
|
||||
memcpy(mem+(loop << 8),memshadow[loop],256);
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePagingForAltRW();
|
||||
}
|
||||
|
||||
// For Cpu6502_altRW() & Cpu65C02_altRW()
|
||||
static void UpdatePagingForAltRW(void)
|
||||
{
|
||||
UINT loop;
|
||||
|
||||
const BYTE memType = (GetCardMgr().QueryAux() == CT_Empty) ? MEM_FloatingBus
|
||||
: (GetCardMgr().QueryAux() == CT_80Col) ? MEM_Aux1K
|
||||
: MEM_Normal;
|
||||
|
||||
for (loop = 0x00; loop < 0x02; loop++)
|
||||
memreadPageType[loop] = SW_ALTZP ? memType : MEM_Normal;
|
||||
|
||||
for (loop = 0x02; loop < 0xC0; loop++)
|
||||
memreadPageType[loop] = SW_AUXREAD ? memType : MEM_Normal;
|
||||
|
||||
for (loop = 0xC0; loop < 0xD0; loop++)
|
||||
memreadPageType[loop] = MEM_IORead;
|
||||
|
||||
for (loop = 0xD0; loop < 0x100; loop++)
|
||||
memreadPageType[loop] = (SW_HIGHRAM && SW_ALTZP) ? memType : MEM_Normal;
|
||||
|
||||
if (SW_80STORE)
|
||||
{
|
||||
for (loop = 0x04; loop < 0x08; loop++)
|
||||
memreadPageType[loop] = SW_PAGE2 ? memType : MEM_Normal;
|
||||
|
||||
for (loop = 0x20; loop < 0x40; loop++)
|
||||
memreadPageType[loop] = (SW_PAGE2 && SW_HIRES) ? memType : MEM_Normal;
|
||||
}
|
||||
|
||||
if (GetCardMgr().QueryAux() == CT_80Col)
|
||||
{
|
||||
// Overide the MEM_Aux1K set above (slightly quicker code-path during CPU emulation)
|
||||
if (SW_AUXREAD || (SW_80STORE && SW_PAGE2))
|
||||
for (loop = 0x04; loop < 0x08; loop++)
|
||||
memreadPageType[loop] = MEM_Normal;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for (loop = 0x00; loop<0x100; loop++)
|
||||
memwriteDirtyPage[loop] = loop;
|
||||
|
||||
if (GetCardMgr().QueryAux() == CT_80Col)
|
||||
{
|
||||
// Dirty pages are only in the 1K range
|
||||
const BYTE kTextPage = TEXT_PAGE1_BEGIN >> 8;
|
||||
|
||||
for (loop = 0x00; loop < 0x02; loop++)
|
||||
if (SW_ALTZP)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
|
||||
for (loop = 0x02; loop < 0xC0; loop++)
|
||||
if (SW_AUXWRITE)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
|
||||
for (loop = 0xD0; loop < 0x100; loop++)
|
||||
if (SW_HIGHRAM && SW_ALTZP)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
|
||||
if (SW_80STORE && SW_PAGE2)
|
||||
{
|
||||
for (loop = 0x04; loop < 0x08; loop++)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
|
||||
for (loop = 0x20; loop < 0x40; loop++)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
}
|
||||
|
||||
// Map all aux writes into the 1K memory
|
||||
// . Need to combine with memwriteDirtyPage[], to that the right page is marked as dirty
|
||||
|
||||
for (loop = 0x00; loop < 0x02; loop++)
|
||||
if (SW_ALTZP)
|
||||
memwrite[loop] = memaux + TEXT_PAGE1_BEGIN + ((loop & 3) << 8);
|
||||
|
||||
for (loop = 0x02; loop < 0xC0; loop++)
|
||||
if (SW_AUXWRITE)
|
||||
memwrite[loop] = (memwrite[loop] - (loop << 8)) + TEXT_PAGE1_BEGIN + ((loop & 3) << 8);
|
||||
|
||||
for (loop = 0xD0; loop < 0x100; loop++)
|
||||
if (SW_HIGHRAM && SW_ALTZP)
|
||||
memwrite[loop] = memaux + TEXT_PAGE1_BEGIN + ((loop & 3) << 8);
|
||||
|
||||
if (SW_80STORE && SW_PAGE2)
|
||||
{
|
||||
for (loop = 0x04; loop < 0x08; loop++)
|
||||
memwrite[loop] = mem + TEXT_PAGE1_BEGIN + ((loop & 3) << 8);
|
||||
|
||||
if (SW_HIRES)
|
||||
{
|
||||
for (loop = 0x20; loop < 0x40; loop++)
|
||||
memwrite[loop] = mem + TEXT_PAGE1_BEGIN + ((loop & 3) << 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1364,13 +1508,20 @@ static LPBYTE MemGetPtrBANK1(const WORD offset, const LPBYTE pMemBase)
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
LPBYTE MemGetAuxPtr(const WORD offset)
|
||||
#if 0 // Unused
|
||||
LPBYTE MemGetAuxPtrWithLC(const WORD offset)
|
||||
{
|
||||
LPBYTE lpMem = MemGetPtrBANK1(offset, memaux);
|
||||
if (lpMem)
|
||||
return lpMem;
|
||||
|
||||
lpMem = (memshadow[(offset >> 8)] == (memaux+(offset & 0xFF00)))
|
||||
return MemGetAuxPtr(offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
LPBYTE MemGetAuxPtr(const WORD offset)
|
||||
{
|
||||
LPBYTE lpMem = (memshadow[(offset >> 8)] == (memaux+(offset & 0xFF00)))
|
||||
? mem+offset // Return 'mem' copy if possible, as page could be dirty
|
||||
: memaux+offset;
|
||||
|
||||
@@ -1422,15 +1573,20 @@ LPBYTE MemGetAuxPtr(const WORD offset)
|
||||
// . if no, then return memmain, as the mem(cache) isn't involved in memmain (any writes will go directly to this backing-store).
|
||||
//
|
||||
|
||||
LPBYTE MemGetMainPtr(const WORD offset)
|
||||
LPBYTE MemGetMainPtrWithLC(const WORD offset)
|
||||
{
|
||||
LPBYTE lpMem = MemGetPtrBANK1(offset, memmain);
|
||||
if (lpMem)
|
||||
return lpMem;
|
||||
|
||||
return (memshadow[(offset >> 8)] == (memmain+(offset & 0xFF00)))
|
||||
? mem+offset // Return 'mem' copy if possible, as page could be dirty
|
||||
: memmain+offset;
|
||||
return MemGetMainPtr(offset);
|
||||
}
|
||||
|
||||
LPBYTE MemGetMainPtr(const WORD offset)
|
||||
{
|
||||
return (memshadow[(offset >> 8)] == (memmain + (offset & 0xFF00)))
|
||||
? mem + offset // Return 'mem' copy if possible, as page could be dirty
|
||||
: memmain + offset;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -1488,7 +1644,7 @@ LPBYTE MemGetCxRomPeripheral()
|
||||
// . false: I/O memory or floating bus
|
||||
bool MemIsAddrCodeMemory(const USHORT addr)
|
||||
{
|
||||
if (addr < 0xC000 || addr > FIRMWARE_EXPANSION_END) // Assume all A][ types have at least 48K
|
||||
if (addr < APPLE_IO_BEGIN || addr > FIRMWARE_EXPANSION_END) // Assume all A][ types have at least 48K
|
||||
return true;
|
||||
|
||||
if (addr < APPLE_SLOT_BEGIN) // [$C000..C0FF]
|
||||
@@ -1665,6 +1821,7 @@ static LPBYTE AllocMemImage(void)
|
||||
void MemInitialize()
|
||||
{
|
||||
// ALLOCATE MEMORY FOR THE APPLE MEMORY IMAGE AND ASSOCIATED DATA STRUCTURES
|
||||
// NB. alloc memaux even if a IIe with an empty aux slot - writes still go to memaux, but reads are from floating bus
|
||||
memaux = ALIGNED_ALLOC(_6502_MEM_LEN); // NB. alloc even if model is Apple II/II+, since it's used by VidHD card
|
||||
memmain = ALIGNED_ALLOC(_6502_MEM_LEN);
|
||||
memimage = AllocMemImage();
|
||||
@@ -1940,10 +2097,13 @@ void MemInitializeFromSnapshot(void)
|
||||
|
||||
memVidHD = NULL;
|
||||
|
||||
if (IsApple2PlusOrClone(GetApple2Type()) && (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD))
|
||||
if ((GetCardMgr().QuerySlot(SLOT3) == CT_VidHD))
|
||||
{
|
||||
VidHDCard& vidHD = dynamic_cast<VidHDCard&>(GetCardMgr().GetRef(SLOT3));
|
||||
memVidHD = vidHD.IsWriteAux() ? memaux : NULL;
|
||||
if (IsApple2PlusOrClone(GetApple2Type()) || IsIIeWithoutAuxMem())
|
||||
{
|
||||
VidHDCard& vidHD = dynamic_cast<VidHDCard&>(GetCardMgr().GetRef(SLOT3));
|
||||
memVidHD = vidHD.IsWriteAux() ? memaux : NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2120,19 +2280,39 @@ void MemReset()
|
||||
|
||||
//===========================================================================
|
||||
|
||||
BYTE MemReadFloatingBus(const ULONG uExecutedCycles)
|
||||
static BYTE ReadFloatingBus(const ULONG uExecutedCycles, const bool fullSpeed, const bool auxEmpty = false)
|
||||
{
|
||||
return mem[ NTSC_VideoGetScannerAddress(uExecutedCycles) ]; // OK: This does the 2-cycle adjust for ANSI STORY (End Credits)
|
||||
BYTE* pMain = MemGetMainPtr(0x0000);
|
||||
|
||||
if (auxEmpty && (SW_AUXREAD || (SW_80STORE && SW_PAGE2)))
|
||||
{
|
||||
// Special case: Aux slot empty and in 80-col mode: video generator reading floating bus. (GH#1341)
|
||||
// Can't rely on using "mem" (ie. the CPU read cache), since "80STORE && PAGE2" will have switched in the non-existent memory from "memaux"!
|
||||
// NB. Only care about $400-7FF (ie. TEXT page 1)
|
||||
pMain = memmain;
|
||||
}
|
||||
|
||||
return pMain[NTSC_VideoGetScannerAddress(uExecutedCycles, fullSpeed)]; // OK: This does the 2-cycle adjust for ANSI STORY (End Credits)
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BYTE MemReadFloatingBus(const ULONG uExecutedCycles)
|
||||
{
|
||||
return ReadFloatingBus(uExecutedCycles, g_bFullSpeed);
|
||||
}
|
||||
|
||||
BYTE MemReadFloatingBus(const BYTE highbit, const ULONG uExecutedCycles)
|
||||
{
|
||||
BYTE r = MemReadFloatingBus(uExecutedCycles);
|
||||
BYTE r = ReadFloatingBus(uExecutedCycles, g_bFullSpeed);
|
||||
return (r & ~0x80) | (highbit ? 0x80 : 0);
|
||||
}
|
||||
|
||||
BYTE MemReadFloatingBusFromNTSC(void)
|
||||
{
|
||||
// fullspeed=false: to avoid NTSC_VideoGetScannerAddress() calling NTSC_VideoClockResync()
|
||||
// NB. g_bFullSpeed only true when doing NTSC_VideoRedrawWholeScreen()
|
||||
return ReadFloatingBus(0, false, true);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
//#define DEBUG_FLIP_TIMINGS
|
||||
@@ -2206,6 +2386,12 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (GetCardMgr().QuerySlot(SLOT3) == CT_VidHD && GetCardMgr().QueryAux() == CT_80Col)
|
||||
{
|
||||
// NB. if aux slot is empty, then writes already occur to memaux
|
||||
memVidHD = MemIsWriteAux(g_memmode) ? memaux : NULL;
|
||||
}
|
||||
}
|
||||
else // Apple ][,][+,][J-Plus or clone ][,][+
|
||||
{
|
||||
@@ -2274,6 +2460,25 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
|
||||
|
||||
//===========================================================================
|
||||
|
||||
// NB. Not particularly accurate (but good enough for now)
|
||||
// . 80STORE && PAGE2 just means that writes occur to aux $400-7FF (and $2000-$3FFF if HIRES=1), not the entire aux 64K
|
||||
|
||||
bool MemIsWriteAux(uint32_t memMode)
|
||||
{
|
||||
return (memMode & MF_AUXWRITE) || // Write to aux: $200-$BFFF
|
||||
((memMode & MF_80STORE) && (memMode & MF_PAGE2)); // Write to aux: $400-$7FF and $2000-$3FFF
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
bool IsIIeWithoutAuxMem(void)
|
||||
{
|
||||
return IsAppleIIe(GetApple2Type()) &&
|
||||
(GetCardMgr().QueryAux() == CT_Empty || GetCardMgr().QueryAux() == CT_80Col);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
bool MemOptimizeForModeChanging(WORD programcounter, WORD address)
|
||||
{
|
||||
if (IsAppleIIeOrAbove(GetApple2Type()))
|
||||
@@ -2380,8 +2585,10 @@ static const UINT kUNIT_AUXSLOT_VER = 2;
|
||||
// Unit version history:
|
||||
// 2: Added: RGB card state
|
||||
// 3: Extended: RGB card state ('80COL changed')
|
||||
static const UINT kUNIT_CARD_VER = 3;
|
||||
// 4: Support aux empty or aux 1KiB card
|
||||
static const UINT kUNIT_CARD_VER = 4;
|
||||
|
||||
#define SS_YAML_VALUE_CARD_EMPTY "Empty"
|
||||
#define SS_YAML_VALUE_CARD_80COL "80 Column"
|
||||
#define SS_YAML_VALUE_CARD_EXTENDED80COL "Extended 80 Column"
|
||||
#define SS_YAML_VALUE_CARD_RAMWORKSIII "RamWorksIII"
|
||||
@@ -2559,7 +2766,6 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT unitVersion)
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Switch from checking 'g_uMaxExPages == n' to using g_SlotAux
|
||||
void MemSaveSnapshotAux(YamlSaveHelper& yamlSaveHelper)
|
||||
{
|
||||
if (IS_APPLE2)
|
||||
@@ -2578,23 +2784,40 @@ void MemSaveSnapshotAux(YamlSaveHelper& yamlSaveHelper)
|
||||
{
|
||||
YamlSaveHelper::Label unitState(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
|
||||
|
||||
std::string card = g_uMaxExPages == 0 ? SS_YAML_VALUE_CARD_80COL : // todo: support empty slot
|
||||
g_uMaxExPages == 1 ? SS_YAML_VALUE_CARD_EXTENDED80COL :
|
||||
SS_YAML_VALUE_CARD_RAMWORKSIII;
|
||||
const SS_CARDTYPE cardType = GetCardMgr().QueryAux();
|
||||
std::string card = cardType == CT_Empty ? SS_YAML_VALUE_CARD_EMPTY :
|
||||
cardType == CT_80Col ? SS_YAML_VALUE_CARD_80COL :
|
||||
cardType == CT_Extended80Col ? SS_YAML_VALUE_CARD_EXTENDED80COL :
|
||||
cardType == CT_RamWorksIII ? SS_YAML_VALUE_CARD_RAMWORKSIII :
|
||||
"";
|
||||
_ASSERT(!card.empty());
|
||||
|
||||
yamlSaveHelper.SaveString(SS_YAML_KEY_CARD, card.c_str());
|
||||
yamlSaveHelper.Save("%s: %d\n", SS_YAML_KEY_VERSION, kUNIT_CARD_VER);
|
||||
|
||||
// Card state
|
||||
if (cardType == CT_80Col)
|
||||
{
|
||||
YamlSaveHelper::Label cardState(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
|
||||
|
||||
// 1KiB memory
|
||||
{
|
||||
const UINT bank = 1;
|
||||
LPBYTE pMemBase = MemGetBankPtr(bank);
|
||||
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", MemGetSnapshotAuxMemStructName().c_str());
|
||||
yamlSaveHelper.SaveMemory(pMemBase + TEXT_PAGE1_BEGIN, TEXT_PAGE1_SIZE);
|
||||
}
|
||||
}
|
||||
else if (cardType == CT_Extended80Col || cardType == CT_RamWorksIII)
|
||||
{
|
||||
YamlSaveHelper::Label cardState(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
|
||||
|
||||
yamlSaveHelper.Save("%s: 0x%02X # [0,1..7F] 0=no aux mem, 1=128K system, etc\n", SS_YAML_KEY_NUMAUXBANKS, g_uMaxExPages);
|
||||
yamlSaveHelper.Save("%s: 0x%02X # [ 0..7E] 0=memaux\n", SS_YAML_KEY_ACTIVEAUXBANK, g_uActiveBank);
|
||||
|
||||
for(UINT uBank = 1; uBank <= g_uMaxExPages; uBank++)
|
||||
for(UINT bank = 1; bank <= g_uMaxExPages; bank++)
|
||||
{
|
||||
MemSaveSnapshotMemory(yamlSaveHelper, false, uBank);
|
||||
MemSaveSnapshotMemory(yamlSaveHelper, false, bank);
|
||||
}
|
||||
|
||||
RGB_SaveSnapshot(yamlSaveHelper);
|
||||
@@ -2602,66 +2825,92 @@ void MemSaveSnapshotAux(YamlSaveHelper& yamlSaveHelper)
|
||||
}
|
||||
}
|
||||
|
||||
static void MemLoadSnapshotAuxCommon(YamlLoadHelper& yamlLoadHelper, const std::string& card)
|
||||
static SS_CARDTYPE MemLoadSnapshotAuxCommon(YamlLoadHelper& yamlLoadHelper, const std::string& card)
|
||||
{
|
||||
// "State"
|
||||
UINT numAuxBanks = yamlLoadHelper.LoadUint(SS_YAML_KEY_NUMAUXBANKS);
|
||||
UINT activeAuxBank = yamlLoadHelper.LoadUint(SS_YAML_KEY_ACTIVEAUXBANK);
|
||||
g_uMaxExPages = 1; // Must be at least 1 (for aux mem) - regardless of Apple2 type!
|
||||
g_uActiveBank = 0;
|
||||
_ASSERT(MemGetBankPtr(1, false)); // Ensure there is always aux mem (eg. for CT_80Col or CT_VidHD)
|
||||
|
||||
SS_CARDTYPE type = CT_Empty;
|
||||
if (card == SS_YAML_VALUE_CARD_80COL)
|
||||
{
|
||||
type = CT_80Col;
|
||||
if (numAuxBanks != 0 || activeAuxBank != 0)
|
||||
throw std::runtime_error(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
|
||||
}
|
||||
SS_CARDTYPE cardType;
|
||||
if (card == SS_YAML_VALUE_CARD_EMPTY)
|
||||
cardType = CT_Empty;
|
||||
else if (card == SS_YAML_VALUE_CARD_80COL)
|
||||
cardType = CT_80Col;
|
||||
else if (card == SS_YAML_VALUE_CARD_EXTENDED80COL)
|
||||
{
|
||||
type = CT_Extended80Col;
|
||||
if (numAuxBanks != 1 || activeAuxBank != 0)
|
||||
throw std::runtime_error(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
|
||||
}
|
||||
cardType = CT_Extended80Col;
|
||||
else if (card == SS_YAML_VALUE_CARD_RAMWORKSIII)
|
||||
{
|
||||
type = CT_RamWorksIII;
|
||||
if (numAuxBanks < 2 || numAuxBanks > 0x7F || (activeAuxBank+1) > numAuxBanks)
|
||||
throw std::runtime_error(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
|
||||
}
|
||||
cardType = CT_RamWorksIII;
|
||||
else
|
||||
{
|
||||
// todo: support empty slot
|
||||
type = CT_Empty;
|
||||
throw std::runtime_error(SS_YAML_KEY_UNIT ": AuxSlot: Unknown card: " + card);
|
||||
|
||||
// "State"
|
||||
UINT numAuxBanks = 0, activeAuxBank = 0;
|
||||
if (card == SS_YAML_VALUE_CARD_EXTENDED80COL || card == SS_YAML_VALUE_CARD_RAMWORKSIII)
|
||||
{
|
||||
numAuxBanks = yamlLoadHelper.LoadUint(SS_YAML_KEY_NUMAUXBANKS);
|
||||
activeAuxBank = yamlLoadHelper.LoadUint(SS_YAML_KEY_ACTIVEAUXBANK);
|
||||
}
|
||||
|
||||
g_uMaxExPages = numAuxBanks;
|
||||
g_uActiveBank = activeAuxBank;
|
||||
|
||||
//
|
||||
|
||||
for(UINT uBank = 1; uBank <= g_uMaxExPages; uBank++)
|
||||
if (cardType == CT_Empty)
|
||||
{
|
||||
LPBYTE pBank = MemGetBankPtr(uBank, false);
|
||||
if (!pBank)
|
||||
{
|
||||
pBank = RWpages[uBank-1] = ALIGNED_ALLOC(_6502_MEM_LEN);
|
||||
}
|
||||
|
||||
// "Auxiliary Memory Bankxx"
|
||||
std::string auxMemName = MemGetSnapshotAuxMemStructName() + ByteToHexStr(uBank-1);
|
||||
// nothing to do here
|
||||
}
|
||||
else if (cardType == CT_80Col)
|
||||
{
|
||||
const UINT bank1 = 1;
|
||||
LPBYTE pBank = MemGetBankPtr(bank1, false);
|
||||
_ASSERT(pBank);
|
||||
|
||||
std::string auxMemName = MemGetSnapshotAuxMemStructName();
|
||||
if (!yamlLoadHelper.GetSubMap(auxMemName))
|
||||
throw std::runtime_error("Memory: Missing map name: " + auxMemName);
|
||||
|
||||
yamlLoadHelper.LoadMemory(pBank, _6502_MEM_LEN);
|
||||
yamlLoadHelper.LoadMemory(pBank + TEXT_PAGE1_BEGIN, TEXT_PAGE1_SIZE);
|
||||
|
||||
yamlLoadHelper.PopMap();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cardType == CT_Extended80Col)
|
||||
{
|
||||
if (numAuxBanks != 1 || activeAuxBank != 0)
|
||||
throw std::runtime_error(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
|
||||
}
|
||||
else // cardType == CT_RamWorksIII
|
||||
{
|
||||
if (numAuxBanks < 2 || numAuxBanks > 0x7F || (activeAuxBank + 1) > numAuxBanks)
|
||||
throw std::runtime_error(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
|
||||
}
|
||||
|
||||
GetCardMgr().InsertAux(type);
|
||||
g_uMaxExPages = numAuxBanks;
|
||||
g_uActiveBank = activeAuxBank;
|
||||
|
||||
//
|
||||
|
||||
for (UINT bank = 1; bank <= g_uMaxExPages; bank++)
|
||||
{
|
||||
LPBYTE pBank = MemGetBankPtr(bank, false);
|
||||
if (!pBank)
|
||||
pBank = RWpages[bank - 1] = ALIGNED_ALLOC(_6502_MEM_LEN);
|
||||
|
||||
// "Auxiliary Memory Bankxx"
|
||||
std::string auxMemName = MemGetSnapshotAuxMemStructName() + ByteToHexStr(bank - 1);
|
||||
|
||||
if (!yamlLoadHelper.GetSubMap(auxMemName))
|
||||
throw std::runtime_error("Memory: Missing map name: " + auxMemName);
|
||||
|
||||
yamlLoadHelper.LoadMemory(pBank, _6502_MEM_LEN);
|
||||
|
||||
yamlLoadHelper.PopMap();
|
||||
}
|
||||
}
|
||||
|
||||
GetCardMgr().InsertAux(cardType);
|
||||
|
||||
memaux = RWpages[g_uActiveBank];
|
||||
// NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v2()
|
||||
|
||||
return cardType;
|
||||
}
|
||||
|
||||
static void MemLoadSnapshotAuxVer1(YamlLoadHelper& yamlLoadHelper)
|
||||
@@ -2675,12 +2924,16 @@ static void MemLoadSnapshotAuxVer2(YamlLoadHelper& yamlLoadHelper)
|
||||
std::string card = yamlLoadHelper.LoadString(SS_YAML_KEY_CARD);
|
||||
UINT cardVersion = yamlLoadHelper.LoadUint(SS_YAML_KEY_VERSION);
|
||||
|
||||
if (!yamlLoadHelper.GetSubMap(std::string(SS_YAML_KEY_STATE)))
|
||||
throw std::runtime_error(SS_YAML_KEY_UNIT ": Expected sub-map name: " SS_YAML_KEY_STATE);
|
||||
if (card != SS_YAML_VALUE_CARD_EMPTY)
|
||||
{
|
||||
if (!yamlLoadHelper.GetSubMap(std::string(SS_YAML_KEY_STATE)))
|
||||
throw std::runtime_error(SS_YAML_KEY_UNIT ": Expected sub-map name: " SS_YAML_KEY_STATE);
|
||||
}
|
||||
|
||||
MemLoadSnapshotAuxCommon(yamlLoadHelper, card);
|
||||
SS_CARDTYPE cardType = MemLoadSnapshotAuxCommon(yamlLoadHelper, card);
|
||||
|
||||
RGB_LoadSnapshot(yamlLoadHelper, cardVersion);
|
||||
if (card == SS_YAML_VALUE_CARD_EXTENDED80COL || card == SS_YAML_VALUE_CARD_RAMWORKSIII)
|
||||
RGB_LoadSnapshot(yamlLoadHelper, cardVersion);
|
||||
}
|
||||
|
||||
bool MemLoadSnapshotAux(YamlLoadHelper& yamlLoadHelper, UINT unitVersion)
|
||||
|
||||
+9
-1
@@ -36,11 +36,16 @@ enum MemoryInitPattern_e
|
||||
, NUM_MIP
|
||||
};
|
||||
|
||||
// For Cpu6502_altRead() & Cpu65C02_altRead()
|
||||
enum { MEM_Normal = 0, MEM_IORead, MEM_FloatingBus, MEM_Aux1K, MEM_NoSlotClock };
|
||||
|
||||
typedef BYTE (__stdcall *iofunction)(WORD nPC, WORD nAddr, BYTE nWriteFlag, BYTE nWriteValue, ULONG nExecutedCycles);
|
||||
|
||||
extern iofunction IORead[256];
|
||||
extern iofunction IOWrite[256];
|
||||
extern LPBYTE memwrite[0x100];
|
||||
extern BYTE memreadPageType[0x100];
|
||||
extern BYTE memwriteDirtyPage[0x100];
|
||||
extern LPBYTE mem;
|
||||
extern LPBYTE memdirty;
|
||||
extern LPBYTE memVidHD;
|
||||
@@ -56,11 +61,14 @@ void MemDestroy ();
|
||||
bool MemCheckSLOTC3ROM();
|
||||
bool MemCheckINTCXROM();
|
||||
LPBYTE MemGetAuxPtr(const WORD);
|
||||
LPBYTE MemGetMainPtrWithLC(const WORD);
|
||||
LPBYTE MemGetMainPtr(const WORD);
|
||||
LPBYTE MemGetBankPtr(const UINT nBank, const bool isSaveSnapshotOrDebugging = true);
|
||||
LPBYTE MemGetCxRomPeripheral();
|
||||
uint32_t GetMemMode(void);
|
||||
void SetMemMode(uint32_t memmode);
|
||||
bool MemIsWriteAux(uint32_t memMode);
|
||||
bool IsIIeWithoutAuxMem(void);
|
||||
bool MemOptimizeForModeChanging(WORD programcounter, WORD address);
|
||||
bool MemIsAddrCodeMemory(const USHORT addr);
|
||||
void MemInitialize ();
|
||||
@@ -71,6 +79,7 @@ void MemInitializeIO(void);
|
||||
void MemInitializeFromSnapshot(void);
|
||||
BYTE MemReadFloatingBus(const ULONG uExecutedCycles);
|
||||
BYTE MemReadFloatingBus(const BYTE highbit, const ULONG uExecutedCycles);
|
||||
BYTE MemReadFloatingBusFromNTSC(void);
|
||||
void MemReset ();
|
||||
void MemResetPaging ();
|
||||
void MemUpdatePaging(BOOL initialize);
|
||||
@@ -102,4 +111,3 @@ UINT GetRamWorksActiveBank(void);
|
||||
void SetMemMainLanguageCard(LPBYTE ptr, UINT slot, bool bMemMain=false);
|
||||
|
||||
LPBYTE GetCxRomPeripheral(void);
|
||||
UINT GetLastSlotToSetMainMemLC(void);
|
||||
|
||||
@@ -4,6 +4,7 @@ enum
|
||||
{
|
||||
// Note: All are in bytes!
|
||||
TEXT_PAGE1_BEGIN = 0x0400,
|
||||
TEXT_PAGE1_SIZE = 0x0400,
|
||||
|
||||
APPLE_SLOT_SIZE = 0x0100, // 1 page = $Cx00 .. $CxFF (slot 1 .. 7)
|
||||
APPLE_IO_BEGIN = 0xC000,
|
||||
|
||||
+20
-11
@@ -1380,8 +1380,8 @@ void updateScreenDoubleHires80 (long cycles6502 ) // wsUpdateVideoDblHires
|
||||
}
|
||||
else if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint8_t *pMain = MemGetMainPtr(addr);
|
||||
uint8_t *pAux = MemGetAuxPtr (addr);
|
||||
uint8_t *pMain = MemGetMainPtr(addr);
|
||||
uint8_t *pAux = MemGetAuxPtr(addr);
|
||||
|
||||
uint8_t m = pMain[0];
|
||||
uint8_t a = pAux [0];
|
||||
@@ -1481,7 +1481,7 @@ void updateScreenDoubleLores80 (long cycles6502) // wsUpdateVideoDblLores
|
||||
else if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint8_t *pMain = MemGetMainPtr(addr);
|
||||
uint8_t *pAux = MemGetAuxPtr (addr);
|
||||
uint8_t *pAux = MemGetAuxPtr(addr);
|
||||
|
||||
uint8_t m = pMain[0];
|
||||
uint8_t a = pAux [0];
|
||||
@@ -1772,11 +1772,14 @@ void updateScreenText80 (long cycles6502)
|
||||
if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
|
||||
{
|
||||
uint8_t *pMain = MemGetMainPtr(addr);
|
||||
uint8_t *pAux = MemGetAuxPtr (addr);
|
||||
uint8_t *pAux = MemGetAuxPtr(addr);
|
||||
|
||||
uint8_t m = pMain[0];
|
||||
uint8_t a = pAux [0];
|
||||
|
||||
if (g_uNewVideoModeFlags & VF_80COL_AUX_EMPTY)
|
||||
a = MemReadFloatingBusFromNTSC();
|
||||
|
||||
uint16_t main = getCharSetBits( m );
|
||||
uint16_t aux = getCharSetBits( a );
|
||||
|
||||
@@ -1911,9 +1914,9 @@ void NTSC_VideoClockResync(const uint32_t dwCyclesThisFrame)
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
uint16_t NTSC_VideoGetScannerAddress ( const ULONG uExecutedCycles )
|
||||
uint16_t NTSC_VideoGetScannerAddress(const ULONG uExecutedCycles, const bool fullSpeed)
|
||||
{
|
||||
if (g_bFullSpeed)
|
||||
if (fullSpeed)
|
||||
{
|
||||
// Ensure that NTSC video-scanner gets updated during full-speed, so video-dependent Apple II code doesn't hang
|
||||
NTSC_VideoClockResync( CpuGetCyclesThisVideoFrame(uExecutedCycles) );
|
||||
@@ -1943,7 +1946,7 @@ uint16_t NTSC_VideoGetScannerAddress ( const ULONG uExecutedCycles )
|
||||
void NTSC_GetVideoVertHorzForDebugger(uint16_t& vert, uint16_t& horz)
|
||||
{
|
||||
ResetCyclesExecutedForDebugger(); // if in full-speed, then reset cycles so that CpuCalcCycles() doesn't ASSERT
|
||||
NTSC_VideoGetScannerAddress(0);
|
||||
NTSC_VideoGetScannerAddress(0, g_bFullSpeed);
|
||||
vert = g_nVideoClockVert;
|
||||
horz = g_nVideoClockHorz;
|
||||
}
|
||||
@@ -1965,10 +1968,13 @@ void NTSC_SetVideoTextMode( int cols )
|
||||
else
|
||||
g_pFuncUpdateTextScreen = updateScreenText80RGB;
|
||||
}
|
||||
else if( cols == 40 )
|
||||
g_pFuncUpdateTextScreen = updateScreenText40;
|
||||
else
|
||||
g_pFuncUpdateTextScreen = updateScreenText80;
|
||||
{
|
||||
if (cols == 40)
|
||||
g_pFuncUpdateTextScreen = updateScreenText40;
|
||||
else
|
||||
g_pFuncUpdateTextScreen = updateScreenText80;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -2808,7 +2814,10 @@ uint16_t NTSC_GetScannerAddressAndData(uint32_t& data, int& dataSize)
|
||||
if (dataSize == 2)
|
||||
{
|
||||
uint8_t* pAux = MemGetAuxPtr(addr);
|
||||
data = pAux[0] << 8;
|
||||
uint8_t a = pAux[0];
|
||||
if (g_uNewVideoModeFlags & VF_80COL_AUX_EMPTY)
|
||||
a = MemReadFloatingBusFromNTSC();
|
||||
data = a << 8;
|
||||
}
|
||||
uint8_t* pMain = MemGetMainPtr(addr);
|
||||
data |= pMain[0];
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ void NTSC_SetVideoStyle(void);
|
||||
void NTSC_SetVideoTextMode(int cols);
|
||||
uint32_t* NTSC_VideoGetChromaTable(bool bHueTypeMonochrome, bool bMonitorTypeColorTV);
|
||||
void NTSC_VideoClockResync(const uint32_t dwCyclesThisFrame);
|
||||
uint16_t NTSC_VideoGetScannerAddress(const ULONG uExecutedCycles);
|
||||
uint16_t NTSC_VideoGetScannerAddress(const ULONG uExecutedCycles, const bool fullSpeed);
|
||||
void NTSC_GetVideoVertHorzForDebugger(uint16_t& vert, uint16_t& horz);
|
||||
uint16_t NTSC_GetVideoVertForDebugger(void);
|
||||
void NTSC_Destroy(void);
|
||||
|
||||
+10
-8
@@ -36,14 +36,15 @@
|
||||
Implementation notes:
|
||||
. II/II+
|
||||
. Mirrors the 80STORE/PAGE2/AUXREAD/AUXWRITE switches to VidHD.
|
||||
. Reuses 'memaux' that's for the //e models.
|
||||
. Reuses 'memaux' that's for the //e models with aux card of 64KiB (or more).
|
||||
. AUXWRITE=1: writes occur to both main & memaux.
|
||||
. 80STORE=1 && PAGE2=1: same as AUXWRITE=1 (but should be changed to *only* allow writes to aux's TEXT1 & HGR2 areas).
|
||||
. Only 6502 (not 65C02) emulation supports this dual write to main & memaux (via the 'memVidHD' pointer):
|
||||
- So a II/II+ with a 65C02 won't correctly support VidHD cards.
|
||||
- And a //e with a 6502 will incur a slight overhead to test 'memVidHD' pointer (which is always NULL for //e's).
|
||||
. VidHD card's save-state includes VidHD's aux mem ($400-$9FFF).
|
||||
. //e with 1KiB 80-Col card: AppleWin doesn't support this - so currently out of scope.
|
||||
. //e with 1KiB 80-Col card or empty aux slot: supported.
|
||||
. Reuses 'memaux' that's for the //e models with aux card of 64KiB (or more).
|
||||
*/
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -100,8 +101,7 @@ void VidHDCard::VideoIOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE value, ULONG
|
||||
|
||||
bool VidHDCard::IsWriteAux(void)
|
||||
{
|
||||
return (m_memMode & MF_AUXWRITE) || // Write to aux: $200-$BFFF
|
||||
((m_memMode & MF_80STORE) && (m_memMode & MF_PAGE2)); // Write to aux: $400-$7FF and $2000-$3FFF
|
||||
return MemIsWriteAux(m_memMode);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -205,12 +205,13 @@ void VidHDCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
|
||||
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_BORDER_COLOR, m_BORDERCOLOR);
|
||||
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SHADOW, m_SHADOW);
|
||||
|
||||
if (IsApple2PlusOrClone(GetApple2Type())) // Save aux mem for II/II+
|
||||
if (IsApple2PlusOrClone(GetApple2Type()) || IsIIeWithoutAuxMem()) // Save aux mem for II/II+ or //e without aux mem
|
||||
{
|
||||
// Save [$400-$9FFF]
|
||||
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", MemGetSnapshotAuxMemStructName().c_str());
|
||||
|
||||
LPBYTE pMemBase = MemGetBankPtr(1);
|
||||
const UINT bank1 = 1;
|
||||
LPBYTE pMemBase = MemGetBankPtr(bank1);
|
||||
yamlSaveHelper.SaveMemory(pMemBase, (SHR_MEMORY_END + 1) - TEXT_PAGE1_BEGIN, TEXT_PAGE1_BEGIN);
|
||||
}
|
||||
}
|
||||
@@ -226,13 +227,14 @@ bool VidHDCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
|
||||
m_BORDERCOLOR = yamlLoadHelper.LoadUint(SS_YAML_KEY_BORDER_COLOR);
|
||||
m_SHADOW = yamlLoadHelper.LoadUint(SS_YAML_KEY_SHADOW);
|
||||
|
||||
if (IsApple2PlusOrClone(GetApple2Type())) // Load aux mem for II/II+
|
||||
if (IsApple2PlusOrClone(GetApple2Type()) || IsIIeWithoutAuxMem()) // Load aux mem for II/II+ or //e without aux mem
|
||||
{
|
||||
// Load [$400-$9FFF]
|
||||
if (!yamlLoadHelper.GetSubMap(MemGetSnapshotAuxMemStructName()))
|
||||
throw std::runtime_error("Memory: Missing map name: " + MemGetSnapshotAuxMemStructName());
|
||||
|
||||
LPBYTE pMemBase = MemGetBankPtr(1, false);
|
||||
const UINT bank1 = 1;
|
||||
LPBYTE pMemBase = MemGetBankPtr(bank1, false);
|
||||
yamlLoadHelper.LoadMemory(pMemBase, (SHR_MEMORY_END + 1) - TEXT_PAGE1_BEGIN, TEXT_PAGE1_BEGIN);
|
||||
|
||||
yamlLoadHelper.PopMap();
|
||||
|
||||
+39
-17
@@ -185,26 +185,26 @@ BYTE Video::VideoSetMode(WORD pc, WORD address, BYTE write, BYTE d, ULONG uExecu
|
||||
address &= 0xFF;
|
||||
switch (address)
|
||||
{
|
||||
case 0x00: g_uVideoMode &= ~VF_80STORE; break;
|
||||
case 0x01: g_uVideoMode |= VF_80STORE; break;
|
||||
case 0x0C: if (!IS_APPLE2){g_uVideoMode &= ~VF_80COL; NTSC_SetVideoTextMode(40);}; break;
|
||||
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 0x00: g_uVideoMode &= ~VF_80STORE; break;
|
||||
case 0x01: g_uVideoMode |= VF_80STORE; break;
|
||||
case 0x0C: if (!IS_APPLE2) { g_uVideoMode &= ~VF_80COL; NTSC_SetVideoTextMode(40); } break;
|
||||
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;
|
||||
case 0x53: g_uVideoMode |= VF_MIXED; break;
|
||||
case 0x54: g_uVideoMode &= ~VF_PAGE2; break;
|
||||
case 0x55: g_uVideoMode |= VF_PAGE2; break;
|
||||
case 0x56: g_uVideoMode &= ~VF_HIRES; break;
|
||||
case 0x57: g_uVideoMode |= VF_HIRES; break;
|
||||
case 0x5E: if (!IS_APPLE2) g_uVideoMode |= VF_DHIRES; break;
|
||||
case 0x5F: if (!IS_APPLE2) g_uVideoMode &= ~VF_DHIRES; break;
|
||||
case 0x50: g_uVideoMode &= ~VF_TEXT; break;
|
||||
case 0x51: g_uVideoMode |= VF_TEXT; break;
|
||||
case 0x52: g_uVideoMode &= ~VF_MIXED; break;
|
||||
case 0x53: g_uVideoMode |= VF_MIXED; break;
|
||||
case 0x54: g_uVideoMode &= ~VF_PAGE2; break;
|
||||
case 0x55: g_uVideoMode |= VF_PAGE2; break;
|
||||
case 0x56: g_uVideoMode &= ~VF_HIRES; break;
|
||||
case 0x57: g_uVideoMode |= VF_HIRES; break;
|
||||
case 0x5E: if (!IS_APPLE2) g_uVideoMode |= VF_DHIRES; break;
|
||||
case 0x5F: if (!IS_APPLE2) g_uVideoMode &= ~VF_DHIRES; break;
|
||||
}
|
||||
|
||||
if (vidHD && vidHD->IsSHR())
|
||||
@@ -220,7 +220,24 @@ BYTE Video::VideoSetMode(WORD pc, WORD address, BYTE write, BYTE d, ULONG uExecu
|
||||
if ((oldVideoMode ^ g_uVideoMode) & (VF_TEXT|VF_MIXED))
|
||||
delay = true;
|
||||
|
||||
NTSC_SetVideoMode(g_uVideoMode, delay);
|
||||
uint32_t ntscVideoMode = g_uVideoMode;
|
||||
if ((!IS_APPLE2) && (GetCardMgr().QueryAux() == CT_Empty || GetCardMgr().QueryAux() == CT_80Col)) // aux empty or 80col (GH#1341)
|
||||
{
|
||||
g_uVideoMode &= ~VF_DHIRES;
|
||||
if (GetCardMgr().QueryAux() == CT_Empty)
|
||||
{
|
||||
if ((g_uVideoMode & VF_80COL) == 0)
|
||||
g_uVideoMode &= ~VF_80COL_AUX_EMPTY;
|
||||
else
|
||||
g_uVideoMode |= VF_80COL_AUX_EMPTY;
|
||||
}
|
||||
|
||||
ntscVideoMode = g_uVideoMode;
|
||||
if (!(ntscVideoMode & VF_TEXT))
|
||||
ntscVideoMode &= ~VF_80COL; // if (aux=empty or aux=80col) && not TEXT: then 80COL switch is ignored
|
||||
}
|
||||
|
||||
NTSC_SetVideoMode(ntscVideoMode, delay);
|
||||
|
||||
return MemReadFloatingBus(uExecutedCycles);
|
||||
}
|
||||
@@ -267,6 +284,11 @@ bool Video::VideoGetSWAltCharSet(void)
|
||||
return g_nAltCharSetOffset != 0;
|
||||
}
|
||||
|
||||
bool Video::VideoGet80COLAUXEMPTY(void)
|
||||
{
|
||||
return g_uVideoMode & VF_80COL_AUX_EMPTY ? true : false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define SS_YAML_KEY_ALT_CHARSET "Alt Char Set"
|
||||
|
||||
+6
-4
@@ -57,10 +57,11 @@ enum VideoFlag_e
|
||||
VF_PAGE2 = 0x00000020, // Text or Hires
|
||||
VF_TEXT = 0x00000040,
|
||||
VF_SHR = 0x00000080, // For VidHD's support for IIgs SHR video modes
|
||||
VF_PAGE0 = 0x00000100, // Pseudo Page $00 (Poorman's heatmap)
|
||||
VF_PAGE3 = 0x00000200, // Pseudo Page $60 (Poorman's heatmap)
|
||||
VF_PAGE4 = 0x00000400, // Pseudo Page $80 (Poorman's heatmap)
|
||||
VF_PAGE5 = 0x00000800, // Pseudo Page $A0 (Poorman's heatmap)
|
||||
VF_80COL_AUX_EMPTY = 0x00000100, // For 80COL when aux slot is empty (returns floating bus)
|
||||
VF_PAGE0 = 0x10000000, // Debugger: Pseudo Page $00 (Poorman's heatmap)
|
||||
VF_PAGE3 = 0x20000000, // Debugger: Pseudo Page $60 (Poorman's heatmap)
|
||||
VF_PAGE4 = 0x40000000, // Debugger: Pseudo Page $80 (Poorman's heatmap)
|
||||
VF_PAGE5 = 0x80000000, // Debugger: Pseudo Page $A0 (Poorman's heatmap)
|
||||
};
|
||||
|
||||
enum AppleFont_e
|
||||
@@ -234,6 +235,7 @@ public:
|
||||
bool VideoGetSWPAGE2(void);
|
||||
bool VideoGetSWTEXT(void);
|
||||
bool VideoGetSWAltCharSet(void);
|
||||
bool VideoGet80COLAUXEMPTY(void);
|
||||
|
||||
void VideoSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
|
||||
void VideoLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version);
|
||||
|
||||
@@ -712,20 +712,23 @@ static void RepeatInitialization(void)
|
||||
if (g_cmdLine.uRamWorksExPages)
|
||||
{
|
||||
SetRamWorksMemorySize(g_cmdLine.uRamWorksExPages);
|
||||
SetExpansionMemType(CT_RamWorksIII);
|
||||
if (!g_cmdLine.auxSlotEmpty)
|
||||
SetExpansionMemType(CT_RamWorksIII);
|
||||
g_cmdLine.uRamWorksExPages = 0; // Don't reapply after a restart
|
||||
}
|
||||
#endif
|
||||
if (g_cmdLine.uSaturnBanks)
|
||||
{
|
||||
Saturn128K::SetSaturnMemorySize(g_cmdLine.uSaturnBanks); // Set number of banks before constructing Saturn card
|
||||
SetExpansionMemType(CT_Saturn128K);
|
||||
if (!g_cmdLine.bSlotEmpty[SLOT0])
|
||||
SetExpansionMemType(CT_Saturn128K);
|
||||
g_cmdLine.uSaturnBanks = 0; // Don't reapply after a restart
|
||||
}
|
||||
|
||||
if (g_cmdLine.bSlot0LanguageCard)
|
||||
{
|
||||
SetExpansionMemType(CT_LanguageCard);
|
||||
if (!g_cmdLine.bSlotEmpty[SLOT0])
|
||||
SetExpansionMemType(CT_LanguageCard);
|
||||
g_cmdLine.bSlot0LanguageCard = false; // Don't reapply after a restart
|
||||
}
|
||||
|
||||
@@ -824,6 +827,22 @@ static void RepeatInitialization(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Aux slot
|
||||
|
||||
if (g_cmdLine.auxSlotEmpty)
|
||||
{
|
||||
GetCardMgr().RemoveAux();
|
||||
SetExpansionMemType(CT_Empty);
|
||||
}
|
||||
else if (g_cmdLine.auxSlotInsert != CT_Empty)
|
||||
{
|
||||
if (GetCardMgr().QueryAux() != g_cmdLine.auxSlotInsert) // Ignore if already got this card type in aux slot
|
||||
{
|
||||
GetCardMgr().InsertAux(g_cmdLine.auxSlotInsert);
|
||||
SetExpansionMemType(g_cmdLine.auxSlotInsert);
|
||||
}
|
||||
}
|
||||
|
||||
// Create window after inserting/removing VidHD card (as it affects width & height)
|
||||
{
|
||||
Win32Frame::GetWin32Frame().SetViewportScale(Win32Frame::GetWin32Frame().GetViewportScale(), true);
|
||||
|
||||
@@ -662,9 +662,9 @@ void Win32Frame::GetTrackSector(UINT slot, int& drive1Track, int& drive2Track, i
|
||||
{
|
||||
// we can't just read from mem[ 0xD357 ] since it might be bank-switched from ROM
|
||||
// and we need the Language Card RAM
|
||||
const int nProDOStrack = *MemGetMainPtr(0xC356); // LC1 $D356
|
||||
const int nProDOSsector = *MemGetMainPtr(0xC357); // LC1 $D357
|
||||
const int nProDOSslot = *MemGetMainPtr(0xC359) / 16; // LC1 $D359
|
||||
const int nProDOStrack = *MemGetMainPtrWithLC(0xC356); // LC1 $D356
|
||||
const int nProDOSsector = *MemGetMainPtrWithLC(0xC357); // LC1 $D357
|
||||
const int nProDOSslot = *MemGetMainPtrWithLC(0xC359) / 16; // LC1 $D359
|
||||
|
||||
if ((nProDOSslot == slot)
|
||||
&& (nProDOStrack >= 0 && nProDOStrack < 40)
|
||||
|
||||
@@ -12,6 +12,8 @@ SynchronousEventManager g_SynchronousEventMgr;
|
||||
|
||||
// From Memory.cpp
|
||||
LPBYTE memwrite[0x100]; // TODO: Init
|
||||
BYTE memreadPageType[0x100]; // TODO: Init
|
||||
BYTE memwriteDirtyPage[0x100]; // TODO: Init
|
||||
LPBYTE mem = NULL; // TODO: Init
|
||||
LPBYTE memdirty = NULL; // TODO: Init
|
||||
LPBYTE memVidHD = NULL; // TODO: Init
|
||||
|
||||
Reference in New Issue
Block a user