A small emulator for the gigatron created for the STM32F746G-DISCO and an NES wii controller

Revision:
0:72d8735c099e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GigatronCPU.cpp	Thu Mar 05 01:07:01 2020 +0000
@@ -0,0 +1,226 @@
+#include<GigatronCPU.h>
+
+CPUStates GigatronCPU::CpuCycle(CPUStates states)
+{
+	CPUState *T = states.New;
+	CPUState *state = states.Current;
+	
+	//states.CopyToNew();
+	//memcpy(T, state, sizeof(CPUState));		// 1us
+	
+	// --- 25us
+	int data = this->ROM[state->PC];
+	
+
+	// --- 21us	
+	T->IR = data; 		// GetAddressL(this->ROM, state->PC);
+	T->D = (data >> 8); 	// GetAddressH(this->ROM, state->PC);	// 4us
+	
+	// --- 17us
+	
+	int ins = state->IR >> 5;            	// Instruction
+	int mod = (state->IR >> 2) & 7;      	// Addressing mode (or condition)
+	int bus = state->IR & 3;             	// Busmode
+	bool W = (ins == 6);                	// Write instruction?
+	bool J = (ins == 7);                	// Jump instruction?
+
+	char lo = state->D;
+	char hi = 0;
+	
+	//uint32_t t0 = micros();
+	
+	// --- 17us
+		
+	// Load address to read from
+	bool incX = false;
+	if (!J)                         // If we are not jumping
+	{
+		switch (mod)
+		{
+			case 0: // From 0D, _AC
+				break;
+
+			case 1: // From OX, _AC
+				lo = state->X;
+				break;
+
+			case 2: // From YD, _AC
+				hi = state->Y;
+				break;
+
+			case 3: // From YX, _AC
+				lo = state->X;
+				hi = state->Y;
+				break;
+
+			case 4: // From 0D, X
+				break;
+
+			case 5: // From 0D, Y
+				break;
+
+			case 6: // From 0D, OUT
+				break;
+
+			case 7: // From Y,X++, OUT
+				lo = state->X;
+				hi = state->Y;
+				incX = true;
+				break;
+		}
+	}
+			
+	// --- 18
+	uint16_t addr = (uint16_t)((hi << 8) | lo);	//1us
+	// --- 17
+
+	// Feed to Data bus
+	uint8_t B = state->undef; // Data Bus
+	switch (bus)
+	{
+		case 0:
+			B = state->D;
+			break;
+
+		case 1:
+			if (!W)
+			{
+				B = this->RAM[addr & 0x7fff];
+				break;
+			}
+			break;
+
+		case 2:
+			B = state->_AC;
+			break;
+
+		case 3:
+			B = T->IN;
+			break;
+	}
+	
+	// --- 13us
+
+	if (W)
+	{
+		this->RAM[addr & 0x7fff] = B; // Random Access Memory
+	}
+
+	// ALU
+	uint8_t ALU = 0; // Arithmetic and Logic Unit
+	switch (ins)
+	{
+		case 0:
+			ALU = (uint8_t) B;
+			break; // LD
+
+		case 1:
+			ALU = (uint8_t)(state->_AC & B);
+			break; // ANDA
+
+		case 2:
+			ALU = (uint8_t)(state->_AC | B);
+			break; // ORA
+
+		case 3:
+			ALU = (uint8_t)(state->_AC ^ B);
+			break; // XORA
+
+		case 4:
+			ALU = (uint8_t)(state->_AC + B);
+			break; // ADDA
+
+		case 5:
+			ALU = (uint8_t) (state->_AC - B);
+			break; // SUBA
+
+		case 6:
+			ALU = state->_AC;
+			break; // ST
+
+		case 7:
+			ALU = (uint8_t) -state->_AC;
+			break; // Bcc/JMP
+	}
+
+
+	// Output to where it needs to go
+	if (!J)                         // If we are not jumping & not writing
+	{
+		switch (mod)
+		{
+			case 0: // To _AC
+			case 1:
+			case 2:
+			case 3:
+				if (!W)
+				{
+					T->_AC = ALU;
+				}
+				break;
+
+			case 4: // To X
+				T->X = ALU;
+				break;
+
+			case 5: // To Y
+				T->Y = ALU;
+				break;
+
+			case 6: // To OUT
+			case 7: // To OUT
+				if (!W)
+				{
+					T->OUT = ALU;
+
+					int rising = (~state->OUT & ALU);
+
+					if ((rising & 0x40) > 0)      // hSync rising
+					{
+						T->OUTX = T->_AC;
+					}
+				}
+				break;
+		}
+	}
+	
+	if (incX)
+	{
+		T->X = (uint8_t)(state->X + 1); // Increment X
+	}
+	
+	if (J)
+	{
+		if (mod != 0)
+		{
+			// Conditional branch within page
+			int cond = (state->_AC >> 7) + 2 * (state->_AC == 0 ? 1 : 0);
+			if ((mod & (1 << cond)) > 0) // 74153
+			{
+				T->PC = (uint16_t)((state->PC & 0xff00) | B);
+			}
+			else
+			{
+				T->PC = (uint16_t) (state->PC + 1); // Next instruction
+			}
+		}
+		else
+		{
+			T->PC = (uint16_t)((state->Y << 8) | B); // Unconditional far jump
+		}
+	}
+	else
+	{
+		T->PC = (uint16_t) (state->PC + 1); // Next instruction
+	}
+	
+    //uint32_t t1 = micros();
+    //uint32_t delta_t = t1 - t0;
+    //Serial.printf( "Delta = %u\n", delta_t ); // this prints around 51 on my system.
+	
+
+	memcpy(state, T, sizeof(CPUState));		// 2us
+	//states.CopyNewToCurrent();
+	
+	return states;
+}