Advertisement
Guest User

Untitled

a guest
May 30th, 2022
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 23.31 KB | None | 0 0
  1. using System;
  2. using System.ComponentModel;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Windows.Forms;
  7. using System.Drawing;
  8. using System.Drawing.Imaging;
  9. using System.Windows.Threading;
  10. using System.Threading;
  11.  
  12. namespace SpaceInvaders
  13. {
  14.     class CPU
  15.     {
  16.         private _8080 _8080 = new _8080();
  17.         private MainForm MainForm = new MainForm();
  18.  
  19.         public byte[] memory = new byte[65000];
  20.  
  21.         private uint opcode; // Opcode
  22.  
  23.         #region Declare Variables
  24.  
  25.  
  26.         // Declare registers
  27.         private byte A { get; set; }
  28.         private byte B { get; set; }
  29.         private byte C { get; set; }
  30.         private byte D { get; set; }
  31.         private byte E { get; set; }
  32.         private byte H { get; set; }
  33.         private byte L { get; set; }
  34.  
  35.         private ushort addr;
  36.  
  37.         private ushort BC
  38.         {
  39.             get
  40.             {
  41.                 return (ushort)(B << 8 | C);
  42.             }
  43.  
  44.             set
  45.             {
  46.                 B = (byte)(value >> 8); C = (byte)value;
  47.             }
  48.         }
  49.  
  50.         private ushort DE
  51.         {
  52.             get
  53.             {
  54.                 return (ushort)(D << 8 | E);
  55.             }
  56.  
  57.             set
  58.             {
  59.                 D = (byte)(value >> 8); E = (byte)value;
  60.             }
  61.         }
  62.  
  63.         private ushort HL
  64.         {
  65.             get
  66.             {
  67.                 return (ushort)(H << 8 | L);
  68.             }
  69.  
  70.             set
  71.             {
  72.                 H = (byte)(value >> 8); L = (byte)value;
  73.             }
  74.         }
  75.  
  76.         public void initialiseEmulator()
  77.         {
  78.             // Reset pointers
  79.             SP = 0;
  80.             PC = 0;
  81.             PREVPC = 0;
  82.  
  83.             // Clear flags
  84.             Z = 0;
  85.             S = 0;
  86.             P = 0;
  87.             CY = 0;
  88.             AC = 0;
  89.  
  90.             isRunning = true;
  91.         }
  92.  
  93.         // Declare flags
  94.         public byte Z { get; set; } // Zero
  95.         public byte S { get; set; } // Signed
  96.         public byte P { get; set; } // Parity
  97.         public byte CY { get; set; } // Carry
  98.         public byte AC { get; set; }
  99.  
  100.         private int PSW;
  101.         private int PSWtemp;
  102.  
  103.         public ushort SP; // Stack Pointer
  104.         public ushort PC; // Program Counter
  105.         public ushort PREVPC; // Previous PC before it was incremented / decremented. Used to write to console.
  106.  
  107.  
  108.  
  109.         private int videoRamStart = 0x2400;
  110.         private int videoRamEnd = 0x4000;
  111.  
  112.         private int counter = 0;
  113.         private bool canInterupt = false;
  114.         public bool isRunning = true;
  115.  
  116.         private Bitmap screenBuffer = new Bitmap(224, 256);
  117.         private int adr = 0x2400;
  118.  
  119.         #endregion
  120.  
  121.         public void emulateCPU()
  122.         {
  123.             while (isRunning)
  124.             {
  125.  
  126.                 opcode = memory[PC];
  127.  
  128.                 switch (opcode)
  129.                 {
  130.                     case 0x00:
  131.                         PREVPC = PC;
  132.                         PC++;
  133.                         DisplayInfo(opcode, "NOP");
  134.                         break;
  135.  
  136.                     case 0x01:
  137.                         PREVPC = PC;
  138.                         BC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  139.                         PC += 3;
  140.                         DisplayInfo(opcode, "LXI B");
  141.                         break;
  142.  
  143.                     case 0x05:
  144.                         PREVPC = PC;
  145.                         B--;
  146.                         setFlag(B, 30);
  147.                         PC++;
  148.                         DisplayInfo(opcode, "DCR B");
  149.                         break;
  150.  
  151.                     case 0x06:
  152.                         PREVPC = PC;
  153.                         B = memory[PC + 1];
  154.                         PC += 2;
  155.                         DisplayInfo(opcode, "MVI B");
  156.                         break;
  157.  
  158.                     case 0x09:
  159.                         PREVPC = PC;
  160.                         HL = ((ushort)(HL + BC));
  161.                         setFlag(HL, 1);
  162.                         PC++;
  163.                         DisplayInfo(opcode, "DAD B");
  164.                         break;
  165.  
  166.                     case 0x0A:
  167.                         PREVPC = PC;
  168.                         A = memory[BC];
  169.                         PC++;
  170.                         DisplayInfo(opcode, "LDAX B");
  171.                         break;
  172.  
  173.                     case 0x0B:
  174.                         PREVPC = PC;
  175.                         BC--;
  176.                         PC++;
  177.                         DisplayInfo(opcode, "DCX B");
  178.                         break;
  179.  
  180.                     case 0x0D:
  181.                         PREVPC = PC;
  182.                         C--;
  183.                         setFlag(C, 30);
  184.                         PC++;
  185.                         DisplayInfo(opcode, "DCR C");
  186.                         break;
  187.  
  188.                     case 0x0E:
  189.                         PREVPC = PC;
  190.                         C = memory[PC + 1];
  191.                         PC += 2;
  192.                         DisplayInfo(opcode, "MVI C");
  193.                         break;
  194.  
  195.                     case 0x0F: // NEEDS CHECKING NEW ****
  196.                         PREVPC = PC;
  197.                         byte temp = A;
  198.                         A = (byte)((byte)((temp & 1) << 7) | (temp >> 1));
  199.                         setFlag(A, 1);
  200.                         PC++;
  201.                         DisplayInfo(opcode, "RRC");
  202.                         break;
  203.  
  204.  
  205.                     case 0x11:
  206.                         PREVPC = PC;
  207.                         DE = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  208.                         PC += 3;
  209.                         DisplayInfo(opcode, "LXI D");
  210.                         break;
  211.  
  212.                     case 0x13:
  213.                         PREVPC = PC;
  214.                         DE++;
  215.                         PC++;
  216.                         DisplayInfo(opcode, "INX D");
  217.                         break;
  218.  
  219.                     case 0x19:
  220.                         PREVPC = PC;
  221.                         HL = ((ushort)(HL + DE));
  222.                         setFlag(HL, 1);
  223.                         PC++;
  224.                         DisplayInfo(opcode, "DAD D");
  225.                         break;
  226.  
  227.                     case 0x1A:
  228.                         PREVPC = PC;
  229.                         A = memory[DE];
  230.                         PC++;
  231.                         DisplayInfo(opcode, "LDAX D");
  232.                         break;
  233.  
  234.  
  235.                     case 0x21:
  236.                         PREVPC = PC;
  237.                         HL = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  238.                         PC += 3;
  239.                         DisplayInfo(opcode, "LXI H");
  240.                         break;
  241.  
  242.                     case 0x23:
  243.                         PREVPC = PC;
  244.                         HL++;
  245.                         PC++;
  246.                         DisplayInfo(opcode, "INC H");
  247.                         break;
  248.  
  249.                     case 0x26:
  250.                         PREVPC = PC;
  251.                         H = memory[PC + 1];
  252.                         PC += 2;
  253.                         DisplayInfo(opcode, "MVI H");
  254.                         break;
  255.  
  256.                     case 0x29:
  257.                         PREVPC = PC;
  258.                         HL = ((ushort)(HL + HL));
  259.                         setFlag(HL, 1);
  260.                         PC++;
  261.                         DisplayInfo(opcode, "DAD H");
  262.                         break;
  263.  
  264.  
  265.                     case 0x31:
  266.                         PREVPC = PC;
  267.                         SP = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  268.                         PC += 3;
  269.                         DisplayInfo(opcode, "LXI SP");
  270.                         break;
  271.  
  272.                     case 0x32: // ** POSSIBLY WRONG ** NEW
  273.                         PREVPC = PC;
  274.                         addr = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  275.                         memory[addr] = A;
  276.                         PC += 3;
  277.                         DisplayInfo(opcode, "STA ADR");
  278.                         break;
  279.  
  280.                     case 0x36:
  281.                         PREVPC = PC;
  282.                         memory[HL] = memory[PC + 1];
  283.                         PC += 2;
  284.                         DisplayInfo(opcode, "MVI M");
  285.                         break;
  286.  
  287.                     case 0x37:
  288.                         PREVPC = PC;
  289.                         CY = 1;
  290.                         PC++;
  291.                         DisplayInfo(opcode, "SET C");
  292.                         break;
  293.  
  294.                     case 0x3A: // THIS IS PROBABLY WRONG!
  295.                         PREVPC = PC;
  296.                         addr = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  297.                         A = memory[addr];
  298.                         PC += 3;
  299.                         DisplayInfo(opcode, "LDA ADR");
  300.                         break;
  301.  
  302.                     case 0x3D:
  303.                         PREVPC = PC;
  304.                         A--;
  305.                         setFlag(A, 30);
  306.                         PC++;
  307.                         DisplayInfo(opcode, "DCR A");
  308.                         break;
  309.  
  310.                     case 0x3E:
  311.                         PREVPC = PC;
  312.                         A = memory[PC + 1];
  313.                         PC += 2;
  314.                         DisplayInfo(opcode, "MVI A");
  315.                         break;
  316.  
  317.                     case 0x56:
  318.                         PREVPC = PC;
  319.                         D = memory[HL];
  320.                         PC++;
  321.                         DisplayInfo(opcode, "MOV D M");
  322.                         break;
  323.  
  324.                     case 0x5E:
  325.                         PREVPC = PC;
  326.                         E = memory[HL];
  327.                         PC++;
  328.                         DisplayInfo(opcode, "MOV E M");
  329.                         break;
  330.  
  331.                     case 0x66:
  332.                         PREVPC = PC;
  333.                         H = memory[HL];
  334.                         PC++;
  335.                         DisplayInfo(opcode, "MOV H M");
  336.                         break;
  337.  
  338.                     case 0x6F:
  339.                         PREVPC = PC;
  340.                         L = A;
  341.                         PC++;
  342.                         DisplayInfo(opcode, "MOV L");
  343.                         break;
  344.  
  345.                     case 0x77:
  346.                         PREVPC = PC;
  347.                         memory[HL] = A;
  348.                         PC++;
  349.                         DisplayInfo(opcode, "MOV M A");
  350.                         break;
  351.  
  352.                     case 0x7A:
  353.                         PREVPC = PC;
  354.                         A = D;
  355.                         PC++;
  356.                         DisplayInfo(opcode, "MOVE A D");
  357.                         break;
  358.  
  359.                     case 0x7B:
  360.                         PREVPC = PC;
  361.                         A = E;
  362.                         PC++;
  363.                         DisplayInfo(opcode, "MOVE A E");
  364.                         break;
  365.  
  366.                     case 0x7C:
  367.                         PREVPC = PC;
  368.                         A = H;
  369.                         PC++;
  370.                         DisplayInfo(opcode, "MOV A H");
  371.                         break;
  372.  
  373.                     case 0x7E:
  374.                         PREVPC = PC;
  375.                         A = memory[HL];
  376.                         PC++;
  377.                         DisplayInfo(opcode, "MOV A M");
  378.                         break;
  379.  
  380.                     case 0xA7:
  381.                         PREVPC = PC;
  382.                         A = (byte)(A & A);
  383.                         setFlag(A, 31);
  384.                         PC++;
  385.                         DisplayInfo(opcode, "ANA A");
  386.                         break;
  387.  
  388.                     case 0xAF:
  389.                         PREVPC = PC;
  390.                         A = (byte)(A ^ A);
  391.                         setFlag(A, 31);
  392.                         PC++;
  393.                         DisplayInfo(opcode, "XRA A");
  394.                         break;
  395.  
  396.                     case 0xC1:
  397.                         PREVPC = PC;
  398.                         C = memory[SP];
  399.                         B = memory[SP + 1];
  400.                         SP += 2;
  401.                         PC++;
  402.                         DisplayInfo(opcode, "POP B");
  403.                         break;
  404.  
  405.                     case 0xC2:
  406.                         PREVPC = PC;
  407.                         if (Z == 0)
  408.                         {
  409.                             PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  410.                         }
  411.                         else
  412.                         {
  413.                             PC += 3;
  414.                         }
  415.                         DisplayInfo(opcode, "JNZ ADR");
  416.                         break;
  417.  
  418.                     case 0xC3:
  419.                         PREVPC = PC;
  420.                         PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  421.                         DisplayInfo(opcode, "JMP ADDR");
  422.                         break;
  423.  
  424.                     case 0xC5:
  425.                         PREVPC = PC;
  426.                         memory[SP - 1] = B;
  427.                         memory[SP - 2] = C;
  428.                         SP -= 2;
  429.                         PC++;
  430.                         DisplayInfo(opcode, "PUSH B");
  431.                         break;
  432.  
  433.                     case 0xC6: // NEEDS CHECKING ***
  434.                         PREVPC = PC;
  435.                         A += (memory[PC + 1]);
  436.                         setFlag(A, 31);
  437.                         PC += 2;
  438.                         DisplayInfo(opcode, "ADI");
  439.                         break;
  440.  
  441.                     case 0xC8:
  442.                         PREVPC = PC;
  443.                         if (Z == 0)
  444.                         {
  445.                             PC = (ushort)(memory[SP + 1] << 8 | memory[SP]);
  446.                             SP += 2;
  447.                         }
  448.                         else
  449.                         {
  450.                             PC++;
  451.                         }
  452.                         DisplayInfo(opcode, "RET");
  453.                         break;
  454.  
  455.                     case 0xC9:
  456.                         PREVPC = PC;
  457.                         PC = (ushort)(memory[SP + 1] << 8 | memory[SP]);
  458.                         SP += 2;
  459.                         DisplayInfo(opcode, "RET");
  460.                         break;
  461.  
  462.                     case 0xCA:
  463.                         PREVPC = PC;
  464.                         if (Z == 1)
  465.                         {
  466.                             PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  467.                         }
  468.                         else
  469.                         {
  470.                             PC += 3;
  471.                         }
  472.                         DisplayInfo(opcode, "JZ ADR");
  473.                         break;
  474.  
  475.  
  476.                     case 0xCD:
  477.                         PREVPC = PC;
  478.                         memory[SP - 1] = (byte)((PC + 3 >> 8) & 0xff);
  479.                         memory[SP - 2] = (byte)(PC + 3 & 0xff);
  480.                         SP -= 2;
  481.                         PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  482.                         DisplayInfo(opcode, "CALL ADDR");
  483.                         break;
  484.  
  485.                     case 0xD1:
  486.                         PREVPC = PC;
  487.                         E = memory[SP];
  488.                         D = memory[SP + 1];
  489.                         SP += 2;
  490.                         PC++;
  491.                         DisplayInfo(opcode, "POP D");
  492.                         break;
  493.  
  494.                     case 0xD3:
  495.                         PC += 2;
  496.                         DisplayInfo(opcode, "OUT D8");
  497.                         break;
  498.  
  499.                     case 0xD5:
  500.                         PREVPC = PC;
  501.                         memory[SP - 1] = D;
  502.                         memory[SP - 2] = E;
  503.                         SP -= 2;
  504.                         PC++;
  505.                         DisplayInfo(opcode, "PUSH D");
  506.                         break;
  507.  
  508.                     case 0xD8:
  509.                         PREVPC = PC;
  510.                         if (CY == 1)
  511.                         {
  512.                             PC = (ushort)(memory[SP + 1] << 8 | memory[SP]);
  513.                             SP += 2;
  514.                         }
  515.                         else
  516.                         {
  517.                             PC++;
  518.                         }
  519.                         DisplayInfo(opcode, "RC");
  520.                         break;
  521.  
  522.                     case 0xDA:
  523.                         PREVPC = PC;
  524.                         if (CY == 1)
  525.                         {
  526.                             PC = (ushort)(memory[PC + 2] << 8 | memory[PC + 1]);
  527.                         }
  528.                         else
  529.                         {
  530.                             PC++;
  531.                         }
  532.                         DisplayInfo(opcode, "JC ADR");
  533.                         break;
  534.  
  535.                     case 0xE1: // ** MIGHT BE WRONG! **
  536.                         PREVPC = PC;
  537.                         L = memory[SP];
  538.                         H = memory[SP + 1];
  539.                         SP += 2;
  540.                         PC++;
  541.                         DisplayInfo(opcode, "POP H");
  542.                         break;
  543.  
  544.                     case 0xE5:
  545.                         PREVPC = PC;
  546.                         memory[SP - 1] = H;
  547.                         memory[SP - 2] = L;
  548.                         SP -= 2;
  549.                         PC++;
  550.                         DisplayInfo(opcode, "PUSH H");
  551.                         break;
  552.  
  553.                     case 0xE6:
  554.                         PREVPC = PC;
  555.                         A = (byte)(A & memory[PC + 1]);
  556.                         setFlag(A, 31);
  557.                         PC += 2;
  558.                         DisplayInfo(opcode, "ANI");
  559.                         break;
  560.  
  561.                     case 0xEB:
  562.                         PREVPC = PC;
  563.                         ushort tmp = HL;
  564.                         HL = DE;
  565.                         DE = tmp;
  566.                         PC++;
  567.                         DisplayInfo(opcode, "XCHG");
  568.                         break;
  569.  
  570.                     case 0xF1:
  571.                         PREVPC = PC;
  572.                         A = memory[SP + 1];
  573.                         PSW = memory[SP];
  574.                         Z = (byte)(PSW & 0x01);
  575.                         S = (byte)(PSW & 0x02);
  576.                         P = (byte)(PSW & 0x04);
  577.                         AC = (byte)(PSW & 0x08);
  578.                         CY = (byte)(PSW & 0x10);
  579.                         SP += 2;
  580.                         PC++;
  581.                         DisplayInfo(opcode, "POP PSW");
  582.                         break;
  583.  
  584.                     case 0xF3:
  585.                         PREVPC = PC;
  586.                         canInterupt = false;
  587.                         PC++;
  588.                         DisplayInfo(opcode, "DI");
  589.                         break;
  590.  
  591.                     case 0xF5:
  592.                         PREVPC = PC;
  593.                         memory[SP - 1] = A;
  594.                         PSW = Z | S << 1 | P << 2 | AC << 3 | CY << 4;
  595.                         memory[SP - 2] = (byte)PSW;
  596.                         SP -= 2;
  597.                         PC++;
  598.                         DisplayInfo(opcode, "PUSH PSW");
  599.                         break;
  600.  
  601.                     case 0xFB:
  602.                         PREVPC = PC;
  603.                         canInterupt = true;
  604.                         DisplayInfo(opcode, "EI");
  605.                         PC++;
  606.                         break;
  607.  
  608.                     case 0xFE: // NEEDS CHECKING TOO ***
  609.                         PREVPC = PC;
  610.                         ushort tempCheck = (ushort)(A - memory[PC + 1]);
  611.                         setFlag(tempCheck, 31);
  612.                         PC += 2;
  613.                         DisplayInfo(opcode, "CPI D8");
  614.                         break;
  615.  
  616.                     default:
  617.                         UnimplementedInstruction(opcode);
  618.                         break;
  619.                 }
  620.             }
  621.         }
  622.  
  623.         public void generateInterupt()
  624.         {
  625.             memory[SP - 1] = (byte)((PC >> 8) & 0xff);
  626.             memory[SP - 2] = (byte)(PC & 0xff);
  627.             SP -= 2;
  628.             PC = 0010;
  629.  
  630.         }
  631.  
  632.         private void setFlag(ushort value, byte bitToCheck)
  633.         {
  634.             //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)
  635.             //If I want to check the ZERO flag and the Carry flag, I would send 9(8 for ZERO and 1 for CARRY).
  636.  
  637.             // Z S P A C
  638.  
  639.             // C = 0 > ADD 1   CHECK CARRY
  640.             // A = 1 > ADD 2   CHECK PARITY
  641.             // P = 2 > ADD 4   CHECK AC
  642.             // S = 3 > ADD 8   CHECK ZERO
  643.             // Z = 4 > ADD 16 CHECK SIGN
  644.  
  645.             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.
  646.             {
  647.                 if ((bitToCheck & (1 << i)) != 0)
  648.                 {
  649.                     if (i == 0) // CARRY CHECK (C)
  650.                     {
  651.                         if (value > 0xFF)
  652.                         {
  653.                             CY = 1; // Set the carry if more than 255
  654.                         }
  655.                         else
  656.                         {
  657.                             CY = 0;
  658.                         }
  659.                     }
  660.  
  661.                     if (i == 2) // PARITY CHECK (P)
  662.                     {
  663.  
  664.                     }
  665.  
  666.                     if (i == 3) // SIGN CHECK (S)
  667.                     {
  668.                         if ((value >> 7) == 1)
  669.                         {
  670.                             S = 1;
  671.                         }
  672.                         else
  673.                         {
  674.                             S = 0;
  675.                         }
  676.                     }
  677.  
  678.                     if (i == 4) // ZERO CHECK (Z)                  
  679.                         if (value == 0)
  680.                         {
  681.                             Z = 1;
  682.                         }
  683.                         else
  684.                         {
  685.                             Z = 0;
  686.                         }
  687.                 }
  688.             }
  689.             PSWtemp = C | 1 << 1 | P << 2 | 0 << 3 | AC << 4 | 0 << 5 | Z << 6 | S << 7;
  690.             string binPSW = Convert.ToString(PSWtemp, 2);
  691.             Console.WriteLine("PSW BINARY " + binPSW);
  692.  
  693.         }
  694.  
  695.         private void UnimplementedInstruction(uint opcode)
  696.         {
  697.             //pc will have advanced one, so undo that    
  698.             Debug.WriteLine("\n" + PC.ToString("X4") + " : *ERROR* " + opcode.ToString("X4") + " is an unimplemented instruction.\n");
  699.             isRunning = false;
  700.         }
  701.  
  702.         private void DisplayInfo(uint opcode, string info)
  703.         {
  704.             string newLine = Environment.NewLine;
  705.             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"));
  706.             //OpcodeList.BeginInvoke(new Action(() => { OpcodeList.AppendText(opcode.ToString("X4") + "  " +  info  + newLine); }));
  707.         }
  708.     }
  709.  
  710. }
  711.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement