mirror of
https://github.com/AppleWin/AppleWin.git
synced 2026-04-20 15:17:50 +00:00
Better support the IIe's aux slot when it's empty or has the 80-col(1KiB) card. - any h/w using this alternate CPU emulation, (ie. aux=empty or 80-col(1KiB)), then the 'mem' cache is completely bypassed. Debugger: change all the direct 'mem' accesses to go via ReadByteFromMemory(). TestCPU6502: test the alt CPU emulation code too.
This commit is contained in:
@@ -59,7 +59,6 @@
|
||||
<ClInclude Include="source\CPU\cpu6502.h" />
|
||||
<ClInclude Include="source\CPU\cpu65C02.h" />
|
||||
<ClInclude Include="source\Debugger\Debug.h" />
|
||||
<ClInclude Include="source\Debugger\DebugDefs.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Assembler.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Color.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Console.h" />
|
||||
|
||||
@@ -498,9 +498,6 @@
|
||||
<ClInclude Include="source\z80emu.h">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\Debugger\DebugDefs.h">
|
||||
<Filter>Source Files\Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\Debugger\Util_MemoryTextFile.h">
|
||||
<Filter>Source Files\Debugger</Filter>
|
||||
</ClInclude>
|
||||
|
||||
+10
-7
@@ -418,8 +418,8 @@ UINT SY6522::GetOpcodeCyclesForRead(BYTE reg)
|
||||
bool indx = false;
|
||||
bool indy = false;
|
||||
|
||||
const BYTE opcodeMinus3 = mem[(::regs.pc - 3) & 0xffff];
|
||||
const BYTE opcodeMinus2 = mem[(::regs.pc - 2) & 0xffff];
|
||||
const BYTE opcodeMinus3 = ReadByteFromMemory(::regs.pc - 3);
|
||||
const BYTE opcodeMinus2 = ReadByteFromMemory(::regs.pc - 2);
|
||||
|
||||
// Check 2-byte opcodes
|
||||
if (((opcodeMinus2 & 0x0f) == 0x01) && ((opcodeMinus2 & 0x10) == 0x00)) // ora (zp,x), and (zp,x), ..., sbc (zp,x)
|
||||
@@ -504,8 +504,8 @@ UINT SY6522::GetOpcodeCyclesForWrite(BYTE reg)
|
||||
bool indx = false;
|
||||
bool indy = false;
|
||||
|
||||
const BYTE opcodeMinus3 = mem[(::regs.pc - 3) & 0xffff];
|
||||
const BYTE opcodeMinus2 = mem[(::regs.pc - 2) & 0xffff];
|
||||
const BYTE opcodeMinus3 = ReadByteFromMemory(::regs.pc - 3);
|
||||
const BYTE opcodeMinus2 = ReadByteFromMemory(::regs.pc - 2);
|
||||
|
||||
// Check 2-byte opcodes
|
||||
if (opcodeMinus2 == 0x81) // sta (zp,x)
|
||||
@@ -577,15 +577,18 @@ UINT SY6522::GetOpcodeCycles(BYTE reg, UINT zpOpcodeCycles, UINT opcodeCycles,
|
||||
|
||||
if (zpOpcode)
|
||||
{
|
||||
BYTE zp = mem[(::regs.pc - 1) & 0xffff];
|
||||
if (IsZeroPageFloatingBus())
|
||||
return 0;
|
||||
|
||||
BYTE zp = ReadByteFromMemory(::regs.pc - 1);
|
||||
if (indx) zp += ::regs.x;
|
||||
zpAddr16 = (mem[zp] | (mem[(zp + 1) & 0xff] << 8));
|
||||
zpAddr16 = (ReadByteFromMemory(zp) | (ReadByteFromMemory((zp + 1) & 0xff) << 8));
|
||||
if (indy) zpAddr16 += ::regs.y;
|
||||
}
|
||||
|
||||
if (opcode)
|
||||
{
|
||||
addr16 = mem[(::regs.pc - 2) & 0xffff] | (mem[(::regs.pc - 1) & 0xffff] << 8);
|
||||
addr16 = ReadByteFromMemory(::regs.pc - 2) | (ReadByteFromMemory(::regs.pc - 1) << 8);
|
||||
if (abs16y) addr16 += ::regs.y;
|
||||
if (abs16x) addr16 += ::regs.x;
|
||||
}
|
||||
|
||||
+104
-62
@@ -379,6 +379,24 @@ static __forceinline void Fetch(BYTE& iOpcode, ULONG uExecutedCycles)
|
||||
regs.pc++;
|
||||
}
|
||||
|
||||
static __forceinline void Fetch_alt(BYTE& iOpcode, ULONG uExecutedCycles)
|
||||
{
|
||||
const USHORT PC = regs.pc;
|
||||
|
||||
#if defined(_DEBUG) && defined(DBG_HDD_ENTRYPOINT)
|
||||
DebugHddEntrypoint(PC);
|
||||
#endif
|
||||
|
||||
iOpcode = _READ_ALT(regs.pc);
|
||||
|
||||
#ifdef USE_SPEECH_API
|
||||
if ((PC == COUT1 || PC == BASICOUT) && g_Speech.IsEnabled() && !g_bFullSpeed)
|
||||
CaptureCOUT();
|
||||
#endif
|
||||
|
||||
regs.pc++;
|
||||
}
|
||||
|
||||
//#define ENABLE_NMI_SUPPORT // Not used - so don't enable
|
||||
static __forceinline bool NMI(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn, BOOL& flagv, BOOL& flagz)
|
||||
{
|
||||
@@ -391,14 +409,28 @@ static __forceinline bool NMI(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn,
|
||||
#ifdef _DEBUG
|
||||
g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles;
|
||||
#endif
|
||||
PUSH(regs.pc >> 8)
|
||||
PUSH(regs.pc & 0xFF)
|
||||
EF_TO_AF
|
||||
PUSH(regs.ps & ~AF_BREAK)
|
||||
regs.ps |= AF_INTERRUPT;
|
||||
if (GetMainCpu() == CPU_65C02) // GH#1099
|
||||
regs.ps &= ~AF_DECIMAL;
|
||||
regs.pc = * (WORD*) (mem+0xFFFA);
|
||||
if (GetIsMemCacheValid())
|
||||
{
|
||||
_PUSH(regs.pc >> 8)
|
||||
_PUSH(regs.pc & 0xFF)
|
||||
EF_TO_AF
|
||||
_PUSH(regs.ps & ~AF_BREAK)
|
||||
regs.ps |= AF_INTERRUPT;
|
||||
if (GetMainCpu() == CPU_65C02) // GH#1099
|
||||
regs.ps &= ~AF_DECIMAL;
|
||||
regs.pc = *(WORD*)(mem + _6502_NMI_VECTOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
_PUSH_ALT(regs.pc >> 8)
|
||||
_PUSH_ALT(regs.pc & 0xFF)
|
||||
EF_TO_AF
|
||||
_PUSH_ALT(regs.ps & ~AF_BREAK)
|
||||
regs.ps |= AF_INTERRUPT;
|
||||
if (GetMainCpu() == CPU_65C02) // GH#1099
|
||||
regs.ps &= ~AF_DECIMAL;
|
||||
regs.pc = READ_WORD_ALT(_6502_NMI_VECTOR);
|
||||
}
|
||||
UINT uExtraCycles = 0; // Needed for CYC(a) macro
|
||||
CYC(7);
|
||||
g_interruptInLastExecutionBatch = true;
|
||||
@@ -433,14 +465,28 @@ static __forceinline bool IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn,
|
||||
#ifdef _DEBUG
|
||||
g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles;
|
||||
#endif
|
||||
PUSH(regs.pc >> 8)
|
||||
PUSH(regs.pc & 0xFF)
|
||||
EF_TO_AF
|
||||
PUSH(regs.ps & ~AF_BREAK)
|
||||
regs.ps |= AF_INTERRUPT;
|
||||
if (GetMainCpu() == CPU_65C02) // GH#1099
|
||||
regs.ps &= ~AF_DECIMAL;
|
||||
regs.pc = * (WORD*) (mem+0xFFFE);
|
||||
if (GetIsMemCacheValid())
|
||||
{
|
||||
_PUSH(regs.pc >> 8)
|
||||
_PUSH(regs.pc & 0xFF)
|
||||
EF_TO_AF;
|
||||
_PUSH(regs.ps & ~AF_BREAK)
|
||||
regs.ps |= AF_INTERRUPT;
|
||||
if (GetMainCpu() == CPU_65C02) // GH#1099
|
||||
regs.ps &= ~AF_DECIMAL;
|
||||
regs.pc = *(WORD*)(mem + _6502_INTERRUPT_VECTOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
_PUSH_ALT(regs.pc >> 8)
|
||||
_PUSH_ALT(regs.pc & 0xFF)
|
||||
EF_TO_AF;
|
||||
_PUSH_ALT(regs.ps & ~AF_BREAK)
|
||||
regs.ps |= AF_INTERRUPT;
|
||||
if (GetMainCpu() == CPU_65C02) // GH#1099
|
||||
regs.ps &= ~AF_DECIMAL;
|
||||
regs.pc = READ_WORD_ALT(_6502_INTERRUPT_VECTOR);
|
||||
}
|
||||
UINT uExtraCycles = 0; // Needed for CYC(a) macro
|
||||
CYC(7);
|
||||
#if defined(_DEBUG) && LOG_IRQ_TAKEN_AND_RTI
|
||||
@@ -462,108 +508,99 @@ 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)
|
||||
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
// 6502 & no debugger
|
||||
#define READ(addr) _READ_WITH_IO_F8xx(addr)
|
||||
#define WRITE(value) _WRITE_WITH_IO_F8xx(value)
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
|
||||
//-------
|
||||
|
||||
// 6502 & no debugger & alt read/write support
|
||||
#define READ _READ_ALT
|
||||
#define CPU_ALT
|
||||
#define READ(addr) _READ_ALT(addr)
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu6502 Cpu6502_altRW
|
||||
#define Fetch Fetch_alt
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
#undef Cpu6502
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef Fetch
|
||||
|
||||
//-------
|
||||
|
||||
// 65C02 & no debugger
|
||||
#define READ _READ
|
||||
#define READ(addr) _READ(addr)
|
||||
#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 CPU_ALT
|
||||
#define READ(addr) _READ_ALT(addr)
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu65C02 Cpu65C02_altRW
|
||||
#define Fetch Fetch_alt
|
||||
#include "CPU/cpu65C02.h" // WDC 65C02
|
||||
#undef Cpu65C02
|
||||
#undef Fetch
|
||||
|
||||
#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"
|
||||
|
||||
// 6502 & debugger
|
||||
#define READ(addr) Heatmap_ReadByte_With_IO_F8xx(addr, uExecutedCycles)
|
||||
#define WRITE(value) Heatmap_WriteByte_With_IO_F8xx(addr, value, uExecutedCycles);
|
||||
|
||||
#define Cpu6502 Cpu6502_debug
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
#undef Cpu6502
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
|
||||
//-------
|
||||
|
||||
// 6502 & debugger & alt read/write support
|
||||
#define READ _READ_ALT
|
||||
#define CPU_ALT
|
||||
#define READ(addr) _READ_ALT(addr)
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu6502 Cpu6502_debug_altRW
|
||||
#define Fetch Fetch_alt
|
||||
#include "CPU/cpu6502.h" // MOS 6502
|
||||
#undef Cpu6502
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef Fetch
|
||||
|
||||
//-------
|
||||
|
||||
// 65C02 & debugger
|
||||
#define READ Heatmap_ReadByte(addr, uExecutedCycles)
|
||||
#define READ(addr) Heatmap_ReadByte(addr, uExecutedCycles)
|
||||
#define WRITE(value) Heatmap_WriteByte(addr, value, uExecutedCycles);
|
||||
|
||||
#define Cpu65C02 Cpu65C02_debug
|
||||
#include "CPU/cpu65C02.h" // WDC 65C02
|
||||
#undef Cpu65C02
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
|
||||
//-------
|
||||
|
||||
// 65C02 & debugger & alt read/write support
|
||||
#define READ _READ_ALT
|
||||
#define CPU_ALT
|
||||
#define READ(addr) _READ_ALT(addr)
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu65C02 Cpu65C02_debug_altRW
|
||||
#define Fetch Fetch_alt
|
||||
#include "CPU/cpu65C02.h" // WDC 65C02
|
||||
#undef Cpu65C02
|
||||
#undef Fetch
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef HEATMAP_X
|
||||
|
||||
//===========================================================================
|
||||
@@ -572,8 +609,9 @@ 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 (!GetIsMemCacheValid())
|
||||
{
|
||||
_ASSERT(memshadow[0]);
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
return Cpu6502_altRW(uTotalCycles, bVideoUpdate); // Apple //e
|
||||
else
|
||||
@@ -589,8 +627,9 @@ static uint32_t InternalCpuExecute(const uint32_t uTotalCycles, const bool bVide
|
||||
{
|
||||
_ASSERT(g_nAppMode == MODE_STEPPING || g_nAppMode == MODE_DEBUG);
|
||||
|
||||
if (IsAppleIIe(GetApple2Type()) && (GetCardMgr().QueryAux() == CT_Empty || GetCardMgr().QueryAux() == CT_80Col))
|
||||
if (!GetIsMemCacheValid())
|
||||
{
|
||||
_ASSERT(memshadow[0]);
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
return Cpu6502_debug_altRW(uTotalCycles, bVideoUpdate); // Apple //e
|
||||
else
|
||||
@@ -615,7 +654,7 @@ BYTE CpuRead(USHORT addr, ULONG uExecutedCycles)
|
||||
{
|
||||
if (g_nAppMode == MODE_RUNNING)
|
||||
{
|
||||
return _READ_WITH_IO_F8xx; // Superset of _READ
|
||||
return _READ_WITH_IO_F8xx(addr); // Superset of _READ
|
||||
}
|
||||
|
||||
return Heatmap_ReadByte_With_IO_F8xx(addr, uExecutedCycles);
|
||||
@@ -764,7 +803,10 @@ void CpuReset()
|
||||
regs.ps |= AF_INTERRUPT;
|
||||
if (GetMainCpu() == CPU_65C02) // GH#1099
|
||||
regs.ps &= ~AF_DECIMAL;
|
||||
regs.pc = *(WORD*)(mem + 0xFFFC);
|
||||
|
||||
_ASSERT(memshadow[_6502_RESET_VECTOR >> 8] != NULL);
|
||||
regs.pc = ReadWordFromMemory(_6502_RESET_VECTOR);
|
||||
|
||||
regs.sp = 0x0100 | ((regs.sp - 3) & 0xFF);
|
||||
|
||||
regs.bJammed = 0;
|
||||
@@ -777,7 +819,7 @@ void CpuReset()
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void CpuSetupBenchmark ()
|
||||
void CpuSetupBenchmark()
|
||||
{
|
||||
regs.a = 0;
|
||||
regs.x = 0;
|
||||
@@ -791,19 +833,19 @@ void CpuSetupBenchmark ()
|
||||
int opcode = 0;
|
||||
do
|
||||
{
|
||||
*(mem+addr++) = benchopcode[opcode];
|
||||
*(mem+addr++) = benchopcode[opcode];
|
||||
WriteByteToMemory(addr++, benchopcode[opcode]);
|
||||
WriteByteToMemory(addr++, benchopcode[opcode]);
|
||||
|
||||
if (opcode >= SHORTOPCODES)
|
||||
*(mem+addr++) = 0;
|
||||
WriteByteToMemory(addr++, 0);
|
||||
|
||||
if ((++opcode >= BENCHOPCODES) || ((addr & 0x0F) >= 0x0B))
|
||||
{
|
||||
*(mem+addr++) = 0x4C;
|
||||
WriteByteToMemory(addr++, 0x4C);
|
||||
// split into 2 lines to avoid -Wunsequenced and undefined behaviour
|
||||
const BYTE value = (opcode >= BENCHOPCODES) ? 0x00 : ((addr >> 4)+1) << 4;
|
||||
*(mem+addr++) = value;
|
||||
*(mem+addr++) = 0x03;
|
||||
WriteByteToMemory(addr++, value);
|
||||
WriteByteToMemory(addr++, 0x03);
|
||||
while (addr & 0x0F)
|
||||
++addr;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,61 @@ along with AppleWin; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
// For regular or alternate (slow-path) CPU emulation
|
||||
#ifndef CPU_ALT
|
||||
// NB READ(x) and WRITE(x) are defined in the parent CPU.cpp.
|
||||
// . but keep here to retain symmetry with the undef's at the end of this file.
|
||||
//#define READ(addr) _READ(addr)
|
||||
//#define WRITE(value) _WRITE(value)
|
||||
#define BRK_NMOS _BRK_NMOS
|
||||
#define BRK_CMOS _BRK_CMOS
|
||||
#define JSR _JSR
|
||||
#define POP _POP
|
||||
#define PUSH(value) _PUSH(value)
|
||||
#define ABS _ABS
|
||||
#define IABSX _IABSX
|
||||
#define ABSX_CONST _ABSX_CONST
|
||||
#define ABSX_OPT _ABSX_OPT
|
||||
#define ABSY_CONST _ABSY_CONST
|
||||
#define ABSY_OPT _ABSY_OPT
|
||||
#define IABS_CMOS _IABS_CMOS
|
||||
#define IABS_NMOS _IABS_NMOS
|
||||
#define INDX _INDX
|
||||
#define INDX _INDX
|
||||
#define INDY_CONST _INDY_CONST
|
||||
#define INDY_OPT _INDY_OPT
|
||||
#define IZPG _IZPG
|
||||
#define REL _REL
|
||||
#define ZPG _ZPG
|
||||
#define ZPGX _ZPGX
|
||||
#define ZPGY _ZPGY
|
||||
#else
|
||||
//#define READ(addr) _READ_ALT(addr)
|
||||
//#define WRITE(value) _WRITE_ALT(value)
|
||||
#define BRK_NMOS _BRK_NMOS_ALT
|
||||
#define BRK_CMOS _BRK_CMOS_ALT
|
||||
#define JSR _JSR_ALT
|
||||
#define POP _POP_ALT
|
||||
#define PUSH(value) _PUSH_ALT(value)
|
||||
#define ABS _ABS_ALT
|
||||
#define IABSX _IABSX_ALT
|
||||
#define ABSX_CONST _ABSX_CONST_ALT
|
||||
#define ABSX_OPT _ABSX_OPT_ALT
|
||||
#define ABSY_CONST _ABSY_CONST_ALT
|
||||
#define ABSY_OPT _ABSY_OPT_ALT
|
||||
#define IABS_CMOS _IABS_CMOS_ALT
|
||||
#define IABS_NMOS _IABS_NMOS_ALT
|
||||
#define INDX _INDX_ALT
|
||||
#define INDX _INDX_ALT
|
||||
#define INDY_CONST _INDY_CONST_ALT
|
||||
#define INDY_OPT _INDY_OPT_ALT
|
||||
#define IZPG _IZPG_ALT
|
||||
#define REL _REL_ALT
|
||||
#define ZPG _ZPG_ALT
|
||||
#define ZPGX _ZPGX_ALT
|
||||
#define ZPGY _ZPGY_ALT
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static uint32_t Cpu6502(uint32_t uTotalCycles, const bool bVideoUpdate)
|
||||
@@ -339,3 +394,30 @@ static uint32_t Cpu6502(uint32_t uTotalCycles, const bool bVideoUpdate)
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#undef CPU_ALT
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef BRK_NMOS
|
||||
#undef BRK_CMOS
|
||||
#undef JSR
|
||||
#undef POP
|
||||
#undef PUSH
|
||||
#undef ABS
|
||||
#undef IABSX
|
||||
#undef ABSX_CONST
|
||||
#undef ABSX_OPT
|
||||
#undef ABSY_CONST
|
||||
#undef ABSY_OPT
|
||||
#undef IABS_CMOS
|
||||
#undef IABS_NMOS
|
||||
#undef INDX
|
||||
#undef INDX
|
||||
#undef INDY_CONST
|
||||
#undef INDY_OPT
|
||||
#undef IZPG
|
||||
#undef REL
|
||||
#undef ZPG
|
||||
#undef ZPGX
|
||||
#undef ZPGY
|
||||
|
||||
@@ -21,6 +21,61 @@ along with AppleWin; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
// For regular or alternate (slow-path) CPU emulation
|
||||
#ifndef CPU_ALT
|
||||
// NB READ(x) and WRITE(x) are defined in the parent CPU.cpp.
|
||||
// . but keep here to retain symmetry with the undef's at the end of this file.
|
||||
//#define READ(addr) _READ(addr)
|
||||
//#define WRITE(value) _WRITE(value)
|
||||
#define BRK_NMOS _BRK_NMOS
|
||||
#define BRK_CMOS _BRK_CMOS
|
||||
#define JSR _JSR
|
||||
#define POP _POP
|
||||
#define PUSH(value) _PUSH(value)
|
||||
#define ABS _ABS
|
||||
#define IABSX _IABSX
|
||||
#define ABSX_CONST _ABSX_CONST
|
||||
#define ABSX_OPT _ABSX_OPT
|
||||
#define ABSY_CONST _ABSY_CONST
|
||||
#define ABSY_OPT _ABSY_OPT
|
||||
#define IABS_CMOS _IABS_CMOS
|
||||
#define IABS_NMOS _IABS_NMOS
|
||||
#define INDX _INDX
|
||||
#define INDX _INDX
|
||||
#define INDY_CONST _INDY_CONST
|
||||
#define INDY_OPT _INDY_OPT
|
||||
#define IZPG _IZPG
|
||||
#define REL _REL
|
||||
#define ZPG _ZPG
|
||||
#define ZPGX _ZPGX
|
||||
#define ZPGY _ZPGY
|
||||
#else
|
||||
//#define READ(addr) _READ_ALT(addr)
|
||||
//#define WRITE(value) _WRITE_ALT(value)
|
||||
#define BRK_NMOS _BRK_NMOS_ALT
|
||||
#define BRK_CMOS _BRK_CMOS_ALT
|
||||
#define JSR _JSR_ALT
|
||||
#define POP _POP_ALT
|
||||
#define PUSH(value) _PUSH_ALT(value)
|
||||
#define ABS _ABS_ALT
|
||||
#define IABSX _IABSX_ALT
|
||||
#define ABSX_CONST _ABSX_CONST_ALT
|
||||
#define ABSX_OPT _ABSX_OPT_ALT
|
||||
#define ABSY_CONST _ABSY_CONST_ALT
|
||||
#define ABSY_OPT _ABSY_OPT_ALT
|
||||
#define IABS_CMOS _IABS_CMOS_ALT
|
||||
#define IABS_NMOS _IABS_NMOS_ALT
|
||||
#define INDX _INDX_ALT
|
||||
#define INDX _INDX_ALT
|
||||
#define INDY_CONST _INDY_CONST_ALT
|
||||
#define INDY_OPT _INDY_OPT_ALT
|
||||
#define IZPG _IZPG_ALT
|
||||
#define REL _REL_ALT
|
||||
#define ZPG _ZPG_ALT
|
||||
#define ZPGX _ZPGX_ALT
|
||||
#define ZPGY _ZPGY_ALT
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static uint32_t Cpu65C02(uint32_t uTotalCycles, const bool bVideoUpdate)
|
||||
@@ -339,3 +394,30 @@ static uint32_t Cpu65C02(uint32_t uTotalCycles, const bool bVideoUpdate)
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#undef CPU_ALT
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef BRK_NMOS
|
||||
#undef BRK_CMOS
|
||||
#undef JSR
|
||||
#undef POP
|
||||
#undef PUSH
|
||||
#undef ABS
|
||||
#undef IABSX
|
||||
#undef ABSX_CONST
|
||||
#undef ABSX_OPT
|
||||
#undef ABSY_CONST
|
||||
#undef ABSY_OPT
|
||||
#undef IABS_CMOS
|
||||
#undef IABS_NMOS
|
||||
#undef INDX
|
||||
#undef INDX
|
||||
#undef INDY_CONST
|
||||
#undef INDY_OPT
|
||||
#undef IZPG
|
||||
#undef REL
|
||||
#undef ZPG
|
||||
#undef ZPGX
|
||||
#undef ZPGY
|
||||
|
||||
+141
-69
@@ -35,8 +35,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#undef AF_TO_EF
|
||||
#undef EF_TO_AF
|
||||
|
||||
|
||||
|
||||
#define AF_TO_EF flagc = (regs.ps & AF_CARRY); \
|
||||
flagn = (regs.ps & AF_SIGN); \
|
||||
flagv = (regs.ps & AF_OVERFLOW); \
|
||||
@@ -50,56 +48,71 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
| AF_RESERVED | AF_BREAK;
|
||||
// CYC(a): This can be optimised, as only certain opcodes will affect uExtraCycles
|
||||
#define CYC(a) uExecutedCycles += (a)+uExtraCycles;
|
||||
#define POP (*(mem+((regs.sp >= 0x1FF) ? (regs.sp = 0x100) : ++regs.sp)))
|
||||
#define PUSH(a) *(mem+regs.sp--) = (a); \
|
||||
if (regs.sp < 0x100) \
|
||||
regs.sp = 0x1FF;
|
||||
#define _READ ( \
|
||||
((addr & 0xF000) == 0xC000) \
|
||||
|
||||
#define _POP (*(mem+((regs.sp >= _6502_STACK_END) ? (regs.sp = _6502_STACK_BEGIN) : ++regs.sp)))
|
||||
#define _POP_ALT ( /*TODO: Support reads from IO & Floating bus*/\
|
||||
*(memshadow[_6502_STACK_PAGE]-_6502_STACK_BEGIN+((regs.sp >= _6502_STACK_END) ? (regs.sp = _6502_STACK_BEGIN) : ++regs.sp)) \
|
||||
)
|
||||
|
||||
#define _PUSH(a) *(mem+regs.sp--) = (a); \
|
||||
if (regs.sp < _6502_STACK_BEGIN) \
|
||||
regs.sp = _6502_STACK_END;
|
||||
#define _PUSH_ALT(a) { \
|
||||
LPBYTE page = memwrite[_6502_STACK_PAGE]; \
|
||||
if (page) { \
|
||||
*(page+(regs.sp & 0xFF)) = (BYTE)(a); \
|
||||
} \
|
||||
regs.sp--; \
|
||||
if (regs.sp < _6502_STACK_BEGIN) \
|
||||
regs.sp = _6502_STACK_END; \
|
||||
}
|
||||
|
||||
#define _READ(addr) ( \
|
||||
((addr & 0xF000) == APPLE_IO_BEGIN) \
|
||||
? IORead[(addr>>4) & 0xFF](regs.pc,addr,0,0,uExecutedCycles) \
|
||||
: *(mem+addr) \
|
||||
)
|
||||
#define _READ_ALT ( \
|
||||
#define _READ_ALT(addr) ( \
|
||||
(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) \
|
||||
? *(memshadow[addr >> 8]+(addr&0xff)) \
|
||||
: (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) \
|
||||
#define _READ_WITH_IO_F8xx(addr) ( /* GH#827 */\
|
||||
((addr & 0xF000) == APPLE_IO_BEGIN) \
|
||||
? IORead[(addr>>4) & 0xFF](regs.pc,addr,0,0,uExecutedCycles) \
|
||||
: (addr >= 0xF800) \
|
||||
? IO_F8xx(regs.pc,addr,0,0,uExecutedCycles) \
|
||||
: *(mem+addr) \
|
||||
)
|
||||
|
||||
#define SETNZ(a) { \
|
||||
flagn = ((a) & 0x80); \
|
||||
flagz = !((a) & 0xFF); \
|
||||
}
|
||||
#define SETZ(a) flagz = !((a) & 0xFF);
|
||||
|
||||
#define _WRITE(a) { \
|
||||
{ \
|
||||
memdirty[addr >> 8] = 0xFF; \
|
||||
LPBYTE page = memwrite[addr >> 8]; \
|
||||
if (page) \
|
||||
*(page+(addr & 0xFF)) = (BYTE)(a); \
|
||||
else if ((addr & 0xF000) == 0xC000) \
|
||||
else if ((addr & 0xF000) == APPLE_IO_BEGIN) \
|
||||
IOWrite[(addr>>4) & 0xFF](regs.pc,addr,1,(BYTE)(a),uExecutedCycles);\
|
||||
} \
|
||||
}
|
||||
#define _WRITE_ALT(a) { \
|
||||
{ \
|
||||
memdirty[memwriteDirtyPage[addr >> 8]] = 0xFF; \
|
||||
memdirty[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) \
|
||||
else if ((addr & 0xF000) == APPLE_IO_BEGIN) \
|
||||
IOWrite[(addr>>4) & 0xFF](regs.pc,addr,1,(BYTE)(a),uExecutedCycles);\
|
||||
} \
|
||||
}
|
||||
@@ -114,7 +127,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
if (memVidHD) /* GH#997 */\
|
||||
*(memVidHD + addr) = (BYTE)(a); \
|
||||
} \
|
||||
else if ((addr & 0xF000) == 0xC000) \
|
||||
else if ((addr & 0xF000) == APPLE_IO_BEGIN) \
|
||||
IOWrite[(addr>>4) & 0xFF](regs.pc,addr,1,(BYTE)(a),uExecutedCycles);\
|
||||
} \
|
||||
}
|
||||
@@ -141,95 +154,154 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define CHECK_PAGE_CHANGE if ((base ^ addr) & 0xFF00) \
|
||||
uExtraCycles=1;
|
||||
|
||||
#define READ_BYTE_ALT(pc) _READ_ALT(pc)
|
||||
#define READ_WORD_ALT(pc) (_READ_ALT(pc) | (_READ_ALT((pc+1))<<8))
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* ADDRESSING MODE MACROS
|
||||
*
|
||||
***/
|
||||
|
||||
#define ABS addr = *(LPWORD)(mem+regs.pc); regs.pc += 2;
|
||||
#define IABSX addr = *(LPWORD)(mem+(*(LPWORD)(mem+regs.pc))+(WORD)regs.x); regs.pc += 2;
|
||||
#define _ABS addr = *(LPWORD)(mem+regs.pc); regs.pc += 2;
|
||||
#define _ABS_ALT \
|
||||
addr = READ_WORD_ALT(regs.pc); \
|
||||
regs.pc += 2;
|
||||
|
||||
#define _IABSX addr = *(LPWORD)(mem+(*(LPWORD)(mem+regs.pc))+(WORD)regs.x); regs.pc += 2;
|
||||
#define _IABSX_ALT \
|
||||
base = READ_WORD_ALT(regs.pc) + (WORD)regs.x; \
|
||||
addr = READ_WORD_ALT(base); \
|
||||
regs.pc += 2;
|
||||
|
||||
// Not optimised for page-cross
|
||||
#define _ABSX_CONST base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.x; regs.pc += 2;
|
||||
#define _ABSX_CONST_ALT \
|
||||
base = READ_WORD_ALT(regs.pc); \
|
||||
addr = base + (WORD)regs.x; \
|
||||
regs.pc += 2;
|
||||
|
||||
// Optimised for page-cross
|
||||
#define ABSX_OPT base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.x; regs.pc += 2; CHECK_PAGE_CHANGE;
|
||||
#define _ABSX_OPT _ABSX_CONST; CHECK_PAGE_CHANGE;
|
||||
#define _ABSX_OPT_ALT _ABSX_CONST_ALT; CHECK_PAGE_CHANGE;
|
||||
|
||||
// Not optimised for page-cross
|
||||
#define ABSX_CONST base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.x; regs.pc += 2;
|
||||
#define _ABSY_CONST base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.y; regs.pc += 2;
|
||||
#define _ABSY_CONST_ALT \
|
||||
base = READ_WORD_ALT(regs.pc); \
|
||||
addr = base + (WORD)regs.y; \
|
||||
regs.pc += 2;
|
||||
|
||||
// Optimised for page-cross
|
||||
#define ABSY_OPT base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.y; regs.pc += 2; CHECK_PAGE_CHANGE;
|
||||
// Not optimised for page-cross
|
||||
#define ABSY_CONST base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.y; regs.pc += 2;
|
||||
#define _ABSY_OPT _ABSY_CONST; CHECK_PAGE_CHANGE;
|
||||
#define _ABSY_OPT_ALT _ABSY_CONST_ALT; CHECK_PAGE_CHANGE;
|
||||
|
||||
// TODO Optimization Note (just for IABSCMOS): uExtraCycles = ((base & 0xFF) + 1) >> 8;
|
||||
#define IABS_CMOS base = *(LPWORD)(mem+regs.pc); \
|
||||
addr = *(LPWORD)(mem+base); \
|
||||
if ((base & 0xFF) == 0xFF) uExtraCycles=1; \
|
||||
#define _IABS_CMOS base = *(LPWORD)(mem+regs.pc); \
|
||||
addr = *(LPWORD)(mem+base); \
|
||||
if ((base & 0xFF) == 0xFF) uExtraCycles=1; \
|
||||
regs.pc += 2;
|
||||
#define IABS_NMOS base = *(LPWORD)(mem+regs.pc); \
|
||||
if ((base & 0xFF) == 0xFF) \
|
||||
addr = *(mem+base)+((WORD)*(mem+(base&0xFF00))<<8);\
|
||||
#define _IABS_CMOS_ALT \
|
||||
base = READ_WORD_ALT(regs.pc); \
|
||||
addr = READ_WORD_ALT(base); \
|
||||
if ((base & 0xFF) == 0xFF) uExtraCycles=1; \
|
||||
regs.pc += 2;
|
||||
|
||||
#define _IABS_NMOS base = *(LPWORD)(mem+regs.pc); \
|
||||
if ((base & 0xFF) == 0xFF) \
|
||||
addr = *(mem+base)+((WORD)*(mem+(base&0xFF00))<<8); \
|
||||
else \
|
||||
addr = *(LPWORD)(mem+base); \
|
||||
addr = *(LPWORD)(mem+base); \
|
||||
regs.pc += 2;
|
||||
#define _IABS_NMOS_ALT \
|
||||
base = READ_WORD_ALT(regs.pc); \
|
||||
if ((base & 0xFF) == 0xFF) \
|
||||
addr = READ_BYTE_ALT(base) | (READ_BYTE_ALT((base&0xFF00))<<8); /* NB. Requires double-parenthesis for 2nd macro */\
|
||||
else \
|
||||
addr = READ_WORD_ALT(base); \
|
||||
regs.pc += 2;
|
||||
|
||||
#define IMM addr = regs.pc++;
|
||||
|
||||
#define INDX base = ((*(mem+regs.pc++))+regs.x) & 0xFF; \
|
||||
if (base == 0xFF) \
|
||||
addr = *(mem+0xFF)+(((WORD)*mem)<<8); \
|
||||
else \
|
||||
#define _INDX base = ((*(mem+regs.pc++))+regs.x) & 0xFF; \
|
||||
if (base == 0xFF) \
|
||||
addr = *(mem+0xFF)+(((WORD)*mem)<<8); \
|
||||
else \
|
||||
addr = *(LPWORD)(mem+base);
|
||||
#define _INDX_ALT \
|
||||
base = (READ_BYTE_ALT(regs.pc)+regs.x) & 0xFF; regs.pc++; \
|
||||
if (base == 0xFF) \
|
||||
addr = READ_BYTE_ALT(0xFF) | (READ_BYTE_ALT(0x00)<<8); \
|
||||
else \
|
||||
addr = READ_WORD_ALT(base);
|
||||
|
||||
// Not optimised for page-cross
|
||||
#define _INDY_CONST if (*(mem+regs.pc) == 0xFF) /*no extra cycle for page-crossing*/ \
|
||||
base = *(mem+0xFF)+(((WORD)*mem)<<8); \
|
||||
else \
|
||||
base = *(LPWORD)(mem+*(mem+regs.pc)); \
|
||||
regs.pc++; \
|
||||
addr = base+(WORD)regs.y;
|
||||
#define _INDY_CONST_ALT \
|
||||
base = READ_BYTE_ALT(regs.pc); \
|
||||
if (base == 0xFF) \
|
||||
base = READ_BYTE_ALT(0xFF) | (READ_BYTE_ALT(0x00)<<8); \
|
||||
else \
|
||||
base = READ_WORD_ALT(base); \
|
||||
regs.pc++; \
|
||||
addr = base+(WORD)regs.y;
|
||||
|
||||
// Optimised for page-cross
|
||||
#define INDY_OPT if (*(mem+regs.pc) == 0xFF) /*incurs an extra cycle for page-crossing*/ \
|
||||
base = *(mem+0xFF)+(((WORD)*mem)<<8); \
|
||||
else \
|
||||
base = *(LPWORD)(mem+*(mem+regs.pc)); \
|
||||
regs.pc++; \
|
||||
addr = base+(WORD)regs.y; \
|
||||
CHECK_PAGE_CHANGE;
|
||||
// Not optimised for page-cross
|
||||
#define INDY_CONST if (*(mem+regs.pc) == 0xFF) /*no extra cycle for page-crossing*/ \
|
||||
base = *(mem+0xFF)+(((WORD)*mem)<<8); \
|
||||
else \
|
||||
base = *(LPWORD)(mem+*(mem+regs.pc)); \
|
||||
regs.pc++; \
|
||||
addr = base+(WORD)regs.y;
|
||||
#define _INDY_OPT _INDY_CONST; CHECK_PAGE_CHANGE;
|
||||
#define _INDY_OPT_ALT _INDY_CONST_ALT; CHECK_PAGE_CHANGE;
|
||||
|
||||
#define IZPG base = *(mem+regs.pc++); \
|
||||
if (base == 0xFF) \
|
||||
addr = *(mem+0xFF)+(((WORD)*mem)<<8); \
|
||||
else \
|
||||
#define _IZPG base = *(mem+regs.pc++); \
|
||||
if (base == 0xFF) \
|
||||
addr = *(mem+0xFF)+(((WORD)*mem)<<8); \
|
||||
else \
|
||||
addr = *(LPWORD)(mem+base);
|
||||
#define _IZPG_ALT \
|
||||
base = READ_BYTE_ALT(regs.pc); regs.pc++; \
|
||||
if (base == 0xFF) \
|
||||
addr = READ_BYTE_ALT(0xFF) | (READ_BYTE_ALT(0x00)<<8); \
|
||||
else \
|
||||
addr = READ_WORD_ALT(base);
|
||||
|
||||
#define REL addr = (signed char)*(mem+regs.pc++);
|
||||
#define _REL addr = (signed char)*(mem+regs.pc++);
|
||||
#define _REL_ALT addr = (signed char)READ_BYTE_ALT(regs.pc); regs.pc++;
|
||||
|
||||
// TODO Optimization Note:
|
||||
// . Opcodes that generate zero-page addresses can't be accessing $C000..$CFFF
|
||||
// so they could be paired with special READZP/WRITEZP macros (instead of READ/WRITE)
|
||||
#define ZPG addr = *(mem+regs.pc++);
|
||||
#define ZPGX addr = ((*(mem+regs.pc++))+regs.x) & 0xFF;
|
||||
#define ZPGY addr = ((*(mem+regs.pc++))+regs.y) & 0xFF;
|
||||
#define _ZPG addr = *(mem+regs.pc++);
|
||||
#define _ZPGX addr = ((*(mem+regs.pc++))+regs.x) & 0xFF;
|
||||
#define _ZPGY addr = ((*(mem+regs.pc++))+regs.y) & 0xFF;
|
||||
|
||||
// Tidy 3 char addressing modes to keep the opcode table visually aligned, clean, and readable.
|
||||
#define _ZPG_ALT addr = READ_BYTE_ALT(regs.pc); regs.pc++;
|
||||
#define _ZPGX_ALT addr = (READ_BYTE_ALT(regs.pc) + regs.x) & 0xFF; regs.pc++;
|
||||
#define _ZPGY_ALT addr = (READ_BYTE_ALT(regs.pc) + regs.y) & 0xFF; regs.pc++;
|
||||
|
||||
// Tidy 3 char opcodes & addressing modes to keep the opcode table visually aligned, clean, and readable.
|
||||
#undef asl
|
||||
#undef lsr
|
||||
#undef rol
|
||||
#undef ror
|
||||
|
||||
#define asl ASLA
|
||||
#define lsr LSRA
|
||||
#define rol ROLA
|
||||
#define ror RORA
|
||||
|
||||
#undef idx
|
||||
#undef imm
|
||||
#undef izp
|
||||
#undef lsr
|
||||
#undef rel
|
||||
#undef rol
|
||||
#undef ror
|
||||
#undef zpx
|
||||
#undef zpy
|
||||
|
||||
#define asl ASLA // Arithmetic Shift Left
|
||||
#define idx INDX
|
||||
#define imm IMM
|
||||
#define izp IZPG
|
||||
#define lsr LSRA // Logical Shift Right
|
||||
#define rel REL
|
||||
#define rol ROLA // Rotate Left
|
||||
#define ror RORA // Rotate Right
|
||||
#define zpx ZPGX
|
||||
#define zpy ZPGY
|
||||
|
||||
@@ -50,13 +50,13 @@ inline void Heatmap_X(uint16_t address)
|
||||
inline uint8_t Heatmap_ReadByte(uint16_t addr, int uExecutedCycles)
|
||||
{
|
||||
Heatmap_R(addr);
|
||||
return _READ;
|
||||
return _READ(addr);
|
||||
}
|
||||
|
||||
inline uint8_t Heatmap_ReadByte_With_IO_F8xx(uint16_t addr, int uExecutedCycles)
|
||||
{
|
||||
Heatmap_R(addr);
|
||||
return _READ_WITH_IO_F8xx;
|
||||
return _READ_WITH_IO_F8xx(addr);
|
||||
}
|
||||
|
||||
inline void Heatmap_WriteByte(uint16_t addr, uint16_t value, int uExecutedCycles)
|
||||
|
||||
@@ -173,7 +173,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// ==========
|
||||
|
||||
#define ADC_NMOS /*bSlowerOnPagecross = 1;*/ \
|
||||
temp = READ; \
|
||||
temp = READ(addr); \
|
||||
if (regs.ps & AF_DECIMAL) { \
|
||||
val = (regs.a & 0x0F) + (temp & 0x0F) + flagc; \
|
||||
if (val > 0x09) \
|
||||
@@ -199,7 +199,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
SETNZ(regs.a); \
|
||||
}
|
||||
#define ADC_CMOS /*bSlowerOnPagecross = 1*/; \
|
||||
temp = READ; \
|
||||
temp = READ(addr); \
|
||||
flagv = !((regs.a ^ temp) & 0x80); \
|
||||
if (regs.ps & AF_DECIMAL) { \
|
||||
uExtraCycles++; \
|
||||
@@ -232,18 +232,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
} \
|
||||
regs.a = val & 0xFF; \
|
||||
SETNZ(regs.a)
|
||||
#define ALR regs.a &= READ; \
|
||||
#define ALR regs.a &= READ(addr); \
|
||||
flagc = (regs.a & 1); \
|
||||
flagn = 0; \
|
||||
regs.a >>= 1; \
|
||||
SETZ(regs.a)
|
||||
#define AND /*bSlowerOnPagecross = 1;*/ \
|
||||
regs.a &= READ; \
|
||||
regs.a &= READ(addr); \
|
||||
SETNZ(regs.a)
|
||||
#define ANC regs.a &= READ; \
|
||||
#define ANC regs.a &= READ(addr); \
|
||||
SETNZ(regs.a) \
|
||||
flagc = !!flagn;
|
||||
#define ARR temp = regs.a & READ; /* Yes, this is sick */ \
|
||||
#define ARR temp = regs.a & READ(addr); /* Yes, this is sick */ \
|
||||
if (regs.ps & AF_DECIMAL) { \
|
||||
val = temp; \
|
||||
val |= (flagc ? 0x100 : 0); \
|
||||
@@ -270,12 +270,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
regs.a = (val & 0xFF); \
|
||||
}
|
||||
#define ASL_NMOS /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ << 1; \
|
||||
val = READ(addr) << 1; \
|
||||
flagc = (val > 0xFF); \
|
||||
SETNZ(val) \
|
||||
WRITE(val)
|
||||
#define ASL_CMOS /*bSlowerOnPagecross = 1*/; \
|
||||
val = READ << 1; \
|
||||
val = READ(addr) << 1; \
|
||||
flagc = (val > 0xFF); \
|
||||
SETNZ(val) \
|
||||
WRITE(val)
|
||||
@@ -284,7 +284,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
SETNZ(val) \
|
||||
regs.a = (BYTE)val;
|
||||
#define ASO /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ << 1; \
|
||||
val = READ(addr) << 1; \
|
||||
flagc = (val > 0xFF); \
|
||||
WRITE(val) \
|
||||
regs.a |= val; \
|
||||
@@ -299,30 +299,45 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define BCS if ( flagc) BRANCH_TAKEN;
|
||||
#define BEQ if ( flagz) BRANCH_TAKEN;
|
||||
#define BIT /*bSlowerOnPagecross = 1;*/ \
|
||||
val = READ; \
|
||||
val = READ(addr); \
|
||||
flagz = !(regs.a & val); \
|
||||
flagn = val & 0x80; \
|
||||
flagv = val & 0x40;
|
||||
#define BITI flagz = !(regs.a & READ);
|
||||
#define BITI flagz = !(regs.a & READ(addr));
|
||||
#define BMI if ( flagn) BRANCH_TAKEN;
|
||||
#define BNE if (!flagz) BRANCH_TAKEN;
|
||||
#define BPL if (!flagn) BRANCH_TAKEN;
|
||||
#define BRA BRANCH_TAKEN;
|
||||
#define BRK_NMOS regs.pc++; \
|
||||
#define _BRK_NMOS regs.pc++; \
|
||||
PUSH(regs.pc >> 8) \
|
||||
PUSH(regs.pc & 0xFF) \
|
||||
EF_TO_AF \
|
||||
PUSH(regs.ps); \
|
||||
regs.ps |= AF_INTERRUPT; \
|
||||
regs.pc = *(LPWORD)(mem+0xFFFE);
|
||||
#define BRK_CMOS regs.pc++; \
|
||||
regs.pc = *(LPWORD)(mem+_6502_INTERRUPT_VECTOR);
|
||||
#define _BRK_NMOS_ALT regs.pc++; \
|
||||
PUSH(regs.pc >> 8) \
|
||||
PUSH(regs.pc & 0xFF) \
|
||||
EF_TO_AF \
|
||||
PUSH(regs.ps); \
|
||||
regs.ps |= AF_INTERRUPT; \
|
||||
regs.pc = READ_WORD_ALT(_6502_INTERRUPT_VECTOR);
|
||||
#define _BRK_CMOS regs.pc++; \
|
||||
PUSH(regs.pc >> 8) \
|
||||
PUSH(regs.pc & 0xFF) \
|
||||
EF_TO_AF \
|
||||
PUSH(regs.ps); \
|
||||
regs.ps |= AF_INTERRUPT; \
|
||||
regs.ps &= ~AF_DECIMAL; /*CMOS clears D flag*/ \
|
||||
regs.pc = *(LPWORD)(mem+0xFFFE);
|
||||
regs.pc = *(LPWORD)(mem+_6502_INTERRUPT_VECTOR);
|
||||
#define _BRK_CMOS_ALT regs.pc++; \
|
||||
PUSH(regs.pc >> 8) \
|
||||
PUSH(regs.pc & 0xFF) \
|
||||
EF_TO_AF \
|
||||
PUSH(regs.ps); \
|
||||
regs.ps |= AF_INTERRUPT; \
|
||||
regs.ps &= ~AF_DECIMAL; /*CMOS clears D flag*/ \
|
||||
regs.pc = READ_WORD_ALT(_6502_INTERRUPT_VECTOR);
|
||||
#define BVC if (!flagv) BRANCH_TAKEN;
|
||||
#define BVS if ( flagv) BRANCH_TAKEN;
|
||||
#define CLC flagc = 0;
|
||||
@@ -330,20 +345,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define CLI regs.ps &= ~AF_INTERRUPT;
|
||||
#define CLV flagv = 0;
|
||||
#define CMP /*bSlowerOnPagecross = 1;*/ \
|
||||
val = READ; \
|
||||
val = READ(addr); \
|
||||
flagc = (regs.a >= val); \
|
||||
val = regs.a-val; \
|
||||
SETNZ(val)
|
||||
#define CPX val = READ; \
|
||||
#define CPX val = READ(addr); \
|
||||
flagc = (regs.x >= val); \
|
||||
val = regs.x-val; \
|
||||
SETNZ(val)
|
||||
#define CPY val = READ; \
|
||||
#define CPY val = READ(addr); \
|
||||
flagc = (regs.y >= val); \
|
||||
val = regs.y-val; \
|
||||
SETNZ(val)
|
||||
#define DCM /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ-1; \
|
||||
val = READ(addr)-1; \
|
||||
WRITE(val) \
|
||||
flagc = (regs.a >= val); \
|
||||
val = regs.a-val; \
|
||||
@@ -351,7 +366,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define DEA --regs.a; \
|
||||
SETNZ(regs.a)
|
||||
#define DEC /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ-1; \
|
||||
val = READ(addr)-1; \
|
||||
SETNZ(val) \
|
||||
WRITE(val)
|
||||
#define DEX --regs.x; \
|
||||
@@ -359,18 +374,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define DEY --regs.y; \
|
||||
SETNZ(regs.y)
|
||||
#define EOR /*bSlowerOnPagecross = 1;*/ \
|
||||
regs.a ^= READ; \
|
||||
regs.a ^= READ(addr); \
|
||||
SETNZ(regs.a)
|
||||
#define HLT regs.bJammed = 1; \
|
||||
--regs.pc;
|
||||
#define INA ++regs.a; \
|
||||
SETNZ(regs.a)
|
||||
#define INC /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ+1; \
|
||||
val = READ(addr)+1; \
|
||||
SETNZ(val) \
|
||||
WRITE(val)
|
||||
#define INS /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ+1; \
|
||||
val = READ(addr)+1; \
|
||||
WRITE(val) \
|
||||
temp = val; \
|
||||
temp2 = regs.a - temp - !flagc; \
|
||||
@@ -400,45 +415,51 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define INY ++regs.y; \
|
||||
SETNZ(regs.y)
|
||||
#define JMP regs.pc = addr;
|
||||
#define JSR addr = *(LPBYTE)(mem+regs.pc); regs.pc++; \
|
||||
#define _JSR addr = *(LPBYTE)(mem+regs.pc); regs.pc++; \
|
||||
PUSH(regs.pc >> 8) \
|
||||
PUSH(regs.pc & 0xFF) \
|
||||
regs.pc = addr | (*(LPBYTE)(mem+regs.pc)) << 8; /* GH#1257 */
|
||||
#define _JSR_ALT \
|
||||
addr = READ_BYTE_ALT(regs.pc); \
|
||||
regs.pc++; \
|
||||
PUSH(regs.pc >> 8) \
|
||||
PUSH(regs.pc & 0xFF) \
|
||||
regs.pc = addr | READ_BYTE_ALT(regs.pc) << 8; /* GH#1257 */
|
||||
#define LAS /*bSlowerOnPagecross = 1*/; \
|
||||
val = (BYTE)(READ & regs.sp); \
|
||||
val = (BYTE)(READ(addr) & regs.sp); \
|
||||
regs.a = regs.x = (BYTE) val; \
|
||||
regs.sp = val | 0x100; \
|
||||
SETNZ(val)
|
||||
#define LAX /*bSlowerOnPagecross = 1;*/ \
|
||||
regs.a = regs.x = READ; \
|
||||
regs.a = regs.x = READ(addr); \
|
||||
SETNZ(regs.a)
|
||||
#define LDA /*bSlowerOnPagecross = 1;*/ \
|
||||
regs.a = READ; \
|
||||
regs.a = READ(addr); \
|
||||
SETNZ(regs.a)
|
||||
#define LDD /*Undocumented 65C02: LoaD and Discard*/ \
|
||||
READ;
|
||||
READ(addr);
|
||||
#define LDX /*bSlowerOnPagecross = 1;*/ \
|
||||
regs.x = READ; \
|
||||
regs.x = READ(addr); \
|
||||
SETNZ(regs.x)
|
||||
#define LDY /*bSlowerOnPagecross = 1;*/ \
|
||||
regs.y = READ; \
|
||||
regs.y = READ(addr); \
|
||||
SETNZ(regs.y)
|
||||
#define LSE /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ; \
|
||||
val = READ(addr); \
|
||||
flagc = (val & 1); \
|
||||
val >>= 1; \
|
||||
WRITE(val) \
|
||||
regs.a ^= val; \
|
||||
SETNZ(regs.a)
|
||||
#define LSR_NMOS /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ; \
|
||||
val = READ(addr); \
|
||||
flagc = (val & 1); \
|
||||
flagn = 0; \
|
||||
val >>= 1; \
|
||||
SETZ(val) \
|
||||
WRITE(val)
|
||||
#define LSR_CMOS /*bSlowerOnPagecross = 1;*/ \
|
||||
val = READ; \
|
||||
val = READ(addr); \
|
||||
flagc = (val & 1); \
|
||||
flagn = 0; \
|
||||
val >>= 1; \
|
||||
@@ -450,11 +471,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
SETZ(regs.a)
|
||||
#define NOP /*bSlowerOnPagecross = 1;*/
|
||||
#define OAL regs.a |= 0xEE; \
|
||||
regs.a &= READ; \
|
||||
regs.a &= READ(addr); \
|
||||
regs.x = regs.a; \
|
||||
SETNZ(regs.a)
|
||||
#define ORA /*bSlowerOnPagecross = 1;*/ \
|
||||
regs.a |= READ; \
|
||||
regs.a |= READ(addr); \
|
||||
SETNZ(regs.a)
|
||||
#define PHA PUSH(regs.a)
|
||||
#define PHP EF_TO_AF \
|
||||
@@ -470,18 +491,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define PLY regs.y = POP; \
|
||||
SETNZ(regs.y)
|
||||
#define RLA /*bSlowerOnPagecross = 0;*/ \
|
||||
val = (READ << 1) | flagc; \
|
||||
val = (READ(addr) << 1) | flagc; \
|
||||
flagc = (val > 0xFF); \
|
||||
WRITE(val) \
|
||||
regs.a &= val; \
|
||||
SETNZ(regs.a)
|
||||
#define ROL_NMOS /*bSlowerOnPagecross = 0;*/ \
|
||||
val = (READ << 1) | flagc; \
|
||||
val = (READ(addr) << 1) | flagc; \
|
||||
flagc = (val > 0xFF); \
|
||||
SETNZ(val) \
|
||||
WRITE(val)
|
||||
#define ROL_CMOS /*bSlowerOnPagecross = 1;*/ \
|
||||
val = (READ << 1) | flagc; \
|
||||
val = (READ(addr) << 1) | flagc; \
|
||||
flagc = (val > 0xFF); \
|
||||
SETNZ(val) \
|
||||
WRITE(val)
|
||||
@@ -490,13 +511,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
regs.a = val & 0xFF; \
|
||||
SETNZ(regs.a);
|
||||
#define ROR_NMOS /*bSlowerOnPagecross = 0;*/ \
|
||||
temp = READ; \
|
||||
temp = READ(addr); \
|
||||
val = (temp >> 1) | (flagc ? 0x80 : 0); \
|
||||
flagc = (temp & 1); \
|
||||
SETNZ(val) \
|
||||
WRITE(val)
|
||||
#define ROR_CMOS /*bSlowerOnPagecross = 1;*/ \
|
||||
temp = READ; \
|
||||
temp = READ(addr); \
|
||||
val = (temp >> 1) | (flagc ? 0x80 : 0); \
|
||||
flagc = (temp & 1); \
|
||||
SETNZ(val) \
|
||||
@@ -506,7 +527,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
regs.a = val & 0xFF; \
|
||||
SETNZ(regs.a)
|
||||
#define RRA /*bSlowerOnPagecross = 0;*/ \
|
||||
temp = READ; \
|
||||
temp = READ(addr); \
|
||||
val = (temp >> 1) | (flagc ? 0x80 : 0); \
|
||||
flagc = (temp & 1); \
|
||||
WRITE(val) \
|
||||
@@ -543,7 +564,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
regs.pc |= (((WORD)POP) << 8); \
|
||||
++regs.pc;
|
||||
#define SAX temp = regs.a & regs.x; \
|
||||
val = READ; \
|
||||
val = READ(addr); \
|
||||
flagc = (temp >= val); \
|
||||
regs.x = temp-val; \
|
||||
SETNZ(regs.x)
|
||||
@@ -552,7 +573,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
ON_PAGECROSS_REPLACE_HI_ADDR \
|
||||
WRITE(val)
|
||||
#define SBC_NMOS /*bSlowerOnPagecross = 1;*/ \
|
||||
temp = READ; \
|
||||
temp = READ(addr); \
|
||||
temp2 = regs.a - temp - !flagc; \
|
||||
if (regs.ps & AF_DECIMAL) { \
|
||||
val = (regs.a & 0x0F) - (temp & 0x0F) - !flagc; \
|
||||
@@ -576,7 +597,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
SETNZ(regs.a); \
|
||||
}
|
||||
#define SBC_CMOS /*bSlowerOnPagecross = 1;*/ \
|
||||
temp = READ; \
|
||||
temp = READ(addr); \
|
||||
flagv = ((regs.a ^ temp) & 0x80); \
|
||||
if (regs.ps & AF_DECIMAL) { \
|
||||
uExtraCycles++; \
|
||||
@@ -640,12 +661,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define TAY regs.y = regs.a; \
|
||||
SETNZ(regs.y)
|
||||
#define TRB /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ; \
|
||||
val = READ(addr); \
|
||||
flagz = !(regs.a & val); \
|
||||
val &= ~regs.a; \
|
||||
WRITE(val)
|
||||
#define TSB /*bSlowerOnPagecross = 0;*/ \
|
||||
val = READ; \
|
||||
val = READ(addr); \
|
||||
flagz = !(regs.a & val); \
|
||||
val |= regs.a; \
|
||||
WRITE(val)
|
||||
@@ -657,7 +678,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#define TYA regs.a = regs.y; \
|
||||
SETNZ(regs.a)
|
||||
#define XAA regs.a = regs.x; \
|
||||
regs.a &= READ; \
|
||||
regs.a &= READ(addr); \
|
||||
SETNZ(regs.a)
|
||||
#define XAS /*bSlowerOnPagecross = 0;*/ \
|
||||
val = regs.x & (((base >> 8) + 1) & 0xFF); \
|
||||
|
||||
+3
-3
@@ -154,9 +154,9 @@ void LogFileTimeUntilFirstKeyRead(void)
|
||||
if (!g_fh || bLogKeyReadDone)
|
||||
return;
|
||||
|
||||
if ( (mem[regs.pc-3] != 0x2C) // AZTEC: bit $c000
|
||||
&& !((regs.pc-2) == 0xE797 && mem[regs.pc-2] == 0xB1 && mem[regs.pc-1] == 0x50) // Phasor1: lda ($50),y
|
||||
&& !((regs.pc-3) == 0x0895 && mem[regs.pc-3] == 0xAD) // Rescue Raiders v1.3,v1.5: lda $c000
|
||||
if ( (ReadByteFromMemory(regs.pc-3) != 0x2C) // AZTEC: bit $c000
|
||||
&& !((regs.pc-2) == 0xE797 && ReadByteFromMemory(regs.pc-2) == 0xB1 && ReadByteFromMemory(regs.pc-1) == 0x50) // Phasor1: lda ($50),y
|
||||
&& !((regs.pc-3) == 0x0895 && ReadByteFromMemory(regs.pc-3) == 0xAD) // Rescue Raiders v1.3,v1.5: lda $c000
|
||||
)
|
||||
return;
|
||||
|
||||
|
||||
+77
-81
@@ -32,7 +32,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Debug.h"
|
||||
#include "DebugDefs.h"
|
||||
#include "Debugger_Win32.h"
|
||||
|
||||
#include "../Windows/AppleWin.h"
|
||||
@@ -1284,7 +1283,7 @@ int CheckBreakpointsIO ()
|
||||
if (_CheckBreakpointValue( pBP, nAddress ))
|
||||
{
|
||||
g_uBreakMemoryAddress = (WORD) nAddress;
|
||||
BYTE opcode = mem[regs.pc];
|
||||
BYTE opcode = ReadByteFromMemory(regs.pc);
|
||||
|
||||
if (pBP->eSource == BP_SRC_MEM_RW)
|
||||
{
|
||||
@@ -1465,7 +1464,7 @@ Update_t CmdBreakpointAddSmart (int nArgs)
|
||||
g_aArgs[ nArgs ].nValue = g_nDisasmCurAddress;
|
||||
}
|
||||
|
||||
if ((nAddress >= _6502_IO_BEGIN) && (nAddress <= _6502_IO_END))
|
||||
if ((nAddress >= APPLE_IO_BEGIN) && (nAddress <= APPLE_IO_END))
|
||||
{
|
||||
return CmdBreakpointAddIO( nArgs );
|
||||
}
|
||||
@@ -2292,9 +2291,9 @@ Update_t CmdStepOver (int nArgs)
|
||||
// g_nDebugSteps = nArgs ? g_aArgs[1].nValue : 1;
|
||||
WORD nDebugSteps = nArgs ? g_aArgs[1].nValue : 1;
|
||||
|
||||
while (nDebugSteps -- > 0)
|
||||
while (nDebugSteps-- > 0)
|
||||
{
|
||||
int nOpcode = *(mem + regs.pc);
|
||||
BYTE nOpcode = ReadByteFromMemory(regs.pc);
|
||||
WORD nExpectedAddr = (regs.pc + 3) & _6502_MEM_END; // Wrap around 64K edge case when PC = $FFFD..$FFFF: 20 xx xx
|
||||
// int eMode = g_aOpcodes[ nOpcode ].addrmode;
|
||||
// int nByte = g_aOpmodes[eMode]._nBytes;
|
||||
@@ -2518,17 +2517,12 @@ Update_t CmdJSR (int nArgs)
|
||||
|
||||
WORD nAddress = g_aArgs[1].nValue & _6502_MEM_END;
|
||||
|
||||
// Mark Stack Page as dirty
|
||||
*(memdirty+(regs.sp >> 8)) = 1;
|
||||
|
||||
// Push PC onto stack
|
||||
*(mem + regs.sp) = ((regs.pc >> 8) & 0xFF);
|
||||
WriteByteToMemory(regs.sp, ((regs.pc >> 8) & 0xFF));
|
||||
regs.sp--;
|
||||
|
||||
*(mem + regs.sp) = ((regs.pc >> 0) - 1) & 0xFF;
|
||||
WriteByteToMemory(regs.sp, ((regs.pc >> 0) - 1) & 0xFF);
|
||||
regs.sp--;
|
||||
|
||||
|
||||
// Jump to new address
|
||||
regs.pc = nAddress;
|
||||
|
||||
@@ -2547,7 +2541,7 @@ Update_t CmdNOP (int nArgs)
|
||||
|
||||
while (nOpbytes--)
|
||||
{
|
||||
*(mem+regs.pc + nOpbytes) = 0xEA;
|
||||
WriteByteToMemory(regs.pc + nOpbytes, 0xEA);
|
||||
}
|
||||
|
||||
return UPDATE_ALL;
|
||||
@@ -3828,27 +3822,27 @@ bool MemoryDumpCheck (int nArgs, WORD * pAddress_ )
|
||||
#ifdef SUPPORT_Z80_EMU
|
||||
else if (strcmp(g_aArgs[1].sArg, "*AF") == 0)
|
||||
{
|
||||
nAddress = *(WORD*)(mem + REG_AF);
|
||||
nAddress = ReadWordFromMemory(REG_AF);
|
||||
bUpdate = true;
|
||||
}
|
||||
else if (strcmp(g_aArgs[1].sArg, "*BC") == 0)
|
||||
{
|
||||
nAddress = *(WORD*)(mem + REG_BC);
|
||||
nAddress = ReadWordFromMemory(REG_BC);
|
||||
bUpdate = true;
|
||||
}
|
||||
else if (strcmp(g_aArgs[1].sArg, "*DE") == 0)
|
||||
{
|
||||
nAddress = *(WORD*)(mem + REG_DE);
|
||||
nAddress = ReadWordFromMemory(REG_DE);
|
||||
bUpdate = true;
|
||||
}
|
||||
else if (strcmp(g_aArgs[1].sArg, "*HL") == 0)
|
||||
{
|
||||
nAddress = *(WORD*)(mem + REG_HL);
|
||||
nAddress = ReadWordFromMemory(REG_HL);
|
||||
bUpdate = true;
|
||||
}
|
||||
else if (strcmp(g_aArgs[1].sArg, "*IX") == 0)
|
||||
{
|
||||
nAddress = *(WORD*)(mem + REG_IX);
|
||||
nAddress = ReadWordFromMemory(REG_IX);
|
||||
bUpdate = true;
|
||||
}
|
||||
#endif
|
||||
@@ -3999,16 +3993,17 @@ Update_t CmdMemoryEnterByte (int nArgs)
|
||||
while (nArgs >= 2)
|
||||
{
|
||||
WORD nData = g_aArgs[nArgs].nValue;
|
||||
if ( nData > 0xFF)
|
||||
|
||||
if (nData > 0xFF)
|
||||
{
|
||||
*(mem + nAddress + nArgs - 2) = (BYTE)(nData >> 0);
|
||||
*(mem + nAddress + nArgs - 1) = (BYTE)(nData >> 8);
|
||||
WriteByteToMemory(nAddress + nArgs - 2, (BYTE)(nData >> 0));
|
||||
WriteByteToMemory(nAddress + nArgs - 1, (BYTE)(nData >> 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
*(mem + nAddress+nArgs-2) = (BYTE)nData;
|
||||
WriteByteToMemory(nAddress + nArgs - 2, (BYTE)nData);
|
||||
}
|
||||
*(memdirty+(nAddress >> 8)) = 1;
|
||||
|
||||
nArgs--;
|
||||
}
|
||||
|
||||
@@ -4030,26 +4025,15 @@ Update_t CmdMemoryEnterWord (int nArgs)
|
||||
{
|
||||
WORD nData = g_aArgs[nArgs].nValue;
|
||||
|
||||
// Little Endian
|
||||
*(mem + nAddress + nArgs - 2) = (BYTE)(nData >> 0);
|
||||
*(mem + nAddress + nArgs - 1) = (BYTE)(nData >> 8);
|
||||
WriteByteToMemory(nAddress + nArgs - 2, (BYTE)(nData >> 0));
|
||||
WriteByteToMemory(nAddress + nArgs - 1, (BYTE)(nData >> 8));
|
||||
|
||||
*(memdirty+(nAddress >> 8)) |= 1;
|
||||
nArgs--;
|
||||
}
|
||||
|
||||
return UPDATE_ALL;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void MemMarkDirty ( WORD nAddressStart, WORD nAddressEnd )
|
||||
{
|
||||
for ( int iPage = (nAddressStart >> 8); iPage <= (nAddressEnd >> 8); iPage++ )
|
||||
{
|
||||
*(memdirty+iPage) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
Update_t CmdMemoryFill (int nArgs)
|
||||
{
|
||||
@@ -4085,15 +4069,13 @@ Update_t CmdMemoryFill (int nArgs)
|
||||
|
||||
if ((nAddressLen > 0) && (nAddressEnd <= _6502_MEM_END))
|
||||
{
|
||||
MemMarkDirty( nAddressStart, nAddressEnd );
|
||||
|
||||
nValue = g_aArgs[nArgs].nValue & 0xFF;
|
||||
while ( nAddressLen-- ) // v2.7.0.22
|
||||
{
|
||||
// TODO: Optimize - split into pre_io, and post_io
|
||||
if ((nAddress2 < _6502_IO_BEGIN) || (nAddress2 > _6502_IO_END))
|
||||
if ((nAddress2 < APPLE_IO_BEGIN) || (nAddress2 > APPLE_IO_END))
|
||||
{
|
||||
*(mem + nAddressStart) = nValue;
|
||||
WriteByteToMemory(nAddressStart, nValue);
|
||||
}
|
||||
nAddressStart++;
|
||||
}
|
||||
@@ -4231,7 +4213,7 @@ Update_t CmdConfigSetDebugDir (int nArgs)
|
||||
|
||||
|
||||
//===========================================================================
|
||||
#if 0 // Original
|
||||
#if 0 // Original - TODO: delete this old "original" code
|
||||
Update_t CmdMemoryLoad (int nArgs)
|
||||
{
|
||||
// BLOAD ["Filename"] , addr[, len]
|
||||
@@ -4297,7 +4279,6 @@ Update_t CmdMemoryLoad (int nArgs)
|
||||
}
|
||||
|
||||
BYTE *pMemory = new BYTE [ _6502_MEM_END + 1 ]; // default 64K buffer
|
||||
BYTE *pDst = mem + nAddressStart;
|
||||
BYTE *pSrc = pMemory;
|
||||
|
||||
if (bHaveFileName)
|
||||
@@ -4325,7 +4306,7 @@ Update_t CmdMemoryLoad (int nArgs)
|
||||
{
|
||||
for ( int iByte = 0; iByte < nAddressLen; iByte++ )
|
||||
{
|
||||
*pDst++ = *pSrc++;
|
||||
WriteByteToMemory(nAddressStart++, *pSrc++);
|
||||
}
|
||||
ConsoleBufferPush( "Loaded." );
|
||||
}
|
||||
@@ -4487,19 +4468,14 @@ Update_t CmdMemoryLoad (int nArgs)
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<BYTE> pMemory(new BYTE[_6502_MEM_END + 1]); // default 64K buffer
|
||||
|
||||
if (bHaveFileName)
|
||||
{
|
||||
g_sMemoryLoadSaveFileName = pFileName;
|
||||
}
|
||||
const std::string sLoadSaveFilePath = g_sCurrentDir + g_sMemoryLoadSaveFileName; // TODO: g_sDebugDir
|
||||
|
||||
BYTE * const pMemBankBase = bBankSpecified ? MemGetBankPtr(nBank) : mem;
|
||||
if (!pMemBankBase)
|
||||
{
|
||||
ConsoleBufferPush( "Error: Bank out of range." );
|
||||
return ConsoleUpdate();
|
||||
}
|
||||
|
||||
FILE *hFile = fopen( sLoadSaveFilePath.c_str(), "rb" );
|
||||
if (hFile)
|
||||
{
|
||||
@@ -4514,7 +4490,9 @@ Update_t CmdMemoryLoad (int nArgs)
|
||||
nAddressLen = nFileBytes;
|
||||
}
|
||||
|
||||
size_t nRead = fread( pMemBankBase+nAddressStart, nAddressLen, 1, hFile );
|
||||
size_t nRead = fread(pMemory.get() + nAddressStart, nAddressLen, 1, hFile);
|
||||
fclose(hFile);
|
||||
|
||||
if (nRead == 1)
|
||||
{
|
||||
ConsoleBufferPushFormat( "Loaded @ A$%04X,L$%04X", nAddressStart, nAddressLen );
|
||||
@@ -4522,18 +4500,27 @@ Update_t CmdMemoryLoad (int nArgs)
|
||||
else
|
||||
{
|
||||
ConsoleBufferPush( "Error loading data." );
|
||||
return ConsoleUpdate();
|
||||
}
|
||||
fclose( hFile );
|
||||
|
||||
if (bBankSpecified)
|
||||
{
|
||||
BYTE* const pMemBankBase = MemGetBankPtr(nBank);
|
||||
if (!pMemBankBase)
|
||||
{
|
||||
ConsoleBufferPush("Error: Bank out of range.");
|
||||
return ConsoleUpdate();
|
||||
}
|
||||
|
||||
memcpy(pMemBankBase + nAddressStart, pMemory.get() + nAddressStart, nAddressLen);
|
||||
|
||||
MemUpdatePaging(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WORD i=(nAddressStart>>8); i!=((nAddressStart+(WORD)nAddressLen)>>8); i++)
|
||||
for (WORD i=nAddressStart; i!=(nAddressStart+(WORD)nAddressLen); i++)
|
||||
{
|
||||
memdirty[i] = 0xff;
|
||||
WriteByteToMemory(i, pMemory.get()[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4578,18 +4565,13 @@ Update_t CmdMemoryMove (int nArgs)
|
||||
|
||||
if ((nAddressLen > 0) && (nAddressEnd <= _6502_MEM_END))
|
||||
{
|
||||
MemMarkDirty( nAddressStart, nAddressEnd );
|
||||
|
||||
// BYTE *pSrc = mem + nAddressStart;
|
||||
// BYTE *pDst = mem + nDst;
|
||||
// BYTE *pEnd = pSrc + nAddressLen;
|
||||
|
||||
while ( nAddressLen-- ) // v2.7.0.23
|
||||
{
|
||||
// TODO: Optimize - split into pre_io, and post_io
|
||||
if ((nDst < _6502_IO_BEGIN) || (nDst > _6502_IO_END))
|
||||
if ((nDst < APPLE_IO_BEGIN) || (nDst > APPLE_IO_END))
|
||||
{
|
||||
*(mem + nDst) = *(mem + nAddressStart);
|
||||
BYTE value = ReadByteFromMemory(nAddressStart);
|
||||
WriteByteToMemory(nDst, value);
|
||||
}
|
||||
nDst++;
|
||||
nAddressStart++;
|
||||
@@ -4602,7 +4584,7 @@ Update_t CmdMemoryMove (int nArgs)
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
#if 0 // Original
|
||||
#if 0 // Original - TODO: delete this old "original" code
|
||||
Update_t CmdMemorySave (int nArgs)
|
||||
{
|
||||
// BSAVE ["Filename"] , addr , len
|
||||
@@ -4684,12 +4666,11 @@ Update_t CmdMemorySave (int nArgs)
|
||||
{
|
||||
BYTE *pMemory = new BYTE [ nAddressLen ];
|
||||
BYTE *pDst = pMemory;
|
||||
BYTE *pSrc = mem + nAddressStart;
|
||||
|
||||
// memcpy -- copy out of active memory bank
|
||||
for ( int iByte = 0; iByte < nAddressLen; iByte++ )
|
||||
{
|
||||
*pDst++ = *pSrc++;
|
||||
*pDst++ = ReadByteFromMemory(nAddressStart + iByte);
|
||||
}
|
||||
|
||||
FILE *hFile = fopen( sLoadSaveFilePath, "rb" );
|
||||
@@ -4832,11 +4813,25 @@ Update_t CmdMemorySave (int nArgs)
|
||||
}
|
||||
sLoadSaveFilePath += g_sMemoryLoadSaveFileName;
|
||||
|
||||
const BYTE * const pMemBankBase = bBankSpecified ? MemGetBankPtr(nBank) : mem;
|
||||
if (!pMemBankBase)
|
||||
std::unique_ptr<BYTE> pMemory(new BYTE[_6502_MEM_END + 1]); // default 64K buffer
|
||||
|
||||
if (bBankSpecified)
|
||||
{
|
||||
ConsoleBufferPush( "Error: Bank out of range." );
|
||||
return ConsoleUpdate();
|
||||
const BYTE* const pMemBankBase = MemGetBankPtr(nBank);
|
||||
if (!pMemBankBase)
|
||||
{
|
||||
ConsoleBufferPush("Error: Bank out of range.");
|
||||
return ConsoleUpdate();
|
||||
}
|
||||
|
||||
memcpy(pMemory.get() + nAddressStart, pMemBankBase + nAddressStart, nAddressLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WORD i = nAddressStart; i != (nAddressStart + (WORD)nAddressLen); i++)
|
||||
{
|
||||
pMemory.get()[i] = ReadByteFromMemory(i);
|
||||
}
|
||||
}
|
||||
|
||||
FILE *hFile = fopen( sLoadSaveFilePath.c_str(), "rb" );
|
||||
@@ -4850,22 +4845,23 @@ Update_t CmdMemorySave (int nArgs)
|
||||
hFile = fopen( sLoadSaveFilePath.c_str(), "wb" );
|
||||
if (hFile)
|
||||
{
|
||||
size_t nWrote = fwrite( pMemBankBase+nAddressStart, nAddressLen, 1, hFile );
|
||||
size_t nWrote = fwrite(pMemory.get() + nAddressStart, nAddressLen, 1, hFile);
|
||||
fclose(hFile);
|
||||
|
||||
if (nWrote == 1)
|
||||
{
|
||||
ConsoleBufferPush( "Saved." );
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleBufferPush( "Error saving." );
|
||||
}
|
||||
fclose( hFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleBufferPush( "Error opening file." );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleBufferPush("Error: Length = 0.");
|
||||
}
|
||||
}
|
||||
|
||||
return ConsoleUpdate();
|
||||
@@ -5727,7 +5723,7 @@ int _SearchMemoryFind (
|
||||
(ms.m_iType == MEM_SEARCH_NIB_HIGH_EXACT) ||
|
||||
(ms.m_iType == MEM_SEARCH_NIB_LOW_EXACT ))
|
||||
{
|
||||
BYTE nTarget = *(mem + nAddress2);
|
||||
BYTE nTarget = ReadByteFromMemory(nAddress2);
|
||||
|
||||
if (ms.m_iType == MEM_SEARCH_NIB_LOW_EXACT)
|
||||
nTarget &= 0x0F;
|
||||
@@ -5764,7 +5760,7 @@ int _SearchMemoryFind (
|
||||
(ms.m_iType == MEM_SEARCH_NIB_HIGH_EXACT) ||
|
||||
(ms.m_iType == MEM_SEARCH_NIB_LOW_EXACT ))
|
||||
{
|
||||
BYTE nTarget = *(mem + nAddress3);
|
||||
BYTE nTarget = ReadByteFromMemory(nAddress3);
|
||||
|
||||
if (ms.m_iType == MEM_SEARCH_NIB_LOW_EXACT)
|
||||
nTarget &= 0x0F;
|
||||
@@ -6566,7 +6562,7 @@ bool ParseAssemblyListing ( bool bBytesToMemory, bool bAddSymbols )
|
||||
if (TextIsHexByte( pStart ))
|
||||
{
|
||||
BYTE nByte = TextConvert2CharsToByte( pStart );
|
||||
*(mem + ((WORD)nAddress) + iByte ) = nByte;
|
||||
WriteByteToMemory(((WORD)nAddress) + iByte, nByte);
|
||||
}
|
||||
}
|
||||
g_nSourceAssembleBytes += iByte;
|
||||
@@ -7002,7 +6998,7 @@ Update_t CmdWatchAdd (int nArgs)
|
||||
WORD nAddress = g_aArgs[iArg].nValue;
|
||||
|
||||
// Make sure address isn't an IO address
|
||||
if ((nAddress >= _6502_IO_BEGIN) && (nAddress <= _6502_IO_END))
|
||||
if ((nAddress >= APPLE_IO_BEGIN) && (nAddress <= APPLE_IO_END))
|
||||
return ConsoleDisplayError("You cannot watch an I/O location.");
|
||||
|
||||
if (iWatch == NO_6502_TARGET)
|
||||
@@ -8611,7 +8607,7 @@ static void CheckBreakOpcode ( int iOpcode )
|
||||
|
||||
static void UpdateLBR (void)
|
||||
{
|
||||
const BYTE nOpcode = *(mem + regs.pc);
|
||||
const BYTE nOpcode = ReadByteFromMemory(regs.pc);
|
||||
|
||||
bool isControlFlowOpcode =
|
||||
nOpcode == OPCODE_BRK ||
|
||||
@@ -8682,7 +8678,7 @@ void DebugContinueStepping (const bool bCallerWillUpdateDisplay/*=false*/)
|
||||
|
||||
if ( MemIsAddrCodeMemory(regs.pc) )
|
||||
{
|
||||
BYTE nOpcode = *(mem+regs.pc);
|
||||
const BYTE nOpcode = ReadByteFromMemory(regs.pc);
|
||||
|
||||
// Update profiling stats
|
||||
int nOpmode = g_aOpcodes[ nOpcode ].nAddressMode;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../MemoryDefs.h"
|
||||
|
||||
#include "Debugger_Types.h"
|
||||
#include "Debugger_DisassemblerData.h"
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
const int _6502_BRANCH_POS = +127;
|
||||
const int _6502_BRANCH_NEG = -128;
|
||||
const unsigned int _6502_ZEROPAGE_END = 0x00FF;
|
||||
const unsigned int _6502_STACK_BEGIN = 0x0100;
|
||||
const unsigned int _6502_STACK_END = 0x01FF;
|
||||
const unsigned int _6502_IO_BEGIN = 0xC000;
|
||||
const unsigned int _6502_IO_END = 0xC0FF;
|
||||
const unsigned int _6502_BRK_VECTOR = 0xFFFE;
|
||||
const unsigned int _6502_MEM_BEGIN = 0x0000;
|
||||
const unsigned int _6502_MEM_END = 0xFFFF;
|
||||
const unsigned int _6502_MEM_LEN = _6502_MEM_END + 1;
|
||||
@@ -168,7 +168,7 @@ const Opcodes_t g_aOpcodes65C02[ NUM_OPCODES ] =
|
||||
};
|
||||
|
||||
const Opcodes_t g_aOpcodes6502[ NUM_OPCODES ] =
|
||||
{ // Should match Cpu.cpp InternalCpuExecute() switch (*(mem+regs.pc++)) !!
|
||||
{
|
||||
|
||||
/*
|
||||
Based on: http://axis.llx.com/~nparker/a2/opcodes.html
|
||||
@@ -477,8 +477,8 @@ WORD _6502_GetStackReturnAddress ()
|
||||
WORD _6502_PeekStackReturnAddress (WORD & nStack)
|
||||
{
|
||||
WORD nAddress;
|
||||
nAddress = ((unsigned) *(LPBYTE)(mem + 0x100 + (nStack & 0xFF)) ); nStack++;
|
||||
nAddress += ((unsigned) *(LPBYTE)(mem + 0x100 + (nStack & 0xFF)) << 8);
|
||||
nAddress = ReadByteFromMemory(_6502_STACK_BEGIN + (nStack & 0xFF)); nStack++;
|
||||
nAddress += (ReadByteFromMemory(_6502_STACK_BEGIN + (nStack & 0xFF)) << 8);
|
||||
nAddress++;
|
||||
return nAddress;
|
||||
}
|
||||
@@ -534,7 +534,7 @@ int _6502_GetOpmodeOpbyte ( const int nBaseAddress, int & iOpmode_, int & nOpby
|
||||
}
|
||||
#endif
|
||||
|
||||
int iOpcode_ = *(mem + nBaseAddress);
|
||||
int iOpcode_ = ReadByteFromMemory(nBaseAddress);
|
||||
iOpmode_ = g_aOpcodes[ iOpcode_ ].nAddressMode;
|
||||
nOpbyte_ = g_aOpmodes[ iOpmode_ ].m_nBytes;
|
||||
|
||||
@@ -571,7 +571,7 @@ int _6502_GetOpmodeOpbyte ( const int nBaseAddress, int & iOpmode_, int & nOpby
|
||||
case NOP_WORD_2: nOpbyte_ = 4; iOpmode_ = AM_M; break;
|
||||
case NOP_WORD_4: nOpbyte_ = 8; iOpmode_ = AM_M; break;
|
||||
case NOP_ADDRESS:nOpbyte_ = 2; iOpmode_ = AM_A; // BUGFIX: 2.6.2.33 Define Address should be shown as Absolute mode, not Indirect Absolute mode. DA BASIC.FPTR D000:D080 // was showing as "da (END-1)" now shows as "da END-1"
|
||||
pData->nTargetAddress = *(LPWORD)(mem+nBaseAddress);
|
||||
pData->nTargetAddress = ReadWordFromMemory(nBaseAddress);
|
||||
break;
|
||||
case NOP_STRING_APPLE:
|
||||
iOpmode_ = AM_DATA;
|
||||
@@ -644,9 +644,9 @@ bool _6502_GetTargets (WORD nAddress, int *pTargetPartial_, int *pTargetPartial2
|
||||
if (pTargetBytes_)
|
||||
*pTargetBytes_ = 0;
|
||||
|
||||
BYTE nOpcode = mem[nAddress];
|
||||
BYTE nTarget8 = mem[(nAddress+1)&0xFFFF];
|
||||
WORD nTarget16 = (mem[(nAddress+2)&0xFFFF]<<8) | nTarget8;
|
||||
BYTE nOpcode = ReadByteFromMemory(nAddress);
|
||||
BYTE nTarget8 = ReadByteFromMemory(nAddress + 1);
|
||||
WORD nTarget16 = (ReadByteFromMemory(nAddress + 2) << 8) | nTarget8;
|
||||
|
||||
int eMode = g_aOpcodes[ nOpcode ].nAddressMode;
|
||||
|
||||
@@ -670,7 +670,7 @@ bool _6502_GetTargets (WORD nAddress, int *pTargetPartial_, int *pTargetPartial2
|
||||
|
||||
*pTargetPartial_ = _6502_STACK_BEGIN + ((sp+1) & 0xFF);
|
||||
*pTargetPartial2_ = _6502_STACK_BEGIN + ((sp+2) & 0xFF);
|
||||
nTarget16 = mem[*pTargetPartial_] + (mem[*pTargetPartial2_]<<8);
|
||||
nTarget16 = ReadByteFromMemory(*pTargetPartial_) + (ReadByteFromMemory(*pTargetPartial2_) << 8);
|
||||
|
||||
if (nOpcode == OPCODE_RTS)
|
||||
++nTarget16;
|
||||
@@ -682,7 +682,7 @@ bool _6502_GetTargets (WORD nAddress, int *pTargetPartial_, int *pTargetPartial2
|
||||
//*pTargetPartial3_ = _6502_STACK_BEGIN + ((regs.sp-2) & 0xFF); // TODO: PHP
|
||||
//*pTargetPartial4_ = _6502_BRK_VECTOR + 0; // TODO
|
||||
//*pTargetPartial5_ = _6502_BRK_VECTOR + 1; // TODO
|
||||
nTarget16 = *(LPWORD)(mem + _6502_BRK_VECTOR);
|
||||
nTarget16 = ReadWordFromMemory(_6502_INTERRUPT_VECTOR);
|
||||
}
|
||||
else // PHn/PLn
|
||||
{
|
||||
@@ -720,7 +720,7 @@ bool _6502_GetTargets (WORD nAddress, int *pTargetPartial_, int *pTargetPartial2
|
||||
*pTargetPartial_ = nTarget16;
|
||||
*pTargetPartial2_ = nTarget16+1;
|
||||
if (bIncludeNextOpcodeAddress)
|
||||
*pTargetPointer_ = *(LPWORD)(mem + nTarget16);
|
||||
*pTargetPointer_ = ReadWordFromMemory(nTarget16);
|
||||
if (pTargetBytes_)
|
||||
*pTargetBytes_ = 2;
|
||||
break;
|
||||
@@ -746,7 +746,7 @@ bool _6502_GetTargets (WORD nAddress, int *pTargetPartial_, int *pTargetPartial2
|
||||
if (GetMainCpu() == CPU_6502 && (nTarget16 & 0xff) == 0xff)
|
||||
*pTargetPartial2_ = nTarget16 & 0xff00;
|
||||
if (bIncludeNextOpcodeAddress)
|
||||
*pTargetPointer_ = mem[*pTargetPartial_] | (mem[*pTargetPartial2_] << 8);
|
||||
*pTargetPointer_ = ReadByteFromMemory(*pTargetPartial_) | (ReadByteFromMemory(*pTargetPartial2_) << 8);
|
||||
if (pTargetBytes_)
|
||||
*pTargetBytes_ = 2;
|
||||
break;
|
||||
@@ -754,21 +754,21 @@ bool _6502_GetTargets (WORD nAddress, int *pTargetPartial_, int *pTargetPartial2
|
||||
case AM_IZX: // Indexed (Zeropage Indirect, X)
|
||||
nTarget8 = (nTarget8 + regs.x) & 0xFF;
|
||||
*pTargetPartial_ = nTarget8;
|
||||
*pTargetPointer_ = *(LPWORD)(mem + nTarget8);
|
||||
*pTargetPointer_ = ReadWordFromMemory(nTarget8);
|
||||
if (pTargetBytes_)
|
||||
*pTargetBytes_ = 2;
|
||||
break;
|
||||
|
||||
case AM_NZY: // Indirect (Zeropage) Indexed, Y
|
||||
*pTargetPartial_ = nTarget8;
|
||||
*pTargetPointer_ = ((*(LPWORD)(mem + nTarget8)) + regs.y) & _6502_MEM_END; // Bugfix:
|
||||
*pTargetPointer_ = ((ReadWordFromMemory(nTarget8)) + regs.y) & _6502_MEM_END;
|
||||
if (pTargetBytes_)
|
||||
*pTargetBytes_ = 1;
|
||||
break;
|
||||
|
||||
case AM_NZ: // Indirect (Zeropage)
|
||||
*pTargetPartial_ = nTarget8;
|
||||
*pTargetPointer_ = *(LPWORD)(mem + nTarget8);
|
||||
*pTargetPointer_ = ReadWordFromMemory(nTarget8);
|
||||
if (pTargetBytes_)
|
||||
*pTargetBytes_ = 2;
|
||||
break;
|
||||
@@ -1037,14 +1037,11 @@ int AssemblerPokeAddress( const int Opcode, const int nOpmode, const WORD nBaseA
|
||||
// if (nOpbytes != nBytes)
|
||||
// ConsoleDisplayError( " ERROR: Input Opcode bytes differs from actual!" );
|
||||
|
||||
*(memdirty + (nBaseAddress >> 8)) |= 1;
|
||||
// *(mem + nBaseAddress) = (BYTE) nOpcode;
|
||||
|
||||
if (nOpbytes > 1)
|
||||
*(mem + nBaseAddress + 1) = (BYTE)(nTargetOffset >> 0);
|
||||
WriteByteToMemory(nBaseAddress + 1, (BYTE)(nTargetOffset >> 0));
|
||||
|
||||
if (nOpbytes > 2)
|
||||
*(mem + nBaseAddress + 2) = (BYTE)(nTargetOffset >> 8);
|
||||
WriteByteToMemory(nBaseAddress + 2, (BYTE)(nTargetOffset >> 8));
|
||||
|
||||
return nOpbytes;
|
||||
}
|
||||
@@ -1065,7 +1062,7 @@ bool AssemblerPokeOpcodeAddress( const WORD nBaseAddress )
|
||||
|
||||
if (nOpmode == iAddressMode)
|
||||
{
|
||||
*(mem + nBaseAddress) = (BYTE) nOpcode;
|
||||
WriteByteToMemory(nBaseAddress, (BYTE)nOpcode);
|
||||
int nOpbytes = AssemblerPokeAddress( nOpcode, nOpmode, nBaseAddress, nTargetValue );
|
||||
|
||||
if (m_bDelayedTargetsDirty)
|
||||
|
||||
@@ -48,15 +48,15 @@ std::string FormatAddress(WORD nAddress, int nBytes)
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
char* FormatCharCopy(char* pDst, const char* pEnd, const char* pSrc, const int nLen)
|
||||
static char* FormatCharCopy(char* pDst, const char* pEnd, uint16_t srcAddr, const int nLen)
|
||||
{
|
||||
for (int i = 0; i < nLen && pDst < pEnd; i++)
|
||||
*pDst++ = FormatCharTxtCtrl(*pSrc++);
|
||||
*pDst++ = FormatCharTxtCtrl(ReadByteFromMemory(srcAddr++));
|
||||
return pDst;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
char FormatCharTxtAsci(const BYTE b, bool* pWasAsci_)
|
||||
static char FormatCharTxtAsci(const BYTE b, bool* pWasAsci_)
|
||||
{
|
||||
if (pWasAsci_)
|
||||
*pWasAsci_ = false;
|
||||
@@ -74,7 +74,7 @@ char FormatCharTxtAsci(const BYTE b, bool* pWasAsci_)
|
||||
|
||||
// Note: FormatCharTxtCtrl() and RemapChar()
|
||||
//===========================================================================
|
||||
char FormatCharTxtCtrl(const BYTE b, bool* pWasCtrl_)
|
||||
char FormatCharTxtCtrl(const BYTE b, bool* pWasCtrl_)
|
||||
{
|
||||
if (pWasCtrl_)
|
||||
*pWasCtrl_ = false;
|
||||
@@ -92,7 +92,7 @@ char FormatCharTxtCtrl(const BYTE b, bool* pWasCtrl_)
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
char FormatCharTxtHigh(const BYTE b, bool* pWasHi_)
|
||||
char FormatCharTxtHigh(const BYTE b, bool* pWasHi_)
|
||||
{
|
||||
if (pWasHi_)
|
||||
*pWasHi_ = false;
|
||||
@@ -229,8 +229,9 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
{
|
||||
nTarget = pData->nTargetAddress;
|
||||
}
|
||||
else {
|
||||
nTarget = mem[(nBaseAddress + 1) & 0xFFFF] | (mem[(nBaseAddress + 2) & 0xFFFF] << 8);
|
||||
else
|
||||
{
|
||||
nTarget = ReadWordFromMemory(nBaseAddress + 1);
|
||||
if (nOpbyte == 2)
|
||||
nTarget &= 0xFF;
|
||||
}
|
||||
@@ -352,7 +353,7 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_POINTER;
|
||||
|
||||
nTargetValue = *(mem + nTargetPointer) | (*(mem + ((nTargetPointer + 1) & 0xffff)) << 8);
|
||||
nTargetValue = ReadWordFromMemory(nTargetPointer);
|
||||
|
||||
//if (((iOpmode >= AM_A) && (iOpmode <= AM_NZ)) && (iOpmode != AM_R))
|
||||
// sTargetValue_ = WordToHexStr( nTargetValue ); // & 0xFFFF
|
||||
@@ -457,7 +458,7 @@ void FormatOpcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
const char* const ep = cp + sizeof(line_.sOpCodes);
|
||||
for (int iByte = 0; iByte < nMaxOpBytes; iByte++)
|
||||
{
|
||||
const BYTE nMem = mem[(nBaseAddress + iByte) & 0xFFFF];
|
||||
const BYTE nMem = ReadByteFromMemory(nBaseAddress + iByte);
|
||||
if ((cp+2) < ep)
|
||||
cp = StrBufferAppendByteAsHex(cp, nMem);
|
||||
|
||||
@@ -482,11 +483,11 @@ struct FAC_t
|
||||
|
||||
void FAC_Unpack(WORD nAddress, FAC_t& fac_)
|
||||
{
|
||||
BYTE e0 = *(LPBYTE)(mem + nAddress + 0);
|
||||
BYTE m1 = *(LPBYTE)(mem + nAddress + 1);
|
||||
BYTE m2 = *(LPBYTE)(mem + nAddress + 2);
|
||||
BYTE m3 = *(LPBYTE)(mem + nAddress + 3);
|
||||
BYTE m4 = *(LPBYTE)(mem + nAddress + 4);
|
||||
BYTE e0 = ReadByteFromMemory(nAddress + 0);
|
||||
BYTE m1 = ReadByteFromMemory(nAddress + 1);
|
||||
BYTE m2 = ReadByteFromMemory(nAddress + 2);
|
||||
BYTE m3 = ReadByteFromMemory(nAddress + 3);
|
||||
BYTE m4 = ReadByteFromMemory(nAddress + 4);
|
||||
|
||||
// sign
|
||||
// EB82:A5 9D SIGN LDA FAC
|
||||
@@ -523,8 +524,8 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
|
||||
for (int iByte = 0; iByte < line_.nOpbyte; )
|
||||
{
|
||||
BYTE nTarget8 = *(LPBYTE)(mem + nBaseAddress + iByte);
|
||||
WORD nTarget16 = *(LPWORD)(mem + nBaseAddress + iByte);
|
||||
BYTE nTarget8 = ReadByteFromMemory(nBaseAddress + iByte);
|
||||
WORD nTarget16 = ReadWordFromMemory(nBaseAddress + iByte);
|
||||
|
||||
switch (line_.iNoptype)
|
||||
{
|
||||
@@ -603,8 +604,8 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
iByte = line_.nOpbyte;
|
||||
if ((pDst + iByte) < pEnd)
|
||||
{
|
||||
memcpy(pDst, mem + nBaseAddress, iByte);
|
||||
pDst += iByte;
|
||||
for (int i = 0; i < iByte; i++)
|
||||
*pDst++ = ReadByteFromMemory(nBaseAddress + i);
|
||||
}
|
||||
*pDst = 0;
|
||||
break;
|
||||
@@ -612,7 +613,6 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
case NOP_STRING_APPLE:
|
||||
{
|
||||
iByte = line_.nOpbyte; // handle all bytes of text
|
||||
const char* pSrc = (const char*)mem + nStartAddress;
|
||||
|
||||
if (nDisplayLen > (DISASM_DISPLAY_MAX_IMMEDIATE_LEN - 2)) // does "text" fit?
|
||||
{
|
||||
@@ -622,7 +622,7 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
;
|
||||
|
||||
// DISPLAY: text_longer_18...
|
||||
pDst = FormatCharCopy(pDst, pEnd, pSrc, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
||||
pDst = FormatCharCopy(pDst, pEnd, nStartAddress, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
||||
|
||||
if (ellipsis && (pDst + 3) < pEnd)
|
||||
{
|
||||
@@ -635,7 +635,7 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
{ // DISPLAY: "max_18_char"
|
||||
if ((pDst + 1) < pEnd)
|
||||
*pDst++ = '"';
|
||||
pDst = FormatCharCopy(pDst, pEnd, pSrc, nDisplayLen); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
||||
pDst = FormatCharCopy(pDst, pEnd, nStartAddress, nDisplayLen); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
||||
if ((pDst + 1) < pEnd)
|
||||
*pDst++ = '"';
|
||||
}
|
||||
|
||||
@@ -2266,17 +2266,17 @@ void DrawMemory ( int line, int iMemDump )
|
||||
std::string sText;
|
||||
|
||||
// .12 Bugfix: DrawMemory() should draw memory byte for IO address: ML1 C000
|
||||
// if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END))
|
||||
// if ((iAddress >= APPLE_IO_BEGIN) && (iAddress <= APPLE_IO_END))
|
||||
// {
|
||||
// sText = "IO ";
|
||||
// }
|
||||
// else
|
||||
{
|
||||
BYTE nData = (unsigned)*(LPBYTE)(mem + iAddress);
|
||||
const BYTE nData = ReadByteFromMemory(iAddress);
|
||||
|
||||
if (iView == MEM_VIEW_HEX)
|
||||
{
|
||||
if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END))
|
||||
if ((iAddress >= APPLE_IO_BEGIN) && (iAddress <= APPLE_IO_END))
|
||||
{
|
||||
DebuggerSetColorFG(DebuggerGetColor(FG_INFO_IO_BYTE));
|
||||
}
|
||||
@@ -2286,7 +2286,7 @@ void DrawMemory ( int line, int iMemDump )
|
||||
else
|
||||
{
|
||||
// .12 Bugfix: DrawMemory() should draw memory byte for IO address: ML1 C000
|
||||
if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END))
|
||||
if ((iAddress >= APPLE_IO_BEGIN) && (iAddress <= APPLE_IO_END))
|
||||
iBackground = BG_INFO_IO_BYTE;
|
||||
|
||||
sText = ColorizeSpecialChar(nData, iView, iBackground);
|
||||
@@ -2856,7 +2856,7 @@ void DrawStack ( int line)
|
||||
if (nAddress <= _6502_STACK_END)
|
||||
{
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE )); // COLOR_FG_DATA_TEXT
|
||||
PrintTextCursorX( StrFormat( " %02X", (unsigned)*(LPBYTE)(mem+nAddress) ).c_str(), rect );
|
||||
PrintTextCursorX(StrFormat(" %02X", ReadByteFromMemory(nAddress)).c_str(), rect);
|
||||
}
|
||||
iStack++;
|
||||
}
|
||||
@@ -2871,7 +2871,7 @@ void DrawTargets ( int line)
|
||||
|
||||
int aTarget[3];
|
||||
_6502_GetTargets( regs.pc, &aTarget[0],&aTarget[1],&aTarget[2], NULL );
|
||||
GetTargets_IgnoreDirectJSRJMP(mem[regs.pc], aTarget[2]);
|
||||
GetTargets_IgnoreDirectJSRJMP(ReadByteFromMemory(regs.pc), aTarget[2]);
|
||||
|
||||
aTarget[1] = aTarget[2]; // Move down as we only have 2 lines
|
||||
|
||||
@@ -2882,7 +2882,7 @@ void DrawTargets ( int line)
|
||||
while (iAddress--)
|
||||
{
|
||||
// .6 Bugfix: DrawTargets() should draw target byte for IO address: R PC FB33
|
||||
// if ((aTarget[iAddress] >= _6502_IO_BEGIN) && (aTarget[iAddress] <= _6502_IO_END))
|
||||
// if ((aTarget[iAddress] >= APPLE_IO_BEGIN) && (aTarget[iAddress] <= APPLE_IO_END))
|
||||
// aTarget[iAddress] = NO_6502_TARGET;
|
||||
|
||||
std::string sAddress = "-none-";
|
||||
@@ -2896,9 +2896,9 @@ void DrawTargets ( int line)
|
||||
{
|
||||
sAddress = WordToHexStr(aTarget[iAddress]);
|
||||
if (iAddress)
|
||||
sData = ByteToHexStr(*(LPBYTE)(mem+aTarget[iAddress]));
|
||||
sData = ByteToHexStr(ReadByteFromMemory(aTarget[iAddress]));
|
||||
else
|
||||
sData = WordToHexStr(*(LPWORD)(mem+aTarget[iAddress]));
|
||||
sData = WordToHexStr(ReadWordFromMemory(aTarget[iAddress]));
|
||||
}
|
||||
|
||||
rect.left = DISPLAY_TARGETS_COLUMN;
|
||||
@@ -2972,11 +2972,11 @@ void DrawWatches (int line)
|
||||
|
||||
//
|
||||
|
||||
BYTE nTargetL = *(LPBYTE)(mem + g_aWatches[iWatch].nAddress);
|
||||
BYTE nTargetL = ReadByteFromMemory(g_aWatches[iWatch].nAddress);
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
||||
PrintTextCursorX( ByteToHexStr( nTargetL ).c_str(), rect2 );
|
||||
|
||||
BYTE nTargetH = *(LPBYTE)(mem + ((g_aWatches[iWatch].nAddress + 1) & 0xffff));
|
||||
BYTE nTargetH = ReadByteFromMemory(g_aWatches[iWatch].nAddress + 1);
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
||||
PrintTextCursorX( ByteToHexStr( nTargetH ).c_str(), rect2 );
|
||||
|
||||
@@ -3009,7 +3009,7 @@ void DrawWatches (int line)
|
||||
else
|
||||
DebuggerSetColorBG( DebuggerGetColor( BG_DATA_2 ));
|
||||
|
||||
BYTE nValue8 = mem[ (nTarget16 + iByte) & 0xffff ];
|
||||
BYTE nValue8 = ReadByteFromMemory(nTarget16 + iByte);
|
||||
PrintTextCursorX( ByteToHexStr( nValue8 ).c_str(), rect2 );
|
||||
}
|
||||
}
|
||||
@@ -3155,14 +3155,14 @@ void DrawZeroPagePointers ( int line )
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
||||
PrintTextCursorX( ":", rect2 );
|
||||
|
||||
WORD nTarget16 = (WORD)mem[ nZPAddr1 ] | ((WORD)mem[ nZPAddr2 ]<< 8);
|
||||
WORD nTarget16 = (WORD)ReadByteFromMemory(nZPAddr1) | (((WORD)ReadByteFromMemory(nZPAddr2)) << 8);
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
|
||||
PrintTextCursorX( WordToHexStr( nTarget16 ).c_str(), rect2 );
|
||||
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
||||
PrintTextCursorX( ":", rect2 );
|
||||
|
||||
BYTE nValue8 = (unsigned)*(LPBYTE)(mem + nTarget16);
|
||||
BYTE nValue8 = ReadByteFromMemory(nTarget16);
|
||||
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
||||
PrintTextCursorX( ByteToHexStr( nValue8 ).c_str(), rect2 );
|
||||
}
|
||||
@@ -3256,10 +3256,10 @@ void DrawSubWindow_Data (Update_t bUpdate)
|
||||
std::string sAddress = WordToHexStr( iAddress );
|
||||
|
||||
std::string sOpcodes;
|
||||
const BYTE* mp = mem + iAddress;
|
||||
for ( int iByte = 0; iByte < nMaxOpcodes; ++iByte, ++mp )
|
||||
WORD srcAddr = iAddress;
|
||||
for (int iByte = 0; iByte < nMaxOpcodes; ++iByte, ++srcAddr)
|
||||
{
|
||||
StrAppendByteAsHex(sOpcodes, *mp);
|
||||
StrAppendByteAsHex(sOpcodes, ReadByteFromMemory(srcAddr));
|
||||
sOpcodes += ' ';
|
||||
}
|
||||
|
||||
@@ -3303,9 +3303,9 @@ void DrawSubWindow_Data (Update_t bUpdate)
|
||||
iAddress = nAddress;
|
||||
for ( int iByte = 0; iByte < nMaxOpcodes; iByte++ )
|
||||
{
|
||||
BYTE nImmediate = (unsigned)*(LPBYTE)(mem + iAddress);
|
||||
BYTE nImmediate = ReadByteFromMemory(iAddress);
|
||||
/*int iTextBackground = iBackground;
|
||||
if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END))
|
||||
if ((iAddress >= APPLE_IO_BEGIN) && (iAddress <= APPLE_IO_END))
|
||||
{
|
||||
iTextBackground = BG_INFO_IO_BYTE;
|
||||
}
|
||||
@@ -3323,7 +3323,7 @@ void DrawSubWindow_Data (Update_t bUpdate)
|
||||
BYTE nImmediate = (unsigned)*(LPBYTE)(membank + iAddress);
|
||||
int iTextBackground = iBackground; // BG_INFO_CHAR;
|
||||
//pMD->eView == MEM_VIEW_HEX
|
||||
if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END))
|
||||
if ((iAddress >= APPLE_IO_BEGIN) && (iAddress <= APPLE_IO_END))
|
||||
iTextBackground = BG_INFO_IO_BYTE;
|
||||
|
||||
std::string sImmediate = ColorizeSpecialChar( nImmediate, MEM_VIEW_APPLE, iBackground );
|
||||
|
||||
@@ -503,7 +503,9 @@ int ArgsCook ( const int nArgs )
|
||||
pArg->bType |= TYPE_NO_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ARG_SYNTAX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (pArg->bType & TYPE_OPERATOR) // prev op type == address?
|
||||
@@ -726,15 +728,17 @@ int ArgsCook ( const int nArgs )
|
||||
// pArg->bType |= TYPE_INDIRECT;
|
||||
// pArg->nValue = nAddressVal;
|
||||
//nAddressVal = pNext->nValue;
|
||||
pArg->nValue = * (WORD*) (mem + nAddressVal);
|
||||
pArg->bType = TYPE_VALUE | TYPE_ADDRESS | TYPE_NO_REG;
|
||||
pArg->nValue = ReadWordFromMemory(nAddressVal);
|
||||
pArg->bType = TYPE_VALUE | TYPE_ADDRESS | TYPE_NO_REG;
|
||||
|
||||
iArg++; // eat ')'
|
||||
nArg -= 2;
|
||||
nParamLen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ARG_SYNTAX_ERROR; // ERROR: unbalanced/unmatched ( )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -746,7 +750,9 @@ int ArgsCook ( const int nArgs )
|
||||
nParamLen = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ARG_SYNTAX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (nParamLen)
|
||||
@@ -757,7 +763,9 @@ int ArgsCook ( const int nArgs )
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ARG_SYNTAX_ERROR;
|
||||
}
|
||||
}
|
||||
else // not an operator, try (1) address, (2) symbol lookup
|
||||
{
|
||||
|
||||
@@ -1170,18 +1170,6 @@ const DisasmData_t* pDisasmData; // If != NULL then bytes are marked up as data
|
||||
|
||||
// Memory _________________________________________________________________________________________
|
||||
|
||||
extern const int _6502_BRANCH_POS ;//= +127
|
||||
extern const int _6502_BRANCH_NEG ;//= -128
|
||||
extern const unsigned int _6502_ZEROPAGE_END ;//= 0x00FF;
|
||||
extern const unsigned int _6502_STACK_BEGIN ;//= 0x0100;
|
||||
extern const unsigned int _6502_STACK_END ;//= 0x01FF;
|
||||
extern const unsigned int _6502_IO_BEGIN ;//= 0xC000;
|
||||
extern const unsigned int _6502_IO_END ;//= 0xC0FF;
|
||||
extern const unsigned int _6502_BRK_VECTOR ;//= 0xFFFE;
|
||||
extern const unsigned int _6502_MEM_BEGIN ;//= 0x0000;
|
||||
extern const unsigned int _6502_MEM_END ;//= 0xFFFF;
|
||||
extern const unsigned int _6502_MEM_LEN ;//= 0x10000;
|
||||
|
||||
enum DEVICE_e
|
||||
{
|
||||
DEV_MEMORY,
|
||||
|
||||
@@ -1038,10 +1038,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadFile(ptr->hFile, mem+address, length, &bytesread, NULL);
|
||||
int loop = 192;
|
||||
while (loop--)
|
||||
*(memdirty+loop) = 0xFF;
|
||||
ReadFile(ptr->hFile, MemGetMainPtr(address), length, &bytesread, NULL);
|
||||
int page = 192;
|
||||
while (page--)
|
||||
*(memdirty+page) = 0xFF;
|
||||
|
||||
regs.pc = address;
|
||||
return true;
|
||||
@@ -1092,11 +1092,11 @@ public:
|
||||
}
|
||||
|
||||
SetFilePointer(pImageInfo->hFile,128,NULL,FILE_BEGIN);
|
||||
ReadFile(pImageInfo->hFile, mem+address, length, &bytesread, NULL);
|
||||
ReadFile(pImageInfo->hFile, MemGetMainPtr(address), length, &bytesread, NULL);
|
||||
|
||||
int loop = 192;
|
||||
while (loop--)
|
||||
*(memdirty+loop) = 0xFF;
|
||||
int page = 192;
|
||||
while (page--)
|
||||
*(memdirty+page) = 0xFF;
|
||||
|
||||
regs.pc = address;
|
||||
return true;
|
||||
|
||||
+9
-10
@@ -664,7 +664,6 @@ BYTE HarddiskInterfaceCard::CmdExecute(HardDiskDrive* pHDD, const ULONG nExecute
|
||||
|
||||
const UINT CYCLES_FOR_DMA_RW_BLOCK = HD_BLOCK_SIZE;
|
||||
const UINT CYCLES_FOR_FORMATTING_1_BLOCK = 100; // Arbitrary
|
||||
const UINT PAGE_SIZE = 256;
|
||||
|
||||
pHDD->m_error = DEVICE_OK;
|
||||
|
||||
@@ -695,8 +694,7 @@ BYTE HarddiskInterfaceCard::CmdExecute(HardDiskDrive* pHDD, const ULONG nExecute
|
||||
{
|
||||
pHDD->m_buf_ptr = 0;
|
||||
|
||||
// Apple II's MMU could be setup so that read & write memory is different,
|
||||
// so can't use 'mem' (like we can for HDD block writes)
|
||||
// Apple II's MMU could be setup so that read & write memory is different, so use 'memwrite' not 'mem'.
|
||||
WORD dstAddr = pHDD->m_memblock;
|
||||
UINT remaining = HD_BLOCK_SIZE;
|
||||
BYTE* pSrc = pHDD->m_buf;
|
||||
@@ -716,7 +714,7 @@ BYTE HarddiskInterfaceCard::CmdExecute(HardDiskDrive* pHDD, const ULONG nExecute
|
||||
}
|
||||
|
||||
// handle both page-aligned & non-page aligned destinations
|
||||
UINT size = PAGE_SIZE - (dstAddr & 0xff);
|
||||
UINT size = _6502_PAGE_SIZE - (dstAddr & 0xff);
|
||||
if (size > remaining) size = remaining; // clip the last memcpy for the unaligned case
|
||||
|
||||
if (g_nAppMode == MODE_STEPPING)
|
||||
@@ -724,7 +722,7 @@ BYTE HarddiskInterfaceCard::CmdExecute(HardDiskDrive* pHDD, const ULONG nExecute
|
||||
|
||||
memcpy(page + (dstAddr & 0xff), pSrc, size);
|
||||
pSrc += size;
|
||||
dstAddr = (dstAddr + size) & (MEMORY_LENGTH - 1); // wraps at 64KiB boundary
|
||||
dstAddr = (dstAddr + size) & (_6502_MEM_LEN - 1); // wraps at 64KiB boundary
|
||||
|
||||
remaining -= size;
|
||||
}
|
||||
@@ -795,22 +793,23 @@ BYTE HarddiskInterfaceCard::CmdExecute(HardDiskDrive* pHDD, const ULONG nExecute
|
||||
}
|
||||
else
|
||||
{
|
||||
// NB. Do the writes in units of PAGE_SIZE so that DMA breakpoints are consistent with reads
|
||||
// NB. Do the writes in units of _6502_PAGE_SIZE so that DMA breakpoints are consistent with reads.
|
||||
// NB. Use `CopyBytesFromMemoryPage()`, as 'mem' may not be valid.
|
||||
WORD srcAddr = pHDD->m_memblock;
|
||||
UINT remaining = HD_BLOCK_SIZE;
|
||||
BYTE* pDst = pHDD->m_buf;
|
||||
|
||||
while (remaining)
|
||||
{
|
||||
UINT size = PAGE_SIZE - (srcAddr & 0xff);
|
||||
UINT size = _6502_PAGE_SIZE - (srcAddr & 0xff);
|
||||
if (size > remaining) size = remaining; // clip the last memcpy for the unaligned case
|
||||
|
||||
if (g_nAppMode == MODE_STEPPING)
|
||||
breakpointHit = DebuggerCheckMemBreakpoints(srcAddr, size, false);
|
||||
|
||||
memcpy(pDst, mem + srcAddr, size);
|
||||
CopyBytesFromMemoryPage(pDst, srcAddr, size);
|
||||
pDst += size;
|
||||
srcAddr = (srcAddr + size) & (MEMORY_LENGTH - 1); // wraps at 64KiB boundary
|
||||
srcAddr = (srcAddr + size) & (_6502_MEM_LEN - 1); // wraps at 64KiB boundary
|
||||
|
||||
remaining -= size;
|
||||
}
|
||||
@@ -1297,7 +1296,7 @@ void HarddiskInterfaceCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
|
||||
// New label
|
||||
{
|
||||
YamlSaveHelper::Label buffer(yamlSaveHelper, "%s:\n", SS_YAML_KEY_FIRMWARE);
|
||||
yamlSaveHelper.SaveMemory(mem + APPLE_IO_BEGIN + m_slot * APPLE_SLOT_SIZE, APPLE_SLOT_SIZE);
|
||||
yamlSaveHelper.SaveMemory(MemGetCxRomPeripheral() + m_slot * APPLE_SLOT_SIZE, APPLE_SLOT_SIZE);
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < NUM_HARDDISKS; i++)
|
||||
|
||||
@@ -160,13 +160,13 @@ BYTE __stdcall LanguageCardUnit::IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValu
|
||||
|
||||
bool LanguageCardUnit::IsOpcodeRMWabs(WORD addr)
|
||||
{
|
||||
BYTE param1 = mem[(regs.pc - 2) & 0xffff];
|
||||
BYTE param2 = mem[(regs.pc - 1) & 0xffff];
|
||||
BYTE param1 = ReadByteFromMemory(regs.pc - 2);
|
||||
BYTE param2 = ReadByteFromMemory(regs.pc - 1);
|
||||
if (param1 != (addr & 0xff) || param2 != 0xC0)
|
||||
return false;
|
||||
|
||||
// GH#404, GH#700: INC $C083,X/C08B,X (RMW) to write enable the LC (any 6502/65C02/816)
|
||||
BYTE opcode = mem[(regs.pc - 3) & 0xffff];
|
||||
BYTE opcode = ReadByteFromMemory(regs.pc - 3);
|
||||
if (opcode == 0xFE && regs.x == 0) // INC abs,x
|
||||
return true;
|
||||
|
||||
|
||||
+247
-141
@@ -53,7 +53,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "Z80VICE/z80.h"
|
||||
#include "../resource/resource.h"
|
||||
#include "Configuration/IPropertySheet.h"
|
||||
#include "Debugger/DebugDefs.h"
|
||||
#include "YamlHelper.h"
|
||||
|
||||
// In this file allocate the 64KB of RAM with aligned memory allocations (0x10000)
|
||||
@@ -223,14 +222,13 @@ SOFT SWITCH STATUS FLAGS
|
||||
// . aux writes outside of the aux TEXT1 get written to memaux (if there's a VidHD card)
|
||||
//
|
||||
|
||||
static LPBYTE memshadow[0x100];
|
||||
LPBYTE memwrite[0x100];
|
||||
BYTE memreadPageType[0x100];
|
||||
BYTE memwriteDirtyPage[0x100];
|
||||
LPBYTE memshadow[_6502_NUM_PAGES];
|
||||
LPBYTE memwrite[_6502_NUM_PAGES];
|
||||
BYTE memreadPageType[_6502_NUM_PAGES];
|
||||
|
||||
iofunction IORead[256];
|
||||
iofunction IOWrite[256];
|
||||
static LPVOID SlotParameters[NUM_SLOTS];
|
||||
static const UINT kNumIOFunctionPointers = APPLE_TOTAL_IO_SIZE / 16; // Split into 16-byte units
|
||||
iofunction IORead[kNumIOFunctionPointers];
|
||||
iofunction IOWrite[kNumIOFunctionPointers];
|
||||
|
||||
LPBYTE mem = NULL;
|
||||
|
||||
@@ -276,6 +274,7 @@ static FILE * g_hMemTempFile = NULL;
|
||||
|
||||
BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
|
||||
static void FreeMemImage(void);
|
||||
static bool g_isMemCacheValid = true; // flag for is 'mem' valid - set in UpdatePaging() and valid for regular (not alternate) CPU emulation
|
||||
|
||||
//=============================================================================
|
||||
|
||||
@@ -459,6 +458,76 @@ LPBYTE GetCxRomPeripheral(void)
|
||||
return pCxRomPeripheral; // Can be NULL if at MODE_LOGO
|
||||
}
|
||||
|
||||
bool GetIsMemCacheValid(void)
|
||||
{
|
||||
return g_isMemCacheValid;
|
||||
}
|
||||
|
||||
uint8_t ReadByteFromMemory(uint16_t addr)
|
||||
{
|
||||
if (GetIsMemCacheValid())
|
||||
return mem[addr];
|
||||
|
||||
if (memreadPageType[addr >> 8] != MEM_FloatingBus) // MEM_Normal or MEM_IORead
|
||||
{
|
||||
_ASSERT(memshadow[addr >> 8]); // Should never be NULL
|
||||
if (memshadow[addr >> 8] == NULL)
|
||||
return 0x00;
|
||||
|
||||
return *(memshadow[addr >> 8] + (addr & 0xff));
|
||||
}
|
||||
|
||||
// Read floating-bus
|
||||
// NB. Can't call MemReadFloatingBus(), as don't have 'uExecutedCycles' - needed when g_FullSpeed == true
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t ReadWordFromMemory(uint16_t addr)
|
||||
{
|
||||
return ReadByteFromMemory(addr) | (ReadByteFromMemory(addr + 1) << 8);
|
||||
}
|
||||
|
||||
void WriteByteToMemory(uint16_t addr, uint8_t data)
|
||||
{
|
||||
if (GetIsMemCacheValid())
|
||||
{
|
||||
mem[addr] = data;
|
||||
memdirty[addr >> 8] = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (memwrite[addr >> 8] == NULL) // Can be NULL (eg. ROM)
|
||||
return;
|
||||
|
||||
*(memwrite[addr >> 8] + (addr & 0xff)) = data;
|
||||
}
|
||||
|
||||
void CopyBytesFromMemoryPage(uint8_t* pDst, uint16_t srcAddr, size_t size)
|
||||
{
|
||||
_ASSERT(((srcAddr & 0xff) + size) <= _6502_PAGE_SIZE);
|
||||
|
||||
uint8_t* pSrc = &mem[srcAddr];
|
||||
|
||||
if (!GetIsMemCacheValid())
|
||||
{
|
||||
_ASSERT(memshadow[srcAddr >> 8]); // Should never be NULL
|
||||
if (memshadow[srcAddr >> 8] == NULL) return;
|
||||
|
||||
pSrc = memshadow[srcAddr >> 8] + (srcAddr & 0xff);
|
||||
}
|
||||
|
||||
memcpy(pDst, pSrc, size);
|
||||
}
|
||||
|
||||
// //e aux slot is empty & ALTZP=1
|
||||
bool IsZeroPageFloatingBus(void)
|
||||
{
|
||||
if (GetIsMemCacheValid())
|
||||
return false;
|
||||
|
||||
return memreadPageType[0x0000 >> 8] == MEM_FloatingBus;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
static BYTE __stdcall IORead_C00x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
|
||||
@@ -751,12 +820,18 @@ static iofunction IOWrite_C0xx[8] =
|
||||
static BYTE IO_SELECT = 0;
|
||||
static bool INTC8ROM = false; // UTAIIe:5-28
|
||||
|
||||
static BYTE* ExpansionRom[NUM_SLOTS];
|
||||
|
||||
enum eExpansionRomType {eExpRomNull=0, eExpRomInternal, eExpRomPeripheral};
|
||||
static eExpansionRomType g_eExpansionRomType = eExpRomNull;
|
||||
static UINT g_uPeripheralRomSlot = 0;
|
||||
|
||||
static struct SlotInfo
|
||||
{
|
||||
iofunction IOReadCx;
|
||||
iofunction IOWriteCx;
|
||||
LPVOID parameters;
|
||||
BYTE* expansionRom;
|
||||
} g_SlotInfo[NUM_SLOTS] = { 0 };
|
||||
|
||||
//=============================================================================
|
||||
|
||||
BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nExecutedCycles)
|
||||
@@ -851,7 +926,8 @@ static BYTE __stdcall IO_Cxxx(WORD programcounter, WORD address, BYTE write, BYT
|
||||
{
|
||||
// NB. SW_INTCXROM==1 ensures that internal rom stays switched in
|
||||
memset(pCxRomPeripheral+0x800, 0, FIRMWARE_EXPANSION_SIZE);
|
||||
memset(mem+FIRMWARE_EXPANSION_BEGIN, 0, FIRMWARE_EXPANSION_SIZE);
|
||||
if (GetIsMemCacheValid())
|
||||
memset(mem+FIRMWARE_EXPANSION_BEGIN, 0, FIRMWARE_EXPANSION_SIZE);
|
||||
g_eExpansionRomType = eExpRomNull;
|
||||
}
|
||||
|
||||
@@ -869,12 +945,12 @@ static BYTE __stdcall IO_Cxxx(WORD programcounter, WORD address, BYTE write, BYT
|
||||
const UINT uSlot = (address>>8)&0x7;
|
||||
if (IS_APPLE2 || uSlot != SLOT3)
|
||||
{
|
||||
if (ExpansionRom[uSlot])
|
||||
if (g_SlotInfo[uSlot].expansionRom)
|
||||
IO_SELECT |= 1<<uSlot;
|
||||
}
|
||||
else // slot3
|
||||
{
|
||||
if ((SW_SLOTC3ROM) && ExpansionRom[uSlot])
|
||||
if ((SW_SLOTC3ROM) && g_SlotInfo[uSlot].expansionRom)
|
||||
IO_SELECT |= 1<<uSlot; // Slot3 & Peripheral ROM
|
||||
else if (!SW_SLOTC3ROM)
|
||||
INTC8ROM = true; // Slot3 & Internal ROM
|
||||
@@ -903,10 +979,11 @@ static BYTE __stdcall IO_Cxxx(WORD programcounter, WORD address, BYTE write, BYT
|
||||
}
|
||||
}
|
||||
|
||||
if (ExpansionRom[uSlot] && (g_uPeripheralRomSlot != uSlot))
|
||||
if (g_SlotInfo[uSlot].expansionRom && (g_uPeripheralRomSlot != uSlot))
|
||||
{
|
||||
memcpy(pCxRomPeripheral+0x800, ExpansionRom[uSlot], FIRMWARE_EXPANSION_SIZE);
|
||||
memcpy(mem+FIRMWARE_EXPANSION_BEGIN, ExpansionRom[uSlot], FIRMWARE_EXPANSION_SIZE);
|
||||
memcpy(pCxRomPeripheral+0x800, g_SlotInfo[uSlot].expansionRom, FIRMWARE_EXPANSION_SIZE);
|
||||
if (GetIsMemCacheValid())
|
||||
memcpy(mem+FIRMWARE_EXPANSION_BEGIN, g_SlotInfo[uSlot].expansionRom, FIRMWARE_EXPANSION_SIZE);
|
||||
g_eExpansionRomType = eExpRomPeripheral;
|
||||
g_uPeripheralRomSlot = uSlot;
|
||||
}
|
||||
@@ -915,7 +992,9 @@ static BYTE __stdcall IO_Cxxx(WORD programcounter, WORD address, BYTE write, BYT
|
||||
{
|
||||
// Enable Internal ROM
|
||||
// . Get this for PR#3
|
||||
memcpy(mem+FIRMWARE_EXPANSION_BEGIN, pCxRomInternal+0x800, FIRMWARE_EXPANSION_SIZE);
|
||||
memcpy(pCxRomPeripheral+0x800, pCxRomInternal+0x800, FIRMWARE_EXPANSION_SIZE);
|
||||
if (GetIsMemCacheValid())
|
||||
memcpy(mem+FIRMWARE_EXPANSION_BEGIN, pCxRomInternal+0x800, FIRMWARE_EXPANSION_SIZE);
|
||||
g_eExpansionRomType = eExpRomInternal;
|
||||
g_uPeripheralRomSlot = 0;
|
||||
}
|
||||
@@ -947,7 +1026,9 @@ static BYTE __stdcall IO_Cxxx(WORD programcounter, WORD address, BYTE write, BYT
|
||||
if (INTC8ROM && (g_eExpansionRomType != eExpRomInternal))
|
||||
{
|
||||
// Enable Internal ROM
|
||||
memcpy(mem+FIRMWARE_EXPANSION_BEGIN, pCxRomInternal+0x800, FIRMWARE_EXPANSION_SIZE);
|
||||
memcpy(pCxRomPeripheral+0x800, pCxRomInternal+0x800, FIRMWARE_EXPANSION_SIZE);
|
||||
if (GetIsMemCacheValid())
|
||||
memcpy(mem+FIRMWARE_EXPANSION_BEGIN, pCxRomInternal+0x800, FIRMWARE_EXPANSION_SIZE);
|
||||
g_eExpansionRomType = eExpRomInternal;
|
||||
g_uPeripheralRomSlot = 0;
|
||||
}
|
||||
@@ -971,7 +1052,7 @@ static BYTE __stdcall IO_Cxxx(WORD programcounter, WORD address, BYTE write, BYT
|
||||
if ((g_eExpansionRomType == eExpRomNull) && (address >= FIRMWARE_EXPANSION_BEGIN))
|
||||
return IO_Null(programcounter, address, write, value, nExecutedCycles);
|
||||
|
||||
return mem[address];
|
||||
return ReadByteFromMemory(address);
|
||||
}
|
||||
|
||||
BYTE __stdcall IO_F8xx(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles) // NSC for Apple II/II+ (GH#827)
|
||||
@@ -1000,12 +1081,6 @@ BYTE __stdcall IO_F8xx(WORD programcounter, WORD address, BYTE write, BYTE value
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static struct SlotInfo
|
||||
{
|
||||
iofunction IOReadCx;
|
||||
iofunction IOWriteCx;
|
||||
} g_SlotInfo[NUM_SLOTS] = {0};
|
||||
|
||||
static void InitIoHandlers()
|
||||
{
|
||||
UINT i=0;
|
||||
@@ -1036,7 +1111,8 @@ static void InitIoHandlers()
|
||||
{
|
||||
g_SlotInfo[i].IOReadCx = IO_Cxxx;
|
||||
g_SlotInfo[i].IOWriteCx = IO_Cxxx;
|
||||
ExpansionRom[i] = NULL;
|
||||
g_SlotInfo[i].parameters = NULL;
|
||||
g_SlotInfo[i].expansionRom = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1044,11 +1120,15 @@ static void InitIoHandlers()
|
||||
void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, iofunction IOReadCx, iofunction IOWriteCx, LPVOID lpSlotParameter, BYTE* pExpansionRom)
|
||||
{
|
||||
_ASSERT(uSlot < NUM_SLOTS);
|
||||
SlotParameters[uSlot] = lpSlotParameter;
|
||||
g_SlotInfo[uSlot].parameters = lpSlotParameter;
|
||||
|
||||
// What about [$C80x..$CFEx]? - Do any cards use this as I/O memory?
|
||||
g_SlotInfo[uSlot].expansionRom = pExpansionRom;
|
||||
|
||||
if (IOReadC0 == NULL) IOReadC0 = IO_Null;
|
||||
if (IOWriteC0 == NULL) IOWriteC0 = IO_Null;
|
||||
|
||||
// Setup the r/w function pointers for I/O in the 16-byte range at: $C080+s*16
|
||||
IORead[uSlot+8] = IOReadC0;
|
||||
IOWrite[uSlot+8] = IOWriteC0;
|
||||
|
||||
@@ -1060,17 +1140,15 @@ void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, io
|
||||
if (IOReadCx == NULL) IOReadCx = IO_Cxxx;
|
||||
if (IOWriteCx == NULL) IOWriteCx = IO_Cxxx;
|
||||
|
||||
for (UINT i=0; i<16; i++)
|
||||
for (UINT i=0; i<16; i++) // Setup the r/w function pointers for I/O in the 256-byte range: $Cs00..CsFF
|
||||
{
|
||||
IORead[uSlot*16+i] = IOReadCx;
|
||||
IOWrite[uSlot*16+i] = IOWriteCx;
|
||||
}
|
||||
|
||||
// Setup the r/w function pointers for I/O in the range: $C800..CFFF
|
||||
g_SlotInfo[uSlot].IOReadCx = IOReadCx;
|
||||
g_SlotInfo[uSlot].IOWriteCx = IOWriteCx;
|
||||
|
||||
// What about [$C80x..$CFEx]? - Do any cards use this as I/O memory?
|
||||
ExpansionRom[uSlot] = pExpansionRom;
|
||||
}
|
||||
|
||||
void UnregisterIoHandler(UINT uSlot)
|
||||
@@ -1078,6 +1156,12 @@ void UnregisterIoHandler(UINT uSlot)
|
||||
RegisterIoHandler(uSlot, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
LPVOID MemGetSlotParameters(UINT uSlot)
|
||||
{
|
||||
_ASSERT(uSlot < NUM_SLOTS);
|
||||
return g_SlotInfo[uSlot].parameters;
|
||||
}
|
||||
|
||||
// From UTAIIe:5-28: Since INTCXROM==1 then state of SLOTC3ROM is not important
|
||||
static void IoHandlerCardsOut(void)
|
||||
{
|
||||
@@ -1215,6 +1299,14 @@ void MemUpdatePaging(BOOL initialize)
|
||||
|
||||
static void UpdatePaging(BOOL initialize)
|
||||
{
|
||||
if (initialize)
|
||||
{
|
||||
// Importantly from:
|
||||
// . MemReset() -> ResetPaging(TRUE)
|
||||
// . MemInitializeFromSnapshot() -> MemUpdatePaging(TRUE);
|
||||
g_isMemCacheValid = !(IsAppleIIe(GetApple2Type()) && (GetCardMgr().QueryAux() == CT_Empty || GetCardMgr().QueryAux() == CT_80Col));
|
||||
}
|
||||
|
||||
modechanging = 0;
|
||||
|
||||
// SAVE THE CURRENT PAGING SHADOW TABLE
|
||||
@@ -1322,129 +1414,141 @@ static void UpdatePaging(BOOL initialize)
|
||||
}
|
||||
}
|
||||
|
||||
// MOVE MEMORY BACK AND FORTH AS NECESSARY BETWEEN THE SHADOW AREAS AND
|
||||
// THE MAIN RAM IMAGE TO KEEP BOTH SETS OF MEMORY CONSISTENT WITH THE NEW
|
||||
// PAGING SHADOW TABLE
|
||||
//
|
||||
// NB. the condition 'loop <= 1' is there because:
|
||||
// . Page0 (ZP) and Page1 (stack) are written to so often that it's almost certain that they'll be dirty every time this function is called.
|
||||
// Note also that:
|
||||
// . Page0 (ZP) : memdirty[0] is set when the 6502 CPU writes to ZP.
|
||||
// . Page1 (stack) : memdirty[1] is NOT set when the 6502 CPU writes to this page with JSR, PHA, etc.
|
||||
// Ultimately this is an optimisation (due to Page1 writes not setting memdirty[1]) and Page0 could be optimised to also not set memdirty[0].
|
||||
|
||||
for (loop = 0x00; loop < 0x100; loop++)
|
||||
if (g_isMemCacheValid)
|
||||
{
|
||||
if (initialize || (oldshadow[loop] != memshadow[loop]))
|
||||
{
|
||||
if (!initialize &&
|
||||
((*(memdirty+loop) & 1) || (loop <= 1)))
|
||||
{
|
||||
*(memdirty+loop) &= ~1;
|
||||
memcpy(oldshadow[loop],mem+(loop << 8),256);
|
||||
}
|
||||
// MOVE MEMORY BACK AND FORTH AS NECESSARY BETWEEN THE SHADOW AREAS AND
|
||||
// THE MAIN RAM IMAGE TO KEEP BOTH SETS OF MEMORY CONSISTENT WITH THE NEW
|
||||
// PAGING SHADOW TABLE
|
||||
//
|
||||
// NB. the condition 'loop <= 1' is there because:
|
||||
// . Page0 (ZP) and Page1 (stack) are written to so often that it's almost certain that they'll be dirty every time this function is called.
|
||||
// Note also that:
|
||||
// . Page0 (ZP) : memdirty[0] is set when the 6502 CPU writes to ZP.
|
||||
// . Page1 (stack) : memdirty[1] is NOT set when the 6502 CPU writes to this page with JSR, PHA, etc.
|
||||
// Ultimately this is an optimisation (due to Page1 writes not setting memdirty[1]) and Page0 could be optimised to also not set memdirty[0].
|
||||
|
||||
memcpy(mem+(loop << 8),memshadow[loop],256);
|
||||
for (UINT page = _6502_ZERO_PAGE; page < _6502_NUM_PAGES; page++)
|
||||
{
|
||||
if (initialize || (oldshadow[page] != memshadow[page]))
|
||||
{
|
||||
if (!initialize &&
|
||||
((*(memdirty+page) & 1) || (page <= _6502_STACK_PAGE)))
|
||||
{
|
||||
*(memdirty+page) &= ~1;
|
||||
memcpy(oldshadow[page],mem+(page << 8),_6502_PAGE_SIZE);
|
||||
}
|
||||
|
||||
memcpy(mem+(page << 8),memshadow[page],_6502_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePagingForAltRW();
|
||||
else
|
||||
{
|
||||
UpdatePagingForAltRW();
|
||||
}
|
||||
}
|
||||
|
||||
// For Cpu6502_altRW() & Cpu65C02_altRW()
|
||||
static void UpdatePagingForAltRW(void)
|
||||
{
|
||||
UINT loop;
|
||||
UINT page;
|
||||
|
||||
const BYTE memType = (GetCardMgr().QueryAux() == CT_Empty) ? MEM_FloatingBus
|
||||
: (GetCardMgr().QueryAux() == CT_80Col) ? MEM_Aux1K
|
||||
: MEM_Normal;
|
||||
const BYTE memType = (GetCardMgr().QueryAux() == CT_Empty) ? MEM_FloatingBus : MEM_Normal;
|
||||
|
||||
for (loop = 0x00; loop < 0x02; loop++)
|
||||
memreadPageType[loop] = SW_ALTZP ? memType : MEM_Normal;
|
||||
for (page = 0x00; page < 0x02; page++)
|
||||
memreadPageType[page] = SW_ALTZP ? memType : MEM_Normal;
|
||||
|
||||
for (loop = 0x02; loop < 0xC0; loop++)
|
||||
memreadPageType[loop] = SW_AUXREAD ? memType : MEM_Normal;
|
||||
for (page = 0x02; page < 0xC0; page++)
|
||||
memreadPageType[page] = SW_AUXREAD ? memType : MEM_Normal;
|
||||
|
||||
for (loop = 0xC0; loop < 0xD0; loop++)
|
||||
memreadPageType[loop] = MEM_IORead;
|
||||
for (page = 0xC0; page < 0xD0; page++)
|
||||
{
|
||||
// NB. I/O SELECT' set on $C100-C7FF access
|
||||
// NB. I/O STROBE' set on $C800-CFFF access
|
||||
// So Cx ROM reads (both internal and slot/expansion) go via IO_Cxxx() - to set I/O SELECT/STROBE correctly
|
||||
// . and then read from memshadow[$Cx]
|
||||
memreadPageType[page] = MEM_IORead;
|
||||
}
|
||||
|
||||
for (loop = 0xD0; loop < 0x100; loop++)
|
||||
memreadPageType[loop] = (SW_HIGHRAM && SW_ALTZP) ? memType : MEM_Normal;
|
||||
for (page = 0xD0; page < 0x100; page++)
|
||||
memreadPageType[page] = (SW_HIGHRAM && SW_ALTZP) ? memType : MEM_Normal;
|
||||
|
||||
if (SW_80STORE)
|
||||
{
|
||||
for (loop = 0x04; loop < 0x08; loop++)
|
||||
memreadPageType[loop] = SW_PAGE2 ? memType : MEM_Normal;
|
||||
for (page = 0x04; page < 0x08; page++)
|
||||
memreadPageType[page] = 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 (page = 0x20; page < 0x40; page++)
|
||||
memreadPageType[page] = (SW_PAGE2 && SW_HIRES) ? memType : MEM_Normal;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
for (loop = 0x00; loop<0x100; loop++)
|
||||
memwriteDirtyPage[loop] = loop;
|
||||
for (page = 0x00; page < 0x02; page++)
|
||||
memwrite[page] = memshadow[page];
|
||||
|
||||
if ((SW_AUXREAD != 0) == (SW_AUXWRITE != 0))
|
||||
{
|
||||
for (page = 0x02; page < 0xC0; page++)
|
||||
memwrite[page] = memshadow[page];
|
||||
}
|
||||
|
||||
if (SW_WRITERAM && SW_HIGHRAM)
|
||||
{
|
||||
for (page = 0xD0; page < 0x100; page++)
|
||||
memwrite[page] = memshadow[page];
|
||||
}
|
||||
|
||||
if (SW_80STORE)
|
||||
{
|
||||
for (page = 0x04; page < 0x08; page++)
|
||||
memwrite[page] = memshadow[page];
|
||||
|
||||
if (SW_HIRES)
|
||||
{
|
||||
for (page = 0x20; page < 0x40; page++)
|
||||
memwrite[page] = memshadow[page];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if (GetCardMgr().QueryAux() == CT_80Col)
|
||||
{
|
||||
// Dirty pages are only in the 1K range
|
||||
const BYTE kTextPage = TEXT_PAGE1_BEGIN >> 8;
|
||||
// Map all aux read/writes into the 1K memory
|
||||
|
||||
for (loop = 0x00; loop < 0x02; loop++)
|
||||
if (SW_ALTZP)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
const uint32_t kBase = TEXT_PAGE1_BEGIN;
|
||||
|
||||
for (loop = 0x02; loop < 0xC0; loop++)
|
||||
if (SW_AUXWRITE)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
if (SW_ALTZP)
|
||||
for (page = 0x00; page < 0x02; page++)
|
||||
memshadow[page] = memwrite[page] = memaux + kBase + ((page & 3) << 8);
|
||||
|
||||
for (loop = 0xD0; loop < 0x100; loop++)
|
||||
if (SW_HIGHRAM && SW_ALTZP)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
if (SW_AUXREAD)
|
||||
for (page = 0x02; page < 0xC0; page++)
|
||||
memshadow[page] = memaux + kBase + ((page & 3) << 8);
|
||||
|
||||
if (SW_80STORE && SW_PAGE2)
|
||||
if (SW_AUXWRITE)
|
||||
for (page = 0x02; page < 0xC0; page++)
|
||||
memwrite[page] = memaux + kBase + ((page & 3) << 8);
|
||||
|
||||
if (SW_HIGHRAM && SW_ALTZP)
|
||||
{
|
||||
for (loop = 0x04; loop < 0x08; loop++)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
|
||||
for (loop = 0x20; loop < 0x40; loop++)
|
||||
memwriteDirtyPage[loop] = kTextPage + (loop & 3);
|
||||
for (page = 0xD0; page < 0x100; page++)
|
||||
{
|
||||
memshadow[page] = memaux + kBase + ((page & 3) << 8);
|
||||
if (SW_WRITERAM)
|
||||
memwrite[page] = memshadow[page];
|
||||
}
|
||||
}
|
||||
|
||||
// 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_WRITERAM && 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);
|
||||
for (page = 0x04; page < 0x08; page++)
|
||||
memshadow[page] = memwrite[page] = memaux + kBase + ((page & 3) << 8);
|
||||
|
||||
if (SW_HIRES)
|
||||
{
|
||||
for (loop = 0x20; loop < 0x40; loop++)
|
||||
memwrite[loop] = mem + TEXT_PAGE1_BEGIN + ((loop & 3) << 8);
|
||||
}
|
||||
for (page = 0x20; page < 0x40; page++)
|
||||
memshadow[page] = memwrite[page] = memaux + kBase + ((page & 3) << 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1515,7 +1619,7 @@ static LPBYTE MemGetPtrBANK1(const WORD offset, const LPBYTE pMemBase)
|
||||
|
||||
// NB. This works for memaux when set to any RWpages[] value, ie. RamWork III "just works"
|
||||
const BYTE bank1page = (offset >> 8) & 0xF;
|
||||
return (memshadow[0xD0+bank1page] == pMemBase+(0xC0+bank1page)*256)
|
||||
return (g_isMemCacheValid && (memshadow[0xD0+bank1page] == pMemBase+(0xC0+bank1page)*_6502_PAGE_SIZE))
|
||||
? mem+offset+0x1000 // Return ptr to $Dxxx address - 'mem' has (a potentially dirty) 4K RAM BANK1 mapped in at $D000
|
||||
: pMemBase+offset; // Else return ptr to $Cxxx address
|
||||
}
|
||||
@@ -1535,7 +1639,7 @@ LPBYTE MemGetAuxPtrWithLC(const WORD offset)
|
||||
|
||||
LPBYTE MemGetAuxPtr(const WORD offset)
|
||||
{
|
||||
LPBYTE lpMem = (memshadow[(offset >> 8)] == (memaux+(offset & 0xFF00)))
|
||||
LPBYTE lpMem = g_isMemCacheValid && (memshadow[(offset >> 8)] == (memaux+(offset & 0xFF00)))
|
||||
? mem+offset // Return 'mem' copy if possible, as page could be dirty
|
||||
: memaux+offset;
|
||||
|
||||
@@ -1548,7 +1652,7 @@ LPBYTE MemGetAuxPtr(const WORD offset)
|
||||
)
|
||||
)
|
||||
{
|
||||
lpMem = (memshadow[(offset >> 8)] == (RWpages[0]+(offset & 0xFF00)))
|
||||
lpMem = g_isMemCacheValid && (memshadow[(offset >> 8)] == (RWpages[0]+(offset & 0xFF00)))
|
||||
? mem+offset
|
||||
: RWpages[0]+offset;
|
||||
}
|
||||
@@ -1598,7 +1702,7 @@ LPBYTE MemGetMainPtrWithLC(const WORD offset)
|
||||
|
||||
LPBYTE MemGetMainPtr(const WORD offset)
|
||||
{
|
||||
return (memshadow[(offset >> 8)] == (memmain + (offset & 0xFF00)))
|
||||
return g_isMemCacheValid && (memshadow[(offset >> 8)] == (memmain + (offset & 0xFF00)))
|
||||
? mem + offset // Return 'mem' copy if possible, as page could be dirty
|
||||
: memmain + offset;
|
||||
}
|
||||
@@ -1607,10 +1711,13 @@ LPBYTE MemGetMainPtr(const WORD offset)
|
||||
|
||||
static void BackMainImage(void)
|
||||
{
|
||||
if (!g_isMemCacheValid)
|
||||
return;
|
||||
|
||||
for (UINT loop = 0; loop < 256; loop++)
|
||||
{
|
||||
if (memshadow[loop] && ((*(memdirty + loop) & 1) || (loop <= 1)))
|
||||
memcpy(memshadow[loop], mem + (loop << 8), 256);
|
||||
memcpy(memshadow[loop], mem + (loop << 8), _6502_PAGE_SIZE);
|
||||
|
||||
*(memdirty + loop) &= ~1;
|
||||
}
|
||||
@@ -2092,11 +2199,11 @@ void MemInitializeFromSnapshot(void)
|
||||
// Potentially init a card's expansion ROM
|
||||
const UINT uSlot = g_uPeripheralRomSlot;
|
||||
|
||||
if (ExpansionRom[uSlot] != NULL)
|
||||
if (g_SlotInfo[uSlot].expansionRom != NULL)
|
||||
{
|
||||
_ASSERT(g_eExpansionRomType == eExpRomPeripheral);
|
||||
|
||||
memcpy(pCxRomPeripheral + 0x800, ExpansionRom[uSlot], FIRMWARE_EXPANSION_SIZE);
|
||||
memcpy(pCxRomPeripheral + 0x800, g_SlotInfo[uSlot].expansionRom, FIRMWARE_EXPANSION_SIZE);
|
||||
// NB. Copied to /mem/ by UpdatePaging(TRUE)
|
||||
}
|
||||
|
||||
@@ -2446,7 +2553,8 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
|
||||
// . Similar to $CFFF access
|
||||
// . None of the peripheral cards can be driving the bus - so use the null ROM
|
||||
memset(pCxRomPeripheral+0x800, 0, FIRMWARE_EXPANSION_SIZE);
|
||||
memset(mem+FIRMWARE_EXPANSION_BEGIN, 0, FIRMWARE_EXPANSION_SIZE);
|
||||
if (GetIsMemCacheValid())
|
||||
memset(mem+FIRMWARE_EXPANSION_BEGIN, 0, FIRMWARE_EXPANSION_SIZE);
|
||||
g_eExpansionRomType = eExpRomNull;
|
||||
g_uPeripheralRomSlot = 0;
|
||||
}
|
||||
@@ -2455,7 +2563,9 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
|
||||
else
|
||||
{
|
||||
// Enable Internal ROM
|
||||
memcpy(mem+0xC800, pCxRomInternal+0x800, FIRMWARE_EXPANSION_SIZE);
|
||||
memcpy(pCxRomPeripheral+0x800, pCxRomInternal+0x800, FIRMWARE_EXPANSION_SIZE);
|
||||
if (GetIsMemCacheValid())
|
||||
memcpy(mem+FIRMWARE_EXPANSION_BEGIN, pCxRomInternal+0x800, FIRMWARE_EXPANSION_SIZE);
|
||||
g_eExpansionRomType = eExpRomInternal;
|
||||
g_uPeripheralRomSlot = 0;
|
||||
IoHandlerCardsOut();
|
||||
@@ -2493,13 +2603,17 @@ bool IsIIeWithoutAuxMem(void)
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static uint32_t ReadUINT24FromMemory(uint16_t addr)
|
||||
{
|
||||
return ReadByteFromMemory(addr) |
|
||||
(ReadByteFromMemory(addr + 1) << 8) |
|
||||
(ReadByteFromMemory(addr + 2) << 16);
|
||||
}
|
||||
|
||||
bool MemOptimizeForModeChanging(WORD programcounter, WORD address)
|
||||
{
|
||||
if (IsAppleIIeOrAbove(GetApple2Type()))
|
||||
{
|
||||
if (programcounter > 0xFFFC) // Prevent out of bounds access!
|
||||
return false;
|
||||
|
||||
// IF THE EMULATED PROGRAM HAS JUST UPDATED THE MEMORY WRITE MODE AND IS
|
||||
// ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
|
||||
// IT DOES SO.
|
||||
@@ -2507,7 +2621,7 @@ bool MemOptimizeForModeChanging(WORD programcounter, WORD address)
|
||||
// NB. A 6502 interrupt occurring between these memory write & read updates could lead to incorrect behaviour.
|
||||
// - although any data-race is probably a bug in the 6502 code too.
|
||||
if ((address >= 4) && (address <= 5) && // Now: RAMWRTOFF or RAMWRTON
|
||||
((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) // Next: STA $C002(RAMRDOFF) or STA $C003(RAMRDON)
|
||||
((ReadUINT24FromMemory(programcounter) & 0x00FFFEFF) == 0x00C0028D)) // Next: STA $C002(RAMRDOFF) or STA $C003(RAMRDON)
|
||||
{
|
||||
modechanging = 1;
|
||||
return true;
|
||||
@@ -2516,8 +2630,8 @@ bool MemOptimizeForModeChanging(WORD programcounter, WORD address)
|
||||
// TODO: support Saturn in any slot.
|
||||
// NB. GH#602 asks for any examples of this happening:
|
||||
if ((address >= 0x80) && (address <= 0x8F) && (programcounter < 0xC000) && // Now: LC
|
||||
(((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0048D) || // Next: STA $C004(RAMWRTOFF) or STA $C005(RAMWRTON)
|
||||
((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D))) // or STA $C002(RAMRDOFF) or STA $C003(RAMRDON)
|
||||
(((ReadUINT24FromMemory(programcounter) & 0x00FFFEFF) == 0x00C0048D) || // Next: STA $C004(RAMWRTOFF) or STA $C005(RAMWRTON)
|
||||
((ReadUINT24FromMemory(programcounter) & 0x00FFFEFF) == 0x00C0028D))) // or STA $C002(RAMRDOFF) or STA $C003(RAMRDON)
|
||||
{
|
||||
modechanging = 1;
|
||||
return true;
|
||||
@@ -2529,14 +2643,6 @@ bool MemOptimizeForModeChanging(WORD programcounter, WORD address)
|
||||
|
||||
//===========================================================================
|
||||
|
||||
LPVOID MemGetSlotParameters(UINT uSlot)
|
||||
{
|
||||
_ASSERT(uSlot < NUM_SLOTS);
|
||||
return SlotParameters[uSlot];
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void MemAnnunciatorReset(void)
|
||||
{
|
||||
for (UINT i=0; i<kNumAnnunciators; i++)
|
||||
|
||||
+8
-2
@@ -37,15 +37,15 @@ enum MemoryInitPattern_e
|
||||
};
|
||||
|
||||
// For Cpu6502_altRead() & Cpu65C02_altRead()
|
||||
enum { MEM_Normal = 0, MEM_IORead, MEM_FloatingBus, MEM_Aux1K, MEM_NoSlotClock };
|
||||
enum { MEM_Normal = 0, MEM_IORead, MEM_FloatingBus, 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 memshadow[0x100];
|
||||
extern LPBYTE memwrite[0x100];
|
||||
extern BYTE memreadPageType[0x100];
|
||||
extern BYTE memwriteDirtyPage[0x100];
|
||||
extern LPBYTE mem;
|
||||
extern LPBYTE memdirty;
|
||||
extern LPBYTE memVidHD;
|
||||
@@ -113,3 +113,9 @@ void SetMemMainLanguageCard(LPBYTE ptr, UINT slot, bool bMemMain=false);
|
||||
void SetRegistryAuxNumberOfBanks(void);
|
||||
|
||||
LPBYTE GetCxRomPeripheral(void);
|
||||
bool GetIsMemCacheValid(void);
|
||||
uint8_t ReadByteFromMemory(uint16_t addr);
|
||||
uint16_t ReadWordFromMemory(uint16_t addr);
|
||||
void WriteByteToMemory(uint16_t addr, uint8_t data);
|
||||
void CopyBytesFromMemoryPage(uint8_t* pDst, uint16_t srcAddr, size_t size);
|
||||
bool IsZeroPageFloatingBus(void);
|
||||
|
||||
+29
-3
@@ -1,19 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
// Apple II defines & memory locations
|
||||
enum
|
||||
{
|
||||
// Note: All are in bytes!
|
||||
TEXT_PAGE1_BEGIN = 0x0400,
|
||||
TEXT_PAGE1_SIZE = 0x0400,
|
||||
HGR_PAGE1_BEGIN = 0x2000,
|
||||
HGR_PAGE1_SIZE = 0x2000,
|
||||
|
||||
APPLE_SLOT_SIZE = 0x0100, // 1 page = $Cx00 .. $CxFF (slot 1 .. 7)
|
||||
APPLE_IO_BEGIN = 0xC000,
|
||||
APPLE_IO_END = 0xC0FF,
|
||||
APPLE_SLOT_BEGIN = 0xC100, // each slot has 1 page reserved for it
|
||||
APPLE_SLOT_END = 0xC7FF, //
|
||||
APPLE_SLOT_END = 0xC7FF,
|
||||
|
||||
FIRMWARE_EXPANSION_SIZE = 0x0800, // 8 pages = $C800 .. $CFFF
|
||||
FIRMWARE_EXPANSION_BEGIN = 0xC800, // [C800,CFFF)
|
||||
FIRMWARE_EXPANSION_END = 0xCFFF, //
|
||||
FIRMWARE_EXPANSION_END = 0xCFFF,
|
||||
|
||||
MEMORY_LENGTH = 0x10000
|
||||
APPLE_TOTAL_IO_SIZE = (FIRMWARE_EXPANSION_END+1) - APPLE_IO_BEGIN
|
||||
};
|
||||
|
||||
// 6502 defines & memory locations
|
||||
enum
|
||||
{
|
||||
_6502_BRANCH_POS = +127,
|
||||
_6502_BRANCH_NEG = -128,
|
||||
_6502_PAGE_SIZE = 0x0100,
|
||||
|
||||
_6502_ZEROPAGE_END = 0x00FF,
|
||||
_6502_STACK_BEGIN = 0x0100,
|
||||
_6502_STACK_END = 0x01FF,
|
||||
_6502_NMI_VECTOR = 0xFFFA,
|
||||
_6502_RESET_VECTOR = 0xFFFC,
|
||||
_6502_INTERRUPT_VECTOR = 0xFFFE, // IRQ & BRK
|
||||
_6502_MEM_BEGIN = 0x0000,
|
||||
_6502_MEM_END = 0xFFFF,
|
||||
_6502_MEM_LEN = _6502_MEM_END + 1,
|
||||
_6502_NUM_PAGES = _6502_MEM_LEN / _6502_PAGE_SIZE,
|
||||
|
||||
_6502_ZERO_PAGE = _6502_MEM_BEGIN >> 8,
|
||||
_6502_STACK_PAGE = _6502_STACK_BEGIN >> 8
|
||||
};
|
||||
|
||||
@@ -617,7 +617,7 @@ BYTE MockingboardCard::IOReadInternal(WORD PC, WORD nAddr, BYTE bWrite, BYTE nVa
|
||||
if (!IS_APPLE2 && MemCheckINTCXROM())
|
||||
{
|
||||
_ASSERT(0); // Card ROM disabled, so IO_Cxxx() returns the internal ROM
|
||||
return mem[nAddr];
|
||||
return ReadByteFromMemory(nAddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -689,22 +689,22 @@ BYTE MockingboardCard::IOWriteInternal(WORD PC, WORD nAddr, BYTE bWrite, BYTE nV
|
||||
#endif
|
||||
|
||||
// Support 6502/65C02 false-reads of 6522 (GH#52)
|
||||
if ( ((mem[(PC-2)&0xffff] == 0x91) && GetMainCpu() == CPU_6502) || // sta (zp),y - 6502 only (no-PX variant only) (UTAIIe:4-23)
|
||||
(mem[(PC-3)&0xffff] == 0x99) || // sta abs16,y - 6502/65C02, but for 65C02 only the no-PX variant that does the false-read (UTAIIe:4-27)
|
||||
(mem[(PC-3)&0xffff] == 0x9D) ) // sta abs16,x - 6502/65C02, but for 65C02 only the no-PX variant that does the false-read (UTAIIe:4-27)
|
||||
if ( ((ReadByteFromMemory(PC-2) == 0x91) && GetMainCpu() == CPU_6502) || // sta (zp),y - 6502 only (no-PX variant only) (UTAIIe:4-23)
|
||||
(ReadByteFromMemory(PC-3) == 0x99) || // sta abs16,y - 6502/65C02, but for 65C02 only the no-PX variant that does the false-read (UTAIIe:4-27)
|
||||
(ReadByteFromMemory(PC-3) == 0x9D) ) // sta abs16,x - 6502/65C02, but for 65C02 only the no-PX variant that does the false-read (UTAIIe:4-27)
|
||||
{
|
||||
WORD base;
|
||||
WORD addr16;
|
||||
if (mem[(PC-2)&0xffff] == 0x91)
|
||||
if (ReadByteFromMemory(PC-2) == 0x91)
|
||||
{
|
||||
BYTE zp = mem[(PC-1)&0xffff];
|
||||
base = (mem[zp] | (mem[(zp+1)&0xff]<<8));
|
||||
BYTE zp = ReadByteFromMemory(PC-1);
|
||||
base = (ReadByteFromMemory(zp) | (ReadByteFromMemory((zp+1)&0xff)<<8));
|
||||
addr16 = base + regs.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
base = mem[(PC-2)&0xffff] | (mem[(PC-1)&0xffff]<<8);
|
||||
addr16 = base + ((mem[(PC-3)&0xffff] == 0x99) ? regs.y : regs.x);
|
||||
base = ReadWordFromMemory(PC-2);
|
||||
addr16 = base + ((ReadByteFromMemory(PC-3) == 0x99) ? regs.y : regs.x);
|
||||
}
|
||||
|
||||
if (((base ^ addr16) >> 8) == 0) // Only the no-PX variant does the false read (to the same I/O SELECT page)
|
||||
|
||||
@@ -235,10 +235,12 @@ void CMouseInterface::SetSlotRom()
|
||||
if (pCxRomPeripheral == NULL)
|
||||
return;
|
||||
|
||||
UINT uOffset = (m_by6821B << 7) & 0x0700;
|
||||
memcpy(pCxRomPeripheral+m_slot*256, m_pSlotRom+uOffset, 256);
|
||||
if (mem)
|
||||
memcpy(mem+0xC000+m_slot*256, m_pSlotRom+uOffset, 256);
|
||||
// m_by6821B (b#0000ppp0) defines the 3-bit ROM page that is switched in at $Cs00
|
||||
const UINT offset = (m_by6821B << 7) & 0x0700;
|
||||
memcpy(pCxRomPeripheral + m_slot * APPLE_SLOT_SIZE, m_pSlotRom + offset, APPLE_SLOT_SIZE);
|
||||
|
||||
if (GetIsMemCacheValid() && mem)
|
||||
memcpy(mem + APPLE_IO_BEGIN + m_slot * APPLE_SLOT_SIZE, m_pSlotRom + offset, APPLE_SLOT_SIZE);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -318,7 +320,7 @@ void CMouseInterface::On6821_B(BYTE byData)
|
||||
|
||||
//
|
||||
|
||||
SetSlotRom(); // Update Cn00 ROM page
|
||||
SetSlotRom(); // Update Cs00 ROM page
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -757,10 +757,6 @@ void SSI263::UpdateAccurateLength(void)
|
||||
if (!m_phonemeAccurateLengthRemaining)
|
||||
return;
|
||||
|
||||
_ASSERT(m_lastUpdateCycle); // Can't be 0, since set in Play()
|
||||
if (m_lastUpdateCycle == 0)
|
||||
return;
|
||||
|
||||
double updateInterval = (double)(GetLastCumulativeCycles() - m_lastUpdateCycle);
|
||||
|
||||
const double nIrqFreq = g_fCurrentCLK6502 / updateInterval + 0.5; // Round-up
|
||||
|
||||
@@ -167,10 +167,12 @@ void Win32Frame::Benchmark(void)
|
||||
Sleep(500);
|
||||
Video& video = GetVideo();
|
||||
|
||||
uint8_t* pMemMain = MemGetMainPtr(_6502_MEM_BEGIN);
|
||||
|
||||
// PREPARE TWO DIFFERENT FRAME BUFFERS, EACH OF WHICH HAVE HALF OF THE
|
||||
// BYTES SET TO 0x14 AND THE OTHER HALF SET TO 0xAA
|
||||
int loop;
|
||||
LPDWORD mem32 = (LPDWORD)mem;
|
||||
LPDWORD mem32 = (LPDWORD)pMemMain;
|
||||
for (loop = 4096; loop < 6144; loop++)
|
||||
*(mem32 + loop) = ((loop & 1) ^ ((loop & 0x40) >> 6)) ? 0x14141414
|
||||
: 0xAAAAAAAA;
|
||||
@@ -184,7 +186,7 @@ void Win32Frame::Benchmark(void)
|
||||
uint32_t totaltextfps = 0;
|
||||
|
||||
video.SetVideoMode(VF_TEXT);
|
||||
memset(mem + 0x400, 0x14, 0x400);
|
||||
memset(pMemMain + TEXT_PAGE1_BEGIN, 0x14, TEXT_PAGE1_SIZE);
|
||||
VideoRedrawScreen();
|
||||
uint32_t milliseconds = GetTickCount();
|
||||
while (GetTickCount() == milliseconds);
|
||||
@@ -192,9 +194,9 @@ void Win32Frame::Benchmark(void)
|
||||
uint32_t cycle = 0;
|
||||
do {
|
||||
if (cycle & 1)
|
||||
memset(mem + 0x400, 0x14, 0x400);
|
||||
memset(pMemMain + TEXT_PAGE1_BEGIN, 0x14, TEXT_PAGE1_SIZE);
|
||||
else
|
||||
memcpy(mem + 0x400, mem + ((cycle & 2) ? 0x4000 : 0x6000), 0x400);
|
||||
memcpy(pMemMain + TEXT_PAGE1_BEGIN, pMemMain + ((cycle & 2) ? 0x4000 : 0x6000), TEXT_PAGE1_SIZE);
|
||||
VideoPresentScreen();
|
||||
if (cycle++ >= 3)
|
||||
cycle = 0;
|
||||
@@ -206,7 +208,7 @@ void Win32Frame::Benchmark(void)
|
||||
// SIMULATE THE ACTIVITY OF AN AVERAGE GAME
|
||||
uint32_t totalhiresfps = 0;
|
||||
video.SetVideoMode(VF_HIRES);
|
||||
memset(mem + 0x2000, 0x14, 0x2000);
|
||||
memset(pMemMain + HGR_PAGE1_BEGIN, 0x14, HGR_PAGE1_SIZE);
|
||||
VideoRedrawScreen();
|
||||
milliseconds = GetTickCount();
|
||||
while (GetTickCount() == milliseconds);
|
||||
@@ -214,9 +216,9 @@ void Win32Frame::Benchmark(void)
|
||||
cycle = 0;
|
||||
do {
|
||||
if (cycle & 1)
|
||||
memset(mem + 0x2000, 0x14, 0x2000);
|
||||
memset(pMemMain + HGR_PAGE1_BEGIN, 0x14, HGR_PAGE1_SIZE);
|
||||
else
|
||||
memcpy(mem + 0x2000, mem + ((cycle & 2) ? 0x4000 : 0x6000), 0x2000);
|
||||
memcpy(pMemMain + HGR_PAGE1_BEGIN, pMemMain + ((cycle & 2) ? 0x4000 : 0x6000), HGR_PAGE1_SIZE);
|
||||
VideoPresentScreen();
|
||||
if (cycle++ >= 3)
|
||||
cycle = 0;
|
||||
@@ -289,7 +291,7 @@ void Win32Frame::Benchmark(void)
|
||||
// WITH FULL EMULATION OF THE CPU, JOYSTICK, AND DISK HAPPENING AT
|
||||
// THE SAME TIME
|
||||
uint32_t realisticfps = 0;
|
||||
memset(mem + 0x2000, 0xAA, 0x2000);
|
||||
memset(pMemMain + HGR_PAGE1_BEGIN, 0xAA, HGR_PAGE1_SIZE);
|
||||
VideoRedrawScreen();
|
||||
milliseconds = GetTickCount();
|
||||
while (GetTickCount() == milliseconds);
|
||||
@@ -305,9 +307,9 @@ void Win32Frame::Benchmark(void)
|
||||
}
|
||||
}
|
||||
if (cycle & 1)
|
||||
memset(mem + 0x2000, 0xAA, 0x2000);
|
||||
memset(pMemMain + HGR_PAGE1_BEGIN, 0xAA, HGR_PAGE1_SIZE);
|
||||
else
|
||||
memcpy(mem + 0x2000, mem + ((cycle & 2) ? 0x4000 : 0x6000), 0x2000);
|
||||
memcpy(pMemMain + HGR_PAGE1_BEGIN, pMemMain + ((cycle & 2) ? 0x4000 : 0x6000), HGR_PAGE1_SIZE);
|
||||
VideoRedrawScreen();
|
||||
if (cycle++ >= 3)
|
||||
cycle = 0;
|
||||
|
||||
@@ -627,16 +627,16 @@ void Win32Frame::GetTrackSector(UINT slot, int& drive1Track, int& drive2Track, i
|
||||
drive2Track = disk2Card.GetTrack(DRIVE_2);
|
||||
|
||||
// Probe known OS's for default Slot/Track/Sector
|
||||
const bool isProDOS = mem[0xBF00] == 0x4C;
|
||||
const bool isProDOS = ReadByteFromMemory(0xBF00) == 0x4C;
|
||||
bool isSectorValid = false;
|
||||
int drive1Sector = -1, drive2Sector = -1;
|
||||
|
||||
// Try DOS3.3 Sector
|
||||
if (!isProDOS)
|
||||
{
|
||||
const int nDOS33slot = mem[0xB7E9] / 16;
|
||||
const int nDOS33track = mem[0xB7EC];
|
||||
const int nDOS33sector = mem[0xB7ED];
|
||||
const int nDOS33slot = ReadByteFromMemory(0xB7E9) / 16;
|
||||
const int nDOS33track = ReadByteFromMemory(0xB7EC);
|
||||
const int nDOS33sector = ReadByteFromMemory(0xB7ED);
|
||||
|
||||
if ((nDOS33slot == slot)
|
||||
&& (nDOS33track >= 0 && nDOS33track < 40)
|
||||
|
||||
@@ -6385,14 +6385,7 @@ BYTE z80_RDMEM(WORD Addr)
|
||||
|
||||
case 0xE:
|
||||
addr = (WORD)Addr - 0x2000;
|
||||
if ((addr & 0xF000) == 0xC000)
|
||||
{
|
||||
return IORead[(addr>>4) & 0xFF]( regs.pc, addr, 0, 0, ConvertZ80TStatesTo6502Cycles(maincpu_clk) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return *(mem+addr);
|
||||
}
|
||||
return IORead[(addr>>4) & 0xFF]( regs.pc, addr, 0, 0, ConvertZ80TStatesTo6502Cycles(maincpu_clk) ); // Maps to 6502 I/O address range: $C000..CFFF
|
||||
break;
|
||||
|
||||
case 0xF:
|
||||
|
||||
@@ -5,26 +5,41 @@
|
||||
#include "../../source/Memory.h"
|
||||
#include "../../source/SynchronousEventManager.h"
|
||||
|
||||
#include "../../source/CPU/cpu_general.inl"
|
||||
#include "../../source/CPU/cpu_instructions.inl"
|
||||
|
||||
// From Applewin.cpp
|
||||
bool g_bFullSpeed = false;
|
||||
enum AppMode_e g_nAppMode = MODE_RUNNING;
|
||||
SynchronousEventManager g_SynchronousEventMgr;
|
||||
|
||||
// From Memory.cpp
|
||||
LPBYTE memwrite[0x100]; // TODO: Init
|
||||
BYTE memreadPageType[0x100]; // TODO: Init
|
||||
BYTE memwriteDirtyPage[0x100]; // TODO: Init
|
||||
LPBYTE memshadow[0x100]; // init() just sets to mem pointers
|
||||
LPBYTE memwrite[0x100]; // init() just sets to mem pointers
|
||||
BYTE memreadPageType[0x100];
|
||||
LPBYTE mem = NULL; // TODO: Init
|
||||
LPBYTE memdirty = NULL; // TODO: Init
|
||||
LPBYTE memVidHD = NULL; // TODO: Init
|
||||
iofunction IORead[256] = {0}; // TODO: Init
|
||||
iofunction IOWrite[256] = {0}; // TODO: Init
|
||||
|
||||
static bool g_isMemCacheValid = true;
|
||||
|
||||
bool GetIsMemCacheValid(void)
|
||||
{
|
||||
return g_isMemCacheValid;
|
||||
}
|
||||
|
||||
BYTE __stdcall IO_F8xx(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
BYTE MemReadFloatingBus(const ULONG uExecutedCycles)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
regsrec regs;
|
||||
|
||||
bool g_irqOnLastOpcodeCycle = false;
|
||||
@@ -53,6 +68,17 @@ static __forceinline int Fetch(BYTE& iOpcode, ULONG uExecutedCycles)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __forceinline int Fetch_alt(BYTE& iOpcode, ULONG uExecutedCycles)
|
||||
{
|
||||
iOpcode = _READ_ALT(regs.pc);
|
||||
regs.pc++;
|
||||
|
||||
if (iOpcode == 0x00 && g_bStopOnBRK)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __forceinline void DoIrqProfiling(uint32_t uCycles)
|
||||
{
|
||||
}
|
||||
@@ -84,27 +110,48 @@ void NTSC_VideoUpdateCycles( long cycles6502 )
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#include "../../source/CPU/cpu_general.inl"
|
||||
#include "../../source/CPU/cpu_instructions.inl"
|
||||
#define HEATMAP_X(address)
|
||||
|
||||
#define READ _READ_WITH_IO_F8xx
|
||||
#define WRITE(a) _WRITE_WITH_IO_F8xx(a)
|
||||
#define HEATMAP_X(pc)
|
||||
// 6502 & no debugger
|
||||
#define READ(addr) _READ_WITH_IO_F8xx(addr)
|
||||
#define WRITE(value) _WRITE_WITH_IO_F8xx(value)
|
||||
|
||||
#include "../../source/CPU/cpu6502.h" // MOS 6502
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
//-------
|
||||
|
||||
// 6502 & no debugger & alt read/write support
|
||||
#define CPU_ALT
|
||||
#define READ(addr) _READ_ALT(addr)
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu6502 Cpu6502_altRW
|
||||
#define Fetch Fetch_alt
|
||||
#include "../../source/CPU/cpu6502.h" // MOS 6502
|
||||
#undef Cpu6502
|
||||
#undef Fetch
|
||||
|
||||
//-------
|
||||
|
||||
#define READ _READ
|
||||
#define WRITE(a) _WRITE(a)
|
||||
// 65C02 & no debugger
|
||||
#define READ(addr) _READ(addr)
|
||||
#define WRITE(value) _WRITE(value)
|
||||
|
||||
#include "../../source/CPU/cpu65C02.h" // WDC 65C02
|
||||
#include "../../source/CPU/cpu65C02.h" // WDC 65C02
|
||||
|
||||
//-------
|
||||
|
||||
// 65C02 & no debugger & alt read/write support
|
||||
#define CPU_ALT
|
||||
#define READ(addr) _READ_ALT(addr)
|
||||
#define WRITE(value) _WRITE_ALT(value)
|
||||
|
||||
#define Cpu65C02 Cpu65C02_altRW
|
||||
#define Fetch Fetch_alt
|
||||
#include "../../source/CPU/cpu65C02.h" // WDC 65C02
|
||||
#undef Cpu65C02
|
||||
#undef Fetch
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef HEATMAP_X
|
||||
|
||||
//-------------------------------------
|
||||
@@ -114,10 +161,17 @@ void init(void)
|
||||
// memory must be zero initialised like MemInitiaize() does.
|
||||
mem = (LPBYTE)calloc(64, 1024);
|
||||
|
||||
for (UINT i=0; i<256; i++)
|
||||
memshadow[i] = mem+i*256;
|
||||
|
||||
for (UINT i=0; i<256; i++)
|
||||
memwrite[i] = mem+i*256;
|
||||
|
||||
memdirty = new BYTE[256];
|
||||
|
||||
memset(memreadPageType, MEM_Normal, sizeof(memreadPageType));
|
||||
for (UINT i = 0xC0; i < 0xD0; i++)
|
||||
memreadPageType[i] = MEM_IORead;
|
||||
}
|
||||
|
||||
void reset(void)
|
||||
@@ -135,12 +189,18 @@ void reset(void)
|
||||
|
||||
uint32_t TestCpu6502(uint32_t uTotalCycles)
|
||||
{
|
||||
return Cpu6502(uTotalCycles, true);
|
||||
if (!GetIsMemCacheValid())
|
||||
return Cpu6502_altRW(uTotalCycles, true);
|
||||
else
|
||||
return Cpu6502(uTotalCycles, true);
|
||||
}
|
||||
|
||||
uint32_t TestCpu65C02(uint32_t uTotalCycles)
|
||||
{
|
||||
return Cpu65C02(uTotalCycles, true);
|
||||
if (!GetIsMemCacheValid())
|
||||
return Cpu65C02_altRW(uTotalCycles, true);
|
||||
else
|
||||
return Cpu65C02(uTotalCycles, true);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
@@ -1098,6 +1158,7 @@ int GH292_test(void)
|
||||
|
||||
// Undocumented 65C02 NOP: LDD - LoaD and Discard
|
||||
IORead[0] = fn_C000;
|
||||
g_fn_C000_count = 0;
|
||||
|
||||
reset();
|
||||
WORD base = regs.pc;
|
||||
@@ -1298,6 +1359,7 @@ int GH1257_test()
|
||||
if (regs.pc != resPC[i]) return 1;
|
||||
}
|
||||
|
||||
g_bStopOnBRK = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1359,7 +1421,7 @@ int SyncEvents_test(void)
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
int DoTest(void)
|
||||
{
|
||||
int res = 1;
|
||||
init();
|
||||
@@ -1389,5 +1451,22 @@ int main(int argc, char* argv[])
|
||||
res = SyncEvents_test();
|
||||
if (res) return res;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int res = 1;
|
||||
|
||||
g_isMemCacheValid = true;
|
||||
res = DoTest();
|
||||
if (res) return res;
|
||||
|
||||
g_isMemCacheValid = false;
|
||||
res = DoTest();
|
||||
if (res) return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user