        Title   SSB boot program to load SDOS
        NAME    SDOS BOOT
*       WITH    WI=107,DE=51
*
*       BOOT.SYS program for SDOS 1.0 or SDOS 1.1 6800/6809
*       Operates with SSB Chieftain, don't care what the physical
*       device is because the physical I/O is handled in the ROM.
*       WARNING: THIS BOOT DOES NOT WORK IF OVERLAYED BY LOADED RECORDS!
*       (Isn't that obvious?)
*
*
*       DISK PARAMETERS
*
NBPS            EQU     128            NUMBER OF BYTES PER SECTOR
SECTOR0OFFSET   EQU     $100
NSPT            EQU     26
*
*               READ PARAMETER BLOCK
*
                ORG     0
FDCYL           RMB     1              CYLINDER
FDTRACK         RMB     1              TRACK
FDSECTOR        RMB     1              SECTOR
FDSECTORBASE    RMB     2              WHERE TO PUT IT
FDDSKCAPABILITY RMB     1              CAPABILITY OF THE DISKETTE
FDDENSITY       RMB     1              DENSITY OF THIS SECTOR
*
*       ROM ENTRY POINTS, RESTORE DONE IN ROM BY RESTART
*
PRINTASCIIZ     EQU     $F813          MSG PRINTER
ROMREADSECTOR   EQU     $FFEE          READ SECTOR ROUTINE IN THE ROM
READSECTOR0     EQU     $F300          READ PARAMETER BLOCK
NMIJMP          EQU     $F3FD          JMP TO NMI ENTRY IN DEBUGGER
        PAGE    RAM & EQU'S
BOOT:NSPC       EQU     $11
BOOT:MAPALG     EQU     $16
BOOT:SIZE       EQU     $40
LOAD:TYPE0      EQU     0
LOAD:TYPE1      EQU     2
LOAD:TYPE2      EQU     2
LOAD:TYPE3      EQU     3
        ORG     0
TEMPX           RMB     2
CNT             RMB     2
SOURCE          RMB     2
DEST            RMB     2
SECTOR          RMB     2
COUNT           RMB     2
LOADADDRESS     RMB     2
STARTAD         RMB     2
DISKBUFFERPOINTER       RMB     2
LSN             RMB     2
TRACK           RMB     1              FUNNY FOR READNEXTLSN
LSNTOPSNMAP     RMB     NSPT
LSNTOPSNMAPEND  EQU     *
K1MODNSPT       RMB     1
K2MODNSPT       RMB     1
K4MODNSPT       RMB     1
K8MODNSPT       RMB     1
K16MODNSPT      RMB     1
                RMB     40             STACK SPACE
STACKBASE       RMB     1
        ORG     $F00
DISKBUFFER      RMB     NBPS
DISKBUFFEREND   EQU     *
        ORG     $1000
TRACKBUF        RMB     NBPS*NSPT
        PAGE
*
*       The boot program is stored in the first cluster of the disk
*       in memory image format offset by the start address, so that
*       location $100 in the boot program (the start address) is byte
*       0 of the file. Also, LSN 0 is PSN 0 on the disk. Beware, the boot
*       program can be mapped.
*
        ORG     $100
*
*       Assert: DP=0, CC=$FF when control is passed here by boot rom!
*
BOOT    LDS     #STACKBASE
        NOP                            ;SWI
        LDA     BOOT:MAPALG+SECTOR0OFFSET+1 READ 2ND SECTOR OF BOOT
        LDX     #SECTOR0OFFSET+1*NBPS
        BSR     READSECTOR             ASSERT HEADS ON TRACK 0 (RESET CODE)
        BRA     MAKEMAP
        IF      *>/BOOT:SIZE+SECTOR0OFFSET
        ?       BOOT CODE OVERLAPS BOOT:SIZE+SECTOR0OFFSET
        FIN
        ORG     BOOT:SIZE+SECTOR0OFFSET
*
READSECTOR
        PSHS    DP,X
        STX     READSECTOR0+FDSECTORBASE
        LDX     #READSECTOR0
        STA     FDSECTOR,X
        JSR     ROMREADSECTOR
        BCC     READSECTOR1
        JSR     PRINTASCIIZ
        SWI
READSECTOR1
        PULS    DP,X,PC
*
MAKEMAP CLRA
        TFR     A,DP
        SUBA    BOOT:MAPALG+SECTOR0OFFSET+1
        LDX     #LSNTOPSNMAP
        STX     TEMPX
MAP1    ADDA    BOOT:MAPALG+SECTOR0OFFSET+1 INVENT A PHYSICAL SECTOR NUMBER
MAP2    SUBA    #NSPT                  MODULO NSPT
        BCC     MAP2
        ADDA    #NSPT
        LDX     #LSNTOPSNMAP-1         SEE IF PSN ALREADY IN THE LIST
MAP3    INX
        CPX     TEMPX
        BEQ     MAP4                   B/ NOT IN THE LIST, STICK IT IN
        CMPA    0,X
        BNE     MAP3
        INCA                           ALREADY IN THE LIST, ADD 1 AND TRY AGAIN
        BRA     MAP2
MAP4    STA     ,X+                    NOT IN THE LIST, STICK IT IN
*                                      AND REMEMBER NEW END OF LIST
        STX     TEMPX
        CPX     #LSNTOPSNMAPEND        ARE WE DONE?
        BNE     MAP1                   B/ NO
*
*       READ IN REST OF BOOT
*
        LDA     LSNTOPSNMAP+2
        LDX     #SECTOR0OFFSET+2*NBPS
        BSR     READSECTOR
        LDA     LSNTOPSNMAP+3
        LDX     #SECTOR0OFFSET+3*NBPS
        BSR     READSECTOR
        LDA     LSNTOPSNMAP+4
        LDX     #SECTOR0OFFSET+4*NBPS
        BSR     READSECTOR
        LDA     LSNTOPSNMAP+5
        LDX     #SECTOR0OFFSET+5*NBPS
        BSR     READSECTOR
        JMP     BUILDSPIRAL
        PAGE
MODNSPTD
        LDX     #0
MODNSPTDL
        LEAX    1,X
        SUBD    #NSPT
        BCC     MODNSPTDL
        ADDD    #NSPT
        LEAX    -1,X
        PSHS    X
        STB     0,S
        PULS    D,PC
*
*       READNEXTLSN -- INTO MEMORY AT (X) ACCORDING TO MAP ALGORITHM
*
READNEXTLSN
        STX     DEST                   REMEMBER WHERE TO READ
        LDD     LSN                    GET DESIRED LSN
        BSR     MODNSPTD               DIVIDE BY NSPT
        ADDA    #LSNTOPSNMAP
        STAA    TEMPX+1
        CLR     TEMPX
        STAB    FDCYL+READSECTOR0      SAVE TARGET TRACK NUMBER
        LDX     TEMPX                  PERFORM MAPPING WITHIN TRACK
        CLRA
        ASRB
        BCC     KMAP1
        ADDA    K1MODNSPT
KMAP1   ASRB
        BCC     KMAP2
        ADDA    K2MODNSPT
KMAP2   ASRB
        BCC     KMAP3
        ADDA    K4MODNSPT
KMAP3   ASRB
        BCC     KMAP4
        ADDA    K8MODNSPT
KMAP4   ASRB
        BCC     KMAP5
        ADDA    K16MODNSPT
KMAP5   ADDA    0,X
        JSR     MODNSPTA
        PSHS    A
        LDD     LSN
        LDX     LSN                    FOR NEXT TIME...
        LEAX    1,X
        STX     LSN
        BSR     MODNSPTD
        TSTA                           START OF NEW TRACK?
        BNE     READFROMBUFFERPOOL     B/ NO
*
        LDX     #TRACKBUF              READ A WHOLE TRACK, PLEASE...
        CLR     SECTOR                 READ ODD NUMBERED SECTORS, START AT 1
        BSR     READ8SECTORSEVERYOTHER
        BSR     READ4SECTORSEVERYOTHER
        BSR     READ1SECTOREVERYOTHER
*
        LDX     #TRACKBUF+NBPS         WHERE TO READ 1ST EVEN SECTOR
        LDA     #1                     READ EVEN NUMBERED SECTORS, START AT 2
        STAA    SECTOR
        BSR     READ8SECTORSEVERYOTHER
        BSR     READ4SECTORSEVERYOTHER
        BSR     READ1SECTOREVERYOTHER
READFROMBUFFERPOOL
        PULS    A
        STA     SECTOR
        LDD     #TRACKBUF
GETAD   DEC     SECTOR                 COMPUTE DISPLACEMENT INTO TRACK BUFFER
        BMI     COPYBYTES
        ADDD    #NBPS
        BRA     GETAD
READ8SECTORSEVERYOTHER ; READ 8 SECTORS, SKIPPING ONE PHYSICAL SECTOR BETWEEN
        BSR     READ4SECTORSEVERYOTHER
READ4SECTORSEVERYOTHER ; READ 4 SECTORS, SKIPPING ONE PHYSICAL SECTOR BETWEEN
        BSR     READ2SECTORSEVERYOTHER
READ2SECTORSEVERYOTHER ; READ 2 SECTORS, SKIPPING ONE PHYSICAL SECTOR BETWEEN
        BSR     READ1SECTOREVERYOTHER
READ1SECTOREVERYOTHER ; READ 1 SECTOR, THEN SKIP NEXT SECTOR
        LDA     SECTOR                 GET DESIRED SECTOR
        JSR     READSECTOR             ISSUE THE READ REQUEST
        LEAX    2*NBPS,X               ADVANCE POINTER TO SECTOR BUFFER
        INC     SECTOR                 ADVANCE SECTOR NUMBER DESIRED
        INC     SECTOR
        RTS
        PAGE
COPYBYTES
        ADDB    #16
        TFR     D,X
        LDA     #NBPS/32
        LDY     DEST
        LEAY    16,Y
FCOPY   LDU     -16,X                  MAGIC 3US/BYTE COPY ROUTINE (2MHZ)
        STU     -16,Y
        LDU     -14,X
        STU     -14,Y
        LDU     -12,X
        STU     -12,Y
        LDU     -10,X
        STU     -10,Y
        LDU     -8,X
        STU     -8,Y
        LDU     -6,X
        STU     -6,Y
        LDU     -4,X
        STU     -4,Y
        LDU     -2,X
        STU     -2,Y
        LDU     0,X
        STU     0,Y
        LDU     2,X
        STU     2,Y
        LDU     4,X
        STU     4,Y
        LDU     6,X
        STU     6,Y
        LDU     8,X
        STU     8,Y
        LDU     10,X
        STU     10,Y
        LDU     12,X
        STU     12,Y
        LDU     14,X
        STU     14,Y
        LEAX    32,X
        LEAY    32,Y
        DECA                           ARE WE DONE?
        BNE     FCOPY                  B/ NO
        RTS                            END OF SECTOR TRANSFER
        PAGE
*
*       MODNSPTA:
*               B:=A/NSPT
*               A:=A MOD NSPT
*
MODNSPTA
        CLRB                           SET QUOTIENT TO ZERO
MODNSPTAL
        INCB                           BUMP QUOTIENT
        SUBA    #NSPT
        BCC     MODNSPTAL
        ADDA    #NSPT
        DECB
        RTS
*
*       BUILDSPIRAL--GENERATE SPIRALLING CONSTANSTS
*
BUILDSPIRAL
        LDA     BOOT:MAPALG+SECTOR0OFFSET
        BSR     MODNSPTA
        STA     K1MODNSPT
        ASLA
        BSR     MODNSPTA
        STA     K2MODNSPT
        ASLA
        BSR     MODNSPTA
        STA     K4MODNSPT
        ASLA
        BSR     MODNSPTA
        STA     K8MODNSPT
        ASLA
        BSR     MODNSPTA
        STA     K16MODNSPT
        PAGE    COMMON ROUTINES
*
*       SDOS LOADER
*       SDOS STARTS AT CLUSTER 1 AND CONTINUES SEQUENTIALLY ON THE DISK
*
LOAD    CLR     LSN                    RE-READ SECTOR 0 TO FORCE TRACK READ
        CLR     LSN+1
        LDX     #DISKBUFFER
        JSR     READNEXTLSN            AS GOOD A PLACE AS ANY
        LDAA    BOOT:NSPC+SECTOR0OFFSET SDOS STARTS AT CLUSTER 1
        STAA    LSN+1
        LDX     #DISKBUFFEREND
        STX     DISKBUFFERPOINTER
        JSR     GETBYTE
        CMPA    #LOAD:TYPE1
        BEQ     LOADTYPE1
        SWI                            FIRST LOAD RECORD WAS NOT TYPE 1
*
*       GET TYPE 1--STARTADDRESS
*
LOADTYPE1
        JSR     GETWORD
        STD     STARTAD
        JSR     GETWORD SEE IF COMPLEMENT CHECKS!
        COMA
        COMB
        CMPD    STARTAD
        BEQ     LOADNEXT               B/ CHECKSUM OK
        SWI                            COMPLEMENT FAILURE ON START ADDRESS
LOADTYPE2
        BSR     LOAD2AND3
LOADNEXT
        JSR     GETBYTE
        CMPA    #LOAD:TYPE3
        BEQ     LOADTYPE3
        CMPA    #LOAD:TYPE2
        BEQ     LOADTYPE2
        CMPA    #LOAD:TYPE0
        BEQ     LOADTYPE0
        SWI                            BAD RECORD TYPE
*
*       SKIP BYTES
*
LOADTYPE0
        JSR     GETWORD
        TFR     D,X
LOADTYPE0.1
        STX     COUNT
        BEQ     LOADNEXT               DONE!
        JSR     GETBYTE
        LDX     COUNT
        LEAX    -1,X
        BRA     LOADTYPE0.1
*
*       LOAD AND QUIT
*
LOADTYPE3
        BSR     LOAD2AND3
*       JMP     [STARTAD]
        LDD     STARTAD
        PSHS    D
        ORCC    #$D0                   ENSURE INTS DISABLED, E FLAG SET
        PSHS    CC,D,DP,X,Y,U
        JMP     NMIJMP                 FAKE AN NMI
*
*       GET BYTES FROM DISK
*
LOAD2AND3
        BSR     GETWORD
        STD     LOADADDRESS
        BSR     GETWORD
        STD     COUNT
LOAD2AND3T
        LDX     COUNT
        BEQ     LOAD2AND3RTS           B/  DONE
*
*       PROCESS TYPE 2 OR 3 RECORD CONTENTS
*
LOAD2AND3L
        LDX     DISKBUFFERPOINTER      IS DISK BUFFER EMPTY ?
        CPX     #DISKBUFFEREND         ... ?
        BNE     LOAD2AND3L1            B/ NO, GET A BYTE FROM THE BUFFER
        LDD     COUNT                  YES, AT LEAST A SECTOR'S WORTH OF BYTES
*                                      LEFT IN THIS LOAD RECORD ?
        SUBD    #NBPS                  ...?
        BCS     LOAD2AND3L2            B/ NOPE, PROCESS BYTES THE HARD WAY
        STD     COUNT                  YES, ADJUST COUNT AND ADDRESS
        LDX     LOADADDRESS            WHERE TO READ THE SECTOR
        LDD     LOADADDRESS            ADJUST LOAD ADDRESS BY NBPS BYTES
        ADDD    #NBPS
        STD     LOADADDRESS
        JSR     READNEXTLSN            GO DO OPTIMIZED LOAD RECORD TRANSFER
        BRA     LOAD2AND3T             CHECK FOR DONE

LOAD2AND3L2
        BSR     GETBYTE0
        BRA     LOAD2AND3L1A

LOAD2AND3L1
        BSR     GETBYTE1
LOAD2AND3L1A
        LDX     LOADADDRESS
        STAA    ,X+
        STX     LOADADDRESS
        LDX     COUNT
        LEAX    -1,X
        STX     COUNT
        BNE     LOAD2AND3L             MORE TO GO
LOAD2AND3RTS
        RTS
*
*       GET A BYTE
*
GETBYTE LDX     DISKBUFFERPOINTER
        CPX     #DISKBUFFEREND  
        BNE     GETBYTE1               B/ BUFFER NOT EMPTY
GETBYTE0
        LDX     #DISKBUFFER            WHERE TO READ
        JSR     READNEXTLSN
        LDX     #DISKBUFFER
GETBYTE1
        LDAA    ,X+
        STX     DISKBUFFERPOINTER
        RTS
GETWORD BSR     GETBYTE
        PSHS    D
        BSR     GETBYTE
        STA     1,S
        PULS    D,PC
        END     BOOT
