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 flags = 0
if ([colNum, rowNum] in locationsWithTriggers)
flags |= 0x20
if (tile?.@obstruction == 'true')
flags |= 0x40
if (tile?.@obstruction == 'true')
flags |= 0x80
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
def inCommon = it.tileIds.intersect(tileIds)
def together = it.tileIds + tileIds
if (together.size() <= 32 && inCommon.size() > bestCommon) {
if (together.size() <= 64 && inCommon.size() > bestCommon) {
tileSet = it
bestCommon = inCommon.size()
}
@ -762,7 +762,7 @@ class PackPartitions
def id = tile?.@id
if (tile && !tileMap.containsKey(id)) {
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
tiles[id].flip() // crazy stuff to append one buffer to another
buf.put(tiles[id])
@ -1748,7 +1748,9 @@ class PackPartitions
y -= yRange[0]
if (!triggers[y])
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.
triggers.each { y, xs ->
emitDataByte(y)
emitDataByte(2 + (xs.size() * 3)) // 2 bytes for y+off, plus 3 bytes per trigger (x, adrlo, adrhi)
xs.each { x, funcAddr ->
emitDataByte(x)
emitDataFixup(funcAddr)
def size = 2 // 2 bytes for y+off
xs.each { x, funcAddrs ->
size += funcAddrs.size() * 3 // plus 3 bytes per trigger (x, adrlo, adrhi)
}
emitDataByte(size)
xs.each { x, funcAddrs ->
funcAddrs.each { funcAddr ->
emitDataByte(x)
emitDataFixup(funcAddr)
}
// Record a list of trigger locations for the caller's reference
locationsWithTriggers << [x, y]
}

View File

@ -1906,14 +1906,16 @@ doAllFixups: !zone
; Utility routine for convenient assembly routines in PLASMA code.
; Params: Y=number of parameters passed from PLASMA routine
; 1. Save PLASMA's X register index to evalStk
; 2. Switch to ROM
; 3. Load the last parameter into A=lo, Y=hi
; 4. Run the calling routine (X still points into evalStk for add'l params if needed)
; 5. Switch back to LC RAM
; 6. Restore PLASMA's X register, and advance it over the parameter(s)
; 7. Store A=lo/Y=hi into PLASMA return value
; 8. Return to PLASMA
; 2. Verify X register is in the range 0-$10
; 3. Switch to ROM
; 4. Load the *last* parameter into A=lo, Y=hi
; 5. Run the calling routine (X still points into evalStk for add'l params if needed)
; 6. Switch back to LC RAM
; 7. Restore PLASMA's X register, and advance it over the parameter(s)
; 8. Store A=lo/Y=hi into PLASMA return value
; 9. Return to PLASMA
__asmPlasm: !zone
bit setROM ; switch to ROM
pla ; save address of calling routine, so we can call it
clc
adc #1
@ -1925,9 +1927,12 @@ __asmPlasm: !zone
dey
sty tmp
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
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
ldy evalStkH,x ; ...Y=hi
.jsr jsr $1111 ; call the routine to do work
@ -1940,6 +1945,16 @@ __asmPlasm: !zone
tya
sta evalStkH,x
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

View File

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

View File

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

View File

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

View File

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