Now processing IF statements with GETYN triggers, and SETMAP events.

This commit is contained in:
Martin Haye 2014-07-19 15:55:27 -07:00
parent 69026ed705
commit ebe228d15f
2 changed files with 338 additions and 224 deletions

View File

@ -29,6 +29,7 @@ class PackPartitions
def TYPE_BYTECODE = 9
def TYPE_FIXUP = 10
def mapNames = [:] // map name (and short name also) to map.2dor3d, map.num
def code = [:] // code name to code.num, code.buf
def maps2D = [:] // map name to map.num, map.buf
def maps3D = [:] // map name to map.num, map.buf
@ -563,8 +564,8 @@ class PackPartitions
def pack2DMap(mapEl, tileEls)
{
def num = maps2D.size() + 1
def name = mapEl.@name ?: "map$num"
def num = mapNames[name][1]
//println "Packing 2D map #$num named '$name'."
def rows = parseMap(mapEl, tileEls)
def (tileSetNum, tileMap) = packTileSet(rows)
@ -575,8 +576,8 @@ class PackPartitions
def pack3DMap(mapEl, tileEls)
{
def num = maps3D.size() + 1
def name = mapEl.@name ?: "map$num"
def num = mapNames[name][1]
println "Packing 3D map #$num named '$name'."
def (scriptModule, locationsWithTriggers) = packScripts(mapEl, name)
def rows = parseMap(mapEl, tileEls)
@ -996,6 +997,26 @@ class PackPartitions
if (javascriptPath)
javascriptOut = new File(javascriptPath).newPrintWriter()
// Number all the maps and record them with names
def num2D = 0
def num3D = 0
dataIn.map.each { map ->
def name = map?.@name
def shortName = name.replaceAll(/[\s-]*[23]D$/, '')
if (map?.@name =~ /\s*2D$/) {
++num2D
mapNames[name] = ['2D', num2D]
mapNames[shortName] = ['2D', num2D]
}
else if (map?.@name =~ /\s*3D$/) {
++num3D
mapNames[name] = ['3D', num3D]
mapNames[shortName] = ['3D', num3D]
}
else
println "Warning: map name '${map?.@name}' should contain '2D' or '3D'. Skipping."
}
// Pack each map This uses the image and tile maps filled earlier.
println "Packing maps."
dataIn.map.each { map ->
@ -1049,15 +1070,12 @@ class PackPartitions
System.exit(1);
}
def m = new ScriptModule()
// Go for it.
new PackPartitions().pack(args[0], args[1], args.size() > 2 ? args[2] : null)
}
}
class ScriptModule
{
class ScriptModule
{
def data = []
def bytecode = []
def fixups = []
@ -1068,6 +1086,8 @@ class ScriptModule
def vec_locationTrigger = 0x300
def vec_displayStr = 0x303
def vec_getYN = 0x306
def vec_setMap = 0x309
def addString(str)
{
@ -1144,8 +1164,17 @@ class ScriptModule
def packBlock(blk)
{
println " Block '${blk.@type}'"
if (blk.@type == 'text_print')
packTextPrint(blk)
switch (blk.@type)
{
case 'text_print':
packTextPrint(blk); break
case 'controls_if':
packIfStmt(blk); break
case 'events_setmap':
packSetMap(blk); break
default:
println "Warning: don't know how to pack block of type '${blk.@type}'"
}
// Strangely, blocks seem to be chained together, but hierarchically. Whatever.
blk.next.each { it.block.each { packBlock(it) } }
@ -1218,6 +1247,60 @@ class ScriptModule
emitCodeByte(0x30) // DROP
}
def packIfStmt(blk)
{
assert blk.value.size() == 1
def cond = blk.value[0]
assert cond.@name == 'IF0'
assert cond.block.size() == 1
assert cond.block[0].@type == 'text_getboolean'
print " Conditional on getboolean,"
emitCodeByte(0x54) // CALL
emitCodeWord(vec_getYN)
emitCodeByte(0x4C) // BRFS
def branchStart = bytecodeAddr()
emitCodeWord(0) // placeholder until we know how far to jump over
assert blk.statement.size() == 1
def doStmt = blk.statement[0]
assert doStmt.block.size() == 1
packBlock(doStmt.block[0])
// Now calculate and fix the relative branch
def branchEnd = bytecodeAddr()
def rel = branchEnd - branchStart
bytecode[branchStart] = (byte)(rel & 0xFF)
bytecode[branchStart+1] = (byte)((rel >> 8) & 0xFF)
}
def packSetMap(blk)
{
assert blk.value.size() == 1
def mapVal = blk.value[0]
assert mapVal.@name == 'VALUE'
assert mapVal.block.size() == 1
def mapValBlk = mapVal.block[0]
assert mapValBlk.@type == 'text'
assert mapValBlk.field.size() == 1
def mapValFld = mapValBlk.field[0]
assert mapValFld.@name == 'TEXT'
def mapName = mapValFld.text()
def mapNum = mapNames[mapName]
assert mapNum
println " Set map to '$mapName' (num $mapNum)"
emitCodeByte(0x2A) // CB
assert mapNum[0] == '2D' || mapNum[0] == '3D'
emitCodeByte(mapNum[0] == '2D' ? 0 : 1)
emitCodeByte(0x2A) // CB
emitCodeByte(mapNum[1])
emitCodeByte(0x54) // CALL
emitCodeWord(vec_setMap)
emitCodeByte(0x30) // DROP
}
def makeInit(scripts)
{
startFunc(0)
@ -1252,4 +1335,6 @@ class ScriptModule
}
}
}
}

View File

@ -85,6 +85,7 @@ const MAX_LOC_TRIG = 80
; Strings.
byte helloStr[] = "Loading Lawless Legends.\n"
byte loopStr[] = "Entering keyboard loop.\n"
byte tooManyTriggers[] = "Too many triggers"
;==================================================================================================
; Global variables
@ -215,6 +216,14 @@ asm crout
rts
end
asm beep
bit setROM
jsr bell
dex ; don't-care return value
bit setLcRW+lcBank2
rts
end
;==================================================================================================
; Allocate memory
asm loader ; (cmd, mainOrAux, amount)
@ -344,20 +353,6 @@ asm goMon
jmp $FF69
end
asm fatal
bit setROM
lda #'F'+$80
jsr cout
lda #'#'+$80
jsr cout
lda evalStkH,x
jsr prbyte
lda evalStkL,x
jsr prbyte
jsr crout
jmp $FF65
end
asm clearWindow
bit setROM
txa
@ -389,6 +384,10 @@ end
;==================================================================================================
; General methods
def fatal(msg)
loader(FATAL_ERROR, MAIN_MEM, msg)
end
def initMap()
word scriptModule
@ -523,8 +522,6 @@ def moveForward()
*playerY = *playerY + walkDirs[(^playerDir << 1) + 1]
if !wasBlocked and isBlocked()
moveBackward()
else
checkScript()
fin
end
@ -564,13 +561,18 @@ def flipToFirstPage
fin
end
def nextMap()
def setMap(is3d, num)
mapNum = num
flipToFirstPage()
initMap()
end
def nextMap()
mapNum = mapNum + 1
if mapNum > 8
mapNum = 1
fin
initMap()
setMap(1, mapNum)
end
def nextSky()
@ -585,22 +587,29 @@ def nextGround()
setColor(3<<8 | skyGndTbl2[groundNum])
end
def getUpperKey()
byte key
while ^keyboard < 128
loop
key = ^keyboard & $7F
^keystrobe
if key >= $60
key = key - $20
fin
return key
end
def kbdLoop()
word key, func
while TRUE
if ^keyboard >= 128
key = ^keyboard & $7F
^keystrobe
key = getUpperKey()
key = key - $20
if key >= $40
key = key - $20
fin
if key >= 0 and key < $40
func = cmdTbl[key]
if func
func()
renderFrame()
fin
checkScript()
fin
fin
loop
@ -608,7 +617,7 @@ end
def setLocationTrigger(x, y, func)
if nLocTrig == MAX_LOC_TRIG
fatal($101)
fatal(@tooManyTriggers)
fin
locTrig_x[nLocTrig] = x
locTrig_y[nLocTrig] = y
@ -616,6 +625,19 @@ def setLocationTrigger(x, y, func)
nLocTrig = nLocTrig + 1
end
def getYN()
byte key
while TRUE
key = getUpperKey()
if key == 'Y'
return 1
elsif key == 'N'
return 0
fin
beep()
loop
end
;==================================================================================================
; Main code.
;
@ -645,9 +667,16 @@ initCmd('G', @nextGround)
callbacks.0 = $4c
callbacks:1 = @setLocationTrigger
callbacks.3 = $4c
callbacks:4 = @displayStr
callbacks.6 = $4c
callbacks:7 = @getYN
callbacks.9 = $4c
callbacks:10 = @setMap
initMap()
setWindow2()