├── Cosmos.System2.Emulation ├── Core │ ├── Executable.cs │ ├── Instruction.cs │ ├── VirtualCPU.cs │ └── VirtualMemory.cs ├── Threading │ ├── TaskManager.cs │ └── Thread.cs ├── Types.cs └── instruction sets │ ├── CHIP8Instruction.cs │ ├── FGMSEInstruction.cs │ └── InstructionSet.cs ├── License.md ├── MSE.Package.csproj ├── obj └── Debug │ └── com.Nik300.ManagedSoftwareExecution.1.0.0.nuspec └── readme.md /Cosmos.System2.Emulation/Core/Executable.cs: -------------------------------------------------------------------------------- 1 | using Sys = System; 2 | using System; 3 | using System.IO; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | namespace Cosmos.System.Emulation 9 | { 10 | public class Executable 11 | { 12 | public string FileName { get; private set; } 13 | public byte Type = 0; // 01 = 8-bit, 02 = 16-bit, 03 = 32-bit 14 | private byte InstructionSet; // 00 - Chip8, 01 - yours, 02 mine, 03 our combined 15 | public byte[] Data { get; private set; } 16 | public byte[] op8 { get; private set; } 17 | public short[] op16 { get; private set; } 18 | public int[] op32 { get; private set; } 19 | public VirtualMemory Memory { get; private set; } 20 | public InstructionSet usingInstructionSet; 21 | 22 | public bool running = true; 23 | 24 | public bool lastInstruction = true; 25 | 26 | public delegate void SystemCall(Executable caller); 27 | private protected List SystemCalls = new List(); 28 | 29 | public List Returns = new List(); 30 | 31 | public Executable(string file, InstructionSet instructionSet = null, byte type = 0) 32 | { 33 | FileName = file; 34 | Data = null; 35 | Type = type; 36 | usingInstructionSet = instructionSet; 37 | } 38 | public Executable(byte[] data, InstructionSet instructionSet = null, byte type = 0) 39 | { 40 | FileName = null; 41 | Data = data; 42 | Type = type; 43 | usingInstructionSet = instructionSet; 44 | } 45 | 46 | public void NextInstruction() 47 | { 48 | try 49 | { 50 | if (!running) return; 51 | if (Type == 1) 52 | { 53 | Instruction instr8 = usingInstructionSet.GetInstruction(op8); 54 | instr8.Delegate(this); 55 | } 56 | else if (Type == 2) 57 | { 58 | Instruction instr16 = usingInstructionSet.GetInstruction(op16); 59 | instr16.Delegate(this); 60 | } 61 | else if (Type == 3) 62 | { 63 | Instruction instr32 = usingInstructionSet.GetInstruction(op32); 64 | instr32.Delegate(this); 65 | } 66 | } 67 | catch(Sys.Exception ex) 68 | { 69 | Sys.Console.WriteLine($"Error while executing program instructions:\n{ex.Message}"); 70 | Sys.Console.WriteLine("Dumping memory..."); 71 | string file = $@"0:\System\bin\dump_{DateTime.Now.Day}{DateTime.Now.Month}_{DateTime.Now.Hour}{DateTime.Now.Minute}_{DateTime.Now.Second}.dat"; 72 | File.Create(file).Close(); 73 | List Bytes = new List(); 74 | for (int i = 0; i < Memory.Data.Count; i++) 75 | { 76 | byte[] number = BitConverter.GetBytes(Memory.Data[i]); 77 | for (int x = 0; x < 4; x++) 78 | { 79 | Bytes.Add(number[x]); 80 | } 81 | } 82 | File.WriteAllBytes(file, Bytes.ToArray()); 83 | Sys.Console.WriteLine($"Dump complete!\nProgram memory dumped at: {file}"); 84 | running = false; 85 | } 86 | } 87 | 88 | public int AddSystemCall(SystemCall systemCall) 89 | { 90 | SystemCalls.Add(systemCall); 91 | return SystemCalls.Count - 1; 92 | } 93 | public bool RunSystemCall(int syscall) 94 | { 95 | if (syscall >= SystemCalls.Count) 96 | return false; 97 | 98 | SystemCalls[syscall](this); 99 | 100 | return true; 101 | } 102 | 103 | public void ReadData() 104 | { 105 | try 106 | { 107 | 108 | if (FileName != null && Data == null) 109 | { 110 | if (!File.Exists(FileName)) 111 | { 112 | throw new FileNotFoundException(); 113 | } 114 | Data = File.ReadAllBytes(FileName); 115 | } 116 | 117 | if (Type == 0) 118 | Type = Data[0]; 119 | InstructionSet = Data[1]; 120 | List tempRam = new List(); 121 | 122 | int i; 123 | 124 | for (i = 2; i < Data.Length; i += 4) 125 | { 126 | List temp = new List(); 127 | if (Data[i] == 0xFF && Data[i + 1] == 0xFA && Data[i + 2] == 0xFF && Data[i + 3] == 0xFA && Data[i + 4] == 0xFB) 128 | { 129 | i += 5; 130 | break; 131 | } 132 | for (int c = 0; c < 4; c++) 133 | temp.Add(Data[i + c]); 134 | int d = BitConverter.ToInt32(temp.ToArray(), 0); 135 | tempRam.Add(d); 136 | } 137 | 138 | if (Type != 1 && Type != 2 && Type != 3) 139 | throw new NotImplementedException(); 140 | 141 | List tempOP = new List(); 142 | 143 | for (; i < Data.Length; i++) 144 | { 145 | tempOP.Add(Data[i]); 146 | } 147 | if (Type == 1) 148 | { 149 | op8 = tempOP.ToArray(); 150 | } 151 | else if (Type == 2) 152 | { 153 | List temp16OP = new List(); 154 | for (i = 0; i < tempOP.Count; i++) 155 | { 156 | List toAdd = new List(); 157 | for (int c = 0; c < 2; c++) 158 | toAdd.Add(tempOP[c + i]); 159 | temp16OP.Add(BitConverter.ToInt16(toAdd.ToArray(), 0)); 160 | } 161 | op16 = temp16OP.ToArray(); 162 | } 163 | else if (Type == 3) 164 | { 165 | List temp32OP = new List(); 166 | for (i = 0; i < tempOP.Count; i += 4) 167 | { 168 | List toAdd = new List(); 169 | for (int c = 0; c < 4; c++) 170 | toAdd.Add(tempOP[c + i]); 171 | toAdd.Reverse(); 172 | temp32OP.Add(BitConverter.ToInt32(toAdd.ToArray(), 0)); 173 | } 174 | op32 = temp32OP.ToArray(); 175 | } 176 | 177 | Data = null; 178 | 179 | Memory = new VirtualMemory(); 180 | Memory.AddArray(tempRam); 181 | if (usingInstructionSet == null) 182 | { 183 | usingInstructionSet = Types.Sets[InstructionSet]; 184 | } 185 | } 186 | catch (Exception ex) 187 | { 188 | Sys.Console.WriteLine($"Error reading executable data: {ex.Message}"); 189 | } 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /Cosmos.System2.Emulation/Core/Instruction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Cosmos.System.Emulation 8 | { 9 | public abstract class InstructionSet 10 | { 11 | public static Dictionary instructions = new Dictionary(); 12 | public string name; 13 | public InstructionSet(byte identifier, string name) 14 | { 15 | this.name = name; 16 | } 17 | internal void AddInstruction(Instruction instr) 18 | { 19 | instructions.Add((uint)instr.OpCode, instr); 20 | } 21 | public abstract Instruction GetInstruction(int[] rawCode); 22 | public abstract Instruction GetInstruction(short[] rawCode); 23 | public abstract Instruction GetInstruction(byte[] rawCode); 24 | } 25 | public abstract class Instruction 26 | { 27 | public string Mnemonic; 28 | public string Format; 29 | public int OpCode; 30 | //man, so I found a much more efficient way to handle arguments 31 | //first thing first every instruction will have built-in their instructions 32 | //then they'll be set by the instructionset when returning the instruction 33 | //then the executable class calss the delegate acording to the executable's architecture 34 | //and the play is done 35 | public List args32 = null; 36 | public List args16 = null; 37 | public List arg8 = null; 38 | //at this point we won't even need the difference between the delegates 39 | //because each instruction will take the arguments it needs 40 | //and if the arguments array it needs is null, it just stops the execution 41 | //and throws one of those weird errors that windows sometimes throws when freaking out XD 42 | //example: "memory at 0x102091 cannot be 'read' by program 0x986241. quitting..." 43 | public delegate void InstructionDelegate(Executable caller); 44 | public InstructionDelegate Delegate; 45 | 46 | public Instruction(string mnem = "NOP", int op = 0x00, string format = "") 47 | { 48 | this.Mnemonic = mnem; 49 | this.OpCode = op; 50 | this.Format = format; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Cosmos.System2.Emulation/Core/VirtualCPU.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | namespace Cosmos.System.Emulation 7 | { 8 | public abstract class VirtualCPU 9 | { 10 | public VirtualMemory Cache; 11 | public byte arch; 12 | public bool isCacheInit; 13 | public VirtualCPU(byte arch, bool initCache = false, int CacheSize = 0) 14 | { 15 | this.arch = arch; 16 | isCacheInit = initCache; 17 | if (isCacheInit && CacheSize > 0) 18 | Cache = new VirtualMemory(); 19 | else 20 | isCacheInit = false; 21 | return; 22 | } 23 | } 24 | public abstract class VirtualCPU32: VirtualCPU 25 | { 26 | public abstract uint GetRegData(byte regAddress); 27 | public abstract bool SetRegData(byte regAddress, uint Data); 28 | public abstract bool ClearRegData(byte regAddress); 29 | public abstract void LoadRegisters(); 30 | public VirtualCPU32(bool initCache = false, int CacheSize = 0) 31 | : base(3, initCache, CacheSize) 32 | { 33 | } 34 | } 35 | public abstract class VirtualCPU16: VirtualCPU 36 | { 37 | public abstract ushort GetRegData(byte regAddress); 38 | public abstract bool SetRegData(byte regAddress, ushort Data); 39 | public abstract bool ClearRegData(byte regAddress); 40 | public VirtualCPU16(bool initCache = false, int CacheSize = 0) 41 | : base(2, initCache, CacheSize) 42 | { 43 | } 44 | } 45 | public abstract class VirtualCPU8: VirtualCPU 46 | { 47 | public abstract byte GetRegData(byte regAddress); 48 | public abstract bool SetRegData(byte regAddress, byte Data); 49 | public abstract bool ClearRegData(byte regAddress); 50 | public VirtualCPU8(bool initCache = false, int CacheSize = 0) 51 | : base(1, initCache, CacheSize) 52 | { 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Cosmos.System2.Emulation/Core/VirtualMemory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Cosmos.System.Emulation 8 | { 9 | public class Stack 10 | { 11 | public List Data { get; private set; } 12 | public Stack() 13 | { 14 | Data = new List(); 15 | } 16 | 17 | /// 18 | /// Push one single element to the stack 19 | /// 20 | /// 21 | /// 22 | public void Push(T element) 23 | { 24 | Data.Add(element); 25 | } 26 | 27 | /// 28 | /// Gather the last element in the stack 29 | /// 30 | /// 31 | public bool Try_Pop(ref T val) 32 | { 33 | if (Data.Count == 0) return false; 34 | val = Data[Data.Count - 1]; 35 | List dat = new List(); 36 | if (Data.Count - 1 != -1) 37 | for (int i = 0; i < Data.Count - 1; i++) 38 | dat.Add(Data[i]); 39 | 40 | Data = dat; 41 | 42 | dat = null; 43 | 44 | return true; 45 | } 46 | 47 | /// 48 | /// Clears entire stack 49 | /// 50 | public void Clear() { Data.Clear(); } 51 | } 52 | public class VirtualMemory 53 | { 54 | //public static readonly int Size; 55 | public List Data { get; private set; } 56 | public Stack Stack { get; private set; } 57 | 58 | public VirtualMemory() 59 | { 60 | Data = new List(); 61 | Stack = new Stack(); 62 | } 63 | 64 | /// 65 | /// Clears entire memory 66 | /// 67 | public void Clear() { Data.Clear(); } 68 | 69 | /// 70 | /// Add single value to ram 71 | /// 72 | /// 73 | /// 74 | public bool AddInt(int data = 0) 75 | { 76 | Data.Add(data); 77 | return true; 78 | } 79 | 80 | /// 81 | /// Add single 8-bit value to ram 82 | /// 83 | /// 84 | /// 85 | public bool AddChar(byte data = 0) 86 | { 87 | List toAdd = new List(); 88 | 89 | toAdd.Add(data); 90 | toAdd.Add(0x00); 91 | toAdd.Add(0x00); 92 | toAdd.Add(0x00); 93 | 94 | Data.Add(BitConverter.ToInt32(toAdd.ToArray(), 0)); 95 | return true; 96 | } 97 | 98 | /// 99 | /// Add single 8-bit value to ram 100 | /// 101 | /// 102 | /// 103 | public bool AddChar(char data = '\0') 104 | { 105 | List toAdd = new List(); 106 | 107 | toAdd.Add((byte)data); 108 | toAdd.Add(0x00); 109 | toAdd.Add(0x00); 110 | toAdd.Add(0x00); 111 | 112 | Data.Add(BitConverter.ToInt32(toAdd.ToArray(), 0)); 113 | return true; 114 | } 115 | 116 | /// 117 | /// Add array to memory 118 | /// 119 | /// 120 | /// 121 | public bool AddArray(List dataArray) 122 | { 123 | foreach (int b in dataArray) 124 | { 125 | Data.Add(b); 126 | } 127 | return true; 128 | } 129 | 130 | /// 131 | /// Add specified amount of integers to memory 132 | /// 133 | /// 134 | /// 135 | public bool AddAmount(int amount) 136 | { 137 | for (int i = 0; i < amount; i++) 138 | { 139 | Data.Add(0x00); 140 | } 141 | return true; 142 | } 143 | 144 | /// 145 | /// Read single 8-bit value from memory 146 | /// 147 | /// 148 | /// 149 | public byte ReadChar(int addr) 150 | { 151 | List data = new List(); 152 | foreach (byte c in BitConverter.GetBytes(Data[addr])) 153 | { 154 | data.Add(c); 155 | } 156 | return data[0]; 157 | } 158 | 159 | public short ReadShort(int addr) 160 | { 161 | List data = new List(); 162 | foreach (byte b in BitConverter.GetBytes(Data[addr])) 163 | { 164 | data.Add(b); 165 | } 166 | return (short)((data[0] << 8) | data[1]); 167 | } 168 | 169 | /// 170 | /// Read single value from memory 171 | /// 172 | /// 173 | /// 174 | public int ReadInt32(int addr) 175 | { 176 | List bdata = new List(); 177 | foreach(byte b in BitConverter.GetBytes(Data[addr])) 178 | { 179 | bdata.Add(b); 180 | } 181 | bdata.Reverse(); 182 | int data = BitConverter.ToInt32(bdata.ToArray(), 0); 183 | return data; 184 | } 185 | 186 | /// 187 | /// Read a range of bytes from memory 188 | /// 189 | /// 190 | /// 191 | public List ReadRange(int addr, int len) 192 | { 193 | List output = new List(); 194 | for (int i = 0; i < len; i++) { output.Add(Data[addr + i]); } 195 | return output; 196 | } 197 | 198 | /// 199 | /// Insert a single value into a location in memory 200 | /// 201 | /// 202 | /// 203 | public bool InsertInt32(int addr, int data) 204 | { 205 | if (addr > Data.Count) { return false; } 206 | Data.Insert(addr, data); 207 | return true; 208 | } 209 | 210 | /// 211 | /// Write a single value into a location in memory 212 | /// 213 | /// 214 | /// 215 | public bool WriteInt32(int addr, int data) 216 | { 217 | List dat = new List(); 218 | foreach (byte b in BitConverter.GetBytes(data)) 219 | { 220 | dat.Add(b); 221 | } 222 | dat.Reverse(); 223 | data = BitConverter.ToInt32(dat.ToArray(), 0); 224 | Data[addr] = data; 225 | return true; 226 | } 227 | 228 | /// 229 | /// Write a range of data into memory 230 | /// 231 | /// 232 | /// 233 | public bool WriteRange(int addr, int length, List data) 234 | { 235 | for (int i = 0; i < length; i++) 236 | { 237 | WriteInt32(addr + i, data[i]); 238 | } 239 | return true; 240 | } 241 | 242 | /// 243 | /// Write character value to memory 244 | /// 245 | /// 246 | /// 247 | public bool WriteChar(int addr, char c) 248 | { 249 | Data[addr] = (byte)c; 250 | return true; 251 | } 252 | 253 | /// 254 | /// Write string(character array) to memory 255 | /// 256 | /// 257 | /// 258 | public bool WriteString(int addr, string txt) 259 | { 260 | for (int i = 0; i < txt.Length; i++) 261 | { 262 | Data[addr + i] = txt[i]; 263 | } 264 | return true; 265 | } 266 | /// 267 | /// Clears The specified address in memory 268 | /// 269 | /// 270 | /// 271 | public bool ClearInt32(int addr) 272 | { 273 | Data[addr] = 0; 274 | return true; 275 | } 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /Cosmos.System2.Emulation/Threading/TaskManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Cosmos.System.Emulation.Threading 6 | { 7 | public class TaskManager 8 | { 9 | public static List LoadedThreads { get; private set; } = new List(); 10 | internal static void Start(Thread thread) 11 | { 12 | LoadedThreads.Add(thread); 13 | } 14 | public static void Next() 15 | { 16 | foreach (Thread thread in LoadedThreads) 17 | { 18 | DateTime startTime = DateTime.Now; 19 | DateTime lastTime = startTime; 20 | while (lastTime.Second < startTime.Second + 1) 21 | { 22 | thread.exec.NextInstruction(); 23 | lastTime = DateTime.Now; 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Cosmos.System2.Emulation/Threading/Thread.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Cosmos.System.Emulation.Threading 6 | { 7 | public class Thread 8 | { 9 | internal readonly Executable exec; 10 | public Thread(Executable exec) 11 | { 12 | this.exec = exec; 13 | } 14 | public Thread(byte[] exec) 15 | { 16 | this.exec = new Executable(exec); 17 | } 18 | 19 | public void Start() 20 | { 21 | //exec.ReadData(); 22 | TaskManager.Start(this); 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Cosmos.System2.Emulation/Types.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Cosmos.System.Emulation 8 | { 9 | public static class Types 10 | { 11 | public static Dictionary Sets = new Dictionary(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Cosmos.System2.Emulation/instruction sets/CHIP8Instruction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Cosmos.System.Emulation 8 | { 9 | public class CHIP8Instruction : Instruction 10 | { 11 | public CHIP8Instruction(string mnem, short op, string format) : base(mnem, op, format) 12 | { 13 | 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Cosmos.System2.Emulation/instruction sets/FGMSEInstruction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Cosmos.System.Emulation 8 | { 9 | public class FGMSEInstruction: Instruction 10 | { 11 | public FGMSEInstruction(string mnem = "NOP", int op = 0, string format = "", InstructionDelegate Delegate = null): base(mnem, op, format) 12 | { 13 | if (Delegate == null) 14 | { 15 | this.Delegate = new InstructionDelegate((Executable caller) => { }); 16 | } 17 | else 18 | this.Delegate = Delegate; 19 | } 20 | private static int GetPointerAddress(List args, FGMSECInstructionSet instrSet, Executable caller, out int shift) 21 | { 22 | int addr = 0; 23 | shift = 1; 24 | if (isRegister(args[0])) 25 | { 26 | addr = (int)instrSet.CPU.GetRegData(BitConverter.GetBytes(args[1])[3]); 27 | } 28 | else if (isData(args[0])) 29 | { 30 | addr = (int)args[1]; 31 | } 32 | else if (isPointer(args[0])) 33 | { 34 | List _args = new List(); 35 | for (int i = 1; i < args.Count; i++) 36 | _args.Add(args[i]); 37 | addr = caller.Memory.ReadInt32(GetPointerAddress(_args, instrSet, caller, out int addShift)); 38 | shift += addShift; 39 | } 40 | else 41 | { 42 | global::System.Console.WriteLine($"No way to set address found ({args[0]})"); 43 | addr = 0; 44 | instrSet.CPU.SetRegData((byte)FGMSECpu.FGMSERegisters.C1, 0xFF00FFA1); 45 | } 46 | return addr; 47 | } 48 | private static uint returnValue(List args, FGMSECInstructionSet instrSet, Executable caller, out int shift, bool ClearValue = false) 49 | { 50 | uint data = 0x00; 51 | shift = 0; 52 | if (isRegister(args[0])) 53 | { 54 | data = instrSet.CPU.GetRegData(BitConverter.GetBytes(args[1])[3]); 55 | if (ClearValue) 56 | instrSet.CPU.ClearRegData(BitConverter.GetBytes(args[1])[3]); 57 | } 58 | else if (isData(args[0])) 59 | { 60 | data = args[1]; 61 | } 62 | else if (isPointer(args[0])) 63 | { 64 | List _args = new List(); 65 | for (int i = 1; i < args.Count; i++) 66 | _args.Add(args[i]); 67 | int addr = GetPointerAddress(_args, instrSet, caller, out shift); 68 | data = (uint)caller.Memory.ReadInt32(addr); 69 | if (ClearValue) 70 | caller.Memory.WriteInt32(addr, 0x00); 71 | } 72 | else 73 | { 74 | throw new Exception("Cannot retrive value of one or more elements"); 75 | } 76 | return data; 77 | } 78 | private static uint returnValueFromAddress(List args, FGMSECInstructionSet instrSet, Executable caller, out int shift) 79 | { 80 | uint data = 0x00; 81 | shift = 0; 82 | if (isRegister(args[0])) 83 | { 84 | data = instrSet.CPU.GetRegData(BitConverter.GetBytes(args[1])[3]); 85 | } 86 | else if (isPointer(args[0])) 87 | { 88 | List _args = new List(); 89 | for (int i = 1; i < args.Count; i++) 90 | _args.Add(args[i]); 91 | int addr = GetPointerAddress(_args, instrSet, caller, out shift); 92 | data = (uint)caller.Memory.ReadInt32(addr); 93 | } 94 | else 95 | { 96 | throw new Exception("Cannot retrive value of one or more elements"); 97 | } 98 | return data; 99 | } 100 | 101 | //0xFE001AFA = register 102 | //0xFE001AFB = data 103 | //0xFE001AFC = pointer 104 | private static bool isRegister(uint preset) 105 | { 106 | preset -= 0xFE000000; 107 | return preset == 0x1AFA; 108 | } 109 | private static bool isData(uint preset) 110 | { 111 | preset -= 0xFE000000; 112 | return preset == 0x1AFB; 113 | } 114 | private static bool isPointer(uint preset) 115 | { 116 | preset -= 0xFE000000; 117 | return preset == 0x1AFC; 118 | } 119 | 120 | //Instructions delegates 121 | 122 | //math delegates 123 | public void MOV(Executable caller) // moves element to another position - len: 4 124 | { 125 | uint data; 126 | var instrSet = ((FGMSECInstructionSet)caller.usingInstructionSet); 127 | data = returnValue(args32, instrSet, caller, out int shift, true); 128 | if (isRegister(args32[2 + shift])) 129 | { 130 | instrSet.CPU.SetRegData(BitConverter.GetBytes(args32[3 + shift])[3], data); 131 | } 132 | else if (isPointer(args32[2 + shift])) 133 | { 134 | List _args = new List(); 135 | for (int i = 3 + shift; i < args32.Count; i++) 136 | _args.Add(args32[i]); 137 | int addr = GetPointerAddress(_args, instrSet, caller, out _); 138 | caller.Memory.WriteInt32(addr, (int)data); 139 | } 140 | } 141 | public void SET(Executable caller) // sets data to determined position - len: 4 142 | { 143 | uint data; 144 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 145 | List args = new List(); 146 | args.Add(args32[0]); 147 | args.Add(args32[1]); 148 | data = returnValue(args32, instrSet, caller, out int shift); 149 | if (isRegister(args32[2 + shift])) 150 | { 151 | instrSet.CPU.SetRegData(BitConverter.GetBytes(args32[3 + shift])[3], data); 152 | } 153 | else if (isPointer(args32[2 + shift])) 154 | { 155 | List _args = new List(); 156 | for (int i = 3 + shift; i < args32.Count; i++) 157 | _args.Add(args32[i]); 158 | caller.Memory.WriteInt32(GetPointerAddress(_args, instrSet, caller, out _), (int)data); 159 | } 160 | } 161 | public void ADD(Executable caller) // adds data to determined position - len: 4 162 | { 163 | uint data; 164 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 165 | List args = new List(); 166 | args.Add(args32[0]); 167 | args.Add(args32[1]); 168 | data = returnValue(args32, instrSet, caller, out int shift); 169 | if (isRegister(args32[2 + shift])) 170 | { 171 | byte reg = BitConverter.GetBytes(args32[3 + shift])[3]; 172 | instrSet.CPU.SetRegData(reg, (uint)(instrSet.CPU.GetRegData(reg) + data)); 173 | } 174 | else if (isPointer(args32[2 + shift])) 175 | { 176 | List _args = new List(); 177 | for (int i = 3 + shift; i < args32.Count; i++) 178 | _args.Add(args32[i]); 179 | caller.Memory.WriteInt32(GetPointerAddress(_args, instrSet, caller, out _), (int)(caller.Memory.ReadInt32((int)args32[3]) + data)); 180 | } 181 | } 182 | public void SUB(Executable caller) // subtracts data from determined position - len: 4 183 | { 184 | uint data; 185 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 186 | List args = new List(); 187 | args.Add(args32[0]); 188 | args.Add(args32[1]); 189 | data = returnValue(args32, instrSet, caller, out int shift); 190 | if (isRegister(args32[2 + shift])) 191 | { 192 | byte reg = BitConverter.GetBytes(args32[3 + shift])[3]; 193 | instrSet.CPU.SetRegData(reg, (uint)(instrSet.CPU.GetRegData(reg) - data)); 194 | } 195 | else if (isPointer(args32[2 + shift])) 196 | { 197 | List _args = new List(); 198 | for (int i = 3 + shift; i < args32.Count; i++) 199 | _args.Add(args32[i]); 200 | caller.Memory.WriteInt32(GetPointerAddress(_args, instrSet, caller, out _), (int)(caller.Memory.ReadInt32((int)args32[3]) - data)); 201 | } 202 | } 203 | public void DIV(Executable caller) // devides data from determined position - len: 4 204 | { 205 | uint data; 206 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 207 | List args = new List(); 208 | args.Add(args32[0]); 209 | args.Add(args32[1]); 210 | data = returnValue(args32, instrSet, caller, out int shift); 211 | if (isRegister(args32[2 + shift])) 212 | { 213 | byte reg = BitConverter.GetBytes(args32[3 + shift])[3]; 214 | instrSet.CPU.SetRegData(reg, (uint)(instrSet.CPU.GetRegData(reg) / data)); 215 | } 216 | else if (isPointer(args32[2 + shift])) 217 | { 218 | List _args = new List(); 219 | for (int i = 3 + shift; i < args32.Count; i++) 220 | _args.Add(args32[i]); 221 | caller.Memory.WriteInt32(GetPointerAddress(_args, instrSet, caller, out _), (int)(caller.Memory.ReadInt32((int)args32[3]) / data)); 222 | } 223 | } 224 | public void MUL(Executable caller) // multiplies data to determined position - len: 4 225 | { 226 | uint data; 227 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 228 | List args = new List(); 229 | args.Add(args32[0]); 230 | args.Add(args32[1]); 231 | data = returnValue(args32, instrSet, caller, out int shift); 232 | if (isRegister(args32[2 + shift])) 233 | { 234 | byte reg = BitConverter.GetBytes(args32[3 + shift])[3]; 235 | instrSet.CPU.SetRegData(reg, (uint)(instrSet.CPU.GetRegData(reg) * data)); 236 | } 237 | else if (isPointer(args32[2 + shift])) 238 | { 239 | List _args = new List(); 240 | for (int i = 3 + shift; i < args32.Count; i++) 241 | _args.Add(args32[i]); 242 | caller.Memory.WriteInt32(GetPointerAddress(_args, instrSet, caller, out _), (int)(caller.Memory.ReadInt32((int)args32[3]) * data)); 243 | } 244 | } 245 | 246 | //OP Delegates 247 | public void JMP(Executable caller) // jumps to determined position 248 | { 249 | uint data; 250 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 251 | data = returnValue(args32, instrSet, caller, out int shift); 252 | 253 | instrSet.CPU.SetRegData((byte)FGMSECpu.FGMSERegisters.IP, data); 254 | } 255 | public void CALL(Executable caller) // calls determined position 256 | { 257 | uint data; 258 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 259 | data = returnValue(args32, instrSet, caller, out int shift); 260 | 261 | caller.Returns.Add((int)(instrSet.CPU.GetRegData((byte)FGMSECpu.FGMSERegisters.IP))); 262 | instrSet.CPU.SetRegData((byte)FGMSECpu.FGMSERegisters.IP, data); 263 | } 264 | public void RET(Executable caller) // returns to the previous called section 265 | { 266 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 267 | 268 | if (caller.Returns.Count == 0) return; 269 | 270 | instrSet.CPU.SetRegData((byte)FGMSECpu.FGMSERegisters.IP, (uint)caller.Returns[caller.Returns.Count - 1]); 271 | List temp = new List(); 272 | for (int i = 0; i < caller.Returns.Count - 1; i++) 273 | temp.Add(caller.Returns[i]); 274 | caller.Returns = temp; 275 | } 276 | public void SYSCALL(Executable caller) // calls the specified system call 277 | { 278 | uint data; 279 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 280 | data = returnValue(args32, instrSet, caller, out int shift); 281 | if (!caller.RunSystemCall((int)data)) 282 | instrSet.CPU.SetRegData((byte)FGMSECpu.FGMSERegisters.C1, 0xFEFEFEFE); 283 | } 284 | public void END(Executable caller) // terminates the execution of the specified program 285 | { 286 | caller.running = false; 287 | } 288 | 289 | // CONDITIONS INSTRUCTIONS 290 | public void CMP(Executable caller) // compares two datas between them 291 | { 292 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 293 | uint arg1 = returnValue(args32, instrSet, caller, out int shift); 294 | List _args = new List(); 295 | for (int i = 2 + shift; i < args32.Count; i++) 296 | _args.Add(args32[i]); 297 | uint arg2 = returnValue(_args, instrSet, caller, out _); 298 | caller.lastInstruction = arg1 > arg2; 299 | } 300 | public void EQU(Executable caller) // compares two datas between them 301 | { 302 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 303 | uint arg1 = returnValue(args32, instrSet, caller, out int shift); 304 | List _args = new List(); 305 | for (int i = 2 + shift; i < args32.Count; i++) 306 | _args.Add(args32[i]); 307 | uint arg2 = returnValue(_args, instrSet, caller, out _); 308 | caller.lastInstruction = arg1 == arg2; 309 | } 310 | public void JE(Executable caller) 311 | { 312 | if (caller.lastInstruction) JMP(caller); 313 | } 314 | public void JNE(Executable caller) 315 | { 316 | if (!caller.lastInstruction) JMP(caller); 317 | } 318 | public void CE(Executable caller) 319 | { 320 | if (caller.lastInstruction) CALL(caller); 321 | } 322 | public void CNE(Executable caller) 323 | { 324 | if (!caller.lastInstruction) CALL(caller); 325 | } 326 | public void SCE(Executable caller) 327 | { 328 | if (caller.lastInstruction) SYSCALL(caller); 329 | } 330 | public void SCNE(Executable caller) 331 | { 332 | if (!caller.lastInstruction) SYSCALL(caller); 333 | } 334 | public void RE(Executable caller) 335 | { 336 | if (caller.lastInstruction) RET(caller); 337 | } 338 | public void RNE(Executable caller) 339 | { 340 | if (!caller.lastInstruction) RET(caller); 341 | } 342 | public void EE(Executable caller) 343 | { 344 | if (caller.lastInstruction) END(caller); 345 | } 346 | public void ENE(Executable caller) 347 | { 348 | if (!caller.lastInstruction) END(caller); 349 | } 350 | 351 | //Stack delegates 352 | public void PUSH(Executable caller) 353 | { 354 | uint data; 355 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 356 | data = returnValue(args32, instrSet, caller, out int shift); 357 | 358 | caller.Memory.Stack.Push((int)data); 359 | } 360 | public void POP(Executable caller) 361 | { 362 | var instrSet = (FGMSECInstructionSet)(caller.usingInstructionSet); 363 | if (isRegister(args32[0])) 364 | { 365 | byte reg = BitConverter.GetBytes(args32[1])[3]; 366 | int data = 0; 367 | 368 | caller.Memory.Stack.Try_Pop(ref data); 369 | instrSet.CPU.SetRegData(reg, (uint)(data)); 370 | } 371 | else if (isPointer(args32[0])) 372 | { 373 | List _args = new List(); 374 | for (int i = 1; i < args32.Count; i++) 375 | _args.Add(args32[i]); 376 | int data = 0; 377 | caller.Memory.Stack.Try_Pop(ref data); 378 | caller.Memory.WriteInt32(GetPointerAddress(_args, instrSet, caller, out _), data); 379 | } 380 | } 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /Cosmos.System2.Emulation/instruction sets/InstructionSet.cs: -------------------------------------------------------------------------------- 1 | using Sys = System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | //man if you're here now, just go check Instruction.cs out because there are some very cool updates going on here. 8 | //things can be a bit confusing but hopefully by having commented everything you'll able to better understand what i did here. 9 | 10 | namespace Cosmos.System.Emulation 11 | { 12 | public class FGMSECpu: VirtualCPU32 13 | { 14 | List registers = new List(); 15 | public override bool ClearRegData(byte regAddress) 16 | { 17 | if (regAddress >= registers.Count) return false; 18 | registers[regAddress] = 0x00; 19 | return true; 20 | } 21 | public override uint GetRegData(byte regAddress) 22 | { 23 | if (regAddress >= registers.Count) 24 | { 25 | throw new Sys.Exception("Requested address register was out of range!"); 26 | } 27 | return registers[regAddress]; 28 | } 29 | public override bool SetRegData(byte regAddress, uint Data) 30 | { 31 | if (regAddress >= registers.Count) return false; 32 | registers[regAddress] = Data; 33 | return true; 34 | } 35 | public override void LoadRegisters() 36 | { 37 | for (int i = 0; i < 15; i++) 38 | { 39 | registers.Add(0x00); 40 | } 41 | } 42 | public enum FGMSERegisters: byte 43 | { 44 | G0 = 0, 45 | G1 = 1, 46 | G2 = 2, 47 | G3 = 3, 48 | G4 = 4, 49 | G5 = 5, 50 | G6 = 6, 51 | G7 = 7, 52 | G8 = 8, 53 | G9 = 9, 54 | C1 = 10, 55 | C2 = 11, 56 | SP = 12, 57 | BP = 13, 58 | IP = 14 59 | } 60 | } 61 | public class CHIP8Cpu: VirtualCPU16 //oh and check out VirtualCPU.cs too 62 | { 63 | //i assume that a CHIP8 cpu has a maximum of 16bit registers, if not change it as you need 64 | 65 | public override bool ClearRegData(byte regAddress) 66 | { 67 | //clear register in address 68 | return true; 69 | } 70 | public override ushort GetRegData(byte regAddress) 71 | { 72 | //get and return data in the specified register 73 | return 0; 74 | } 75 | public override bool SetRegData(byte regAddress, ushort Data) 76 | { 77 | //put data in register 78 | return true; 79 | } 80 | } 81 | public class CHIP8InstructionSet : InstructionSet 82 | { 83 | public CHIP8Cpu cpu = new CHIP8Cpu(); //and yeah by this not being static, each executable will have its own cpu. 84 | //actually idk if i really wanna do this, tell me what you think about it. 85 | 86 | // chip-8 instructions 87 | public static CHIP8Instruction CHIP8_CLS = new CHIP8Instruction("CLS", 0x00E0, "") { 88 | Delegate = new Instruction.InstructionDelegate((Executable caller) => 89 | { 90 | // clear buffer 91 | 92 | }) 93 | }; 94 | public static CHIP8Instruction CHIP8_RET = new CHIP8Instruction("RET", 0x00EE, "") 95 | { 96 | Delegate = new Instruction.InstructionDelegate((Executable caller) => 97 | { 98 | }) 99 | }; 100 | public static CHIP8Instruction CHIP8_SYS = new CHIP8Instruction("RET", 0x1000, "") { }; 101 | public static CHIP8Instruction CHIP8_JUMP = new CHIP8Instruction("RET", 0x00EE, "") { }; 102 | 103 | // maybe creating a function like: call(byte[] code); and then it'll call the instruction as needed 104 | 105 | public override Instruction GetInstruction(short[] rawCode) 106 | { 107 | //here you set the value and arguments of the instruction set 108 | //then you add to the register pointer that manages the location into the opcode the number of times you went on reading 109 | //the array 110 | 111 | //let's assume that 5 is the register encharged of maintaining the pointer of the OPCODE 112 | 113 | int readNum = 0; //increase this each time you read next value in rawCode 114 | 115 | //here you would set the args into the instruction and determin which instruction is it 116 | Instruction instr = CHIP8_SYS; 117 | instr.arg8 = null; //here you may put 118 | instr.args16 = null;//all the arguments 119 | instr.args32 = null;//needed by the instruction 120 | //always acording to its architecture 121 | 122 | cpu.SetRegData(5, (ushort)(cpu.GetRegData(5) + readNum)); //and as said before here you actually set the 123 | //op pointer after the read instruction. 124 | 125 | return instr; //and here you return the instruction, ready to be called by the executable instance 126 | } 127 | public override Instruction GetInstruction(int[] rawCode) 128 | { 129 | //this function will never be usend since chip8 doesn't take 32bit opcodes 130 | return new CHIP8Instruction("NOP", 0, ""); 131 | } 132 | public override Instruction GetInstruction(byte[] rawCode) 133 | { 134 | //this function will never be usend since chip8 doesn't take 8bit opcodes 135 | return new CHIP8Instruction("NOP", 0, ""); 136 | } 137 | 138 | public CHIP8InstructionSet(): base(0x00, "Chip8 instruction set") 139 | { 140 | AddInstruction(CHIP8_CLS); 141 | } 142 | 143 | } 144 | public class FGMSECInstructionSet : InstructionSet 145 | { 146 | public FGMSECpu CPU = new FGMSECpu(); 147 | public FGMSECInstructionSet(): base(0x02, "FGMSE instruction set") 148 | { 149 | CPU.LoadRegisters(); 150 | } 151 | public static void Install() 152 | { 153 | try 154 | { 155 | FGMSEInstruction NOP = new FGMSEInstruction("NOP", 0, "NOP"); 156 | instructions.Add(0, NOP); 157 | 158 | //math instructions 159 | 160 | // MOV instruction - 1 161 | FGMSEInstruction instr = new FGMSEInstruction("MOV", 4, "MOV"); 162 | instr.Delegate = instr.MOV; 163 | instructions.Add(1, instr); 164 | 165 | // SET instruction - 2 166 | instr = new FGMSEInstruction("SET", 4, "SET"); 167 | instr.Delegate = instr.SET; 168 | instructions.Add(2, instr); 169 | 170 | // ADD instruction - 3 171 | instr = new FGMSEInstruction("ADD", 4, "ADD"); 172 | instr.Delegate = instr.ADD; 173 | instructions.Add(3, instr); 174 | 175 | // SUB instruction - 4 176 | instr = new FGMSEInstruction("SUB", 4, "SUB"); 177 | instr.Delegate = instr.SUB; 178 | instructions.Add(4, instr); 179 | 180 | // DIV instruction - 5 181 | instr = new FGMSEInstruction("DIV", 4, "DIV"); 182 | instr.Delegate = instr.DIV; 183 | instructions.Add(5, instr); 184 | 185 | // MUL instruction - 6 186 | instr = new FGMSEInstruction("MUL", 4, "MUL"); 187 | instr.Delegate = instr.MUL; 188 | instructions.Add(6, instr); 189 | 190 | //system instructions 191 | 192 | // JMP instruction - 7 193 | instr = new FGMSEInstruction("JMP", 2, "JMP"); 194 | instr.Delegate = instr.JMP; 195 | instructions.Add(7, instr); 196 | 197 | // CALL instruction - 8 198 | instr = new FGMSEInstruction("CALL", 2, "CALL"); 199 | instr.Delegate = instr.CALL; 200 | instructions.Add(8, instr); 201 | 202 | // RET instruction - 9 203 | instr = new FGMSEInstruction("RET", 0, "RET"); 204 | instr.Delegate = instr.RET; 205 | instructions.Add(9, instr); 206 | 207 | // SYSCALL instruction - 10 208 | instr = new FGMSEInstruction("SYSCALL", 2, "SYSCALL"); 209 | instr.Delegate = instr.SYSCALL; 210 | instructions.Add(10, instr); 211 | 212 | // END instruction - 11 213 | instr = new FGMSEInstruction("END", 0, "END"); 214 | instr.Delegate = instr.END; 215 | instructions.Add(11, instr); 216 | 217 | //conditional instructions 218 | 219 | // CMP instruction - 12 220 | instr = new FGMSEInstruction("CMP", 4, "CMP"); 221 | instr.Delegate = instr.CMP; 222 | instructions.Add(12, instr); 223 | 224 | // EQU instruction - 13 225 | instr = new FGMSEInstruction("EQU", 4, "EQU"); 226 | instr.Delegate = instr.EQU; 227 | instructions.Add(13, instr); 228 | 229 | // JE instruction - 14 230 | instr = new FGMSEInstruction("JE", 2, "JE"); 231 | instr.Delegate = instr.JE; 232 | instructions.Add(14, instr); 233 | 234 | // JNE instruction - 15 235 | instr = new FGMSEInstruction("JNE", 2, "JNE"); 236 | instr.Delegate = instr.JNE; 237 | instructions.Add(15, instr); 238 | 239 | // CE instruction - 16 240 | instr = new FGMSEInstruction("CE", 2, "CE"); 241 | instr.Delegate = instr.CE; 242 | instructions.Add(16, instr); 243 | 244 | // CNE instruction - 17 245 | instr = new FGMSEInstruction("CNE", 2, "CNE"); 246 | instr.Delegate = instr.CNE; 247 | instructions.Add(17, instr); 248 | 249 | // SCE instruction - 18 250 | instr = new FGMSEInstruction("SCE", 2, "SCE"); 251 | instr.Delegate = instr.SCE; 252 | instructions.Add(18, instr); 253 | 254 | // SCNE instruction - 19 255 | instr = new FGMSEInstruction("SCNE", 2, "SCNE"); 256 | instr.Delegate = instr.SCNE; 257 | instructions.Add(19, instr); 258 | 259 | // RE instruction - 20 260 | instr = new FGMSEInstruction("RE", 0, "RE"); 261 | instr.Delegate = instr.RE; 262 | instructions.Add(20, instr); 263 | 264 | // RNE instruction - 21 265 | instr = new FGMSEInstruction("RNE", 0, "RNE"); 266 | instr.Delegate = instr.RNE; 267 | instructions.Add(21, instr); 268 | 269 | // EE instruction - 22 270 | instr = new FGMSEInstruction("EE", 0, "EE"); 271 | instr.Delegate = instr.EE; 272 | instructions.Add(22, instr); 273 | 274 | // ENE instruction - 23 275 | instr = new FGMSEInstruction("ENE", 0, "ENE"); 276 | instr.Delegate = instr.ENE; 277 | instructions.Add(23, instr); 278 | 279 | // PUSH instruction - 24 280 | instr = new FGMSEInstruction("PUSH", 2, "PUSH"); 281 | instr.Delegate = instr.PUSH; 282 | instructions.Add(24, instr); 283 | 284 | // PUSH instruction - 25 285 | instr = new FGMSEInstruction("POP", 2, "POP"); 286 | instr.Delegate = instr.POP; 287 | instructions.Add(25, instr); 288 | 289 | Types.Sets.Add(0x02, new FGMSECInstructionSet()); 290 | 291 | } 292 | catch (Sys.Exception ex) 293 | { 294 | Sys.Console.WriteLine($"Fatal error loading instructions: {ex.Message}"); 295 | } 296 | } 297 | public override Instruction GetInstruction(byte[] rawCode) 298 | { 299 | throw new Sys.NotImplementedException(); 300 | } 301 | public override Instruction GetInstruction(int[] rawCode) 302 | { 303 | uint pos = CPU.GetRegData((byte)FGMSECpu.FGMSERegisters.IP); 304 | Instruction instr; 305 | try 306 | { 307 | instr = instructions[(uint)rawCode[(int)pos]]; 308 | } 309 | catch(Sys.Exception ex) 310 | { 311 | Sys.Console.WriteLine($"Instruction not found! ({(uint)rawCode[(int)pos]})"); 312 | return null; 313 | } 314 | try 315 | { 316 | pos++; 317 | List tempArgs = new List(); 318 | for (int i = 0; i < instr.OpCode; i++) 319 | { 320 | tempArgs.Add((uint)rawCode[(int)pos]); 321 | if ((uint)rawCode[(int)pos] == 0xFE001AFC) 322 | { 323 | i--; 324 | } 325 | pos++; 326 | } 327 | instr.args32 = tempArgs; 328 | CPU.SetRegData((byte)FGMSECpu.FGMSERegisters.IP, pos); 329 | } 330 | catch (global::System.Exception ex) 331 | { 332 | global::System.Console.WriteLine($"Error while loading instruction: {ex.Message}"); 333 | } 334 | return instr; 335 | } 336 | public override Instruction GetInstruction(short[] rawCode) 337 | { 338 | throw new Sys.NotImplementedException(); 339 | } 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MSE is distributed under GPL terms and conditions 2 | Copyright (C) 2020-2021 Nicola Leone Ciardi 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | USA 18 | 19 | For more documentation/information about the project contact 20 | Nicola Leone Ciardi 21 | at nicolaciardi@icloud.com 22 | or nicolaflavio22@gmail.com 23 | or by leaving a comment here 24 | 25 | Have a nice day, 26 | Nicola Leone Ciardi -------------------------------------------------------------------------------- /MSE.Package.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | false 6 | true 7 | true 8 | 9 | 10 | 11 | com.Nik300.ManagedSoftwareExecution 12 | 1.0.0.0 13 | Nicola Leone Ciardi 14 | 15 | https://github.com/Nik300/ManagedSoftwareExecutionCosmos 16 | http://ICON_URL_HERE_OR_DELETE_THIS_LINE 17 | https://github.com/Nik300/ManagedSoftwareExecutionCosmos 18 | true 19 | This package has been made to help people using CosmosOS project to execute external code. 20 | 21 | You are welcome to redistribute/modify the code of this project. 22 | Summary of changes made in this release of the package. 23 | Copyright (C) 2020-2021 Nicola Leone Ciardi 24 | ManagedSoftwareExecution, CosmosOS 25 | true 26 | 27 | $(TargetsForTfmSpecificContentInPackage);_AddAnalyzersToOutput 28 | 29 | ManagedSoftwareExecution 30 | 31 | Cosmos.System.Emulation 32 | 33 | 2.0 34 | 35 | GitHub Repo 36 | 37 | 2.0.1.1 38 | 39 | 2.0.10.0 40 | 41 | License.md 42 | 43 | 44 | 45 | 46 | 47 | True 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /obj/Debug/com.Nik300.ManagedSoftwareExecution.1.0.0.nuspec: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | com.Nik300.ManagedSoftwareExecution 5 | 1.0.0 6 | Nicola Leone Ciardi 7 | true 8 | License.md 9 | https://aka.ms/deprecateLicenseUrl 10 | https://github.com/Nik300/ManagedSoftwareExecutionCosmos 11 | http://icon_url_here_or_delete_this_line/ 12 | This package has been made to help people using CosmosOS project to execute external code. 13 | 14 | You are welcome to redistribute/modify the code of this project. 15 | Summary of changes made in this release of the package. 16 | Copyright (C) 2020-2021 Nicola Leone Ciardi 17 | ManagedSoftwareExecution, CosmosOS 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ManagedSoftwareExecution 2 | ## What is it? 3 | Well, MSE is a method that allows anybody to load external code from CosmosOS! 4 | ## How do i do that? 5 | To get this working it's actually pretty simple: 6 | ### Install the package 7 | Right click on your solution > Manage NuGET packages, then go to "Browse" and search ManagedSoftwareExecution, then install the package with the CosmosOS icon. 8 | ### Include the namespace 9 | `using Cosmos.System.Emulation` should do the job ;) 10 | ### Choose an executable 11 | #### a. Create your executable 12 | To compile your code (by the moment ASM is only supported but I am working on C support too) go to the github page https://github.com/Nik300/ASMCompilerForMSE/releases and download the latest version available. 13 | As of the moment of writing the current version is 1.0.0 14 | #### b. Download a test program 15 | If you don't know much about assembly and you don't want to waste much time on it go to [this link](https://github.com/Nik300/ASMCompilerForMSE/tree/main/Test%20programs) and download one of the test programs i compiled. 16 | Note that these programs need to have special systemcalls (such as systemcall 0, 1, 2, 3, 4) 17 | ### Install the instruction set 18 | By now the only available instruction set for MSE, is the one that I myself created: the FGMSEC Instruction Set. Don't ask me where that name came from because I don't know myself XD. 19 | Anyhow to install it just do 20 | ` 21 | FGMSECInstructionSet.Install(); 22 | ` 23 | in the 'BeforeRun' method in your code 24 | ### Run the executable 25 | Now we just need to load the executable into an instance 26 | ```C# 27 | FGMSECInstructionSet set = new FGMSECInstructionSet(); 28 | Executable exec; 29 | exec = new Executable(resource_data, set, 3); 30 | ``` 31 | in which 'resource_data' is 32 | ```C# 33 | [ManifestResourceStream(ResourceName = "project_name.path.to.executable.extension")] static byte[] resource_data; 34 | ``` 35 | now we simply load the executable data with `exec.ReadData();` and we run it by adding an infinite loop that executes its next instruction: 36 | ```C# 37 | while (exec.running) 38 | exec.NextInstruction(); 39 | ``` 40 | As you may notice, we are not in an actual 'endless' loop, but as soon as the program stops, it gives us back the control. This can be useful for the future (e.g. adding a TaskManager which is almos done, this means that MSE has multithreading :D) 41 | ## System Calls 42 | Actually, running an executable as i did before, won't do much... this is because we didn't add any of the necessary Systemcalls that the executable requires. These are the basic systemcalls that ALL my test programs use: 43 | ```C# 44 | exec.AddSystemCall((Executable caller) => 45 | { 46 | int addr = (int)((FGMSECInstructionSet)caller.usingInstructionSet).CPU.GetRegData(3); 47 | char c = (char)caller.Memory.ReadChar(addr); 48 | while (c != 0) 49 | { 50 | Console.Write(c); 51 | addr++; 52 | c = (char)caller.Memory.ReadChar(addr); 53 | } 54 | }); 55 | exec.AddSystemCall((Executable caller) => 56 | { 57 | string input = Console.ReadLine(); 58 | input += '\0'; 59 | int addr = caller.Memory.Data.Count; 60 | int caddr = 0; 61 | for (int i = 0; i < input.Length; i++) 62 | { 63 | char c = input[i]; 64 | if (!caller.Memory.AddChar(c)) 65 | { 66 | caller.Memory.WriteChar(caddr, c); 67 | addr = 0; 68 | caddr++; 69 | } 70 | } 71 | ((FGMSECInstructionSet)caller.usingInstructionSet).CPU.SetRegData(3, (uint)addr); 72 | }); 73 | exec.AddSystemCall((Executable caller) => 74 | { 75 | Console.Clear(); 76 | }); 77 | ``` 78 | You can simply copy-paste those and run one of my test programs. 79 | ## Conclusion 80 | MSE is a very powerful tool, and if you know how to use it, you can do very cool stuff with it! 81 | I can't wait to see what kind of weird stuff you come up with it! 82 | And PLEASE feedback everything! 83 | If you're enjoying FEEDBACK or if you're hating it feedback it too giving reasons! 84 | ## Projects using MSE 85 | If you didn't understand a word of what i said... well I can't blame you! Give a look at [my OS](https://github.com/Nik300/TestEnvOS) which uses MSE (look expecially at function 'ConstructExecutable' and the last part of 'RunCommand' 86 | 87 | Enjoy your code! 88 | --------------------------------------------------------------------------------