diff --git a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy index 572db1b8..7f9725e7 100644 --- a/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy +++ b/Platform/Apple/tools/PackPartitions/src/org/badvision/A2PackPartitions.groovy @@ -95,6 +95,7 @@ class A2PackPartitions def maps2D = [:] // map name to map.num, map.buf def maps3D = [:] // map name to map.num, map.buf 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 avatars = [:] // avatar tile name to tile num (within the special tileset) def lampTiles = [] // animated series of lamp tiles @@ -281,10 +282,8 @@ class A2PackPartitions return DatatypeConverter.printHexBinary(md.digest()) } - def pixelize(dataEl) + def pixelize(dataEl, stride, nBytes, nLines) { - def nBytes = dataEl.@width as int - def nLines = dataEl.@height as int def hexStr = dataEl.text() return (0.. def outRow = [] @@ -314,15 +313,48 @@ class A2PackPartitions // Locate the data for the Apple II (as opposed to C64 etc.) def data = imgEl.displayData?.find { it.@platform == "AppleII" } assert data : "image '${imgEl.@name}' missing AppleII platform data" - def rows = pixelize(data) + def rows = pixelize(data, data.@width as int, 10, 64) // Retain only the upper-left 64 lines x 32 pixels - return rows[0..63].collect { it[0..31] } + return rows.collect { it[0..31] } + } + + /* + * Add a pixel to a reduction pixel buffer + */ + def addPix(pixBuf, hibitBuf, int pix) + { + if (pixBuf.containsKey(pix)) + pixBuf[pix] += 1 + else + pixBuf[pix] = 1 + + int hibit = pix >> 2 + if (hibitBuf.containsKey(hibit)) + hibitBuf[hibit] += 1 + else + hibitBuf[hibit] = 1 } /* * Parse raw tile image data and return it as a buffer. */ + def choosePix(pixBuf, x, y) + { + def inv = ((((x>>1)+(y>>1)) & 1) * 2) - 1 // 1 or -1, in a dither pattern + inv = 1 // FOO: no dither for now + def accum = [] + pixBuf.each { pix, count -> + accum << [count, pix*inv] + } + def choice = accum.sort().reverse()[0] + return Math.abs(choice[1]) + } + + /* + * Parse raw tile image data and return it as a two buffers: fullsize mainBuf, + * and reduced size smBuf + */ def parseTileData(imgEl) { // Locate the data for the Apple II (as opposed to C64 etc.) @@ -331,14 +363,44 @@ class A2PackPartitions // Parse out the hex data on each line and add it to a buffer. def hexStr = dataEl.text() - def outBuf = ByteBuffer.allocate(50000) + def mainBuf = ByteBuffer.allocate(32) for (def pos = 0; pos < hexStr.size(); pos += 2) { def val = Integer.parseInt(hexStr[pos..pos+1], 16) - outBuf.put((byte)val) + mainBuf.put((byte)val) } - // All done. Return the buffer. - return outBuf + // Make a reduced-size version + def rows = pixelize(dataEl, 2, 2, 16) + def smBuf = ByteBuffer.allocate(9) + smBuf.put((byte)0) // placeholder for hi bits + def hibits = 0 + def pixBuf + for (int y = 0; y < 16; y += 2) + { + def hibitBuf = [:] + def outByte = 0 + for (int x = 0; x < 7; x += 2) + { + pixBuf = [:] + addPix(pixBuf, hibitBuf, rows[y] [x]) + addPix(pixBuf, hibitBuf, rows[y+1][x]) + if (x < 6) { + addPix(pixBuf, hibitBuf, rows[y] [x+1]) + addPix(pixBuf, hibitBuf, rows[y+1][x+1]) + } + def outPix = choosePix(pixBuf, x, y) + outByte = (outByte >> 2) | ((outPix & 3) << 6) + } + // No: (outByte >> 7) | ((outByte << 1) & 0xFF) // rotate one bit for efficient Apple II code + smBuf.put((byte)outByte) + hibits = (hibits >> 1) | (choosePix(hibitBuf, 0, y) << 7) + } + smBuf.position(0) + smBuf.put((byte)hibits) + smBuf.position(9) + + // All done. Return the buffers. + return [mainBuf, smBuf] } /* @@ -875,8 +937,9 @@ class A2PackPartitions def packTile(imgEl) { - def buf = parseTileData(imgEl) - tiles[imgEl.@id] = buf + def (mainBuf, smBuf) = parseTileData(imgEl) + tiles[imgEl.@id] = mainBuf + smTiles[imgEl.@id] = smBuf } /** Identify the avatars and other global tiles, and number them */ @@ -920,7 +983,7 @@ class A2PackPartitions } } - tileSets[setName] = [num:setNum, buf:buf, tileMap:tileMap, tileIds:tileIds] + tileSets[setName] = [num:setNum, mainBuf:buf, smBuf:ByteBuffer.allocate(1), tileMap:tileMap, tileIds:tileIds] return [setNum, tileMap] } @@ -968,7 +1031,11 @@ class A2PackPartitions else { setNum = tileSets.size() + 1 //println "Creating new tileSet $setNum." - tileSet = [num:setNum, buf:ByteBuffer.allocate(50000), tileMap:[:], tileIds:tileIds] + tileSet = [num:setNum, + mainBuf:ByteBuffer.allocate(50000), + smBuf:ByteBuffer.allocate(20000), + tileMap:[:], + tileIds:tileIds] tileSets["tileSet${setNum}"] = tileSet } @@ -977,7 +1044,8 @@ class A2PackPartitions // Start by assuming we'll create a new tileset def tileMap = tileSet.tileMap - def buf = tileSet.buf + def mainBuf = tileSet.mainBuf + def smBuf = tileSet.smBuf // Then add each non-null tile to the set (yOff ..< yOff+height).each { y -> @@ -990,12 +1058,15 @@ class A2PackPartitions assert num < 64 : "Error: Only 63 kinds of tiles are allowed on any given map." tileMap[id] = num tiles[id].flip() // crazy stuff to append one buffer to another - buf.put(tiles[id]) + mainBuf.put(tiles[id]) + smTiles[id].flip() + smBuf.put(smTiles[id]) } } } assert tileMap.size() > 0 - assert buf.position() > 0 + assert mainBuf.position() > 0 + assert smBuf.position() > 0 return [setNum, tileMap] } @@ -2377,7 +2448,13 @@ class A2PackPartitions // Now that the tileSets are complete, compress them. tileSets.each { name, tileSet -> - tileSet.buf = compress(unwrapByteBuffer(tileSet.buf)) + def buf = ByteBuffer.allocate(50000) + buf.put((byte)(tileSet.tileIds.size())) + tileSet.mainBuf.flip() // crazy stuff to append one buffer to another + buf.put(tileSet.mainBuf) + tileSet.smBuf.flip() // crazy stuff to append one buffer to another + buf.put(tileSet.smBuf) + tileSet.buf = compress(unwrapByteBuffer(buf)) } //println("rdeps - phase 2:" + JsonOutput.prettyPrint(JsonOutput.toJson(resourceDeps))) @@ -4062,8 +4139,8 @@ end outIndented("p_player = global=>p_players\n") outIndented("while p_player\n") ++indent - outIndented( - "setStat(p_player, $stat, getStat(p_player, $stat) ${blk.@type == 'interaction_increase_party_stats' ? '+' : '-'} $amount)\n") + outIndented("setStat(p_player, $stat, getStat(p_player, $stat) " + + "${blk.@type == 'interaction_increase_party_stats' ? '+' : '-'} $amount)\n") outIndented("p_player = p_player=>p_nextObj\n") --indent outIndented("loop\n") diff --git a/Platform/Apple/virtual/src/plasma/automap.pla b/Platform/Apple/virtual/src/plasma/automap.pla index 07d0a657..64506b65 100644 --- a/Platform/Apple/virtual/src/plasma/automap.pla +++ b/Platform/Apple/virtual/src/plasma/automap.pla @@ -19,7 +19,7 @@ predef _automap_show()#1 word[] funcTbl = @_automap_show word tilePtrs[40] -byte blankTile[32] +byte blankTile[9] /////////////////////////////////////////////////////////////////////////////////////////////////// // Definitions used by assembly code @@ -28,150 +28,121 @@ asm _defs !source "../../include/global.i" !source "../../include/plasma.i" !source "../../include/mem.i" +!source "../../include/fontEngine.i" tmp = $2 ; length 2 pTmp = $4 ; length 2 -pix0 = $6 ; length 1 -pix1 = $7 ; length 1 -tilePtrs = $8 ; length 2 -tileOff = $A ; length 1 -nTiles = $B ; length 1 -pScreen = $C ; length 2 -pTile = $E ; length 2 -ysav = $34 +tilePtrs = $6 ; length 2 +pTile = $8 ; length 2 +pBlank = $A ; length 2 +hibits = $C ; length 1 +nTiles = $D ; length 1 +prevBits = $E ; length 1 +unused0F = $F ; length 1 +linePtrs = $10 ; length 2*8 = 16 +ysav = $34 ; length 1 end /////////////////////////////////////////////////////////////////////////////////////////////////// -asm drawSlice(tilePtrs, nTiles, pScreen)#0 - +asmPlasmNoRet 3 - - lda #$60 - sta 0 - jsr 0 ; FOO - - lda #0 ; start at zero tile offset -.row - sta tileOff - sty pScreen+1 - lda evalStkL+0,x ; re-init low byte of screen ptr each row - sta pScreen +asm drawSlice(pBlank, pScreen, nTiles, tilePtrs)#0 + +asmPlasmNoRet 4 + sta tilePtrs + sty tilePtrs+1 lda evalStkL+1,x sta nTiles lda evalStkL+2,x - sta tilePtrs + sta pTmp lda evalStkH+2,x - sta tilePtrs+1 - clc ; start with even-tile logic -.tileLoop + sta pTmp+1 + lda evalStkL+3,x + sta pBlank + lda evalStkH+3,x + sta pBlank+1 + ; Grab the line pointers for all 8 lines + ldx #0 +- lda pTmp + sta linePtrs,x + inx + lda pTmp+1 + sta linePtrs,x + inx + jsr NextScreenLine + cpx #16 + bne - + ; Process one tile +.tile ldy #0 lda (tilePtrs),y sta pTile - inc tilePtrs - bne + - inc tilePtrs+1 -+ lda (tilePtrs),y + iny + lda (tilePtrs),y sta pTile+1 - inc tilePtrs - bne + - inc tilePtrs+1 -+ ldy tileOff ; start at correct vertical offset within each tile - lda (pTile),y - bcs .oddTile ; first time even, second time odd, third time even, etc. -.evenTile - lsr ; in bit A-0 - ror pix0 ; out bit 0 - lsr ; in bit A-1 - ror pix0 ; out bit 1 - lsr ; in bit A-2 (skip) - lsr ; in bit A-3 (skip) - lsr ; in bit A-4 - ror pix0 ; out bit 2 - lsr ; in bit A-5 - ror pix0 ; out bit 3 - ; in bit A-6 (skip) - ; in bit A-7 (hi skip) - iny - lda (pTile),y - lsr ; in bit A-8 (skip) - lsr ; in bit A-9 - ror pix0 ; out bit 4 - lsr ; in bit A-10 - ror pix0 ; out bit 5 - lsr ; in bit A-11 (skip) - lsr ; in bit A-12 (skip) - lsr ; in bit A-13 - ror pix0 ; out bit 6 - lsr ; in bit A-14 - ror pix1 ; out bit 8 (!) - lsr ; in bit A-15 (hibit) - ror pix0 ; out bit 7 (!) - lda pix0 - sec ; next iteration, use odd-tile logic - -.store - ldy #0 - sta (pScreen),y - inc pScreen - dec nTiles ; count down tiles done - bne .tileLoop ; go until we've done all tiles for the row - lda pScreen+1 + lda tilePtrs clc - adc #4 ; advance to next screen line - tay - lda tileOff ; carry already clear from above - adc #4 ; advance 2 rows within the tiles (1 we did, 1 skipping for downsize) - cmp #32 ; until done with all 32 bytes of tiles - bcc .row - rts ; finished - -.oddTile - lsr ; in bit B-0 (skip) - lsr ; in bit B-1 (skip) - lsr ; in bit B-2 - ror pix1 ; out bit 9 - lsr ; in bit B-3 - ror pix1 ; out bit 10 - lsr ; in bit B-4 (skip) - lsr ; in bit B-5 (skip) - lsr ; in bit B-6 - ror pix1 ; out bit 11 - ; in bit B-7 (hi skip) - iny + adc #2 + sta tilePtrs + bcc + + inc tilePtrs+1 ++ dey lda (pTile),y - lsr ; in bit B-8 - ror pix1 ; out bit 12 - lsr ; in bit B-9 (skip) - lsr ; in bit B-10 (skip) - lsr ; in bit B-11 - ror pix1 ; out bit 13 - lsr ; in bit B-12 - ror pix1 ; out bit 14 - lsr ; in bit B-13 (skip) - lsr ; in bit B-14 (skip) - lsr ; in bit B-15 (hibit) - ror pix1 ; out bit 15 (hibit) - lda pix1 - clc ; next iteration, use even-tile logic - bcc .store ; always taken + sta hibits + sta (pBlank),y ; if next tile is blank, match hi bits of this tile + iny + ldx #0 + lda linePtrs + lsr + bcs .odd +.even + lda (pTile),y + iny + asl + ror prevBits + lsr hibits + ror + sta (linePtrs,x) + inc linePtrs,x + inx + inx + cpx #16 + bne .even + beq .next ; always taken +.odd + lda (pTile),y + iny + lsr prevBits + rol + asl + lsr hibits + ror + sta (linePtrs,x) + inc linePtrs,x + inx + inx + cpx #16 + bne .odd +.next + dec nTiles + bne .tile + rts end /////////////////////////////////////////////////////////////////////////////////////////////////// -def displayRow(rowNum, mapRowData, tileTrans, pTileset, width)#0 +def displayRow(rowNum, mapRowData, tileTrans, pSmallTiles, width)#0 byte x, mapRaw, tileNum for x = 0 to width-1 mapRaw = ^(mapRowData + x) & $1F if mapRaw tileNum = ^(tileTrans + ((mapRaw - 1) << 1)) - tilePtrs[x] = pTileset + ((tileNum-1) << 5) // 32 bytes per tile in the tileset + tilePtrs[x] = pSmallTiles + ((tileNum-1) * 9) // 9 bytes per reduced tile in the tileset else tilePtrs[x] = @blankTile fin next - drawSlice(@tilePtrs, width, getScreenLine((rowNum+2)<<3) + 2) + drawSlice(@blankTile, getScreenLine((rowNum+2)<<3) + 2, width, @tilePtrs) end /////////////////////////////////////////////////////////////////////////////////////////////////// def _automap_show()#1 - word pTileset, tileTrans, mapData + word pTileset, pSmallTiles, tileTrans, mapData byte nTextures, y, rowSize, numRows setBigWindow @@ -186,6 +157,9 @@ def _automap_show()#1 pTileset = mmgr(QUEUE_LOAD, (^(pCurMap+3))<<8 | RES_TYPE_TILESET) mmgr(FINISH_LOAD, 0) + // Figure out where the small tiles reside (at the end of the full size tiles) + pSmallTiles = pTileset + 1 + ((^pTileset) << 5) + // Extract significant pointers from the map blob rowSize = ^pCurMap numRows = ^(pCurMap+1) @@ -198,12 +172,12 @@ def _automap_show()#1 //printf2("mapData=$%x, rowSize=%d\n", mapData, rowSize) // FOO // Clear out the blank tile buffer - memset(@blankTile, 0, 32) + memset(@blankTile, 0, 9) // Display each row for y = 0 to numRows-3 // two sentinel rows, and an extra because zero-indexed. // The +1's below are to skip over the sentinel row and column that 3D maps have - displayRow(y, mapData + ((y+1)*rowSize) + 1, tileTrans, pTileset, rowSize-2) + displayRow(y, mapData + ((y+1)*rowSize) + 1, tileTrans, pSmallTiles, rowSize-2) next getUpperKey diff --git a/Platform/Apple/virtual/src/tile/tileEngine.s b/Platform/Apple/virtual/src/tile/tileEngine.s index 8f434df5..6e893226 100644 --- a/Platform/Apple/virtual/src/tile/tileEngine.s +++ b/Platform/Apple/virtual/src/tile/tileEngine.s @@ -862,7 +862,7 @@ ROW_OFFSET = 3 ROL .tsadd+1 DEY BNE - - CLC + SEC ; skip over initial count ADC GLOBAL_TILESET_LOC TAY LDA GLOBAL_TILESET_LOC+1 @@ -892,7 +892,7 @@ ROW_OFFSET = 3 ROL TILE_SOURCE+1 ASL ROL TILE_SOURCE+1 - CLC + SEC ; skip over initial tile count ADC TILE_BASE TAY LDA TILE_SOURCE+1