diff --git a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy index 646068e2..9dcfc87b 100644 --- a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy +++ b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy @@ -392,7 +392,7 @@ class A2PackPartitions /* * Parse raw tile image data and return it as a two buffers: fullsize mainBuf, - * and reduced size smBuf + * and reduced size smBuf (for automap display) */ def parseTileData(imgEl) { @@ -1027,6 +1027,7 @@ class A2PackPartitions def numberGlobalTiles(dataIn) { def tileNum = 0 + def amapTnum = 0 dataIn.tile.sort{(it.@category + it.@name).toLowerCase()}.each { tile -> def lname = tile.@name.toLowerCase().trim().replaceAll(/\s*-\s*[23][dD]\s*/, "") def cat = tile.@category.toLowerCase().trim() @@ -1043,7 +1044,7 @@ class A2PackPartitions { def setNum = tileSets.size() + 1 assert setNum == 1 : "Special tile set must be first." - def setName = "tileSet_special" + def setName = "tileSet_global" def tileIds = [] as Set def tileMap = [:] def buf = ByteBuffer.allocate(50000) @@ -1064,6 +1065,37 @@ class A2PackPartitions } tileSets[setName] = [num:setNum, mainBuf:buf, smBuf:ByteBuffer.allocate(1), tileMap:tileMap, tileIds:tileIds] + addResourceDep("map", "", "tileSet", "tileSet_global") + return [setNum, tileMap] + } + + /** Pack tiles for special automap places into their own tile set. */ + def packAutomapTileSet(dataIn) + { + def setNum = tileSets.size() + 1 + assert setNum == 2 : "Automap tile set must be first." + def setName = "tileSet_automap" + def tileIds = [] as Set + def tileMap = [:] + def buf = ByteBuffer.allocate(50000) + + // Add each automap tile to the set + dataIn.tile.sort{(it.@category + it.@name).toLowerCase()}.each { tile -> + def name = tile.@name + def id = tile.@id + def data = tiles[id] + def cat = tile.@category.toLowerCase().trim() + if (cat == "automap") { + def num = tileMap.size() + tileIds.add(id) + tileMap[id] = num + data.flip() // crazy stuff to append one buffer to another + buf.put(data) + } + } + + tileSets[setName] = [num:setNum, mainBuf:buf, smBuf:ByteBuffer.allocate(1), tileMap:tileMap, tileIds:tileIds] + addResourceDep("map", "", "tileSet", "tileSet_automap") return [setNum, tileMap] } @@ -1120,7 +1152,6 @@ class A2PackPartitions } addMapDep("tileSet", "tileSet${setNum}") - addMapDep("tileSet", "tileSet_special") // each map requires the global tileset as well // Start by assuming we'll create a new tileset def tileMap = tileSet.tileMap @@ -2406,39 +2437,39 @@ class A2PackPartitions automapSpecials.sort().each { mapNum, y, x, tileNum -> if (mapNum != prevMapNum) { if (prevY > 0) { - out.println(" !byte 0 ; end of y=$prevY") + out.println(" !byte \$FF ; end of y=$prevY") out.println("+") } if (prevMapNum) { - out.println(" !byte 0 ; end of data for map $prevMapNum") + out.println(" !byte \$FF ; end of data for map $prevMapNum") out.println("++") } out.println("") out.println(" !byte $mapNum ; start of data for map $mapNum") - out.println(" !byte ++ - * + 1; length of this map's data (incl. hdr)") + out.println(" !byte ++ - *; length of this map's data (incl. hdr) - 1") prevMapNum = mapNum prevY = -1 } if (y != prevY) { if (prevY > 0) { - out.println(" !byte 0 ; end of y=$prevY") + out.println(" !byte \$FF ; end of y=$prevY") out.println("+") } out.println(" !byte $y ; y=$y") - out.println(" !byte + - * + 1 ; length of y=$y data (incl. hdr)") + out.println(" !byte + - * ; length of y=$y data (incl. hdr) - 1") prevY = y } - out.println(" !byte $x, 3, $tileNum ; x=$x, size=3, tile=$tileNum") + out.println(" !byte $x, 2, $tileNum ; x=$x, size=2, tile=$tileNum") } if (prevY > 0) { - out.println(" !byte 0 ; end of y=$prevY") + out.println(" !byte \$FF ; end of y=$prevY") out.println("+") } if (prevMapNum) { - out.println(" !byte 0 ; end of data for map $prevMapNum") + out.println(" !byte \$FF ; end of data for map $prevMapNum") out.println("++") } - out.println(" !byte 0; end of all maps") + out.println(" !byte \$FF; end of all maps") } replaceIfDiff("build/src/mapScripts/gen_mapSpecials.s") } @@ -2639,6 +2670,9 @@ class A2PackPartitions numberGlobalTiles(dataIn) packGlobalTileSet(dataIn) + // Automap special tiles have to come next. + packAutomapTileSet(dataIn) + // Play around with music def midiFile = new File(xmlFile.getAbsoluteFile().getParentFile(), "song.mid") if (midiFile.exists()) @@ -2757,6 +2791,7 @@ class A2PackPartitions buf.put((byte)(tileSet.tileIds.size())) tileSet.mainBuf.flip() // crazy stuff to append one buffer to another buf.put(tileSet.mainBuf) + // After the large size tiles, add the small size tiles for automap display tileSet.smBuf.flip() // crazy stuff to append one buffer to another buf.put(tileSet.smBuf) tileSet.buf = compress(unwrapByteBuffer(buf)) diff --git a/Platform/Apple/virtual/src/core/mem.s b/Platform/Apple/virtual/src/core/mem.s index 30ce3900..4d5c12b4 100644 --- a/Platform/Apple/virtual/src/core/mem.s +++ b/Platform/Apple/virtual/src/core/mem.s @@ -2142,6 +2142,8 @@ disk_queueLoad: !zone ldx tmp ; get back lo part of addr rts ; success! all done. .notFound: + +prByte resType + +prByte resNum jsr inlineFatal : !text "ResNotFnd", 0 .bump3: iny ; skip resource number iny ; skip lo byte of length diff --git a/Platform/Apple/virtual/src/include/mem.i b/Platform/Apple/virtual/src/include/mem.i index 07f952ff..6999fdce 100644 --- a/Platform/Apple/virtual/src/include/mem.i +++ b/Platform/Apple/virtual/src/include/mem.i @@ -8,8 +8,48 @@ ; governing permissions and limitations under the License. ;**************************************************************************************** -; Memory manager -; ------------------ +;------------------------------------------------------------------------------ +; 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 + +;------------------------------------------------------------------------------ +; Command codes +RESET_MEMORY = $10 +REQUEST_MEMORY = $11 +LOCK_MEMORY = $12 +UNLOCK_MEMORY = $13 +SET_MEM_TARGET = $14 +START_LOAD = $15 +QUEUE_LOAD = $16 +FINISH_LOAD = $17 +FREE_MEMORY = $18 +CALC_FREE = $19 +DEBUG_MEM = $1A +CHECK_MEM = $1B +ADVANCE_ANIMS = $1C +FIND_IN_MEM = $1D +FATAL_ERROR = $1F +HEAP_SET = $20 +HEAP_ADD_TYPE = $21 +HEAP_ALLOC = $22 +HEAP_INTERN = $23 +HEAP_COLLECT = $24 + +;------------------------------------------------------------------------------ +; Memory manager description +; -------------------------- ; ; Memory is managed in variable-sized segments. In each 48kb memory bank (main and aux), ; a linked list identifies each segment there as well as usage flags to mark free, used, @@ -150,27 +190,11 @@ mainLoader = $800 auxLoader = mainLoader+3 -;------------------------------------------------------------------------------ -; 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 = 10 -RES_TYPE_PORTRAIT = 11 -RES_TYPE_SONG = 12 - ;------------------------------------------------------------------------------ ; Command codes ;------------------------------------------------------------------------------ -RESET_MEMORY = $10 +;RESET_MEMORY = $10 ; Input: None ; ; Output: None @@ -188,7 +212,7 @@ RESET_MEMORY = $10 ; This command is acted upon and then passed on to chained loaders. ;------------------------------------------------------------------------------ -REQUEST_MEMORY = $11 +;REQUEST_MEMORY = $11 ; Input: X-reg(lo) / Y-reg(hi) - number of bytes to allocate ; ; Output: X-reg(lo) / Y-reg(hi) - address allocated @@ -206,7 +230,7 @@ REQUEST_MEMORY = $11 ; This command is acted upon immediately and chained loaders are not called. ;------------------------------------------------------------------------------ -LOCK_MEMORY = $12 +;LOCK_MEMORY = $12 ; Input: X-reg(lo) / Y-reg(hi) - address of segment to lock ; ; Output: None @@ -217,7 +241,7 @@ LOCK_MEMORY = $12 ; This command is acted upon immediately and chained loaders are not called. ;------------------------------------------------------------------------------ -UNLOCK_MEMORY = $13 +;UNLOCK_MEMORY = $13 ; Input: X-reg(lo) / Y-reg(hi) - address of segment to unlock (must be start ; of a memory area that was previously locked) ; @@ -227,7 +251,7 @@ UNLOCK_MEMORY = $13 ; RESET_MEMORY. ;------------------------------------------------------------------------------ -SET_MEM_TARGET = $14 +;SET_MEM_TARGET = $14 ; Input: X-reg(lo) / Y-reg(hi) - address to target ; ; Output: None @@ -240,7 +264,7 @@ SET_MEM_TARGET = $14 ; subsequent allocations will revert to their normal behavior. ;------------------------------------------------------------------------------ -START_LOAD = $15 +;START_LOAD = $15 ; Input: X-reg - disk partition number (1 for boot disk, 2-15 for others) ; ; Output: None @@ -251,7 +275,7 @@ START_LOAD = $15 ; The partition is recorded and passed on to chained loaders. ;------------------------------------------------------------------------------ -QUEUE_LOAD = $16 +;QUEUE_LOAD = $16 ; Input: X-reg - resource type ; Y-reg - resource number ; @@ -273,7 +297,7 @@ QUEUE_LOAD = $16 ; triggered. ;------------------------------------------------------------------------------ -FINISH_LOAD = $17 +;FINISH_LOAD = $17 ; Input: None ; ; Output: None @@ -284,7 +308,7 @@ FINISH_LOAD = $17 ; This command is acted upon by this loader and passed to chained loaders. ;------------------------------------------------------------------------------ -FREE_MEMORY = $18 +;FREE_MEMORY = $18 ; Input: X-reg(lo) / Y-reg(hi) - address of segment to mark as free (must ; be start of a memory area that was previously requested or loaded) ; @@ -294,7 +318,7 @@ FREE_MEMORY = $18 ; reused. This also clears the lock bit! ;------------------------------------------------------------------------------ -CALC_FREE = $19 +;CALC_FREE = $19 ; Input: None ; ; Output: X-reg(lo) / Y-reg(hi) - bytes of memory currently free @@ -303,7 +327,7 @@ CALC_FREE = $19 ; loader for main mem free, or aux mem loader for aux mem free. ;------------------------------------------------------------------------------ -DEBUG_MEM = $1A +;DEBUG_MEM = $1A ; Input: None ; ; Output: None @@ -311,7 +335,7 @@ DEBUG_MEM = $1A ; Print out the currently allocated memory blocks and their states. ;------------------------------------------------------------------------------ -CHECK_MEM = $1B +;CHECK_MEM = $1B ; Input: None ; ; Output: None @@ -320,7 +344,7 @@ CHECK_MEM = $1B ; has been set) are all intact. ;------------------------------------------------------------------------------ -ADVANCE_ANIMS = $1C +;ADVANCE_ANIMS = $1C ; Input: X-reg - direction change (0=no change, 1=change). ; Only applied to resources marked as "forward/backward" order. ; Y-reg - number of frames to skip. @@ -340,7 +364,7 @@ ADVANCE_ANIMS = $1C ; or main) are processed. ;------------------------------------------------------------------------------ -FIND_IN_MEM = $1D +;FIND_IN_MEM = $1D ; Input: X-reg - resource type ; Y-reg - resource number ; @@ -350,7 +374,7 @@ FIND_IN_MEM = $1D ; its address. Otherwise returns 0000. ;------------------------------------------------------------------------------ -FATAL_ERROR = $1F +;FATAL_ERROR = $1F ; Input: X-reg(lo) / Y-reg(hi): message pointer. Message can be: ; (1) a zero-terminated, hi-bit ASCII string, (assembly style), or ; (2) a length-prefixed, lo-bit ASCII string (PLASMA / ProDOS style) @@ -364,7 +388,7 @@ FATAL_ERROR = $1F ; This command halts and thus never returns. ;------------------------------------------------------------------------------ -HEAP_SET = $20 +;HEAP_SET = $20 ; Input: X-reg(lo) / Y-reg(hi): pointer to allocated block for heap ; ; Output: None @@ -377,7 +401,7 @@ HEAP_SET = $20 ; setting the global type ($80). ;------------------------------------------------------------------------------ -HEAP_ADD_TYPE = $21 +;HEAP_ADD_TYPE = $21 ; Input: X-reg(lo) / Y-reg(hi): pointer to type table ; ; Output: None @@ -395,7 +419,7 @@ HEAP_ADD_TYPE = $21 ; byte n: zero (0) value marks end of table ;------------------------------------------------------------------------------ -HEAP_ALLOC = $22 +;HEAP_ALLOC = $22 ; Input: X-reg: string length $00-7F, or type code $80-FF ; ; Output: X-reg(lo) / Y-reg(hi): pointer to allocated object space @@ -419,7 +443,7 @@ HEAP_ALLOC = $22 ; Note: strings of length zero are considered valid and supported. ;------------------------------------------------------------------------------ -HEAP_INTERN = $23 +;HEAP_INTERN = $23 ; Input: X-reg(lo) / Y-reg(hi): PLASMA-style string in regular RAM ; ; Output: X-reg(lo) / Y-reg(hi): pointer to allocated object space @@ -431,7 +455,7 @@ HEAP_INTERN = $23 ; Else, allocates heap space and copy the string into it. ;------------------------------------------------------------------------------ -HEAP_COLLECT = $24 +;HEAP_COLLECT = $24 ; Input: None. ; ; Output: X-reg(lo) / Y-reg(hi): new top of heap after collection. If you diff --git a/Platform/Apple/virtual/src/plasma/automap.pla b/Platform/Apple/virtual/src/plasma/automap.pla index a2c104f0..6f7a710a 100644 --- a/Platform/Apple/virtual/src/plasma/automap.pla +++ b/Platform/Apple/virtual/src/plasma/automap.pla @@ -22,6 +22,9 @@ const SCREEN_COLS = 36 const SECTION_WIDTH_2D = 22 const SECTION_HEIGHT_2D = 23 +const specPtr = $BC // must match asm definition below for pSpecials +const specScanFor = $BE // must match asm definition below for scanFor + struc TMapSection byte bm_mapNum word pm_map @@ -57,6 +60,10 @@ byte nHorzSects byte sectionBuf[SECT_BUF_SIZE] word pLastSection word pAllMarks +word pSpecialsBuf +word pSpecialTiles +word scanSpecials = $100 // placed at $100 so it can easily access aux mem +word pSpecTiles /////////////////////////////////////////////////////////////////////////////////////////////////// // Definitions used by assembly code @@ -81,6 +88,8 @@ ysav = $34 ; length 1 ; do not use $50..B5, as the current render (tile engine or raycaster) use these pSrc = $B8 ; length 2 pDst = $BA ; length 2 +pSpecials = $BC ; length 2 +scanFor = $BE ; length 1 HB = evalStkH-evalStkL ; offset to get from lo byte to hi byte on eval stack @@ -247,29 +256,36 @@ asm scroll(srcLine, srcOff, dstLine, dstOff, width, dir, nLines)#0 end /////////////////////////////////////////////////////////////////////////////////////////////////// -asm fillRow(mapRowData, mask, tileTrans, pSmallTiles, blankTile, width, tilePtrs)#0 +asm fillRow(mapRowData, mask, tileTrans, pSmallTiles, pSpecialTiles, blankTile, width, tilePtrs)#0 !zone - +asmPlasmNoRet 7 -.param_mapRowData = evalStkL+6 -.param_mask = evalStkL+5 -.param_tileTrans = evalStkL+4 -.param_pSmallTiles = evalStkL+3 -.param_blankTile = evalStkL+2 -.param_width = evalStkL+1 -.param_tilePtrs = evalStkL+0 -.srcOff = pTile -.dstOff = pTile+1 + +asmPlasmNoRet 8 +.param_mapRowData = evalStkL+7 +.param_mask = evalStkL+6 +.param_tileTrans = evalStkL+5 +.param_pSmallTiles = evalStkL+4 +.param_pSpecialTiles = evalStkL+3 +.param_blankTile = evalStkL+2 +.param_width = evalStkL+1 +.param_tilePtrs = evalStkL+0 +.srcOff = scanFor +.dstOff = pTile ; temporary use since we don't need it in this routine +.special = pTile+1 ; ditto ; psudocode: ; byte x, mapRaw, tileNum ; for x = 0 to width-1 ; mapRaw = ^(mapRowData + x) & $1F -; if mapRaw -; if tileTrans -; tileNum = ^(tileTrans + ((mapRaw - 1) << 1)) +; if mapRaw and (^(mapRowData + x) & $40) // automap 'seen' flag +; tileNum = scanSpecials(x) +; if tileNum +; tilePtrs[x] = pSpecialTiles + ((tileNum-1) * 9) // 9 bytes per reduced tile in the tileset ; else -; tileNum = mapRaw +; if tileTrans +; tileNum = ^(tileTrans + ((mapRaw - 1) << 1)) +; else +; tileNum = mapRaw +; fin +; tilePtrs[x] = pSmallTiles + ((tileNum-1) * 9) // 9 bytes per reduced tile in the tileset ; fin -; tilePtrs[x] = pSmallTiles + ((tileNum-1) * 9) // 9 bytes per reduced tile in the tileset ; else ; tilePtrs[x] = @blankTile ; fin @@ -297,6 +313,13 @@ asm fillRow(mapRowData, mask, tileTrans, pSmallTiles, blankTile, width, tilePtrs asl bpl .blank ; skip unless $40 bit is set denoting this space has been seen lsr + pha + jsr $100 ; scan for automap specials override + sta .special + beq + + dex ; to use pSpecialTiles instead of pSmallTiles + bpl .got ; always taken ++ pla ; normal processing (no special override) and .param_mask,x ; mask to get just tile number beq .blank tay @@ -307,6 +330,7 @@ asm fillRow(mapRowData, mask, tileTrans, pSmallTiles, blankTile, width, tilePtrs asl tay lda (pTmp),y +.got tay .notrans dey ; tileNum - 1 @@ -324,11 +348,14 @@ asm fillRow(mapRowData, mask, tileTrans, pSmallTiles, blankTile, width, tilePtrs bcc + inc tmp+1 + clc - adc .param_pSmallTiles,x + adc .param_pSmallTiles,x ; X may have been adjusted to address pSpecialTiles instead pha lda tmp+1 adc .param_pSmallTiles+HB,x - bcc .store ; always taken + ldy .special + beq + + inx ; back to using normal pSmallTiles ++ bcc .store ; always taken .blank lda .param_blankTile,x pha @@ -475,11 +502,58 @@ asm mergeMarks(allMarks, mapNum, mapData, width, stride, height)#0 } ; end of zone end +/////////////////////////////////////////////////////////////////////////////////////////////////// +asm _scanSpecials_start()#0 +; Advance pSpecials looking for 'scanFor' +!zone { + ; This gets copied to and run from $100 so it can easily access aux mem + sta setAuxRd + + lda #$60 + sta 0 + jsr 0 ; FOO + +.loop + ldy #0 + lda (pSpecials),y + iny + cmp scanFor + beq + + eor #$FF ; if end of table... + beq .ret ; ...return zero (and don't go past end of table) + lda (pSpecials),y + tay ++ tya ; at this point, y=1 is match, 2+ is no-match skipping + sec ; yes, add one extra + adc pSpecials + sta pSpecials + bcc + + inc pSpecials+1 ++ dey ; if len was 1, it was match; >=2 no match, loop again + bne .loop + lda (pSpecials),y ; y=0: match, get the value inside +.ret + sta clrAuxRd + rts +} +end +asm _scanSpecials_end()#0 + nop ; dummy +end + /////////////////////////////////////////////////////////////////////////////////////////////////// def loadMarks()#0 word len - // First, call the automark write routine. This has not only the effect of flushing the marks + // Load the specials table since partition zero is probably still open + auxMmgr(START_LOAD, 1) // partition 1 is where the table lives + pSpecialsBuf = auxMmgr(QUEUE_LOAD, CODE_GEN_MAP_SPECIALS<<8 | RES_TYPE_CODE) + + // While we're at it, load the automap special tiles. + pSpecTiles = mmgr(QUEUE_LOAD, 2<<8 | RES_TYPE_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 // to disk, but also leaving them loaded for us at $4000 (main). writeMarks @@ -487,17 +561,20 @@ def loadMarks()#0 len = *$4000 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 = pSpecialsBuf + 1 + ((^pSpecialsBuf) << 5) end /////////////////////////////////////////////////////////////////////////////////////////////////// -def displayRow3D(pScreen, mapRowData, tileTrans, pSmallTiles, width)#0 - fillRow(mapRowData, $1F, tileTrans, pSmallTiles, @blankTile, width, @tilePtrs) +def displayRow3D(pScreen, mapRowData, tileTrans, pSmallTiles, pSpecialTiles, width)#0 + fillRow(mapRowData, $1F, tileTrans, pSmallTiles, pSpecialTiles, @blankTile, width, @tilePtrs) drawSlice(@blankTile, pScreen, width, @tilePtrs) end /////////////////////////////////////////////////////////////////////////////////////////////////// -def displayRow2D(pScreen, mapRowData, pSmallTiles, width)#0 - fillRow(mapRowData, $3F, NULL, pSmallTiles, @blankTile, width, @tilePtrs) +def displayRow2D(pScreen, mapRowData, pSmallTiles, pSpecialTiles, width)#0 + fillRow(mapRowData, $3F, NULL, pSmallTiles, pSpecialTiles, @blankTile, width, @tilePtrs) drawSlice(@blankTile, pScreen, width, @tilePtrs) end @@ -625,13 +702,10 @@ def freeSections#0 end /////////////////////////////////////////////////////////////////////////////////////////////////// -def displaySection3D(pSection)#0 - word pSmallTiles, tileTrans, mapData, rowData +def displaySection3D(pSection, pSmallTiles)#0 + word tileTrans, mapData, rowData, specBlk byte nTextures, y, rowSize, line, lx - // Figure out where the small tiles reside (at the end of the full size tiles) - pSmallTiles = pSection=>pm_tileset + 1 + ((^(pSection=>pm_tileset)) << 5) - // Extract significant pointers from the map blob rowSize = ^(pSection=>pm_map) tileTrans = pSection=>pm_map + 4 @@ -654,22 +728,28 @@ def displaySection3D(pSection)#0 line = (pSection->bm_sy << 3) + MAP_TOP lx = MAP_LEFT + pSection->bm_sx + // Find the map data in the specials buf + *specPtr = pSpecialsBuf + ^specScanFor = pSection->bm_mapNum | $80 + scanSpecials()#0 + specBlk = *specPtr + // Display each visible row for y = 1 to pSection->bm_ch // offset is 1 to skip over sentinel row - displayRow3D(getScreenLine(line) + lx, rowData, tileTrans, pSmallTiles, pSection->bm_cw) + *specPtr = specBlk + ^specScanFor = y + pSection->wm_y0 + scanSpecials()#0 + displayRow3D(getScreenLine(line) + lx, rowData, tileTrans, pSmallTiles, pSpecialTiles, pSection->bm_cw) rowData = rowData + rowSize line = line + 8 next end /////////////////////////////////////////////////////////////////////////////////////////////////// -def displaySection2D(pSection)#0 - word pSmallTiles, rowData +def displaySection2D(pSection, pSmallTiles)#0 + word rowData byte y, line, lx - // Figure out where the small tiles reside (at the end of the full size tiles) - pSmallTiles = pSection=>pm_tileset + 1 + ((^(pSection=>pm_tileset)) << 5) - // Merge automap marks into the data if not done yet rowData = pSection=>pm_map + 6 // header = 6 bytes if pSection->bm_needMarks @@ -683,9 +763,14 @@ def displaySection2D(pSection)#0 line = (pSection->bm_sy << 3) + MAP_TOP lx = MAP_LEFT + pSection->bm_sx + // Find the map data in the specials buf + *specPtr = pSpecialsBuf + ^specScanFor = pSection->bm_mapNum + scanSpecials()#0 + // Display each visible row for y = 1 to pSection->bm_ch - displayRow2D(getScreenLine(line) + lx, rowData, pSmallTiles, pSection->bm_cw) + displayRow2D(getScreenLine(line) + lx, rowData, pSmallTiles, pSpecialTiles, pSection->bm_cw) rowData = rowData + SECTION_WIDTH_2D line = line + 8 next @@ -693,15 +778,23 @@ end /////////////////////////////////////////////////////////////////////////////////////////////////// def displaySections#0 - word pSection + word pSection, pSmallTiles, x pSection = @sectionBuf + + // Set up routine that scans the specials table in aux mem (routine lives in low stack page) + memcpy(@_scanSpecials_start, scanSpecials, @_scanSpecials_end - @_scanSpecials_start, 0) + while pSection <> pLastSection //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 + 1 + ((^(pSection=>pm_tileset)) << 5) + + // And draw (different routines to handle differing map data layouts) if mapIs3D - displaySection3D(pSection) + displaySection3D(pSection, pSmallTiles) else - displaySection2D(pSection) + displaySection2D(pSection, pSmallTiles) fin fin pSection = pSection + TMapSection @@ -914,6 +1007,8 @@ def _automap_show()#1 until key == 27 or key == 'Q' or key == '-' // esc or Q or - to exit auxMmgr(FREE_MEMORY, pAllMarks) + auxMmgr(FREE_MEMORY, pSpecialsBuf) + mmgr(FREE_MEMORY, pSpecTiles) return 0 end diff --git a/Platform/Apple/virtual/src/plasma/gameloop.pla b/Platform/Apple/virtual/src/plasma/gameloop.pla index 0ac6c2ce..218ac4fa 100644 --- a/Platform/Apple/virtual/src/plasma/gameloop.pla +++ b/Platform/Apple/virtual/src/plasma/gameloop.pla @@ -2228,6 +2228,7 @@ def initMap(x, y, dir)#0 else mmgr(QUEUE_LOAD, CODE_TILE_ENGINE<<8 | RES_TYPE_CODE) fin + pGlobalTileset = mmgr(QUEUE_LOAD, 1<<8 | RES_TYPE_TILESET) // even in 3d, need tiles for lamp/etc. mmgr(FINISH_LOAD, 0) // Set up the command table @@ -2237,7 +2238,6 @@ def initMap(x, y, dir)#0 curMapPartition = lookupResourcePart(mapIs3D+1, mapNum) mmgr(START_LOAD, curMapPartition) pCurMap = mmgr(QUEUE_LOAD, mapNum<<8 | (RES_TYPE_2D_MAP+mapIs3D)) - pGlobalTileset = mmgr(QUEUE_LOAD, 1<<8 | RES_TYPE_TILESET) // even in 3d, need tiles for lamp/etc. mmgr(FINISH_LOAD, 0) // Clear all the windows to the background color (hi-bit set)