6502-opcodes/firepower-demo/src/main/scala/com/htmlism/firepower/demo/SnakeEasy6502.scala

81 lines
2.1 KiB
Scala
Raw Normal View History

2022-12-07 15:33:29 +00:00
package com.htmlism.firepower.demo
2022-12-07 22:49:56 +00:00
import scala.annotation.tailrec
import scala.collection.immutable.ListMap
2022-12-07 19:42:03 +00:00
import scala.util.chaining.*
2022-12-07 15:33:29 +00:00
2023-10-03 20:15:10 +00:00
import cats.syntax.all.*
2022-12-07 22:55:54 +00:00
2022-12-07 19:42:03 +00:00
import com.htmlism.firepower.core.*
2024-03-04 14:47:50 +00:00
import com.htmlism.firepower.core.AsmBlock.Intent
2022-12-07 15:33:29 +00:00
object SnakeEasy6502:
2022-12-07 23:12:49 +00:00
val program: List[MetaIntent] =
2022-12-07 19:42:03 +00:00
List(
init.call,
loop.call
)
lazy val init =
2022-12-07 22:55:54 +00:00
Subroutine("init", "initializes values")
2022-12-07 22:49:56 +00:00
.copy(intents =
2022-12-07 23:08:09 +00:00
() =>
List(
2022-12-07 23:19:49 +00:00
initSnake.call,
generateApplePosition.call
2022-12-07 23:08:09 +00:00
)
2022-12-07 22:49:56 +00:00
)
2022-12-07 19:42:03 +00:00
lazy val loop =
2022-12-07 22:55:54 +00:00
Subroutine("loop", "primary game loop")
2022-12-07 19:42:03 +00:00
lazy val initSnake =
2022-12-07 22:55:54 +00:00
Subroutine("initSnake", "initializes the snake")
2022-12-07 19:42:03 +00:00
2022-12-07 23:19:49 +00:00
lazy val generateApplePosition =
Subroutine("generateApplePosition", "generates the position of the apple")
2022-12-07 23:12:49 +00:00
def firstCodeBlock(xs: List[MetaIntent]): AsmBlock.AnonymousCodeBlock =
2022-12-07 19:42:03 +00:00
AsmBlock
2022-12-07 23:12:49 +00:00
.AnonymousCodeBlock(xs.map(_.toIntent))
2022-12-07 19:42:03 +00:00
2022-12-07 23:12:49 +00:00
def callGraph(xs: List[MetaIntent]): List[AsmBlock.NamedCodeBlock] =
2022-12-07 22:49:56 +00:00
callGraphRecur(ListMap.empty, xs)
.values
.toList
@tailrec
private def callGraphRecur(
callGraph: ListMap[String, AsmBlock.NamedCodeBlock],
2022-12-07 23:12:49 +00:00
todo: List[MetaIntent]
2022-12-07 22:49:56 +00:00
): ListMap[String, AsmBlock.NamedCodeBlock] =
2022-12-07 23:12:49 +00:00
todo.collect { case x: MetaIntent.Jump => x } match
2022-12-07 22:49:56 +00:00
case head :: tail =>
2023-10-03 20:15:10 +00:00
if callGraph.contains(head.target) then callGraphRecur(callGraph, tail)
2022-12-07 22:49:56 +00:00
else
2022-12-07 23:19:49 +00:00
val rts =
AsmBlock.Intent(
None,
List(
AsmBlock.Intent.Instruction.zero("rts")
)
)
2022-12-07 22:49:56 +00:00
val sub =
AsmBlock.NamedCodeBlock(
head.target,
2022-12-07 22:55:54 +00:00
head.description.some,
2022-12-07 23:19:49 +00:00
head.xs.map(_.toIntent) :+ rts
2022-12-07 22:49:56 +00:00
)
2022-12-07 23:19:49 +00:00
// breadth-first expansion
2022-12-07 23:08:09 +00:00
callGraphRecur(callGraph.updated(head.target, sub), todo ::: head.xs)
2022-12-07 22:49:56 +00:00
case Nil =>
callGraph
2022-12-07 19:42:03 +00:00
2022-12-07 18:36:57 +00:00
def assemble(opts: AssemblerOptions): List[String] =
2022-12-07 19:42:03 +00:00
(firstCodeBlock(program) :: callGraph(program))
2022-12-07 15:33:29 +00:00
.map(AsmBlock.toLines(opts.instructionCase))
.pipe(xs => AsmBlock.interFlatMap(xs)(List("", ""), identity))