; Loads a program off a disk and runs it. ; ; Everything this needs already existed: the filesystem reads the file, the controller ; writes Program Memory, and BRD jumps to an address worked out at run time. The only new ; part is the sixteen bytes on the front of a loadable program that say where it goes. ; ; Nothing relocates anything. The program is put exactly where its header asks, and that ; has to be where it was assembled for, or every branch inside it points somewhere wrong. ; This loader therefore keeps out of the way: its own code and data sit above the ; addresses the loaded program claims, which is an arrangement rather than a mechanism. ; ; Correct output is: ; loader ; loaded off a disk, with a string and a loop of its own #Include print.asm #Include sbfs.asm #Program ; print.asm branches here at the top of the Program Segment, so this is where the machine ; arrives whether or not the Boot Vector is obeyed. Naming it in the Vector Segment as ; well says plainly where the program begins. start: SETD.0 LoaderName CALL printString CALL lineFeed CALL sbfsMount BNQ loaderNoDisk SETD.0 ProgramName CALL sbfsFind BNQ loaderMissing SETD.1 Staging CALL sbfsRead BNQ loaderUnreadable ; "SBEX", or it is not a program at all. Loading a text file would otherwise put ; nonsense into Program Memory and jump into it. SETD.0 Staging SETD.2 ExecMagic INIA 0d4 SETD.1 LoaderCount STA.1 loaderMagicLoop: LDA.0 LDB.2 XOR BNQ loaderNotProgram INCD.0 INCD.2 LDA.1 DECA STA.1 BNA loaderMagicLoop SETD.0 Staging DPUP.0 0d04 LDA.0 INIB 0d1 XOR BNQ loaderWrongVersion ; The code first. Source is the bytes just past the header; destination is wherever the ; header says the code lives. INIA 0d1 OUTA 0xE0 ; SourceBank: Data Memory, where the file was read to. SETD.0 Staging DPUP.0 0d16 PSHD.0 POPA POPB OUTB 0xE1 OUTA 0xE2 RSTA OUTA 0xE3 ; DestBank: Program Memory. ; Where the code goes. Read and written out a byte at a time rather than through a ; subroutine, because a subroutine could not hand the two bytes back: CALL preserves ; A and B along with the first three Data Pointers, so anything a routine puts in them ; is undone by its own return. SETD.0 Staging DPUP.0 0d06 LDA.0 OUTA 0xE4 INCD.0 LDA.0 OUTA 0xE5 ; How much of it there is. SETD.0 Staging 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 Staging DPUP.0 0d12 LDA.0 OUTA 0xE4 INCD.0 LDA.0 OUTA 0xE5 SETD.0 Staging DPUP.0 0d14 LDA.0 OUTA 0xE6 INCD.0 LDA.0 OUTA 0xE7 INIA 0x01 OUTA 0xE8 ; Blit. ; And go. The entry address is a number until BRD makes it a place. DP3 is built from ; the two bytes by hand, since it is the pointer nothing puts back. SETD.0 Staging DPUP.0 0d08 LDA.0 INCD.0 LDB.0 PSHA PSHB POPD.3 BRD.3 loaderNoDisk: SETD.0 NoDisk BRI loaderComplain loaderMissing: SETD.0 NotThere BRI loaderComplain loaderUnreadable: SETD.0 Unreadable BRI loaderComplain loaderNotProgram: SETD.0 NotProgram BRI loaderComplain loaderWrongVersion: SETD.0 WrongVersion loaderComplain: CALL printString CALL lineFeed HALT #Data ExecMagic: "SBEX" LoaderName: "loader" ProgramName: "hello.sbx" NoDisk: "no disk" NotThere: "no such program" Unreadable: "could not read it" NotProgram: "not a program" WrongVersion: "a version I do not know" LoaderCount: 0x00 Staging: #Reserve 0d512 #Vectors Boot start