lawless-legends/Platform/Apple/virtual/src/plasma/gameloop.pla

897 lines
23 KiB
Plaintext
Raw Normal View History

2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Handy constants.
2014-06-25 15:47:28 +00:00
const FALSE = 0
const TRUE = !FALSE
const NULL = 0
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Fixed memory locations
2015-04-05 16:52:38 +00:00
const displayEngine = $6000 // main mem (raycaster and tile engine at same location)
const expandVec = $2000 // aux mem (only for raycaster)
const fontEngine = $BA00 // main mem
2014-07-06 21:40:35 +00:00
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Resource numbers
2014-07-06 21:40:35 +00:00
const RES_NUM_RAYCASTER = 1
const RES_NUM_EXPAND_VEC = 2
const RES_NUM_FONT_ENGINE = 3
const RES_NUM_TILE_ENGINE = 4
2014-07-06 21:40:35 +00:00
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Hardware addresses.
2014-06-25 15:47:28 +00:00
const keyboard = $C000
const keystrobe = $C010
2014-07-06 21:40:35 +00:00
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Memory manager definitions
2014-07-06 21:40:35 +00:00
2014-08-21 15:17:50 +00:00
// Resource types
2014-07-06 21:40:35 +00:00
const RES_TYPE_CODE = 1
const RES_TYPE_2D_MAP = 2
const RES_TYPE_3D_MAP = 3
const RES_TYPE_TILE = 4
const RES_TYPE_TEXTURE = 5
const RES_TYPE_SCREEN = 6
const RES_TYPE_FONT = 7
const RES_TYPE_MODULE = 8
const RES_TYPE_BYTECODE = 9
const RES_TYPE_FIXUP = 10
2014-08-21 15:17:50 +00:00
// Memory banks
2014-07-06 21:40:35 +00:00
const MAIN_MEM = 0
const AUX_MEM = 1
2014-08-21 15:17:50 +00:00
// Command codes
2014-07-06 21:40:35 +00:00
const RESET_MEMORY = $10
const REQUEST_MEMORY = $11
const LOCK_MEMORY = $12
const UNLOCK_MEMORY = $13
const SET_MEM_TARGET = $14
const START_LOAD = $15
const QUEUE_LOAD = $16
const FINISH_LOAD = $17
const FREE_MEMORY = $18
const CALC_FREE = $19
const DEBUG_MEM = $1A
2014-07-06 21:40:35 +00:00
const CHAIN_LOADER = $1E
const FATAL_ERROR = $1F
///////////////////////////////////////////////////////////////////////////////////////////////////
// Other constants
2014-07-09 02:11:03 +00:00
const callbacks = $300
const MAX_LOC_TRIG = 128
// 3D mode
//const OVERMAP_NUM = 11
//const OVERMAP_IS_3D = 1
// 2D mode
const OVERMAP_NUM = 1
const OVERMAP_IS_3D = 0
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Predefined functions, for circular calls or out-of-order calls
predef setWindow2, initCmds2D, initCmds3D
2015-01-18 16:59:56 +00:00
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Font engine variables
const wndleft = $70 // left edge of the window
const wndwdth = $71 // right edge (NOT width) of text window
const wndtop = $72 // top of text window
const wndbtm = $73 // bottom+1 of text window
const cursh = $74 // Cursor H-pos 0-39
const cursv = $75 // Cursor V-pos 0-23
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Global variables
byte mapNum = OVERMAP_NUM
byte mapIs3D = OVERMAP_IS_3D
2014-07-06 21:40:35 +00:00
word pFont
word pMap
word pScripts
word cmdTbl[64]
2015-02-27 13:33:11 +00:00
word triggerTbl
byte prevX
byte prevY
byte prevMapNum
byte prevMapIs3D
byte redraw
byte titleLoaded = FALSE
2015-03-03 17:03:22 +00:00
byte textDrawn = FALSE
word skyNum = 9
word groundNum = 10
2015-04-05 16:52:38 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// 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
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Definitions used by assembly code
asm __defs
2015-02-27 13:33:11 +00:00
; Use hi-bit ASCII for Apple II
!convtab "../../include/hiBitAscii.ct"
2015-02-27 13:33:11 +00:00
; Headers
2014-07-06 21:40:35 +00:00
!source "../../include/global.i"
!source "../../include/plasma.i"
!source "../../include/mem.i"
!source "../../include/fontEngine.i"
2015-02-27 13:33:11 +00:00
; Optional debug printing support
DEBUG = 1
!if DEBUG { !source "../../include/debug.i" }
; General use
tmp = $2
pTmp = $4
end
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Print a string
asm puts
+asmPlasm 1
2014-07-06 21:40:35 +00:00
sta pTmp
sty pTmp+1
2014-07-06 21:40:35 +00:00
ldy #0
lda (pTmp),y
tax
iny
- lda (pTmp),y
ora #$80
jsr cout
iny
dex
bne -
rts
2014-07-06 14:40:57 +00:00
end
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Print part of a string, until we hit the end or a '%' code. Return how far we got, or -1 for end.
asm partialPrintf
+asmPlasm 2
lda evalStkL+1,x
sta pTmp
lda evalStkH+1,x
sta pTmp+1
ldy #0
lda (pTmp),y ; get length byte
sec
sbc evalStkL,x ; minus offset
sta tmp ; to count of characters left to print
lda evalStkL,x ; get desired offset into string
tay
iny ; increment past length byte
inx ; drop second argument
- lda (pTmp),y
ora #$80
cmp #'%' ; stop if we hit % code
beq +
jsr cout
iny
dec tmp ; otherwise go until end of string
bne -
ldy #$FF ; if we hit end of string, return -1
tya
rts
+ dey ; adjust back for length byte
tya ; that's the lo byte of return
ldy #0 ; hi byte of return is zero
rts
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Print a 16-bit hex value
2014-07-06 14:40:57 +00:00
asm printHex
+asmPlasm 1
tax
tya
jmp prntax
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Print a single character
asm printChar
+asmPlasm 1
jmp cout
2014-06-25 15:47:28 +00:00
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Print a carriage return
asm crout
+asmPlasm 0
jmp crout
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Ring the bell
asm beep
+asmPlasm 0
jmp bell
end
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Send a command to the memory manager
2014-08-21 15:17:50 +00:00
// Params: cmd, mainOrAux, amount
asm loader
+asmPlasm 3
2014-07-06 21:40:35 +00:00
lda evalStkL+2,x ; command code
pha
lda evalStkL+1,x ; main or aux
lsr
ldy evalStkH,x ; address (or other param)
lda evalStkL,x
tax
pla
bcs +
jmp mainLoader ; ret value in A=lo/Y=hi
+ jmp auxLoader ; ditto
2014-07-06 21:40:35 +00:00
end
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Set up the font engine
// Params: pFont
asm initFontEngine
+asmPlasm 1
2014-07-06 21:40:35 +00:00
ldy evalStkL,x ; font engine likes *lo* byte in Y
lda evalStkH,x ; hi byte in X
tax
jsr setFONT
; Set to write text on both hi-res pages at the same time
lda #pHGR3
jsr displayMODE
; Set to normal (non-inverse) text
lda #pNORMAL
jmp drawMODE
end
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Jump straight to the system monitor
// Params: None
2014-07-06 21:40:35 +00:00
asm goMon
bit setROM
jmp $FF69
end
2015-03-03 17:03:22 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
2015-04-05 16:52:38 +00:00
// Execute a monitor breakpoint
2015-03-03 17:03:22 +00:00
// Params: None
asm brk
bit setROM
brk
end
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Use the font engine to clear the current text window
// Params: None
2014-07-09 02:11:03 +00:00
asm clearWindow
+asmPlasm 0
jmp clearWINDOW
2014-07-09 02:11:03 +00:00
end
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Display a string using the font engine. Automatically splits lines to keep words from breaking.
// Params: pStr
asm displayStr
+asmPlasm 1
2014-07-20 22:52:51 +00:00
sta pTmp
sty pTmp+1
2014-07-20 22:52:51 +00:00
ldy #0
lda (pTmp),y
beq ++
inc pTmp
bne +
inc pTmp+1
+
-- tax
ldy #0
- lda (pTmp),y
cmp #$20
bcc +
cmp #$80
bcc ++
+ lda #$C4
jsr $fded
brk
++ dex
2014-07-20 22:52:51 +00:00
cmp #$20
beq +
sta $281,y
iny
cpx #0
bne -
+ sty $280
tya
sec
adc pTmp
sta pTmp
bcc +
inc pTmp+1
+ txa
pha
tya
clc
adc cursh
sec
sbc #2
cmp wndwdth
bcc +
lda #$D
jsr printCHAR
+ ldy #$80
2014-07-20 22:52:51 +00:00
ldx #2
jsr printSTR
lda cursh
cmp wndleft
beq +
lda #$20
jsr printCHAR
+ pla
2014-07-20 22:52:51 +00:00
bne --
++ lda #$d
jmp printCHAR
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Convert a PLASMA string (starts with length, lo-bit ascii) to an assembly string
// (zero-terminated, hi-bit ascii).
asm toAsmStr
lda evalStkL,x
sta pTmp
lda evalStkH,x
sta pTmp+1
ldy #0
lda (pTmp),y
beq +
sta tmp
- iny
lda (pTmp),y
ora #$80
dey
sta (pTmp),y
iny
dec tmp
bne -
lda #0
sta (pTmp),y
+ rts
end
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// General methods
2014-07-06 23:45:27 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Fatal error: print message and stop the system.
def fatal(msg)
toAsmStr(msg)
loader(FATAL_ERROR, MAIN_MEM, msg)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Print a signed decimal word
def printDec(n)
if n < 0; printChar('-'); n = -n; fin
if n > 9999; printChar('0' + n/10000); n = n%10000; fin
if n > 999; printChar('0' + n/1000); n = n%1000; fin
if n > 99; printChar('0' + n/100); n = n%100; fin
if n > 9; printChar('0' + n/10); n = n%10; fin
printChar('0' + n)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Print a formatted string a'la C printf, with up to four parameters.
def printf4(str, arg1, arg2, arg3, arg4)
word pos
word curArg
word p
pos = 0
curArg = @arg1
while TRUE
pos = partialPrintf(str, pos)
if pos < 0
break
fin
p = str + pos + 2
when ^p
is 'x'
printHex(*curArg); break
is 'd'
printDec(*curArg); break
is 's'
puts(*curArg); break
is '%'
printChar('%'); break
otherwise
printHex(^p); fatal("Unknown % code")
wend
curArg = curArg + 2
pos = pos + 2
loop
end
def printf1(str, arg1); printf4(str, arg1, 0, 0, 0); end
def printf2(str, arg1, arg2); printf4(str, arg1, arg2, 0, 0); end
def printf3(str, arg1, arg2, arg3); printf4(str, arg1, arg2, arg3, 0); end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Get a keystroke and convert it to upper case
def getUpperKey()
byte key
while ^keyboard < 128
loop
key = ^keyboard & $7F
^keystrobe
if key >= $60
key = key - $20
fin
return key
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Set the sky color (relevant to 3D display only)
def setSky(num)
skyNum = num
setColor(0, skyNum)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Switch to the next sky color (3D only)
def nextSky()
setSky((skyNum + 1) & $F)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Set the ground color (relevant to 3D display only)
def setGround(num)
groundNum = num
setColor(1, groundNum)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Switch to the next ground color (3D only)
def nextGround()
setGround((groundNum + 1) & $F)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Switch to text mode and display mem manager debug printout, get a key, switch back to graphics.
def debugMem(bank)
^$c051
^$c054
loader(DEBUG_MEM, bank, 0)
getUpperKey()
^$c050
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Establish a keystroke -> command association in the command table
def initCmd(key, func)
if key >= $60
key = key - $20
fin
cmdTbl[key-$20] = func
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Load the Frame Image, and lock it.
def loadFrameImg()
byte img
if titleLoaded
loader(UNLOCK_MEMORY,MAIN_MEM, $2000)
loader(FREE_MEMORY, MAIN_MEM, $2000)
titleLoaded = FALSE
fin
loader(SET_MEM_TARGET, MAIN_MEM, $2000)
loader(QUEUE_LOAD, MAIN_MEM, (3-mapIs3D)<<8 | RES_TYPE_SCREEN)
loader(LOCK_MEMORY, MAIN_MEM, $2000)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Load code and data, set up everything to display a 3D map
2015-04-05 16:52:38 +00:00
def initMap(x, y, dir)
word scriptModule
2014-07-06 23:45:27 +00:00
// Set up the command table
initCmds3D()
2014-08-21 15:17:50 +00:00
// Reset memory (our module will stay since memory manager locked it upon load)
2014-07-06 23:45:27 +00:00
loader(RESET_MEMORY, MAIN_MEM, 0)
2015-04-05 16:52:38 +00:00
// Load the font engine and its font
2014-07-06 23:45:27 +00:00
loader(SET_MEM_TARGET, MAIN_MEM, fontEngine)
loader(QUEUE_LOAD, MAIN_MEM, RES_NUM_FONT_ENGINE<<8 | RES_TYPE_CODE)
2014-08-21 15:17:50 +00:00
loader(SET_MEM_TARGET, MAIN_MEM, $9000)
pFont = loader(QUEUE_LOAD, MAIN_MEM, 1<<8 | RES_TYPE_FONT)
2015-04-05 16:52:38 +00:00
// Queue loading of the raycaster or tile engine and the map data
loader(SET_MEM_TARGET, MAIN_MEM, displayEngine)
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)
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)
fin
2014-07-06 23:45:27 +00:00
2014-08-21 15:17:50 +00:00
// Load everything that we just queued
loader(FINISH_LOAD, MAIN_MEM, 1) // 1 = keep open
2014-07-06 23:45:27 +00:00
2014-08-21 15:17:50 +00:00
// Load the frame image (and lock it there)
loadFrameImg()
2014-08-21 15:17:50 +00:00
// 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
2014-08-21 15:17:50 +00:00
loader(FINISH_LOAD, MAIN_MEM, 0) // 1 = keep open, for loading textures
2014-07-09 02:11:03 +00:00
2014-08-21 15:17:50 +00:00
// Start up the font engine
2014-07-06 23:45:27 +00:00
initFontEngine(pFont)
2015-04-05 16:52:38 +00:00
// Start up the display engine with map data and starting position
cMapName = initDisplay(pMap, x, y, dir)
2014-07-06 23:45:27 +00:00
2014-08-21 15:17:50 +00:00
// Initialize the map scripts
2014-07-09 02:11:03 +00:00
setWindow2()
clearWindow()
2015-03-03 17:03:22 +00:00
textDrawn = FALSE
2014-07-25 18:23:27 +00:00
2014-07-09 02:11:03 +00:00
prevX = -1
prevY = -1
2015-02-27 13:33:11 +00:00
triggerTbl = NULL
if pScripts
*pScripts()
fin
end
///////////////////////////////////////////////////////////////////////////////////////////////////
2014-08-21 15:17:50 +00:00
// Window for the map name bar
def setWindow1()
^wndtop = 1
^wndbtm = 2
^wndleft = 4
^wndwdth = 18
^cursv = ^wndtop
^cursh = ^wndleft
end
///////////////////////////////////////////////////////////////////////////////////////////////////
2014-08-21 15:17:50 +00:00
// Window for the large upper right bar
def setWindow2()
^wndtop = 3
^wndbtm = 17
^wndleft = 22
2014-07-23 20:39:43 +00:00
^wndwdth = 37
^cursv = ^wndtop
^cursh = ^wndleft
end
///////////////////////////////////////////////////////////////////////////////////////////////////
2014-08-21 15:17:50 +00:00
// Window for the mid-size lower right bar
def setWindow3()
^wndtop = 18
^wndbtm = 23
^wndleft = 23
^wndwdth = 37
^cursv = ^wndtop
^cursh = ^wndleft
end
2015-02-27 13:33:11 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
def callScripts(x, y)
word p
word pNext
word script
2015-03-03 17:03:22 +00:00
2015-02-27 13:33:11 +00:00
p = triggerTbl
while TRUE
if ^p == $FF
return
fin
2015-03-03 17:03:22 +00:00
pNext = p + p->1
2015-02-27 13:33:11 +00:00
if ^p == y
2015-03-03 17:03:22 +00:00
p = p + 2
2015-02-27 13:33:11 +00:00
while p < pNext
2015-03-03 17:03:22 +00:00
if x == ^p
script = p=>1
script()
2015-02-27 13:33:11 +00:00
fin
p = p + 3
loop
fin
p = pNext
loop
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Check for script(s) attached to the current location, and call them if there are any.
2015-02-27 13:33:11 +00:00
def checkScripts()
2014-07-09 02:11:03 +00:00
word x
word y
if !triggerTbl; return; fin
2015-02-27 13:33:11 +00:00
if mapIs3D
x = playerX.1 - 1
y = playerY.1 - 1
else
x = ^avatarX
y = ^avatarY
fin
2014-07-09 02:11:03 +00:00
if x <> prevX or y <> prevY
prevX = x
prevY = y
2015-03-03 17:03:22 +00:00
if textDrawn
clearWindow()
2015-03-03 17:03:22 +00:00
textDrawn = FALSE
fin
if isScripted()
2015-02-27 13:33:11 +00:00
callScripts(x, y)
if (mapNum <> prevMapNum) or (mapIs3D <> prevMapIs3D)
2015-04-05 16:52:38 +00:00
flipToPage1()
initMap()
fin
fin
fin
2014-07-09 02:11:03 +00:00
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Advance one step forward (3D maps only)
def moveForward()
word wasBlocked
2014-07-09 02:11:03 +00:00
word func
wasBlocked = isBlocked()
*playerX = *playerX + walkDirs[^playerDir << 1]
*playerY = *playerY + walkDirs[(^playerDir << 1) + 1]
if !wasBlocked and isBlocked()
moveBackward()
fin
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Adjust player's direction plus or minus n increments (3D mode)
def adjustDir(n)
^playerDir = (^playerDir + n) & $F
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Move backward one step (3D mode)
def moveBackward()
adjustDir(8)
moveForward()
adjustDir(8)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Turn left (3D mode)
def rotateLeft()
adjustDir(-1)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Rotate to the right (3D mode)
def rotateRight()
adjustDir(1)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Sidestep to the right (3D mode)
def strafeRight()
adjustDir(4)
moveForward()
adjustDir(-4)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Sidestep to the left (3D mode)
def strafeLeft()
adjustDir(-4)
moveForward()
adjustDir(4)
end
2015-01-18 16:59:56 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
def move2D(ox, oy)
*relX = ox + *relX
*relY = oy + *relY
checkCrossing()
2015-02-03 17:16:24 +00:00
redraw = TRUE
2015-01-18 16:59:56 +00:00
end
def moveNorth()
move2D(0, -1)
end
def moveEast()
move2D(1, 0)
end
def moveSouth()
move2D(0, 1)
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
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Switch to a new map (2D or 3D)
def setMap(is3D, num, x, y, dir)
mapIs3D = is3D
mapNum = num
teleport(x, y, dir)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Get a key and dispatch it to a command. Then do it again, forever.
def kbdLoop()
word key, func
while TRUE
key = getUpperKey()
key = key - $20
if key >= 0 and key < $40
func = cmdTbl[key]
if func
func()
renderFrame()
redraw = FALSE
2015-02-27 13:33:11 +00:00
checkScripts()
if redraw
renderFrame()
redraw = FALSE
fin
fin
fin
loop
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Associate a location with a trigger function (i.e. a script)
def setLocationTrigger(tbl)
2015-02-27 13:33:11 +00:00
triggerTbl = tbl
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Called by scripts to display a string. We set the flag noting that something has been
// displayed, then use an assembly routine to do the work.
def scriptDisplayStr(str)
2015-03-03 17:03:22 +00:00
textDrawn = TRUE
2015-02-27 13:33:11 +00:00
displayStr(str)
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
while TRUE
key = getUpperKey()
if key == 'Y'
return 1
elsif key == 'N'
clearWindow()
2015-03-03 17:03:22 +00:00
textDrawn = FALSE
return 0
fin
beep()
loop
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Set up the command table for 3D mode
def initCmds3D()
2015-04-05 16:52:38 +00:00
// Clear the command table
byte i
for i = 0 to 63
cmdTbl[i] = 0
next
// Handle 3D vs 2D commands separately
if mapIs3D
initCmd('W', @moveForward)
initCmd('A', @rotateLeft)
initCmd('D', @rotateRight)
initCmd('S', @moveBackward)
initCmd('X', @moveBackward)
initCmd('Z', @strafeLeft)
initCmd('C', @strafeRight)
initCmd('I', @moveForward)
initCmd('J', @rotateLeft)
initCmd('L', @rotateRight)
initCmd('K', @moveBackward)
initCmd(',', @moveBackward)
initCmd('M', @strafeLeft)
initCmd('.', @strafeRight)
initCmd('Y', @nextSky)
initCmd('G', @nextGround)
else
initCmd('W', @moveNorth)
initCmd('D', @moveEast)
initCmd('S', @moveSouth)
initCmd('X', @moveSouth)
initCmd('A', @moveWest)
end
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Load and display the title screen.
def loadTitle()
2015-03-03 17:03:22 +00:00
puts("Loading Lawless Legends.\n")
// Load the title screen
2015-03-03 17:03:22 +00:00
puts("Loading title screen.\n")
loader(SET_MEM_TARGET, MAIN_MEM, $2000)
loader(QUEUE_LOAD, MAIN_MEM, 1<<8 | RES_TYPE_SCREEN) // title screen is fixed at #1
loader(LOCK_MEMORY, MAIN_MEM, $2000)
loader(FINISH_LOAD, MAIN_MEM, 1) // 1 = keep open
titleLoaded = TRUE
2015-03-03 17:03:22 +00:00
puts("Title loaded.\n")
^$c050
^$c057
^$c054
^$c052
// Hack for real (not emulated) IIc: sometimes displays only lo-bit graphics
// unless we do this. *HUGE* thanks to Brendan Robert for the fix!
^$C07E=0 // disable double-hi-res
^$C05F // disable double-hi-res
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Set vectors so that scripts in PLASMA can call back to do things with this engine.
def setCallbacks()
// $300
callbacks.0 = $4c
callbacks:1 = @setLocationTrigger
// $303
callbacks.3 = $4c
2015-02-27 13:33:11 +00:00
callbacks:4 = @scriptDisplayStr
// $306
callbacks.6 = $4c
callbacks:7 = @getYN
// $309
callbacks.9 = $4c
callbacks:10 = @setMap
// $30C
callbacks.12 = $4c
callbacks:13 = @setSky
// $30F
callbacks.15 = $4c
callbacks:16 = @setGround
// $312
callbacks.18 = $4c
callbacks:19 = @teleport
end
2014-08-21 15:17:50 +00:00
///////////////////////////////////////////////////////////////////////////////////////////////////
// Main code.
//
loadTitle()
setCallbacks()
initMap()
setWindow2()
kbdLoop()
2014-06-25 15:47:28 +00:00
done