mirror of
https://github.com/mcanlas/6502-opcodes.git
synced 2024-12-22 09:30:45 +00:00
81 lines
2.1 KiB
Scala
81 lines
2.1 KiB
Scala
package com.htmlism.firepower.demo
|
|
|
|
import scala.annotation.tailrec
|
|
import scala.collection.immutable.ListMap
|
|
import scala.util.chaining.*
|
|
|
|
import cats.syntax.all._
|
|
|
|
import com.htmlism.firepower.core.AsmBlock.Intent
|
|
import com.htmlism.firepower.core.*
|
|
|
|
object SnakeEasy6502:
|
|
val program: List[MetaIntent] =
|
|
List(
|
|
init.call,
|
|
loop.call
|
|
)
|
|
|
|
lazy val init =
|
|
Subroutine("init", "initializes values")
|
|
.copy(intents =
|
|
() =>
|
|
List(
|
|
initSnake.call,
|
|
generateApplePosition.call
|
|
)
|
|
)
|
|
|
|
lazy val loop =
|
|
Subroutine("loop", "primary game loop")
|
|
|
|
lazy val initSnake =
|
|
Subroutine("initSnake", "initializes the snake")
|
|
|
|
lazy val generateApplePosition =
|
|
Subroutine("generateApplePosition", "generates the position of the apple")
|
|
|
|
def firstCodeBlock(xs: List[MetaIntent]): AsmBlock.AnonymousCodeBlock =
|
|
AsmBlock
|
|
.AnonymousCodeBlock(xs.map(_.toIntent))
|
|
|
|
def callGraph(xs: List[MetaIntent]): List[AsmBlock.NamedCodeBlock] =
|
|
callGraphRecur(ListMap.empty, xs)
|
|
.values
|
|
.toList
|
|
|
|
@tailrec
|
|
private def callGraphRecur(
|
|
callGraph: ListMap[String, AsmBlock.NamedCodeBlock],
|
|
todo: List[MetaIntent]
|
|
): ListMap[String, AsmBlock.NamedCodeBlock] =
|
|
todo.collect { case x: MetaIntent.Jump => x } match
|
|
case head :: tail =>
|
|
if (callGraph.contains(head.target)) callGraphRecur(callGraph, tail)
|
|
else
|
|
val rts =
|
|
AsmBlock.Intent(
|
|
None,
|
|
List(
|
|
AsmBlock.Intent.Instruction.zero("rts")
|
|
)
|
|
)
|
|
|
|
val sub =
|
|
AsmBlock.NamedCodeBlock(
|
|
head.target,
|
|
head.description.some,
|
|
head.xs.map(_.toIntent) :+ rts
|
|
)
|
|
|
|
// breadth-first expansion
|
|
callGraphRecur(callGraph.updated(head.target, sub), todo ::: head.xs)
|
|
|
|
case Nil =>
|
|
callGraph
|
|
|
|
def assemble(opts: AssemblerOptions): List[String] =
|
|
(firstCodeBlock(program) :: callGraph(program))
|
|
.map(AsmBlock.toLines(opts.instructionCase))
|
|
.pipe(xs => AsmBlock.interFlatMap(xs)(List("", ""), identity))
|