mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-04 06:28:28 +08:00
Renamed object code to byte code.
This commit is contained in:
parent
924b084db4
commit
2e6b3c9cdb
@ -91,7 +91,7 @@ Features that are in ***bold italics*** are planned but not yet implemented.
|
||||
- ***Spawn NPCs***
|
||||
- ***Reorder actions***
|
||||
|
||||
## Script Object Code
|
||||
## Script Byte Code
|
||||
|
||||
- Disassembler
|
||||
- Assembler
|
||||
|
@ -40,7 +40,7 @@ fun assemble(
|
||||
private class Assembler(private val assembly: List<String>, private val manualStack: Boolean) {
|
||||
private var lineNo = 1
|
||||
private lateinit var tokens: MutableList<Token>
|
||||
private var objectCode: MutableList<Segment> = mutableListOf()
|
||||
private var ir: MutableList<Segment> = mutableListOf()
|
||||
|
||||
/**
|
||||
* The current segment.
|
||||
@ -113,7 +113,7 @@ private class Assembler(private val assembly: List<String>, private val manualSt
|
||||
lineNo++
|
||||
}
|
||||
|
||||
return result.success(objectCode)
|
||||
return result.success(ir)
|
||||
}
|
||||
|
||||
private fun addInstruction(
|
||||
@ -133,7 +133,7 @@ private class Assembler(private val assembly: List<String>, private val manualSt
|
||||
srcLoc = SegmentSrcLoc()
|
||||
)
|
||||
|
||||
objectCode.add(segment!!)
|
||||
ir.add(segment!!)
|
||||
}
|
||||
|
||||
is InstructionSegment -> {
|
||||
@ -172,7 +172,7 @@ private class Assembler(private val assembly: List<String>, private val manualSt
|
||||
srcLoc = SegmentSrcLoc()
|
||||
)
|
||||
|
||||
objectCode.add(segment!!)
|
||||
ir.add(segment!!)
|
||||
}
|
||||
|
||||
is DataSegment -> {
|
||||
@ -200,7 +200,7 @@ private class Assembler(private val assembly: List<String>, private val manualSt
|
||||
srcLoc = SegmentSrcLoc()
|
||||
)
|
||||
|
||||
objectCode.add(segment!!)
|
||||
ir.add(segment!!)
|
||||
}
|
||||
|
||||
is StringSegment -> {
|
||||
@ -260,7 +260,7 @@ private class Assembler(private val assembly: List<String>, private val manualSt
|
||||
val srcLoc = SrcLoc(lineNo, token.col, token.len)
|
||||
|
||||
if (prevLineHadLabel) {
|
||||
val segment = objectCode.last()
|
||||
val segment = ir.last()
|
||||
segment.labels.add(label)
|
||||
segment.srcLoc.labels.add(srcLoc)
|
||||
}
|
||||
@ -274,7 +274,7 @@ private class Assembler(private val assembly: List<String>, private val manualSt
|
||||
srcLoc = SegmentSrcLoc(labels = mutableListOf(srcLoc)),
|
||||
)
|
||||
|
||||
objectCode.add(segment!!)
|
||||
ir.add(segment!!)
|
||||
}
|
||||
|
||||
if (nextToken != null) {
|
||||
@ -293,7 +293,7 @@ private class Assembler(private val assembly: List<String>, private val manualSt
|
||||
data = Buffer.withCapacity(0),
|
||||
srcLoc = SegmentSrcLoc(labels = mutableListOf(srcLoc)),
|
||||
)
|
||||
objectCode.add(segment!!)
|
||||
ir.add(segment!!)
|
||||
}
|
||||
|
||||
if (nextToken != null) {
|
||||
@ -312,7 +312,7 @@ private class Assembler(private val assembly: List<String>, private val manualSt
|
||||
value = "",
|
||||
srcLoc = SegmentSrcLoc(labels = mutableListOf(srcLoc)),
|
||||
)
|
||||
objectCode.add(segment!!)
|
||||
ir.add(segment!!)
|
||||
}
|
||||
|
||||
if (nextToken != null) {
|
||||
@ -509,7 +509,7 @@ private class Assembler(private val assembly: List<String>, private val manualSt
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns true if arguments can be translated to object code, possibly after truncation. False otherwise.
|
||||
* Returns true iff arguments can be translated to byte code, possibly after truncation.
|
||||
*/
|
||||
private fun parseArgs(
|
||||
params: List<Param>,
|
||||
|
@ -100,7 +100,7 @@ enum class SegmentType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Segment of object code. A segment starts with an instruction, byte or string character that is
|
||||
* Segment of byte code. A segment starts with an instruction, byte or string character that is
|
||||
* referenced by one or more labels. The segment ends right before the next instruction, byte or
|
||||
* string character that is referenced by a label.
|
||||
*/
|
||||
|
@ -129,11 +129,11 @@ enum class StackInteraction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Opcode for script object code. Invoked by instructions.
|
||||
* Opcode for script byte code. Invoked by instructions.
|
||||
*/
|
||||
class Opcode(
|
||||
/**
|
||||
* 1- Or 2-byte big-endian representation of this opcode as used in object code.
|
||||
* 1- Or 2-byte big-endian representation of this opcode as used in byte code.
|
||||
*/
|
||||
val code: Int,
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@ class BinFile(
|
||||
val questName: String,
|
||||
val shortDescription: String,
|
||||
val longDescription: String,
|
||||
val objectCode: Buffer,
|
||||
val byteCode: Buffer,
|
||||
val labelOffsets: IntArray,
|
||||
val shopItems: UIntArray,
|
||||
)
|
||||
@ -40,18 +40,18 @@ enum class BinFormat {
|
||||
}
|
||||
|
||||
fun parseBin(cursor: Cursor): BinFile {
|
||||
val objectCodeOffset = cursor.int()
|
||||
val byteCodeOffset = cursor.int()
|
||||
val labelOffsetTableOffset = cursor.int() // Relative offsets
|
||||
val size = cursor.int()
|
||||
cursor.seek(4) // Always seems to be 0xFFFFFFFF.
|
||||
|
||||
val format = when (objectCodeOffset) {
|
||||
val format = when (byteCodeOffset) {
|
||||
DC_GC_OBJECT_CODE_OFFSET -> BinFormat.DC_GC
|
||||
PC_OBJECT_CODE_OFFSET -> BinFormat.PC
|
||||
BB_OBJECT_CODE_OFFSET -> BinFormat.BB
|
||||
else -> {
|
||||
logger.warn {
|
||||
"Object code at unexpected offset $objectCodeOffset, assuming file is a PC file."
|
||||
"Byte code at unexpected offset $byteCodeOffset, assuming file is a PC file."
|
||||
}
|
||||
BinFormat.PC
|
||||
}
|
||||
@ -100,9 +100,9 @@ fun parseBin(cursor: Cursor): BinFile {
|
||||
.seekStart(labelOffsetTableOffset)
|
||||
.intArray(labelOffsetCount)
|
||||
|
||||
val objectCode = cursor
|
||||
.seekStart(objectCodeOffset)
|
||||
.buffer(labelOffsetTableOffset - objectCodeOffset)
|
||||
val byteCode = cursor
|
||||
.seekStart(byteCodeOffset)
|
||||
.buffer(labelOffsetTableOffset - byteCodeOffset)
|
||||
|
||||
return BinFile(
|
||||
format,
|
||||
@ -111,7 +111,7 @@ fun parseBin(cursor: Cursor): BinFile {
|
||||
questName,
|
||||
shortDescription,
|
||||
longDescription,
|
||||
objectCode,
|
||||
byteCode,
|
||||
labelOffsets,
|
||||
shopItems,
|
||||
)
|
||||
|
@ -44,14 +44,14 @@ val BUILTIN_FUNCTIONS = setOf(
|
||||
860,
|
||||
)
|
||||
|
||||
fun parseObjectCode(
|
||||
objectCode: Buffer,
|
||||
fun parseByteCode(
|
||||
byteCode: Buffer,
|
||||
labelOffsets: IntArray,
|
||||
entryLabels: Set<Int>,
|
||||
dcGcFormat: Boolean,
|
||||
lenient: Boolean,
|
||||
): PwResult<List<Segment>> {
|
||||
val cursor = BufferCursor(objectCode)
|
||||
val cursor = BufferCursor(byteCode)
|
||||
val labelHolder = LabelHolder(labelOffsets)
|
||||
val result = PwResultBuilder<List<Segment>>(logger)
|
||||
val offsetToSegment = mutableMapOf<Int, Segment>()
|
||||
@ -138,7 +138,7 @@ fun parseObjectCode(
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check parsed object code.
|
||||
// Sanity check parsed byte code.
|
||||
if (cursor.size != offset) {
|
||||
result.addProblem(
|
||||
Severity.Error,
|
||||
@ -351,7 +351,7 @@ private fun parseSegment(
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
if (lenient) {
|
||||
logger.error(e) { "Couldn't fully parse object code segment." }
|
||||
logger.error(e) { "Couldn't fully parse byte code segment." }
|
||||
} else {
|
||||
throw e
|
||||
}
|
@ -25,7 +25,7 @@ class Quest(
|
||||
val npcs: List<QuestNpc>,
|
||||
val events: List<DatEvent>,
|
||||
val datUnknowns: List<DatUnknown>,
|
||||
val objectCode: List<Segment>,
|
||||
val byteCodeIr: List<Segment>,
|
||||
val shopItems: UIntArray,
|
||||
val mapDesignations: Map<Int, Int>,
|
||||
)
|
||||
@ -59,30 +59,30 @@ fun parseBinDatToQuest(
|
||||
// Initialize NPCs with random episode and correct it later.
|
||||
val npcs = dat.npcs.map { QuestNpc(Episode.I, it.areaId, it.data) }
|
||||
|
||||
// Extract episode and map designations from object code.
|
||||
// Extract episode and map designations from byte code.
|
||||
var episode = Episode.I
|
||||
var mapDesignations = emptyMap<Int, Int>()
|
||||
|
||||
val objectCodeResult = parseObjectCode(
|
||||
bin.objectCode,
|
||||
val parseByteCodeResult = parseByteCode(
|
||||
bin.byteCode,
|
||||
bin.labelOffsets,
|
||||
extractScriptEntryPoints(objects, npcs),
|
||||
bin.format == BinFormat.DC_GC,
|
||||
lenient,
|
||||
)
|
||||
|
||||
rb.addResult(objectCodeResult)
|
||||
rb.addResult(parseByteCodeResult)
|
||||
|
||||
if (objectCodeResult !is Success) {
|
||||
if (parseByteCodeResult !is Success) {
|
||||
return rb.failure()
|
||||
}
|
||||
|
||||
val objectCode = objectCodeResult.value
|
||||
val byteCodeIr = parseByteCodeResult.value
|
||||
|
||||
if (objectCode.isEmpty()) {
|
||||
if (byteCodeIr.isEmpty()) {
|
||||
rb.addProblem(Severity.Warning, "File contains no instruction labels.")
|
||||
} else {
|
||||
val instructionSegments = objectCode.filterIsInstance<InstructionSegment>()
|
||||
val instructionSegments = byteCodeIr.filterIsInstance<InstructionSegment>()
|
||||
|
||||
var label0Segment: InstructionSegment? = null
|
||||
|
||||
@ -117,7 +117,7 @@ fun parseBinDatToQuest(
|
||||
npcs,
|
||||
events = dat.events,
|
||||
datUnknowns = dat.unknowns,
|
||||
objectCode,
|
||||
byteCodeIr,
|
||||
shopItems = bin.shopItems,
|
||||
mapDesignations,
|
||||
))
|
||||
|
@ -9,7 +9,7 @@ import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ObjectCode {
|
||||
class ByteCode {
|
||||
@Test
|
||||
fun minimal() {
|
||||
val buffer = Buffer.fromByteArray(ubyteArrayOf(
|
||||
@ -18,7 +18,7 @@ class ObjectCode {
|
||||
0x01u // ret
|
||||
).toByteArray())
|
||||
|
||||
val result = parseObjectCode(
|
||||
val result = parseByteCode(
|
||||
buffer,
|
||||
labelOffsets = intArrayOf(0),
|
||||
entryLabels = setOf(0),
|
Loading…
Reference in New Issue
Block a user