From 9e94928f0a09ab959ad4c0d0a47e3d6c2fe1fa5e Mon Sep 17 00:00:00 2001 From: Martin Haye Date: Thu, 9 Apr 2015 10:31:36 -0700 Subject: [PATCH] More refactoring. --- .../src/org/demo/PackPartitions.groovy | 73 +++---- .../Apple/virtual/src/plasma/gameloop.pla | 188 +++++++----------- Platform/Apple/virtual/src/raycast/render.s | 139 ++++++------- 3 files changed, 157 insertions(+), 243 deletions(-) diff --git a/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy b/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy index 6cbc7f7b..74bd7872 100644 --- a/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy +++ b/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy @@ -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.. (0.. @@ -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() diff --git a/Platform/Apple/virtual/src/plasma/gameloop.pla b/Platform/Apple/virtual/src/plasma/gameloop.pla index ca666f2f..f476f28a 100644 --- a/Platform/Apple/virtual/src/plasma/gameloop.pla +++ b/Platform/Apple/virtual/src/plasma/gameloop.pla @@ -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 /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Platform/Apple/virtual/src/raycast/render.s b/Platform/Apple/virtual/src/raycast/render.s index a95ea0a9..208a17b5 100644 --- a/Platform/Apple/virtual/src/raycast/render.s +++ b/Platform/Apple/virtual/src/raycast/render.s @@ -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 - 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.