mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-12-26 04:32:05 +00:00
Much better error and warning pinpointing during pack process.
This commit is contained in:
parent
a480dc8c96
commit
c43f381296
3
.gitignore
vendored
3
.gitignore
vendored
@ -25,3 +25,6 @@
|
|||||||
/Platform/Apple/tools/PLASMA/src/plvm
|
/Platform/Apple/tools/PLASMA/src/plvm
|
||||||
/Platform/Apple/tools/PLASMA/src/PLVM02.SYSTEM.sys
|
/Platform/Apple/tools/PLASMA/src/PLVM02.SYSTEM.sys
|
||||||
/Platform/Apple/tools/PLASMA/src/*#*
|
/Platform/Apple/tools/PLASMA/src/*#*
|
||||||
|
|
||||||
|
# Packer sometimes produces an error text file.
|
||||||
|
error_stack.txt
|
||||||
|
@ -50,6 +50,47 @@ class PackPartitions
|
|||||||
|
|
||||||
def javascriptOut = null
|
def javascriptOut = null
|
||||||
|
|
||||||
|
def currentContext = []
|
||||||
|
def nWarnings = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep track of context within the XML file, so we can spit out more useful
|
||||||
|
* error and warning messages.
|
||||||
|
*/
|
||||||
|
def withContext(name, closure)
|
||||||
|
{
|
||||||
|
def threw = false
|
||||||
|
try {
|
||||||
|
currentContext << name
|
||||||
|
closure()
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
threw = true
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
// Preserve context in the case of an exception
|
||||||
|
if (!threw)
|
||||||
|
currentContext.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def getContextStr()
|
||||||
|
{
|
||||||
|
return currentContext.join(" -> ")
|
||||||
|
}
|
||||||
|
|
||||||
|
def printError(str)
|
||||||
|
{
|
||||||
|
System.out.format("Error in ${getContextStr()}: %s\n", str)
|
||||||
|
}
|
||||||
|
|
||||||
|
def printWarning(str)
|
||||||
|
{
|
||||||
|
System.out.format("Warning in ${getContextStr()}: %s\n", str)
|
||||||
|
++nWarnings
|
||||||
|
}
|
||||||
|
|
||||||
def parseMap(map, tiles)
|
def parseMap(map, tiles)
|
||||||
{
|
{
|
||||||
// Parse each row of the map
|
// Parse each row of the map
|
||||||
@ -460,7 +501,7 @@ class PackPartitions
|
|||||||
texMap[id] |= 0x80; // hi-bit flag to mark sprite cells
|
texMap[id] |= 0x80; // hi-bit flag to mark sprite cells
|
||||||
}
|
}
|
||||||
else if (id) {
|
else if (id) {
|
||||||
println "Warning: can't match tile name '$name' to any image; treating as blank."
|
printWarning("can't match tile name '$name' to any image; treating as blank.")
|
||||||
texMap[id] = 0
|
texMap[id] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -559,7 +600,7 @@ class PackPartitions
|
|||||||
{
|
{
|
||||||
def num = frames.size() + 1
|
def num = frames.size() + 1
|
||||||
def name = imgEl.@name ?: "img$num"
|
def name = imgEl.@name ?: "img$num"
|
||||||
println "Packing frame image #$num named '${imgEl.@name}'."
|
//println "Packing frame image #$num named '${imgEl.@name}'."
|
||||||
def buf = parseFrameData(imgEl)
|
def buf = parseFrameData(imgEl)
|
||||||
frames[imgEl.@name] = [num:num, buf:buf]
|
frames[imgEl.@name] = [num:num, buf:buf]
|
||||||
return buf
|
return buf
|
||||||
@ -620,12 +661,14 @@ class PackPartitions
|
|||||||
{
|
{
|
||||||
def name = mapEl.@name ?: "map$num"
|
def name = mapEl.@name ?: "map$num"
|
||||||
def num = mapNames[name][1]
|
def num = mapNames[name][1]
|
||||||
println "Packing 3D map #$num named '$name'."
|
//println "Packing 3D map #$num named '$name'."
|
||||||
def (scriptModule, locationsWithTriggers) = packScripts(mapEl, name)
|
withContext("map '$name'") {
|
||||||
def rows = parseMap(mapEl, tileEls)
|
def (scriptModule, locationsWithTriggers) = packScripts(mapEl, name)
|
||||||
def buf = ByteBuffer.allocate(50000)
|
def rows = parseMap(mapEl, tileEls)
|
||||||
write3DMap(buf, name, rows, scriptModule, locationsWithTriggers)
|
def buf = ByteBuffer.allocate(50000)
|
||||||
maps3D[name] = [num:num, buf:buf]
|
write3DMap(buf, name, rows, scriptModule, locationsWithTriggers)
|
||||||
|
maps3D[name] = [num:num, buf:buf]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def packScripts(mapEl, mapName)
|
def packScripts(mapEl, mapName)
|
||||||
@ -636,7 +679,7 @@ class PackPartitions
|
|||||||
module.packScripts(mapEl.scripts[0])
|
module.packScripts(mapEl.scripts[0])
|
||||||
def num = modules.size() + 1
|
def num = modules.size() + 1
|
||||||
def name = "mapScript$num"
|
def name = "mapScript$num"
|
||||||
println "Packing scripts for map $mapName, to module $num."
|
//println "Packing scripts for map $mapName, to module $num."
|
||||||
modules[name] = [num:num, buf:wrapByteList(module.data)]
|
modules[name] = [num:num, buf:wrapByteList(module.data)]
|
||||||
bytecodes[name] = [num:num, buf:wrapByteList(module.bytecode)]
|
bytecodes[name] = [num:num, buf:wrapByteList(module.bytecode)]
|
||||||
fixups[name] = [num:num, buf:wrapByteList(module.fixups)]
|
fixups[name] = [num:num, buf:wrapByteList(module.fixups)]
|
||||||
@ -1059,7 +1102,7 @@ class PackPartitions
|
|||||||
mapNames[shortName] = ['3D', num3D]
|
mapNames[shortName] = ['3D', num3D]
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
println "Warning: map name '${map?.@name}' should contain '2D' or '3D'. Skipping."
|
printWarning "map name '${map?.@name}' should contain '2D' or '3D'. Skipping."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pack each map This uses the image and tile maps filled earlier.
|
// Pack each map This uses the image and tile maps filled earlier.
|
||||||
@ -1070,7 +1113,7 @@ class PackPartitions
|
|||||||
else if (map?.@name =~ /3D/)
|
else if (map?.@name =~ /3D/)
|
||||||
pack3DMap(map, dataIn.tile)
|
pack3DMap(map, dataIn.tile)
|
||||||
else
|
else
|
||||||
println "Warning: map name '${map?.@name}' should contain '2D' or '3D'. Skipping."
|
printWarning "map name '${map?.@name}' should contain '2D' or '3D'. Skipping."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ready to start writing the output file.
|
// Ready to start writing the output file.
|
||||||
@ -1095,6 +1138,9 @@ class PackPartitions
|
|||||||
|
|
||||||
static void main(String[] args)
|
static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
// Set auto-flushing for stdout
|
||||||
|
System.out = new PrintStream(new BufferedOutputStream(System.out), true)
|
||||||
|
|
||||||
// Verify that assertions are enabled
|
// Verify that assertions are enabled
|
||||||
def flag = false
|
def flag = false
|
||||||
try {
|
try {
|
||||||
@ -1114,9 +1160,42 @@ class PackPartitions
|
|||||||
println " (where intcastMap.js is to aid in debugging the Javascript raycaster)"
|
println " (where intcastMap.js is to aid in debugging the Javascript raycaster)"
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there's an existing error file, remote it.
|
||||||
|
def errorFile = new File("pack_error.txt")
|
||||||
|
if (errorFile.exists())
|
||||||
|
errorFile.delete()
|
||||||
|
|
||||||
// Go for it.
|
// Go for it.
|
||||||
new PackPartitions().pack(args[0], args[1], args.size() > 2 ? args[2] : null)
|
def inst = new PackPartitions()
|
||||||
|
try {
|
||||||
|
inst.pack(args[0], args[1], args.size() > 2 ? args[2] : null)
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
errorFile.withWriter { out ->
|
||||||
|
out.println "Packing error: ${t.message}"
|
||||||
|
out.println "\nContext:"
|
||||||
|
out.println " ${inst.getContextStr()}"
|
||||||
|
out.println "\nGroovy call stack:"
|
||||||
|
t.getStackTrace().each {
|
||||||
|
if (it.toString().contains(".groovy:"))
|
||||||
|
out.println " $it"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def msg = "Fatal error encountered in ${inst.getContextStr()}.\nDetails written to file 'pack_error.txt'."
|
||||||
|
println msg
|
||||||
|
System.out.flush()
|
||||||
|
javax.swing.JOptionPane.showMessageDialog(null, msg, "Fatal packing error",
|
||||||
|
javax.swing.JOptionPane.ERROR_MESSAGE)
|
||||||
|
System.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst.nWarnings > 0) {
|
||||||
|
javax.swing.JOptionPane.showMessageDialog(null,
|
||||||
|
"${inst.nWarnings} warning(s) noted during packing.\nCheck console for details.",
|
||||||
|
"Pack warnings",
|
||||||
|
javax.swing.JOptionPane.ERROR_MESSAGE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScriptModule
|
class ScriptModule
|
||||||
@ -1183,24 +1262,32 @@ class PackPartitions
|
|||||||
def name = script.name[0].text()
|
def name = script.name[0].text()
|
||||||
if (name.toLowerCase() == "init") // this special script gets processed later
|
if (name.toLowerCase() == "init") // this special script gets processed later
|
||||||
return
|
return
|
||||||
println " Script '$name'"
|
//println " Script '$name'"
|
||||||
|
withContext("script '$name'")
|
||||||
|
{
|
||||||
|
if (script.block.size() == 0) {
|
||||||
|
printWarning("empty script found; skipping.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (script.block.size() == 0)
|
// Record the function's start address in its corresponding stub
|
||||||
return
|
startFunc(scriptNum+1)
|
||||||
|
|
||||||
// Record the function's start address in its corresponding stub
|
// Process the code inside it
|
||||||
startFunc(scriptNum+1)
|
def proc = script.block[0]
|
||||||
|
assert proc.@type == "procedures_defreturn"
|
||||||
// Process the code inside it
|
if (proc.statement.size() > 0) {
|
||||||
def proc = script.block[0]
|
assert proc.statement.size() == 1
|
||||||
assert proc.@type == "procedures_defreturn"
|
def stmt = proc.statement[0]
|
||||||
assert proc.statement.size() == 1
|
assert stmt.@name == "STACK"
|
||||||
def stmt = proc.statement[0]
|
stmt.block.each { packBlock(it) }
|
||||||
assert stmt.@name == "STACK"
|
}
|
||||||
stmt.block.each { packBlock(it) }
|
else
|
||||||
|
printWarning "empty statement found; skipping."
|
||||||
// And complete the function
|
|
||||||
finishFunc()
|
// And complete the function
|
||||||
|
finishFunc()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def finishFunc()
|
def finishFunc()
|
||||||
@ -1212,24 +1299,25 @@ class PackPartitions
|
|||||||
|
|
||||||
def packBlock(blk)
|
def packBlock(blk)
|
||||||
{
|
{
|
||||||
println " Block '${blk.@type}'"
|
withContext("${blk.@type}") {
|
||||||
switch (blk.@type)
|
switch (blk.@type)
|
||||||
{
|
{
|
||||||
case 'text_print':
|
case 'text_print':
|
||||||
case 'text_println':
|
case 'text_println':
|
||||||
packTextPrint(blk); break
|
packTextPrint(blk); break
|
||||||
case 'controls_if':
|
case 'controls_if':
|
||||||
packIfStmt(blk); break
|
packIfStmt(blk); break
|
||||||
case 'events_set_map':
|
case 'events_set_map':
|
||||||
packSetMap(blk); break
|
packSetMap(blk); break
|
||||||
case 'events_set_sky':
|
case 'events_set_sky':
|
||||||
packSetSky(blk); break
|
packSetSky(blk); break
|
||||||
case 'events_set_ground':
|
case 'events_set_ground':
|
||||||
packSetGround(blk); break
|
packSetGround(blk); break
|
||||||
case 'events_teleport':
|
case 'events_teleport':
|
||||||
packTeleport(blk); break
|
packTeleport(blk); break
|
||||||
default:
|
default:
|
||||||
println "Warning: don't know how to pack block of type '${blk.@type}'"
|
printWarning "don't know how to pack block of type '${blk.@type}'"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strangely, blocks seem to be chained together, but hierarchically. Whatever.
|
// Strangely, blocks seem to be chained together, but hierarchically. Whatever.
|
||||||
@ -1283,7 +1371,10 @@ class PackPartitions
|
|||||||
|
|
||||||
def packTextPrint(blk)
|
def packTextPrint(blk)
|
||||||
{
|
{
|
||||||
assert blk.value.size() == 1
|
if (blk.value.size() == 0) {
|
||||||
|
printWarning "empty text_print block, skipping."
|
||||||
|
return
|
||||||
|
}
|
||||||
def val = blk.value[0]
|
def val = blk.value[0]
|
||||||
assert val.@name == 'VALUE'
|
assert val.@name == 'VALUE'
|
||||||
assert val.block.size() == 1
|
assert val.block.size() == 1
|
||||||
@ -1293,7 +1384,7 @@ class PackPartitions
|
|||||||
def fld = valBlk.field[0]
|
def fld = valBlk.field[0]
|
||||||
assert fld.@name == 'TEXT'
|
assert fld.@name == 'TEXT'
|
||||||
def text = fld.text()
|
def text = fld.text()
|
||||||
println " text: '$text'"
|
//println " text: '$text'"
|
||||||
|
|
||||||
emitCodeByte(0x26) // LA
|
emitCodeByte(0x26) // LA
|
||||||
def textAddr = addString(text)
|
def textAddr = addString(text)
|
||||||
@ -1305,13 +1396,17 @@ class PackPartitions
|
|||||||
|
|
||||||
def packIfStmt(blk)
|
def packIfStmt(blk)
|
||||||
{
|
{
|
||||||
|
if (blk.value.size() == 0) {
|
||||||
|
printWarning "missing condition; skipping."
|
||||||
|
return
|
||||||
|
}
|
||||||
assert blk.value.size() == 1
|
assert blk.value.size() == 1
|
||||||
def cond = blk.value[0]
|
def cond = blk.value[0]
|
||||||
assert cond.@name == 'IF0'
|
assert cond.@name == 'IF0'
|
||||||
assert cond.block.size() == 1
|
assert cond.block.size() == 1
|
||||||
assert cond.block[0].@type == 'text_getboolean'
|
assert cond.block[0].@type == 'text_getboolean'
|
||||||
|
|
||||||
print " Conditional on getboolean,"
|
//print " Conditional on getboolean,"
|
||||||
|
|
||||||
emitCodeByte(0x54) // CALL
|
emitCodeByte(0x54) // CALL
|
||||||
emitCodeWord(vec_getYN)
|
emitCodeWord(vec_getYN)
|
||||||
@ -1338,7 +1433,11 @@ class PackPartitions
|
|||||||
assert fld.@name == 'NAME'
|
assert fld.@name == 'NAME'
|
||||||
def mapName = fld.text()
|
def mapName = fld.text()
|
||||||
def mapNum = mapNames[mapName]
|
def mapNum = mapNames[mapName]
|
||||||
println " Set map to '$mapName' (num $mapNum)"
|
if (!mapNum) {
|
||||||
|
printWarning "map '$mapName' not found; skipping set_map."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//println " Set map to '$mapName' (num $mapNum)"
|
||||||
assert mapNum : "Map $mapName not found!"
|
assert mapNum : "Map $mapName not found!"
|
||||||
|
|
||||||
emitCodeByte(0x2A) // CB
|
emitCodeByte(0x2A) // CB
|
||||||
@ -1358,7 +1457,7 @@ class PackPartitions
|
|||||||
assert fld.@name == 'COLOR'
|
assert fld.@name == 'COLOR'
|
||||||
def color = fld.text().toInteger()
|
def color = fld.text().toInteger()
|
||||||
assert color >= 0 && color <= 15
|
assert color >= 0 && color <= 15
|
||||||
println " Set sky to $color"
|
//println " Set sky to $color"
|
||||||
|
|
||||||
emitCodeByte(0x2A) // CB
|
emitCodeByte(0x2A) // CB
|
||||||
emitCodeByte(color)
|
emitCodeByte(color)
|
||||||
@ -1374,7 +1473,7 @@ class PackPartitions
|
|||||||
assert fld.@name == 'COLOR'
|
assert fld.@name == 'COLOR'
|
||||||
def color = fld.text().toInteger()
|
def color = fld.text().toInteger()
|
||||||
assert color >= 0 && color <= 15
|
assert color >= 0 && color <= 15
|
||||||
println " Set ground to $color"
|
//println " Set ground to $color"
|
||||||
|
|
||||||
emitCodeByte(0x2A) // CB
|
emitCodeByte(0x2A) // CB
|
||||||
emitCodeByte(color)
|
emitCodeByte(color)
|
||||||
@ -1393,7 +1492,7 @@ class PackPartitions
|
|||||||
def y = blk.field[1].text().toInteger()
|
def y = blk.field[1].text().toInteger()
|
||||||
def facing = blk.field[2].text().toInteger()
|
def facing = blk.field[2].text().toInteger()
|
||||||
assert facing >= 0 && facing <= 15
|
assert facing >= 0 && facing <= 15
|
||||||
println " Teleport to ($x,$y) facing $facing"
|
//println " Teleport to ($x,$y) facing $facing"
|
||||||
|
|
||||||
emitCodeByte(0x2C) // CW
|
emitCodeByte(0x2C) // CW
|
||||||
emitCodeWord(x)
|
emitCodeWord(x)
|
||||||
@ -1408,7 +1507,7 @@ class PackPartitions
|
|||||||
|
|
||||||
def makeInit(scripts)
|
def makeInit(scripts)
|
||||||
{
|
{
|
||||||
println " Script: special 'init'"
|
//println " Script: special 'init'"
|
||||||
startFunc(0)
|
startFunc(0)
|
||||||
scripts.script.eachWithIndex { script, idx ->
|
scripts.script.eachWithIndex { script, idx ->
|
||||||
def name = script.name[0].text()
|
def name = script.name[0].text()
|
||||||
|
Loading…
Reference in New Issue
Block a user