aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/cpu/Cpu.kt
blob: f474dbb7dab8bd04402faa3034569ff81d3bbc42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package cpu

import cpu.opcodes.*
import ram.Ram
import kotlin.concurrent.thread

class Cpu {

  val registers = Registers()
  val ram = Ram()

  var currentOp: Operation? = null
  var nextOp: Operation? = null

  var standardOpcodes: Map<Int, Operation>
  var extendedOpcodes: Map<Int, Operation>
  init {
    val stdCommandGroup: MutableMap<Int, Operation> = mutableMapOf()
    stdCommandGroup.putAll(loads8Bit)
    stdCommandGroup.putAll(loads16Bit)
    stdCommandGroup.putAll(arithmetic8Bit)
    stdCommandGroup.putAll(arithmetic16Bit)
    stdCommandGroup.putAll(misc)
    stdCommandGroup.putAll(rotates)
    stdCommandGroup.putAll(jumps)
    stdCommandGroup.putAll(calls)
    stdCommandGroup.putAll(restarts)
    stdCommandGroup.putAll(returns)
    standardOpcodes = stdCommandGroup.toMap()

    val extCommandGroup: MutableMap<Int, Operation> = mutableMapOf()
    extCommandGroup.putAll(miscExtended)
    extCommandGroup.putAll(rotatesExtended)
    extCommandGroup.putAll(shiftsExtended)
    extCommandGroup.putAll(generateExtendedBitOps())
    extendedOpcodes = extCommandGroup.toMap()

  }

  fun loadRom(rom: ByteArray) {
    ram.load(rom)
  }

  fun executeNextInstruction() {

    val (op, opArgs) = getNextOp()
    op.command.invoke(registers, ram, opArgs)

    currentOp = op
    nextOp = peekNextOp()
  }

  fun run() {
    thread {
      while(true) {
        executeNextInstruction()
      }
    }

  }

  private fun getNextOp(): Pair<Operation, IntArray> {

    var addr = registers.PC
    val startByte = ram.readByte(addr)
    val op: Operation

    op = if(startByte == 0xCB) {
      extendedOpcodes[ram.readByte(++addr)]!!
    } else {
      standardOpcodes[startByte]!!
    }

    val opLength = op.length
    val opArgs = IntArray(opLength)

    IntRange(0, opLength -1).forEach {i ->
      opArgs[i] = ram.readByte(++addr)
    }

    registers.PC = ++addr

    return Pair(op, opArgs)
  }


  private fun peekNextOp(): Operation {

    val startByte = ram.readByte(registers.PC)
    return if(startByte == 0xCB) {
      extendedOpcodes[ram.readByte(registers.PC + 1)]!!
    } else {
      standardOpcodes[startByte]!!
    }
  }

}