From 44f7b1bccbc75a05a6f9e1c049d1dd6c9b76cd1e Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Fri, 12 Sep 2025 15:56:35 +0100 Subject: [PATCH 01/12] Add Rider idea folder to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5c8a8e9..42ad913 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ riderModule.iml YODA_Python/venv/ YODA_TypeScript/node_modules/ YODA_Python/__pycache__/ +.idea/ From efea8029243e7cebaf3ae5a007c655dc911dfb29 Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Fri, 12 Sep 2025 16:01:24 +0100 Subject: [PATCH 02/12] Fix-up off-by-1 values for the misc operands --- YODA/OpCodes.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/YODA/OpCodes.cs b/YODA/OpCodes.cs index dd6201d..7852fcc 100644 --- a/YODA/OpCodes.cs +++ b/YODA/OpCodes.cs @@ -10,11 +10,11 @@ public static class OpCode { // Misc (opcodes without operands) public const byte Halt = 0b0000_0000; // 00 - public const byte Wait = 0b0000_0001; // 00 - public const byte Ret = 0b0000_0011; // 02 - public const byte Nop = 0b0000_0100; // 03 - public const byte Sif = 0b0000_0101; // 04 - public const byte Cif = 0b0000_0110; // 05 + public const byte Wait = 0b0000_0001; // 01 + public const byte Ret = 0b0000_0010; // 02 + public const byte Nop = 0b0000_0011; // 03 + public const byte Sif = 0b0000_0100; // 04 + public const byte Cif = 0b0000_0101; // 05 public const byte SaveToFileMMM = 0b0001_0000; //16 public const byte SaveToFileMMI = 0b0001_0001; //17 From 67ed755cad0a2669e879645eb6e0397b1d8e48c4 Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Sat, 13 Sep 2025 09:36:17 +0100 Subject: [PATCH 03/12] Initial solution, project, plus Exercise 1 work --- mark-csharp.sln | 56 ++++++++++++++++ mark-csharp/Files/ex1 | Bin 0 -> 256 bytes mark-csharp/YodaExercises/Program.cs | 60 ++++++++++++++++++ .../YodaExercises/YodaExercises.csproj | 15 +++++ 4 files changed, 131 insertions(+) create mode 100644 mark-csharp.sln create mode 100644 mark-csharp/Files/ex1 create mode 100644 mark-csharp/YodaExercises/Program.cs create mode 100644 mark-csharp/YodaExercises/YodaExercises.csproj diff --git a/mark-csharp.sln b/mark-csharp.sln new file mode 100644 index 0000000..895695d --- /dev/null +++ b/mark-csharp.sln @@ -0,0 +1,56 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mark-csharp", "mark-csharp", "{5C3CA1F0-BEFB-913A-467C-9BC8E8763114}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YodaExercises", "mark-csharp\YodaExercises\YodaExercises.csproj", "{8D8C9463-C990-4962-996E-1EEE84C8441E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "YODA", "YODA", "{53427892-8E56-C6A7-C67E-0E35C96E3AED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleInstructionMachine", "YODA\SimpleInstructionMachine.csproj", "{7B6C7992-E188-49CD-AC66-6B959606752F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Debug|x64.ActiveCfg = Debug|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Debug|x64.Build.0 = Debug|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Debug|x86.ActiveCfg = Debug|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Debug|x86.Build.0 = Debug|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Release|Any CPU.Build.0 = Release|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Release|x64.ActiveCfg = Release|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Release|x64.Build.0 = Release|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Release|x86.ActiveCfg = Release|Any CPU + {8D8C9463-C990-4962-996E-1EEE84C8441E}.Release|x86.Build.0 = Release|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Debug|x64.ActiveCfg = Debug|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Debug|x64.Build.0 = Debug|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Debug|x86.ActiveCfg = Debug|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Debug|x86.Build.0 = Debug|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Release|Any CPU.Build.0 = Release|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Release|x64.ActiveCfg = Release|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Release|x64.Build.0 = Release|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Release|x86.ActiveCfg = Release|Any CPU + {7B6C7992-E188-49CD-AC66-6B959606752F}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {8D8C9463-C990-4962-996E-1EEE84C8441E} = {5C3CA1F0-BEFB-913A-467C-9BC8E8763114} + {7B6C7992-E188-49CD-AC66-6B959606752F} = {53427892-8E56-C6A7-C67E-0E35C96E3AED} + EndGlobalSection +EndGlobal diff --git a/mark-csharp/Files/ex1 b/mark-csharp/Files/ex1 new file mode 100644 index 0000000000000000000000000000000000000000..65f57c2ee985713476ac0b6e3483e6fe472e2176 GIT binary patch literal 256 LcmZQz7})>-0RR92 literal 0 HcmV?d00001 diff --git a/mark-csharp/YodaExercises/Program.cs b/mark-csharp/YodaExercises/Program.cs new file mode 100644 index 0000000..b267304 --- /dev/null +++ b/mark-csharp/YodaExercises/Program.cs @@ -0,0 +1,60 @@ +using System.Reflection; +using SimpleInstructionMachine; + +namespace YodaExercises; + +internal static class Program +{ + private static string FilePath = null!; + + internal static void Main(string[] args) + { + // Get individual path parts to the assembly and where the assembly is in the list + var pathParts = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + .Split(Path.DirectorySeparatorChar) + .ToList(); + var assemblyIndex = pathParts.IndexOf(nameof(YodaExercises)); + // Reassemble the paths up to the point of the assembly name + var basePath = string.Join(Path.DirectorySeparatorChar, pathParts[..assemblyIndex]); + // Append Files to the path - this is the location of the boot file area + FilePath = Path.Combine(basePath, "Files"); + + // Make sure the Files folder exists + if(!Directory.Exists(FilePath)) + Directory.CreateDirectory(FilePath); + + Exercise1(); + } + + private static void WriteFile(string name, byte[]? contents) + { + // programs can only occupy 256 bytes - any more will break the sim! + var fileLength = 1 + byte.MaxValue; + ArgumentOutOfRangeException.ThrowIfGreaterThan(contents?.Length ?? 0, fileLength, nameof(contents)); + + // Create the 256 byte buffer for the file + var buffer = new byte[fileLength]; + // Copy any contents we have been sent to the buffer + if (contents?.Length > 0) + contents.CopyTo(buffer, 0); + // Dump the buffer to the specified file, ensuring we only retain the name of the file and place it correctly + File.WriteAllBytes(Path.Combine(FilePath, Path.GetFileName(name)), buffer); + } + + private static void MakeFileBoot(string name) + { + var fileName = Path.Combine(FilePath, Path.GetFileName(name)); + if(!File.Exists(fileName)) + throw new FileNotFoundException($"File {fileName} not found."); + File.Copy(fileName, Path.Combine(FilePath, "boot"), true); + } + + private static void Exercise1() + { + WriteFile("ex1", null); + MakeFileBoot("ex1"); + + var vm = new VirtualMachine(true); + vm.Run(FilePath).Wait(); + } +} \ No newline at end of file diff --git a/mark-csharp/YodaExercises/YodaExercises.csproj b/mark-csharp/YodaExercises/YodaExercises.csproj new file mode 100644 index 0000000..3d095ac --- /dev/null +++ b/mark-csharp/YodaExercises/YodaExercises.csproj @@ -0,0 +1,15 @@ + + + + + + + + Exe + net9.0 + yoda_exercises + enable + enable + + + From 3b51eb948bb3f67db4faddd26ffc54846715194c Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Sat, 13 Sep 2025 09:39:16 +0100 Subject: [PATCH 04/12] Refactor to use a common method to run a VM for all exercises --- mark-csharp/YodaExercises/Program.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mark-csharp/YodaExercises/Program.cs b/mark-csharp/YodaExercises/Program.cs index b267304..5560522 100644 --- a/mark-csharp/YodaExercises/Program.cs +++ b/mark-csharp/YodaExercises/Program.cs @@ -48,13 +48,18 @@ private static void MakeFileBoot(string name) throw new FileNotFoundException($"File {fileName} not found."); File.Copy(fileName, Path.Combine(FilePath, "boot"), true); } - - private static void Exercise1() + + private static void RunVm(string program) { - WriteFile("ex1", null); - MakeFileBoot("ex1"); + MakeFileBoot(program); var vm = new VirtualMachine(true); vm.Run(FilePath).Wait(); } + + private static void Exercise1() + { + WriteFile("ex1", null); + RunVm("ex1"); + } } \ No newline at end of file From 766c5e6d89c81433a97a22412b823a40a1610615 Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Sat, 13 Sep 2025 09:42:56 +0100 Subject: [PATCH 05/12] Add Exercise 2 work, including boot file --- mark-csharp/Files/ex2 | Bin 0 -> 256 bytes mark-csharp/YodaExercises/Program.cs | 9 ++++++++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 mark-csharp/Files/ex2 diff --git a/mark-csharp/Files/ex2 b/mark-csharp/Files/ex2 new file mode 100644 index 0000000000000000000000000000000000000000..551efc7e0b7f179a2aad5478bc5d4d56e72b2567 GIT binary patch literal 256 Lcmey*FtPyv01p8G literal 0 HcmV?d00001 diff --git a/mark-csharp/YodaExercises/Program.cs b/mark-csharp/YodaExercises/Program.cs index 5560522..03c7950 100644 --- a/mark-csharp/YodaExercises/Program.cs +++ b/mark-csharp/YodaExercises/Program.cs @@ -23,7 +23,8 @@ internal static void Main(string[] args) if(!Directory.Exists(FilePath)) Directory.CreateDirectory(FilePath); - Exercise1(); + // Exercise1(); + Exercise2(); } private static void WriteFile(string name, byte[]? contents) @@ -62,4 +63,10 @@ private static void Exercise1() WriteFile("ex1", null); RunVm("ex1"); } + + private static void Exercise2() + { + WriteFile("ex2", [0xFF]); + RunVm("ex2"); + } } \ No newline at end of file From 4e144da8355ada1fb0bf03e37abf538f6045e5a7 Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Sat, 13 Sep 2025 09:55:11 +0100 Subject: [PATCH 06/12] Add Exercise 3 work, including boot and output file --- mark-csharp/Files/0 | 1 + mark-csharp/Files/ex3 | Bin 0 -> 256 bytes mark-csharp/YodaExercises/Program.cs | 19 ++++++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 mark-csharp/Files/0 create mode 100644 mark-csharp/Files/ex3 diff --git a/mark-csharp/Files/0 b/mark-csharp/Files/0 new file mode 100644 index 0000000..9acfbbf --- /dev/null +++ b/mark-csharp/Files/0 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mark-csharp/Files/ex3 b/mark-csharp/Files/ex3 new file mode 100644 index 0000000000000000000000000000000000000000..94cd65e7bc7ba29da6fbce964444702f24f57de2 GIT binary patch literal 256 XcmWe Date: Sun, 14 Sep 2025 10:01:38 +0100 Subject: [PATCH 07/12] fix-up Rider warnings --- mark-csharp/YodaExercises/Program.cs | 28 +++++++++---------- .../YodaExercises/YodaExercises.csproj | 26 ++++++++--------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/mark-csharp/YodaExercises/Program.cs b/mark-csharp/YodaExercises/Program.cs index 859581c..e31c75b 100644 --- a/mark-csharp/YodaExercises/Program.cs +++ b/mark-csharp/YodaExercises/Program.cs @@ -5,24 +5,24 @@ namespace YodaExercises; internal static class Program { - private static string FilePath = null!; - + private static string _filePath = null!; + internal static void Main(string[] args) { // Get individual path parts to the assembly and where the assembly is in the list - var pathParts = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + var pathParts = (Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "") .Split(Path.DirectorySeparatorChar) .ToList(); var assemblyIndex = pathParts.IndexOf(nameof(YodaExercises)); // Reassemble the paths up to the point of the assembly name var basePath = string.Join(Path.DirectorySeparatorChar, pathParts[..assemblyIndex]); // Append Files to the path - this is the location of the boot file area - FilePath = Path.Combine(basePath, "Files"); + _filePath = Path.Combine(basePath, "Files"); // Make sure the Files folder exists - if(!Directory.Exists(FilePath)) - Directory.CreateDirectory(FilePath); - + if (!Directory.Exists(_filePath)) + Directory.CreateDirectory(_filePath); + // Exercise1(); // Exercise2(); Exercise3(); @@ -40,15 +40,15 @@ private static void WriteFile(string name, byte[]? contents) if (contents?.Length > 0) contents.CopyTo(buffer, 0); // Dump the buffer to the specified file, ensuring we only retain the name of the file and place it correctly - File.WriteAllBytes(Path.Combine(FilePath, Path.GetFileName(name)), buffer); + File.WriteAllBytes(Path.Combine(_filePath, Path.GetFileName(name)), buffer); } private static void MakeFileBoot(string name) { - var fileName = Path.Combine(FilePath, Path.GetFileName(name)); - if(!File.Exists(fileName)) + var fileName = Path.Combine(_filePath, Path.GetFileName(name)); + if (!File.Exists(fileName)) throw new FileNotFoundException($"File {fileName} not found."); - File.Copy(fileName, Path.Combine(FilePath, "boot"), true); + File.Copy(fileName, Path.Combine(_filePath, "boot"), true); } private static void RunVm(string program) @@ -56,9 +56,9 @@ private static void RunVm(string program) MakeFileBoot(program); var vm = new VirtualMachine(true); - vm.Run(FilePath).Wait(); + vm.Run(_filePath).Wait(); } - + private static void Exercise1() { WriteFile("ex1", null); @@ -70,7 +70,7 @@ private static void Exercise2() WriteFile("ex2", [0xFF]); RunVm("ex2"); } - + private static void Exercise3() { // Two parts to this... the program itself and its data diff --git a/mark-csharp/YodaExercises/YodaExercises.csproj b/mark-csharp/YodaExercises/YodaExercises.csproj index 3d095ac..0b036e3 100644 --- a/mark-csharp/YodaExercises/YodaExercises.csproj +++ b/mark-csharp/YodaExercises/YodaExercises.csproj @@ -1,15 +1,15 @@ - - + + - - - - Exe - net9.0 - yoda_exercises - enable - enable - - - + + + + Exe + net9.0 + YodaExercises + enable + enable + + + From 46753fedbe312cbf3c686521690bdf65ca064e07 Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Sun, 14 Sep 2025 10:07:28 +0100 Subject: [PATCH 08/12] Add exercise 4 work, inclusive of boot and output files --- mark-csharp/Files/9.txt | 1 + mark-csharp/Files/ex4 | Bin 0 -> 256 bytes mark-csharp/YodaExercises/Program.cs | 16 +++++++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 mark-csharp/Files/9.txt create mode 100644 mark-csharp/Files/ex4 diff --git a/mark-csharp/Files/9.txt b/mark-csharp/Files/9.txt new file mode 100644 index 0000000..4dd7de8 --- /dev/null +++ b/mark-csharp/Files/9.txt @@ -0,0 +1 @@ +5 4 3 2 1 LIFTOFF \ No newline at end of file diff --git a/mark-csharp/Files/ex4 b/mark-csharp/Files/ex4 new file mode 100644 index 0000000000000000000000000000000000000000..084dfe4874852ffac1ec80393bc2de37346e12c8 GIT binary patch literal 256 jcmWgVR1jpq156c66pR&&6bu!7Jl#V4-Q4h~9g0!_WEKPa literal 0 HcmV?d00001 diff --git a/mark-csharp/YodaExercises/Program.cs b/mark-csharp/YodaExercises/Program.cs index e31c75b..2ee94c9 100644 --- a/mark-csharp/YodaExercises/Program.cs +++ b/mark-csharp/YodaExercises/Program.cs @@ -25,7 +25,8 @@ internal static void Main(string[] args) // Exercise1(); // Exercise2(); - Exercise3(); + // Exercise3(); + Exercise4(); } private static void WriteFile(string name, byte[]? contents) @@ -86,4 +87,17 @@ private static void Exercise3() WriteFile("ex3", buffer); RunVm("ex3"); } + + private static void Exercise4() + { + byte[] message = "5 4 3 2 1 LIFTOFF".ToCharArray().Select(x => (byte)x).ToArray(); + byte[] program = [OpCode.SaveToFileIII, 9, 0x20, (byte)message.Length]; + + // Copy program and message to a temp buffer to pass to the VM Runner + var buffer = new byte[64]; + program.CopyTo(buffer, 0); + message.CopyTo(buffer, 0x20); + WriteFile("ex4", buffer); + RunVm("ex4"); + } } \ No newline at end of file From ab5d7e68bf6696874b6da8ed559963929f98e6b4 Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Sun, 14 Sep 2025 12:31:25 +0100 Subject: [PATCH 09/12] Add exercise 5 work, inclusive of refuel, boot and output files --- mark-csharp/Files/1 | 1 + mark-csharp/Files/ex5 | Bin 0 -> 256 bytes mark-csharp/Files/refuelFile1 | Bin 0 -> 256 bytes mark-csharp/YodaExercises/Program.cs | 27 ++++++++++++++++++++++++++- 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 mark-csharp/Files/1 create mode 100644 mark-csharp/Files/ex5 create mode 100644 mark-csharp/Files/refuelFile1 diff --git a/mark-csharp/Files/1 b/mark-csharp/Files/1 new file mode 100644 index 0000000..fa7af8b --- /dev/null +++ b/mark-csharp/Files/1 @@ -0,0 +1 @@ +z \ No newline at end of file diff --git a/mark-csharp/Files/ex5 b/mark-csharp/Files/ex5 new file mode 100644 index 0000000000000000000000000000000000000000..0e6f02ce924c4bd011ee22f422e80c0fa8efd9cf GIT binary patch literal 256 TcmY#pY$$9HXKY|(7?}V7CdmRX literal 0 HcmV?d00001 diff --git a/mark-csharp/Files/refuelFile1 b/mark-csharp/Files/refuelFile1 new file mode 100644 index 0000000000000000000000000000000000000000..f070424dd30e3ed26bfc6c7a9ee87041f744f517 GIT binary patch literal 256 TcmWe Date: Sun, 14 Sep 2025 13:58:35 +0100 Subject: [PATCH 10/12] Add exercise 6 work, inclusive of boot file --- mark-csharp/Files/ex6 | Bin 0 -> 256 bytes mark-csharp/YodaExercises/Program.cs | 44 +++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 mark-csharp/Files/ex6 diff --git a/mark-csharp/Files/ex6 b/mark-csharp/Files/ex6 new file mode 100644 index 0000000000000000000000000000000000000000..255a05c3617cf6228ffda057d34465f9e270d054 GIT binary patch literal 256 rcmXr|(O~?S(fBU|qtTB>II9WHYKF5~pezQe0#g%XBSWg1NSa{)<~kKd literal 0 HcmV?d00001 diff --git a/mark-csharp/YodaExercises/Program.cs b/mark-csharp/YodaExercises/Program.cs index 463812e..cb06ff3 100644 --- a/mark-csharp/YodaExercises/Program.cs +++ b/mark-csharp/YodaExercises/Program.cs @@ -27,7 +27,8 @@ internal static void Main(string[] args) // Exercise2(); // Exercise3(); // Exercise4(); - Exercise5(); + // Exercise5(); + Exercise6(); } private static void WriteFile(string name, byte[]? contents) @@ -111,11 +112,12 @@ private static void RefuelFile1(byte refuelAmount) WriteFile("refuelFile1", buffer); RunVm("refuelFile1"); } - + private static void Exercise5() { RefuelFile1(123); - byte[] program = [ + byte[] program = + [ OpCode.LoadFromFileII, 1, 0x80, OpCode.DecI, 0x80, OpCode.SaveToFileIII, 1, 0x80, 1 @@ -125,4 +127,40 @@ private static void Exercise5() WriteFile("ex5", buffer); RunVm("ex5"); } + + private static void Exercise6() + { + byte[] message = "54321".ToCharArray().Select(x => (byte)x).ToArray(); + byte[] program = + [ + OpCode.WriteIM, KnownMemory.LCD_0, 0x80, + OpCode.WriteII, KnownMemory.ControlFlags, 0x01, + OpCode.WriteII, KnownMemory.ControlFlags, 0x00, + OpCode.Wait, + OpCode.WriteIM, KnownMemory.LCD_0, 0x81, + OpCode.WriteII, KnownMemory.ControlFlags, 0x01, + OpCode.WriteII, KnownMemory.ControlFlags, 0x00, + OpCode.Wait, + OpCode.WriteIM, KnownMemory.LCD_0, 0x82, + OpCode.WriteII, KnownMemory.ControlFlags, 0x01, + OpCode.WriteII, KnownMemory.ControlFlags, 0x00, + OpCode.Wait, + OpCode.WriteIM, KnownMemory.LCD_0, 0x83, + OpCode.WriteII, KnownMemory.ControlFlags, 0x01, + OpCode.WriteII, KnownMemory.ControlFlags, 0x00, + OpCode.Wait, + OpCode.WriteIM, KnownMemory.LCD_0, 0x84, + OpCode.WriteII, KnownMemory.ControlFlags, 0x01, + OpCode.WriteII, KnownMemory.ControlFlags, 0x00, + OpCode.Wait, + ]; + + // Copy program and message to a temp buffer to pass to the VM Runner + var buffer = new byte[1 + byte.MaxValue]; + program.CopyTo(buffer, 0); + message.CopyTo(buffer, 0x80); + + WriteFile("ex6", buffer); + RunVm("ex6"); + } } \ No newline at end of file From 16b89d8548e84c571dfd074f9a45e6e92b84fd96 Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Wed, 17 Sep 2025 09:54:25 +0100 Subject: [PATCH 11/12] Add exercise 7 work, including fixing up the VM with a Sub method --- YODA/VirtualMachine.cs | 18 ++++- mark-csharp/YodaExercises/Program.cs | 99 +++++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/YODA/VirtualMachine.cs b/YODA/VirtualMachine.cs index da11ce8..859cdbc 100644 --- a/YODA/VirtualMachine.cs +++ b/YODA/VirtualMachine.cs @@ -84,7 +84,9 @@ public async Task Run(string folderPath) Add(opCode); continue; case Mask.Sub: - throw new Exception("Due to lack of time this method has not been implemented"); + // throw new Exception("Due to lack of time this method has not been implemented"); + Sub(opCode); + continue; case Mask.Inc: Inc(opCode); continue; @@ -405,4 +407,18 @@ private byte Read(int location,int opCode, int mask) return _memory[reference]; } + + /// + /// Sub LHS RHS Total + /// + private void Sub(int opCode) + { + var lhs = Read(_instructionPointer + 1, opCode, 2); + var rhs = Read(_instructionPointer + 2, opCode, 1); + var location = Read(_instructionPointer + 3, opCode, 0); + + if (Debug) Console.WriteLine($"{_instructionPointer:x4} Sub:: {lhs} - {rhs} = {lhs - rhs} ==> {location:x2}"); + _memory[location] = (byte)(lhs - rhs); // Can overflow + _instructionPointer += 4; + } } \ No newline at end of file diff --git a/mark-csharp/YodaExercises/Program.cs b/mark-csharp/YodaExercises/Program.cs index cb06ff3..f14b9dc 100644 --- a/mark-csharp/YodaExercises/Program.cs +++ b/mark-csharp/YodaExercises/Program.cs @@ -1,4 +1,5 @@ using System.Reflection; +using System.Xml.Serialization; using SimpleInstructionMachine; namespace YodaExercises; @@ -28,7 +29,8 @@ internal static void Main(string[] args) // Exercise3(); // Exercise4(); // Exercise5(); - Exercise6(); + // Exercise6(); + Exercise7(); } private static void WriteFile(string name, byte[]? contents) @@ -163,4 +165,99 @@ private static void Exercise6() WriteFile("ex6", buffer); RunVm("ex6"); } + + private static void Exercise7() + { + // Spaces that can be used to blank the screen area + byte[] spaces = " "u8.ToArray(); + byte leftVector = 0x40; + byte rightVector = 0x60; + // If the position has moved, then a value here will indicate the screen needs a refresh + byte movementCheck = 0x90; + byte currentPosition = 0x91; + byte blankScreen = 0x80; + + byte[] program = + [ + // 0x00 + // Write the spaces to file 8 so LCD segments can be overwritten simultaneously. + OpCode.SaveToFileIII, 8, blankScreen, (byte)spaces.Length, + // 0x04 + OpCode.Sif, + // 0x05 + OpCode.Wait, + // 0x06 + OpCode.JumpIfZeroII, movementCheck, 0x04, + // 0x09 - reset movement check + OpCode.WriteII, movementCheck, 0x00, + // 0x0C - write spaces into all LCD segments + OpCode.LoadFromFileII, 8, KnownMemory.LCD_0, + // 0x0F - write the dash to LCD at the correct position + OpCode.WriteMI, currentPosition, (byte)'-', + // 0x12 - refresh LCD + OpCode.WriteII, KnownMemory.ControlFlags, 0x01, + // 0x15 - reset LCD refresh + OpCode.WriteII, KnownMemory.ControlFlags, 0x00, + // 0x18 - loop from start of main loop + OpCode.JumpIfZeroII, movementCheck, 0x04, + // 0x1B + ]; + + // Interrupt handler for the left arrow keypress + byte[] leftInterrupt = + [ + // +0x00 + // Do not interrupt the interrupt + OpCode.Cif, + // +0x01 + // Check if current position is far-left, store result in movementCheck location + OpCode.SubMII, currentPosition, KnownMemory.LCD_0, movementCheck, + // +0x05 + // If movementCheck location is zero, do not perform any movement + OpCode.JumpIfZeroII, movementCheck, (byte)(leftVector + 0x0A), + // +0x08 + // Move one position left + OpCode.DecI, currentPosition, + // +0x0A + OpCode.Ret, + ]; + + // Interrupt handler for the right arrow keypress + byte[] rightInterrupt = + [ + // +0x00 + // Do not interrupt the interrupt + OpCode.Cif, + // +0x01 + OpCode.SubMII, currentPosition, KnownMemory.LCD_4, movementCheck, + // +0x05 + OpCode.JumpIfZeroII, movementCheck, (byte)(rightVector + 0x0A), + // +0x08 + // Move one position right + OpCode.IncI, currentPosition, + // +0x0A + OpCode.Ret, + ]; + + // Copy program and data to a temp buffer to pass to the VM Runner + var buffer = new byte[1 + byte.MaxValue]; + // Copy main program loop + program.CopyTo(buffer, 0); + // Copy left arrow interrupt routine + leftInterrupt.CopyTo(buffer, leftVector); + // Copy right arrow interrupt routine + rightInterrupt.CopyTo(buffer, rightVector); + + // Initial signal is we have "moved" into the central location + buffer[movementCheck] = 0x01; + // Set current position as central LCD segment + buffer[currentPosition] = KnownMemory.LCD_2; + // Write the spaces into a "high" memory area + spaces.CopyTo(buffer, blankScreen); + buffer[KnownMemory.IVT_LEFT_ARROW] = leftVector; + buffer[KnownMemory.IVT_RIGHT_ARROW] = rightVector; + + WriteFile("ex7", buffer); + RunVm("ex7"); + } } \ No newline at end of file From 4cc693f29499dd05d610e876a291292a3030436c Mon Sep 17 00:00:00 2001 From: Mark Allott Date: Wed, 17 Sep 2025 18:23:40 +0100 Subject: [PATCH 12/12] Work for exercise 8, plus input file and boot file --- mark-csharp/Files/2 | 1 + mark-csharp/Files/ex8 | Bin 0 -> 256 bytes mark-csharp/YodaExercises/Program.cs | 29 ++++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 mark-csharp/Files/2 create mode 100644 mark-csharp/Files/ex8 diff --git a/mark-csharp/Files/2 b/mark-csharp/Files/2 new file mode 100644 index 0000000..d8188da --- /dev/null +++ b/mark-csharp/Files/2 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mark-csharp/Files/ex8 b/mark-csharp/Files/ex8 new file mode 100644 index 0000000000000000000000000000000000000000..5f534afc4ce1b01d7a779c855b32e6da6ebbf7e2 GIT binary patch literal 256 VcmY#pY6xs-oFL9TfstV(0std`12X^s literal 0 HcmV?d00001 diff --git a/mark-csharp/YodaExercises/Program.cs b/mark-csharp/YodaExercises/Program.cs index f14b9dc..6522b47 100644 --- a/mark-csharp/YodaExercises/Program.cs +++ b/mark-csharp/YodaExercises/Program.cs @@ -30,7 +30,8 @@ internal static void Main(string[] args) // Exercise4(); // Exercise5(); // Exercise6(); - Exercise7(); + // Exercise7(); + Exercise8(); } private static void WriteFile(string name, byte[]? contents) @@ -260,4 +261,30 @@ private static void Exercise7() WriteFile("ex7", buffer); RunVm("ex7"); } + + private static void Exercise8() + { + // Load values to this location + byte loadArea = 0x80; + // Write result to this location + byte saveArea = 0x90; + // Define the file number to read values from + byte valuesFile = 2; + // Define the file number to write the result to + byte resultFile = 3; + byte[] program = + [ + // Load from file + OpCode.LoadFromFileII, valuesFile, loadArea, + // Subtract, store result in area to be saved + OpCode.SubMMI, loadArea, (byte)(loadArea + 1), saveArea, + // Save the result to the file + OpCode.SaveToFileIII, resultFile, saveArea, 1 + ]; + + byte[] buffer = new byte[1 + program.Length]; + program.CopyTo(buffer, 0); + WriteFile("ex8", buffer); + RunVm("ex8"); + } } \ No newline at end of file