6502 emulator for Commodore 64 ROMs, serial terminal edition for MBED. Recommend terminal echo on, line edit on, caps lock, 115200bps, implicit carriage return on newline, currently non-buffered so don't paste lots of stuff

More details at:

[https://github.com/davervw] [https://techwithdave.davevw.com/2020/03/simple-emu-c64.html]

Revision:
4:0461c100cbbb
Parent:
0:90de1cbc8a5f
Child:
7:f49fa56672d8
--- a/emu6502.cpp	Fri Apr 10 04:32:54 2020 +0000
+++ b/emu6502.cpp	Sun Apr 12 19:26:44 2020 +0000
@@ -11,7 +11,6 @@
 // davevw.com
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
-//
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@@ -55,6 +54,8 @@
 bool trace = false;
 bool step = false;
 
+#define USE_IRQ 0
+
 extern void ResetRun(bool (*ExecutePatch)(void))
 {
 	ushort addr = (ushort)((GetMemory(0xFFFC) | (GetMemory(0xFFFD) << 8))); // RESET vector
@@ -98,9 +99,9 @@
 static void BRK(byte *p_bytes)
 {
 	++PC;
-	PHP();
 	Push(HI(PC));
 	Push(LO(PC));
+	PHP();
 	B = true;
 	PC = (ushort)(GetMemory(0xFFFE) + (GetMemory(0xFFFF) << 8));
 	*p_bytes = 0;
@@ -186,7 +187,7 @@
 	}
 }
 
-static void ADC(byte value)
+static void ADC_OP(byte value)
 {
 	int result;
 	if (D)
@@ -228,7 +229,7 @@
 	SetA(A & value);
 }
 
-static void BIT(byte value)
+static void BIT_OP(byte value)
 {
 	Z = (A & value) == 0;
 	N = (value & 0x80) != 0;
@@ -491,8 +492,8 @@
 static void RTI(ushort *p_addr, byte *p_bytes)
 {
 	PLP();
+	byte lo = Pop();
 	byte hi = Pop();
-	byte lo = Pop();
 	*p_bytes = 0; // make sure caller does not increase addr by one
 	*p_addr = (ushort)((hi << 8) | lo);
 }
@@ -660,39 +661,60 @@
 	bool conditional;
 	byte bytes;
 
+#if (USE_IRQ == 1)
+	// IRQ support
+	Timer timer;
+	const double interrupt_time = 1.0 / 60.0 ; // 60 times per second
+	timer.start();
+	double timer_then = timer.read();	
+#endif
+
 	PC = addr;
 
 	while (true)
 	{
 		while (true)
 		{
-			bytes = 1;
-			//bool breakpoint = false;
-			//if (Breakpoints.Contains(PC))
-			//	breakpoint = true;
-			bool breakpoint = (addr == 0xFD88);
-			if (trace || breakpoint || step)
+#if (USE_IRQ == 1)
+			if (!I && (timer.read()-timer_then) >= interrupt_time) // IRQ
+			{
+				timer_then = timer.read(); // reset timer
+				Push(HI(PC));
+				Push(LO(PC));
+				PHP();
+				I = true;
+				PC = (GetMemory(0xfffe) | (GetMemory(0xffff) << 8));
+			}
+			else
+#endif			
 			{
-				ushort addr2;
-				char line[27];
-				char dis[13];
-				DisassembleLong(PC, &conditional, &bytes, &addr2, dis, sizeof(dis), line, sizeof(line));
-				char state[33];
-				GetDisplayState(state, sizeof(state));
-				char full_line[80];
-				snprintf(full_line, sizeof(full_line), "%-30s%s\n", line, state);
-#ifdef WIN32
-				OutputDebugStringA(full_line);
-#else				
-				pc.printf("%s", full_line);
-#endif				
-				if (step)
-					step = step; // user can put debug breakpoint here to allow stepping
-				if (breakpoint)
-					breakpoint = breakpoint; // user can put debug breakpoint here to allow break
+				bytes = 1;
+				bool breakpoint = false;
+				//if (Breakpoints.Contains(PC))
+				//	breakpoint = true;
+				if (trace || breakpoint || step)
+				{
+					ushort addr2;
+					char line[27];
+					char dis[13];
+					DisassembleLong(PC, &conditional, &bytes, &addr2, dis, sizeof(dis), line, sizeof(line));
+					char state[33];
+					GetDisplayState(state, sizeof(state));
+					char full_line[80];
+					snprintf(full_line, sizeof(full_line), "%-30s%s\n", line, state);
+	#ifdef WIN32
+					OutputDebugStringA(full_line);
+	#else				
+					pc.printf("%s", full_line);
+	#endif				
+					if (step)
+						step = step; // user can put debug breakpoint here to allow stepping
+					if (breakpoint)
+						breakpoint = breakpoint; // user can put debug breakpoint here to allow break
+				}
+				if (ExecutePatch != 0 && !ExecutePatch()) // allow execute to be overriden at a specific address
+					break;
 			}
-			if (ExecutePatch != 0 && !ExecutePatch()) // allow execute to be overriden at a specific address
-				break;
 		}
 
 		switch (GetMemory(PC))
@@ -718,13 +740,13 @@
 
 		case 0x20: JSR(&PC, &bytes); break;
 		case 0x21: AND(GetIndX(PC, &bytes)); break;
-		case 0x24: BIT(GetZP(PC, &bytes)); break;
+		case 0x24: BIT_OP(GetZP(PC, &bytes)); break;
 		case 0x25: AND(GetZP(PC, &bytes)); break;
 		case 0x26: SetZP(ROL(GetZP(PC, &bytes)), PC, &bytes); break;
 		case 0x28: PLP(); break;
 		case 0x29: AND(GetIM(PC, &bytes)); break;
 		case 0x2A: SetA(ROL(A)); break;
-		case 0x2C: BIT(GetABS(PC, &bytes)); break;
+		case 0x2C: BIT_OP(GetABS(PC, &bytes)); break;
 		case 0x2D: AND(GetABS(PC, &bytes)); break;
 		case 0x2E: ROL(GetABS(PC, &bytes)); break;
 
@@ -758,23 +780,23 @@
 		case 0x5E: SetABSX(LSR(GetABSX(PC, &bytes)), PC, &bytes); break;
 
 		case 0x60: RTS(&PC, &bytes); break;
-		case 0x61: ADC(GetIndX(PC, &bytes)); break;
-		case 0x65: ADC(GetZP(PC, &bytes)); break;
+		case 0x61: ADC_OP(GetIndX(PC, &bytes)); break;
+		case 0x65: ADC_OP(GetZP(PC, &bytes)); break;
 		case 0x66: SetZP(ROR(GetZP(PC, &bytes)), PC, &bytes); break;
 		case 0x68: PLA(); break;
-		case 0x69: ADC(GetIM(PC, &bytes)); break;
+		case 0x69: ADC_OP(GetIM(PC, &bytes)); break;
 		case 0x6A: SetA(ROR(A)); break;
 		case 0x6C: JMPIND(&PC, &bytes); break;
-		case 0x6D: ADC(GetABS(PC, &bytes)); break;
+		case 0x6D: ADC_OP(GetABS(PC, &bytes)); break;
 		case 0x6E: SetABS(ROR(GetABS(PC, &bytes)), PC, &bytes); break;
 
 		case 0x70: BVS(&PC, &conditional, &bytes); break;
-		case 0x71: ADC(GetIndY(PC, &bytes)); break;
-		case 0x75: ADC(GetZPX(PC, &bytes)); break;
+		case 0x71: ADC_OP(GetIndY(PC, &bytes)); break;
+		case 0x75: ADC_OP(GetZPX(PC, &bytes)); break;
 		case 0x76: SetZPX(ROR(GetZPX(PC, &bytes)), PC, &bytes); break;
 		case 0x78: SEI(); break;
-		case 0x79: ADC(GetABSY(PC, &bytes)); break;
-		case 0x7D: ADC(GetABSX(PC, &bytes)); break;
+		case 0x79: ADC_OP(GetABSY(PC, &bytes)); break;
+		case 0x7D: ADC_OP(GetABSX(PC, &bytes)); break;
 		case 0x7E: SetABSX(ROR(GetABSX(PC, &bytes)), PC, &bytes); break;
 
 		case 0x81: SetIndX(A, PC, &bytes); break;