More refactoring.

This commit is contained in:
Martin Haye 2015-04-09 10:31:36 -07:00
parent 046b35faa9
commit 9e94928f0a
3 changed files with 157 additions and 243 deletions

View File

@ -434,9 +434,6 @@ class PackPartitions
}
}
// Finish the index buffer with the map name
writeString(indexBuf, mapName.replaceFirst(/ ?-? ?2D/, ""))
// Now create each map section
(0..<nVertSections).each { vsect ->
(0..<nHorzSections).each { hsect ->
@ -568,9 +565,6 @@ class PackPartitions
// Followed by script module num
buf.put((byte)scriptModule)
// Followed by name
writeString(buf, mapName.replaceFirst(/ ?-? ?3D/, ""))
// Followed by the list of textures
texList.each { buf.put((byte)it) }
buf.put((byte)0)
@ -798,18 +792,12 @@ class PackPartitions
def packScripts(mapEl, mapName, xRange = null, yRange = null)
{
if (!mapEl.scripts)
return [0, [] as Set]
def num = modules.size() + 1
def name = "mapScript$num"
//println "Packing scripts for map $mapName, to module $num."
ScriptModule module = new ScriptModule()
if (!module.packScripts(mapEl.scripts[0], xRange, yRange)) {
//println "...no scripts applied; will re-use module num"
return [0, [] as Set]
}
module.packScripts(mapName, mapEl.scripts ? mapEl.scripts[0] : [], xRange, yRange)
modules[name] = [num:num, buf:wrapByteList(module.data)]
bytecodes[name] = [num:num, buf:wrapByteList(module.bytecode)]
@ -1350,7 +1338,7 @@ class PackPartitions
def locationsWithTriggers = [] as Set
def vec_locationTrigger = 0x300
def vec_setScriptInfo = 0x300
def vec_displayStr = 0x303
def vec_getYN = 0x306
def vec_setMap = 0x309
@ -1370,10 +1358,8 @@ class PackPartitions
/**
* Pack scripts from a map. Either the whole map, or optionally just an X and Y
* bounded section of it.
*
* Returns true if any matching scripts were found.
*/
def packScripts(inScripts, xRange = null, yRange = null)
def packScripts(mapName, inScripts, xRange = null, yRange = null)
{
// If we're only processing a section of the map, make sure this script is
// referenced within that section.
@ -1388,21 +1374,19 @@ class PackPartitions
(!yRange || trig.@y.toInteger() in yRange) })
scripts << script
}
nScripts = scripts.script.size()
if (nScripts == 0)
return false
// Even if there were no scripts, we still need an init to display
// the map name.
makeStubs()
scripts.eachWithIndex { script, idx ->
packScript(idx, script)
}
makeInit(scripts, xRange, yRange)
makeInit(mapName, scripts, xRange, yRange)
emitFixupByte(0xFF)
//println "data: $data"
//println "bytecode: $bytecode"
//println "fixups: $fixups"
return true
}
def makeStubs()
@ -1683,7 +1667,7 @@ class PackPartitions
emitCodeByte(0x30) // DROP
}
def makeInit(scripts, xRange, yRange)
def makeInit(mapName, scripts, xRange, yRange)
{
//println " Script: special 'init'"
startFunc(0)
@ -1723,29 +1707,28 @@ class PackPartitions
}
}
// If any triggers, register and output a trigger table
if (triggers.size())
{
// Code to register the table
emitCodeByte(0x26) // LA
emitCodeFixup(dataAddr())
emitCodeByte(0x54) // CALL
emitCodeWord(vec_locationTrigger)
emitCodeByte(0x30) // DROP
// 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)
// Record a list of trigger locations for the caller's reference
locationsWithTriggers << [x, y]
}
// Code to register the table and map name
emitCodeByte(0x26) // LA
def textAddr = addString(mapName)
emitCodeFixup(textAddr)
emitCodeByte(0x26) // LA
emitCodeFixup(dataAddr())
emitCodeByte(0x54) // CALL
emitCodeWord(vec_setScriptInfo)
emitCodeByte(0x30) // DROP
// 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)
// Record a list of trigger locations for the caller's reference
locationsWithTriggers << [x, y]
}
emitDataByte(0xFF) // mark the end end of the trigger table
}
emitDataByte(0xFF) // mark the end end of the trigger table
// All done with the init function.
finishFunc()

View File

@ -59,7 +59,6 @@ const FATAL_ERROR = $1F
///////////////////////////////////////////////////////////////////////////////////////////////////
// Other constants
const callbacks = $300
const MAX_LOC_TRIG = 128
// 3D mode
//const OVERMAP_NUM = 11
@ -70,7 +69,7 @@ const OVERMAP_IS_3D = 0
///////////////////////////////////////////////////////////////////////////////////////////////////
// Predefined functions, for circular calls or out-of-order calls
predef setWindow2, initCmds2D, initCmds3D
predef setWindow2, initCmds
///////////////////////////////////////////////////////////////////////////////////////////////////
// Font engine variables
@ -87,13 +86,8 @@ byte mapNum = OVERMAP_NUM
byte mapIs3D = OVERMAP_IS_3D
word pFont
word pMap
word pScripts
word cmdTbl[64]
word triggerTbl
byte prevX
byte prevY
byte prevMapNum
byte prevMapIs3D
byte redraw
byte titleLoaded = FALSE
byte textDrawn = FALSE
@ -101,15 +95,6 @@ byte textDrawn = FALSE
word skyNum = 9
word groundNum = 10
///////////////////////////////////////////////////////////////////////////////////////////////////
// API to call rendering engine (same API for raycaster and tile engine)
const initDisplay = displayEngine + 0 // params: pMapData, x, y, dir; return: map name (as C str)
const flipToPage1 = displayEngine + 3 // params: none; return: nothing
const getPos = displayEngine + 6 // params: @x, @y, @dir; return: nothing
const setPos = displayEngine + 9 // params: x (0-255), y (0-255), dir (0-15); return: nothing
const advance = displayEngine + 12 // params: none; return: 1 if new pos *and* scripted
const setColor = displayEngine + 15 // params: slot (0=sky/1=ground), color (0-15); return: nothing
///////////////////////////////////////////////////////////////////////////////////////////////////
// Definitions used by assembly code
asm __defs
@ -133,6 +118,33 @@ pTmp = $4
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// API to call rendering engine (same API for raycaster and tile engine)
asm initDisplay // params: pMapData, x, y, dir
jmp $6000
end
asm flipToPage1 // no params
jmp $6003
end
asm getPos // params: @x, @y
jmp $6006
end
asm setPos // params: x (0-255), y (0-255)
jmp $6009
end
asm getDir // no params; returns: dir (0-15)
jmp $600C
end
asm setDir // params: dir (0-15)
jmp $600F
end
asm advance // no params; return: 0 if same pos, 1 if new pos, 2 if new pos and scripted
jmp $6012
end
asm setColor // params: slot (0=sky/1=ground), color (0-15)
jmp $6015
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Print a string
asm puts
@ -495,10 +507,8 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Load code and data, set up everything to display a 3D map
def initMap(x, y, dir)
word scriptModule
// Set up the command table
initCmds3D()
initCmds()
// Reset memory (our module will stay since memory manager locked it upon load)
loader(RESET_MEMORY, MAIN_MEM, 0)
@ -515,6 +525,8 @@ def initMap(x, y, dir)
if mapIs3D
loader(QUEUE_LOAD, MAIN_MEM, RES_NUM_RAYCASTER<<8 | RES_TYPE_CODE)
pMap = loader(QUEUE_LOAD, MAIN_MEM, mapNum<<8 | RES_TYPE_3D_MAP)
loader(SET_MEM_TARGET, AUX_MEM, expandVec)
loader(QUEUE_LOAD, AUX_MEM, RES_NUM_EXPAND_VEC<<8 | RES_TYPE_CODE)
else
loader(QUEUE_LOAD, MAIN_MEM, RES_NUM_TILE_ENGINE<<8 | RES_TYPE_CODE)
pMap = loader(QUEUE_LOAD, MAIN_MEM, mapNum<<8 | RES_TYPE_2D_MAP)
@ -526,30 +538,18 @@ def initMap(x, y, dir)
// Load the frame image (and lock it there)
loadFrameImg()
// Load the scripts for this map, if it has any.
scriptModule = pMap->2 // first 2 bytes are width and height, third byte is script module num
if scriptModule
pScripts = loader(QUEUE_LOAD, MAIN_MEM, (scriptModule << 8) | RES_TYPE_MODULE)
fin
loader(FINISH_LOAD, MAIN_MEM, 0) // 1 = keep open, for loading textures
// Start up the font engine
initFontEngine(pFont)
// Start up the display engine with map data and starting position
cMapName = initDisplay(pMap, x, y, dir)
// Initialize the map scripts
// Set up for map scripts
setWindow2()
clearWindow()
textDrawn = FALSE
prevX = -1
prevY = -1
// Start up the display engine with map data and starting position. This will also load and
// init the script module, if any, which will end up calling us back at the setTrigger
triggerTbl = NULL
if pScripts
*pScripts()
fin
initDisplay(pMap, x, y, dir)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -586,11 +586,17 @@ def setWindow3()
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def callScripts(x, y)
// Check for script(s) attached to the current location, and call them if there are any.
def checkScripts()
word x
word y
word p
word pNext
word script
if !triggerTbl; return; fin
setWindow2()
getPos(@x, @y)
p = triggerTbl
while TRUE
if ^p == $FF
@ -611,53 +617,24 @@ def callScripts(x, y)
loop
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Check for script(s) attached to the current location, and call them if there are any.
def checkScripts()
word x
word y
if !triggerTbl; return; fin
if mapIs3D
x = playerX.1 - 1
y = playerY.1 - 1
else
x = ^avatarX
y = ^avatarY
fin
if x <> prevX or y <> prevY
prevX = x
prevY = y
if textDrawn
clearWindow()
textDrawn = FALSE
fin
if isScripted()
callScripts(x, y)
if (mapNum <> prevMapNum) or (mapIs3D <> prevMapIs3D)
flipToPage1()
initMap()
fin
fin
fin
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Advance one step forward (3D maps only)
def moveForward()
word wasBlocked
word func
wasBlocked = isBlocked()
*playerX = *playerX + walkDirs[^playerDir << 1]
*playerY = *playerY + walkDirs[(^playerDir << 1) + 1]
if !wasBlocked and isBlocked()
moveBackward()
byte val
val = advance()
if val > 0 and textDrawn
clearWindow()
textDrawn = FALSE
fin
if val == 2
checkScripts()
fin
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Adjust player's direction plus or minus n increments (3D mode)
// Adjust player's direction plus or minus n increments
def adjustDir(n)
^playerDir = (^playerDir + n) & $F
setDir((getDir() + n) & 15)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -697,35 +674,24 @@ def strafeLeft()
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def move2D(ox, oy)
*relX = ox + *relX
*relY = oy + *relY
checkCrossing()
redraw = TRUE
end
def moveNorth()
move2D(0, -1)
setDir(0)
moveForward()
end
def moveEast()
move2D(1, 0)
setDir(4)
moveForward()
end
def moveSouth()
move2D(0, 1)
setDir(8)
moveForward()
end
def moveWest()
move2D(-1, 0)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Jump to a new map location (and point in the given direction)
def teleport(x, y, dir)
//nextX = x
//nextY = y
//nextDir = dir
setDir(12)
moveForward()
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -733,7 +699,9 @@ end
def setMap(is3D, num, x, y, dir)
mapIs3D = is3D
mapNum = num
teleport(x, y, dir)
flipToPage1()
initMap(x, y, dir)
checkScripts()
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -745,24 +713,18 @@ def kbdLoop()
key = key - $20
if key >= 0 and key < $40
func = cmdTbl[key]
if func
func()
renderFrame()
redraw = FALSE
checkScripts()
if redraw
renderFrame()
redraw = FALSE
fin
fin
if func; func(); fin
fin
loop
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Associate a location with a trigger function (i.e. a script)
def setLocationTrigger(tbl)
triggerTbl = tbl
// Set initial info for the scripts on this map: the trigger table and the name of the map. This
// is called by the init function for the scripts.
def setScriptInfo(mapName, trigTbl)
setWindow1()
displayStr(mapName)
triggerTbl = trigTbl
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -792,7 +754,7 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Set up the command table for 3D mode
def initCmds3D()
def initCmds()
// Clear the command table
byte i
@ -826,7 +788,7 @@ def initCmds3D()
initCmd('S', @moveSouth)
initCmd('X', @moveSouth)
initCmd('A', @moveWest)
end
fin
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -858,7 +820,7 @@ def setCallbacks()
// $300
callbacks.0 = $4c
callbacks:1 = @setLocationTrigger
callbacks:1 = @setScriptInfo
// $303
callbacks.3 = $4c
@ -879,10 +841,6 @@ def setCallbacks()
// $30F
callbacks.15 = $4c
callbacks:16 = @setGround
// $312
callbacks.18 = $4c
callbacks:19 = @teleport
end
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -10,11 +10,13 @@ start:
; then routines that call those to build complexity. The main
; code is at the very end.
jmp pl_initMap ; params: pMapData, x, y, dir; return: map name (as C str)
jmp pl_initMap ; params: pMapData, x, y, dir
jmp pl_flipToPage1 ; params: none; return: nothing
jmp pl_getPos ; params: @x, @y, @dir; return: nothing
jmp pl_setPos ; params: x (0-255), y (0-255), dir (0-15); return: nothing
jmp pl_advance ; params: none; return: 1 if new pos *and* scripted
jmp pl_getPos ; params: @x, @y; return: nothing
jmp pl_setPos ; params: x (0-255), y (0-255); return: nothing
jmp pl_getDir ; params: none; return: dir (0-15)
jmp pl_setDir ; params: dir (0-15); return: nothing
jmp pl_advance ; params: none; return: 0 if same, 1 if new map tile, 2 if new and scripted
jmp pl_setColor ; params: slot (0=sky/1=ground), color (0-15); return: nothing
; Conditional assembly flags
@ -38,7 +40,6 @@ MAX_SPRITES = 64 ; max # sprites visible at once
NUM_COLS = 63
SPRITE_DIST_LIMIT = 8
SPRITE_CT_LIMIT = 4
MAX_NAME_LEN = 14
; Starting position and dir. Eventually this will come from the map
PLAYER_START_X = $280 ; 1.5
@ -59,8 +60,6 @@ mapHeader: !word 0 ; map with header first
mapBase: !word 0 ; first byte after the header
mapRayOrigin: !word 0
mapNum: !byte 1
mapName: !word 0 ; pointer to map name
mapNameLen: !byte 0 ; length of map name
nMapSprites: !byte 0 ; number of sprite entries on map to fix up
nextLink: !byte 0 ; next link to allocate
tablesInitted: !byte 0 ; 1 after init
@ -1554,7 +1553,8 @@ getTileFlags: !zone
rts
;-------------------------------------------------------------------------------
; Load the texture expansion code, copy it to aux mem
; Parse map header, and load the textures into aux mem. Also loads the script
; module and inits it.
loadTextures: !zone
!if DEBUG { +prStr : !text "Loading textures.",0 }
; Scan the map header
@ -1566,29 +1566,14 @@ loadTextures: !zone
sta mapWidth ; and save it
jsr .get ; get map height
sta mapHeight ; and save it
jsr .get ; ignore script module num (it gets loaded by PLASMA code)
lda .get+1 ; current pointer is the map name
sta mapName ; save it
lda .get+2
sta mapName+1
lda #$FF ; pre-decrement, since the zero is going to be counted
sta mapNameLen
.skip: jsr .get ; skip over the map name
inc mapNameLen
cmp #0
bne .skip ; until end-of-string is reached (zero byte)
lda mapNameLen ; clamp length of map name
cmp #MAX_NAME_LEN
bcc .notrnc
lda mapName
sta .trunc+1
lda mapName+1
sta .trunc+2
ldx #MAX_NAME_LEN
lda #0
.trunc sta mapName,x
stx mapNameLen
.notrnc lda #0 ; now comes the list of textures.
jsr .get ; get script module num
tay ; and get ready to load it
lda #QUEUE_LOAD
ldx #RES_TYPE_MODULE
jsr mainLoader ; queue script to load
stx .scInit+1 ; store its location so we call its init...
sty .scInit+2 ; ...after it loads of course.
lda #0 ; now comes the list of textures.
sta txNum
.lup: jsr .get ; get texture resource number
tay ; to Y for mem manager
@ -1625,17 +1610,14 @@ loadTextures: !zone
; to load.
lda #FINISH_LOAD
ldx #0
jmp mainLoader
jsr mainLoader
; finally, init the scripts.
.scInit jmp $1111
.get: lda $1111
inc .get+1
bne +
inc .get+2
+ rts
.set lda .get+2
sta .set2+2
ldy .get+1
.set2 sta $1100,y
rts
;-------------------------------------------------------------------------------
; Set up front and back buffers, go to hires mode, and clear for first blit.
@ -1678,7 +1660,9 @@ calcMapOrigin: !zone
;-------------------------------------------------------------------------------
; Advance in current direction if not blocked.
; Params: none
; Return 1 if player is on a new block *and* that block has script(s).
; Return: 0 if same map tile;
; 1 if pos is on a new map tile;
; 2 if that new tile is also scripted
pl_advance: !zone
txa
pha ; save PLASMA eval stk pos
@ -1717,7 +1701,7 @@ pl_advance: !zone
ldy playerX+1
lda (pMap),y
and #$1F
beq +
beq .ok ; empty tiles are never blocked
tax
jsr getTileFlags
sta tmp+1
@ -1745,34 +1729,23 @@ pl_advance: !zone
tay
pla
tya
beq .done ; if not a new position, return zero
beq .done ; if not a new map tile, return zero
; It is a new position. Is script hint set?
ldy playerX+1
lda (pMap),y
ldy #0
ldy #1
and #$20 ; map flag $20 is the script hint
beq .done ; if not scripted, return zero
iny ; else return 1
beq .done ; if not scripted, return one
iny ; else return 2
.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
sta evalStkH,x ; hi byte of return is zero
bit setLcRW+lcBank2 ; switch PLASMA runtime back in
rts
;-------------------------------------------------------------------------------
; Check if the player's current location has a script flag on it
isScripted: !zone
jsr calcMapOrigin
sta pMap
sty pMap+1
ldy playerX+1
lda (pMap),y
and #$20
rts
rts ; and return to PLASMA
;-------------------------------------------------------------------------------
; Cast all the rays from the current player coord
@ -1926,17 +1899,14 @@ copyScreen: !zone
;-------------------------------------------------------------------------------
; Called by PLASMA code to get the position on the map.
; Parameters: @x, @y, @dir
; Parameters: @x, @y
; Returns: Nothing
pl_getPos: !zone {
lda playerDir
jsr .sto
inx
lda playerY+1
jsr .sto
inx
lda playerX+1
; Now fall thru, and exit with X incremented twice (3 params - 1 return slot = 2)
; Now fall thru, and exit with X incremented once (2 params - 1 return slot = 1)
.sto ldy evalStkL,x
sty pTmp
ldy evalStkH,x
@ -1951,15 +1921,12 @@ pl_getPos: !zone {
;-------------------------------------------------------------------------------
; Called by PLASMA code to set the position on the map.
; Parameters: x, y, dir
; Parameters: x, y
; Returns: Nothing
pl_setPos: !zone {
lda evalStkL,x
and #15
sta playerDir
lda evalStkL+1,x
sta playerY+1
lda evalStkL+2,x
lda evalStkL,x
sta playerX+1
lda #$80
sta playerY
@ -1967,6 +1934,29 @@ pl_setPos: !zone {
rts
}
;-------------------------------------------------------------------------------
; Called by PLASMA code to get the player's direction
; Parameters: dir (0-15)
; Returns: Nothing
pl_getDir: !zone {
lda playerDir
sta evalStkL,x
lda #0
sta evalStkH,x
rts
}
;-------------------------------------------------------------------------------
; Called by PLASMA code to set the player's direction
; Parameters: dir (0-15)
; Returns: Nothing
pl_setDir: !zone {
lda evalStkL,x
and #15
sta playerDir
rts
}
;-------------------------------------------------------------------------------
pl_setColor: !zone
lda evalStkL,x ; color number
@ -1986,18 +1976,6 @@ pl_setColor: !zone
inx ; toss unused stack slot (parms=2, ret=1, diff=1)
rts
;-------------------------------------------------------------------------------
; Load texture expansion code into aux mem
loadExpand: !zone
lda #SET_MEM_TARGET
ldx #<expandVec
ldy #>expandVec
jsr auxLoader
lda #QUEUE_LOAD
ldx #RES_TYPE_TEXTURE
ldy #RES_NUM_EXPAND_VEC
jmp auxLoader
;-------------------------------------------------------------------------------
; The real action
pl_initMap: !zone
@ -2012,7 +1990,6 @@ pl_initMap: !zone
jsr pl_setPos
; Proceed with loading
bit setROM ; switch out PLASMA while we work
jsr loadExpand
jsr loadTextures
jsr copyScreen
lda tablesInitted
@ -2035,10 +2012,6 @@ pl_initMap: !zone
inx
inx ; toss 3 slots (params=4, ret=1, diff=3)
inx
lda mapName
sta evalStkL,x ; return map name to PLASMA caller
lda mapName+1
sta evalStkH,x
rts
; Following are log/pow lookup tables. For speed, align them on a page boundary.