Skip to content

Instantly share code, notes, and snippets.

@fujidig
Created May 5, 2021 10:49
Show Gist options
  • Save fujidig/804f85a1393f8a2c5f6b5d0986ccc15a to your computer and use it in GitHub Desktop.
Save fujidig/804f85a1393f8a2c5f6b5d0986ccc15a to your computer and use it in GitHub Desktop.
using System;
namespace ConsoleApp1
{
class Interpreter
{
ushort af;
ushort bc;
ushort de;
ushort hl;
ushort pc;
ushort sp;
bool ime;
byte[] mem;
static string[] REGNAME = { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
static string[] REGNAME2 = { "BC", "DE", "HL", "AF", "SP" };
public Interpreter(byte[] mem_)
{
mem = mem_;
af = bc = de = hl = 0;
sp = 0xfffe;
pc = 0x100;
ime = false;
}
public void RunLoop()
{
for (int i = 0; i < 100; i ++)
{
Run();
}
}
void Run()
{
Console.Write("pc={0:x}: ", pc);
byte insn = read(pc++);
switch (insn)
{
case 0x00:
Console.WriteLine("nop");
break;
case 0xc3:
{
byte lsb = read(pc++);
byte msb = read(pc++);
ushort nn = (ushort)(lsb | (msb << 8));
Console.WriteLine("jp {0:x}", nn);
pc = nn;
break;
}
case 0xf3:
Console.WriteLine("di");
ime = false;
break;
case 0xea:
{
byte lsb = read(pc++);
byte msb = read(pc++);
ushort nn = (ushort)(lsb | (msb << 8));
Console.WriteLine("ld ({0:x}), A", nn);
write(nn, (byte)(af >> 8));
break;
}
case 0x3e:
{
byte n = read(pc++);
Console.WriteLine("ld A, {0:x}", n);
af = (ushort)((n << 8) | (af & 0xff));
break;
}
case 0xe0:
{
byte n = read(pc++);
Console.WriteLine("ldh ({0:x}), A", n);
write((ushort)(0xff00 | n), (byte)(af >> 8));
break;
}
case 0xcd:
{
byte lsb = read(pc++);
byte msb = read(pc++);
ushort nn = (ushort)(lsb | (msb << 8));
Console.WriteLine("call ({0:x})", nn);
write(--sp, (byte)(pc >> 8));
write(--sp, (byte)(pc & 0xff));
pc = nn;
break;
}
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
{
int lhs = (insn >> 3) - 8;
int rhs = insn & 7;
Console.WriteLine("ld {0} {1}", REGNAME[lhs], REGNAME[rhs]);
writereg(lhs, readreg(rhs));
break;
}
case 0x18:
{
sbyte e = (sbyte)read(pc++);
Console.WriteLine("jr {0}", e);
pc = (ushort)(pc + e);
break;
}
case 0xc9:
{
Console.WriteLine("ret");
byte lsb = read(sp++);
byte msb = read(sp++);
pc = (ushort)(msb << 8 | lsb);
break;
}
case 0xc5: case 0xd5: case 0xe5: case 0xf5:
{
int i = (insn >> 4) - 0xc;
Console.WriteLine("push {0}", REGNAME2[i]);
ushort v = readreg2(i);
write(--sp, (byte)(v >> 8));
write(--sp, (byte)(v & 0xff));
break;
}
case 0xc1: case 0xd1: case 0xe1: case 0xf1:
{
int i = (insn >> 4) - 0xc;
Console.WriteLine("pop {0}", REGNAME2[i]);
byte lsb = read(sp++);
byte msb = read(sp++);
writereg2(i, (ushort)(lsb | msb << 8));
break;
}
case 0x03: case 0x13: case 0x23: case 0x33:
{
int i = (insn >> 4);
if (i == 3) i = 4;
Console.WriteLine("inc {0}", REGNAME2[i]);
writereg2(i, (ushort)(readreg2(i) + 1));
break;
}
case 0x2a:
{
Console.WriteLine("ldi a, (hl)");
writereg(7, read(hl));
hl++;
break;
}
case 0x01: case 0x11: case 0x21: case 0x31:
{
int i = (insn >> 4);
if (i == 3) i = 4;
byte lsb = read(pc++);
byte msb = read(pc++);
ushort nn = (ushort)(lsb | (msb << 8));
Console.WriteLine("ld {0}, {1:x}", REGNAME2[i], nn);
writereg2(i, nn);
break;
}
case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
{
int i = insn & 0x7;
Console.WriteLine("or {0}", REGNAME[i]);
writereg(7, (byte)(readreg(7) | readreg(i)));
break;
}
default:
Console.WriteLine("unimplemented insn: {0:x}", insn);
throw new Exception();
}
}
byte read(ushort addr)
{
return mem[addr];
}
void write(ushort addr, byte val)
{
Console.WriteLine("({0:x}) <- {1:x}", addr, val);
mem[addr] = val;
}
byte readreg(int i)
{
switch (i)
{
case 0: return (byte)(bc >> 8);
case 1: return (byte)(bc & 0xff);
case 2: return (byte)(de >> 8);
case 3: return (byte)(de & 0xff);
case 4: return (byte)(hl >> 8);
case 5: return (byte)(hl & 0xff);
case 6: return read(hl);
case 7: return (byte)(af >> 8);
default: throw new Exception("readreg: unknown i");
}
}
void writereg(int i, byte v)
{
switch (i)
{
case 0: bc = (ushort)(v << 8 | (bc & 0xff)); break;
case 1: bc = (ushort)((bc & 0xff00) | v); break;
case 2: de = (ushort)(v << 8 | (de & 0xff)); break;
case 3: de = (ushort)((de & 0xff00) | v); break;
case 4: hl = (ushort)(v << 8 | (hl & 0xff)); break;
case 5: hl = (ushort)((hl & 0xff00) | v); break;
case 6: write(hl, v); break;
case 7: af = (ushort)(v << 8 | (af & 0xff)); break;
default: throw new Exception("writereg: unknown i");
}
}
ushort readreg2(int i)
{
switch (i)
{
case 0: return bc;
case 1: return de;
case 2: return hl;
case 3: return af;
case 4: return sp;
default: throw new Exception("readreg2: unknwon i");
}
}
void writereg2(int i, ushort v)
{
switch (i)
{
case 0: bc = v; break;
case 1: de = v; break;
case 2: hl = v; break;
case 3: af = v; break;
case 4: sp = v; break;
default: throw new Exception("writereg2: unknown i");
}
}
}
}
using System;
using System.IO;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
FileStream fs = new FileStream("C:/Users/Owner/Downloads/cpu_instrs/cpu_instrs/cpu_instrs.gb", FileMode.Open, FileAccess.Read);
int fileSize = (int)fs.Length;
byte[] buf = new byte[fileSize];
fs.Read(buf, 0, fileSize);
Interpreter intp = new Interpreter(buf);
intp.RunLoop();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment