Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.IO;
- using System.Linq;
- using System.Windows.Forms;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Windows.Threading;
- using System.Threading;
- namespace SpaceInvaders
- {
- class CPU
- {
- private _8080 _8080 = new _8080();
- private MainForm MainForm = new MainForm();
- public byte[] memory = new byte[65000];
- private uint opcode; // Opcode
- #region Declare Variables
- // Declare registers
- private byte A { get; set; }
- private byte B { get; set; }
- private byte C { get; set; }
- private byte D { get; set; }
- private byte E { get; set; }
- private byte H { get; set; }
- private byte L { get; set; }
- private ushort addr;
- private ushort BC
- {
- get
- {
- return (ushort)(B << 8 | C);
- }
- set
- {
- B = (byte)(value >> 8); C = (byte)value;
- }
- }
- private ushort DE
- {
- get
- {
- return (ushort)(D << 8 | E);
- }
- set
- {
- D = (byte)(value >> 8); E = (byte)value;
- }
- }
- private ushort HL
- {
- get
- {
- return (ushort)(H << 8 | L);
- }
- set
- {
- H = (byte)(value >> 8); L = (byte)value;
- }
- }
- public void initialiseEmulator()
- {
- // Reset pointers
- SP = 0;
- PC = 0;
- PREVPC = 0;
- // Clear flags
- Z = 0;
- S = 0;
- P = 0;
- CY = 0;
- AC = 0;
- isRunning = true;
- }
- // Declare flags
- public byte Z { get; set; } // Zero
- public byte S { get; set; } // Signed
- public byte P { get; set; } // Parity
- public byte CY { get; set; } // Carry
- public byte AC { get; set; }
- private int PSW;
- private int PSWtemp;
- public ushort SP; // Stack Pointer
- public ushort PC; // Program Counter
- public ushort PREVPC; // Previous PC before it was incremented / decremented. Used to write to console.
- private int videoRamStart = 0x2400;
- private int videoRamEnd = 0x4000;
- private int counter = 0;
- private bool canInterupt = false;
- public bool isRunning = true;
- private Bitmap screenBuffer = new Bitmap(224, 256);
- private int adr = 0x2400;
- #endregion
- public void emulateCPU()
- {
- while (isRunning)
- {
- opcode = memory[PC];
- switch (opcode)
- {
- case 0x00:
- PREVPC = PC;
- PC++;
- DisplayInfo(opcode, "NOP");
- break;
- case 0x01:
- PREVPC = PC;
- BC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- PC += 3;
- DisplayInfo(opcode, "LXI B");
- break;
- case 0x05:
- PREVPC = PC;
- B--;
- setFlag(B, 30);
- PC++;
- DisplayInfo(opcode, "DCR B");
- break;
- case 0x06:
- PREVPC = PC;
- B = memory[PC + 1];
- PC += 2;
- DisplayInfo(opcode, "MVI B");
- break;
- case 0x09:
- PREVPC = PC;
- HL = ((ushort)(HL + BC));
- setFlag(HL, 1);
- PC++;
- DisplayInfo(opcode, "DAD B");
- break;
- case 0x0A:
- PREVPC = PC;
- A = memory[BC];
- PC++;
- DisplayInfo(opcode, "LDAX B");
- break;
- case 0x0B:
- PREVPC = PC;
- BC--;
- PC++;
- DisplayInfo(opcode, "DCX B");
- break;
- case 0x0D:
- PREVPC = PC;
- C--;
- setFlag(C, 30);
- PC++;
- DisplayInfo(opcode, "DCR C");
- break;
- case 0x0E:
- PREVPC = PC;
- C = memory[PC + 1];
- PC += 2;
- DisplayInfo(opcode, "MVI C");
- break;
- case 0x0F: // NEEDS CHECKING NEW ****
- PREVPC = PC;
- byte temp = A;
- A = (byte)((byte)((temp & 1) << 7) | (temp >> 1));
- setFlag(A, 1);
- PC++;
- DisplayInfo(opcode, "RRC");
- break;
- case 0x11:
- PREVPC = PC;
- DE = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- PC += 3;
- DisplayInfo(opcode, "LXI D");
- break;
- case 0x13:
- PREVPC = PC;
- DE++;
- PC++;
- DisplayInfo(opcode, "INX D");
- break;
- case 0x19:
- PREVPC = PC;
- HL = ((ushort)(HL + DE));
- setFlag(HL, 1);
- PC++;
- DisplayInfo(opcode, "DAD D");
- break;
- case 0x1A:
- PREVPC = PC;
- A = memory[DE];
- PC++;
- DisplayInfo(opcode, "LDAX D");
- break;
- case 0x21:
- PREVPC = PC;
- HL = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- PC += 3;
- DisplayInfo(opcode, "LXI H");
- break;
- case 0x23:
- PREVPC = PC;
- HL++;
- PC++;
- DisplayInfo(opcode, "INC H");
- break;
- case 0x26:
- PREVPC = PC;
- H = memory[PC + 1];
- PC += 2;
- DisplayInfo(opcode, "MVI H");
- break;
- case 0x29:
- PREVPC = PC;
- HL = ((ushort)(HL + HL));
- setFlag(HL, 1);
- PC++;
- DisplayInfo(opcode, "DAD H");
- break;
- case 0x31:
- PREVPC = PC;
- SP = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- PC += 3;
- DisplayInfo(opcode, "LXI SP");
- break;
- case 0x32: // ** POSSIBLY WRONG ** NEW
- PREVPC = PC;
- addr = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- memory[addr] = A;
- PC += 3;
- DisplayInfo(opcode, "STA ADR");
- break;
- case 0x36:
- PREVPC = PC;
- memory[HL] = memory[PC + 1];
- PC += 2;
- DisplayInfo(opcode, "MVI M");
- break;
- case 0x37:
- PREVPC = PC;
- CY = 1;
- PC++;
- DisplayInfo(opcode, "SET C");
- break;
- case 0x3A: // THIS IS PROBABLY WRONG!
- PREVPC = PC;
- addr = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- A = memory[addr];
- PC += 3;
- DisplayInfo(opcode, "LDA ADR");
- break;
- case 0x3D:
- PREVPC = PC;
- A--;
- setFlag(A, 30);
- PC++;
- DisplayInfo(opcode, "DCR A");
- break;
- case 0x3E:
- PREVPC = PC;
- A = memory[PC + 1];
- PC += 2;
- DisplayInfo(opcode, "MVI A");
- break;
- case 0x56:
- PREVPC = PC;
- D = memory[HL];
- PC++;
- DisplayInfo(opcode, "MOV D M");
- break;
- case 0x5E:
- PREVPC = PC;
- E = memory[HL];
- PC++;
- DisplayInfo(opcode, "MOV E M");
- break;
- case 0x66:
- PREVPC = PC;
- H = memory[HL];
- PC++;
- DisplayInfo(opcode, "MOV H M");
- break;
- case 0x6F:
- PREVPC = PC;
- L = A;
- PC++;
- DisplayInfo(opcode, "MOV L");
- break;
- case 0x77:
- PREVPC = PC;
- memory[HL] = A;
- PC++;
- DisplayInfo(opcode, "MOV M A");
- break;
- case 0x7A:
- PREVPC = PC;
- A = D;
- PC++;
- DisplayInfo(opcode, "MOVE A D");
- break;
- case 0x7B:
- PREVPC = PC;
- A = E;
- PC++;
- DisplayInfo(opcode, "MOVE A E");
- break;
- case 0x7C:
- PREVPC = PC;
- A = H;
- PC++;
- DisplayInfo(opcode, "MOV A H");
- break;
- case 0x7E:
- PREVPC = PC;
- A = memory[HL];
- PC++;
- DisplayInfo(opcode, "MOV A M");
- break;
- case 0xA7:
- PREVPC = PC;
- A = (byte)(A & A);
- setFlag(A, 31);
- PC++;
- DisplayInfo(opcode, "ANA A");
- break;
- case 0xAF:
- PREVPC = PC;
- A = (byte)(A ^ A);
- setFlag(A, 31);
- PC++;
- DisplayInfo(opcode, "XRA A");
- break;
- case 0xC1:
- PREVPC = PC;
- C = memory[SP];
- B = memory[SP + 1];
- SP += 2;
- PC++;
- DisplayInfo(opcode, "POP B");
- break;
- case 0xC2:
- PREVPC = PC;
- if (Z == 0)
- {
- PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- }
- else
- {
- PC += 3;
- }
- DisplayInfo(opcode, "JNZ ADR");
- break;
- case 0xC3:
- PREVPC = PC;
- PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- DisplayInfo(opcode, "JMP ADDR");
- break;
- case 0xC5:
- PREVPC = PC;
- memory[SP - 1] = B;
- memory[SP - 2] = C;
- SP -= 2;
- PC++;
- DisplayInfo(opcode, "PUSH B");
- break;
- case 0xC6: // NEEDS CHECKING ***
- PREVPC = PC;
- A += (memory[PC + 1]);
- setFlag(A, 31);
- PC += 2;
- DisplayInfo(opcode, "ADI");
- break;
- case 0xC8:
- PREVPC = PC;
- if (Z == 0)
- {
- PC = (ushort)(memory[SP + 1] << 8 | memory[SP]);
- SP += 2;
- }
- else
- {
- PC++;
- }
- DisplayInfo(opcode, "RET");
- break;
- case 0xC9:
- PREVPC = PC;
- PC = (ushort)(memory[SP + 1] << 8 | memory[SP]);
- SP += 2;
- DisplayInfo(opcode, "RET");
- break;
- case 0xCA:
- PREVPC = PC;
- if (Z == 1)
- {
- PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- }
- else
- {
- PC += 3;
- }
- DisplayInfo(opcode, "JZ ADR");
- break;
- case 0xCD:
- PREVPC = PC;
- memory[SP - 1] = (byte)((PC + 3 >> 8) & 0xff);
- memory[SP - 2] = (byte)(PC + 3 & 0xff);
- SP -= 2;
- PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- DisplayInfo(opcode, "CALL ADDR");
- break;
- case 0xD1:
- PREVPC = PC;
- E = memory[SP];
- D = memory[SP + 1];
- SP += 2;
- PC++;
- DisplayInfo(opcode, "POP D");
- break;
- case 0xD3:
- PC += 2;
- DisplayInfo(opcode, "OUT D8");
- break;
- case 0xD5:
- PREVPC = PC;
- memory[SP - 1] = D;
- memory[SP - 2] = E;
- SP -= 2;
- PC++;
- DisplayInfo(opcode, "PUSH D");
- break;
- case 0xD8:
- PREVPC = PC;
- if (CY == 1)
- {
- PC = (ushort)(memory[SP + 1] << 8 | memory[SP]);
- SP += 2;
- }
- else
- {
- PC++;
- }
- DisplayInfo(opcode, "RC");
- break;
- case 0xDA:
- PREVPC = PC;
- if (CY == 1)
- {
- PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
- }
- else
- {
- PC++;
- }
- DisplayInfo(opcode, "JC ADR");
- break;
- case 0xE1: // ** MIGHT BE WRONG! **
- PREVPC = PC;
- L = memory[SP];
- H = memory[SP + 1];
- SP += 2;
- PC++;
- DisplayInfo(opcode, "POP H");
- break;
- case 0xE5:
- PREVPC = PC;
- memory[SP - 1] = H;
- memory[SP - 2] = L;
- SP -= 2;
- PC++;
- DisplayInfo(opcode, "PUSH H");
- break;
- case 0xE6:
- PREVPC = PC;
- A = (byte)(A & memory[PC + 1]);
- setFlag(A, 31);
- PC += 2;
- DisplayInfo(opcode, "ANI");
- break;
- case 0xEB:
- PREVPC = PC;
- ushort tmp = HL;
- HL = DE;
- DE = tmp;
- PC++;
- DisplayInfo(opcode, "XCHG");
- break;
- case 0xF1:
- PREVPC = PC;
- A = memory[SP + 1];
- PSW = memory[SP];
- Z = (byte)(PSW & 0x01);
- S = (byte)(PSW & 0x02);
- P = (byte)(PSW & 0x04);
- AC = (byte)(PSW & 0x08);
- CY = (byte)(PSW & 0x10);
- SP += 2;
- PC++;
- DisplayInfo(opcode, "POP PSW");
- break;
- case 0xF3:
- PREVPC = PC;
- canInterupt = false;
- PC++;
- DisplayInfo(opcode, "DI");
- break;
- case 0xF5:
- PREVPC = PC;
- memory[SP - 1] = A;
- PSW = Z | S << 1 | P << 2 | AC << 3 | CY << 4;
- memory[SP - 2] = (byte)PSW;
- SP -= 2;
- PC++;
- DisplayInfo(opcode, "PUSH PSW");
- break;
- case 0xFB:
- PREVPC = PC;
- canInterupt = true;
- DisplayInfo(opcode, "EI");
- PC++;
- break;
- case 0xFE: // NEEDS CHECKING TOO ***
- PREVPC = PC;
- ushort tempCheck = (ushort)(A - memory[PC + 1]);
- setFlag(tempCheck, 31);
- PC += 2;
- DisplayInfo(opcode, "CPI D8");
- break;
- default:
- UnimplementedInstruction(opcode);
- break;
- }
- }
- }
- public void generateInterupt()
- {
- memory[SP - 1] = (byte)((PC >> 8) & 0xff);
- memory[SP - 2] = (byte)(PC & 0xff);
- SP -= 2;
- PC = 0010;
- }
- private void setFlag(ushort value, byte bitToCheck)
- {
- //If I want to check the ZERO flag, then I pass the value to check and the bit number for Z, which is 8(4th bit in binary is 8)
- //If I want to check the ZERO flag and the Carry flag, I would send 9(8 for ZERO and 1 for CARRY).
- // Z S P A C
- // C = 0 > ADD 1 CHECK CARRY
- // A = 1 > ADD 2 CHECK PARITY
- // P = 2 > ADD 4 CHECK AC
- // S = 3 > ADD 8 CHECK ZERO
- // Z = 4 > ADD 16 CHECK SIGN
- for (int i = 0; i < 5; i++) // Check the 5 bits. If 0th bit is set, check Half carry of Value. If 1 is set, check Carry of Value ... etc.
- {
- if ((bitToCheck & (1 << i)) != 0)
- {
- if (i == 0) // CARRY CHECK (C)
- {
- if (value > 0xFF)
- {
- CY = 1; // Set the carry if more than 255
- }
- else
- {
- CY = 0;
- }
- }
- if (i == 2) // PARITY CHECK (P)
- {
- }
- if (i == 3) // SIGN CHECK (S)
- {
- if ((value >> 7) == 1)
- {
- S = 1;
- }
- else
- {
- S = 0;
- }
- }
- if (i == 4) // ZERO CHECK (Z)
- if (value == 0)
- {
- Z = 1;
- }
- else
- {
- Z = 0;
- }
- }
- }
- PSWtemp = C | 1 << 1 | P << 2 | 0 << 3 | AC << 4 | 0 << 5 | Z << 6 | S << 7;
- string binPSW = Convert.ToString(PSWtemp, 2);
- Console.WriteLine("PSW BINARY " + binPSW);
- }
- private void UnimplementedInstruction(uint opcode)
- {
- //pc will have advanced one, so undo that
- Debug.WriteLine("\n" + PC.ToString("X4") + " : *ERROR* " + opcode.ToString("X4") + " is an unimplemented instruction.\n");
- isRunning = false;
- }
- private void DisplayInfo(uint opcode, string info)
- {
- string newLine = Environment.NewLine;
- Debug.WriteLine("{0,0} : {1,-4} {2,-10} : Results > PC {3} SP {4} BC {5} DE {6} HL {7} : B {8} C {9} D {10} E {11} H {12} L {13} : FLAGS >> Z {14} S {15} P {16} CY {17} AC {18} : SPECIAL > A {19} > PSW {20}", PREVPC.ToString("X4"), opcode.ToString("X4"), info, PC.ToString("X4"), SP.ToString("X4"), BC.ToString("X4"), DE.ToString("X4"), HL.ToString("X4"), B.ToString("X2"), C.ToString("X2"), D.ToString("X2"), E.ToString("X2"), H.ToString("X2"), L.ToString("X2"), Z.ToString("X"), S.ToString("X"), P.ToString("X"), CY.ToString("X"), AC.ToString("X"), A.ToString("X2"), PSWtemp.ToString("X2"));
- //OpcodeList.BeginInvoke(new Action(() => { OpcodeList.AppendText(opcode.ToString("X4") + " " + info + newLine); }));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement