Got triggers working right on 3D map, including multiple triggers per location.

This commit is contained in:
Martin Haye 2015-05-15 08:19:18 -07:00
parent 375cac1459
commit 80cf3ddb03
6 changed files with 133 additions and 119 deletions

View File

@ -470,9 +470,9 @@ class PackPartitions
def tile = (row && x < width) ? row[x] : null def tile = (row && x < width) ? row[x] : null
def flags = 0 def flags = 0
if ([colNum, rowNum] in locationsWithTriggers) if ([colNum, rowNum] in locationsWithTriggers)
flags |= 0x20
if (tile?.@obstruction == 'true')
flags |= 0x40 flags |= 0x40
if (tile?.@obstruction == 'true')
flags |= 0x80
buf.put((byte)((tile ? tileMap[tile.@id] : 0) | flags)) buf.put((byte)((tile ? tileMap[tile.@id] : 0) | flags))
} }
} }
@ -727,7 +727,7 @@ class PackPartitions
// See if the set we're considering has room for all our tiles // See if the set we're considering has room for all our tiles
def inCommon = it.tileIds.intersect(tileIds) def inCommon = it.tileIds.intersect(tileIds)
def together = it.tileIds + tileIds def together = it.tileIds + tileIds
if (together.size() <= 32 && inCommon.size() > bestCommon) { if (together.size() <= 64 && inCommon.size() > bestCommon) {
tileSet = it tileSet = it
bestCommon = inCommon.size() bestCommon = inCommon.size()
} }
@ -762,7 +762,7 @@ class PackPartitions
def id = tile?.@id def id = tile?.@id
if (tile && !tileMap.containsKey(id)) { if (tile && !tileMap.containsKey(id)) {
def num = tileMap.size()+1 def num = tileMap.size()+1
assert num < 32 : "Error: Only 31 kinds of tiles are allowed on any given map." assert num < 64 : "Error: Only 63 kinds of tiles are allowed on any given map."
tileMap[id] = num tileMap[id] = num
tiles[id].flip() // crazy stuff to append one buffer to another tiles[id].flip() // crazy stuff to append one buffer to another
buf.put(tiles[id]) buf.put(tiles[id])
@ -1748,7 +1748,9 @@ class PackPartitions
y -= yRange[0] y -= yRange[0]
if (!triggers[y]) if (!triggers[y])
triggers[y] = [:] as TreeMap triggers[y] = [:] as TreeMap
triggers[y][x] = (idx+1) * 5 // address of function if (!triggers[y][x])
triggers[y][x] = []
triggers[y][x].add((idx+1) * 5) // address of function
} }
} }
} }
@ -1767,10 +1769,16 @@ class PackPartitions
// The table itself goes in the data segment. // The table itself goes in the data segment.
triggers.each { y, xs -> triggers.each { y, xs ->
emitDataByte(y) emitDataByte(y)
emitDataByte(2 + (xs.size() * 3)) // 2 bytes for y+off, plus 3 bytes per trigger (x, adrlo, adrhi) def size = 2 // 2 bytes for y+off
xs.each { x, funcAddr -> xs.each { x, funcAddrs ->
emitDataByte(x) size += funcAddrs.size() * 3 // plus 3 bytes per trigger (x, adrlo, adrhi)
emitDataFixup(funcAddr) }
emitDataByte(size)
xs.each { x, funcAddrs ->
funcAddrs.each { funcAddr ->
emitDataByte(x)
emitDataFixup(funcAddr)
}
// Record a list of trigger locations for the caller's reference // Record a list of trigger locations for the caller's reference
locationsWithTriggers << [x, y] locationsWithTriggers << [x, y]
} }

View File

@ -1906,14 +1906,16 @@ doAllFixups: !zone
; Utility routine for convenient assembly routines in PLASMA code. ; Utility routine for convenient assembly routines in PLASMA code.
; Params: Y=number of parameters passed from PLASMA routine ; Params: Y=number of parameters passed from PLASMA routine
; 1. Save PLASMA's X register index to evalStk ; 1. Save PLASMA's X register index to evalStk
; 2. Switch to ROM ; 2. Verify X register is in the range 0-$10
; 3. Load the last parameter into A=lo, Y=hi ; 3. Switch to ROM
; 4. Run the calling routine (X still points into evalStk for add'l params if needed) ; 4. Load the *last* parameter into A=lo, Y=hi
; 5. Switch back to LC RAM ; 5. Run the calling routine (X still points into evalStk for add'l params if needed)
; 6. Restore PLASMA's X register, and advance it over the parameter(s) ; 6. Switch back to LC RAM
; 7. Store A=lo/Y=hi into PLASMA return value ; 7. Restore PLASMA's X register, and advance it over the parameter(s)
; 8. Return to PLASMA ; 8. Store A=lo/Y=hi into PLASMA return value
; 9. Return to PLASMA
__asmPlasm: !zone __asmPlasm: !zone
bit setROM ; switch to ROM
pla ; save address of calling routine, so we can call it pla ; save address of calling routine, so we can call it
clc clc
adc #1 adc #1
@ -1925,9 +1927,12 @@ __asmPlasm: !zone
dey dey
sty tmp sty tmp
txa txa
.add adc tmp cpx #$11
bcs .badx ; X must be in range 0..$10
.add adc tmp ; carry cleared by cpx above
pha ; and save that pha ; and save that
bit setROM ; switch to ROM cmp #$11 ; again, X must be in range 0..$10
bcs .badx
lda evalStkL,x ; get last param to A=lo lda evalStkL,x ; get last param to A=lo
ldy evalStkH,x ; ...Y=hi ldy evalStkH,x ; ...Y=hi
.jsr jsr $1111 ; call the routine to do work .jsr jsr $1111 ; call the routine to do work
@ -1940,6 +1945,16 @@ __asmPlasm: !zone
tya tya
sta evalStkH,x sta evalStkH,x
rts ; and return to PLASMA interpreter rts ; and return to PLASMA interpreter
.badx jsr crout ; X reg ran outside valid range. Print and abort.
lda #'X'
jsr cout
txa
jsr prbyte
jsr crout
ldx #<+
ldy #>+
jmp fatalError
+ !text $8D, "PLASMA x-reg out of range", 0
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
; Segment tables ; Segment tables

View File

@ -277,16 +277,16 @@ FATAL_ERROR = $1F
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
; Convenience for writing assembly routines in PLASMA source ; Convenience for writing assembly routines in PLASMA source
; Macro param: number of parameters passed from PLASMA routine ; Macro param: number of parameters passed from PLASMA to the asm routine
; 1. Save PLASMA's X register index ; 1. Save PLASMA's X register index to evalStk
; 2. Switch to ROM ; 2. Verify X register is in the range 0-$10
; 3. Load the last parameter (if any) into A=lo, Y=hi ; 3. Switch to ROM
; 4. Run the calling routine (X still points into evalStk for add'l params if needed) ; 4. Load the *last* parameter into A=lo, Y=hi
; 5. Switch back to LC RAM ; 5. Run the calling routine (X still points into evalStk for add'l params if needed)
; 6. Restore PLASMA's X register, and advance it over the parameter(s), leaving ; 6. Switch back to LC RAM
; space for the return value. ; 7. Restore PLASMA's X register, and advance it over the parameter(s)
; 7. Store A=lo/Y=hi into PLASMA return value ; 8. Store A=lo/Y=hi into PLASMA return value
; 8. Return to PLASMA ; 9. Return to PLASMA
!macro asmPlasm nArgs { !macro asmPlasm nArgs {
ldy #nArgs ldy #nArgs
jsr _asmPlasm jsr _asmPlasm

View File

@ -91,6 +91,7 @@ word triggerTbl
byte redraw byte redraw
byte frameLoaded = 0 byte frameLoaded = 0
byte textDrawn = FALSE byte textDrawn = FALSE
byte needRender = FALSE
word skyNum = 9 word skyNum = 9
word groundNum = 10 word groundNum = 10
@ -125,30 +126,39 @@ end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
// API to call rendering engine (same API for raycaster and tile engine) // API to call rendering engine (same API for raycaster and tile engine)
asm initDisplay // params: mapNum, pMapData, x, y, dir asm initDisplay // params: mapNum, pMapData, x, y, dir
+asmPlasm 5
jmp $6000 jmp $6000
end end
asm flipToPage1 // no params asm flipToPage1 // no params
+asmPlasm 0
jmp $6003 jmp $6003
end end
asm getPos // params: @x, @y asm getPos // params: @x, @y
+asmPlasm 2
jmp $6006 jmp $6006
end end
asm setPos // params: x, y asm setPos // params: x, y
+asmPlasm 2
jmp $6009 jmp $6009
end end
asm getDir // no params; returns: dir (0-15) asm getDir // no params; returns: dir (0-15)
+asmPlasm 0
jmp $600C jmp $600C
end end
asm setDir // params: dir (0-15) asm setDir // params: dir (0-15)
+asmPlasm 1
jmp $600F jmp $600F
end end
asm advance // no params; return: 0 if same pos, 1 if new pos, 2 if new pos and scripted asm advance // no params; return: 0 if same pos, 1 if new pos, 2 if new pos and scripted
+asmPlasm 0
jmp $6012 jmp $6012
end end
asm setColor // params: slot (0=sky/1=ground), color (0-15) asm setColor // params: slot (0=sky/1=ground), color (0-15)
+asmPlasm 2
jmp $6015 jmp $6015
end end
asm render // no params asm render // no params
+asmPlasm 0
jmp $6018 jmp $6018
end end
@ -156,11 +166,9 @@ end
// Simply retrieve the X register. Used to double-check that we're not leaking PLASMA eval // Simply retrieve the X register. Used to double-check that we're not leaking PLASMA eval
// stack entries. // stack entries.
asm getXReg asm getXReg
+asmPlasm 0
txa txa
dex ; make room for return value ldy #0
sta evalStkL,x
lda #0
sta evalStkH,x
rts rts
end end
@ -628,6 +636,7 @@ def initMap(x, y, dir)
puts("Calling initDisplay.\n") puts("Calling initDisplay.\n")
initDisplay(mapNum, pMap, x, y, dir) initDisplay(mapNum, pMap, x, y, dir)
puts("Back from initDisplay.\n") puts("Back from initDisplay.\n")
needRender = FALSE
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -700,12 +709,20 @@ end
def moveForward() def moveForward()
byte val byte val
val = advance() val = advance()
printf1("advance returned %d\n", val)
if val > 0 and textDrawn // If not blocked, render at the new position.
if val > 0
needRender = TRUE
fin
// If we're on a new map tile, clear text from script(s) on the old tile.
if val >= 2 and textDrawn
clearWindow() clearWindow()
textDrawn = FALSE textDrawn = FALSE
fin fin
if val == 2
// If there are script(s) on the new tile, run them.
if val == 3
checkScripts() checkScripts()
fin fin
end end
@ -728,16 +745,14 @@ end
// Turn left (3D mode) // Turn left (3D mode)
def rotateLeft() def rotateLeft()
adjustDir(-1) adjustDir(-1)
render() needRender = TRUE
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
// Rotate to the right (3D mode) // Rotate to the right (3D mode)
def rotateRight() def rotateRight()
adjustDir(1) adjustDir(1)
puts("About to call render.\n") needRender = TRUE
render()
puts("Back from render.\n")
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -788,7 +803,7 @@ def setMap(is3D, num, x, y, dir)
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
def teleport() def kbdTeleport()
word x, y word x, y
byte dir byte dir
@ -815,9 +830,11 @@ def teleport()
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
def oldTeleport(x, y, dir) def teleport(x, y, dir)
printf3("Old teleport: x=%d y=%d dir=%d\n", x, y, dir) printf3("Teleport: x=%d y=%d dir=%d\n", x, y, dir)
puts("Doing nothing for now.\n") setPos(x, y)
setDir(dir)
needRender = TRUE
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -838,6 +855,10 @@ def kbdLoop()
func = cmdTbl[key] func = cmdTbl[key]
if func; func(); fin if func; func(); fin
fin fin
if needRender
render()
needRender = FALSE
fin
loop loop
end end
@ -855,10 +876,8 @@ def setScriptInfo(mapName, trigTbl)
setWindow1() setWindow1()
//displayStr(mapName) //displayStr(mapName)
// Set up for drawing other script text. // Back to the main text window.
setWindow2() setWindow2()
clearWindow()
textDrawn = FALSE
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -897,7 +916,7 @@ def initCmds()
next next
// Commands common to both 2D and 3D // Commands common to both 2D and 3D
initCmd('T', @teleport) initCmd('T', @kbdTeleport)
// Commands handled differently in 3D vs 2D // Commands handled differently in 3D vs 2D
if mapIs3D if mapIs3D
@ -987,7 +1006,7 @@ def setCallbacks()
// $312 // $312
callbacks.18 = $4c callbacks.18 = $4c
callbacks:19 = @oldTeleport callbacks:19 = @teleport
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -1668,13 +1668,11 @@ calcMapOrigin: !zone
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; Advance in current direction if not blocked. ; Advance in current direction if not blocked.
; Params: none ; Params: none
; Return: 0 if same map tile; ; Return: 0 if blocked;
; 1 if pos is on a new map tile; ; 1 if advanced but still within same map tile;
; 2 if that new tile is also scripted ; 2 if pos is on a new map tile;
; 3 if that new tile is also scripted
pl_advance: !zone pl_advance: !zone
txa
pha ; save PLASMA eval stk pos
bit setROM ; switch out PLASMA while we work
lda playerDir lda playerDir
asl asl
asl ; shift twice: each dir is 4 bytes in table asl ; shift twice: each dir is 4 bytes in table
@ -1699,7 +1697,6 @@ pl_advance: !zone
sta playerY sta playerY
lda playerY+1 lda playerY+1
pha pha
clc
adc walkDirs+3,x adc walkDirs+3,x
sta playerY+1 sta playerY+1
@ -1728,9 +1725,7 @@ pl_advance: !zone
sta playerX sta playerX
ldy #0 ldy #0
beq .done beq .done
.ok ; Not blocked. Render at the new position .ok ; Not blocked. See if we're in a new map tile.
jsr renderFrame
; See if we're in a new map tile.
pla pla
eor playerY+1 eor playerY+1
sta tmp sta tmp
@ -1741,39 +1736,26 @@ pl_advance: !zone
tay tay
pla pla
tya tya
beq .done ; if not a new map tile, return zero bne +
; It is a new position. Is script hint set? iny ; not a new map tile, return 1
bne .done ; always taken
+ ; It is a new map tile. Is script hint set?
ldy playerX+1 ldy playerX+1
lda (pMap),y lda (pMap),y
ldy #1 ; ret val 1 = new blk but no script ldy #2 ; ret val 2 = new blk but no script
and #$20 ; map flag $20 is the script hint and #$20 ; map flag $20 is the script hint
beq .done ; if not scripted, return one beq .done ; if not scripted, return one
iny ; else return 2 = new blk and a script iny ; else return 3 = new blk and a script
.done pla .done tya ; retrieve ret value
tax ; restore PLASMA eval stk pos ldy #0 ; hi byte of ret is always 0
dex ; make room for return value rts ; all done
tya ; retrieve ret value
sta evalStkL,x ; and store it
lda #0
sta evalStkH,x ; hi byte of return is zero
bit setLcRW+lcBank2 ; switch PLASMA runtime back in
rts ; and return to PLASMA
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; Render at the current position and direction. ; Render at the current position and direction.
; Params: none ; Params: none
; Return: none ; Return: none
pl_render: !zone pl_render: !zone
txa jmp renderFrame
pha ; save PLASMA eval stk pos
bit setROM ; switch out PLASMA while we work
jsr renderFrame
pla
tax ; restore PLASMA eval stk pos
jsr prbyte
jsr crout
bit setLcRW+lcBank2 ; switch PLASMA runtime back in
rts ; and return to PLASMA
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; Cast all the rays from the current player coord ; Cast all the rays from the current player coord
@ -1934,12 +1916,16 @@ copyScreen: !zone
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; Called by PLASMA code to get the position on the map. ; Called by PLASMA code to get the position on the map.
; Parameters: @x, @y ; Parameters: @x, @y
; Returns: Nothing ; Returns: Nothing (but stores into the addressed variables)
pl_getPos: !zone { pl_getPos: !zone {
lda playerY+1 lda playerY+1
sec
sbc #1 ; adjust for border guards
jsr .sto jsr .sto
inx inx
lda playerX+1 lda playerX+1
sec
sbc #1 ; adjust for border guards
; Now fall thru, and exit with X incremented once (2 params - 1 return slot = 1) ; Now fall thru, and exit with X incremented once (2 params - 1 return slot = 1)
.sto ldy evalStkL,x .sto ldy evalStkL,x
sty pTmp sty pTmp
@ -1958,14 +1944,16 @@ pl_getPos: !zone {
; Parameters: x, y ; Parameters: x, y
; Returns: Nothing ; Returns: Nothing
pl_setPos: !zone { pl_setPos: !zone {
lda evalStkL,x clc
adc #1 ; adjust for border guards
sta playerY+1 sta playerY+1
lda evalStkL+1,x lda evalStkL+1,x
clc
adc #1 ; adjust for border guards
sta playerX+1 sta playerX+1
lda #$80 lda #$80
sta playerY sta playerY
sta playerX sta playerX
inx ; 2 params - 1 ret = +1
rts rts
} }
@ -1975,10 +1963,7 @@ pl_setPos: !zone {
; Returns: Nothing ; Returns: Nothing
pl_getDir: !zone { pl_getDir: !zone {
lda playerDir lda playerDir
dex ldy #0
sta evalStkL,x
lda #0
sta evalStkH,x
rts rts
} }
@ -1987,35 +1972,28 @@ pl_getDir: !zone {
; Parameters: dir (0-15) ; Parameters: dir (0-15)
; Returns: Nothing ; Returns: Nothing
pl_setDir: !zone { pl_setDir: !zone {
lda evalStkL,x
and #15 and #15
sta playerDir sta playerDir
dex ; 0 param - 1 ret = -1
rts rts
} }
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
pl_setColor: !zone pl_setColor: !zone
lda evalStkL,x ; color number and #15
tay tay ; color number
lda skyGndTbl2,y lda evalStkL+1,x
pha
lda skyGndTbl1,y
pha
lda evalStkH,x ; slot
and #1 and #1
asl tax ; slot
tay lda skyGndTbl1,y
pla sta skyColorEven,x
sta skyColorEven,y lda skyGndTbl2,y
pla sta skyColorOdd,x
sta skyColorOdd,y
inx ; toss unused stack slot (parms=2, ret=1, diff=1)
rts rts
;------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------
; The real action ; The real action
pl_initMap: !zone pl_initMap: !zone
; Figure out PLASMA stack for calling script init
txa txa
clc clc
adc #5 ; 5 params adc #5 ; 5 params
@ -2030,7 +2008,6 @@ pl_initMap: !zone
inx inx
jsr pl_setPos jsr pl_setPos
; Proceed with loading ; Proceed with loading
bit setROM ; switch out PLASMA runtime while we work
jsr loadTextures jsr loadTextures
jsr copyScreen jsr copyScreen
lda tablesInitted lda tablesInitted
@ -2045,11 +2022,7 @@ pl_initMap: !zone
sta tablesInitted sta tablesInitted
jsr setExpansionCaller jsr setExpansionCaller
jsr graphInit jsr graphInit
jsr renderFrame jmp renderFrame
bit setLcRW+lcBank2 ; switch PLASMA runtime back in
ldx plasmaStk ; restore PLASMA's eval stk pos
dex ; make room for dummy return (inc'd over params earlier)
rts
; Following are log/pow lookup tables. For speed, align them on a page boundary. ; Following are log/pow lookup tables. For speed, align them on a page boundary.
!align 255,0 !align 255,0

View File

@ -220,10 +220,9 @@ LOAD_TILESET
;---------------------------------------------------------------------- ;----------------------------------------------------------------------
; >> GET TILE IN CARDINAL DIRECTION AND FLAGS ; >> GET TILE IN CARDINAL DIRECTION AND FLAGS
; (Returns Tile # in Y, Flags in A) ; (Returns Tile # in Y, Flags in A)
; Each tile in memory can be 0-32, the flags are the upper 3 bits ; Each tile in memory can be 0-63, the flags are the upper 2 bits
; 0 0 0 ; 0 0
; | | `- Visible obstruction (Can not see behind it) ; | `--- Obstructed / Boundary (Can not walk on it)
; | `--- Boundary (Can not walk on it)
; `----- Script assigned, triggers script lookup ; `----- Script assigned, triggers script lookup
;---------------------------------------------------------------------- ;----------------------------------------------------------------------
; >> SET X,Y COORDINATES FOR VIEWPORT CENTER ; >> SET X,Y COORDINATES FOR VIEWPORT CENTER
@ -841,15 +840,16 @@ ROW_OFFSET = 3
LDA #>emptyTile+1 LDA #>emptyTile+1
BNE .store_src ; always taken BNE .store_src ; always taken
.not_empty .not_empty
; Calculate location of tile data == tile_base + (((tile & 31) - 1) * 32) ; Calculate location of tile data == tile_base + (((tile & 63) - 1) * 32)
LDY #0 LDY #0
STY TILE_SOURCE+1 STY TILE_SOURCE+1
AND #31 AND #63
SEC SEC
SBC #1 ; tile map is 1-based, tile set indexes are 0-based SBC #1 ; tile map is 1-based, tile set indexes are 0-based
ASL ASL
ASL ASL
ASL ASL
ROL TILE_SOURCE+1
ASL ASL
ROL TILE_SOURCE+1 ROL TILE_SOURCE+1
ASL ASL
@ -1289,8 +1289,7 @@ ADVANCE: !zone {
JSR CALC JSR CALC
LDA AVATAR_TILE ; get tile flags LDA AVATAR_TILE ; get tile flags
AND #$40 ; obstructed? BPL + ; no hi bit = not obstructed
BEQ +
; Player moved to an obstructed place. Undo! ; Player moved to an obstructed place. Undo!
LDA AVATAR_DIR LDA AVATAR_DIR
@ -1314,7 +1313,7 @@ ADVANCE: !zone {
BEQ .ret BEQ .ret
INY ; moved INY ; moved
LDA AVATAR_TILE LDA AVATAR_TILE
AND #$20 ; check script flag AND #$40 ; check script flag
BEQ .ret BEQ .ret
INY ; moved and also new place is scripted INY ; moved and also new place is scripted
.ret RTS .ret RTS