ls, a listing laid out to be read
> ls Copy.sbx Say.sbx Where.sbx Walk.sbx ls.sbx Lander where.sh dir says what is there one line each, with sizes and a tally of the disk. This says the names in columns and nothing else, which is what you want ninety times in a hundred. Two programs rather than one with a switch, because they answer different questions and neither answer is a worse version of the other. AND THIS IS A PROGRAM WHERE DIR IS BUILT IN, which is the difference that matters when the disk is what you are doubting: dir is already in memory and this has to be loaded off the disk it is about to list. The daily driver and the diagnostic. Two passes over the directory and no buffer at all. Columns need the longest name before the first line can be printed, which usually means holding every name - twenty four bytes each against a format that allows 1,024 entries. Walking twice costs a read of each directory block, into a buffer that is already there. Across and not down. Real listings go down the columns so that names next to each other alphabetically are next to each other on the screen, and that reason depends on sorting - which nothing here does. With the order arbitrary, down-and-across buys nothing and costs a division. Directories in blue and wearing a separator, unfinished saves in red, everything else plain: whether a file is runnable cannot be known without opening it, and opening every file in a directory to colour a listing is a price nobody agreed to pay. The colour reaches a terminal as well as the screen, so it is one mechanism and not two. ---- Three bugs, and one of them is this machine's oldest trap ---- nameLength answered in A, and a RET puts A back the way the caller had it. So it answered with nothing, and every gap between the columns came out the same width because the padding was subtracting whatever A happened to hold. Q is the ALU's output and nothing puts it back, which is why every answer here comes home in it. The padding subtracted the other way round - the name from the cell - which borrowed on every name that was not the longest, so all of them took the "wider than its cell" path and the listing came out separated by one space. And padding after a name left trailing spaces on every line that did not fill its last column. It goes before the next name now, so spaces only ever fall between two things and a line ends on a name. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
323d7a0330
commit
a13bbeb4db
@@ -0,0 +1,369 @@
|
||||
; A listing laid out to be read.
|
||||
;
|
||||
; > ls
|
||||
; Copy.sbx Say.sbx Where.sbx
|
||||
; Walk.sbx Lander where.sh
|
||||
;
|
||||
; > ls /Apps
|
||||
;
|
||||
; dir says what is there, one line each, with sizes and a tally of the disk. This says the
|
||||
; names and nothing else, in columns, which is what you want ninety times in a hundred - and
|
||||
; the two are separate programs rather than one with a switch because they answer different
|
||||
; questions and neither answer is a worse version of the other.
|
||||
;
|
||||
; ---- Why this is a program and dir is not ----
|
||||
;
|
||||
; dir is built into the shell, and that is what makes it the one to trust when the disk is
|
||||
; the thing being doubted: it is already in memory. This has to be loaded FROM the disk, so it
|
||||
; cannot list a disk too broken to load it. The daily driver and the diagnostic, and it is
|
||||
; worth having both.
|
||||
;
|
||||
; ---- Two passes, and no buffer at all ----
|
||||
;
|
||||
; Columns need the longest name before the first line can be printed, which usually means
|
||||
; holding every name in memory - twenty four bytes each, and this format allows 1,024 entries
|
||||
; on a disk. So instead the directory is walked TWICE: once to find the longest name and count
|
||||
; them, once to print. A walk costs a read of each directory block and the disk buffer is
|
||||
; already there, where a buffer for the names would be memory this program has to have whether
|
||||
; the directory is large or not.
|
||||
;
|
||||
; ---- Across and then down, rather than down and then across ----
|
||||
;
|
||||
; Real listings go down the columns, so that names next to each other alphabetically are next
|
||||
; to each other on the screen. THAT IS A REASON THAT DEPENDS ON SORTING, and nothing here
|
||||
; sorts: entries come back in the order the directory holds them, which is the order they were
|
||||
; made. With the order arbitrary, down-and-across buys nothing and costs a division to work
|
||||
; out how many rows there are - on a machine that cannot divide.
|
||||
;
|
||||
; So this goes across. If sorting ever arrives, that is the moment to change it, and this
|
||||
; comment is the reason why.
|
||||
|
||||
#Include services.asm
|
||||
|
||||
#Program
|
||||
|
||||
#Base 0x5000
|
||||
|
||||
start:
|
||||
; A directory to list, if one was named. The shell puts the working directory back when a
|
||||
; program exits, so this can walk off somewhere and not tidy up after itself.
|
||||
SETD.0 Given
|
||||
INIB 0d64
|
||||
SWI osArgument
|
||||
SETD.0 Given
|
||||
LDA.0
|
||||
BRA lsHere
|
||||
SWI osChangeDir
|
||||
BNQ lsNoSuchPlace
|
||||
|
||||
lsHere:
|
||||
; ---- Pass one: how wide the widest of them is ----
|
||||
RSTA
|
||||
SETD.0 Longest
|
||||
STA.0
|
||||
SETD.0 Seen
|
||||
STA.0
|
||||
|
||||
SETD.0 Name
|
||||
INIB 0d24
|
||||
SWI osDirFirst
|
||||
BRI lsMeasure
|
||||
|
||||
lsMeasureNext:
|
||||
SETD.0 Name
|
||||
INIB 0d24
|
||||
SWI osDirNext
|
||||
|
||||
lsMeasure:
|
||||
MVQA
|
||||
SETD.0 Kind
|
||||
STA.0
|
||||
INIB 0xFF
|
||||
CCF
|
||||
SUB
|
||||
BRQ lsMeasured
|
||||
|
||||
SETD.0 Seen
|
||||
LDA.0
|
||||
INCA
|
||||
STA.0
|
||||
|
||||
CALL nameLength
|
||||
MVQA
|
||||
|
||||
; A directory wears a separator, which is a character of width like any other.
|
||||
SETD.0 Kind
|
||||
LDB.0
|
||||
DECB
|
||||
BNB lsMeasureWidth
|
||||
INCA
|
||||
|
||||
lsMeasureWidth:
|
||||
SETD.0 Longest
|
||||
LDB.0
|
||||
CCF
|
||||
SUB
|
||||
BRC lsMeasureKeep ; Borrowed, so this one is not the longest.
|
||||
STA.0
|
||||
|
||||
lsMeasureKeep:
|
||||
BRI lsMeasureNext
|
||||
|
||||
lsMeasured:
|
||||
; Nothing at all is said with nothing at all, which is what an empty directory looks like.
|
||||
SETD.0 Seen
|
||||
LDA.0
|
||||
BRA lsDone
|
||||
|
||||
; ---- How many of them fit across ----
|
||||
;
|
||||
; Two spaces between columns, so that names never touch. Worked out by taking the cell width
|
||||
; off the screen width until there is not room for another, because this machine cannot
|
||||
; divide and the answer is never more than a handful.
|
||||
SETD.0 Longest
|
||||
LDA.0
|
||||
INCA
|
||||
INCA
|
||||
SETD.0 Cell
|
||||
STA.0
|
||||
|
||||
INA 0x32
|
||||
SETD.1 Across
|
||||
STA.1 ; What is left of the line, counted down.
|
||||
RSTA
|
||||
SETD.1 Columns
|
||||
STA.1
|
||||
|
||||
lsFitting:
|
||||
SETD.1 Across
|
||||
LDA.1
|
||||
SETD.1 Cell
|
||||
LDB.1
|
||||
CCF
|
||||
SUB
|
||||
BRC lsFitted ; Borrowed, so there is not room for another column.
|
||||
MVQA
|
||||
SETD.1 Across
|
||||
STA.1
|
||||
SETD.1 Columns
|
||||
LDA.1
|
||||
INCA
|
||||
STA.1
|
||||
BRI lsFitting
|
||||
|
||||
lsFitted:
|
||||
; A name wider than the screen still gets a column of its own. One that runs over is better
|
||||
; than one that is not shown.
|
||||
SETD.0 Columns
|
||||
LDA.0
|
||||
BNA lsPrint
|
||||
INIA 0d1
|
||||
STA.0
|
||||
|
||||
lsPrint:
|
||||
RSTA
|
||||
SETD.0 At
|
||||
STA.0
|
||||
|
||||
SETD.0 Name
|
||||
INIB 0d24
|
||||
SWI osDirFirst
|
||||
BRI lsSay
|
||||
|
||||
lsSayNext:
|
||||
SETD.0 Name
|
||||
INIB 0d24
|
||||
SWI osDirNext
|
||||
|
||||
lsSay:
|
||||
MVQA
|
||||
SETD.0 Kind
|
||||
STA.0
|
||||
INIB 0xFF
|
||||
CCF
|
||||
SUB
|
||||
BRQ lsLastLine
|
||||
|
||||
; ---- The cell the last name started, finished now rather than then ----
|
||||
;
|
||||
; Padding AFTER a name puts spaces at the end of every line that does not fill its last
|
||||
; column, and trailing whitespace on a line is the kind of thing that is invisible until
|
||||
; something else reads the output. Padding before the next name instead means the spaces
|
||||
; only ever go between two things, and a line ends on the last character of a name.
|
||||
SETD.0 At
|
||||
LDA.0
|
||||
BRA lsColour ; First on its line, so there is nothing to finish.
|
||||
CALL padOut
|
||||
|
||||
lsColour:
|
||||
; ---- What it is, said in colour ----
|
||||
;
|
||||
; The attribute reaches a terminal as well as the screen now, so this is one mechanism and
|
||||
; not two. A directory in blue and an unfinished save in red; everything else plain, because
|
||||
; whether a file is runnable cannot be known without opening it, and opening every file in a
|
||||
; directory to colour a listing is a price nobody agreed to pay.
|
||||
SETD.0 Kind
|
||||
LDA.0
|
||||
BRA lsPlain
|
||||
DECA
|
||||
BRA lsBlue
|
||||
INIA 0d1 ; An unfinished save, which is worth looking at.
|
||||
BRI lsInk
|
||||
lsBlue:
|
||||
INIA 0d4
|
||||
BRI lsInk
|
||||
lsPlain:
|
||||
RSTA
|
||||
lsInk:
|
||||
OUTA 0x06
|
||||
|
||||
SETD.0 Name
|
||||
SWI osPrintString
|
||||
CALL nameLength
|
||||
MVQA
|
||||
|
||||
SETD.0 Kind
|
||||
LDB.0
|
||||
DECB
|
||||
BNB lsWidth
|
||||
PSHA
|
||||
SETD.0 Slash
|
||||
SWI osPrintString
|
||||
POPA
|
||||
INCA
|
||||
|
||||
lsWidth:
|
||||
; How much of the cell this name took, for whoever finishes it.
|
||||
SETD.0 Used
|
||||
STA.0
|
||||
|
||||
; Back to plain before anything else is written, so that a scheme with paper in it would
|
||||
; not paint the gap between the columns.
|
||||
RSTA
|
||||
OUTA 0x06
|
||||
|
||||
SETD.0 At
|
||||
LDA.0
|
||||
INCA
|
||||
STA.0
|
||||
SETD.0 Columns
|
||||
LDB.0
|
||||
CCF
|
||||
SUB
|
||||
BNQ lsSayNext ; Room for another on this line.
|
||||
|
||||
RSTA
|
||||
SETD.0 At
|
||||
STA.0
|
||||
CALL newLine
|
||||
BRI lsSayNext
|
||||
|
||||
lsLastLine:
|
||||
; A line with something on it needs ending. One that ended on its last column does not, and
|
||||
; a blank line under a listing looks like a listing with a gap in it.
|
||||
SETD.0 At
|
||||
LDA.0
|
||||
BRA lsDone
|
||||
CALL newLine
|
||||
|
||||
lsDone:
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
lsNoSuchPlace:
|
||||
SETD.0 NoSuchPlace
|
||||
SWI osPrintString
|
||||
SETD.0 Given
|
||||
SWI osPrintString
|
||||
CALL newLine
|
||||
INIA 0x01
|
||||
SWI osExit
|
||||
|
||||
; ---- How wide the name in the buffer is ----
|
||||
;
|
||||
; Q COMES BACK THE COUNT, not A. A RET puts A back the way the caller had it, so a subroutine
|
||||
; that answers in A answers with nothing - and this one did, which made every gap between the
|
||||
; columns the same width because the padding was subtracting whatever A happened to hold.
|
||||
; Q is the ALU's output and nothing puts it back, which is why every answer on this machine
|
||||
; comes home in it.
|
||||
nameLength:
|
||||
SETD.0 Name
|
||||
RSTA
|
||||
lengthNext:
|
||||
LDB.0
|
||||
BRB lengthDone
|
||||
INCA
|
||||
INCD.0
|
||||
BRI lengthNext
|
||||
lengthDone:
|
||||
RSTB
|
||||
CCF
|
||||
ADD
|
||||
RET
|
||||
|
||||
; A is how much of the cell the name took. Fills the rest of it with spaces.
|
||||
padOut:
|
||||
; The cell less what the name took, and IN THAT ORDER. Written the other way round first,
|
||||
; which borrowed on every name that was not the longest - so every one of them took the
|
||||
; "wider than its cell" path below and the whole listing came out separated by one space.
|
||||
SETD.0 Cell
|
||||
LDA.0
|
||||
SETD.0 Used
|
||||
LDB.0
|
||||
CCF
|
||||
SUB
|
||||
BRC padDone ; Wider than its cell, so one space keeps the names apart.
|
||||
MVQA
|
||||
BRA padOne
|
||||
padLoop:
|
||||
PSHA
|
||||
SETD.0 Space
|
||||
SWI osPrintString
|
||||
POPA
|
||||
DECA
|
||||
BNA padLoop
|
||||
RET
|
||||
padOne:
|
||||
padDone:
|
||||
SETD.0 Space
|
||||
SWI osPrintString
|
||||
RET
|
||||
|
||||
newLine:
|
||||
SETD.0 NewLine
|
||||
SWI osPrintString
|
||||
RET
|
||||
|
||||
#Data
|
||||
|
||||
#Base 0x3000
|
||||
|
||||
Slash:
|
||||
"/"
|
||||
Space:
|
||||
" "
|
||||
NoSuchPlace:
|
||||
"there is no such directory: "
|
||||
NewLine:
|
||||
0x0A 0x00
|
||||
|
||||
Kind:
|
||||
0x00
|
||||
Longest:
|
||||
0x00
|
||||
Cell:
|
||||
0x00
|
||||
Columns:
|
||||
0x00
|
||||
Across:
|
||||
0x00
|
||||
At:
|
||||
0x00
|
||||
Seen:
|
||||
0x00
|
||||
Used:
|
||||
0x00
|
||||
Name:
|
||||
#Reserve 0d24
|
||||
Given:
|
||||
#Reserve 0d64
|
||||
@@ -693,6 +693,43 @@ compares the images byte for byte. Every field one writes and the other only rea
|
||||
checked there and nowhere else: which entry a thing lands in, which block, what a
|
||||
directory's unused fields hold, the version, the free count.
|
||||
|
||||
### Two Listings:
|
||||
|
||||
`dir` says what is there one line each, with sizes and a tally of the disk. `ls` says the
|
||||
names in columns and nothing else, which is what you want ninety times in a hundred.
|
||||
|
||||
```text
|
||||
> ls
|
||||
Copy.sbx Say.sbx Where.sbx Walk.sbx ls.sbx Lander where.sh
|
||||
```
|
||||
|
||||
They are two programs rather than one with a switch, because they answer different questions
|
||||
and neither answer is a worse version of the other.
|
||||
|
||||
**And `ls` is a program where `dir` is built into the shell.** That is the difference that
|
||||
matters when the disk is the thing being doubted: `dir` is already in memory, and `ls` has to
|
||||
be loaded off the disk it is about to list. The daily driver and the diagnostic, and it is
|
||||
worth having both.
|
||||
|
||||
**Two passes over the directory, and no buffer.** Columns need the longest name before the
|
||||
first line can be printed, which usually means holding every name in memory - twenty four
|
||||
bytes each, against a format that allows 1,024 entries on a disk. So the directory is walked
|
||||
twice instead: once to measure, once to print. That is also the first thing `osDirFirst` made
|
||||
possible which `dir` could not already do.
|
||||
|
||||
**Across, and not down.** Real listings go down the columns so that names next to each other
|
||||
alphabetically are next to each other on the screen - and that is a reason which depends on
|
||||
sorting. Nothing here sorts; entries come back in the order the directory holds them. With the
|
||||
order arbitrary, down-and-across buys nothing and costs a division on a machine that cannot
|
||||
divide. If sorting ever arrives, that is the moment to change it.
|
||||
|
||||
**The width comes from the screen**, port `0x32`, which is 80 while CosmOS is running because
|
||||
CosmOS asks for the wide mode as it starts.
|
||||
|
||||
**Padding goes before a name rather than after it**, so that a line ends on the last character
|
||||
of a name. Trailing spaces on a line are the kind of thing nobody sees until something else
|
||||
reads the output.
|
||||
|
||||
### What A Listing Says About The Disk:
|
||||
|
||||
`dir` ends with what is there and what is left:
|
||||
@@ -840,6 +877,7 @@ from every assembly file in it. Several are old programs written for the bare ma
|
||||
| Keys | The console interrupting rather than being asked. The only one that brings a vector of its own, which is what the version two format exists for. |
|
||||
| Play | Four voices on one clock, which is what music is and one channel cannot be. The timer keeps a tick and every voice keeps its own place in its own track and its own count of how much longer the note it is holding lasts, so the parts move at four different rates and share nothing but the beat. A track is pairs of bytes, what to play and how many ticks it lasts: 1 to 127 is a MIDI note, zero is a rest, and 255 ends it - MIDI stops at 127, so neither of those had to be invented. A note's duration is its whole life and the gate goes down when the count runs out, which means a gap between two notes is written as a rest rather than invented by the player out of some fraction it decided on. Each voice loads an instrument of its own before a note is played - an oboe for the melody, strings under it, a square wave for the bass and a kalimba for the arpeggio - out of the format SoundPatch writes, which the player reads as a count and that many parameter and value pairs and understands nothing else about. Four patches can be up at once because a patch belongs to its channel; Kalimba has an LFO switched off and the other three have one on, and under a device where the LFOs belonged to the whole machine the last patch loaded would have imposed its setting on every part. A voice does not play one long track: it walks an ORDER LIST of its own, a table of sequence addresses, and takes the next one when a sequence runs out. That is where repetition comes from and it costs no notation - the bass plays the same sequence in the first bar and the last, written once. The four columns are how it reads and how a tracker would show it; per voice is how it is stored, because a voice's order cursor is then a pointer it advances by itself. Sequence and patch names are INDICES through two tables, which are the only places an address lives - so a tune read from a file will need its base added to two arrays and nothing else, rather than a loader that walks every sequence looking for addresses to correct. A sequence can also carry commands, which take no time at all: 0x80 plays the rest of that voice on a different patch, which is how the melody's last bar becomes a swell rather than a reed. Nothing keeps the voices together except that their sequences add up to the same length, which is the first thing a compiler should check. The patch each voice starts on is declared rather than assumed, because a voice given no instrument would play on whatever the device woke up with. `Play <file>` reads a tune and plays that; `Play` on its own plays the one built into it. A tune file is "SBTU", a version, the tick in cycles, and offsets to a patch table, a sequence table and four order lists - everything in it an OFFSET from wherever it was put, so loading one is adding the base to two tables and pointing four voices at their order lists. No sequence is walked and nothing inside one is an address, which is what makes a malformed tune something that plays wrongly rather than something that takes the loader with it; the magic is checked first, because the loader follows what the offsets name. The patch each voice starts on is in the header, because a starting instrument is state. The engine that plays it is Libraries/player.asm rather than this program. It spends over ninety nine per cent of its time asleep, because a beat is something to be woken by rather than counted up to. |
|
||||
| Say | Prints whatever it was told, which is the shortest thing that shows osArgument working. |
|
||||
| ls | The listing you read, where dir is the listing you audit: the names in columns, sized to the longest of them, with directories in blue and wearing a separator. Takes a directory to list, and says nothing at all about an empty one. |
|
||||
| Walk | Says what is in the working directory, one line each: what kind of thing it is, its name, and how many blocks. The shortest thing that shows osDirFirst and osDirNext working, and the first program that could see a directory at all. |
|
||||
| Where | Says the path it was loaded from, and with a name after it, the path of that name beside it. The shortest thing that shows osWhereAmI and path.asm working, and the answer follows the program rather than whoever ran it. |
|
||||
| Reboot | Starts the machine again, in 45 bytes. Writes a port rather than asking the system, because a reset has to work when the system does not. |
|
||||
|
||||
@@ -125,7 +125,7 @@ from `make`, not from here.
|
||||
### 1. Recorded output
|
||||
|
||||
`Tests/run.sh` assembles each program named in `Tests/manifest`, runs it, and compares
|
||||
everything it printed against a file in `Tests/expected`. 218 tests, of which 156 run, 35
|
||||
everything it printed against a file in `Tests/expected`. 219 tests, of which 157 run, 35
|
||||
only assemble, 16 are expected to fail to assemble, and 11 boot from ROM with no image
|
||||
given at all.
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ pass.script 20
|
||||
holds.script 87
|
||||
crossed.txt 560
|
||||
36 files, 2 directories
|
||||
47 of 64 entries, 1890 blocks free
|
||||
48 of 64 entries, 1887 blocks free
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -40,7 +40,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> drive 1
|
||||
> dir
|
||||
other.txt 28
|
||||
|
||||
@@ -57,7 +57,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -47,7 +47,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -47,7 +47,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
CosmOS
|
||||
> ls
|
||||
greet.sbx hello.sbx Life.sbx Snake.sbx Keys.sbx
|
||||
Say.sbx Where.sbx Break.sbx Grid.sbx Press.sbx
|
||||
Mode.sbx Flip.sbx Sprite.sbx Depth.sbx [0;34mPackages/[0m
|
||||
Pad.sbx Crash.sbx vars.script blocks.script loops.script
|
||||
tune.sbx Play.sbx notes.txt [0;34mApps/[0m hi.script
|
||||
bad.script plain.script cross.script nonl.script outer.script
|
||||
inner.script loop.script hush.script aloud.script args.script
|
||||
pass.script holds.script
|
||||
finished
|
||||
> cd /Apps
|
||||
/Apps> ls
|
||||
Copy.sbx Say.sbx Where.sbx Walk.sbx ls.sbx Lander where.sh
|
||||
finished
|
||||
/Apps> cd /
|
||||
> ls /Packages/app.Lander
|
||||
Lander.sbx splash.tune
|
||||
finished
|
||||
> mkdir /empty
|
||||
made
|
||||
> cd /empty
|
||||
/empty> ls
|
||||
finished
|
||||
/empty> cd /
|
||||
> ls nowhere
|
||||
there is no such directory: nowhere
|
||||
finished
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
[exit 0]
|
||||
@@ -133,7 +133,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -52,7 +52,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -40,7 +40,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> load
|
||||
load what?
|
||||
> load nosuch.sbx
|
||||
|
||||
@@ -38,7 +38,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> load Say.sbx
|
||||
loaded, starting at 5000
|
||||
> run the disk took its time
|
||||
|
||||
@@ -38,7 +38,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> drive 1
|
||||
> dir
|
||||
f1.txt 1500
|
||||
|
||||
@@ -47,7 +47,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
35 files, 2 directories
|
||||
46 of 64 entries, 1893 blocks free
|
||||
47 of 64 entries, 1890 blocks free
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -44,6 +44,7 @@ f Copy.sbx 7
|
||||
f Say.sbx 1
|
||||
f Where.sbx 4
|
||||
f Walk.sbx 1
|
||||
f ls.sbx 3
|
||||
f Lander 4
|
||||
f where.sh 3
|
||||
finished
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
ls
|
||||
cd /Apps
|
||||
ls
|
||||
cd /
|
||||
ls /Packages/app.Lander
|
||||
mkdir /empty
|
||||
cd /empty
|
||||
ls
|
||||
cd /
|
||||
ls nowhere
|
||||
exit
|
||||
@@ -283,6 +283,12 @@ python3 -c "open('twoblocks.txt','w').write('the second disk, at length. ' * 20)
|
||||
# Walk goes in /Apps and nowhere else, so that it is reachable from any directory - which is
|
||||
# what lets the same program list the root and then list /Apps.
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/Walk.sbx" /Apps/Walk.sbx >/dev/null
|
||||
# ls is the listing you read, where dir is the listing you audit. It is a PROGRAM and dir is
|
||||
# built in, which is the difference that matters when the disk is what you are doubting: dir
|
||||
# is already in memory, and this has to be loaded off the disk it is about to list.
|
||||
"$ROOT/Assembler" -I "$ROOT/Programs/CosmOS/Source" \
|
||||
"$ROOT/Programs/CosmOS/Apps/ls.asm" -o "$WORK/ls.sbx" >/dev/null
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/ls.sbx" /Apps/ls.sbx >/dev/null
|
||||
# And the launcher for Lunar Porter, under the bare name somebody types. Put here rather than
|
||||
# beside the game above, because /Apps is not made until now.
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$ROOT/Programs/CosmOS/Launchers/Lander" /Apps/Lander >/dev/null
|
||||
|
||||
@@ -1051,6 +1051,23 @@ cosmosWalk | CosmOS/Source/cosmos.asm | run | cosmosWal
|
||||
# when it differs from the free total, so the first listing is silent about it and the second
|
||||
# is not - a line that appears only when something is wrong is a line somebody reads.
|
||||
cosmosSpace | CosmOS/Source/cosmos.asm | run | cosmosSpace.in | 200000000 | disks/cosmos.img+disks/holes.img
|
||||
# ---- A listing laid out to be read ----
|
||||
#
|
||||
# dir says what is there one line each with sizes and a tally; ls says the names in columns.
|
||||
# Two programs rather than one with a switch, because they answer different questions - and ls
|
||||
# is a PROGRAM where dir is built in, which is the difference that matters when the disk is
|
||||
# what you are doubting.
|
||||
#
|
||||
# TWO PASSES AND NO BUFFER. Columns need the longest name before the first line can be
|
||||
# printed, which usually means holding every name in memory - twenty four bytes each against a
|
||||
# format that allows 1,024 entries. So the directory is walked twice instead, which is the
|
||||
# first thing osDirFirst made possible that dir could not already do.
|
||||
#
|
||||
# Five things in one session: the root, where the directories are coloured and wear a
|
||||
# separator; a subdirectory; a directory named as an argument, which changes there and lets
|
||||
# the shell put it back; an EMPTY one, which says nothing at all rather than saying so; and a
|
||||
# name that is not a directory, which says so and fails.
|
||||
cosmosLs | CosmOS/Source/cosmos.asm | run | cosmosLs.in | 200000000 | disks/cosmos.img
|
||||
# ---- Starting itself ----
|
||||
#
|
||||
# /System/Boot/startup.sh runs before anybody can type. This one is also the check on #quiet
|
||||
|
||||
Reference in New Issue
Block a user