6502-opcodes/src/main/scala/com/htmlism/mos6502/dsl/DslDemo.scala

142 lines
3.0 KiB
Scala
Raw Normal View History

2020-08-13 04:16:30 +00:00
package com.htmlism.mos6502.dsl
import scala.collection.mutable.ListBuffer
2020-08-14 20:54:29 +00:00
import cats.implicits._
import com.htmlism._
2020-08-13 04:16:30 +00:00
object DslDemo extends App {
val cpu =
new CPU
import registers.{A, X}
// address demonstration
2020-08-13 04:21:15 +00:00
withAssemblyContext { implicit ctx =>
2020-08-13 04:16:30 +00:00
val payloadLocation =
0x01.z
cpu.A = 0x40
A.add(payloadLocation)
}
// a becomes others
2020-08-13 04:21:15 +00:00
withAssemblyContext { implicit ctx =>
2020-08-13 04:16:30 +00:00
cpu.A = cpu.X
cpu.A = cpu.Y
}
// demonstrate first example
2020-08-13 04:21:15 +00:00
withAssemblyContext { implicit ctx =>
2020-08-13 04:16:30 +00:00
cpu.A = 0xC0
cpu.X = cpu.A
X.incr
A.add(0xc4)
}
2020-08-13 04:42:21 +00:00
// first color example
withAssemblyContext { implicit ctx =>
2020-08-14 02:41:22 +00:00
val scr =
0x0200.indexed
scr(0).write[Color](Color.White)
scr(1).write[Color](Color.Green)
scr(2).write[Color](Color.Orange)
2020-08-13 04:42:21 +00:00
}
2020-08-13 04:21:15 +00:00
def withAssemblyContext(f: AssemblyContext => Unit): Unit = {
val ctx: AssemblyContext =
new AssemblyContext
f(ctx)
2020-08-13 04:16:30 +00:00
ctx.printOut()
println()
println()
}
implicit class AddressOps(n: Int) {
def z: ZeroAddress =
ZeroAddress(n)
def addr: GlobalAddress =
GlobalAddress(n)
2020-08-14 02:41:22 +00:00
def indexed: IndexedAddressCollection =
IndexedAddressCollection(n)
2020-08-13 04:16:30 +00:00
}
}
object registers {
sealed trait Register
sealed trait DestinationA
case object A extends Register {
2020-08-14 20:54:29 +00:00
def add[A](x: A)(implicit ctx: AssemblyContext, ev: Operand[A]): Unit =
ctx.push(ADC, x, s"add ADDR | LITERAL to a")
2020-08-13 04:16:30 +00:00
}
case object X extends Register with DestinationA {
2020-08-14 20:54:29 +00:00
def incr(implicit ctx: AssemblyContext): Unit =
ctx.push(INX, "incr x")
2020-08-13 04:16:30 +00:00
}
case object Y extends Register with DestinationA
}
class CPU {
def A: registers.A.type =
registers.A
2020-08-14 21:13:55 +00:00
def A_=[A](x: A)(implicit ctx: AssemblyContext, ev: Operand[A]): Unit =
2020-08-15 02:02:34 +00:00
ctx.push(LDA, x, "set A to value " + ev.toAddressLiteral(x))
2020-08-13 04:42:21 +00:00
2020-08-13 04:16:30 +00:00
def A_=(reg: registers.DestinationA)(implicit ctx: AssemblyContext): Unit =
2020-08-14 20:54:29 +00:00
reg match {
case registers.X =>
ctx.push(TXA)
case registers.Y =>
ctx.push(TYA)
}
2020-08-13 04:16:30 +00:00
def X: registers.X.type =
registers.X
2020-08-14 20:54:29 +00:00
def X_=(reg: registers.A.type)(implicit ctx: AssemblyContext): Unit =
ctx.push(TAX, s"set x to register $reg")
2020-08-13 04:16:30 +00:00
def Y: registers.Y.type =
registers.Y
def Y_=(reg: registers.A.type)(implicit ctx: AssemblyContext): Unit =
2020-08-14 20:54:29 +00:00
ctx.push(TAY, s"set x to register $reg")
2020-08-13 04:16:30 +00:00
}
class AssemblyContext {
2020-08-14 20:54:29 +00:00
val xs: ListBuffer[Statement] =
2020-08-13 04:16:30 +00:00
ListBuffer()
2020-08-14 20:54:29 +00:00
def push(instruction: Instruction): Unit =
xs.append(UnaryInstruction(instruction, None))
def push(instruction: Instruction, s: String): Unit =
xs.append(UnaryInstruction(instruction, s.some))
2020-08-13 04:30:00 +00:00
2020-08-14 20:54:29 +00:00
def push[A : Operand](instruction: Instruction, x: A): Unit =
xs.append(InstructionWithOperand(instruction, x, None))
2020-08-13 04:30:00 +00:00
2020-08-14 20:54:29 +00:00
def push[A : Operand](instruction: Instruction, x: A, s: String): Unit =
xs.append(InstructionWithOperand(instruction, x: A, s.some))
2020-08-13 04:16:30 +00:00
2020-08-13 04:30:00 +00:00
def printOut(): Unit = {
2020-08-14 21:08:59 +00:00
xs
.map(_.toAsm)
.foreach(println)
2020-08-13 04:30:00 +00:00
}
2020-08-14 20:54:29 +00:00
}