Added version stamp (encoded engine time, plus scenario differential)

This commit is contained in:
Martin Haye 2017-08-11 11:17:38 -07:00
parent 3a452e3de1
commit 8cd36fad17
2 changed files with 85 additions and 7 deletions

View File

@ -19,6 +19,7 @@ import java.nio.ByteBuffer
import java.nio.channels.Channels
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.util.Calendar
import java.util.zip.GZIPInputStream
import java.util.LinkedHashMap
import java.security.MessageDigest
@ -773,6 +774,12 @@ class A2PackPartitions
cache[key] = [hash:hash, data:buf]
}
def updateEngineStamp(name, hash)
{
if (!cache.containsKey("engineStamp") || cache["engineStamp"].hash < hash)
cache["engineStamp"] = [hash:hash]
}
def grabEntireFromCache(kind, addTo, hash)
{
if (cache.containsKey(kind) && cache[kind].hash == hash) {
@ -1559,6 +1566,30 @@ class A2PackPartitions
}
}
/**
* Make a compact representation of a timestamp, useful as a version number
*/
def timestampToVersionNum(engineStamp, scenarioStamp)
{
Calendar cal = Calendar.getInstance()
cal.setTimeInMillis(engineStamp)
def year = cal.get(Calendar.YEAR)
def month = cal.get(Calendar.MONTH)
def day = cal.get(Calendar.DAY_OF_MONTH)
def hour = cal.get(Calendar.HOUR_OF_DAY)
def yearCode = year % 10
def monthCode = (month < 9) ? (char) (48+month+1) :
month == 9 ? 'o' :
month == 10 ? 'n' :
'd'
def hourCode = (char) (65 + hour)
def engineCode = String.format("%d%c%02d%c", yearCode, monthCode, day, hourCode)
def offset = (int) ((scenarioStamp - engineStamp) / (1000 * 60 * 60))
return String.format("%s%s%d", engineCode, offset < 0 ? "-" : ".", Math.abs(offset))
}
/**
* Make an index listing the partition number wherein each map and portrait can be found.
*/
@ -1566,6 +1597,12 @@ class A2PackPartitions
{
def tmp = ByteBuffer.allocate(5000)
// Start with the version number
def combinedVersion = timestampToVersionNum(cache["engineStamp"].hash, cache["scenarioStamp"].hash)
tmp.put((byte)(combinedVersion.length()))
combinedVersion.getBytes().each { b -> tmp.put((byte)b) }
// Then output 2D maps, 3d maps, and portraits
tmp.put((byte) maps2D.size())
maps2D.each { k, v ->
tmp.put((byte) ((parseOrder(v.order) < 0) ? 255 : v.buf.partNum))
@ -1859,6 +1896,7 @@ class A2PackPartitions
def uncompData = readBinary(inDir + "build/" + codeName + ".b")
addToCache("code", code, codeName, hash, compress(uncompData))
updateEngineStamp(codeName, hash)
}
def assembleCore(inDir)
@ -1878,8 +1916,10 @@ class A2PackPartitions
def file = jitCopy(
new File("build/tools/${name=="PRORWTS" ? "ProRWTS/PRORWTS2" : "PLASMA/src/PLVM02"}#4000"))
hash = file.lastModified()
if (!grabFromCache("sysCode", sysCode, name, hash))
if (!grabFromCache("sysCode", sysCode, name, hash)) {
addToCache("sysCode", sysCode, name, hash, compress(readBinary(file.toString())))
updateEngineStamp(name, hash)
}
}
else {
hash = getLastDep(new File(inDir, "${name}.s"))
@ -1892,6 +1932,7 @@ class A2PackPartitions
addToCache("sysCode", sysCode, name, hash,
(name ==~ /loader|decomp/) ? [data:uncompData, len:uncompData.length, compressed:false]
: compress(uncompData))
updateEngineStamp(name, hash)
}
}
@ -1952,6 +1993,8 @@ class A2PackPartitions
addToCache("modules", modules, moduleName, hash, module)
addToCache("bytecodes", bytecodes, moduleName, hash, bytecode)
addToCache("fixups", fixups, moduleName, hash, fixup)
if (!(moduleName ==~ /.*(gs|gen)_.*/ || codeDir ==~ /.*mapScript.*/))
updateEngineStamp(moduleName, hash)
}
def readAllCode()
@ -2127,11 +2170,14 @@ class A2PackPartitions
addResourceDep("map", curMapName, toType, toName)
}
def pack(xmlPath, dataIn)
def pack(xmlFile, dataIn)
{
// Save time by using cache of previous run
readCache()
// Record scenario timestamp
cache["scenarioStamp"] = [hash: xmlFile.lastModified()]
// Record global script names
recordGlobalScripts(dataIn)
@ -3088,7 +3134,7 @@ end
return [name.trim(), animFrameNum, animFlags]
}
def dataGen(xmlPath, dataIn)
def dataGen(xmlFile, dataIn)
{
// When generating code, we need to use Unix linebreaks since that's what
// the PLASMA compiler expects to see.

View File

@ -1365,9 +1365,9 @@ def lookupResourcePart(sectionNum, resourceNum)#1
word ptr
byte n
// Skip to the requested section
// Skip to the requested section (starting just after version num)
ptr = pResourceIndex
while sectionNum > 1
while sectionNum > 0
ptr = ptr + readAuxByte(ptr) + 1
sectionNum--
loop
@ -1405,6 +1405,36 @@ export def setGround(num)#0
needRender = TRUE
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def printVersion()#0
word p, len, cv, ch
if !pResourceIndex; return; fin
cv = ^$25
^$23 = 24 // full height window
^$25 = 22
crout()
^$24 = 25
puts("V ")
setWindow(183, 192, 168, 254)
clearWindow()
setWindow(183, 192, 175, 245)
rawDisplayStr("^YV ")
p = pResourceIndex
len = readAuxByte(p)
while len
p++
ch = readAuxByte(p)
printChar(ch)
displayChar(ch)
len--
loop
rawDisplayStr("^N")
^$23 = 23 // shrink window to protect version num
^$25 = cv-1
crout()
setWindow2()
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Load the Frame Image, and lock it.
export def loadFrameImg(img)#0
@ -1435,6 +1465,9 @@ export def loadFrameImg(img)#0
// And show the first frame of the screen image
showAnimFrame()
// Brand the image with the version number
printVersion()
else
curFullscreenImg = NULL
anyAnims = FALSE
@ -1847,7 +1880,7 @@ end
def moveForward()#1
byte dir
dir = getDir()
moveInternal(dir, dir, TRUE)
return moveInternal(dir, dir, TRUE)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -3091,7 +3124,6 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Main code.
//
^$25 = 23
loadTitle()
startGame(TRUE) // ask whether new or load
kbdLoop()