From 26107026f177700d412c91d5fbe1b5fbd998b309 Mon Sep 17 00:00:00 2001 From: BaronKiko Date: Thu, 14 Feb 2019 14:16:40 +0000 Subject: [PATCH] Lazy with commits, the rest --- .gitignore | 1 + Chup-8.csproj | 7 + Chup-8.sln | 6 + Chup8.cs | 396 ++++++++++++++++++++++++++-- Chup_OGL/Chup_OGL.csproj | 57 ++++ Chup_OGL/OGLWindow.cs | 101 +++++++ Chup_OGL/OpenTK.dll.config | 25 ++ Chup_OGL/Properties/AssemblyInfo.cs | 36 +++ Chup_OGL/WindowManager.cs | 87 ++++++ Chup_OGL/packages.config | 4 + Fonts.cs | 127 +++++++++ OpCode.cs | 45 +++- Program.cs | 4 +- 13 files changed, 870 insertions(+), 26 deletions(-) create mode 100644 Chup_OGL/Chup_OGL.csproj create mode 100644 Chup_OGL/OGLWindow.cs create mode 100644 Chup_OGL/OpenTK.dll.config create mode 100644 Chup_OGL/Properties/AssemblyInfo.cs create mode 100644 Chup_OGL/WindowManager.cs create mode 100644 Chup_OGL/packages.config create mode 100644 Fonts.cs diff --git a/.gitignore b/.gitignore index c590295..bd27cff 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ bin/ obj/ Chup-8.sln.DotSettings.user Chup-8.csproj.user +packages/ diff --git a/Chup-8.csproj b/Chup-8.csproj index ae9d1b0..54f36e6 100644 --- a/Chup-8.csproj +++ b/Chup-8.csproj @@ -44,6 +44,7 @@ + @@ -51,5 +52,11 @@ + + + {62639432-a4d4-4a78-bac4-eda9a6ee3bd0} + Chup_OGL + + \ No newline at end of file diff --git a/Chup-8.sln b/Chup-8.sln index 75457d3..a582cb1 100644 --- a/Chup-8.sln +++ b/Chup-8.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.28307.168 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chup-8", "Chup-8.csproj", "{474ED285-A946-422D-B19B-9148FA5443A0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chup_OGL", "Chup_OGL\Chup_OGL.csproj", "{62639432-A4D4-4A78-BAC4-EDA9A6EE3BD0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {474ED285-A946-422D-B19B-9148FA5443A0}.Debug|Any CPU.Build.0 = Debug|Any CPU {474ED285-A946-422D-B19B-9148FA5443A0}.Release|Any CPU.ActiveCfg = Release|Any CPU {474ED285-A946-422D-B19B-9148FA5443A0}.Release|Any CPU.Build.0 = Release|Any CPU + {62639432-A4D4-4A78-BAC4-EDA9A6EE3BD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {62639432-A4D4-4A78-BAC4-EDA9A6EE3BD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {62639432-A4D4-4A78-BAC4-EDA9A6EE3BD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {62639432-A4D4-4A78-BAC4-EDA9A6EE3BD0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Chup8.cs b/Chup8.cs index 92c716e..dfb62f6 100644 --- a/Chup8.cs +++ b/Chup8.cs @@ -1,15 +1,16 @@ -using System; -using System.Collections.Generic; +using Chup_OGL; +using System; +using System.Diagnostics; using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; +using System.Threading; namespace Chup_8 { public class Chup8 { - Random rnd = new Random(); + Random rnd = new Random(); + Stopwatch sw = new Stopwatch(); private ushort PC; private byte[] Memory; @@ -18,27 +19,98 @@ public class Chup8 private ushort StackPointer; private ushort[] Stack; - public Chup8(string FilePath) + public ulong[] Display; + private int DisplayMode; + private int DisplayWidth, DisplayHeight; + + private bool[] keys; + + private byte DelayTimer; + private byte SoundTimer; + private long lastTime, lastStep; + + private WindowManager wm; + + private bool redrawNeeded = true; + private bool RendorToConsole = false; + + public Chup8(string FilePath, int displayMode) { + if (RendorToConsole) + Console.OutputEncoding = Encoding.UTF8; + else + wm = new WindowManager(); + // Init variables PC = 0x200; Memory = new byte[4096]; V = new byte[16]; + + // Stack StackPointer = 0; Stack = new ushort[16]; + // Init display + DisplayMode = displayMode; + if (displayMode == 0) + { + DisplayWidth = 64; + DisplayHeight = 32; + + Display = new ulong[DisplayHeight]; + } + else + throw new Exception($"Unsupported Display Mode {displayMode}"); + + // Init Timers + DelayTimer = 0; + SoundTimer = 0; + lastTime = 0; + lastStep = 0; + sw.Start(); + //Load the ROM byte[] FileData = File.ReadAllBytes(FilePath); for (int Index = 0; Index < FileData.Length; ++Index) Memory[Index + 0x200] = FileData[Index]; + + // Load fonts + Fonts.LoadFonts(ref Memory); } - public void Run() + public void Run(int frequency) { while (true) - Step(); + { + if (sw.ElapsedMilliseconds - lastStep > 1000.0 / frequency) + { + keys = wm.GetKeys(); + Step(); + lastStep = sw.ElapsedMilliseconds; + } + + if (sw.ElapsedMilliseconds - lastTime > 1000.0 / 60) + { + if (DelayTimer > 0) + DelayTimer--; + + if (SoundTimer > 0) + SoundTimer--; + + lastTime = sw.ElapsedMilliseconds; + } + + if (redrawNeeded) + { + if (RendorToConsole) + DrawDisplay(); + else + wm.DrawFrame(Display); + redrawNeeded = false; + } + } } @@ -50,21 +122,73 @@ private void Push(ushort value) public ushort Pop() { - return Stack[StackPointer--]; + return Stack[--StackPointer]; } - private void Step() + private void DrawDisplay() + { + string output = ""; + + for (int i = 0; i < 32; i++) + { + ulong mask = (ulong)1 << 63; + + for (int x = 0; x < 64; x++) + { + output += ((Display[i] & mask) == 0) ? " " : "\u2588"; + mask >>= 1; + } + + output += '\n'; + } + + Console.SetCursorPosition(0, 0); + Console.Clear(); + Console.Write(output); + } + + + private bool DrawByte(int x, int y, byte draw) + { + bool collision = false; + + for (int i = 0; i < 8; i++) + { + if ((draw & (1 << (8 - i - 1))) == 0) + continue; + + int destX = (x + i) % DisplayWidth; + ulong bitmask = ((ulong)1) << (DisplayWidth - destX - 1); + + // Get current displayed pixel + if ((Display[y] & bitmask) != 0) + collision = true; + + Display[y] ^= bitmask; + } + + redrawNeeded = true; + + return collision; + } + + public void Step() { ushort instruction = (ushort)(Memory[PC] << 8 | Memory[PC + 1]); + PC += 2; // Complete instructions switch ((OpCode)instruction) { case OpCode.Clear: - //TODO: Clear graphics - PC += 2; - break; + for (int i = 0; i < Display.Length; i++) + Display[i] = 0; + return; + + case OpCode.RET: + PC = Pop(); + return; } // Opcodes @@ -77,20 +201,254 @@ private void Step() // 2nnn case OpCode.CALL: - Push((ushort)(PC + 2)); + Push((ushort)(PC)); PC = (ushort)(instruction & 0xFFF); break; - //Cxkk - case OpCode.RND: - V[(instruction & 0x0F00) >> 8] = (byte)(rnd.Next() & instruction); - PC += 2; + // 3xkk + case OpCode.SKIP: + if (V[(instruction & 0x0F00) >> 8] == (byte)instruction) + PC += 2; + break; + + // 4xkk + case OpCode.NSKIP: + if (V[(instruction & 0x0F00) >> 8] != (byte)instruction) + PC += 2; + break; + + // 5xy0 + case OpCode.SKIPR: + if (V[(instruction & 0x0F00) >> 8] == V[(instruction & 0x00F0) >> 4]) + PC += 2; + break; + + // 6xkk + case OpCode.LDRC: + V[(instruction & 0x0F00) >> 8] = (byte)instruction; + break; + + // 7xkk + case OpCode.ADDRC: + V[(instruction & 0x0F00) >> 8] += (byte)instruction; + break; + + case OpCode.HEX8: + Run8(instruction); + break; + + // 9xy0 + case OpCode.NSKIPR: + if (V[(instruction & 0x0F00) >> 8] != V[(instruction & 0x0F0) >> 4]) + PC += 2; break; // Annn case OpCode.LDI: I = (ushort)(instruction & 0x0FFF); - PC += 2; + break; + + // Bnnn + case OpCode.JUMPO: + PC = (ushort)((ushort)(instruction & 0xFFF) + V[0]); + break; + + // Cxkk + case OpCode.RND: + V[(instruction & 0x0F00) >> 8] = (byte)(rnd.Next() & instruction); + break; + + // Dxyn + case OpCode.DRAW: + byte x = V[(instruction & 0xF00) >> 8]; + byte y = V[(instruction & 0x0F0) >> 4]; + byte len = (byte)(instruction & 0x00F); + int end = I + len; + + // Set collision to 0 + byte vf = 0; + + for (int pos = I; pos < end; pos++) + { + if (DrawByte(x, y++ % DisplayHeight, Memory[pos])) + vf = 1; + } + + V[0xF] = vf; + + break; + + // Ex9E + // ExA1 NOT skip + case OpCode.SKIPKEY: + bool state = keys[V[(instruction & 0x0F00) >> 8]]; + + if ((byte)instruction == 0xA1) + state = !state; + + if (state) + PC += 2; + + break; + + case OpCode.F: + RunF(instruction); + break; + + default: + throw new Exception($"Instruction [0x{instruction:X4}] is unknown!"); + } + } + + private void Run8(ushort instruction) + { + byte vf; + + int x = (instruction & 0x0F00) >> 8; + int y = (instruction & 0x00F0) >> 4; + + switch ((OpCode)(instruction & 0xF)) + { + // 8xy0 + case OpCode.LDRR: + V[x] = V[y]; + break; + + // 8xy1 + case OpCode.ORRR: + V[x] |= V[y]; + break; + + // 8xy2 + case OpCode.ANDRR: + V[x] &= V[y]; + break; + + // 8xy3 + case OpCode.XORRR: + V[x] ^= V[y]; + break; + + // 8xy4 + case OpCode.ADDRR: + int temp = V[x] + V[y]; + vf = (byte)((temp >> 8) & 1); + V[x] = (byte)temp; + V[0xF] = vf; + break; + + // 8xy5 + case OpCode.SUBRR: + vf = (byte)((V[x] > V[y]) ? 1 : 0); + V[x] -= V[y]; + V[0xF] = vf; + break; + + // 8x06 + case OpCode.SHR: + vf = (byte)(V[x] & 1); + V[x] >>= 1; + V[0xF] = vf; + break; + + // 8xy7 + case OpCode.SUBRRN: + vf = (byte)((V[y] > V[x]) ? 1 : 0); + V[x] -= V[y]; + V[0xF] = vf; + break; + + // 8x0E + case OpCode.SHL: + vf = (byte)((V[x] >> 7) & 1); + V[x] <<= 1; + V[0xF] = vf; + break; + + default: + throw new Exception($"Instruction [0x{instruction:X4}] is unknown!"); + } + } + + private void RunF(ushort instruction) + { + int count; + + switch ((OpCode) (instruction & 0xFF)) + { + // 0xFx07 + case OpCode.GETDELAY: + V[(instruction & 0x0F00) >> 8] = DelayTimer; + break; + + // 0xFx0A + case OpCode.WAITKEY: + byte key = 0xFF; + while (key == 0xFF) + { + bool[] keys = wm.GetKeys(); + for (byte i = 0; i < 16; i++) + { + if (keys[i]) + { + key = i; + break; + } + } + + if (key == 0xFF) + Thread.Sleep(1); + } + + V[(instruction & 0x0F00) >> 8] = key; + + break; + + // Fx15 + case OpCode.SETDELAY: + DelayTimer = V[(instruction & 0x0F00) >> 8]; + break; + + // Fx18 + case OpCode.SETSOUND: + SoundTimer = V[(instruction & 0x0F00) >> 8]; + break; + + // Fx1E + case OpCode.ADDIR: + I += V[(instruction & 0x0F00) >> 8]; + break; + + // Fx29 + case OpCode.LDFT: + I = (ushort)(V[(instruction & 0x0F00) >> 8] * 5); + break; + + // Fx33 + case OpCode.LDBCD: + byte value = V[(instruction & 0x0F00) >> 8]; + + Memory[I] = (byte)((value / 100) % 10); + Memory[I + 1] = (byte)((value / 10) % 10); + Memory[I + 2] = (byte)(value % 10); + break; + + // Fx55 + case OpCode.LDRANGE: + count = ((instruction & 0x0F00) >> 8) + 1; + + for (int i = 0; i < count; i++) + Memory[I + i] = V[i]; + + break; + + // Fx65 + case OpCode.RDRANGE: + count = ((instruction & 0x0F00) >> 8) + 1; + + for (int i = 0; i < count; i++) + V[i] = Memory[I + i]; + break; default: diff --git a/Chup_OGL/Chup_OGL.csproj b/Chup_OGL/Chup_OGL.csproj new file mode 100644 index 0000000..45d06c7 --- /dev/null +++ b/Chup_OGL/Chup_OGL.csproj @@ -0,0 +1,57 @@ + + + + + Debug + AnyCPU + {62639432-A4D4-4A78-BAC4-EDA9A6EE3BD0} + Library + Properties + Chup_OGL + Chup_OGL + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\OpenTK.3.0.1\lib\net20\OpenTK.dll + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Chup_OGL/OGLWindow.cs b/Chup_OGL/OGLWindow.cs new file mode 100644 index 0000000..344fb0d --- /dev/null +++ b/Chup_OGL/OGLWindow.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; + +namespace Chup_OGL +{ + public class OGLWindow : GameWindow + { + private bool ViewportUpdated; + + public uint[] data; + private int viewTexture; + + public OGLWindow() + : base(1280, 720) + { + Title = "Chup-8"; + + VSync = VSyncMode.On; + Visible = true; + ViewportUpdated = true; + + viewTexture = GL.GenTexture(); + + // Release context for render thread + Context.MakeCurrent(null); + } + + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + + ViewportUpdated = true; + } + + public void Update() + { + ProcessEvents(); + } + + public void Draw() + { + // Update viewport + if (ViewportUpdated) + { + GL.Viewport(0, 0, Width, Height); + + GL.MatrixMode(MatrixMode.Projection); + GL.LoadIdentity(); + GL.Ortho(0, Width, 0, Height, 0.0, 4.0); + + ViewportUpdated = false; + } + + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + GL.ClearColor(Color.Black); + + // Convert raw data into texture + GL.BindTexture(TextureTarget.Texture2D, viewTexture); + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Clamp); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp); + + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, 64, 32, 0, PixelFormat.Rgba, PixelType.UnsignedInt8888, data); + + // Enable blending and textures + GL.Enable(EnableCap.Texture2D); + GL.Enable(EnableCap.Blend); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + + // Draw texture + GL.Color3(Color.White); + GL.Begin(PrimitiveType.Triangles); + + GL.TexCoord2(0, 1); GL.Vertex2(0, 0); + GL.TexCoord2(0, 0); GL.Vertex2(0, Height); + GL.TexCoord2(1, 0); GL.Vertex2(Width, Height); + + GL.TexCoord2(1, 0); GL.Vertex2(Width, Height); + GL.TexCoord2(1, 1); GL.Vertex2(Width, 0); + GL.TexCoord2(0, 1); GL.Vertex2(0, 0); + + GL.End(); + + // Cleanup for caller + GL.BindTexture(TextureTarget.Texture2D, 0); + GL.Disable(EnableCap.Texture2D); + GL.Disable(EnableCap.Blend); + + SwapBuffers(); + } + } +} diff --git a/Chup_OGL/OpenTK.dll.config b/Chup_OGL/OpenTK.dll.config new file mode 100644 index 0000000..7098d39 --- /dev/null +++ b/Chup_OGL/OpenTK.dll.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Chup_OGL/Properties/AssemblyInfo.cs b/Chup_OGL/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..29a68e3 --- /dev/null +++ b/Chup_OGL/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Chup_OGL")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Chup_OGL")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("62639432-a4d4-4a78-bac4-eda9a6ee3bd0")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Chup_OGL/WindowManager.cs b/Chup_OGL/WindowManager.cs new file mode 100644 index 0000000..f7d5839 --- /dev/null +++ b/Chup_OGL/WindowManager.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using OpenTK.Input; + +namespace Chup_OGL +{ + public class WindowManager + { + private OGLWindow window; + private Thread renderThread; + private Thread mainThread; + private bool running; + + public WindowManager() + { + mainThread = new Thread(() => + { + window = new OGLWindow(); + running = true; + + while (running) + { + window.Update(); + Thread.Sleep(1); + } + }); + mainThread.Start(); + + while (!running) + Thread.Sleep(1); + } + + public void DrawFrame(ulong[] frame) + { + uint[] data = new uint[64 * 32]; + for (int y = 0; y < 32; y++) + { + ulong line = frame[y]; + for (int x = 0; x < 64; x++) + { + data[y * 64 + 63 - x] = ((line & 1) == 0) ? 0x000000FF : 0xFFFFFFFF; + line >>= 1; + } + } + + window.data = data; + + window.Context.MakeCurrent(window.WindowInfo); + window.Draw(); + } + + private Key[] keys = new Key[16] + { + Key.X, // 0 + Key.Number1, // 1 + Key.Number2, // 2 + Key.Number3, // 3 + Key.Q, // 4 + Key.W, // 5 + Key.E, // 6 + Key.A, // 7 + Key.S, // 8 + Key.D, // 9 + Key.Z, // A + Key.C, // B + Key.Number4, // C + Key.R, // D + Key.F, // E + Key.V, // F + }; + + public bool[] GetKeys() + { + var state = Keyboard.GetState(); + bool[] states = new bool[16]; + + for (int i = 0; i < 16; i++) + states[i] = state.IsKeyDown(keys[i]); + + return states; + } + } +} diff --git a/Chup_OGL/packages.config b/Chup_OGL/packages.config new file mode 100644 index 0000000..14a78f8 --- /dev/null +++ b/Chup_OGL/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Fonts.cs b/Fonts.cs new file mode 100644 index 0000000..ef9f4da --- /dev/null +++ b/Fonts.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chup_8 +{ + public static class Fonts + { + public static void LoadFonts(ref byte[] memory) + { + // 0 + memory[0] = 0xF0; + memory[1] = 0x90; + memory[2] = 0x90; + memory[3] = 0x90; + memory[4] = 0xF0; + + // 1 + memory[5] = 0x20; + memory[6] = 0x60; + memory[7] = 0x20; + memory[8] = 0x20; + memory[9] = 0x70; + + // 2 + memory[10] = 0xF0; + memory[11] = 0x10; + memory[12] = 0xF0; + memory[13] = 0x80; + memory[14] = 0xF0; + + // 3 + memory[15] = 0xF0; + memory[16] = 0x10; + memory[17] = 0xF0; + memory[18] = 0x10; + memory[19] = 0xF0; + + // 4 + memory[20] = 0x90; + memory[21] = 0x90; + memory[22] = 0xF0; + memory[23] = 0x10; + memory[24] = 0x10; + + // 5 + memory[25] = 0x90; + memory[26] = 0x90; + memory[27] = 0xF0; + memory[28] = 0x10; + memory[29] = 0x10; + + // 6 + memory[30] = 0xF0; + memory[31] = 0x80; + memory[32] = 0xF0; + memory[33] = 0x90; + memory[34] = 0xF0; + + // 7 + memory[35] = 0xF0; + memory[36] = 0x10; + memory[37] = 0x20; + memory[38] = 0x40; + memory[39] = 0x40; + + // 8 + memory[40] = 0xF0; + memory[41] = 0x90; + memory[42] = 0xF0; + memory[43] = 0x90; + memory[44] = 0xF0; + + + // 9 + memory[45] = 0xF0; + memory[46] = 0x90; + memory[47] = 0xF0; + memory[48] = 0x10; + memory[49] = 0xF0; + + // A + memory[50] = 0xF0; + memory[51] = 0x90; + memory[52] = 0xF0; + memory[53] = 0x90; + memory[54] = 0x90; + + // B + memory[55] = 0xE0; + memory[56] = 0x90; + memory[57] = 0xE0; + memory[58] = 0x90; + memory[59] = 0xE0; + + // C + memory[60] = 0xF0; + memory[61] = 0x80; + memory[62] = 0x80; + memory[63] = 0x80; + memory[64] = 0xF0; + + // D + memory[65] = 0xE0; + memory[66] = 0x90; + memory[67] = 0x90; + memory[68] = 0x90; + memory[69] = 0xE0; + + // E + memory[70] = 0xF0; + memory[71] = 0x80; + memory[72] = 0xF0; + memory[73] = 0x80; + memory[74] = 0xF0; + + // F + memory[75] = 0xF0; + memory[76] = 0x80; + memory[77] = 0xF0; + memory[78] = 0x80; + memory[79] = 0x80; + } + } +} diff --git a/OpCode.cs b/OpCode.cs index 6ca9299..1cda19d 100644 --- a/OpCode.cs +++ b/OpCode.cs @@ -2,10 +2,45 @@ { public enum OpCode { - Clear = 0x00E0, - JP = 0x1000, - CALL = 0x2000, - LDI = 0xA000, - RND = 0xC000, + Clear = 0x00E0, + RET = 0x00EE, + JP = 0x1000, + CALL = 0x2000, + SKIP = 0x3000, + NSKIP = 0x4000, + SKIPR = 0x5000, + LDRC = 0x6000, + ADDRC = 0x7000, + NSKIPR = 0x9000, + LDI = 0xA000, + JUMPO = 0xB000, + RND = 0xC000, + DRAW = 0xD000, + SKIPKEY = 0xE000, + + // 8 + HEX8 = 0x8000, + LDRR = 0x0000, + ORRR = 0x0001, + ANDRR = 0x0002, + XORRR = 0x0003, + ADDRR = 0x0004, + SUBRR = 0x0005, + SHR = 0x0006, + SUBRRN = 0x0007, + SHL = 0x000E, + + + // F + F = 0xF000, + GETDELAY = 0x0007, + WAITKEY = 0x000A, + SETDELAY = 0x0015, + SETSOUND = 0x0018, + ADDIR = 0x001E, + LDFT = 0x0029, + LDBCD = 0x0033, + LDRANGE = 0x0055, + RDRANGE = 0x0065, } } diff --git a/Program.cs b/Program.cs index 2b9df5b..c95ec85 100644 --- a/Program.cs +++ b/Program.cs @@ -10,8 +10,8 @@ class Program { static void Main(string[] args) { - Chup8 chup8 = new Chup8(args[0]); - chup8.Run(); + Chup8 chup8 = new Chup8(args[0], 0); + chup8.Run(1000); } } }