Lots of progress making automap target work.

This commit is contained in:
Martin Haye 2018-11-15 09:00:20 -08:00
parent 44a3aadf86
commit e1bc8de7f6
4 changed files with 282 additions and 134 deletions

View File

@ -64,7 +64,6 @@ proRWTS = $D000
; Memory buffers
plasmaFrames = $E00 ; 2 pages
gameLoop = $1000 ; just after plasma frames
unusedBuf = $4000 ; used to be for ProDOS file buf and a copy space, but no longer
headerBuf = $4C00 ; len $1400
; Memory used only during garbage collection

View File

@ -49,7 +49,7 @@ const SECT_BUF_SIZE = MAX_MAP_SECT * TMapSection
// Exported functions go here. First a predef for each one, then a table with function pointers
// in the same order as the constants are defined in the header.
predef _automap_show()#1
predef _automap_show(targetX, targetY)#1
word[] funcTbl = @_automap_show
word tilePtrs[40]
@ -65,6 +65,11 @@ word pSpecialsBuf
word pSpecialTiles
word scanSpecials = $100 // placed at $100 so it can easily access aux mem
word specTileset
word targetX, targetY
// Pixel representation for displaying the target (shape of an "X")
//byte[] targetData = 0, $63, $36, $1C, $1C, $36, $63, 0
byte[] targetData = 0, 0, $36, $1C, $1C, $36, 0, 0
///////////////////////////////////////////////////////////////////////////////////////////////////
// Definitions used by assembly code
@ -547,6 +552,42 @@ asm _scanSpecials_end()#0
nop ; dummy
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Swap 8x7 pixel area from the target graphic buffer to the screen.
asm swapTarget(x, y, swapBuf)#0
!zone {
+asmPlasmNoRet 3
sta pSrc ; swapBuf
sty pSrc+1
lda evalStkL+1,x
sta tmp+1 ; y
lda evalStkL+2,x
sta tmp ; x
lda #8 ; lineCount
.nextLine
pha
lda tmp+1
jsr GetScreenLine
ldy tmp
ldx #0
lda (pSrc,x) ; swap buffer byte...
pha
lda (pTmp),y ; ...with screen byte
sta (pSrc,x)
pla
sta (pTmp),y
inc pSrc ; next buffer position
bne +
inc pSrc+1
+ inc tmp+1 ; advance to next line
pla
sec
sbc #1 ; decrement count
bne .nextLine ; loop until done
rts
}
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def loadMarks()#0
word len
@ -621,18 +662,18 @@ def make2DSection(pSection, sh, sv)#0
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def printSection(pSection)#0
printf1("Sect %d: ", (pSection - @sectionBuf) / TMapSection)
printf2("%d/%d - ", pSection=>wm_x0, pSection=>wm_y0)
printf2("%d/%d; ", pSection=>wm_x1, pSection=>wm_y1)
printf1("vis=%d ", pSection->bm_visible)
if pSection->bm_visible
printf2("scrn=%d/%d ", pSection->bm_sx, pSection->bm_sy)
printf2("off=%d/%d ", pSection->bm_ox, pSection->bm_oy)
printf2("clip=%dw/%dh", pSection->bm_cw, pSection->bm_ch)
fin
puts(".\n")
end
//def printSection(pSection)#0
// printf1("Sect %d: ", (pSection - @sectionBuf) / TMapSection)
// printf2("%d/%d - ", pSection=>wm_x0, pSection=>wm_y0)
// printf2("%d/%d; ", pSection=>wm_x1, pSection=>wm_y1)
// printf1("vis=%d ", pSection->bm_visible)
// if pSection->bm_visible
// printf2("scrn=%d/%d ", pSection->bm_sx, pSection->bm_sy)
// printf2("off=%d/%d ", pSection->bm_ox, pSection->bm_oy)
// printf2("clip=%dw/%dh", pSection->bm_cw, pSection->bm_ch)
// fin
// puts(".\n")
//end
///////////////////////////////////////////////////////////////////////////////////////////////////
def prepSections(extraLeft, extraTop)#0
@ -926,12 +967,91 @@ def centerScreen#0
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def cursorWait#1
word x, y, i
byte phase, color
getPos(@x, @y)
def showTarget(targetX, targetY)#0
word hx, hy, cx, cy, dx, dy, x, y
byte color, xbit, xbyte
// If the target is within the screen area, our work is easy
if targetX >= screenX0 and targetX < screenX1 and targetY >= screenY0 and targetY < screenY1
x = targetX - screenX0
y = targetY - screenY0
else
// Target is outside the screen area. Use line calculations to show the direction by clipping it.
hx = SCREEN_COLS >> 1 // half width
hy = SCREEN_ROWS >> 1 // half height
cx = (screenX0 + screenX1)>>1 // center coordinate
cy = (screenY0 + screenY1)>>1
dx = targetX - cx
dy = targetY - cy
// for a line through the origin 0,0:
// m = dy/dx
// y = mx
// so: y = dy*x / dx
if dy < 0
// Intersect with top
y = -hy
// -hy = dy*x / dx
// so: -hy*dx = dy*x
x = (-hy * dx) / dy
elsif dy > 0
// Intersect with bottom
y = hy
// hy = dy*x / dx
// so: hy*dx = dy*x
x = (hy*dx) / dy
elsif dx < 0
y = 0
x = -hx
else
y = 0
x = hx-1
fin
if x < -hx
// Intersect with left
x = -hx
y = (dy*-hx) / dx
elsif x > hx-1
// Intersect with right
x = hx-1
y = (dy*(hx-1)) / dx
fin
// Finally adjust for the origin at the center of the screen
x = x + hx
y = y + hy
fin
swapTarget(x + MAP_LEFT, (y<<3) + MAP_TOP, @targetData)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def cursorWait(targetX, targetY)#1
word playerX, playerY, i, j
byte phase, color, targetOn
getPos(@playerX, @playerY)
phase = 0
targetOn = 0
i = 100
while ^kbd < 128
// Blink the target on and off at a slower rate
i++
if i > 3 and targetX <> 9999
if playerX == targetX and playerY == targetY and !targetOn
showCursor(0, getScreenLine(((playerY-screenY0)<<3)+MAP_TOP) + (playerX-screenX0+MAP_LEFT))
fin
targetOn = !targetOn
showTarget(targetX, targetY)
i = 0
fin
// Determine color for the player marker
when phase
is 0; color = $AA; break
is 1; color = $D5; break
@ -939,15 +1059,21 @@ def cursorWait#1
is 3; color = $D5; break
is 4; color = $FF; break
wend
if x >= screenX0 and x < screenX1 and y >= screenY0 and y < screenY1
showCursor(color, getScreenLine(((y-screenY0)<<3)+MAP_TOP) + (x-screenX0+MAP_LEFT))
if playerX >= screenX0 and playerX < screenX1 and playerY >= screenY0 and playerY < screenY1
if playerX <> targetX or playerY <> targetY or !targetOn
showCursor(color, getScreenLine(((playerY-screenY0)<<3)+MAP_TOP) + (playerX-screenX0+MAP_LEFT))
fin
fin
i = 0
while i < 200 and ^kbd < 128
i++
j = 0
while j < 200 and ^kbd < 128
j++
loop
phase = (phase+1) % 5
loop
// Erase target if it's still showing
if targetX <> 9999 and targetOn; showTarget(targetX, targetY); fin
i = ^kbd
^kbdStrobe
return charToUpper(i & $7F)
@ -963,9 +1089,14 @@ def showTitle#0
end
///////////////////////////////////////////////////////////////////////////////////////////////////
def _automap_show()#1
def _automap_show(targetX, targetY)#1
byte key
// FIXME FOO
word playerX, playerY
getPos(@playerX, @playerY)
targetX = playerX+1; targetY = playerY // FIXME - just for testing
// Clear out the blank tile buffer
memset(@blankTile, 0, 9)
@ -984,8 +1115,18 @@ def _automap_show()#1
// Now allow the player to scroll the map
repeat
key = cursorWait
key = cursorWait(targetX, targetY)
when key
is 'I'; //FIXME FOO
targetY--; break
is 'K'; //FIXME FOO
targetX++; break
is 'M'; //FIXME FOO
targetY++; break
is 'J'; //FIXME FOO
targetX--; break
is 'W'; is 'I'; is 11
if screenY1-8 > 0
screenY0 = screenY0 - 8 // north

View File

@ -36,6 +36,7 @@ import gamelib
predef clearPortrait()#0
predef clearWindow()#0
predef centerStr(str, windowWidth)#0
predef copyWindow(flip)#0
predef countList(p)#1
predef crout()#0
predef displayChar(chr)#0
@ -84,6 +85,7 @@ import gamelib
predef pause(count)#1
predef payGold(amount)#1
predef percentToRatio(pct)#1
predef plotLinePixels(page, color, len, xbyte, xbit, xinc, xdir, y, yinc, ydir)#0
predef printf1(fmt, arg1)#0
predef printf2(fmt, arg1, arg2)#0
predef printf3(fmt, arg1, arg2, arg3)#0

View File

@ -388,9 +388,21 @@ export asm memset(pDst, val, len)#0
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Specialized line routine for drawing the clock. Plots in black or white only, on hi-res pg 2.
asm _drawLine(color, len, xbyte, xbit, xinc, xdir, y, yinc, ydir)#0
// Specialized line routine for drawing the clock. Plots in black or white only.
// Parameters:
// page : 0=page1, $60=page2
// color: 0=black, $7F=white
// len : number of pixels to plot
// xbyte: x/7, e.g. 0-39 byte offset within screen row
// xbit : (3<<(x%7)) & $7F
// xinc : fraction 0..$FF telling how often to advance on X axis
// xdir : 0=left, 1=right
// y : hi-res line number 0..191
// yinc : fraction 0..$FF telling how often to advance on X axis
// ydir : 0=up, 1=down
export asm plotLinePixels(page, color, len, xbyte, xbit, xinc, xdir, y, yinc, ydir)#0
!zone {
.param_page = evalStkL+9
.param_color = evalStkL+8
.param_len = evalStkL+7
.param_xbyte = evalStkL+6
@ -402,7 +414,7 @@ asm _drawLine(color, len, xbyte, xbit, xinc, xdir, y, yinc, ydir)#0
.param_ydir = evalStkL+0
.xfrac = tmp
.yfrac = tmp+1
+asmPlasmNoRet 9
+asmPlasmNoRet 10
lda #0
sta .xfrac
sta .yfrac
@ -414,7 +426,7 @@ asm _drawLine(color, len, xbyte, xbit, xinc, xdir, y, yinc, ydir)#0
pla
tax
lda pTmp+1
eor #$60 ; always draw on hi-res pg 2
eor .param_page,x ; $60 flips to page 2, 0 for page 1
sta pTmp+1
clc ; signal to take X path first
.pix
@ -936,10 +948,10 @@ export asm clearWindow()#0
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Use the font engine to copy the current text window to hi-res page 2.
// Use the font engine to copy the current text window to hi-res page 2 (or vice-versa)
// If flip=0, copies page 1 to page 2
// If flip=$60, copies page 2 to page 1
asm copyWindow(flip)#0
export asm copyWindow(flip)#0
+asmPlasmNoRet 1
tay
jmp CopyWindow
@ -1228,92 +1240,92 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
// The following only used for speed testing
asm readNoSlotClock(dstBuf)#0 // param: dstBuf (will receive 8 BCD bytes)
!zone {
+asmPlasmNoRet 1
; record dst ptr
sta tmp
sty tmp+1
; obtain a pointer to our little table of magic values
lda #$60
sta pTmp
.base = *+2
jsr pTmp
tsx
dex
dex
txs
pla
sta pTmp
pla
sta pTmp+1
ldy #<(.tbl - .base)
; record state of slot ROM, then turn on C3 ROM
sei
lda $CFFF
pha
sta $C300
lda $C304
ldx #8
.wr1:
lda (pTmp),y
sec
ror
.wr2:
bcs +
bit $C300
bcc ++
+ bit $C301
++ lsr
bne .wr2
iny
dex
bne .wr1
ldy #7
.rd1:
ldx #8
.rd2:
lda $C304
lsr
ror pTmp
dex
bne .rd2
lda pTmp
sta (tmp),y
dey
bpl .rd1
; restore slot ROM state
pla
bmi +
sta $CFFF
+ cli
rts
.tbl !byte $C5,$3A,$A3,$5C,$C5,$3A,$A3,$5C
} ; end zone
end
def getTick()
byte timeBuf[8]
word tick
readNoSlotClock(@timeBuf)
tick = (timeBuf[7] & $F) + ((timeBuf[7] >> 4) * 10)
tick = tick + ((timeBuf[6] & $F) * 100) + ((timeBuf[6] >> 4) * 1000)
return tick + (((timeBuf[5] & $F) % 5) * 6000)
end
def tickDiff(tStart, tEnd)
word diff
diff = tEnd - tStart
if diff >= 0; return diff; fin
return diff + 30000
end
def prtick(str)#0
if lastTick
printf2("%s:%d ", str, tickDiff(lastTick, getTick()))
fin
lastTick = getTick()
end
//asm readNoSlotClock(dstBuf)#0 // param: dstBuf (will receive 8 BCD bytes)
//!zone {
// +asmPlasmNoRet 1
// ; record dst ptr
// sta tmp
// sty tmp+1
// ; obtain a pointer to our little table of magic values
// lda #$60
// sta pTmp
//.base = *+2
// jsr pTmp
// tsx
// dex
// dex
// txs
// pla
// sta pTmp
// pla
// sta pTmp+1
// ldy #<(.tbl - .base)
// ; record state of slot ROM, then turn on C3 ROM
// sei
// lda $CFFF
// pha
// sta $C300
// lda $C304
// ldx #8
//.wr1:
// lda (pTmp),y
// sec
// ror
//.wr2:
// bcs +
// bit $C300
// bcc ++
//+ bit $C301
//++ lsr
// bne .wr2
// iny
// dex
// bne .wr1
// ldy #7
//.rd1:
// ldx #8
//.rd2:
// lda $C304
// lsr
// ror pTmp
// dex
// bne .rd2
// lda pTmp
// sta (tmp),y
// dey
// bpl .rd1
// ; restore slot ROM state
// pla
// bmi +
// sta $CFFF
//+ cli
// rts
//.tbl !byte $C5,$3A,$A3,$5C,$C5,$3A,$A3,$5C
//} ; end zone
//end
//
//def getTick()
// byte timeBuf[8]
// word tick
// readNoSlotClock(@timeBuf)
// tick = (timeBuf[7] & $F) + ((timeBuf[7] >> 4) * 10)
// tick = tick + ((timeBuf[6] & $F) * 100) + ((timeBuf[6] >> 4) * 1000)
// return tick + (((timeBuf[5] & $F) % 5) * 6000)
//end
//
//def tickDiff(tStart, tEnd)
// word diff
// diff = tEnd - tStart
// if diff >= 0; return diff; fin
// return diff + 30000
//end
//
//def prtick(str)#0
// if lastTick
// printf2("%s:%d ", str, tickDiff(lastTick, getTick()))
// fin
// lastTick = getTick()
//end
///////////////////////////////////////////////////////////////////////////////////////////////////
// General methods
@ -1328,31 +1340,25 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Return the max of two signed 16-bit numbers
export def max(a, b)#1
if a < b; return b; fin
return a
return a > b ?? a :: b
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Return the min of two signed 16-bit numbers
export def min(a, b)#1
if a < b; return a; fin
return b
return a < b ?? a :: b
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Return the absolute value of a number
export def abs(n)#1
if n < 0; return -n; fin
return n
return n < 0 ?? -n :: n
end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Convert a lower-case character to upper-case (or return unchanged if it's not lower-case)
export def charToUpper(c)#1
if c >= 'a' and c <= 'z'
return c - $20
fin
return c
return (c >= 'a' and c <= 'z') ?? (c - $20) :: c
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -2061,8 +2067,8 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
def horzSegment(color, len, x, y)#0
//params: color, len, xbyte, xbit, xinc, xdir, y, yinc, ydir
_drawLine(color, len, x/7, (3<<(x%7)) & $7F, $FF, 1, y, 0, 0)
//params: page, color, len, xbyte, xbit, xinc, xdir, y, yinc, ydir
plotLinePixels($60, color, len, x/7, (3<<(x%7)) & $7F, $FF, 1, y, 0, 0)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -2122,16 +2128,16 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
def drawHand(color, hour, isShort)#0
word xdir, xinc, ydir, yinc, len
ydir = (hour > 3 and hour < 9) & 1 // 3..9 = 1
xdir = (hour < 6) & 1 // 1..6 = 1
ydir = (hour > 3 and hour < 9) & 1 // 3..9 = 1
xdir = (hour < 6) & 1 // 1..6 = 1
xinc = (^("123210123210"+hour) - '0') * 85
yinc = (^("210123210123"+hour) - '0') * 85
len = (hour % 3) ?? (CLOCK_RADIUS*3/2)-4 :: CLOCK_RADIUS-2
if isShort
len = len * 3 / 5
fin
//params: color, len, xbyte, xbit, xinc, xdir, y, yinc, ydir
_drawLine(color, len, CLOCK_X/7, (3<<(CLOCK_X%7)) & $7F, xinc, xdir, CLOCK_Y, yinc, ydir)
//params: page, color, len, xbyte, xbit, xinc, xdir, y, yinc, ydir
plotLinePixels($60, color, len, CLOCK_X/7, (3<<(CLOCK_X%7)) & $7F, xinc, xdir, CLOCK_Y, yinc, ydir)
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -2967,7 +2973,7 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
// Load the automap engine and display the map
def showAutomap()#1
loadEngine(MOD_AUTOMAP)=>automap_show()
loadEngine(MOD_AUTOMAP)=>automap_show(9999, 9999) // 9999 = no quest target
returnFromEngine(TRUE)
return 0
end