; cosmos.asm ; CosmOS, and the shell that is most of it. ; ; The machine boots into this. It registers what the hardware brought, mounts whatever ; disk is attached, and then reads lines and does what they say until there is no more ; typing to be had. ; ; ---- Where things live ---- ; ; The system keeps to the bottom of both memories, and everything above is for whatever ; it is running: ; ; Program Memory 0x0000 - 0x1FFF the system ; 0x2000 - a loaded program's code ; Data Memory 0x0000 - 0x0FFF the system ; 0x1000 - a loaded program's data ; ; Nothing enforces that. Nothing can: the fence guards a range, and this is a convention ; about which range belongs to whom rather than a rule about what may be touched. The ; assembler prints both segment sizes, and they are what to watch. ; ; A program is staged at 0x8000 while it is being loaded, which is inside the region a ; loaded program will own. That is safe because nothing is running during a load, and it ; is where a big program can be read without the system reserving the room for good. ; ; ---- What it can do ---- ; ; dir List what is on the disk. ; load Read a program off the disk and put it where it asks to go. ; run Start the program that was loaded. ; help Say what these are. ; exit Stop. ; ; dump is next. The dispatch below is a chain of comparisons, which is the right shape for ; five commands and the wrong shape for twenty; when it grows, the table that ; dispatchTest.asm demonstrates is where it should go. ; ; Written by Anachronaut #Include console.asm #Include text.asm #Include sbfs.asm #Include services.asm #Program boot: SETD.0 Banner CALL printString CALL newLine ; Find out whether there is a filesystem to talk to. Doing this once at boot rather than ; once per command means a disk swapped underneath us is not noticed, which is honest ; for a machine whose disk is a file named on the command line. CALL sbfsMount SETD.0 DiskReady BNQ bootNoDisk INIA 0x01 STA.0 BRI prompt bootNoDisk: RSTA STA.0 SETD.0 NoDisk CALL printString CALL newLine ; ---- The loop ---- prompt: SETD.0 PromptText CALL printString SETD.0 CommandLine INIB 0d63 CALL readLine ; Running out of typing is how this ends. It is not the same as an empty line, which is ; just somebody pressing return, and the shell should sit there when that happens. SETD.0 ConsoleEndOfInput LDA.0 BNA quitRanOut SETD.0 CommandLine CALL textSplit ; An empty line asks for nothing. SETD.0 CommandLine LDA.0 BRA prompt SETD.0 CommandLine SETD.1 DirName CALL textSame BRQ doDir SETD.0 CommandLine SETD.1 LoadName CALL textSame BRQ doLoad SETD.0 CommandLine SETD.1 RunName CALL textSame BRQ doRun SETD.0 CommandLine SETD.1 DumpName CALL textSame BRQ doDump SETD.0 CommandLine SETD.1 DeleteName CALL textSame BRQ doDelete SETD.0 CommandLine SETD.1 RenameName CALL textSame BRQ doRename SETD.0 CommandLine SETD.1 HelpName CALL textSame BRQ doHelp SETD.0 CommandLine SETD.1 ExitName CALL textSame BRQ quit ; Nothing matched. Saying which word was not understood is worth the four instructions: ; it tells somebody who mistyped what they actually typed. SETD.0 Unknown CALL printString SETD.0 CommandLine CALL printString CALL newLine BRI prompt ; Running out of console leaves the cursor part way along a line, because there was no ; return at the end to move it on. Somebody who typed "exit" has already pressed one, and ; a second would only leave a blank line behind. quitRanOut: CALL newLine quit: SETD.0 Farewell CALL printString CALL newLine HALT ; ---- dir ---- ; ; Walks the directory and prints what is in it. A free entry in the middle of a directory ; is stepped over by the walk, so what comes out is the files and nothing else. doDir: SETD.0 DiskReady LDA.0 BRA dirNoDisk RSTA SETD.0 DirSeen STA.0 CALL sbfsFirst BRI dirCheck dirStep: CALL sbfsNext dirCheck: BNQ dirDone SETD.0 DirSeen LDA.0 INCA STA.0 SETD.0 SbfsName CALL printString SETD.0 SbfsName CALL nameWidth MVQA CALL printSpaces ; A file's length is its block count times 256 plus its tail, which is the block count ; in the high byte and the tail in the low one. Nothing has to multiply anything. SETD.0 SbfsFileBlocks DPUP.0 0d01 LDA.0 SETD.1 DirSize STA.1 SETD.0 SbfsFileTail LDA.0 SETD.1 DirSize INCD.1 STA.1 SETD.0 DirSize CALL printWordDecimal CALL newLine BRI dirStep dirDone: SETD.0 DirSeen LDA.0 CALL printByteDecimal ; One file is not one files. Cheap to get right and it reads as carelessness otherwise. SETD.0 DirSeen LDA.0 DECA BRA dirOne SETD.0 FilesText BRI dirCount dirOne: SETD.0 FileText dirCount: CALL printString CALL newLine BRI prompt dirNoDisk: SETD.0 NoDisk CALL printString CALL newLine BRI prompt ; DP0 names a string. Q is how many spaces pad it out to twenty four columns. A name ; already that long gets one space, so that it cannot run into the number after it. nameWidth: INIA 0d24 SETD.1 WidthLeft STA.1 widthLoop: LDA.0 BRA widthDone SETD.1 WidthLeft LDA.1 DECA STA.1 BRA widthFloor INCD.0 BRI widthLoop widthFloor: INIA 0d1 SETD.1 WidthLeft STA.1 widthDone: SETD.1 WidthLeft LDA.1 RSTB CCF ADD RET ; ---- load ---- ; ; Reads a program off the disk and puts it where its header asks to go. Nothing relocates ; anything: the addresses in the header are the ones the program was built for, and it ; would not work anywhere else. ; ; The whole file is staged at 0x8000 first and then blitted into place, because where the ; pieces belong is not known until the header has been read, and the header is in the file. doLoad: SETD.0 DiskReady LDA.0 BRA loadNoDisk SETD.1 TextRest LDD.0.1 LDA.0 BRA loadNothingNamed CALL sbfsFind BNQ loadMissing SETD.1 0x80 0x00 CALL sbfsRead BNQ loadUnreadable ; "SBEX", or this is not a program. Without this, loading a text file would put nonsense ; into Program Memory and then jump into the middle of it. SETD.0 0x80 0x00 SETD.2 ExecMagic INIA 0d4 SETD.1 LoadCount STA.1 loadMagicLoop: LDA.0 LDB.2 XOR BNQ loadNotProgram INCD.0 INCD.2 LDA.1 DECA STA.1 BNA loadMagicLoop ; Version one is code and data. Version two also brings vectors, which is a thing a ; loader has to know how to do rather than a detail it can skip: a program whose handlers ; were quietly dropped would run and then go wrong somewhere with nothing to connect it ; back to here. Anything else is refused. SETD.0 0x80 0x00 DPUP.0 0d04 LDA.0 SETD.1 LoadVersion STA.1 INIB 0d1 XOR BRQ loadVersionKnown SETD.1 LoadVersion LDA.1 INIB 0d2 XOR BNQ loadWrongVersion loadVersionKnown: ; The code. It comes from the staging area just past the sixteen byte header, and goes ; wherever the header says, in Program Memory, which the instruction set cannot write ; and the controller can. INIA 0d1 OUTA 0xE0 ; SourceBank: Data Memory, where the file was staged. INIA 0x80 OUTA 0xE1 INIA 0d16 OUTA 0xE2 ; 0x8010, the first byte after the header. RSTA OUTA 0xE3 ; DestBank: Program Memory. SETD.0 0x80 0x00 DPUP.0 0d06 LDA.0 OUTA 0xE4 INCD.0 LDA.0 OUTA 0xE5 SETD.0 0x80 0x00 DPUP.0 0d10 LDA.0 OUTA 0xE6 INCD.0 LDA.0 OUTA 0xE7 INIA 0x01 OUTA 0xE8 ; Blit. ; Then the data. A blit leaves its addresses past whatever it touched, so the source is ; already sitting on the first byte of the data and only the destination changes. INIA 0d1 OUTA 0xE3 ; DestBank: Data Memory. SETD.0 0x80 0x00 DPUP.0 0d12 LDA.0 OUTA 0xE4 INCD.0 LDA.0 OUTA 0xE5 SETD.0 0x80 0x00 DPUP.0 0d14 LDA.0 OUTA 0xE6 INCD.0 LDA.0 OUTA 0xE7 INIA 0x01 OUTA 0xE8 ; Blit. ; ---- The vectors it brought ---- ; ; Kept here rather than installed. A vector points into a program, so it has no business ; being in the table while that program is only loaded and not running: run puts them in ; and exit takes them out again, so the window they are live in is exactly the run. ; Keeping our own copy is also what lets a program be run more than once, since the ; staging area it came in on is fair game for the program's own use. ; ; Where to read them from is not worked out. The data blit left the controller's source ; address on the first byte after the data, which is where they are, so it is read back. SETD.0 VectorSource INA 0xE1 STA.0 INCD.0 INA 0xE2 STA.0 SETD.0 0x80 0x00 DPUP.0 0d05 LDA.0 SETD.1 LoadedVectorCount STA.1 BRA loadVectorsCopied ; More than there is room for is refused rather than half taken. Half a program's ; handlers is not a smaller version of that program. INIB 0d17 CCF SUB BNC loadTooManyVectors SETD.0 VectorSource LDD.2.0 ; DP2 walks the entries where they are staged. SETD.3 LoadedVectors ; DP3 walks our own copy of them. SETD.1 LoadedVectorCount LDA.1 SETD.1 VectorsLeft STA.1 loadVectorCopy: ; Four bytes: where it goes, then what goes there. The two bytes for what was there ; before are left alone until something is actually put in. LDA.2 STA.3 INCD.2 INCD.3 LDA.2 STA.3 INCD.2 INCD.3 LDA.2 STA.3 INCD.2 INCD.3 LDA.2 STA.3 INCD.2 INCD.3 INCD.3 INCD.3 SETD.1 VectorsLeft LDA.1 DECA STA.1 BNA loadVectorCopy loadVectorsCopied: ; Where it starts. Written out by hand rather than through a routine, because a routine ; could not hand two bytes back: CALL puts A, B and the first three pointers back the ; way it found them. SETD.0 0x80 0x00 DPUP.0 0d08 LDA.0 SETD.1 LoadedEntry STA.1 INCD.0 INCD.1 LDA.0 STA.1 INIA 0x01 SETD.0 LoadedOk STA.0 SETD.0 LoadedText CALL printString SETD.0 LoadedEntry CALL printWordHex CALL newLine BRI prompt loadNoDisk: SETD.0 NoDisk BRI loadComplain loadNothingNamed: SETD.0 LoadWhat BRI loadComplain loadTooManyVectors: SETD.0 TooManyVectors BRI loadComplain loadMissing: SETD.0 NoSuchFile BRI loadComplain loadUnreadable: SETD.0 Unreadable BRI loadComplain loadNotProgram: SETD.0 NotProgram BRI loadComplain loadWrongVersion: SETD.0 WrongVersion loadComplain: CALL printString CALL newLine BRI prompt ; ---- delete and rename ---- ; ; The two things a disk needs that reading and writing do not provide, and the two that ; anything editing a document will want from the shell as well as from a program. Deleting ; frees an entry and its blocks; renaming changes twenty two bytes and moves nothing. doDelete: SETD.0 DiskReady LDA.0 BRA fileNoDisk SETD.1 TextRest LDD.0.1 LDA.0 BRA deleteWhat CALL sbfsDelete BNQ deleteFailed SETD.0 Deleted CALL printString CALL newLine BRI prompt deleteWhat: SETD.0 DeleteWhat BRI fileComplain deleteFailed: SETD.0 NoSuchFile BRI fileComplain doRename: SETD.0 DiskReady LDA.0 BRA fileNoDisk SETD.1 TextRest LDD.0.1 LDA.0 BRA renameWhat ; Two names, so the rest of the line is split again. textSplit writes a zero over the ; space it cuts at, so what was one string becomes two without anything being copied. SETD.1 TextRest LDD.0.1 SETD.1 RenameFrom STD.0.1 CALL textSplit SETD.1 TextRest LDD.1.1 LDA.1 BRA renameWhat ; Only one name was given, and this needs both. SETD.2 RenameFrom LDD.0.2 CALL sbfsRename BNQ renameFailed SETD.0 Renamed CALL printString CALL newLine BRI prompt renameWhat: SETD.0 RenameWhat BRI fileComplain renameFailed: ; Either there is no such file or the new name is already taken. Which of the two is not ; worth another message: both mean the disk does not have room for that name to move. SETD.0 RenameNo BRI fileComplain fileNoDisk: SETD.0 NoDisk fileComplain: CALL printString CALL newLine BRI prompt ; ---- run ---- ; ; Hands the machine to whatever was loaded. Where the Stack is now is written down first, ; because the program is not going to unwind anything it pushes and the exit handler has ; to be able to put the Stack back. doRun: SETD.0 LoadedOk LDA.0 BRA runNothing MVSD.0 SETD.1 SystemStack STD.0.1 ; Whatever followed the word "run" is kept where the program can ask for it. Copied ; rather than pointed at, because what it is pointing at is the line the shell typed ; into, and a program is entitled to outlive the shell's opinion of that. SETD.1 TextRest LDD.0.1 SETD.1 RunArgument INIB 0d64 CALL copyText CALL installVectors ; The entry address is a number until BRD makes it a place. DP3 is the one to build it ; in, because it is the pointer nothing puts back. SETD.1 LoadedEntry LDD.3.1 BRD.3 runNothing: SETD.0 NothingLoaded CALL printString CALL newLine BRI prompt ; DP0 is a string, DP1 is where it should go, and B is how much room there is counting ; the zero on the end. What does not fit is left behind, and what is written is a string ; either way. copyText: BRB copyTextDone ; No room at all, so nothing is written, not even the zero. copyTextLoop: DECB BRB copyTextEnd ; Only room for the terminator now. LDA.0 STA.1 BRA copyTextDone INCD.0 INCD.1 BRI copyTextLoop copyTextEnd: RSTA STA.1 copyTextDone: RET ; ---- Putting a program's vectors in, and taking them out again ---- ; ; The vector table lives in Program Memory, which no instruction can write, so both of ; these go through the memory controller. Port 0xE9 reads a byte from the source and writes ; a byte to the destination, stepping the address on either way, so a two byte entry is two ; reads or two writes and no address arithmetic in between. ; ; What was in the slot is kept before anything replaces it, and put back afterwards, rather ; than the slot being cleared. Clearing would be wrong wherever a program has installed a ; handler over one the system was already using: the program is allowed to do that, and ; when it goes, what it covered up has to come back rather than becoming a hole. installVectors: SETD.0 LoadedVectorCount LDA.0 BRA installDone SETD.1 VectorsLeft STA.1 SETD.3 LoadedVectors installOne: ; DP3 walks one six byte entry: where it goes, what goes there, and room for what was ; there before. Reading and writing the same slot, so the controller is pointed at it ; from both ends at once and the address is only worked out once. RSTA OUTA 0xE0 ; SourceBank: Program Memory. OUTA 0xE3 ; DestBank: the same. LDA.3 OUTA 0xE1 OUTA 0xE4 INCD.3 LDA.3 OUTA 0xE2 OUTA 0xE5 INCD.3 ; On the handler. ; What is there now, before anything replaces it. INA 0xE9 PSHA INA 0xE9 PSHA ; And the handler in its place. LDA.3 OUTA 0xE9 INCD.3 LDA.3 OUTA 0xE9 INCD.3 ; On the two bytes kept for what was there before. ; The Stack gives them back in the reverse of the order they went on, so the low byte ; arrives first and is written to the second of the two. Getting this the natural way ; round instead put the low byte where the high one goes and the high byte over the ; handler, which the first run of a program survives - the table is already written by ; then - and the second run does not. POPA INCD.3 STA.3 DECD.3 POPA STA.3 INCD.3 INCD.3 SETD.1 VectorsLeft LDA.1 DECA STA.1 BNA installOne installDone: RET removeVectors: SETD.0 LoadedVectorCount LDA.0 BRA removeDone SETD.1 VectorsLeft STA.1 SETD.3 LoadedVectors removeOne: RSTA OUTA 0xE3 ; DestBank: Program Memory. LDA.3 OUTA 0xE4 INCD.3 LDA.3 OUTA 0xE5 INCD.3 INCD.3 INCD.3 ; Past the handler, to what was underneath it. LDA.3 OUTA 0xE9 INCD.3 LDA.3 OUTA 0xE9 INCD.3 SETD.1 VectorsLeft LDA.1 DECA STA.1 BNA removeOne removeDone: RET ; ---- The services ---- ; ; These are what a loaded program is allowed to ask for. The names and their numbers come ; from services.asm, which the programs include as well, so neither side writes a number ; down and the two cannot disagree about them. ; ; A handler arrives with the caller's registers exactly as they were: an interrupt frame ; is pushed, not cleared. So the pointer a program put in DP0 is still there to be used. ; The disk finishing, acknowledged and ignored. ; ; The system drives the disk by asking its status port and waiting, so it has no use for ; the line. But the disk raises one after every operation whether anybody wants it or not, ; and a line goes on waiting while the Interrupt Flag is down rather than being lost. The ; shell keeps the flag down, so the line from the last disk read was still standing when ; the first program to enable interrupts ran, and it arrived there - a fault, in a program ; that had never heard of the disk, blamed on the innocent instruction that let it through. ; ; Answering a line is what takes it down, so this is one instruction and that is the point. diskDone: RETI handlePrintString: CALL printString RETI handleReadLine: CALL readLine RETI ; What the program was asked to work on. DP0 says where to put it and B how much room ; there is, counting the zero on the end, which is the same bargain readLine offers. ; ; Being asked for rather than left at an agreed address is deliberate. The two sides of ; this already have to agree on a vector number and nothing else, and that number is ; written down once in services.asm; an address would be a second thing to agree about, in ; a memory map that is a convention rather than anything enforced. handleArgument: PSHD.0 POPD.1 SETD.0 RunArgument CALL copyText RETI ; Giving the machine back. This is the one place MVDS earns its keep. The program's Stack, ; and the frame this very interrupt arrived on, are both abandoned where they lie, because ; nothing is going to return through either of them. ; ; Which is exactly why this cannot RETI. Its return address is on the Stack it just walked ; away from, so it branches to the prompt instead. handleExit: SETD.1 SystemStack LDD.0.1 MVDS.0 ; Whatever the program put in the vector table comes out again. A vector points into the ; program that supplied it, and the program is gone, so anything left installed would aim ; an interrupt at whatever those addresses hold next. CALL removeVectors ; The console goes back to how the shell wants it, whatever the program left it in: line ; mode, and not interrupting. A program that wanted either is expected to put it back ; itself, but one that stopped early, or forgot, would otherwise hand back a shell with ; no echo and no backspace, or one being interrupted about keys it is reading anyway. ; Zero is both bits, so this undoes everything the control port can be asked for, and ; asking for what is already the case costs a byte out of a port and does nothing. That ; is the right price for not having to know. RSTA OUTA 0x02 SETD.0 Finished CALL printString CALL newLine BRI prompt ; ---- dump ---- ; ; dump Sixty four more bytes, carrying on from the last one. ; dump From the start of that bank. ; dump From there. ; ; is program, data, or a bank number in hexadecimal. That the CPU cannot read ; Program Memory and this can is the whole point: the instruction set has no way to look ; at itself, and the controller does, so a monitor is possible at all only through it. doDump: SETD.1 TextRest LDD.0.1 LDA.0 BRA dumpGo ; Nothing said, so carry on from where the last one stopped. ; Which bank. The two that always exist have names, because typing "program" is what ; somebody means and 0 is what the machine calls it. CALL textSplit SETD.1 ProgramWord CALL textSame BRQ dumpBankProgram SETD.1 DataWord CALL textSame BRQ dumpBankData CALL textHexWord BNQ dumpBadWhere SETD.0 TextValue INCD.0 LDA.0 BRI dumpSetBank dumpBankProgram: RSTA BRI dumpSetBank dumpBankData: INIA 0d1 dumpSetBank: SETD.0 DumpBank STA.0 ; And where in it. Naming a bank without an address means the start of it, which is the ; only answer that does not depend on what was asked for last time. RSTA SETD.0 DumpAt STA.0 INCD.0 STA.0 SETD.1 TextRest LDD.0.1 LDA.0 BRA dumpCheckBank CALL textHexWord BNQ dumpBadWhere SETD.0 TextValue LDA.0 SETD.1 DumpAt STA.1 SETD.0 TextValue INCD.0 LDA.0 SETD.1 DumpAt INCD.1 STA.1 dumpCheckBank: ; Is there such a bank? Asking the controller for a bank that is not there is refused, ; and a refusal nobody catches stops the machine, which is a poor answer to a typing ; mistake. The bank table says what exists, and it lives in bank 2. ; ; Bank n's record starts at n times eight. A and B are a shift register sixteen bits ; wide, so putting the number in the low half and rotating left three times multiplies ; it by eight without anything falling off the top: the most it can reach is 2040. RSTA SETD.0 DumpBank LDB.0 SHL SHL SHL SETD.0 DumpRecord STA.0 INCD.0 STB.0 INIA 0d2 OUTA 0xE0 ; SourceBank: the controller's own memory. SETD.0 DumpRecord LDA.0 OUTA 0xE1 INCD.0 LDA.0 OUTA 0xE2 INA 0xE9 ; The flags byte of that bank's record. INIB 0x01 AND BRQ dumpNoBank ; The present bit is down, so nothing is there. dumpGo: INIA 0d4 SETD.0 DumpRows STA.0 dumpRow: SETD.0 DumpAt CALL printWordHex INIA 0d2 CALL printSpaces ; Point the controller at the row. Reading the Data port takes a byte and steps the ; source on, so the whole row is one instruction repeated. SETD.0 DumpBank LDA.0 OUTA 0xE0 SETD.0 DumpAt LDA.0 OUTA 0xE1 INCD.0 LDA.0 OUTA 0xE2 ; Sixteen bytes, kept as they go past so that they can be shown twice. INIA 0d16 SETD.0 DumpCount STA.0 SETD.1 DumpBytes dumpByte: INA 0xE9 STA.1 CALL printByteHex INIA 0x20 OUTA 0x00 INCD.1 SETD.0 DumpCount LDA.0 DECA STA.0 BNA dumpByte ; The same sixteen again, as characters. Anything that is not printable shows as a dot, ; because a control character sent to the console would move the cursor and ruin the ; shape of the dump. INIA 0x20 OUTA 0x00 INIA 0d16 SETD.0 DumpCount STA.0 SETD.1 DumpBytes dumpChar: LDA.1 INIB 0x20 CCF SUB BRC dumpDot ; Below a space. INIB 0x7F CCF SUB BNC dumpDot ; Delete, or above it. OUTA 0x00 BRI dumpCharNext dumpDot: INIA 0x2E OUTA 0x00 dumpCharNext: INCD.1 SETD.0 DumpCount LDA.0 DECA STA.0 BNA dumpChar CALL newLine ; Sixteen further along, carrying into the high byte if the low one wrapped. SETD.0 DumpAt INCD.0 LDA.0 INIB 0d16 CCF ADD STQ.0 BNC dumpRowNext SETD.0 DumpAt LDA.0 INCA STA.0 dumpRowNext: SETD.0 DumpRows LDA.0 DECA STA.0 BNA dumpRow BRI prompt dumpBadWhere: SETD.0 DumpUsage CALL printString CALL newLine BRI prompt dumpNoBank: SETD.0 NoSuchBank CALL printString CALL newLine BRI prompt ; ---- help ---- doHelp: SETD.0 HelpText CALL printString CALL newLine SETD.0 HelpMoreText CALL printString CALL newLine BRI prompt #Data Banner: "CosmOS" PromptText: "> " NoDisk: "no filesystem on the disk" Unknown: "I do not know: " Farewell: "halted" FilesText: " files" FileText: " file" ; Two strings rather than one, because a string literal stops at 255 characters and each ; one carries its own zero byte, so they are printed in turn rather than joined. HelpText: "dir list what is on the disk load read a program off the disk run [words] start what was loaded, and tell it those words delete take it off the disk rename call it something else" HelpMoreText: "dump sixty four bytes of memory, and again for more dump
help this exit stop" DumpUsage: "dump
" NoSuchBank: "there is no such bank" ProgramWord: "program" DataWord: "data" DumpName: "dump" ExecMagic: "SBEX" LoadWhat: "load what?" NoSuchFile: "no such file" Deleted: "gone" Renamed: "renamed" DeleteWhat: "delete what?" RenameWhat: "rename what to what?" RenameNo: "there is no such file, or that name is taken" TooManyVectors: "that program wants more vectors than there is room for" Unreadable: "could not read it" NotProgram: "not a program" WrongVersion: "a version I do not know" LoadedText: "loaded, starting at " NothingLoaded: "nothing is loaded" Finished: "finished" DirName: "dir" LoadName: "load" RunName: "run" DeleteName: "delete" RenameName: "rename" HelpName: "help" ExitName: "exit" DiskReady: 0x00 LoadedOk: 0x00 LoadedEntry: 0x00 0x00 LoadCount: 0x00 LoadVersion: 0x00 ; Where the first of rename's two names is, kept while the second is picked out of the ; line, since finding that needs the pointers for itself. RenameFrom: 0x00 0x00 ; What followed "run", kept for the program to ask for. RunArgument: #Reserve 0d64 ; ---- The vectors a loaded program brought with it ---- ; ; Six bytes each: where it goes, what goes there, and what was there before. The last two ; are filled in when the program runs and read back when it exits, so what a program covers ; up comes back rather than becoming a hole. ; ; Sixteen is a limit rather than a considered number. It is far more than anything written ; so far wants, and a program asking for more is refused at load rather than having some of ; its handlers installed and the rest dropped. VectorSource: 0x00 0x00 VectorsLeft: 0x00 LoadedVectorCount: 0x00 LoadedVectors: #Reserve 0d96 ; Where the monitor is looking, so that a bare 'dump' can carry on from it. DumpBank: 0x00 DumpAt: 0x00 0x00 DumpRows: 0x00 DumpCount: 0x00 DumpRecord: 0x00 0x00 DumpBytes: #Reserve 0d16 ; Where the system's Stack was when it handed the machine to a program. Kept below the ; region a program owns, so that a program has to go looking to break it. SystemStack: 0x00 0x00 DirSeen: 0x00 DirSize: 0x00 0x00 WidthLeft: 0x00 ; Sixty three characters and the zero byte that ends them. CommandLine: #Reserve 0d64 #Vectors Boot boot osPrintString handlePrintString osReadLine handleReadLine osExit handleExit osArgument handleArgument Device 0x20 diskDone