Save memory during automap display by packing small tilesets separately from regular tilesets.

This commit is contained in:
Martin Haye 2020-05-25 13:32:51 -07:00
parent 18031e182d
commit 9e93360d11
6 changed files with 75 additions and 75 deletions

View File

@ -56,6 +56,7 @@ class A2PackPartitions
def TYPE_PORTRAIT = 11
def TYPE_SONG = 12
def TYPE_STORY = 13
def TYPE_SM_TILE_SET = 14
static final int FLOPPY_SIZE = 35*8 // good old 140k floppy = 280 blks
static final int AC_KLUDGE = 2 // minus 1 to work around last-block bug in AppleCommander
@ -76,21 +77,23 @@ class A2PackPartitions
10: "Code",
11: "Portrait image",
12: "Song",
13: "Story"]
13: "Story",
14: "Small tile set"]
def typeNameToNum = ["code": TYPE_CODE,
"map2D": TYPE_2D_MAP,
"map3D": TYPE_3D_MAP,
"tileSet": TYPE_TILE_SET,
"texture": TYPE_TEXTURE_IMG,
"frame": TYPE_SCREEN,
"font": TYPE_FONT,
"module": TYPE_MODULE,
"bytecode": TYPE_BYTECODE,
"fixup": TYPE_FIXUP,
"portrait": TYPE_PORTRAIT,
"song": TYPE_SONG,
"story": TYPE_STORY]
def typeNameToNum = ["code": TYPE_CODE,
"map2D": TYPE_2D_MAP,
"map3D": TYPE_3D_MAP,
"tileSet": TYPE_TILE_SET,
"texture": TYPE_TEXTURE_IMG,
"frame": TYPE_SCREEN,
"font": TYPE_FONT,
"module": TYPE_MODULE,
"bytecode": TYPE_BYTECODE,
"fixup": TYPE_FIXUP,
"portrait": TYPE_PORTRAIT,
"song": TYPE_SONG,
"story": TYPE_STORY,
"smTileSet": TYPE_SM_TILE_SET]
def typeNumToName = [1: "code",
2: "map2D",
@ -104,7 +107,8 @@ class A2PackPartitions
10: "fixup",
11: "portrait",
12: "song",
13: "story"]
13: "story",
14: "smTileSet"]
def mapNames = [:] // map name (and short name also) to map.2dor3d, map.num
def mapSizes = [] // array of [2dOr3D, mapNum, marksSize]
@ -115,6 +119,7 @@ class A2PackPartitions
def tiles = [:] // tile id to tile.buf
def smTiles = [:] // tile id to small-size tile.buf
def tileSets = [:] // tileset name to tileset.num, tileset.buf
def smTileSets= [:] // tileset name to tileset.num, tileset.buf
def avatars = [:] // avatar tile name to tile num (within the special tileset)
def lampTiles = [] // animated series of lamp tiles
def textures = [:] // img name to img.num, img.buf
@ -1117,6 +1122,7 @@ class A2PackPartitions
}
tileSets[setName] = [num:setNum, tileMap:tileMap, tileIds:tileIds]
smTileSets[setName] = [num:setNum, tileMap:tileMap, tileIds:tileIds]
addResourceDep("map", "<root>", "tileSet", "tileSet_global")
return [setNum, tileMap]
}
@ -1141,6 +1147,7 @@ class A2PackPartitions
}
tileSets[setName] = [num:setNum, tileMap:tileMap, tileIds:tileIds]
smTileSets[setName] = [num:setNum, tileMap:tileMap, tileIds:tileIds]
addResourceDep("map", "<root>", "tileSet", "tileSet_automap")
return [setNum, tileMap]
}
@ -1189,10 +1196,9 @@ class A2PackPartitions
else {
setNum = tileSets.size() + 1
//println "Creating new tileSet $setNum."
tileSet = [num:setNum,
tileMap:[:],
tileIds:tileIds]
tileSet = [num:setNum, tileMap:[:], tileIds:tileIds]
tileSets["tileSet${setNum}"] = tileSet
smTileSets["tileSet${setNum}"] = [num:setNum, tileMap: tileSet.tileMap, tileIds:tileIds]
}
addMapDep("tileSet", "tileSet${setNum}")
@ -1985,6 +1991,7 @@ class A2PackPartitions
recordChunks("map2D", maps2D)
recordChunks("map3D", maps3D)
recordChunks("tileSet", tileSets)
recordChunks("smTileSet",smTileSets)
recordChunks("texture", textures)
recordChunks("frame", frames)
recordChunks("portrait", portraits)
@ -2845,6 +2852,8 @@ class A2PackPartitions
if (!resourceDeps.containsKey(fromKey))
resourceDeps[fromKey] = [] as Set
resourceDeps[fromKey] << [toType, toName]
if (toType == "tileSet")
addResourceDep(fromType, fromName, "smTileSet", toName)
}
def addMapDep(toType, toName)
@ -2867,48 +2876,35 @@ class A2PackPartitions
tileFrames[fullName] << tile.@id
}
// Then finish each set
tileSets.each { name, tileSet -> finishTileSet(tileNames, tileFrames, tileSet) }
// Then finish each tile set
tileSets.each { name, tileSet ->
// Determine the max # of animation frames
tileSet.buf = packAnimTiles(tileSet, tileNames, tileFrames, tiles)
smTileSets[name].buf = packAnimTiles(tileSet, tileNames, tileFrames, smTiles)
}
}
def finishTileSet(tileNames, tileFrames, tileSet)
def packAnimTiles(tileSet, tileNames, tileFrames, tiles)
{
// Determine the max # of animation frames
def maxFrames = 0
tileSet.tileIds.each { id ->
maxFrames = Math.max(maxFrames, tileFrames[tileNames[id]].size)
}
//println("tileSet.num=${tileSet.num}, maxFrames=$maxFrames")
def animBuf = new AnimBuf()
for (int frameNum = 1; frameNum <= maxFrames; frameNum++)
{
def frameBuf = ByteBuffer.allocate(50000)
frameBuf.put((byte)(tileSet.tileIds.size()))
// First the large size tiles
tileSet.tileIds.each { id ->
def frames = tileFrames[tileNames[id]]
def frame = frames[(frameNum-1) % frames.size()]
tiles[frame].flip() // crazy stuff to append one buffer to another
frameBuf.put(tiles[frame])
}
// Then add the small size tiles for automap display
tileSet.tileIds.each { id ->
def frames = tileFrames[tileNames[id]]
def frame = frames[(frameNum-1) % frames.size()]
smTiles[frame].flip() // crazy stuff to append one buffer to another
frameBuf.put(smTiles[frame])
}
// Now that we have all the tiles for this frame, put it in the animation buffer
//println(" frame=$frameNum buf.size=${frameBuf.position()}")
animBuf.addImage(frameNum, "f", frameBuf)
}
// Make the diffs and do the final packing.
tileSet.buf = compress(animBuf.pack())
return compress(animBuf.pack())
}
def pack(xmlFile, dataIn)

View File

@ -2689,6 +2689,8 @@ advanceAnims: !zone {
beq .anim
cmp #RES_TYPE_TILESET
beq .anim
cmp #RES_TYPE_SM_TILESET
beq .anim
bne .next ; not animated; skip
.anim lda tSegAdrLo,x ; pointer to start of resource
sta pTmp

View File

@ -11,19 +11,20 @@
;------------------------------------------------------------------------------
; Resource types
RES_TYPE_CODE = $1
RES_TYPE_2D_MAP = $2
RES_TYPE_3D_MAP = $3
RES_TYPE_TILESET = $4
RES_TYPE_TEXTURE = $5
RES_TYPE_SCREEN = $6
RES_TYPE_FONT = $7
RES_TYPE_MODULE = $8
RES_TYPE_BYTECODE = $9
RES_TYPE_FIXUP = $A
RES_TYPE_PORTRAIT = $B
RES_TYPE_SONG = $C
RES_TYPE_STORY = $D
RES_TYPE_CODE = $1
RES_TYPE_2D_MAP = $2
RES_TYPE_3D_MAP = $3
RES_TYPE_TILESET = $4
RES_TYPE_TEXTURE = $5
RES_TYPE_SCREEN = $6
RES_TYPE_FONT = $7
RES_TYPE_MODULE = $8
RES_TYPE_BYTECODE = $9
RES_TYPE_FIXUP = $A
RES_TYPE_PORTRAIT = $B
RES_TYPE_SONG = $C
RES_TYPE_STORY = $D
RES_TYPE_SM_TILESET = $E
;------------------------------------------------------------------------------
; Command codes

View File

@ -597,7 +597,7 @@ def loadMarks()#0
pSpecialsBuf = auxMmgr(QUEUE_LOAD, CODE_GEN_MAP_SPECIALS<<8 | RES_TYPE_CODE)
// While we're at it, load the automap special tiles.
specTileset = mmgr(QUEUE_LOAD, 2<<8 | RES_TYPE_TILESET) // always tileset 2 (just after global tiles)
specTileset = mmgr(QUEUE_LOAD, 2<<8 | RES_TYPE_SM_TILESET) // always tileset 2 (just after global tiles)
mmgr(FINISH_LOAD, 0)
// Call the automark write routine. This has not only the effect of flushing the marks
@ -609,8 +609,8 @@ def loadMarks()#0
pAllMarks = auxMmgr(REQUEST_MEMORY, len)
memcpy($4002, pAllMarks, len, 1)
// Figure out where the small versions of the special tiles reside (at the end of the full size tiles)
pSpecialTiles = specTileset + 3 + ((^(specTileset+2)) << 5)
// Figure out where the small versions of the special tiles reside
pSpecialTiles = specTileset + 3
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -722,7 +722,7 @@ def prepSections(extraLeft, extraTop)#0
// This part only happens in 2D mode (a 3D section have tileset filled in at construction)
pSection->bm_tilesetNum = ^(pSection=>pm_map + 4)
fin
pSection=>pm_tileset = mmgr(QUEUE_LOAD, (pSection->bm_tilesetNum)<<8 | RES_TYPE_TILESET)
pSection=>pm_tileset = mmgr(QUEUE_LOAD, (pSection->bm_tilesetNum)<<8 | RES_TYPE_SM_TILESET)
fin
pSection = pSection + TMapSection
loop
@ -839,7 +839,7 @@ def displaySections#0
//printSection(pSection)
if pSection->bm_visible
// Figure out where the small tiles reside (at the end of the full size tiles)
pSmallTiles = pSection=>pm_tileset + 3 + ((^(pSection=>pm_tileset + 2)) << 5)
pSmallTiles = pSection=>pm_tileset + 3
// And draw (different routines to handle differing map data layouts)
if mapIs3D
@ -1156,7 +1156,7 @@ def _automap_show(targetX, targetY)#1
// Ensure the global tileset is reloaded (otherwise tile eng will try to load it from wrong partition)
mmgr(START_LOAD, 1)
pGlobalTileset = mmgr(QUEUE_LOAD, 1<<8 | RES_TYPE_TILESET)
pGlobalTileset = mmgr(QUEUE_LOAD, 1<<8 | RES_TYPE_SM_TILESET)
mmgr(FINISH_LOAD, 0)
// All done.

View File

@ -2143,14 +2143,14 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
export def textureControl(flg)#0
flipToPage1
if flg <> texturesLoaded and renderLoaded and mapIs3D
if flg <> texturesLoaded and renderLoaded
if flg
_texControl(1)
loadUtil3d
showingLamp = (skyNum == 0 or skyNum == 8)
if mapIs3D; loadUtil3d; fin
showingLamp = mapIs3D and (skyNum == 0 or skyNum == 8)
else
_texControl(0)
if pModUtil3d and !inScript // e.g. strafe -> script -> combat: need strafe to stay in mem!
if pModUtil3d and mapIs3D and !inScript // e.g. strafe -> script -> combat: need strafe to stay in mem!
mmgr(FREE_MEMORY, pModUtil3d)
pModUtil3d = NULL
util3d = NULL

View File

@ -34,19 +34,20 @@ const BIGWIN_HEIGHT = BIGWIN_BOTTOM - BIGWIN_TOP
// Memory manager definitions
// Resource types
const RES_TYPE_CODE = 1
const RES_TYPE_2D_MAP = 2
const RES_TYPE_3D_MAP = 3
const RES_TYPE_TILESET = 4
const RES_TYPE_TEXTURE = 5
const RES_TYPE_SCREEN = 6
const RES_TYPE_FONT = 7
const RES_TYPE_MODULE = 8
const RES_TYPE_BYTECODE = 9
const RES_TYPE_FIXUP = 10
const RES_TYPE_PORTRAIT = 11
const RES_TYPE_SONG = 12
const RES_TYPE_STORY = 13
const RES_TYPE_CODE = 1
const RES_TYPE_2D_MAP = 2
const RES_TYPE_3D_MAP = 3
const RES_TYPE_TILESET = 4
const RES_TYPE_TEXTURE = 5
const RES_TYPE_SCREEN = 6
const RES_TYPE_FONT = 7
const RES_TYPE_MODULE = 8
const RES_TYPE_BYTECODE = 9
const RES_TYPE_FIXUP = 10
const RES_TYPE_PORTRAIT = 11
const RES_TYPE_SONG = 12
const RES_TYPE_STORY = 13
const RES_TYPE_SM_TILESET = 14
// Command codes
const RESET_MEMORY = $10