Work across two disks: copy between them, and run a program from one on

files from the other

Two things anybody expects of a second disk, and each needed something
different.

COPYING NEEDED TWO THINGS TO REMEMBER A DRIVE.

The write stream is the only thing here that lives across service calls, so
it is the only thing whose drive can change underneath it: every
osFileBlock names its source path again and goes back to the source drive,
and then osFileWrite has to come home. It records the drive it was opened
on and returns there.

And the file lookup CACHE. It keeps the last path resolved so a reader
walking a file does not re-walk the directory for every block - and
skipping the walk skipped the drive the path named, so block one of a
cross-drive copy read the source's block numbers off the DESTINATION disk.
It only showed on files of more than one block, because a file of one is
never looked up twice. One block worked and two did not, which is a
suspicious enough shape to have suspected sooner.

RUNNING A PROGRAM FROM ELSEWHERE NEEDED A THIRD PLACE TO LOOK, and two
restorations.

The shell tried where you are and /Apps on the disk you are on. It now
tries /Apps on drive 0 as well, which is what makes the system's programs
work from a disk of your own - one with your files on it and no system,
which is most of the point of having a second disk.

The drive goes back after the load, because by then the program is in
memory and the blocks it came from mean nothing; and again when it exits,
because a program that copies between disks moves the drive as its own
paths need to and being left wherever it finished is not what was asked
for. Copy 1:/a 0:/b now leaves you exactly where you were.

The fixture disk grew an /Apps, because it kept its programs at the root
and so could not exercise the third place at all.

Two hours of the debugging above were spent on a stale disk image. The
machine boots the system that is ON the image, so a rebuilt cosmos.bin
means nothing until the image is rebuilt too - and the trace said my new
code never ran, which was true. Third time this project has been misled by
one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-08-31 16:14:53 -04:00
co-authored by Claude Opus 5
parent 4cc6393f5b
commit e4f4bae762
12 changed files with 223 additions and 21 deletions
+99 -11
View File
@@ -437,14 +437,24 @@ promptUnknown:
LDA.0
BRA promptSayUnknown ; No filesystem, so there is nothing to look through.
; TWO PLACES, TRIED IN ORDER: where you are, and then the system's own place for
; programs. The first is what makes a program you are working on the one that runs; the
; second is what makes Snake work from anywhere without a copy of it in every directory.
; Neither is stored anywhere, so there is nothing to configure and nothing to go stale.
; THREE PLACES, TRIED IN ORDER: where you are, the system's own place for programs on the
; disk you are on, and then that same place on drive 0. The first is what makes a program
; you are working on the one that runs; the second is what makes Snake work from anywhere
; without a copy of it in every directory; the third is what makes it work from a disk of
; your own, which has your files on it and no system.
;
; None of them is stored anywhere, so there is nothing to configure and nothing to go
; stale.
RSTA
SETD.0 NamePrefix
STA.0
; Where the person is, kept so it can be given back. A program is fetched from wherever it
; lives and then runs on the files of whoever ran it.
INA 0x24
SETD.0 SearchDrive
STA.0
promptSearch:
CALL nameProgram
SETD.0 NameOk
@@ -454,7 +464,22 @@ promptSearch:
CALL loadProgram
SETD.0 LoadStatus
LDA.0
BRA runLoaded ; It loaded, and the machine is its now.
BNA promptNotLoaded
; ---- Loaded, so the drive goes back to the person ----
;
; The program is in memory now and the block numbers it came from mean nothing any more,
; which is what makes this safe here and not in the middle of a path. A program fetched
; from the system disk then runs on the disk its user was standing on - which is the whole
; point of being able to keep a disk of your own.
SETD.0 SearchDrive
LDA.0
CALL sbfsUse
BRI runLoaded ; It loaded, and the machine is its now.
promptNotLoaded:
SETD.0 LoadStatus
LDA.0
; No file of that name is not a fault. It is the ordinary case of a word this shell does
; not know, and it is the only answer worth looking somewhere else for. Anything else
@@ -467,10 +492,13 @@ promptSearch:
BNQ loadFailed
promptElsewhere:
; Was that already the second place?
; Was that the last place there is?
SETD.0 NamePrefix
LDA.0
BNA promptSayUnknown
INIB 0d2
CCF
SUB
BRQ promptGaveUp
; A word beginning with a separator has said where to look, and looking somewhere else
; would be answering a different question from the one asked.
@@ -481,11 +509,19 @@ promptElsewhere:
SUB
BRQ promptSayUnknown
INIA 0x01
SETD.0 NamePrefix
LDA.0
INCA
STA.0
BRI promptSearch
promptGaveUp:
; Every place has been tried, and the drive is put back before anybody is told anything:
; the search moved it, and a word the shell does not know should not move somebody either.
SETD.0 SearchDrive
LDA.0
CALL sbfsUse
promptSayUnknown:
; Saying which word was not understood is worth the four instructions: it tells somebody
; who mistyped what they actually typed.
@@ -760,7 +796,15 @@ nameProgram:
SETD.0 NamePrefix
LDA.0
BRA nameFromLine
; One is the system's place on this disk; two is the same place on drive 0.
INIB 0d2
CCF
SUB
BRQ nameSystemApps
SETD.0 AppsPrefix
BRI namePrefixCopy
nameSystemApps:
SETD.0 SystemAppsPrefix
namePrefixCopy:
LDA.0
BRA nameFromLine
@@ -1789,6 +1833,13 @@ scriptNoName:
SETD.0 ScriptUsage
BRI fileComplain
; Where the person was standing when a program was started, so it can be given back when the
; program has finished with the machine. A program that copies between two disks moves the
; drive as its own paths need it to; that is its business, and being left on the disk it
; happened to finish with is not what the person asked for.
;
; SET WHEREVER A PROGRAM STARTS, of which there are two: run, and typing a program's name.
; Restored in handleExit, which is the one place they both come back through.
; ---- run ----
;
; Hands the machine to whatever was loaded. Where the Stack is now is written down first,
@@ -1805,6 +1856,9 @@ doRun:
; program's own name it is what followed the name, which is the same thing meaning the
; same thing.
runLoaded:
INA 0x24
SETD.0 RunDrive
STA.0
MVSD.0
SETD.1 SystemStack
STD.0.1
@@ -2151,9 +2205,20 @@ fileLookup:
CALL textSame
BNQ fileLookupSearch
; The same file as last time. The description still has to be put back, because anything
; that went to the disk in between - a directory listing, a program being loaded - left
; its own answer in those three.
; ---- The same file as last time, and possibly not the same disk ----
;
; The description has to be put back, because anything that went to the disk in between - a
; directory listing, a program being loaded - left its own answer in those three.
;
; AND THE DRIVE WITH IT. Skipping the walk skips the drive the path named, so a cache hit
; on a machine that had moved read the right block numbers off the wrong disk. Copying
; between two disks is exactly that: block 0 walks and goes to the source, the write goes to
; the destination, and block 1 hits this cache. It only showed on files of more than one
; block, because a file of one is never looked up twice.
SETD.0 FileCacheDrive
LDA.0
CALL sbfsUse
SETD.0 SbfsFileStart
SETD.2 FileCacheStart
CALL sbfsSetWord
@@ -2196,6 +2261,14 @@ fileLookupSearch:
SETD.0 FileCacheTail
STA.0
; ---- And which disk those block numbers are on ----
;
; A start block means nothing without it. The walk above went to whatever drive the path
; named, so the answer is the drive now.
INA 0x24
SETD.0 FileCacheDrive
STA.0
; Marked good last, so that a cache half filled is never a cache believed.
INIA 0d1
SETD.0 FileCacheValid
@@ -2622,6 +2695,13 @@ handleExit:
SETD.1 LastStatus
STA.1
; The drive the person was on, whatever the program did with it.
PSHA
SETD.1 RunDrive
LDA.1
CALL sbfsUse
POPA
; And the line that started it failed, if the program says it did. The script reader asks
; one question - did this line work - and a program answering "no" is one of the ways it
; can be answered.
@@ -3831,6 +3911,8 @@ Separator:
; next, and there is no such place yet.
AppsPrefix:
"/Apps/"
SystemAppsPrefix:
"0:/Apps/"
IsDirectory:
"that is a directory"
AndText:
@@ -4106,6 +4188,12 @@ PrintNumber:
;
; The name is twenty three bytes for a name of twenty two, so that a name filling the
; field still has a zero after it and can be compared as a string.
FileCacheDrive:
0x00
SearchDrive:
0x00
RunDrive:
0x00
FileCacheValid:
0x00
FileCacheName:
+22
View File
@@ -2932,6 +2932,16 @@ sbfsStreamNoTemp:
SETD.2 SbfsFileStart
CALL sbfsSetWord
; ---- And which disk all of that is on ----
;
; A write stream is the one thing here that lives across service calls, so it is the one
; thing that can have the drive changed underneath it. Copying between two disks is exactly
; that: every osFileBlock re-resolves the SOURCE path and goes to its drive, and then
; osFileWrite has to come back here. The path was walked above, so the drive is right now.
INA 0x24
SETD.0 SbfsStreamDrive
STA.0
INIA 0x01
SETD.0 SbfsStreamOpen
STA.0
@@ -2941,6 +2951,13 @@ sbfsStreamNoTemp:
ADD
RET
; Back to the disk the open stream belongs to, whatever has been read in between.
sbfsStreamHere:
SETD.0 SbfsStreamDrive
LDA.0
CALL sbfsUse
RET
sbfsStreamNo:
RSTA
INIB 0d1
@@ -2954,6 +2971,7 @@ sbfsStreamWrite:
SETD.0 SbfsStreamOpen
LDA.0
BRA sbfsStreamNo
CALL sbfsStreamHere
; Where the file is and how big it is, said again rather than looked up: all three were
; settled when the temporary was made, and everything since has been describing whatever
@@ -2980,6 +2998,7 @@ sbfsStreamFetch:
SETD.0 SbfsStreamOpen
LDA.0
BRA sbfsStreamNo
CALL sbfsStreamHere
SETD.0 SbfsStreamTo
STD.1.0
@@ -3016,6 +3035,7 @@ sbfsStreamDone:
SETD.0 SbfsStreamOpen
LDA.0
BRA sbfsStreamNo
CALL sbfsStreamHere
; What it really came to, put aside before anything walks the disk.
SETD.0 SbfsStreamNewBlocks
@@ -3639,6 +3659,8 @@ SbfsTempName:
"sbfs.part"
; ---- What a file being written a block at a time keeps ----
SbfsStreamDrive:
0x00
SbfsStreamOpen:
0x00
SbfsStreamPath: