//
// Virtual 65C02 Emulator v1.0
//
-// by James L. Hammons
+// by James Hammons
// (c) 2005 Underground Software
//
-// JLH = James L. Hammons <jlhamm@acm.org>
+// JLH = James Hammons <jlhamm@acm.org>
//
// WHO WHEN WHAT
// --- ---------- ------------------------------------------------------------
if (!(regs.cc & FLAG_C))
HANDLE_BRANCH_TAKEN(m)
-// regs.pc += m;
}
static void OpB0(void) // BCS
if (regs.cc & FLAG_C)
HANDLE_BRANCH_TAKEN(m)
-// regs.pc += m;
}
static void OpF0(void) // BEQ
if (regs.cc & FLAG_Z)
HANDLE_BRANCH_TAKEN(m)
-// regs.pc += m;
}
/*
static void Op00(void) // BRK
{
+//#ifdef __DEBUG__
+#if 1
+WriteLog("\n*** BRK ***\n\n");
+WriteLog(" [PC=%04X, SP=%04X, CC=%s%s.%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n",
+ regs.pc, 0x0100 + regs.sp,
+ (regs.cc & FLAG_N ? "N" : "-"), (regs.cc & FLAG_V ? "V" : "-"),
+ (regs.cc & FLAG_B ? "B" : "-"), (regs.cc & FLAG_D ? "D" : "-"),
+ (regs.cc & FLAG_I ? "I" : "-"), (regs.cc & FLAG_Z ? "Z" : "-"),
+ (regs.cc & FLAG_C ? "C" : "-"), regs.a, regs.x, regs.y);
+#endif
regs.cc |= FLAG_B; // Set B
regs.pc++; // RTI comes back to the instruction one byte after the BRK
regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8); // Save PC and CC
static void Op96(void)
{
- regs.WrMem(EA_ZP_X, regs.x);
+// BUG!!! [FIXED]
+//WAS: regs.WrMem(EA_ZP_X, regs.x);
+ regs.WrMem(EA_ZP_Y, regs.x);
}
static void Op8E(void)
OpF0, OpF1, OpF2, Op__, Op__, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, Op__, Op__, OpFD, OpFE, OpFF
};
+
//
// Internal "memcpy" (so we don't have to link with any external libraries!)
//
//int instCount[256];
#ifdef __DEBUG__
bool dumpDis = false;
+//bool dumpDis = true;
#endif
+/*
+On //e, $FCAA is the delay routine. (seems to not have changed from ][+)
+*/
+
+
//Note: could enforce regs.clock to zero on starting the CPU with an Init() function...
//bleh.
//static uint32_t limit = 0;
-
+// Or, we could just say that initializing the CPU struct is the responsibility
+// of the caller. :-)
+
+#define DO_BACKTRACE
+#ifdef DO_BACKTRACE
+#define BACKTRACE_SIZE 16384
+uint32_t btQueuePtr = 0;
+V65C02REGS btQueue[BACKTRACE_SIZE];
+uint8_t btQueueInst[BACKTRACE_SIZE][4];
+#endif
//
// Function to execute 65C02 for "cycles" cycles
//
myMemcpy(®s, context, sizeof(V65C02REGS));
// Execute here...
-// NOTE: There *must* be some way of doing this without requiring the caller to subtract out
-// the previous run's cycles. !!! FIX !!!
-// Could try:
-// while (regs.clock < regs.clock + cycles) <-- won't work
-/*
- // This isn't as accurate as subtracting out cycles from regs.clock...
- // Unless limit is a static variable, adding cycles to it each time through...
- uint32_t limit = regs.clock + cycles;
- while (regs.clock < limit)
-*/
-// but have wraparound to deal with. :-/
-/*
-Let's see...
-
- if (regs.clock + cycles > 0xFFFFFFFF)
- wraparound = true;
-*/
- uint64_t endCycles = regs.clock + (uint64_t)cycles;
+ uint64_t endCycles = regs.clock + (uint64_t)cycles - regs.overflow;
while (regs.clock < endCycles)
{
dumpDis = false;
}//*/
#endif
+/*if (regs.pc >= 0xC600 && regs.pc <=0xC6FF)
+{
+ dumpDis = true;
+}
+else
+ dumpDis = false;//*/
+/*if (regs.pc == 0xE039)
+{
+ dumpDis = true;
+}//*/
+#if 0
+/*if (regs.pc == 0x0801)
+{
+ WriteLog("\n*** DISK BOOT subroutine...\n\n");
+ dumpDis = true;
+}//*/
+if (regs.pc == 0xE000)
+{
+#if 0
+ WriteLog("\n*** Dump of $E000 routine ***\n\n");
+
+ for(uint32_t addr=0xE000; addr<0xF000;)
+ {
+ addr += Decode65C02(addr);
+ WriteLog("\n");
+ }
+#endif
+ WriteLog("\n*** DISK part II subroutine...\n\n");
+ dumpDis = true;
+}//*/
+if (regs.pc == 0xD000)
+{
+ WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n");
+ dumpDis = false;
+}//*/
+if (regs.pc == 0xD1BE)
+{
+// WriteLog("\n*** DISK part II subroutine...\n\n");
+ dumpDis = true;
+}//*/
+if (regs.pc == 0xD200)
+{
+ WriteLog("\n*** CUSTOM SCREEN subroutine...\n\n");
+ dumpDis = false;
+}//*/
+if (regs.pc == 0xD269)
+{
+// WriteLog("\n*** DISK part II subroutine...\n\n");
+ dumpDis = true;
+}//*/
+#endif
+//if (regs.pc == 0xE08E)
+/*if (regs.pc == 0xAD33)
+{
+ WriteLog("\n*** After loader ***\n\n");
+ dumpDis = true;
+}//*/
+/*if (regs.pc == 0x0418)
+{
+ WriteLog("\n*** CUSTOM DISK READ subroutine...\n\n");
+ dumpDis = false;
+}
+if (regs.pc == 0x0)
+{
+ dumpDis = true;
+}//*/
#ifdef __DEBUGMON__
//WAIT is commented out here because it's called by BELL1...
if (regs.pc == 0xFCA8)
#endif
#ifdef __DEBUG__
+static char disbuf[80];
if (dumpDis)
- Decode65C02(regs.pc);
+{
+ Decode65C02(disbuf, regs.pc);
+ WriteLog("%s", disbuf);
+}
#endif
uint8_t opcode = regs.RdMem(regs.pc++);
}
}
-//This is a lame way of doing it, but in the end the simplest--however, it destroys any
-//record of elasped CPU time. Not sure that it's important to keep track, but there it is.
-// Now we use a 64-bit integer, so it won't wrap for about 500 millenia. ;-)
-// regs.clock -= cycles;
+ // If we went longer than the passed in cycles, make a note of it so we can
+ // subtract it out from a subsequent run. It's guaranteed to be positive,
+ // because the condition that exits the main loop above is written such
+ // that regs.clock has to be larger than endCycles to exit from it.
+ regs.overflow = regs.clock - endCycles;
myMemcpy(context, ®s, sizeof(V65C02REGS));
}
+
//
// Get the clock of the currently executing CPU
//
{
return regs.clock;
}
+