private void Run()
    {
        Stopwatch sw = Stopwatch.StartNew();

        while (running)
        {
            state = DCPU.step(state);
            tts++;
            ticks++;
            if (state.ticks % 1000 == 0)
            {
                for (int i = 0; i < state.peripherals.Count; i++)
                {
                    state.peripherals[i].updatePeripheral();
                }
            }

            if (sw.ElapsedMilliseconds - lastMilli >= 1000)
            {
                lastElapsed = tts;
                tts         = 0;
                lastMilli   = sw.ElapsedMilliseconds;
            }

            while (sw.ElapsedTicks < ticks * 100)
            {
            }
        }
    }
Beispiel #2
0
 public override void sendInterrupt(dcpuState state)
 {
     switch (state.registers[DCPU.A_REG])
     {
     case 0:
         screen_Reg = state.registers[DCPU.B_REG];
         break;
     }
 }
Beispiel #3
0
    private static ushort ifJumpNum(dcpuState state)
    {
        ushort amount = 1;
        ushort addr = state.memory[state.PC];
        ushort aa = (ushort)((addr >> 10) & 0x3F), bb = (ushort)((addr >> 5) & 0x1F);

        if (needsNextVar(aa))
        {
            amount++;
        }
        if (needsNextVar(bb))
        {
            amount++;
        }
        return(amount);
    }
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && !running)
        {
            StartDCPU();
        }

        if (Input.GetKeyDown(KeyCode.Return) && !running)
        {
            state = DCPU.step(state);

            if (state.ticks % 1000 == 0)
            {
                for (int i = 0; i < state.peripherals.Count; i++)
                {
                    state.peripherals[i].updatePeripheral();
                }
            }
        }
    }
Beispiel #5
0
    public dcpuState copy()
    {
        dcpuState newState = new dcpuState();

        for (int i = 0; i < DCPU.MEM_SIZE; i++)
        {
            newState.memory[i] = memory[i];
        }

        for (int i = 0; i < DCPU.REG_SIZE; i++)
        {
            newState.registers[i] = registers[i];
        }
        newState.PC    = PC;
        newState.EX    = EX;
        newState.SP    = SP;
        newState.IA    = IA;
        newState.ticks = ticks;

        return(newState);
    }
    private void Start()
    {
        state = new dcpuState();

        for (int i = 0; i < peripherals.Count; i++)
        {
            peripherals[i].dcpuController = this;
        }

        state.peripherals = peripherals;
        ushort[] program =   // Simple Hello World LEM1802 Program
        {
            0x1a00, 0x84e1, 0x1e20, 0x7c12, 0xf615, 0x7f81, 0x000d, 0x88e2, 0x1cd2, 0x7f81,
            0x0011, 0x7f81, 0x0002, 0x1fc1, 0x0029, 0x7f81, 0x0007, 0x7cc1, 0x002a, 0x7ce1,
            0x8000, 0x3801, 0x8412, 0x7f81, 0x0020, 0x7c0b, 0x7000, 0x01e1, 0x88c2, 0x88e2,
            0x7f81, 0x0015, 0x7de1, 0x709f, 0x8401, 0x7c21, 0x8000, 0x7a40, 0x0029, 0x7f81,
            0x0027, 0xffff, 0x0048, 0x0045, 0x004c, 0x004c, 0x004f, 0x0020, 0x0057, 0x004f,
            0x0052, 0x004c, 0x0044, 0x0000
        };

        state.loadProgram(program);
    }
Beispiel #7
0
    // takes the current dcpu state
    // moves it one cycle forward
    // and returns a  new state
    public static dcpuState step(dcpuState state)
    {
        aRef  = 0;  bRef = 0;
        aMode = 0; bMode = 0;
        ushort addr = state.memory[state.PC++];
        ushort aa = (ushort)((addr >> 10) & 0x3F), bb = (ushort)((addr >> 5) & 0x1F), op = (ushort)((addr) & 0x1F);
        ushort nxtA = 0, nxtB = 0;

        if (op != 0)
        {
            if (needsNextVar(aa))
            {
                nxtA = state.memory[state.PC++];
                tick(state);
            }
            if (needsNextVar(bb))
            {
                nxtB = state.memory[state.PC++];
                tick(state);
            }
            ushort a = handleVar(state, aa, nxtA, false);
            ushort b = handleVar(state, bb, nxtB, true);
            handleOpCode(state, op, b, a);
        }
        else
        {
            if (needsNextVar(aa))
            {
                nxtA = state.memory[state.PC++];
                tick(state);
            }
            ushort a = handleSpecialVar(state, aa, nxtA);
            handleSpecialOpCode(state, bb, a);
        }
        tick(state);
        return(state);
    }
Beispiel #8
0
 //helper functions for basic op codes
 private static ushort handleVar(dcpuState state, ushort value, ushort nxtVal, bool isB)
 {
     if (value <= 0x07) // register (A, B, C, X, Y, Z, I, J)
     {
         if (isB)
         {
             bMode = (ushort)varMode.REG_MODE;
             bRef  = value;
         }
         return(state.registers[value]);
     }
     else if (value <= 0x0F)  // [register]
     {
         if (isB)
         {
             bMode = (ushort)varMode.MEM_MODE;
             bRef  = state.registers[value % REG_SIZE];
         }
         return(state.memory[state.registers[value % REG_SIZE]]);
     }
     else if (value <= 0x17)  // [register + next word]
     {
         if (isB)
         {
             bMode = (ushort)varMode.MEM_MODE;
             bRef  = (ushort)(state.registers[value % REG_SIZE] + nxtVal);
         }
         return(state.memory[state.registers[value % REG_SIZE] + nxtVal]);
     }
     else if (value == 0x18)  // PUSH/[--SP] POP/[SP++]
     {
         if (isB)
         {
             bMode = (ushort)varMode.MEM_MODE;
             ushort temp = --state.SP;
             bRef = (temp);
             return(state.memory[temp]);
         }
         else
         {
             return(state.memory[state.SP++]);
         }
     }
     else if (value == 0x19)  // [SP] / PEEK
     {
         if (isB)
         {
             bMode = (ushort)varMode.MEM_MODE;
             bRef  = state.SP;
         }
         return(state.memory[state.SP]);
     }
     else if (value == 0x1A)  // [SP + next word] / PICK n
     {
         if (isB)
         {
             bMode = (ushort)varMode.MEM_MODE;
             bRef  = (ushort)(state.SP + nxtVal);
         }
         return(state.memory[state.SP + nxtVal]);
     }
     else if (value == 0x1B)  // SP
     {
         if (isB)
         {
             bMode = (ushort)varMode.SP_MODE;
             bRef  = state.SP;
         }
         return(state.SP);
     }
     else if (value == 0x1C)   // PC
     {
         if (isB)
         {
             bMode = (ushort)varMode.PC_MODE;
             bRef  = state.PC;
         }
         return(state.PC);
     }
     else if (value == 0x1D)  // EX
     {
         if (isB)
         {
             bMode = (ushort)varMode.EX_MODE;
             bRef  = state.EX;
         }
         return(state.EX);
     }
     else if (value == 0x1E)  // [next word]
     {
         if (isB)
         {
             bMode = (ushort)varMode.MEM_MODE;
             bRef  = nxtVal;
         }
         return(state.memory[nxtVal]);
     }
     else if (value == 0x1F)  // next word (lit)
     {
         if (isB)
         {
             bMode = (ushort)varMode.LIT_MODE;
             bRef  = nxtVal;
         }
         return(nxtVal);
     }
     else if (value >= 0x20 && value <= 0x3F)
     {
         if (isB)
         {
             bMode = (ushort)varMode.LIT_MODE;
             bRef  = (ushort)(value - 33);
         }
         return((ushort)(value - 33));
     }
     else
     {
         //this is for if the a or b variable exceeds its bounds
     }
     return(0);
 }
Beispiel #9
0
 //utils
 private static void tick(dcpuState state, int n = 1)
 {
     state.ticks += n;
 }
Beispiel #10
0
 private static ushort handleSpecialVar(dcpuState state, ushort value, ushort nxtVal)
 {
     if (value <= 0x07)  // register (A, B, C, X, Y, Z, I, J)
     {
         aMode = (ushort)varMode.REG_MODE;
         aRef  = value;
         return(state.registers[value]);
     }
     else if (value <= 0x0F)  // [register]
     {
         aMode = (ushort)varMode.MEM_MODE;
         aRef  = state.registers[value % REG_SIZE];
         return(state.memory[state.registers[value % REG_SIZE]]);
     }
     else if (value <= 0x17)  // [register + next word]
     {
         aMode = (ushort)varMode.MEM_MODE;
         aRef  = (ushort)(state.registers[value % REG_SIZE] + nxtVal);
         return(state.memory[state.registers[value % REG_SIZE] + nxtVal]);
     }
     else if (value == 0x18)  // PUSH/[--SP] POP/[SP++]
     {
         aMode = (ushort)varMode.MEM_MODE;
         aRef  = state.SP++;
         return(state.memory[aRef]);
     }
     else if (value == 0x19)  // [SP] / PEEK
     {
         aMode = (ushort)varMode.MEM_MODE;
         aRef  = state.SP;
         return(state.memory[state.SP]);
     }
     else if (value == 0x1A)  // [SP + next word] / PICK n
     {
         aMode = (ushort)varMode.MEM_MODE;
         aRef  = (ushort)(state.SP + nxtVal);
         return(state.memory[state.SP + nxtVal]);
     }
     else if (value == 0x1B)  // SP
     {
         aMode = (ushort)varMode.SP_MODE;
         aRef  = state.SP;
         return(state.SP);
     }
     else if (value == 0x1C)  // PC
     {
         aMode = (ushort)varMode.PC_MODE;
         aRef  = state.PC;
         return(state.PC);
     }
     else if (value == 0x1D)  // EX
     {
         aMode = (ushort)varMode.EX_MODE;
         aRef  = state.EX;
         return(state.EX);
     }
     else if (value == 0x1E)  // [next word]
     {
         aMode = (ushort)varMode.MEM_MODE;
         aRef  = nxtVal;
         return(state.memory[nxtVal]);
     }
     else if (value == 0x1F)  // next word (lit)
     {
         aMode = (ushort)varMode.LIT_MODE;
         aRef  = nxtVal;
         return(nxtVal);
     }
     else if (value >= 0x20 && value <= 0x3F)
     {
         aMode = (ushort)varMode.LIT_MODE;
         aRef  = (ushort)(value - 33);
         return((ushort)(value - 33));
     }
     else
     {
         //this is for if the a or b variable exceeds its boudns
     }
     return(0);
 }
Beispiel #11
0
    //helper functions for advanced op codes
    private static void handleSpecialOpCode(dcpuState state, ushort op, ushort a)
    {
        bool   needsProcessing = false;
        ushort res             = 0;

        switch (op)
        {
        case (ushort)spOpCodes.JSR:
            state.memory[--state.SP] = state.PC;
            state.PC = a;
            tick(state, 3);
            break;

        case (ushort)spOpCodes.INT:
            if (state.IA == 0 || state.canQueue)
            {
                return;
            }

            state.memory[--state.SP] = state.PC;
            state.memory[--state.SP] = state.registers[DCPU.A_REG];
            state.PC = state.IA;
            state.registers[DCPU.A_REG] = a;
            tick(state, 4);
            break;

        case (ushort)spOpCodes.IAG:
            res             = state.IA;
            needsProcessing = true;
            tick(state);
            break;

        case (ushort)spOpCodes.IAS:
            state.IA = a;
            tick(state);
            break;

        case (ushort)spOpCodes.RFI:
            state.registers[DCPU.A_REG] = state.memory[state.SP++];
            state.PC = state.memory[state.SP++];
            tick(state, 3);
            break;

        case (ushort)spOpCodes.IAQ:
            if (a == 0)
            {
                state.canQueue = false;
            }
            else
            {
                state.canQueue = true;
            }
            break;

        case (ushort)spOpCodes.HWN:
            res = (ushort)state.peripherals.Count;
            tick(state, 2);
            needsProcessing = true;
            break;

        case (ushort)spOpCodes.HWQ:
            if (a < state.peripherals.Count)
            {
                //id
                state.registers[DCPU.A_REG] = (ushort)(state.peripherals[a].id & 0xFFFF);
                state.registers[DCPU.B_REG] = (ushort)((state.peripherals[a].id >> 16) & 0xFFFF);
                //version
                state.registers[DCPU.C_REG] = (ushort)(state.peripherals[a].version);
                //manufacturer
                state.registers[DCPU.X_REG] = (ushort)(state.peripherals[a].manufacturer & 0xFFFF);
                state.registers[DCPU.Y_REG] = (ushort)((state.peripherals[a].manufacturer >> 16) & 0xFFFF);
            }
            tick(state, 4);
            break;

        case (ushort)spOpCodes.HWI:
            if (a < state.peripherals.Count)
            {
                state.peripherals[a].sendInterrupt(state);
            }
            tick(state, 4);
            break;
        }
        if (needsProcessing)
        {
            if (aMode == (ushort)varMode.MEM_MODE)
            {
                state.memory[aRef] = res;
            }
            else if (aMode == (ushort)varMode.REG_MODE)
            {
                state.registers[aRef] = res;
            }
            else if (aMode == (ushort)varMode.PC_MODE)
            {
                state.PC = res;
            }
            else if (aMode == (ushort)varMode.SP_MODE)
            {
                state.SP = res;
            }
            else if (aMode == (ushort)varMode.EX_MODE)
            {
                state.EX = res;
            }
            else
            {
            }
        }
    }
Beispiel #12
0
    private static void handleOpCode(dcpuState state, ushort op, ushort b, ushort a)
    {
        ushort res             = 0;    // temp container for result
        bool   needsProcessing = true; // this will only be true if data needs to be stored back to the dcpu
        ushort amt             = 0;    //used for calculating the skip length of the dcpu's if statements

        switch (op)
        {
        case (ushort)opCodes.SET:     //sets b to a
            res = a;
            tick(state);
            break;

        case (ushort)opCodes.ADD:     //add b and a together and stores it in b
            res = (ushort)(b + a);
            if ((b + a) > 0xFFFF)
            {
                state.EX = (ushort)((b + a) % 0xFFFF);
            }
            tick(state, 2);
            break;

        case (ushort)opCodes.SUB:     //subtracts b from a
            res = (ushort)(b - a);
            if ((b - a) < 0)
            {
                state.EX = 0xFFFF;
            }
            tick(state, 2);
            break;

        case (ushort)opCodes.MUL:     // multiply b and a unsgined
            res      = (ushort)(b * a);
            state.EX = (ushort)(((b * a) >> 16) & 0xFFFF);
            tick(state, 2);
            break;

        case (ushort)opCodes.MLI:     // multiply b and a signed
            res      = (ushort)((short)b * (short)a);
            state.EX = (ushort)((((short)b * (short)a) >> 16) & 0xFFFF);
            break;

        case (ushort)opCodes.DIV:     // divide b by a signed
            if (a == 0)
            {
                state.EX = 0;
            }
            else
            {
                res = (ushort)(b / a); state.EX = (ushort)(((b << 16) / a) & 0xFFFF);
            }
            tick(state, 3);
            break;

        case (ushort)opCodes.DVI:     // divide b by a unsigned
            if (a == 0)
            {
                state.EX = 0;
            }
            else
            {
                res = (ushort)((short)b / (short)a); state.EX = (ushort)((((short)b << 16) / (short)a) & 0xFFFF);
            }
            tick(state, 3);
            break;

        case (ushort)opCodes.MOD:     // gets the modulus of b using a signed
            if (a == 0)
            {
                res = b;
            }
            else
            {
                res = (ushort)(b % a);
            }
            tick(state, 3);
            break;

        case (ushort)opCodes.MDI:     // gets the modulus of b using a unsigned
            if (a == 0)
            {
                res = b;
            }
            else
            {
                res = (ushort)((short)b % (short)a);
            }
            tick(state, 3);
            break;

        case (ushort)opCodes.AND:     // and b and a together
            res = (ushort)(b & a);
            tick(state);
            break;

        case (ushort)opCodes.BOR:     // its or's a and b together
            res = (ushort)(b | a);
            tick(state);
            break;

        case (ushort)opCodes.XOR:     // exclusively or's a and b
            res = (ushort)(b ^ a);
            tick(state);
            break;

        case (ushort)opCodes.SHR:     // does a logical right shift
            res      = (ushort)(b >> a);
            state.EX = (ushort)(((b << 16) >> a) & 0xFFFF);
            tick(state);
            break;

        case (ushort)opCodes.ASR:     // does a arithmatic right shift
            res      = (ushort)((short)b >> (short)a);
            state.EX = (ushort)((((short)b << 16) >> (short)a) & 0xFFFF);
            tick(state);
            break;

        case (ushort)opCodes.SHL:     // shifts to the left
            res      = (ushort)(b << a);
            state.EX = (ushort)(((b << a) >> 16) & 0xFFFF);
            tick(state);
            break;

        case (ushort)opCodes.IFB:     // processes the next instruction if binary and'ing dosen't equal
            amt = ifJumpNum(state);
            if ((b & a) == 0)
            {
                state.PC += amt; tick(state, amt);
            }
            tick(state, 2);
            needsProcessing = false;
            break;

        case (ushort)opCodes.IFC:    // processes the next instruction if binary and'ing equal 0
            amt = ifJumpNum(state);
            if ((b & a) != 0)
            {
                state.PC += amt; tick(state, amt);
            }
            tick(state, 2);
            needsProcessing = false;
            break;

        case (ushort)opCodes.IFE:    // processes the next instruction if a and b are equal
            amt = ifJumpNum(state);
            if (b != a)
            {
                state.PC += amt; tick(state, amt);
            }
            tick(state, 2);
            needsProcessing = false;
            break;

        case (ushort)opCodes.IFN:     // processes the next instruction if a and b are not equal
            amt = ifJumpNum(state);
            if (b == a)
            {
                state.PC += amt; tick(state, amt);
            }
            tick(state, 2);
            needsProcessing = false;
            break;

        case (ushort)opCodes.IFG:     // processes the next instruction if b is greater than a (unsigned)
            amt = ifJumpNum(state);
            if (b < a)
            {
                state.PC += amt; tick(state, amt);
            }
            tick(state, 2);
            needsProcessing = false;
            break;

        case (ushort)opCodes.IFA:     // processes the next instruction if b is greate than a (signed)
            amt = ifJumpNum(state);
            if ((short)b < (short)a)
            {
                state.PC += amt; tick(state, amt);
            }
            tick(state, 2);
            needsProcessing = false;
            break;

        case (ushort)opCodes.IFL:     // processes the next instruction if b is less than a (unsigned)
            amt = ifJumpNum(state);
            if (b > a)
            {
                state.PC += amt; tick(state, amt);
            }
            tick(state, 2);
            needsProcessing = false;
            break;

        case (ushort)opCodes.IFU:     // processes the next instruction if b is less than a (signed)
            amt = ifJumpNum(state);
            if ((short)b > (short)a)
            {
                state.PC += amt; tick(state, amt);
            }
            tick(state, 2);
            needsProcessing = false;
            break;

        case (ushort)opCodes.ADX:     // sets b to b + a + EX and set EX to 0x0001 if there is an overflow otherwise EX = 0
            res = (ushort)(b + a + state.EX);
            if ((int)(b + a + state.EX) > 0xffff)
            {
                state.EX = 1;
            }
            else
            {
                state.EX = 0;
            }
            break;

        case (ushort)opCodes.SBX:     // sets b to b - a + EX and set EX to 0xFFFF if there is an overflow otherwise EX = 0
            res = (ushort)(b - a + state.EX);
            if ((b - a + state.EX) < 0x0)
            {
                state.EX = 0xFFFF;
            }
            else
            {
                state.EX = 0;
            }
            break;

        case (ushort)opCodes.STI:     //sets a to b and adds one to the I and J reigsters
            res = a;
            ++state.registers[I_REG];
            ++state.registers[J_REG];
            break;

        case (ushort)opCodes.STD:     //sets a to b and subtracts one from the I and J reigsters
            res = a;
            --state.registers[I_REG];
            --state.registers[J_REG];
            break;
        }
        if (needsProcessing)
        {
            if (bMode == (ushort)varMode.MEM_MODE)
            {
                state.memory[bRef] = res;
            }
            else if (bMode == (ushort)varMode.REG_MODE)
            {
                state.registers[bRef] = res;
            }
            else if (bMode == (ushort)varMode.PC_MODE)
            {
                state.PC = res;
            }
            else if (bMode == (ushort)varMode.SP_MODE)
            {
                state.SP = res;
            }
            else if (bMode == (ushort)varMode.EX_MODE)
            {
                state.EX = res;
            }
            else
            {
            }
        }
    }
Beispiel #13
0
 public abstract void sendInterrupt(dcpuState state);