mirror of
https://github.com/KarolS/millfork.git
synced 2024-10-31 14:04:58 +00:00
Add support for ld65 label file format (#128)
This commit is contained in:
parent
73a223b9b6
commit
c9313e5dbe
1
.gitignore
vendored
1
.gitignore
vendored
@ -36,6 +36,7 @@ issue*.mfk
|
|||||||
*.fns
|
*.fns
|
||||||
*.sym
|
*.sym
|
||||||
*.mlb
|
*.mlb
|
||||||
|
*.dbg
|
||||||
*.deb
|
*.deb
|
||||||
*.xex
|
*.xex
|
||||||
*.nes
|
*.nes
|
||||||
|
@ -50,6 +50,8 @@ The extension and the file format are platform-dependent.
|
|||||||
|
|
||||||
* `-G mesen` – format used by the Mesen emulator. The extension is `.mlb`.
|
* `-G mesen` – format used by the Mesen emulator. The extension is `.mlb`.
|
||||||
|
|
||||||
|
* `-G ld65` – a simplified version of the format used by the `ld65` linker (used by CC65 and CA65). The extension is `.dbg`.
|
||||||
|
|
||||||
* `-G raw` – Millfork-specific format. The extension is '.labels'. Each row contains bank number, start address, end address (if known), object type, and Millfork-specific object identifier.
|
* `-G raw` – Millfork-specific format. The extension is '.labels'. Each row contains bank number, start address, end address (if known), object type, and Millfork-specific object identifier.
|
||||||
|
|
||||||
* `-fbreakpoints`, `-fno-breakpoints` –
|
* `-fbreakpoints`, `-fno-breakpoints` –
|
||||||
|
@ -269,3 +269,5 @@ Default: `main,*`
|
|||||||
* `fceux` – multi-file format used by the FCEUX emulator. The extension is `.nl`.
|
* `fceux` – multi-file format used by the FCEUX emulator. The extension is `.nl`.
|
||||||
|
|
||||||
* `mesen` – format used by the Mesen emulator. The extension is `.mlb`.
|
* `mesen` – format used by the Mesen emulator. The extension is `.mlb`.
|
||||||
|
|
||||||
|
* `ld65` – format used by the `ld65` linker. The extension is `.dbg`.
|
||||||
|
@ -3,6 +3,7 @@ package millfork
|
|||||||
import millfork.output.{BankLayoutInFile, FormattableLabel}
|
import millfork.output.{BankLayoutInFile, FormattableLabel}
|
||||||
|
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
import scala.collection.mutable
|
||||||
import scala.util.control.Breaks.{break, breakable}
|
import scala.util.control.Breaks.{break, breakable}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,6 +21,10 @@ object DebugOutputFormat {
|
|||||||
"mlb" -> MesenOutputFormat,
|
"mlb" -> MesenOutputFormat,
|
||||||
"mesen" -> MesenOutputFormat,
|
"mesen" -> MesenOutputFormat,
|
||||||
"asm6f" -> MesenOutputFormat,
|
"asm6f" -> MesenOutputFormat,
|
||||||
|
"ld65" -> Ld65OutputFormat,
|
||||||
|
"ca65" -> Ld65OutputFormat,
|
||||||
|
"cc65" -> Ld65OutputFormat,
|
||||||
|
"dbg" -> Ld65OutputFormat,
|
||||||
"sym" -> SymDebugOutputFormat)
|
"sym" -> SymDebugOutputFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,3 +181,48 @@ object MesenOutputFormat extends DebugOutputFormat {
|
|||||||
|
|
||||||
override def addOutputExtension: Boolean = false
|
override def addOutputExtension: Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Ld65OutputFormat extends DebugOutputFormat {
|
||||||
|
override def formatLine(label: FormattableLabel): String = throw new UnsupportedOperationException()
|
||||||
|
|
||||||
|
override def formatBreakpoint(bank: Int, value: Int): Option[String] = None
|
||||||
|
|
||||||
|
override def fileExtension(bank: Int): String = ".dbg"
|
||||||
|
|
||||||
|
override def filePerBank: Boolean = false
|
||||||
|
|
||||||
|
override def addOutputExtension: Boolean = true
|
||||||
|
|
||||||
|
override def formatAll(b: BankLayoutInFile, labels: Seq[FormattableLabel], breakpoints: Seq[(Int, Int)]): String = {
|
||||||
|
val q = '"'
|
||||||
|
val allBanksInFile = b.allBanks()
|
||||||
|
val allBanks = (labels.map(_.bankName).distinct ++ allBanksInFile).distinct
|
||||||
|
val result = mutable.ListBuffer[String]()
|
||||||
|
result += "version\tmajor=2,minor=0"
|
||||||
|
result += s"info\tcsym=0,file=0,lib=0,line=0,mod=0,scope=1,seg=${allBanks.size},span=0,sym=${labels.size},type=4"
|
||||||
|
for ((bank, ix) <- allBanks.zipWithIndex) {
|
||||||
|
val common = s"seg\tid=${ix},name=$q${bank}$q,start=0x${b.getStart(bank).toHexString},size=0x0,addrsize=absolute"
|
||||||
|
if (allBanksInFile.contains(bank)) {
|
||||||
|
result += common + s",ooffs=${b.ld65Offset(bank)}"
|
||||||
|
} else {
|
||||||
|
result += common
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += "scope\tid=0,name=\"\""
|
||||||
|
for ((label, ix) <- labels.sortBy(l => (l.bankName, l.startValue, l.labelName)).zipWithIndex) {
|
||||||
|
val name = label.labelName.replace('$', '@').replace('.', '@')
|
||||||
|
val sb = new StringBuilder
|
||||||
|
sb ++= s"sym\tid=${ix},name=$q${name}$q,addrsize=absolute,"
|
||||||
|
label.endValue match {
|
||||||
|
case Some(e) =>
|
||||||
|
if (!labels.exists(l => l.ne(label) && l.startValue >= label.startValue && l.startValue <= e)) {
|
||||||
|
sb ++= s"size=${ e - label.startValue + 1 },"
|
||||||
|
}
|
||||||
|
case None =>
|
||||||
|
}
|
||||||
|
sb ++= s"scope=0,val=0x${label.startValue.toHexString},seg=${allBanks.indexOf(label.bankName)},type=lab"
|
||||||
|
result += sb.toString
|
||||||
|
}
|
||||||
|
result.mkString("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -28,5 +28,9 @@ class BankLayoutInFile(startInFile: Map[String, Int], firstAddress: Map[String,
|
|||||||
|
|
||||||
def wasWritten(bank: String): Boolean = startInFile.contains(bank)
|
def wasWritten(bank: String): Boolean = startInFile.contains(bank)
|
||||||
|
|
||||||
def Ld65Offset(bank: String): Int = startInFile(bank)
|
def getStart(bank:String): Int = firstAddress.getOrElse(bank, 0) // ??
|
||||||
|
|
||||||
|
def ld65Offset(bank: String): Int = startInFile(bank)
|
||||||
|
|
||||||
|
def allBanks(): Set[String] = firstAddress.keySet
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user