2022-12-06 17:56:29 +00:00
|
|
|
package com.htmlism.firepower.demo
|
|
|
|
|
2022-12-06 19:58:20 +00:00
|
|
|
import scala.collection.immutable._
|
2022-12-06 17:56:29 +00:00
|
|
|
import scala.util.chaining._
|
|
|
|
|
|
|
|
import cats.syntax.all._
|
|
|
|
|
|
|
|
import com.htmlism.firepower.core.AsmBlock._
|
|
|
|
import com.htmlism.firepower.core._
|
|
|
|
|
|
|
|
object PrintThree:
|
2022-12-06 19:58:20 +00:00
|
|
|
case class Move[A: Definable](src: A, dest: String):
|
|
|
|
def defines: Option[ListMap[String, String]] =
|
|
|
|
implicitly[Definable[A]]
|
|
|
|
.table
|
|
|
|
.some
|
2022-12-06 18:43:48 +00:00
|
|
|
|
2022-12-06 19:30:35 +00:00
|
|
|
val program: List[Move[Easy6502.Color]] =
|
2022-12-06 17:56:29 +00:00
|
|
|
List(
|
2022-12-06 19:30:35 +00:00
|
|
|
Move(Easy6502.Color.White, "$0200"),
|
|
|
|
Move(Easy6502.Color.Green, "$0201"),
|
|
|
|
Move(Easy6502.Color.Orange, "$0202")
|
2022-12-06 18:43:48 +00:00
|
|
|
)
|
|
|
|
|
2022-12-06 19:58:20 +00:00
|
|
|
def assemble(opts: AssemblerOptions): String =
|
|
|
|
(defines(opts) ++ codes(opts))
|
|
|
|
.map(AsmBlock.toLines)
|
|
|
|
.pipe(xs => AsmBlock.interFlatMap(xs)(List("", ""), identity))
|
|
|
|
.pipe(str.Line.mkString)
|
|
|
|
|
|
|
|
private def defines(opts: AssemblerOptions) =
|
|
|
|
opts.definitionsMode match
|
|
|
|
case AssemblerOptions.DefinitionsMode.UseLiterals =>
|
|
|
|
Nil
|
|
|
|
|
|
|
|
case AssemblerOptions.DefinitionsMode.UseDefinitions =>
|
|
|
|
program
|
|
|
|
.flatMap(_.defines.toList)
|
|
|
|
.distinct
|
|
|
|
.map { xs =>
|
|
|
|
xs
|
|
|
|
.toList
|
|
|
|
.map { case (k, v) =>
|
|
|
|
s"define $k $v"
|
|
|
|
}
|
|
|
|
.pipe(AsmBlock.CommentBlock(_))
|
|
|
|
}
|
|
|
|
|
|
|
|
case AssemblerOptions.DefinitionsMode.UseDefinitionsWithMath =>
|
|
|
|
program
|
|
|
|
.flatMap(_.defines.toList)
|
|
|
|
.distinct
|
|
|
|
.map { xs =>
|
|
|
|
xs
|
|
|
|
.toList
|
|
|
|
.map { case (k, v) =>
|
|
|
|
s"define $k $v"
|
|
|
|
}
|
|
|
|
.pipe(AsmBlock.CommentBlock(_))
|
|
|
|
}
|
|
|
|
|
|
|
|
private def codes(opts: AssemblerOptions) =
|
2022-12-06 18:43:48 +00:00
|
|
|
program
|
|
|
|
.map { mv =>
|
2022-12-06 19:58:20 +00:00
|
|
|
val argument =
|
|
|
|
opts.definitionsMode match
|
|
|
|
case AssemblerOptions.DefinitionsMode.UseLiterals =>
|
|
|
|
f"#$$${mv.src.toValue}%02X"
|
|
|
|
|
|
|
|
case AssemblerOptions.DefinitionsMode.UseDefinitions |
|
|
|
|
AssemblerOptions.DefinitionsMode.UseDefinitionsWithMath =>
|
|
|
|
mv.src.toDefine
|
2022-12-06 19:30:35 +00:00
|
|
|
|
2022-12-06 18:43:48 +00:00
|
|
|
AsmBlock.Intent(
|
2022-12-06 19:30:35 +00:00
|
|
|
s"${mv.dest} = ${mv.src.toComment}".some,
|
2022-12-06 18:43:48 +00:00
|
|
|
List(
|
2022-12-06 19:58:20 +00:00
|
|
|
AsmBlock.Intent.Instruction(instruction("LDA", opts.instructionCase) + " " + argument, None),
|
|
|
|
AsmBlock.Intent.Instruction(instruction("STA", opts.instructionCase) + " " + mv.dest, None)
|
2022-12-06 17:56:29 +00:00
|
|
|
)
|
|
|
|
)
|
2022-12-06 18:43:48 +00:00
|
|
|
}
|
|
|
|
.pipe(AnonymousCodeBlock(_))
|
|
|
|
.pipe(List(_))
|
|
|
|
|
|
|
|
def instruction(s: String, instructionCase: AssemblerOptions.InstructionCase): String =
|
|
|
|
instructionCase match
|
|
|
|
case AssemblerOptions.InstructionCase.Uppercase =>
|
|
|
|
s.toUpperCase
|
|
|
|
|
|
|
|
case AssemblerOptions.InstructionCase.Lowercase =>
|
|
|
|
s.toLowerCase
|