mirror of
https://github.com/dschmenk/PLASMA.git
synced 2026-03-12 01:41:40 +00:00
739 lines
19 KiB
Plaintext
Executable File
739 lines
19 KiB
Plaintext
Executable File
//
|
|
// Handle based swapping memory manager
|
|
//
|
|
include "inc/cmdsys.plh"
|
|
include "inc/fileio.plh"
|
|
|
|
struc t_initdata
|
|
word volptr
|
|
word freeblks
|
|
word ramvol
|
|
word bestvol
|
|
word ramfree
|
|
word bestfree
|
|
word filecnt
|
|
word catentry
|
|
byte catref
|
|
byte firstblk
|
|
byte entrylen
|
|
byte entriesblk
|
|
byte swapstrlen
|
|
byte[4] volparms
|
|
byte[] volinfo
|
|
byte[] catalog
|
|
end
|
|
word initdata
|
|
//
|
|
// Access bytes within a word
|
|
//
|
|
struc t_word
|
|
byte lsb
|
|
byte msb
|
|
end
|
|
//
|
|
// Alloced memory block structure
|
|
//
|
|
struc t_memblk
|
|
word blksiz
|
|
byte blkref
|
|
byte blklok
|
|
end
|
|
//
|
|
// Free memory block structure
|
|
//
|
|
struc t_freblk
|
|
word fresiz
|
|
word frenxt
|
|
end
|
|
//
|
|
// Block size
|
|
//
|
|
const MAX_BLK_SIZE = $2010
|
|
const MAX_BLK_MASK = $1FFF
|
|
const MIN_BLK_SIZE = $04
|
|
const MIN_BLK_MASK = $03
|
|
//
|
|
// Block states
|
|
//
|
|
const HMEM_ADDR = $FFFC
|
|
const HMEM_SIZE = $FFFC
|
|
const HMEM_STATE = $03
|
|
const HMEM_MOVEABLE = $00 // Many dependencies on this being $00
|
|
const HMEM_AVAIL = $01
|
|
const HMEM_LOCKED = $02
|
|
const HMEM_SWAPPED = $03
|
|
//
|
|
// Block flags
|
|
//
|
|
const HMEM_ACCESSED = $80
|
|
//
|
|
// Handle modifier
|
|
//
|
|
const HMOD = $4321
|
|
//
|
|
// Handle tables/lists
|
|
//
|
|
const PG_SIZE = 512
|
|
const PG_ENTRIES = 256
|
|
const PG_TBL_SIZE = 8
|
|
word sysbuf
|
|
word[PG_TBL_SIZE] hpgtbl // Handle page table
|
|
word pooladdr
|
|
word poolsize
|
|
word frelst // Free list
|
|
byte sweeppg, sweepen
|
|
byte[64] swapvol = "/" // Swap volume
|
|
byte swapdir = "/SWAP/"
|
|
byte hexchar = '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
|
|
//
|
|
// DEBUG
|
|
//
|
|
//byte swapinstr = "Swap in:"
|
|
//byte swapoutstr = "Swap out:"
|
|
//byte getblkstr = "Get block = "
|
|
//byte allocpgstr = "Alloc page:"
|
|
//
|
|
//def putln
|
|
// return putc($0D)
|
|
//end
|
|
//def putb(hexb)
|
|
// return call($FDDA, hexb, 0, 0, 0)
|
|
//end
|
|
//def puth(hex)
|
|
// return call($F941, hex >> 8, hex, 0, 0)
|
|
//end
|
|
//
|
|
// Fill block filename
|
|
//
|
|
def strcharadd(str, chr)#0
|
|
^str = ^str + 1
|
|
str->.[^str] = chr
|
|
end
|
|
def swapfile(filestr, hmem)#0
|
|
memcpy(filestr, @swapvol, swapvol + 1)
|
|
strcharadd(filestr, 'H')
|
|
strcharadd(filestr, hexchar[(hmem >> 12) & $0F])
|
|
strcharadd(filestr, hexchar[(hmem >> 8) & $0F])
|
|
strcharadd(filestr, hexchar[(hmem >> 4) & $0F])
|
|
strcharadd(filestr, hexchar[ hmem & $0F])
|
|
end
|
|
//
|
|
// Find exact/best free memory match
|
|
//
|
|
def unlink(freblk, freprv)
|
|
//
|
|
// Unlink free block
|
|
//
|
|
if freprv
|
|
freprv=>frenxt = freblk=>frenxt
|
|
else
|
|
frelst = freblk=>frenxt
|
|
fin
|
|
return freblk
|
|
end
|
|
def unfre(freblk, freprv, size)
|
|
word shrink
|
|
|
|
if freblk=>fresiz == size
|
|
//
|
|
// Unlink free block
|
|
//
|
|
unlink(freblk, freprv)
|
|
elsif freblk=>fresiz > size
|
|
//
|
|
// Shrink free block
|
|
//
|
|
shrink = freblk + size
|
|
if freprv
|
|
freprv=>frenxt = shrink
|
|
else
|
|
frelst = shrink
|
|
fin
|
|
shrink=>fresiz = freblk=>fresiz - size
|
|
shrink=>frenxt = freblk=>frenxt
|
|
else
|
|
freblk = 0
|
|
fin
|
|
return freblk
|
|
end
|
|
def addfre(freblk)#0
|
|
word srch
|
|
|
|
//freblk=>fresiz = freblk=>blksiz
|
|
if frelst and frelst < freblk
|
|
srch = frelst
|
|
while srch=>frenxt
|
|
if srch=>frenxt > freblk
|
|
//
|
|
// Insert into list
|
|
//
|
|
freblk=>frenxt = srch=>frenxt
|
|
srch=>frenxt = freblk
|
|
return
|
|
fin
|
|
srch = srch=>frenxt
|
|
loop
|
|
//
|
|
// Add to end of list
|
|
//
|
|
freblk=>frenxt = 0
|
|
srch=>frenxt = freblk
|
|
else
|
|
//
|
|
// Add to beginning of list
|
|
//
|
|
freblk=>frenxt = frelst
|
|
frelst = freblk
|
|
fin
|
|
end
|
|
//
|
|
// Memory coallesce/compaction/swap out routines
|
|
//
|
|
def coallesce
|
|
word srch, combined
|
|
|
|
combined = 0
|
|
srch = frelst
|
|
while srch and srch=>frenxt
|
|
if srch + srch=>fresiz == srch=>frenxt
|
|
//
|
|
// Combine adjacent free space
|
|
//
|
|
//putc('C');putc(' ');puth(srch);putc('+');puth(srch=>frenxt);putc(' ')
|
|
srch=>fresiz = srch=>fresiz + srch=>frenxt=>fresiz
|
|
srch=>frenxt = srch=>frenxt=>frenxt
|
|
combined = 1
|
|
else
|
|
srch = srch=>frenxt
|
|
fin
|
|
loop
|
|
return combined
|
|
end
|
|
def compact
|
|
word page, entry, memblk, moveblk, size, srch, prev
|
|
byte moved
|
|
|
|
moved = 0
|
|
for page = PG_TBL_SIZE - 1 downto 0
|
|
if hpgtbl[page]
|
|
for entry = 255 downto 0
|
|
if hpgtbl:[page, entry].lsb & HMEM_STATE == HMEM_MOVEABLE
|
|
memblk = hpgtbl:[page, entry]
|
|
size = memblk=>blksiz
|
|
moveblk = 0
|
|
prev = 0
|
|
srch = frelst
|
|
while srch and srch < memblk
|
|
if srch=>fresiz >= size
|
|
moveblk = unfre(srch, prev, size)
|
|
break
|
|
fin
|
|
prev = srch
|
|
srch = srch=>frenxt
|
|
loop
|
|
if moveblk
|
|
//putc('M');putc(' ');puth(moveblk);putc('=');puth(memblk);putc(' ')
|
|
memcpy(moveblk, memblk, size)
|
|
hpgtbl:[page, entry] = moveblk
|
|
addfre(memblk)
|
|
moved = 1
|
|
fin
|
|
fin
|
|
next
|
|
else
|
|
break
|
|
fin
|
|
next
|
|
if moved
|
|
coallesce
|
|
fin
|
|
return moved
|
|
end
|
|
//
|
|
// Swap out memory block
|
|
//
|
|
def swapout(accessed)
|
|
byte[64] filename
|
|
byte ref
|
|
word page, entry, memblk, hmem, size
|
|
byte swapped
|
|
|
|
swapped = 0
|
|
for page = PG_TBL_SIZE - 1 downto 0
|
|
if hpgtbl[page]
|
|
for entry = 255 downto 0
|
|
if hpgtbl:[page, entry].lsb & HMEM_STATE == HMEM_MOVEABLE
|
|
memblk = hpgtbl:[page, entry]
|
|
if not (memblk->blklok & accessed)
|
|
//
|
|
// Swap this block out
|
|
//
|
|
size = memblk=>blksiz
|
|
hmem.lsb = page
|
|
hmem.msb = entry
|
|
swapfile(@filename, hmem)
|
|
fileio:create(@filename, $00, size) // embed size in aux type
|
|
//puts(@swapoutstr);puts(@filename);putc('@');puth(memblk);putc(':');puth(size);putln
|
|
ref = fileio:open(@filename)
|
|
if ref
|
|
//
|
|
// Write it out
|
|
//
|
|
if fileio:write(ref, memblk, size) == size
|
|
//
|
|
// Zero size in page table flags swapin to read from disk
|
|
//
|
|
hpgtbl:[page, entry] = HMEM_SWAPPED
|
|
addfre(memblk)
|
|
swapped = 1
|
|
fin
|
|
fileio:close(ref)
|
|
fin
|
|
fin
|
|
fin
|
|
next
|
|
else
|
|
break
|
|
fin
|
|
next
|
|
if swapped
|
|
coallesce
|
|
compact
|
|
fin
|
|
return swapped
|
|
end
|
|
//
|
|
// Find a memory block
|
|
//
|
|
def findexact(size)
|
|
word srch, prev
|
|
|
|
srch = frelst
|
|
prev = 0
|
|
while srch
|
|
if srch=>fresiz == size
|
|
//putc('E')
|
|
return unlink(srch, prev)
|
|
fin
|
|
prev = srch
|
|
srch = srch=>frenxt
|
|
loop
|
|
return 0
|
|
end
|
|
def findbest(size)
|
|
word srch, prev
|
|
|
|
prev = 0
|
|
srch = frelst
|
|
while srch
|
|
if srch=>fresiz >= size
|
|
//putc('B')
|
|
return unfre(srch, prev, size)
|
|
fin
|
|
prev = srch
|
|
srch = srch=>frenxt
|
|
loop
|
|
return 0
|
|
end
|
|
def findblk(size)
|
|
word addr
|
|
|
|
if size > MAX_BLK_SIZE; return 0; fin
|
|
addr = findexact(size)
|
|
if !addr
|
|
coallesce
|
|
addr = findexact(size)
|
|
if !addr
|
|
compact
|
|
addr = findbest(size)
|
|
if !addr
|
|
swapout(HMEM_ACCESSED)
|
|
addr = findbest(size)
|
|
if !addr
|
|
swapout(0)
|
|
addr = findbest(size)
|
|
fin
|
|
fin
|
|
fin
|
|
fin
|
|
//
|
|
// Fill in the block
|
|
//
|
|
//puts(@getblkstr);puth(addr);putc(':');puth(size);putln
|
|
if addr
|
|
addr=>blksiz = size
|
|
addr->blkref = 1
|
|
addr->blklok = 0
|
|
fin
|
|
return addr
|
|
end
|
|
//
|
|
// Swap in a memory block (or allocate an uninitialized block)
|
|
//
|
|
def swapin(hmem)
|
|
byte[64] filename
|
|
byte[15] info
|
|
byte ref
|
|
word memblk, size
|
|
|
|
size = hpgtbl:[hmem.lsb, hmem.msb] & HMEM_SIZE
|
|
if size
|
|
//
|
|
// This was just uninitialized memory, don't bother reading from file
|
|
//
|
|
memblk = findblk(size)
|
|
else
|
|
//
|
|
// Swap this block back in
|
|
//
|
|
swapfile(@filename, hmem)
|
|
fileio:getfileinfo(@filename, @info)
|
|
size = info:2 // Size encoded in aux type
|
|
memblk = findblk(size)
|
|
//puts(@swapinstr);puts(@filename);putc('@');puth(memblk);putc(':');puth(size);putln
|
|
if memblk
|
|
//
|
|
// Read it in
|
|
//
|
|
ref = fileio:open(@filename)
|
|
if ref
|
|
fileio:read(ref, memblk, size)
|
|
fileio:close(ref)
|
|
fileio:destroy(@filename)
|
|
fin
|
|
fin
|
|
fin
|
|
if memblk
|
|
hpgtbl:[hmem.lsb, hmem.msb] = memblk
|
|
fin
|
|
return memblk
|
|
end
|
|
//
|
|
// Incrementally clear the ACCESSED BIT
|
|
//
|
|
export def sweep#0
|
|
word memblk
|
|
|
|
if hpgtbl[sweeppg]
|
|
memblk = hpgtbl:[sweeppg, sweepen]
|
|
when memblk.lsb & HMEM_STATE
|
|
is HMEM_MOVEABLE
|
|
is HMEM_LOCKED
|
|
memblk = memblk & HMEM_ADDR
|
|
if memblk->blklok & HMEM_ACCESSED
|
|
memblk->blklok = memblk->blklok & $7F
|
|
fin
|
|
wend
|
|
if sweepen == 255
|
|
sweepen = 0
|
|
if sweeppg == 0
|
|
sweeppg = PG_TBL_SIZE - 1
|
|
else
|
|
sweeppg = sweeppg - 1
|
|
fin
|
|
else
|
|
sweepen = sweepen + 1
|
|
fin
|
|
else
|
|
sweeppg = PG_TBL_SIZE - 1
|
|
fin
|
|
end
|
|
//
|
|
// Set end of memory pool
|
|
//
|
|
export def brk(addr)
|
|
word heapalign, brkblk, brksiz, srch
|
|
|
|
//
|
|
// Check if addr is too high or low
|
|
//
|
|
if isuge(addr, @heapalign); return 0; fin
|
|
if isule(addr, heapmark); return 0; fin
|
|
if not pooladdr
|
|
//
|
|
// Allocate the memory pool
|
|
//
|
|
heapalign = (heapmark | MIN_BLK_MASK) + 1
|
|
brksiz = addr - heapalign
|
|
if isult(brksiz, MAX_BLK_SIZE); return 0; fin // Not enough heap
|
|
poolsize = addr - heapmark
|
|
pooladdr = heapalloc(poolsize)
|
|
if pooladdr
|
|
frelst = heapalign
|
|
frelst=>fresiz = brksiz
|
|
frelst=>frenxt = 0
|
|
else
|
|
poolsize = 0
|
|
fin
|
|
else
|
|
//
|
|
// Can we extend the memory pool?
|
|
//
|
|
if pooladdr + poolsize == heapmark
|
|
brksiz = addr - heapmark
|
|
brkblk = heapalloc(brksiz)
|
|
if brkblk
|
|
//
|
|
// Add block to end of free list
|
|
//
|
|
poolsize = poolsize + brksiz
|
|
brkblk=>fresiz = brksiz
|
|
brkblk=>frenxt = 0
|
|
if frelst
|
|
srch = frelst
|
|
while srch=>frenxt; srch = srch=>frenxt; loop
|
|
srch=>frenxt = brkblk
|
|
else
|
|
frelst = brkblk
|
|
fin
|
|
coallesce // combine adjacent free space
|
|
fin
|
|
fin
|
|
fin
|
|
return poolsize
|
|
end
|
|
export def sbrk(size)
|
|
return brk((heapmark | MIN_BLK_MASK) + 1 + size + MIN_BLK_SIZE)
|
|
end
|
|
//
|
|
// Return the amount of free memory available, after garbage
|
|
// collection, swaps
|
|
//
|
|
export def hmemFre(lptr)
|
|
word srch, free, largest
|
|
|
|
coallesce
|
|
while compact; loop
|
|
free = 0
|
|
largest = 0
|
|
srch = frelst
|
|
while srch
|
|
//putc('F'); putc(' '); puth(srch); putc(':'); puth(srch=>fresiz); putln
|
|
free = free + srch=>fresiz
|
|
if srch=>fresiz > largest
|
|
largest = srch=>fresiz
|
|
fin
|
|
srch = srch=>frenxt
|
|
loop
|
|
if lptr
|
|
*lptr = largest - MIN_BLK_SIZE
|
|
fin
|
|
return free - MIN_BLK_SIZE
|
|
end
|
|
//
|
|
// Allocate memory block
|
|
//
|
|
export def hmemNew(size)
|
|
word page, entry, hnew, memblk
|
|
|
|
//
|
|
// First, find a free handle
|
|
//
|
|
for page = PG_TBL_SIZE - 1 downto 0
|
|
if !hpgtbl[page]
|
|
//
|
|
// Allocate a new page table
|
|
//
|
|
hpgtbl[page] = heapalloc(PG_SIZE)
|
|
memset(hpgtbl[page], HMEM_AVAIL, PG_SIZE)
|
|
//puts(@allocpgstr);puth(hpgtbl[page]);putln
|
|
//
|
|
// Check if we need to allocate the memory pool
|
|
//
|
|
if not pooladdr
|
|
//
|
|
// Allocate 3/4 of available heap on 128K machine, 1/2 on 64K machine
|
|
//
|
|
poolsize = (heapavail >> 1) & $7FFF
|
|
if MACHID & $30 == $30
|
|
poolsize = poolsize + (poolsize >> 1)
|
|
fin
|
|
if isult(poolsize, MAX_BLK_SIZE)
|
|
poolsize = MAX_BLK_SIZE
|
|
fin
|
|
sbrk(poolsize)
|
|
fin
|
|
fin
|
|
for entry = 255 downto 0
|
|
if hpgtbl:[page, entry].lsb == HMEM_AVAIL
|
|
//
|
|
// Reserve handle as swapped out block
|
|
// Nonzero size will flag swapin to not read from disk
|
|
//
|
|
//putc('N');putc(' ');putb(entry);putb(page);putc('@')
|
|
size = ((size + t_memblk) | MIN_BLK_MASK) + 1
|
|
hpgtbl:[page, entry] = size | HMEM_SWAPPED
|
|
hnew.lsb = page
|
|
hnew.msb = entry
|
|
return hnew
|
|
fin
|
|
next
|
|
next
|
|
return 0
|
|
end
|
|
//
|
|
// Lock memory block in place
|
|
//
|
|
export def hmemLock(hmem)
|
|
word memblk
|
|
|
|
memblk = hpgtbl:[hmem.lsb, hmem.msb]
|
|
when memblk.lsb & HMEM_STATE
|
|
is HMEM_SWAPPED
|
|
memblk = swapin(hmem)
|
|
if not memblk; return 0; fin
|
|
is HMEM_MOVEABLE
|
|
hpgtbl:[hmem.lsb, hmem.msb] = memblk | HMEM_LOCKED
|
|
is HMEM_LOCKED
|
|
memblk = memblk & HMEM_ADDR
|
|
memblk->blklok = (memblk->blklok + 1) | HMEM_ACCESSED
|
|
//putc('L');putc(' ');puth(hmem);putc('@');puth(memblk);putln
|
|
return memblk + t_memblk
|
|
wend
|
|
return 0
|
|
end
|
|
//
|
|
// Unlock memory block
|
|
//
|
|
export def hmemUnlock(hmem)#0
|
|
byte lock
|
|
word memblk
|
|
|
|
memblk = hpgtbl:[hmem.lsb, hmem.msb]
|
|
if memblk.lsb & HMEM_STATE == HMEM_LOCKED
|
|
memblk = memblk & HMEM_ADDR
|
|
lock = memblk->blklok - 1
|
|
if lock == HMEM_ACCESSED
|
|
//
|
|
// Block is now moveable
|
|
//
|
|
hpgtbl:[hmem.lsb, hmem.msb] = memblk
|
|
fin
|
|
memblk->blklok = lock
|
|
//putc('U');putc(' ');puth(hmem);putln
|
|
fin
|
|
end
|
|
//
|
|
// Increment reference count
|
|
//
|
|
export def hmemRef(hmem)#0
|
|
word memblk
|
|
|
|
memblk = hpgtbl:[hmem.lsb, hmem.msb]
|
|
when memblk.lsb & HMEM_STATE
|
|
is HMEM_SWAPPED
|
|
memblk = swapin(hmem)
|
|
is HMEM_LOCKED
|
|
is HMEM_MOVEABLE
|
|
memblk = memblk & HMEM_ADDR
|
|
if not memblk; return; fin
|
|
memblk->blkref = memblk->blkref + 1
|
|
wend
|
|
end
|
|
//
|
|
// Decrement reference count
|
|
//
|
|
export def hmemDel(hmem)#0
|
|
byte ref
|
|
word memblk
|
|
|
|
memblk = hpgtbl:[hmem.lsb, hmem.msb]
|
|
when memblk & HMEM_STATE
|
|
is HMEM_SWAPPED
|
|
memblk = swapin(hmem)
|
|
is HMEM_LOCKED
|
|
is HMEM_MOVEABLE
|
|
memblk = memblk & HMEM_ADDR
|
|
if not memblk; return; fin
|
|
ref = memblk->blkref - 1
|
|
if ref == 0
|
|
//
|
|
// No more references, free block
|
|
//
|
|
hpgtbl:[hmem.lsb, hmem.msb] = HMEM_AVAIL
|
|
addfre(memblk)
|
|
else
|
|
memblk->blkref = ref
|
|
fin
|
|
break
|
|
wend
|
|
end
|
|
//
|
|
// Initialization:
|
|
//
|
|
// Search for best swap volume
|
|
//
|
|
// !!! Does this work on Apple ///???
|
|
//
|
|
sysbuf = $0800 // heapallocalign(1024, 8, 0)
|
|
initdata = heapalloc(t_initdata) // Use data on heap for initialization
|
|
initdata=>volparms.0 = 2
|
|
initdata=>volparms.1 = 0
|
|
initdata=>volparms:2 = sysbuf
|
|
syscall($C5, @initdata=>volparms)
|
|
initdata=>volptr = sysbuf
|
|
initdata=>ramfree = 0
|
|
initdata=>bestfree = 0
|
|
for sweepen = 0 to 15
|
|
^initdata=>volptr = ^initdata=>volptr & $0F
|
|
if ^initdata=>volptr
|
|
memcpy(@swapvol + 2, initdata=>volptr + 1, ^initdata=>volptr)
|
|
swapvol = ^initdata=>volptr + 1
|
|
fileio:getfileinfo(@swapvol, @initdata->volinfo)
|
|
initdata=>freeblks = initdata=>volinfo:2 - initdata=>volinfo:5
|
|
if initdata=>volptr:1 == $522F and initdata=>volptr:3 == $4D41 // '/RAM'
|
|
if isugt(initdata=>freeblks, initdata=>ramfree)
|
|
initdata=>ramvol = initdata=>volptr
|
|
initdata=>ramfree = initdata=>freeblks
|
|
fin
|
|
elsif isugt(initdata=>freeblks, initdata=>bestfree)
|
|
initdata=>bestvol = initdata=>volptr
|
|
initdata=>bestfree = initdata=>freeblks
|
|
fin
|
|
fin
|
|
initdata=>volptr = initdata=>volptr + 16
|
|
next
|
|
if isugt(initdata=>ramfree, $40) or isugt(initdata=>ramfree, initdata=>bestfree) // RAMdrive greater than 64K? Use it
|
|
initdata=>bestvol = initdata=>ramvol
|
|
initdata=>bestfree = initdata=>ramfree
|
|
fin
|
|
memcpy(@swapvol + 2, initdata=>bestvol + 1, ^initdata=>bestvol)
|
|
swapvol = ^initdata=>bestvol + 1
|
|
memcpy(@swapvol + swapvol + 1, @swapdir + 1, swapdir)
|
|
swapvol = swapvol + swapdir
|
|
fileio:create(@swapvol, $0F, $0000) // Create the swap directory
|
|
//
|
|
// Clear out left over swap files
|
|
//
|
|
initdata->catref = fileio:open(@swapvol)
|
|
initdata->firstblk = 1
|
|
initdata->swapstrlen = swapvol
|
|
repeat
|
|
if fileio:read(initdata->catref, @initdata->catalog, 512) == 512
|
|
initdata=>catentry = @initdata->catalog.4
|
|
if initdata->firstblk
|
|
initdata->entrylen = initdata->catalog.$23
|
|
initdata->entriesblk = initdata->catalog.$24
|
|
initdata=>filecnt = initdata=>catalog:$25
|
|
initdata=>catentry = initdata=>catentry + initdata->entrylen
|
|
fin
|
|
for sweepen = initdata->firstblk to initdata->entriesblk
|
|
^initdata=>catentry = ^initdata=>catentry & $0F
|
|
if ^initdata=>catentry
|
|
memcpy(@swapvol + swapvol + 1, initdata=>catentry + 1, ^initdata=>catentry)
|
|
swapvol = swapvol + ^initdata=>catentry
|
|
fileio:destroy(@swapvol)
|
|
swapvol = initdata->swapstrlen
|
|
fin
|
|
initdata=>catentry = initdata=>catentry + initdata->entrylen
|
|
next
|
|
initdata->firstblk = 0
|
|
else
|
|
initdata->filecnt = 0
|
|
fin
|
|
until !initdata->filecnt
|
|
fileio:close(initdata->catref)
|
|
heaprelease(initdata)
|
|
//puts(@swapvol); putln
|
|
done
|