mirror of
https://github.com/KarolS/millfork.git
synced 2024-05-31 18:41:30 +00:00
72 lines
2.7 KiB
Scala
72 lines
2.7 KiB
Scala
package millfork.output
|
|
|
|
import millfork.error.Logger
|
|
|
|
import scala.collection.mutable
|
|
|
|
/**
|
|
* @author Karol Stasiak
|
|
*/
|
|
class CompiledMemory(bankNames: List[(String, Int)], bankFills: Map[String, Int], bigEndian: Boolean, labels: mutable.Map[String, (String, Int)], log: Logger) {
|
|
var programName = "MILLFORK"
|
|
val banks: mutable.Map[String, MemoryBank] = mutable.Map(bankNames.map{p =>
|
|
val bank = new MemoryBank(p._2, bigEndian)
|
|
bank.fill(bankFills.getOrElse(p._1, 0))
|
|
p._1 -> bank
|
|
}: _*)
|
|
|
|
def getAddress(symbol: String): Int = {
|
|
if (labels.contains(symbol)) {
|
|
labels(symbol)._2
|
|
} else {
|
|
log.error(s"Symbol `$symbol` (used in the output format) is not defined")
|
|
0
|
|
}
|
|
}
|
|
}
|
|
|
|
class MemoryBank(val index: Int, val isBigEndian: Boolean) {
|
|
|
|
def fill(value: Int): Unit = {
|
|
output.indices.foreach(i => output(i) = value.toByte)
|
|
}
|
|
|
|
def readByte(addr: Int): Int = output(addr) & 0xff
|
|
|
|
def readWord(addr: Int): Int =
|
|
if (isBigEndian) readByte(addr + 1) + (readByte(addr) << 8)
|
|
else readByte(addr) + (readByte(addr + 1) << 8)
|
|
|
|
def readMedium(addr: Int): Int =
|
|
if (isBigEndian) readByte(addr + 2) + (readByte(addr + 1) << 8) + (readByte(addr) << 16)
|
|
else readByte(addr) + (readByte(addr + 1) << 8) + (readByte(addr + 2) << 16)
|
|
|
|
def readLong(addr: Int): Int =
|
|
if (isBigEndian) readByte(addr + 3) + (readByte(addr + 2) << 8) + (readByte(addr + 1) << 16) + (readByte(addr) << 24)
|
|
else readByte(addr) + (readByte(addr + 1) << 8) + (readByte(addr + 2) << 16) + (readByte(addr + 3) << 24)
|
|
|
|
def readLongLong(addr: Int): Long =
|
|
if (isBigEndian) readLong(addr).toLong.<<(32) + readLong(addr + 4).&(1L.<<(32).-(1))
|
|
else readLong(addr + 4).toLong.<<(32) + readLong(addr).&(1L.<<(32).-(1))
|
|
|
|
def readWord(addrHi: Int, addrLo: Int): Int = readByte(addrLo) + (readByte(addrHi) << 8)
|
|
|
|
// TODO: use new:
|
|
val output: Array[Byte] = Array.fill[Byte](1 << 16)(0)
|
|
val occupied: Array[Boolean] = Array.fill(1 << 16)(false)
|
|
val initialized: Array[Boolean] = Array.fill(1 << 16)(false)
|
|
val readable: Array[Boolean] = Array.fill(1 << 16)(false)
|
|
val writeable: Array[Boolean] = Array.fill(1 << 16)(false)
|
|
val outputted: Array[Boolean] = Array.fill(1 << 16)(false)
|
|
var start: Int = 0
|
|
var end: Int = 0
|
|
|
|
def markAsOutputted(start: Int, pastEnd: Int): Unit = for (i <- start until pastEnd) outputted(i) = true
|
|
|
|
def initializedNotOutputted: Seq[Int] = (0 until 0x10000).filter(i => initialized(i) && !outputted(i))
|
|
|
|
def dump(startAddr: Int, count: Int)(dumper: String => Any): Unit = {
|
|
(0 until count).map(i => (i + startAddr) -> output(i + startAddr)).grouped(16).zipWithIndex.map { case (c, i) => f"${c.head._1}%04X: " + c.map(i => f"${i._2}%02x").mkString(" ") }.foreach(dumper)
|
|
}
|
|
}
|