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.
277 lines
4.4 KiB
NASM
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
|