Expanded small-object heap to make more space for inventory. Started implementing pack size limits.

This commit is contained in:
Martin Haye 2017-09-12 08:21:23 -07:00
parent ea25619c78
commit 05d96b1243
12 changed files with 129 additions and 86 deletions

View File

@ -50,7 +50,7 @@ class A2PackPartitions
static final int FLOPPY_SIZE = 35*8 // good old 140k floppy = 280 blks
static final int AC_KLUDGE = 2 // minus 1 to work around last-block bug in AppleCommander
static final int DOS_OVERHEAD = 3 // only 3 blks overhead! ProRWTS is so freaking amazing.
static final int SAVE_GAME_SIZE = 7 // 6 blocks data, 1 block index
static final int SAVE_GAME_SIZE = 10 // 9 blocks data, 1 block index
static final int MAX_DISKS = 20 // for now this should be way more than enough
def typeNumToName = [1: "Code",
@ -2817,7 +2817,8 @@ end
"${parseByteAttr(row, "aiming")}, " +
"${parseByteAttr(row, "hand-to-hand")}, " +
"${parseByteAttr(row, "dodging")}, " +
"${parseGenderAttr(row, "gender")})")
"${parseGenderAttr(row, "gender")}, " +
"${parseByteAttr(row, "pack size")})")
row.attributes().sort().eachWithIndex { name, val, idx ->
if (name =~ /^skill-(.*)/) {
out.println(" addToList(@p=>p_skills, " +
@ -3123,7 +3124,7 @@ def makePlayer_pt1(name, intelligence, strength, agility, stamina, charisma, spi
return p
end
def makePlayer_pt2(p, health, level, aiming, handToHand, dodging, gender)#1
def makePlayer_pt2(p, health, level, aiming, handToHand, dodging, gender, packSize)#1
p=>w_health = health
p->b_level = level
p=>w_maxHealth = health
@ -3133,6 +3134,13 @@ def makePlayer_pt2(p, health, level, aiming, handToHand, dodging, gender)#1
p->b_handToHand = handToHand
p->b_dodging = dodging
p->c_gender = gender
if packSize
p->b_packSize = packSize
elsif global=>p_players
p->b_packSize = 15
else
p->b_packSize = 30
fin
initPlayerXP(p)
return p
end
@ -3347,7 +3355,7 @@ end
else {
// Create empty save file
newSave.withOutputStream { outStream ->
(0..3071).each {
(0..(18*256 - 1)).each {
outStream.write( (byte) 0)
}
}
@ -4198,7 +4206,7 @@ end
{
def name = getSingle(blk.field, "NAME").text().trim()
assert itemNameToFunc.containsKey(name.toLowerCase()) : "Can't locate item '$name'"
out << "playerHasItem(${escapeString(name)})"
out << "partyHasItem(${escapeString(name)})"
}
def packHasPlayer(blk)

View File

@ -212,7 +212,7 @@ init: !zone
; 5: main $2000 -> 6, active + locked
; 6: main $6000 -> 7, inactive
; 7: main $BFFD -> 8, active + locked
; 8: main $E000 -> 9, inactive
; 8: main $DA00 -> 9, inactive
; 9: main $FFFA -> 0, active + locked
; First, the flags
ldy #$C0 ; flags for active + locked (with no resource)
@ -253,7 +253,7 @@ init: !zone
sta tSegAdrHi+5
lda #$60
sta tSegAdrHi+6
lda #$E0
lda #$DA
sta tSegAdrHi+8
lda #$FA
sta tSegAdrLo+9
@ -710,6 +710,25 @@ partFilename:
;------------------------------------------------------------------------------
; Heap management routines
;------------------------------------------------------------------------------
; Zero memory heapTop up to but not including $xx00 where XX is in A reg
heapClr: !zone
bit setLcRW+lcBank2 ; heap begins in bank 2
sta .cmp+1
lda #0
sta targetAddr+1 ; clear target addr now that we're done with heap top
ldx heapTop
ldy heapTop+1
.pg sty .st+2
.st sta $1000,x ; self-modified above
inx
bne .st
iny
.cmp cpy #11 ; self-modified above
bcc .pg
bit setLcRW+lcBank1 ; back to mmgr's bank
rts
; Check if blk pSrc is in GC hash; optionally add it if not.
; Input : pSrc = blk to check/add
; Carry set = add if not found, clear = check only, don't add
@ -770,6 +789,7 @@ memCheck: !zone
heapCheck: !zone
jsr startHeapScan
.blklup bcc + ; if top-of-heap, we're done
bit setLcRW+lcBank1 ; back to mmgr's bank
rts
+ bvs .isobj ; handle objects separately
; it's a string; check its characters
@ -812,6 +832,7 @@ heapCorrupt:
; Begin a heap scan by setting pTmp to start-of-heap, then returns
; everything as per nextHeapBlk below
startHeapScan: !zone
bit setLcRW+lcBank2 ; heap is in bank 2 (bulk of mmgr is in bnk 1)
lda #0
ldx heapStartPg
sta pDst ; used in gc2 sweep init
@ -982,10 +1003,16 @@ heapCollect: !zone
lda nSegsQueued
bne .unfin
jsr closePartFile
bit setLcRW+lcBank2 ; heap starts in bank 2
lda heapTop+1 ; save old heap top for end of later clear
pha
jsr gc1_mark ; mark reachable blocks
jsr gc2_sweep ; sweep them into one place
jsr gc3_fix ; adjust all pointers
jsr heapClr ; and clear newly freed space
pla ; old heap top
clc
adc #1
jsr heapClr ; and clear newly freed space (switches back to bnk1 when done)
ldx heapTop ; return new top-of-heap in x=lo/y=hi
ldy heapTop+1
rts
@ -995,6 +1022,7 @@ heapCollect: !zone
; And yes, type $80 is valid (conventionally used for the Global Object).
; And yes, string length $00 is valid (it's an empty string).
heapAlloc: !zone
bit setLcRW+lcBank2 ; heap starts in bank 2
lda heapTop
sta pSrc
lda heapTop+1
@ -1014,6 +1042,7 @@ heapAlloc: !zone
+ sta heapTop
sty heapTop+1
retPSrc:
bit setLcRW+lcBank1 ; back to mmgr's bank
ldx pSrc ; return ptr in X=lo/Y=hi
ldy pSrc+1
rts
@ -1046,7 +1075,8 @@ heapIntern: !zone
.notfnd lda (pTmp),y ; get string length
pha ; save it
tax
jsr heapAlloc ; make space for it
jsr heapAlloc ; make space for it (switches to mmgr bank at end)
bit setLcRW+lcBank2 ; back to heap bank
pla ; string length back
tax
inx ; add 1 to copy length byte also
@ -1058,6 +1088,44 @@ heapIntern: !zone
bne .cplup
beq .found ; always taken
;------------------------------------------------------------------------------
; Variables
targetAddr: !word 0
unusedSeg: !byte 0
scanStart: !byte 0, 1 ; main, aux
segNum: !byte 0
nextLdVec: jmp diskLoader
curPartition: !byte 0
partFileOpen: !byte 0
curMarkPos: !fill 4 ; really 3, but 1 extra to match ProRWTS needs
setMarkPos: !fill 3
nSegsQueued: !byte 0
bufferDigest: !fill 4
diskActState: !byte 0
floppyDrive: !byte 0
;------------------------------------------------------------------------------
; Heap management variables
MAX_TYPES = 12
nTypes !byte 0
typeTblL !fill MAX_TYPES
typeTblH !fill MAX_TYPES
typeLen !fill MAX_TYPES ; length does not include type byte
heapStartPg !byte 0
heapEndPg !byte 0
heapTop !word 0
gcHash_top !byte 0
lastLoMem = *
} ; end of !pseodupc $800
loMemEnd = *
;------------------------------------------------------------------------------
; The remainder of the code gets relocated up into the Language Card, bank 1.
hiMemBegin: !pseudopc $D000 {
;------------------------------------------------------------------------------
; Show or hide the disk activity icon (at the top of hi-res page 1). The icon consists of a 4x4
; block of blue pixels surrounded by a black border.
@ -1089,44 +1157,6 @@ showDiskActivity: !zone
bne -
.done rts
lastLoMem = *
} ; end of !pseodupc $800
loMemEnd = *
;------------------------------------------------------------------------------
; The remainder of the code gets relocated up into the Language Card, bank 1.
hiMemBegin: !pseudopc $D000 {
;------------------------------------------------------------------------------
; Variables
targetAddr: !word 0
unusedSeg: !byte 0
scanStart: !byte 0, 1 ; main, aux
segNum: !byte 0
nextLdVec: jmp diskLoader
curPartition: !byte 0
partFileOpen: !byte 0
curMarkPos: !fill 4 ; really 3, but 1 extra to match ProRWTS needs
setMarkPos: !fill 3
nSegsQueued: !byte 0
bufferDigest: !fill 4
diskActState: !byte 0
floppyDrive: !byte 0
;------------------------------------------------------------------------------
; Heap management variables
MAX_TYPES = 16
nTypes !byte 0
typeTblL !fill MAX_TYPES
typeTblH !fill MAX_TYPES
typeLen !fill MAX_TYPES ; length does not include type byte
heapStartPg !byte 0
heapEndPg !byte 0
heapTop !word 0
gcHash_top !byte 0
;------------------------------------------------------------------------------
grabSegment: !zone
; Input: None
@ -2557,7 +2587,7 @@ doAllFixups: !zone
glibBase !word $1111
;------------------------------------------------------------------------------
; More heap management routines
; More heap management routines (that don't need to actually access LC bank 2)
;------------------------------------------------------------------------------
; Establish a new heap
@ -2587,21 +2617,8 @@ heapSet: !zone
ldy targetAddr
+ stx heapTop+1 ; set heap top
sty heapTop
; fall through to:
; Zero memory heapTop.heapEnd
heapClr: !zone
lda #0
sta targetAddr+1 ; clear target addr now that we're done with heap top
ldx heapTop
ldy heapTop+1
.pg sty .st+2
.st sta $1000,x ; self-modified above
inx
bne .st
iny
cpy heapEndPg
bne .pg
rts
lda heapEndPg
jmp heapClr ; clear out the new heap space
;------------------------------------------------------------------------------
; Set the table for the next type in order. Starts with type $80, then $81, etc.

View File

@ -27,7 +27,7 @@ const RWTS_DRV2 = $80
const RWTS_RDWRPART = (0<<8)
const RWTS_OPENDIR = (1<<8)
const LOAD_SAVE_BUF = $5000
const LOAD_SAVE_BUF = $4E00
// 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 the header.

View File

@ -77,10 +77,10 @@ import gamelib
predef numToPlayer(num)#1
predef parseDec(str)#1
predef partyHasPlayer(playerName)#1
predef partyHasItem(itemName)#1
predef pause(count)#0
predef payGold(amount)#1
predef percentToRatio(pct)#1
predef playerHasItem(itemName)#1
predef printf1(fmt, arg1)#0
predef printf2(fmt, arg1, arg2)#0
predef printf3(fmt, arg1, arg2, arg3)#0
@ -103,6 +103,7 @@ import gamelib
predef rollDice(encoded)#1
predef rollDiceWithLuck(encoded, luck)#1
predef rollPercentileWithLuck(luck)#1
predef roomInPack(p_player)#1
predef scanForNamedObj(p_obj, name)#1
predef scriptCombat(mapCode)#1
predef scriptDisplayStr(str)#0

View File

@ -141,6 +141,7 @@ export byte[] S_DODGING = "Dodging"
export byte[] S_GOLD = "Gold"
export byte[] S_XP = "XP"
export byte[] S_SP = "SP"
export byte[] S_PACK_SIZE = "Pack size"
export byte[] S_ENTER = "Enter"
export byte[] S_LEAVE = "Leave"
export byte[] S_USE = "Use"
@ -1431,7 +1432,7 @@ export def heapCollect()#0
word pct
mmgr(CHECK_MEM, 0)
global=>w_heapSize = mmgr(HEAP_COLLECT, 0) - HEAP_BOTTOM
pct = min(99, max(0, ((global=>w_heapSize / 10) * 100) / 307))
pct = min(99, max(0, ((global=>w_heapSize / 10) * 100) / (HEAP_SIZE / 10)))
if pct <> curHeapPct
curHeapPct = pct
printHeapPct()
@ -1518,10 +1519,12 @@ end
///////////////////////////////////////////////////////////////////////////////////////////////////
def clearTextWindow()#0
setWindow2(); clearWindow()
if mapIs3D and texturesLoaded; copyWindow(); fin
textDrawn = FALSE
textClearCountdown = 0
if textDrawn or textClearCountdown
setWindow2(); clearWindow()
if mapIs3D and texturesLoaded; copyWindow(); fin
textDrawn = FALSE
textClearCountdown = 0
fin
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -2073,8 +2076,8 @@ def kbdLoop()#0
func = cmdTbl[key]
if func
if textClearCountdown
if textClearCountdown == 1; clearTextWindow(); fin
textClearCountdown--
if !textClearCountdown; clearTextWindow(); fin
fin
func()
fin
@ -2608,6 +2611,7 @@ def toggleGodMode()#1
flipToPage1()
clearTextWindow()
displayf1("gm:%d\n", global->b_godmode & 1)
textDrawn = TRUE
beep; beep
clearTextWindow()
saveMapPos(); restoreMapPos() // reload everything, including god module
@ -2892,6 +2896,11 @@ export def createAndAddUnique(moduleID, creationFuncNum, pList)#1
return p_thing
end
///////////////////////////////////////////////////////////////////////////////////////////////////
export def roomInPack(p_player)#1
return countList(p_player=>p_items) < p_player->b_packSize
end
///////////////////////////////////////////////////////////////////////////////////////////////////
export def giveItemToPlayer(p_player, itemFuncNum)#0
createAndAddUnique(MOD_GEN_ITEMS, itemFuncNum, @p_player=>p_items)
@ -2968,8 +2977,8 @@ export def addPlayerToParty(playerFuncNum)#0
beep
return
fin
// Create the player (NPC flag will be established inside the creation func)
p = createAndAddUnique(MOD_GEN_PLAYERS, playerFuncNum, @global=>p_players)
p->b_playerFlags = p->b_playerFlags | PLAYER_FLAG_NPC
addXP(0) // to set initial skill pts
needShowParty = TRUE
end
@ -3010,8 +3019,14 @@ export def removePlayerFromParty(playerName)#0
end
///////////////////////////////////////////////////////////////////////////////////////////////////
export def playerHasItem(itemName)#1
return scanForNamedObj(global=>p_players=>p_items, itemName) <> NULL
export def partyHasItem(itemName)#1
word p_player
p_player = global=>p_players
while p_player
if scanForNamedObj(global=>p_players=>p_items, itemName) <> NULL; return TRUE; fin
p_player = p_player=>p_nextObj
loop
return FALSE
end
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -3038,6 +3053,7 @@ export def getStat(player, statName)#1
is streqi(statName, @S_GOLD); return global=>w_gold
is streqi(statName, @S_XP); return player=>w_curXP
is streqi(statName, @S_SP); return player->b_skillPoints
is streqi(statName, @S_PACK_SIZE); return player->b_packSize
wend
pSkill = player=>p_skills
while pSkill
@ -3078,7 +3094,8 @@ export def setStat(player, statName, val)#0
is streqi(statName, @S_DODGING); player->b_dodging = clampByte(val); break
is streqi(statName, @S_GOLD); global=>w_gold = max(0, val); needShowParty = TRUE; break
is streqi(statName, @S_XP); player=>w_curXP = max(player=>w_curXP, val); needShowParty = TRUE; break
is streqi(statName, @S_SP); player->b_skillPoints = max(0, val); needShowParty = TRUE; break
is streqi(statName, @S_SP); player->b_skillPoints = clampByte(max(0, val)); needShowParty = TRUE; break
is streqi(statName, @S_PACK_SIZE); player->b_packSize = clampByte(max(player->b_packSize, val)); break
otherwise
pSkill = player=>p_skills
while pSkill

View File

@ -69,8 +69,8 @@ const HEAP_INTERN = $23
const HEAP_COLLECT = $24
// Heap location in memory
const HEAP_BOTTOM = $E000
const HEAP_SIZE = $C00
const HEAP_BOTTOM = $DA00
const HEAP_SIZE = $1200
// Event code
const EVENT_ENTER = 1

View File

@ -168,6 +168,7 @@ def showDerived(player)#0
rawDisplayf2("\n^T%D%s\n", STAT_X-5, "^I LEVEL UP ^N")
rawDisplayf2("^T%D%s\n", STAT_X-5+8, "in S)kills\n")
fin
vspace()
rightJustifyNum(player=>w_curXP, STAT_X)
rawDisplayf2("^T%D%s\n", STATLBL_X, "Current XP")
rightJustifyNum(player=>w_nextXP, STAT_X)
@ -202,9 +203,14 @@ def showDerived(player)#0
displayDice(dmg)
rawDisplayf1("^T%DMelee\n", STATLBL_X)
vspace()
rightJustifyStr(sprintf2("%d/%d", countList(player=>p_items), player->b_packSize), STAT_X)
rawDisplayf1("^T%DPack size\n", STATLBL_X)
vspace()
rightJustifyNum(global=>w_gold, STAT_X)
rawDisplayf1("^T%DParty gold", STATLBL_X)
rawDisplayf1("^T%DParty gold\n", STATLBL_X)
end
def clearLittleArea(x, y)#0

View File

@ -80,7 +80,8 @@ struc Player
byte b_level
word w_curXP
word w_nextXP
word b_skillPoints
byte b_skillPoints
byte b_packSize
// Lists
word p_skills // list:Modifier

View File

@ -254,13 +254,6 @@ def _buyFromStore(storeCode, profitPercent)#1
while TRUE
if redisplay
nItemsOnPage = displayBuyPage(pItemTbl, ratio, pageNum, nPages)
flipToPage1 // FOO
^$c051
mmgr(DEBUG_MEM, 0)
rdkey
auxMmgr(DEBUG_MEM, 0)
rdkey
^$c050
fin
choice = getUpperKey()
redisplay = TRUE