Files
SplitBit-Emulator/Programs/CosmOS/Apps/Copy.asm
T
Anachronaut 87d819847e A program can say how it went
SWI osExit takes a status in A, and the shell keeps it. Fifty eight exits
across twenty three programs now say deliberately whether they worked: 25
did what they were asked, 24 did not, 9 were asked wrongly. Compare is the
exception and says so - one there means the files differ, which is a result
rather than a failure, the way diff has always had it.

IN A RATHER THAN Q, which is not a departure from the rule that a service
answers in Q. This one takes an ARGUMENT, the way osPrintNumber takes A and
B, and it never returns to answer anything. A is free precisely because a
return would have put it back - and Q is the ALU's output, so a small
number costs four instructions there against one in A.

The shell does not print it. A program that failed has already said so in
words and a number beside that is noise, so osLastStatus hands it back and
Status is the program that shows it. That indirection is the point: the
number exists for the thing that cannot read words.

MARKING THE EXITS FOUND A DEFECT ON THE FIRST RUN. Type and More printed
why they had failed and then fell through into the success exit, reporting
that all was well. Nobody had noticed, because while the only reader was a
person, the person could see both the complaint and the claim.

Two smaller things. Snake sets the console to line mode and then exits with
zero, and the linter flagged the second RSTA as redundant - an exit status
and a console mode, equal by accident, which is the class that must never
be collapsed. And the README still taught answering by writing into the
frame, three months of habit that SRET replaced yesterday; that section is
gone and the one describing SRET stands in its place.
2026-08-27 19:16:21 -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 0x4000
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 0x2000
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