diff --git a/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy b/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy index 9686befe..c288df46 100644 --- a/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy +++ b/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy @@ -263,6 +263,9 @@ class PackPartitions srcPos += 2 } dstPos += 18 + + // Skip unused source data + srcPos += (40 - 18)*2 } // Put the results into the buffer @@ -652,7 +655,6 @@ class PackPartitions //println "Packing frame image #$num named '${imgEl.@name}'." def buf = parseFrameData(imgEl) frames[imgEl.@name] = [num:num, buf:buf] - return buf } def packPortrait(imgEl) @@ -662,7 +664,7 @@ class PackPartitions //println "Packing 126 image named '${imgEl.@name}'." def buf = parse126Data(imgEl) portraits[imgEl.@name] = [num:num, buf:buf] - //println "...compressed: ${buf.len} bytes." + //println "...uncompressed: ${buf.position()} bytes." } def packTile(imgEl) @@ -1784,9 +1786,15 @@ class PackPartitions } } + // Process the map name + def shortName = mapName.replaceAll(/[\s-]*[23][dD][-0-9]*$/, '').take(12) + def extra = (12 - shortName.length()) >> 1 + shortName = (" " * extra) + shortName + // Code to register the table and map name emitCodeByte(0x26) // LA - def textAddr = addString(mapName) + println "Adding string: $shortName" + def textAddr = addString(shortName) emitCodeFixup(textAddr) emitCodeByte(0x26) // LA emitCodeFixup(dataAddr()) diff --git a/Platform/Apple/virtual/src/plasma/gameloop.pla b/Platform/Apple/virtual/src/plasma/gameloop.pla index bd6d69bf..b669f1e2 100644 --- a/Platform/Apple/virtual/src/plasma/gameloop.pla +++ b/Platform/Apple/virtual/src/plasma/gameloop.pla @@ -36,6 +36,7 @@ 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 // Memory banks const MAIN_MEM = 0 @@ -96,6 +97,7 @@ byte needRender = FALSE word skyNum = 9 word groundNum = 10 +byte portraitNum = 1 // Queue setMap / teleport, since otherwise script might be replaced while executing byte q_mapIs3D @@ -170,6 +172,95 @@ asm render // no params jmp $6018 end +/////////////////////////////////////////////////////////////////////////////////////////////////// +asm blitPortrait // params: srcData, dstScreenPtr + +asmPlasm 2 + + ; Save the dest pointer + sta pTmp + sty pTmp+1 + + ; Save the source pointer + lda evalStkL+1,x + sta tmp + lda evalStkH+1,x + sta tmp+1 + + ; Create the following subroutine, used to copy pixels from aux to main: + ; 0010- 8D 03 C0 STA $C003 + ; 0013- B1 02 LDA ($02),Y + ; 0015- 91 04 STA ($04),Y + ; 0017- 88 DEY + ; 0018- 10 F9 BPL $0013 + ; 001A- 8D 02 C0 STA $C002 + ; 001D- 60 RTS + lda #$8D + sta $10 + sta $1A + ldx #2 + stx $14 + stx $1B + inx + stx $11 + lda #$C0 + sta $12 + sta $1C + lda #$B1 + sta $13 + lda #$91 + sta $15 + inx + stx $16 + lda #$88 + sta $17 + lda #$10 + sta $18 + lda #$F9 + sta $19 + lda #$60 + sta $1D + + ; Outer copy loop + ldx #128 ; line count +.loop ldy #17 ; byte count minus 1 + jsr $10 ; copy pixel bytes + + ; Advance to next row of data + lda tmp + clc + adc #18 + sta tmp + bcc + + inc tmp+1 ++ + ; Fun code to advance to the next hi-res line + ldy pTmp+1 + iny + iny + iny + iny + cpy #$40 + bcc .ok2 + tya + sbc #$20 ; carry already set + tay + lda pTmp + eor #$80 + bmi .ok + iny + cpy #$24 + bcc .ok + ldy #$20 + adc #$27 ; carry was set, so actually adding $28 +.ok sta pTmp +.ok2 sty pTmp+1 + + ; Loop until we've done all rows. + dex + bne .loop + rts +end + /////////////////////////////////////////////////////////////////////////////////////////////////// // Simply retrieve the X register. Used to double-check that we're not leaking PLASMA eval // stack entries. @@ -352,6 +443,19 @@ asm clearWindow jmp clearWINDOW end +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Display a string using the font engine, but without any break checking. +// Params: pStr +asm rawDisplayStr + +asmPlasm 1 + pha + tya + tax ; hi byte of addr to X + pla + tay ; lo byte of addr to Y + jmp printSTR +end + /////////////////////////////////////////////////////////////////////////////////////////////////// // Display a string using the font engine. Automatically splits lines to keep words from breaking. // Params: pStr @@ -360,58 +464,61 @@ asm displayStr sta pTmp sty pTmp+1 ldy #0 - lda (pTmp),y - beq ++ - inc pTmp + lda (pTmp),y ; get string length + beq .done ; if zero, get out. + inc pTmp ; advance past string len bne + inc pTmp+1 + --- tax +-- tax ; length will be tracked in X reg ldy #0 -- lda (pTmp),y - cmp #$20 +- lda (pTmp),y ; next character + cmp #$20 ; check for invalid control chars bcc + - cmp #$80 + cmp #$80 ; check for invalid hi-bit chars bcc ++ -+ lda #$C4 ++ lda #$C4 ; failure path jsr $fded brk -++ dex - cmp #$20 +++ dex ; used a char + cmp #$20 ; is the char a space? beq + - sta $281,y + sta $281,y ; no, save to word buffer iny - cpx #0 + cpx #0 ; last char? bne - -+ sty $280 ++ sty $280 ; found a word break; save word length. tya sec - adc pTmp + adc pTmp ; advance main pointer over word sta pTmp bcc + inc pTmp+1 -+ txa ++ txa ; save X reg pha - tya + tya ; string length clc - adc cursh + adc cursh ; ...plus cursor pos sec sbc #2 - cmp wndwdth + cmp wndwdth ; ...vs. window width bcc + - lda #$D + lda #$D ; force a line break jsr printCHAR -+ ldy #$80 ++ tya ; if zero length (e.g. string starts with space), just print the space + beq + + ldy #$80 ; now display string at $280 (word buf) ldx #2 jsr printSTR lda cursh cmp wndleft - beq + - lda #$20 + beq ++ ++ lda #$20 jsr printCHAR -+ pla +++ pla ; restore string length bne -- -++ lda #$d +.done: + lda #$d jmp printCHAR end @@ -542,6 +649,7 @@ end def setSky(num) skyNum = num setColor(0, skyNum) + needRender = TRUE end /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -555,6 +663,7 @@ end def setGround(num) groundNum = num setColor(1, groundNum) + needRender = TRUE end /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -646,36 +755,40 @@ def initMap(x, y, dir) end /////////////////////////////////////////////////////////////////////////////////////////////////// -// Window for the map name bar -def setWindow1() - ^wndtop = 1 - ^wndbtm = 2 - ^wndleft = 4 - ^wndwdth = 18 +def setWindow(top, btm, lft, rt) + ^wndtop = top + ^wndbtm = btm + ^wndleft = lft + ^wndwdth = rt ^cursv = ^wndtop ^cursh = ^wndleft end +// Window for the map name bar +def setWindow1() + setWindow(1, 2, 5, 17) +end + /////////////////////////////////////////////////////////////////////////////////////////////////// // Window for the large upper right bar def setWindow2() - ^wndtop = 3 - ^wndbtm = 17 - ^wndleft = 22 - ^wndwdth = 37 - ^cursv = ^wndtop - ^cursh = ^wndleft + setWindow(3, 17, 22, 37) end /////////////////////////////////////////////////////////////////////////////////////////////////// // Window for the mid-size lower right bar def setWindow3() - ^wndtop = 18 - ^wndbtm = 23 - ^wndleft = 23 - ^wndwdth = 37 - ^cursv = ^wndtop - ^cursh = ^wndleft + setWindow(18, 23, 23, 37) +end + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Window for the map area (used for clearing it) +def setMapWindow() + if mapIs3D + setWindow(3, 19, 2, 19) + else + setWindow(3, 21, 2, 19) + fin end /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -808,9 +921,13 @@ def setMap(is3D, num, x, y, dir) setDir(dir) needRender = TRUE else + flipToPage1() + setWindow1(); clearWindow() + rawDisplayStr("Traveling...") + setMapWindow(); clearWindow() + setWindow2(); clearWindow() mapIs3D = is3D mapNum = num - flipToPage1() initMap(x, y, dir) fin // Don't check scripts, because we often land on an "Exit to wilderness?" script @@ -853,8 +970,11 @@ def showPos() ^$c053 if ^$25 < 23; ^$25 = 23; fin getPos(@x, @y) - printf3("\nCurrent: X=%d Y=%d Facing=%d\n", x, y, getDir()) - puts("Hit any key.\n") + printf2("\nX=%d Y=%d ", x, y) + if mapIs3D + printf3("Facing=%d Sky=%d Ground=%d", getDir(), skyNum, groundNum) + fin + puts("\nHit any key.\n") getUpperKey() ^$c052 end @@ -916,7 +1036,8 @@ def setScriptInfo(mapName, trigTbl) // Display map name setWindow1() - //displayStr(mapName) + clearWindow() + rawDisplayStr(mapName) // Back to the main text window. setWindow2() @@ -934,6 +1055,10 @@ end // Get a key, and don't return until it's Y or N (or lower-case of those). Returns 1 for Y. def getYN() byte key + if needRender + render() + needRender = FALSE + fin while TRUE key = getUpperKey() if key == 'Y' @@ -947,6 +1072,34 @@ def getYN() loop end +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Test out portrait drawing +def testPortrait() + byte img + word srcData + + flipToPage1() + + setWindow2() + clearWindow() + + setMapWindow() + clearWindow() + + srcData = loader(QUEUE_LOAD, AUX_MEM, portraitNum<<8 | RES_TYPE_PORTRAIT) + loader(FINISH_LOAD, MAIN_MEM, 0) // 0 = close + + if mapIs3D + blitPortrait(srcData, $2182) // start at 3rd text line + else + blitPortrait(srcData, $2202) // start at 4th text line + fin + + loader(FREE_MEMORY, AUX_MEM, srcData) + + portraitNum = portraitNum + 1 +end + /////////////////////////////////////////////////////////////////////////////////////////////////// // Set up the command table for 3D mode def initCmds() @@ -960,6 +1113,7 @@ def initCmds() // Commands common to both 2D and 3D initCmd('T', @kbdTeleport) initCmd('P', @showPos) + initCmd('/', @testPortrait) // Commands handled differently in 3D vs 2D if mapIs3D diff --git a/Platform/Apple/virtual/src/raycast/render.s b/Platform/Apple/virtual/src/raycast/render.s index 89ec42d2..a3354ff5 100644 --- a/Platform/Apple/virtual/src/raycast/render.s +++ b/Platform/Apple/virtual/src/raycast/render.s @@ -1986,6 +1986,7 @@ pl_setColor: !zone tay ; color number lda evalStkL+1,x and #1 + asl tax ; slot lda skyGndTbl1,y sta skyColorEven,x