Support IIe aux slot: 80-col(1KiB) card via generic read ptrs (#1341, PR #1391)

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:
TomCh
2025-04-03 13:10:02 -07:00
committed by GitHub
parent 629e1344a2
commit 839c493b67
31 changed files with 1073 additions and 589 deletions
-1
View File
@@ -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" />
-3
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+82
View File
@@ -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
+82
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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)
+68 -47
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,6 +1,7 @@
#pragma once
#include "../Common.h"
#include "../MemoryDefs.h"
#include "Debugger_Types.h"
#include "Debugger_DisassemblerData.h"
-13
View File
@@ -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;
+18 -21
View File
@@ -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)
+21 -21
View File
@@ -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++ = '"';
}
+20 -20
View File
@@ -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 );
+10 -2
View File
@@ -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
{
-12
View File
@@ -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,
+8 -8
View File
@@ -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
View File
@@ -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++)
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
};
+9 -9
View File
@@ -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)
+7 -5
View File
@@ -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
}
}
-4
View File
@@ -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
+12 -10
View File
@@ -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;
+4 -4
View File
@@ -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)
+1 -8
View File
@@ -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:
+97 -18
View File
@@ -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;
}