summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/xmltree.nim3
-rw-r--r--tests/manyloc/gbemulator/cpu.nim393
-rw-r--r--tests/manyloc/gbemulator/cpu.nimrod.cfg2
-rw-r--r--tests/manyloc/gbemulator/gpu.nim110
-rw-r--r--tests/manyloc/gbemulator/mem.nim173
-rw-r--r--tests/manyloc/gbemulator/readme.markdown12
6 files changed, 3 insertions, 690 deletions
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 1a1467e8f..8cf484bfc 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -109,6 +109,7 @@ iterator items*(n: PXmlNode): PXmlNode {.inline.} =
 
 proc attrs*(n: PXmlNode): PXmlAttributes {.inline.} = 
   ## gets the attributes belonging to `n`.
+  ## Returns `nil` if attributes have not been initialised for this node.
   assert n.k == xnElement
   result = n.fAttr
   
@@ -282,5 +283,7 @@ proc child*(n: PXmlNode, name: string): PXmlNode =
 
 proc attr*(n: PXmlNode, name: string): string =
   ## Finds the first attribute of `n` with a name of `name`.
+  ## Returns "" on failure.
   assert n.kind == xnElement
+  if n.attrs == nil: return ""
   return n.attrs[name]
diff --git a/tests/manyloc/gbemulator/cpu.nim b/tests/manyloc/gbemulator/cpu.nim
deleted file mode 100644
index a8346b9ae..000000000
--- a/tests/manyloc/gbemulator/cpu.nim
+++ /dev/null
@@ -1,393 +0,0 @@
-# Part of the Nimrod Gameboy emulator.
-# Copyright (C) Dominik Picheta.
-import mem, gpu
-import strutils
-type
-  # m (machine cycles), t (time cycles).
-  # Ref: http://www.zilog.com/docs/z80/um0080.pdf
-  TClock = tuple[m, t: int]
-
-  PRegister = ref object
-    pc, sp: int32 # 16-bit
-    a, b, c, d, e, H, L, f: int32 # 8-bit
-    clock: TClock
-
-  PCPU = ref object
-    clock: TClock
-    r: PRegister
-    mem: PMem
-
-  TFlagState = enum
-    FUnchanged, FSet, FUnset
-
-const
-  BitZ = 1 shl 7
-  BitN = 1 shl 6
-  BitH = 1 shl 5
-  BitC = 1 shl 4
-
-## Flags
-## -----
-## 0x80 (1 shl 7) - (Zero|Z) Last result was zero.
-## 0x40 (1 shl 6) - (Operation|N) Set if last operation was a subtraction
-## 0x20 (1 shl 5) - (Half carry|H)
-## 0x10 (1 shl 4) - (Carry|C)
-## 0x08 (1 shl 3) - (Sign flag|S)               NOT USED IN GB's Z80
-## 0x04 (1 shl 2) - (Parity/Overflow Flag|P/V)  NOT USED IN GB's Z80
-
-proc newCPU(mem: PMem): PCPU =
-  new(result)
-  new(result.r)
-  result.mem = mem
-
-# Split a 16-bit into 8-bit: let (a, b) = (x shr 8 and 0xff, x and 0xff)
-
-template changeFlag(f: var int32, state: TFlagState, bit: int32)  =
-  case state
-  of FSet:
-    f = f or bit
-  of FUnset:
-    f = f and (not bit)
-  else: assert false
-
-template changeFlags(cpu: PCPU, Z = FUnchanged, N = FUnchanged,
-                     H = FUnchanged, C = FUnchanged) =
-  if Z != FUnchanged: changeFlag(cpu.r.f, Z, BitZ)
-  if N != FUnchanged: changeFlag(cpu.r.f, N, BitN)
-  if H != FUnchanged: changeFlag(cpu.r.f, H, BitH)
-  if C != FUnchanged: changeFlag(cpu.r.f, C, BitC)
-
-template isFSet(cpu: PCPU, bit: int32): bool = (cpu.r.f and bit) != 0
-
-proc `>>`(b: bool): TFlagState =
-  if b: return FSet
-  else: return FUnset
-
-proc `/<</`(v: int32, interval: int): int32 =
-  ## Circular shift 8-bit value left ``interval`` times.
-  let leftMost = v shr (8-interval)
-  result = ((v shl interval) or leftMost).int32
-  result = result and 0xFF
-
-template LDrn(cpu: PCPU, register: expr) {.immediate.} =
-  cpu.r.register = cpu.mem.readByte(cpu.r.pc)
-  inc(cpu.r.pc)
-  cpu.r.clock.m = 2
-
-template PUSHqq(cpu: PCPU, r1, r2: expr) {.immediate.} =
-  cpu.r.sp.dec
-  cpu.mem.writeByte(cpu.r.sp, cpu.r.r1)
-  cpu.r.sp.dec
-  cpu.mem.writeByte(cpu.r.sp, cpu.r.r2)
-  cpu.r.clock.m = 3
-
-template POPqq(cpu: PCPU, r1, r2: expr) {.immediate.} =
-  ## r1 = High, r2 = Low
-  cpu.r.r2 = cpu.mem.readByte(cpu.r.sp)
-  cpu.r.sp.inc
-  cpu.r.r1 = cpu.mem.readByte(cpu.r.sp)
-  cpu.r.sp.inc
-  cpu.r.clock.m = 3
-
-template RLr(cpu: PCPU, register: expr) {.immediate.} =
-  let bit7 = cpu.r.register shl 7
-  let prevCarry = cpu.isFSet(BitC)
-  cpu.r.register = cpu.r.register /<</ 1
-  if prevCarry: cpu.r.register = cpu.r.register or 1 # Set Bit 0
-  else: cpu.r.register = cpu.r.register and (not 1) # Unset bit 0
-  cpu.changeFlags(Z = >>(cpu.r.register == 0), H = FUnset, N = FUnset,
-                  C = >>(bit7 == 1))
-  cpu.r.clock.m = 2
-
-template INCrr(cpu: PCPU, r1, r2: expr, flags = false) {.immediate.} =
-  let x = ((cpu.r.r1 shl 8) or cpu.r.r2) + 1
-  let (hi, low) = (x shr 8 and 0xFF, x and 0xFF)
-  cpu.r.r2 = low; cpu.r.r1 = hi
-  if flags:
-    cpu.changeFlags(Z = >>(x == 0), H = >>((x and 0xF) == 0), N = FUnset)
-    cpu.r.clock.m = 3
-
-template DECr(cpu: PCPU, register: expr) {.immediate.} =
-  cpu.r.register = (cpu.r.register - 1) and 0xFF
-  cpu.changeFlags(Z = >>(cpu.r.register == 0),
-                  H = >>((cpu.r.register and 0xF) == 0xF),
-                  N = FSet)
-  
-  cpu.r.clock.m = 1
-
-proc LDSimple(cpu: PCPU, opcode: int32) =
-  ## All (simple) variants of the LD opcodes end up here.
-  ## Essentially what we want is a register to be copied to another register.
-  
-  case opcode
-  of 0x40 .. 0x45:
-    # LD B, B .. LD B, L
-    # TODO JUST USE A MACRO
-    assert false
-    
-  else: assert false
-
-proc exec(cpu: PCPU) =
-  ## Executes the next instruction
-  let opcode = cpu.mem.readByte(cpu.r.pc)
-  #echo("OPCODE: 0x", toHex(opcode, 2))
-  cpu.r.pc.inc()
-  # PROBLEM: 0x7B is part of some range later but the compiler does not care!
-  case opcode
-  of 0x06:
-    # LD B, n
-    # Load 8-bit immediate into B
-    LDrn(cpu, b)
-  of 0x0E:
-    # LD C, n
-    # Load 8-bit immediate into C.
-    LDrn(cpu, c)
-  of 0x1E:
-    # LD E, n
-    LDrn(cpu, e)
-  of 0x2E:
-    # LD L, n
-    LDrn(cpu, L)
-  of 0x3E:
-    # LD A, n
-    # Load 8-bit immediate into A.
-    LDrn(cpu, a)
-
-  of 0x0C:
-    # INC c
-    # Increment C
-    cpu.r.c = (cpu.r.c + 1) and 0xFF
-    cpu.r.clock.m = 1
-    cpu.changeFlags(Z = >>(cpu.r.c == 0), H = >>((cpu.r.c and 0xF) == 0),
-                    N = FUnset)
-  
-  of 0x03:
-    # INC BC
-    INCrr(cpu, b, c, true)
-  of 0x13:
-    # INC DE
-    INCrr(cpu, d, e, true)
-  of 0x23:
-    # INC HL
-    # Increment 16-bit HL
-    INCrr(cpu, H, L, true)
-  
-  of 0x05:
-    # DEC B
-    # Decrement B
-    DECr(cpu, b)
-  of 0x0D:
-    # DEC C
-    DECr(cpu, c)
-  of 0x1D:
-    # DEC E
-    DECr(cpu, e)
-  of 0x2D:
-    # DEC L
-    DECr(cpu, L)
-  of 0x3D:
-    # DEC A
-    DECr(cpu, a)
-
-  of 0x11:
-    # LD DE, nn
-    # Load 16-bit immediate into DE
-    cpu.r.e = cpu.mem.readByte(cpu.r.pc)
-    cpu.r.d = cpu.mem.readByte(cpu.r.pc+1)
-    cpu.r.pc.inc(2)
-    cpu.r.clock.m = 3
-  
-  of 0x17:
-    # RL A
-    # Rotate A left.
-    RLr(cpu, a)
-  
-  of 0x1A:
-    # LD A, (DE)
-    # Load A from address pointed to by DE
-    cpu.r.a = cpu.mem.readByte((cpu.r.d shl 8) or cpu.r.e)
-    cpu.r.clock.m = 2
-    
-  of 0x20, 0x28:
-    # (0x20) JR NZ, n; Relative jump by signed immediate if last result was not zero
-    # (0x28) JR Z, n; Same as above, but when last result *was* zero.
-    var x = cpu.mem.readByte(cpu.r.pc)
-    if x > 127: x = -(((not x) + 1) and 255)
-    cpu.r.pc.inc
-    cpu.r.clock.m = 2
-    if (opcode == 0x20 and (not isFSet(cpu, BitZ))) or
-       (opcode == 0x28 and isFSet(cpu, BitZ)):
-      cpu.r.pc.inc(x); cpu.r.clock.m.inc 
-  of 0x18:
-    # JR n
-    # Relative jump by signed immediate
-    var x = cpu.mem.readByte(cpu.r.pc)
-    if x > 127: x = -(((not x) + 1) and 255)
-    cpu.r.pc.inc
-    cpu.r.pc.inc(x)
-    cpu.r.clock.m = 3
- 
-  of 0x21:
-    # LD HL, nn
-    # Load 16-bit immediate into (registers) H and L
-    cpu.r.L = cpu.mem.readByte(cpu.r.pc)
-    cpu.r.H = cpu.mem.readByte(cpu.r.pc+1)
-    cpu.r.pc.inc(2)
-    cpu.r.clock.m = 3
-  of 0x22:
-    # LDI (HL), A
-    # Save A to address pointed by HL and increment HL.
-    cpu.mem.writeByte((cpu.r.h shl 8) or cpu.r.l, cpu.r.a)
-    INCrr(cpu, H, L)
-    # TODO: Should flags be changed? (Z80 ref says they should.)
-    # cpu.changeFlags(H = FUnset, N = FUnset)
-    cpu.r.clock.m = 2
-  
-  of 0x31:
-    # LD SP, nn
-    # Load 16-bit immediate into (register) SP
-    cpu.r.sp = cpu.mem.readWord(cpu.r.pc)
-    cpu.r.pc.inc(2)
-    cpu.r.clock.m = 3
-  of 0x32:
-    # LDD (HL), A
-    # Save A to address pointed by HL, and decrement HL
-    cpu.mem.writeByte((cpu.r.h shl 8) or cpu.r.l, cpu.r.a)
-    let x = ((cpu.r.h shl 8) or cpu.r.l) - 1
-    let (hi, low) = (x shr 8 and 0xFF, x and 0xFF)
-    cpu.r.L = low; cpu.r.H = hi
-    # TODO: Should flags be changed? (Z80 ref says they should.)
-    cpu.r.clock.m = 2
-  
-
-  of 0x7B:
-    # LD A, E; Copy E into A
-    cpu.r.a = cpu.r.e
-    cpu.r.clock.m = 1
-    
-  of 0x77:
-    # LD (HL), A
-    # Copy A to address pointed by HL
-    let HL = ((cpu.r.h shl 8) or cpu.r.L)
-    cpu.mem.writeByte(HL, cpu.r.a)
-    cpu.r.clock.m = 2
-  
-  of 0xAF:
-    # XOR A
-    # Logical XOR against (register) A
-    cpu.r.a = (cpu.r.a xor cpu.r.a) and 255 # If result is bigger than 255, will be set to 0
-    cpu.changeFlags(Z = >>(cpu.r.a == 0), H = FUnset, C = FUnset)
-    cpu.r.clock.m = 1
-  
-  of 0xC1:
-    # POP BC
-    # Pop 16-bit value into BC
-    POPqq(cpu, b, c)
-  of 0xD1:
-    # POP DE
-    POPqq(cpu, d, e)
-  of 0xE1:
-    # POP HL
-    POPqq(cpu, H, L)
-  of 0xF1:
-    # POP AF
-    POPqq(cpu, a, f)
-  of 0xC5:
-    # PUSH BC
-    # Push 16-bit BC onto stack.
-    PUSHqq(cpu, b, c)
-  of 0xD5:
-    # PUSH DE
-    PUSHqq(cpu, d, e)
-  of 0xE5:
-    # PUSH HL
-    PUSHqq(cpu, H, L)
-  of 0xF5:
-    # PUSH AF
-    PUSHqq(cpu, a, f)
-  
-  of 0xC9:
-    # RET
-    # Return to calling routine.
-    cpu.r.pc = cpu.mem.readWord(cpu.r.sp)
-    cpu.r.sp.inc(2)
-    cpu.r.clock.m = 3
-  
-  of 0xCB:
-    # Extended Ops
-    let extop = cpu.mem.readByte(cpu.r.pc)
-    cpu.r.pc.inc
-    case extop
-    of 0x11:
-      # RL C
-      # Rotate C left.
-      RLr(cpu, c)
-    of 0x7C:
-      # BIT 7, H
-      # Test whether bit 7 of H is zero
-      cpu.changeFlags(Z = >>((cpu.r.h and (1 shl 7)) == 0), H = FSet, N = FUnset)
-      cpu.r.clock.m = 2
-    else:
-      echo "Unknown extended op: 0x", extop.toHex(2)
-      assert false
-  
-  of 0xCD:
-    # CALL nn
-    # Call routine at 16-bit location
-    cpu.r.sp.dec(2)
-    
-    # We pushing pc+2 onto the stack because the next two bits are used. Below next line.
-    cpu.mem.writeWord(cpu.r.sp, cpu.r.pc+2)
-    cpu.r.pc = cpu.mem.readWord(cpu.r.pc)
-    cpu.r.clock.m = 5
-  of 0xE0:
-    # LDH (0xFF00 + n), A
-    # Save A at address pointed to by (0xFF00 + 8-bit immediate).
-    cpu.mem.writeByte(0xFF00 + cpu.mem.readByte(cpu.r.pc), cpu.r.a)
-    cpu.r.pc.inc
-    cpu.r.clock.m = 3
-  
-  of 0xE2:
-    # LDH (0xFF00 + C), A
-    # Save A at address pointed to by 0xFF00+C
-    cpu.mem.writeByte(0xFF00 + cpu.r.c, cpu.r.a)
-    cpu.r.clock.m = 2
-  
-  of 0xFE:
-    # CP n; compare 8-bit immediate against A.
-    # TODO: This may be wrong. Review.
-    
-    var n = cpu.mem.readByte(cpu.r.pc)
-    var sum = cpu.r.a - n
-    let isNegative = sum < 0
-    sum = sum and 0xFF
-    
-    cpu.r.pc.inc
-    cpu.changeFlags(C = >>isNegative, Z = >>(sum == 0), N = FSet, 
-                    H = >>((sum and 0xF) > (cpu.r.a and 0xF)))
-    cpu.r.clock.m = 2
-  
-  of 0xEA:
-    # LD (nn), A; Save A at given 16-bit address.
-    cpu.mem.writeByte(cpu.mem.readWord(cpu.r.pc), cpu.r.a)
-    cpu.r.pc.inc(2)
-    cpu.r.clock.m = 4
-  
-  of 0x40 .. 0x45, 0x50 .. 0x55, 0x60 .. 0x65, 0x47 .. 0x4D, 0x57 .. 0x5D,
-     0x67 .. 0x6D, 0x78 .. 0x7D, 0x4F, 0x5F, 0x6F, 0x7F:
-    # Simple LD instructions. (Copy register1 to register2)
-    LDSimple(cpu, opcode)
-  
-  else:
-    echo "Unknown opcode: 0x", opcode.toHex(2)
-    assert false
-
-proc next*(cpu: PCPU) =
-  cpu.exec()
-  cpu.mem.gpu.next(cpu.r.clock.m)
-
-
-when isMainModule:
-  var cpu = newCpu(mem.load("/home/dom/code/nimrod/gbemulator/Pokemon_Red.gb"))
-  while True:
-    cpu.next()
\ No newline at end of file
diff --git a/tests/manyloc/gbemulator/cpu.nimrod.cfg b/tests/manyloc/gbemulator/cpu.nimrod.cfg
deleted file mode 100644
index 1119d356b..000000000
--- a/tests/manyloc/gbemulator/cpu.nimrod.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-# This config file marks 'cpu' as the main module.
-
diff --git a/tests/manyloc/gbemulator/gpu.nim b/tests/manyloc/gbemulator/gpu.nim
deleted file mode 100644
index 1f59d7904..000000000
--- a/tests/manyloc/gbemulator/gpu.nim
+++ /dev/null
@@ -1,110 +0,0 @@
-# Part of the Nimrod Gameboy emulator.
-# Copyright (C) Dominik Picheta.
-
-import colors, strutils
-
-type
-  TGPUMode = enum
-    HBlank = 0, VBlank = 1, OAMRead = 2, VRAMRead = 3, 
-
-  TBGTile = enum
-    TileSet0, TileSet1
-  TBGMap = enum
-    TileMap0, TileMap1
-
-  TPaletteKind = enum
-    PaletteBG, PaletteObj, PaletteObj1
-
-  PGPU* = ref object
-    vram*: array[0 .. 8191, int32]
-    mode*: TGPUMode
-    clock: int32
-    line: int
-    palette: array[TPaletteKind, array[0..3, TColor]] # 4 colors. 0-1 (Lightest), 7-8 (Darkest)
-    scrollY, scrollX: int32
-    bgtilemap: TBGMap
-    bgtileset: TBGTile
-
-proc newGPU*(): PGPU =
-  new(result)
-  
-  # Set default palette
-  result.palette[PaletteBG] = [colWhite, rgb(192, 192, 192), rgb(96, 96, 96), colBlack]
-
-proc getTileAddr(gpu: PGPU, index: int32): int =
-  ## Returns the address of the beginning of the tile at ``index``.
-  case gpu.bgtileset
-  of TileSet0:
-    return 0x1000+(index*16) # Each tile is 2 bytes (16 bits)
-  of TileSet1:
-    return 0x0000+(index*16)
-
-proc getTileRow(gpu: PGPU, index: int32): array[0..7, int32] =
-  let tileAddr = getTileAddr(gpu, index)
-  let y = (gpu.line + gpu.scrollY) and 7
-  for px in 0 .. 7:
-    result[px] = gpu.vram[tileAddr+px] or (gpu.vram[tileAddr+px+1] shl 8)
-
-proc renderLine*(gpu: PGPU) =
-  echo("Render Line: ", gpu.line, " scrollX: ", gpu.scrollX, " scrollY: ", gpu.scrollY)
-  var mapOffset = if gpu.bgTileMap == TileMap0: 0x1800 else: 0x1C00
-  # Get the line of tiles to use.
-  mapOffset.inc(((gpu.line + gpu.scrollY) and 0xFF) shr 3)
-  echo("MapOffset: ", mapOffset.toHex(4))  
-  
-  let lineOffset = (gpu.scrollX shr 3) # Which tile to start with in the map line
-  
-  # Get tile index from background map
-  var tileIndex = gpu.vram[mapOffset + lineOffset]
-  
-  echo("Tile index: ", tileIndex)
-  
-  echo("bgtileset: ", gpu.bgtileset)
-
-  
-  let tile = getTileRow(gpu, tileIndex)
-
-  let y = (gpu.line + gpu.scrollY) and 7
-  let x = gpu.scrollX and 7
-  let surfaceOffset = gpu.line * 160 * 4
-
-proc next*(gpu: PGPU, time: int) =
-  gpu.clock.inc(time)
-  #echo("GPU Mode: ", gpu.mode)
-  case gpu.mode
-  of OAMRead:
-    if gpu.clock >= 80:
-      # Enter VRAMRead
-      gpu.mode = VRAMRead
-      gpu.clock = 0
-  of VRAMRead:
-    if gpu.clock >= 172:
-      # Enter HBlank
-      gpu.mode = HBlank
-      gpu.clock = 0
-      
-      # Render scanline
-      gpu.renderLine()
-  of HBlank:
-    if gpu.clock >= 204:
-      gpu.clock = 0
-      gpu.line.inc
-      #echo("HBlank line: ", gpu.line)
-      if gpu.line == 143:
-        # We reached the bottom edge of the screen (screen is 144 pixels in height.)
-        # Enter VBlank
-        gpu.mode = VBlank
-        
-        # TODO: Render surface on screen.
-      else:
-        gpu.mode = OAMRead
-  of VBlank:
-    if gpu.clock >= 456:
-      gpu.clock = 0
-      
-      # TODO: according to ref, line should be increased and, should wait
-      # for line to be greater than 153? then restart the line and mode?
-      echo("Vblank done. Line = ", gpu.line)
-      gpu.mode = OAMRead
-      gpu.line = 0
-      
\ No newline at end of file
diff --git a/tests/manyloc/gbemulator/mem.nim b/tests/manyloc/gbemulator/mem.nim
deleted file mode 100644
index 953f97dfe..000000000
--- a/tests/manyloc/gbemulator/mem.nim
+++ /dev/null
@@ -1,173 +0,0 @@
-# Part of the Nimrod Gameboy emulator.
-# Copyright (C) Dominik Picheta.
-
-import os, strutils, unsigned
-import gpu
-
-type
-  PMem* = ref object
-    rom: string
-    gameName*: string
-    cartType*, romSize*, ramSize*: char
-    bios: array[0 .. 255, int32]    # 255 Bytes
-    extRAM: array[0 .. 8191, int32] # 8KB
-    workRAM: array[0 .. 8191, int32] # 8KB
-    zeroRAM: array[0 .. 127, int32]
-    gpu*: PGPU
-    
-proc hexdump(s: string) =
-  for c in s:
-    stdout.write(c.ord.BiggestInt.toHex(2) & " ")
-  echo("")
-
-const
-  NintendoGraphic =
-    [
-      '\xCE', '\xED', '\x66', '\x66', '\xCC', '\x0D', '\x00', '\x0B',
-      '\x03', '\x73', '\x00', '\x83', '\x00', '\x0C', '\x00', '\x0D',
-      '\x00', '\x08', '\x11', '\x1F', '\x88', '\x89', '\x00', '\x0E',
-      '\xDC', '\xCC', '\x6E', '\xE6', '\xDD', '\xDD', '\xD9', '\x99',
-      '\xBB', '\xBB', '\x67', '\x63', '\x6E', '\x0E', '\xEC', '\xCC',
-      '\xDD', '\xDC', '\x99', '\x9F', '\xBB', '\xB9', '\x33', '\x3E'
-    ]
-  bios = [
-    0x31'i32, 0xFE, 0xFF, 0xAF, 0x21, 0xFF, 0x9F, 0x32, 0xCB, 0x7C, 0x20, 0xFB, 0x21, 0x26, 0xFF, 0x0E,
-    0x11, 0x3E, 0x80, 0x32, 0xE2, 0x0C, 0x3E, 0xF3, 0xE2, 0x32, 0x3E, 0x77, 0x77, 0x3E, 0xFC, 0xE0,
-    0x47, 0x11, 0x04, 0x01, 0x21, 0x10, 0x80, 0x1A, 0xCD, 0x95, 0x00, 0xCD, 0x96, 0x00, 0x13, 0x7B,
-    0xFE, 0x34, 0x20, 0xF3, 0x11, 0xD8, 0x00, 0x06, 0x08, 0x1A, 0x13, 0x22, 0x23, 0x05, 0x20, 0xF9,
-    0x3E, 0x19, 0xEA, 0x10, 0x99, 0x21, 0x2F, 0x99, 0x0E, 0x0C, 0x3D, 0x28, 0x08, 0x32, 0x0D, 0x20,
-    0xF9, 0x2E, 0x0F, 0x18, 0xF3, 0x67, 0x3E, 0x64, 0x57, 0xE0, 0x42, 0x3E, 0x91, 0xE0, 0x40, 0x04,
-    0x1E, 0x02, 0x0E, 0x0C, 0xF0, 0x44, 0xFE, 0x90, 0x20, 0xFA, 0x0D, 0x20, 0xF7, 0x1D, 0x20, 0xF2,
-    0x0E, 0x13, 0x24, 0x7C, 0x1E, 0x83, 0xFE, 0x62, 0x28, 0x06, 0x1E, 0xC1, 0xFE, 0x64, 0x20, 0x06,
-    0x7B, 0xE2, 0x0C, 0x3E, 0x87, 0xF2, 0xF0, 0x42, 0x90, 0xE0, 0x42, 0x15, 0x20, 0xD2, 0x05, 0x20,
-    0x4F, 0x16, 0x20, 0x18, 0xCB, 0x4F, 0x06, 0x04, 0xC5, 0xCB, 0x11, 0x17, 0xC1, 0xCB, 0x11, 0x17,
-    0x05, 0x20, 0xF5, 0x22, 0x23, 0x22, 0x23, 0xC9, 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B,
-    0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E,
-    0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99, 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC,
-    0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E, 0x3c, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x4C,
-    0x21, 0x04, 0x01, 0x11, 0xA8, 0x00, 0x1A, 0x13, 0xBE, 0x20, 0xFE, 0x23, 0x7D, 0xFE, 0x34, 0x20,
-    0xF5, 0x06, 0x19, 0x78, 0x86, 0x23, 0x05, 0x20, 0xFB, 0x86, 0x20, 0xFE, 0x3E, 0x01, 0xE0, 0x50
-  ]
-  
-proc verifyBytes[R](raw: var string, bytes: array[R, char], start: int): bool =
-  result = true
-  for i in 0 .. bytes.high:
-    if raw[i+start] != bytes[i]:
-      return false
-
-proc getBytes(raw: var string, dest: var string, slice: TSlice[int]) =
-  assert slice.a < slice.b
-  assert slice.a > 0
-  let len = slice.b - slice.a
-  dest = newString(len)
-  for i in 0 .. len:
-    dest[i] = raw[slice.a + i]
-
-proc load*(path: string): PMem =
-  new result
-  result.rom = readFile(path)
-  
-  # Verify Nintendo graphic
-  # TODO: Proper exceptions.
-  #doAssert result.rom.verifyBytes(NintendoGraphic, 0x0104)
-  
-  # Gather meta data.
-  result.gameName = result.rom[0x0134 .. 0x0142]
-  echo("Game is: " & result.gameName)
-
-  doAssert result.rom[0x0143].ord != 0x80 # 0x80 here means the ROM is for Color GB.
-  
-  result.cartType = result.rom[0x0147]
-  result.romSize  = result.rom[0x0148]
-  result.ramSize  = result.rom[0x0149]
-  result.bios = bios
-
-  result.GPU = newGPU()
-
-proc reset*(mem: PMem) =
-  for i in 0..mem.extRam.len: mem.extRam[i] = 0
-  for i in 0..mem.workRam.len: mem.workRam[i] = 0
-
-proc readByte*(mem: PMem, address: int32): int32 =
-  if (address in {0x104 .. 0x133}):
-    echo("Bios is accessing the location of the nintendo logo: ", address.toHex(4))
-  case (address and 0xF000)
-  of 0x0000:
-    # BIOS
-    if address > mem.bios.high: return 0 # TODO: Correct?
-    return mem.bios[address]
-  of 0x1000, 0x2000, 0x3000:
-    return mem.rom[address.int].ord
-  of 0x4000, 0x5000, 0x6000, 0x7000:
-    # ROM Bank 1
-  of 0x8000, 0x9000:
-    # VRAM
-    return mem.GPU.vram[address and 0x1FFF]
-  of 0xF000:
-    case address and 0x0F00
-    of 0x0F00:
-      if address > 0xFF7F:
-        return mem.zeroRAM[address and 0x007F]
-      
-      assert false
-    else:
-      assert false
-  else:
-    echo("Read ", address.toHex(4))
-    assert false
-
-proc readWord*(mem: PMem, address: int32): int32 =
-  return readByte(mem, address) or (readByte(mem, address+1) shl 8) 
-
-proc writeByte*(mem: PMem, address: int32, b: int32) =
-  case (address and 0xF000)
-  of 0x8000, 0x9000:
-    # VRAM
-    # Each pixel is 2 bits. VRAM is the tileset.
-    echo("VRAM. Address: 0x", toHex(address, 4), " Value: ", toHex(b, 4))
-    mem.GPU.vram[address and 0x1FFF] = b
-  
-  of 0xF000:
-    case address and 0x0F00
-    of 0x0F00:
-      if address > 0xFF7F:
-        #echo("ZeroRam. Address: ", toHex(address, 4), " Value: ", toHex(b, 4))
-        mem.zeroRAM[address and 0x007F] = b
-        return 
-    
-      case address
-      of 0xFF11:
-        # TODO:
-        echo("Sound Mode 1 register (0xFF11): ", b.toHex(4))
-      of 0xFF26:
-        # TODO:
-        echo("Sound on/off (0xFF26): ", b.toHex(4))
-      of 0xFF47:
-        # TODO:
-        echo("BG Palette (0xFF47): ", b.toHex(4))
-      else:
-        echo("Interrupts. Address: 0x", toHex(Address, 4), " Value: ", toHex(b, 4))
-    else:
-      echo("0xF000. Address: 0x", toHex(Address, 4), " Value: ", toHex(b, 4))
-  
-  else:
-    echo("writeByte. Address: 0x", toHex(address, 4), " Value: ", toHex(b, 4))
-
-proc writeWord*(mem: PMem, address: int32, w: int32) =
-  mem.writeByte(address, w and 255)
-  mem.writeByte(address+1, w shr 8)
-
-when isMainModule:
-  var rom = load("/home/dom/code/nimrod/gbemulator/Pokemon_Red.gb")
-  
-  
-  
-  
-  
-  
-  
-  
-  
-  
-  
-  
\ No newline at end of file
diff --git a/tests/manyloc/gbemulator/readme.markdown b/tests/manyloc/gbemulator/readme.markdown
deleted file mode 100644
index 796191224..000000000
--- a/tests/manyloc/gbemulator/readme.markdown
+++ /dev/null
@@ -1,12 +0,0 @@
-# gbemulator
-
-Inspired by the Rust NES emulator I have decided to write a Gameboy emulator in
-my favourite programming language.
-
-## References
-
-http://www.devrs.com/gb/files/gbspec.txt
-http://www.zilog.com/docs/z80/um0080.pdf
-https://github.com/Two9A/jsGB/blob/master/js
-https://github.com/grantgalitz/GameBoy-Online/blob/master/js/GameBoyCore.js
-http://imrannazar.com/Gameboy-Z80-Opcode-Map
\ No newline at end of file