Files
AnachronautandClaude Opus 5 3449405b18 Give the system another page of each memory
CosmOS had 1,161 bytes of Program Memory left before the address applications
load at, and Tab completion is not going to fit in that with anything to spare.
So the wall moves up one page: the system keeps below 0x4FFF and 0x2FFF, and an
application is based at 0x5000 and 0x3000.

A PAGE IS A CHEAP THING TO GIVE IT AND AN EXPENSIVE THING TO RUN OUT OF. An
application still has 44K of Program Memory before the vector table and the
largest one here uses 7.5K, so what was taken from applications is space nothing
has ever asked for - while what the system gained is the difference between
building the next thing and counting bytes while building it.

Not doubling, which was the version that would have cost application space worth
minding. One page, and the same again when it is needed.

Nothing in the machine knows where the wall is, so this is 34 #Base lines, one
threshold in the fault handler, and the table in the CosmOS README that
Tests/docs.sh reads its limits out of.

The native assembler's scratch map had to move with it, and docs.sh said so
before anything ran: its data reached 0x40D6 and its buffers began at 0x4000, so
they were sitting on its variables. That file already carries a paragraph about
the floor coming up and the map staying where it was. It has happened twice now,
and been caught by a check the first time wrote.

Twenty three recordings are the same runs a page higher.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
2026-09-01 16:49:12 -04:00

277 lines
4.4 KiB
NASM

; Copy one file to another without asking either file to fit in Data Memory.
;
; The two paths are the two words in the argument. Filesystem names can contain spaces,
; but the CosmOS command line has no quoting yet, so this deliberately has the same rule
; as the shell: a space separates things.
;
; osFileInfo reports how many disk blocks the source occupies, while osFileStart wants the
; shape stored in an SBFS entry: whole blocks and a possible tail. Reading the last block
; first recovers that distinction. The ordinary copy then walks forward one block at a
; time, through one 256-byte buffer.
;
; Written by ChatGPT for Anachronaut's SplitBit
#Include services.asm
#Program
#Base 0x5000
start:
SETD.0 Arguments
INIB 0xFF
SWI osArgument
SETD.0 Arguments
LDA.0
BRA usage
CALL textSplit
SETD.0 TextRest
LDD.0.0
LDA.0
BRA usage
; How many occupied blocks the source has. Keep it as both the loop bound and the
; distinction between an empty file and one whose last block must be inspected.
SETD.0 Arguments
SWI osFileInfo
BNQ sourceFailed
SETD.0 SourceBlocks
STD.3.0
PSHD.3
POPB
POPA
OR
BRQ emptySource
; Read the final occupied block. DP3 says how many bytes of it belong to the file:
; 0x0100 for a whole block, or 0x0001 through 0x00FF for a tail.
SETD.0 SourceBlocks
LDD.3.0
DECD.3
SETD.0 Index
STD.3.0
SETD.0 Arguments
SETD.1 Block
SETD.2 Index
LDA.2
INCD.2
LDB.2
SWI osFileBlock
BNQ readFailed
SETD.0 LastCount
STD.3.0
; A full final block means every occupied block is whole. A short final block means
; there is one fewer whole block and its low-byte count is the tail.
SETD.0 LastCount
LDA.0
BNA wholeEnding
SETD.0 Index
SETD.1 OutputWhole
CALL copyWord
SETD.0 LastCount
INCD.0
LDA.0
SETD.1 OutputTail
STA.1
BRI sizeKnown
wholeEnding:
SETD.0 SourceBlocks
SETD.1 OutputWhole
CALL copyWord
RSTA
SETD.0 OutputTail
STA.0
sizeKnown:
BRI startOutput
emptySource:
RSTA
SETD.0 OutputWhole
STA.0
INCD.0
STA.0
SETD.0 OutputTail
STA.0
startOutput:
SETD.0 TextRest
LDD.0.0
SETD.2 OutputWhole
LDD.3.2
SETD.2 OutputTail
LDA.2
SWI osFileStart
BNQ startFailed
; Empty files have no blocks to transfer, but still need committing so that an existing
; destination becomes an empty file.
SETD.0 SourceBlocks
SETD.1 RemainingBlocks
CALL copyWord
RSTA
SETD.0 Index
STA.0
INCD.0
STA.0
copyNext:
SETD.0 RemainingBlocks
LDA.0
INCD.0
LDB.0
OR
BRQ copyDone
SETD.0 Arguments
SETD.1 Block
SETD.2 Index
LDA.2
INCD.2
LDB.2
SWI osFileBlock
BNQ readFailed
SETD.1 Block
SETD.2 Index
LDA.2
INCD.2
LDB.2
SWI osFileWrite
BNQ writeFailed
CALL stepIndex
CALL takeBlock
BRI copyNext
copyDone:
SETD.2 OutputWhole
LDD.3.2
SETD.2 OutputTail
LDA.2
SWI osFileDone
BNQ doneFailed
SETD.0 Copied
SWI osPrintString
RSTA
SWI osExit
; DP0 names the source word and DP1 the destination word.
copyWord:
LDA.0
STA.1
INCD.0
INCD.1
LDA.0
STA.1
RET
; Increment the big-endian sixteen-bit Index.
stepIndex:
SETD.0 Index
INCD.0
LDA.0
INCA
STA.0
BNC stepDone
DECD.0
LDA.0
INCA
STA.0
stepDone:
RET
; Decrement the big-endian sixteen-bit RemainingBlocks.
takeBlock:
SETD.0 RemainingBlocks
INCD.0
LDA.0
BRA takeBorrow
DECA
STA.0
RET
takeBorrow:
INIA 0xFF
STA.0
DECD.0
LDA.0
DECA
STA.0
RET
usage:
SETD.0 Usage
SWI osPrintString
INIA 0d2
SWI osExit
sourceFailed:
SETD.0 SourceError
SWI osPrintString
INIA 0d1
SWI osExit
readFailed:
SETD.0 ReadError
SWI osPrintString
INIA 0d1
SWI osExit
startFailed:
SETD.0 StartError
SWI osPrintString
INIA 0d1
SWI osExit
writeFailed:
SETD.0 WriteError
SWI osPrintString
INIA 0d1
SWI osExit
doneFailed:
SETD.0 DoneError
SWI osPrintString
INIA 0d1
SWI osExit
#Data
#Base 0x3000
Arguments:
#Reserve 0d256
SourceBlocks:
0x00 0x00
RemainingBlocks:
0x00 0x00
Index:
0x00 0x00
LastCount:
0x00 0x00
OutputWhole:
0x00 0x00
OutputTail:
0x00
Block:
#Reserve 0d256
Usage:
"copy: give me a source and destination
"
SourceError:
"copy: cannot find the source
"
ReadError:
"copy: cannot read the source
"
StartError:
"copy: cannot create the destination
"
WriteError:
"copy: cannot write the destination
"
DoneError:
"copy: cannot finish the destination
"
Copied:
"copied
"
#Include text.asm