        TITLE   ROM CODE FOR SSB CHIEFTAIN
*       WITH    WI=107,DE=51
*
*       MISCELLANEOUS BOOT DEFS
*
CONTROLD        EQU     'D-'@
CONSOLEPORT     EQU     $F7E8
LOADPORT        EQU     $F7EA
*
*       READ PARAMETER BLOCK
*
                ORG     0
FDCYL           RMB     1              What cylinder
FDTRACK         RMB     1              What track (head)
FDSECTOR        RMB     1              What sector
FDSECTORBASE    RMB     2              Where to put it
FDDSKCAPABILITY RMB     1              Capability of the diskette
FDDENSITY       RMB     1              Density of this sector
FDREADBLOCKSIZE EQU     *
*
*       Disk capability parameters
*
CAP:BITSINVALID EQU     32             Bits invalid, use default from switches
CAP:DOUBLESIDE  EQU     16             Double sided disk
CAP:DOUBLETRACK EQU     8              Double track disk
CAP:DDTRACK1    EQU     4              Double density on first track
CAP:DDTRACK2    EQU     2              Double density on second track
CAP:IBMNUMBERS  EQU     1              Sector numbers are IBM style (1..26)
*
*       Equates for SSB Chieftain DCB-4 1791 floppy disk controller
*
SSBIOBUFFER     EQU     $F760 OR $F761 READ OR WRITE 1K BUFFER ON DCB-4
SSBIOBUFADRHI   EQU     $F762          WRITE ADDRESS COUNTER FOR DCB-4 BUFFER
SSBIOBUFADRLO   EQU     $F763          WRITE ADDRESS COUNTER FOR DCB-4 BUFFER
SSBEXTSTATUS    EQU     $F762 OR $F763 READ EXTERNAL STATUS
SSBPIAORA       EQU     $F764          PIA register controlling floppy
SSBPIAORB       EQU     $F765          PIA register controlling floppy
SSBPIACRA       EQU     $F766          PIA register controlling floppy
SSBPIACRB       EQU     $F767          PIA register controlling floppy
SSBWDSTATUS     EQU     $F76C          WD 1791 Status Register
SSBWDCMD        EQU     $F76C          WD 1791 Command Register
SSBWDTRACK      EQU     $F76D          WD 1791 Track Editor
SSBWDSECTOR     EQU     $F76E          WD 1791 Sector Register
SSBWDDATA       EQU     $F76F          WD 1791 Data Register
                PAGE
                ORG     $F400-6*3      place ROM vectors at top of RAM
SWI3JMP         RMB     3
SWI2JMP         RMB     3
FIRQJMP         RMB     3
IRQJMP          RMB     3
SWIJMP          RMB     3
NMIJMP          RMB     3
*
*       BOOT VARIABLES
*
                ORG     $F300
READSECTOR0     RMB     FDREADBLOCKSIZE READBLOCK FOR TRYBOOT
READYCOUNT      RMB     1              COUNTS # READY UNITS DURING BOOT LOOP
RETRYCOUNT      RMB     1              # RETRIES PERMITTED ON DISK I/O
UNIT            RMB     1              DRIVE UNIT NUMBER SELECTED
FDDRVCAPABILITY RMB     1              CAPABILITY OF FLOPPY DRIVE
RUNNINGENCRYPTED RMB    1              RUNNING ENCRYPTED FLAG
READSECTORADDRESS RMB   2              ADDRESS OF READSECTOR ROUTINE
*
*       CONFIGURATION
*
                IFUND   WIRE
WIRE            EQU     1
                FIN
                IFUND   SDOSLOADER
SDOSLOADER      EQU     0
                FIN
                IFUND   LISTIDB
LISTIDB         EQU     0
                FIN
                IF      SDOSLOADER
IDB09CODE       EQU     $E000
                ELSE
IDB09CODE       EQU     $F800
                FIN
IDB09RAM        EQU     *
                LIST    LISTIDB
                INCLUDE IDB09.ASM
                LIST    1
        PAGE    MESSAGES
ERR:TRACKDENSITYMISMATCH
        FCC     /track density mismatch/
        FCB     CR,LF,0
ERR:DISKNOTREADY
        FCC     /not ready/
        FCB     CR,LF,0
ERR:SEEKTIMEDOUT
        FCC     /seek timed out/
        FCB     CR,LF,0
ERR:READTIMEDOUT
        FCC     /read timed out/
        FCB     CR,LF,0
ERR:SEEKERROR
        FCC     /seek error/
        FCB     CR,LF,0
ERR:READERROR
        FCC     /read error/
        FCB     CR,LF,0
ERR:NOTABOOTDISK
        FCC     /not a boot disk/
        FCB     CR,LF,0
ERR:NOBOOTDEVICEREADY
        FCC     /No boot device ready/
        FCB     CR,LF,0
BOOTINGFROMWINCHESTER
        FCC     /Booting from Winchester... /
        FCB     0
BOOTINGFROMMINIFLOPPY
        FCC     /Booting from Minifloppy... /
        FCB     0
BOOTINGFROMFLOPPY
        FCC     /Booting from Floppy... /
        FCB     0
        PAGE    IDB09 I/O ROUTINES
*
*       RETURN INPUT CHAR FROM LOAD PORT IN A, PARITY STRIPPED
*       NO REGISTER RESTRICTIONS
*
READLOAD
        LDX     #LOADPORT
        BRA     GETCHR1
*
*       RETURN INPUT CHAR FROM CONSOLE PORT IN A, PARITY STRIPPED
*       NO REGISTER RESTRICTIONS
*
GETCHAR LDX     #CONSOLEPORT
GETCHR1 LDA     0,X
        RORA
        BCC     GETCHR1
        LDA     1,X
        ANDA    #$7F                   MASK THE PARITY
        IF      WIRE
*
*       CONTROL-@ GIVES CONTROL TO THE REMOTE (TURN OFF WIRE)
*       CONTROL-W GIVES CONTROL TO THE HOST (TURN ON WIRE)
*
        CMPX    #CONSOLEPORT           IS THIS A CONSOLE INPUT?
        BNE     GETCHR2                B/NO
        CMPA    #'W-'@                 TIME FOR WIRE?
        BNE     GETCHR2                B/ NO
WIRE1   LDA     LOADPORT               WIRE LOOP
        RORA                           SOMETHING AT THE LOAD PORT?
        BCC     WIRE2                  B/ NO
        LDA     LOADPORT+1             YES
        STA     CONSOLEPORT+1
WIRE2   LDA     CONSOLEPORT            SOMETHING AT THE CONSOLE PORT?
        RORA
        BCC     WIRE1                  B/ NO
        LDA     CONSOLEPORT+1
        ANDA    #$7F                   YES, SEE IF IT IS THE QUIT CODE
        CMPA    #'@-'@
        BEQ     GETCHR1                B/ YES, CONTROL BACK TO THE DEBUGGER
        STA     LOADPORT+1
        BRA     WIRE1
        FIN     WIRE
*
GETCHR2 RTS
*
*       OPEN THE LOAD PORT
*       NO REGISTER RESTRICTIONS
*
OPENLOAD
        LDA     #DC1
        LDX     #LOADPORT
        BRA     PUTCHR1
*
*       CLOSE THE LOAD PORT
*       NO REGISTER RESTRICTIONS
*
CLOSELOAD
        LDA     #DC3
        LDX     #LOADPORT
        BRA     PUTCHR1
*
*       OUTPUT THE CHAR IN A
*       NO REGISTER RESTRICTIONS
*
PCHAR   LDX     #CONSOLEPORT
PUTCHR1 LDB     0,X
        BITB    #%00000010
        BEQ     PUTCHR1
        STA     1,X
        RTS
*
*       If an escape check were required, this would do the trick
*
*ESCAPECHECK
*       LDA     CONSOLEPORT            IS THERE AN INPUT CHAR?
*       ORA     #2                     MAKES Z BIT CLEAR IF EXIT
*       RORA
*       BCC     ESCCHK1                B/ NO
*       LDA     CONSOLEPORT+1          YES, GET IT
*       ANDA    #$7F                   MASK PARITY
*       CMPA    #ESCAPE
*ESCCHK1 RTS
*
*       Pointer to default user context block passed in X,
*       Sets up context block (optional) and
*       returns pointer to default user context block in X
*       (this way, you can change it if you don't like it where it is)
*       There are no register restrictions
*
INITIALIZE
        LDD     #BOOT
        STD     PREG,X                 SET DEFAULT PROGRAM COUNTER
        CLR     DPREG,X                ENSURE DATA PAGE POINTER IS ZERO
        LDA     #$FF                   TURN OFF ALL THE USER'S INTS
        STA     CCREG,X
*
*       Give ACIA's enough time to finish transmitting current character
*       at slowest baud rate (110) before hitting him over the head
*       with a reset.
*       110 baud = 10 cps = 100ms/char =100000us/char
*       delay time = 100000us
*       delay count = (2mhz*100000us/char)/(cycles/loop) = 25000
*
        LDY     #25000
INIT1   LEAY    -1,Y
        BNE     INIT1
*
*       Reset the ACIA, then set up for 8+1 bits, divide by 64
*
        LDD     #$0316
        STA     CONSOLEPORT
        STA     LOADPORT
        STB     CONSOLEPORT
        STB     LOADPORT
*
*       if it is intended that the machine should boot after reset
*       then
*           wait 5 seconds (give operator time to strike ^D, delay
*               in reset code is sufficient)
*           repeat
*               if control-d on console
*               then return to IDB09 via RTS, X pointing to context block
*               try to boot (see TRYBOOT)
*           end
*       else return to IDB09 via RTS, X pointing to context block
*
*       It is intended that the machine should boot after reset
*
        PSHS    DP,X                   SAVE THE CONTEXT BLOCK POINTER
INIT2   BSR     CONTROLDCHECK          IS THERE A CONTROL-D?
        BNE     INIT3                  B/ NOT A CONTROL-D
        PULS    DP,X,PC                RESTORE THE CONTEXT BLOCK PTR AND RTS
INIT3   BSR     TRYBOOT                TRY TO BOOT
        BRA     INIT2                  B/ FAILED TO BOOT, KEEP TRYING
*
*        SECOND DELAY
*
DELAY2S BSR     DELAY1S
DELAY1S LDY     #62500
DELAY1  MUL                            (11~)
        MUL                            (11~)
        CLRA                           (2~)
        LEAY    -1,Y                   (5~)
        BNE     DELAY1                 (3~)
        RTS
*
*       CONTROL-D CHECK
*       IF CONTROL-D TYED, RETURN Z BIT SET
*       ELSE RETURN Z BIT CLEAR
*
CONTROLDCHECK
        LDA     CONSOLEPORT            IS THERE AN INPUT CHAR?
        ORA     #2                     MAKES Z BIT CLEAR IF EXIT
        RORA
        BCC     CDCHK1                 B/ NO
        LDA     CONSOLEPORT+1          YES, GET IT
        ANDA    #$7F                   MASK PARITY
        CMPA    #CONTROLD
CDCHK1  RTS
        PAGE    WINCHESTER DRIVER
        SETDPR  $F700
WDREAD  LDU     #ERR:READERROR
        COMA                           (SET THE CARRY)
        RTS
WDRESTORE
        LDU     #ERR:SEEKERROR
        COMA                           (SET THE CARRY)
        RTS
WDREADYCHECK
        LDU     #ERR:DISKNOTREADY
        COMA                           (SET THE CARRY)
        RTS
*
*       JSR     WDSELECT
*       FDB     NAME OF DISK ROUTINE THAT WILL BE ACTIVE DURING BOOT
*
WDSELECT
        PULS    Y                      GET POINTER TO PARAMS
        LDD     ,Y++                   GET SECTOR READ ROUTINE ADDRESS
        STD     READSECTORADDRESS
*       ???DO WINCHESTER SELECT CODE HERE
        JMP     ,Y                     DONE
        PAGE    BOOT LOOP
BOOT1   BSR     TRYBOOT                TRY TO BOOT
BOOT    BSR     CONTROLDCHECK          BOOT FAILED, IS THERE A CONTROL-D?
        BNE     BOOT1                  B/ NOT A CONTROL-D
        SWI                            GO ENTER THE DEBUGGER
*
*       clear ready count
*       if winchester ready
*       then
*           increment ready count
*           print "Booting from Winchester... ";
*           if err when restore
*           then print "seek error"
*           else
*               if err when read sector 0
*               then print "read error"
*               else
*                   if sector 0 does not contain a boot program
*                   then print "not a boot disk"
*                   else
*                       jump to $100
*                   fi
*               fi
*           fi
*       fi
*       if minifloppy ready
*       then
*           do same as for winchester,
*           substituting 'minifloppy' text for 'winchester'
*       fi
*       if 8-inch ready
*       then
*           do same as for winchester,
*           substituting 'floppy' text for 'winchester'
*       fi
*       if ready count = 0 then print "No boot device ready"
*       delay 1 sec
*
*       SEE IF WE CAN BOOT FROM WINCHESTER
*
TRYBOOT CLR     READYCOUNT
        BSR     SETDATAPAGE
        BSR     WDSELECT               TRY TO BOOT FROM WINCHESTER
        FDB     WDREAD                 NAME OF DISK READ ROUTINE TO USE
        BSR     WDREADYCHECK           IS THE WINCHESTER READY?
        BCS     TRYB2                  B/ IT'S NOT READY
        LDU     #BOOTINGFROMWINCHESTER TELL HIM WE'RE ATTEMPTING TO BOOT
        JSR     PRINTASCIIZ
        INC     READYCOUNT             AT LEAST ONE DISK IS READY
        BSR     WDRESTORE              "GO HOME, WINCHESTER"
        BCS     TRYB1                  B/ SOME KIND OF ERROR
        BSR     SETUPREAD0
        JSR     READSECTOR             TRY TO READ SECTOR 0
TRYB1   BSR     SMELLTEST              SEE IF IT LOOKS LIKE A BOOT SECTOR
*
*       SEE IF WE CAN BOOT FROM MINIFLOPPIES
*
TRYB2   BRA     TRYB2.1      ?????????????
        BSR     FDSELECT               TRY TO BOOT FROM WINCHESTERS
        FCB     0                      UNIT NUMBER TO SELECT
        FCB     %00011110              X/X/X/DS/DT/DD/DD/X (X=DON'T CARE)
        FDB     BOOTINGFROMMINIFLOPPY  TELL HIM WE'RE ATTEMPTING TO BOOT
*
*       SEE IF WE CAN BOOT FROM UNIT 4 (8-INCH FLOPPY)
*
TRYB2.1 ; ?????
        BSR     FDSELECT               TRY TO BOOT FROM WINCHESTERS
        FCB     4                      UNIT NUMBER TO SELECT
        FCB     %00000000              X/X/X/SS/ST/SD/SD/X (X=DON'T CARE)
        FDB     BOOTINGFROMFLOPPY
*
*       IF ALL THE DRIVES WERE NOT READY, SAY 'No Boot device ready'
*
TRYB3   LDA     READYCOUNT
        BNE     TRYB4                  B/ SOME DRIVE WAS READY
        LDU     #ERR:NOBOOTDEVICEREADY
        BSR     PRINTASCIIZ
TRYB4   JMP     DELAY2S
*
SETRETRYCOUNT
        LDA     #4
        STA     RETRYCOUNT
*       RTS                            CHEAP TRICK HERE
*
SETDATAPAGE
        LDB     #$F7
        TFR     B,DP
        RTS
*
SETUPREAD0
        LDX     #READSECTOR0
        CLRA
        CLRB
        STD     FDCYL,X                CYL 0, TRACK 0
        STA     FDSECTOR,X             SECTOR 0
        STD     FDDSKCAPABILITY,X
        INCA
        STD     FDSECTORBASE,X         SECTORBASE=$100
SETUPREAD0.1
        RTS
        PAGE    FD DISK ROUTINES
*
*       JSR     FDSELECT
*       FCB     UNIT NUMBER
*       FCB     DRIVE CAPABILITY
*       FDB     ADDRESS OF BOOT MESSAGE
*
FDSELECT
        PULS    Y                      GET POINTER TO PARAMS
        LDD     ,Y++                   GET UNIT AND CAPABILITY
        STA     UNIT
        STB     FDDRVCAPABILITY
        COMA                           UNIT NUMBER IS INVERTED
        STA     SSBPIAORB              HEAD LOAD IS DISABLED
        EORA    #$80                   ENABLE HEAD LOAD
        STA     SSBPIAORB
        LDU     ,Y++                   GET BOOT MESSAGE POINTER
        PSHS    Y                      NEW RETURN ADDRESS
        LDD     #FDREAD                SETUP SECTOR READ ROUTINE ADDRESS
        STD     READSECTORADDRESS
        BSR     FDREADYCHECK           IS THE FLOPPY READY?
        BCS     SETUPREAD0.1           B/ IT'S NOT READY
        INC     READYCOUNT             AT LEAST ONE DISK IS READY
        BSR     PRINTASCIIZ
        BSR     SETRETRYCOUNT
        BSR     FDRESTORE              RESTORE THE FD
        BCS     PRINTASCIIZ            B/ SOME KIND OF ERROR
*
        BSR     SETUPREAD0             TRY SD/ NON-IBM NUMBERS
        BSR     SMELLTEST              SEE IF IT LOOKS LIKE A BOOT SECTOR
*
        INC     FDDSKCAPABILITY,X      TRY SD/ IBM NUMBERS
        BSR     SMELLTEST              SEE IF IT LOOKS LIKE A BOOT SECTOR
*
        INC     FDDENSITY,X            TRY DD/ NON-IBM NUMBERS
        CLR     FDDSKCAPABILITY,X
        BSR     SMELLTEST              SEE IF IT LOOKS LIKE A BOOT SECTOR
*
        INC     FDDSKCAPABILITY,X      TRY DD/ IBM NUMBERS
        BSR     SMELLTEST              SEE IF IT LOOKS LIKE A BOOT SECTOR
        BRA     PRINTASCIIZ            GO PRINT THE ERROR AND RETURN
*
*       PRINTS ASCIIZ MESSAGE POINTED TO BY U
*       AND TERMINATED BY A NULL BYTE
*
PRASCIIZ1
        JSR     PCHAR
PRINTASCIIZ
        LDA     ,U+                    GET NEXT CHAR
        BNE     PRASCIIZ1              B/ GO PRINT IT
        RTS                            DONE
*
SMELLTEST       ; READ A SECTOR AND SNIFF IT FOR GOOD BOOT CODE
        JSR     READSECTOR
        PULS    Y                      POP RETURN ADDR IN CASE WE TAKE BRANCH
        BCS     SMELLTEST1             B/ SOME ERROR ENCOUNTERED WHILE READING
        LDU     #ERR:NOTABOOTDISK      ASSUME IT'S NOT A BOOT DISK
        LDD     #$10CE                 SMELL THE SECTOR FOR A LOAD STACK INST
        CMPD    $100
        BNE     PRINTASCIIZ            B/ DOESN'T SMELL LIKE LOAD STACK TO ME!
        JMP     $100                   GO EXECUTE IT
SMELLTEST1
        JMP     ,Y
        PAGE
*
*       This code is here because mini-floppies don't have ready line
*       (unbelievable!!)
*
*       Wait for Disk Ready (change in index hole status)
*
FDREADYCHECK
        BSR     FDDISKABORT            Get type I status
        BPL     FDREADYCHECK2          STATUS SAYS IT'S READY
        LDX     #16666                 LOOK FOR CHANGE IN INDEX HOLE
        LDB     #%00100000             HEAD MUST BE LOADED FOR VALID STATUS
FDREADYCHECK1
        LDA     SSBWDSTATUS
        LEAX    -1,X                   (5~) ARE WE TIMED OUT YET?
        BEQ     FDREADYCHECK3          (3~) B/ YES
        BITB    SSBWDSTATUS            (4~) IS THE HEAD STILL LOADED?
        BEQ     FDREADYCHECK           (3~) B/ NO
        EORA    SSBWDSTATUS            (4~) IS THERE A CHANGE IN INDEX HOLE?
        BITA    #%00000010             (2~)
        BEQ     FDREADYCHECK1          (3~) B/ NO
FDREADYCHECK2
        CLRA                           (CLEAR THE CARRY)
        RTS
FDREADYCHECK3
        LDU     #ERR:DISKNOTREADY
        COMA                           (SET THE CARRY)
        RTS
*
FDRESTORE
        BSR     FDDISKABORT            Kill whatever disk is doing
        LDA     #%00001001             PICK UP A RESTORE COMMAND
        JSR     FDISSUECMD             Go do the restore
        BCS     FDRESTORE1             B/ TIMED OUT ON SEEK
        BITA    #%00000100             Check for arrival at cylinder zero
        BNE     FDRESTORE1             B/ GOT THERE (ASSERT CARRY IS CLEAR)
        DEC     RETRYCOUNT
        BPL     FDRESTORE
        LDU     #ERR:SEEKERROR         ASSUME SEEK ERROR
        COMA                           (SET THE CARRY)
FDRESTORE1
        RTS
        PAGE
WAIT28US
        LDA     #(28*2-7-5)//(2+3)     = # times around loop to make 28 Us.
        DECA                           2 cycles
        BNE     *-1                    3 cycles
        RTS
*
*       Make the controller idle and get status
*       Issue abort command, wait 28us for status to be valid,
*       then read.
*
FDDISKABORT
        LDA     #%11010000             abort with no interrupts
        STA     SSBWDCMD
        BSR     WAIT28US
        LDA     SSBWDSTATUS            return with status in B
*
*       BECAUSE THE DISK SELECT LINES ARE GATED WITH HEAD LOAD,
*       WE CAN ONLY HAVE VALID STATUS WHEN THE HEADS ARE LOADED
*
        BITA    #%00100000             STATUS IS VALID ONLY IF HEAD IS LOADED
        BEQ     FDDISKABORT1           B/ STATUS IS NOT VALID
        TSTA
        RTS
FDDISKABORT1    ; OH, LOOK! THE HEADS ARE NOT LOADED. LOAD THEM!
        LDA     SSBWDTRACK
        STA     SSBWDDATA
        LDA     #%00011001             MAKE HIM SEEK TO SAME TRACK
*
*       Issue the 1791 command in (A)
*
FDISSUECMD
        STA     SSBWDCMD               Tell the 1791 to stick this up his...
        BSR     WAIT28US
        LDY     #62500                 USE 1 SEC TIMEOUT (62500*32=2000000 CYC)
FDISSUECMD1
        PSHS    D                      (7~)
        PULS    D                      (7~)
        LEAY    -1,Y                   (5~) HAS THE DISK TIMED OUT?
        BEQ     FDISSUECMD2            (3~) B/ YES
        LDA     SSBEXTSTATUS           (5~) NO, SEE IF DONE
        RORA                           (2~)
        BCC     FDISSUECMD1            (3~) B/ NOT DONE
        CLRA                           (CLEAR THE CARRY)
        LDA     SSBWDSTATUS            GET THE STATUS
        RTS
FDISSUECMD2
        BSR     FDDISKABORT            HE TIMED OUT, TELL HIM TO STOP IT
        LDU     #ERR:SEEKTIMEDOUT
        COMA                           (SET THE CARRY)
        RTS
        PAGE
FDSEEKS STA     SSBWDDATA              This will get us to the right track
*
*       I am not doing seek with verify because I assert that the drive
*       is reliable (assumption). If the drive is reliable, then it is
*       pointless to seek with verify, considering the read and write
*       verify automatically. If the drive is not reliable, then (get
*       one that is) the read and write will error and recover correctly.
*       Furthermore, if we do end up on the wrong track, both the seek
*       with verify and the read/write take 5 revs to complain about the
*       wrong track, so again assume it's right and let the read/write
*       tell us otherwise.
*
        LDA     #%00011001             LOAD UP THE SEEK COMMAND
        BSR     FDISSUECMD             Tell 1791 what to do
        BCC     FDSEEKS1               B/ NO ERROR
        PULS    Y,PC                   POP ONE AND RETURN
*
*       A seek without verify can't have a CRC or SEEK ERROR status
*       from the 1791. It's like adding 1 and 1 to get 3, it just can't
*       happen. If it does, something is really wrong.
*
FDSEEKS1
        BITA    #%00011000             Seek or CRC error?
        BEQ     FDSEEKS2               B/ NO
        SWI
FDSEEKS2
        RTS
*
*       SEEK -- See if the head must be moved with a seek operation;
*       if it must, the seek is done without verification, as a seek
*       failure will be picked up by a subsequent read/write as
*       "record not found" status, for which the remedy will be
*       a restore operation.  The restore operation IS verified; if
*       it fails, a "seek error" is registered, and the restore is
*       retried, up to the seek-retry count.
*
FDSEEK  ; See if Seek is needed
        LDA     FDCYL,X                FIND OUT WHERE TO PUT THE HEADS
*
*       Check track capability of drive against track configuration of disk.
*       If capability and configuration match, do a vanilla (plain) seek.
*       Else, it must be single track disk, double track drive.
*       In this case, seek twice.
*
        LDB     FDDSKCAPABILITY,X      ARE THE CAPABILITY BITS VALID?
        EORB    FDDRVCAPABILITY        SAME CAPABILITY?
        ANDB    #CAP:DOUBLETRACK
        BEQ     FDSEEK1                B/ YES, SAME TRACK CAPABILITY
        LDB     FDDSKCAPABILITY,X      IS IT A DOUBLE TRACK DISK?
        ANDB    #CAP:DOUBLETRACK
        BNE     FDSEEK3                B/ YES, YOU CAN'T DO THIS!
        LDB     SSBWDTRACK             FIND OUT WHERE THE HEADS ARE NOW
        BSR     FDSEEKS
        STB     SSBWDTRACK             FAKE HIM OUT
        LDA     FDCYL,X                TELL THE 1791 WHERE TO PUT THE HEADS
FDSEEK1 BSR     FDSEEKS
        CLRA
        RTS
FDSEEK2 LDU     #ERR:TRACKDENSITYMISMATCH
FDSEEK3 COMA
        RTS
        PAGE
*
FDREADERROR
        DEC     RETRYCOUNT
        BPL     READERROR1
        LDU     #ERR:DISKNOTREADY
        BITA    #%10000000             CHECK NOT READY
        BNE     FDSEEK3                B/ NOT READY
        LDU     #ERR:SEEKERROR
        BITA    #%00010000             CHECK RECORD NOT FOUND
        BNE     FDSEEK3                B/ RECORD NOT FOUND
        LDU     #ERR:READERROR
        BITA    #%00001000
        BNE     FDSEEK3                B/ CRC ERROR
        SWI                            WHO KNOWS WHAT
        PAGE
FDREAD  JSR     SETRETRYCOUNT
READERROR1
        BITA    #%00010000             WAS THIS A RECORD NOT FOUND (SEEK ERR)?
        BEQ     FDREAD0                B/ NO, TRY RE-READING IT
        BSR     FDRESTORE
FDREAD0 BSR     FDSEEK                 MAKE SURE WE GET TO THE RIGHT TRACK
        BCS     FDREAD5                B/ SOME KIND OF ERROR, PASS IT ON
*
*       Set density, data direction, side, transfer enable.
*       Head load and unit unchanged
*
        LDB     UNIT                   Start with the unit number
        ORB     #%10010000             Set head load enable, xfer enable
*                                      assume SD, read, side 0
        LDA     FDDENSITY,X            IS THE SECTOR DD?
        BEQ     FDREAD1                B/ NO
        ORB     #%01000000             YES, SET DD
FDREAD1 LDA     FDTRACK,X              IS IT SIDE 0?
        BEQ     FDREAD2                B/ YES
        ORB     #%00001000             NO, SET SIDE 1
FDREAD2 COMB                           It's inverted data
*                                      Set density, data direction, side, and
        STB     SSBPIAORB              xfer enable, head load, unit.
        LDA     FDSECTOR,X             Get the desired sector number
        LDB     FDDSKCAPABILITY,X      Add IBM offsets if required
        RORB
        ADCA    #0
        STA     SSBWDSECTOR            Tell 1791 what sector to search for
        BSR     SETSSBIOBUFADDRESS
*
*       Sector number register is set, set the side select for
*       the 1791 read command, then read a sector
*
*       LDA     #%10000000
*       LDB     FDDISKCAPABILITY,X
*       BITB    #CAP:DOUBLESIDE
*       BEQ
*       ORA     #%00000010
        LDA     #%10000010             PICK UP A READ COMMAND
        LDB     FDTRACK,X              TEST THE TRACK (HEAD) NUMBER
        BEQ     FDREAD3                B/ SIDE 0
        ORA     #%00001000             SET SIDE 1
FDREAD3 BSR     FDISSUECMD             go tell the disk what to do
        LDU     #ERR:READTIMEDOUT      ASSUME A TIMEOUT HAPPENED
        BCS     FDREAD5                B/ ERROR (DON'T BOTHER WITH RETRY)
        ANDA    #%11011111             Ignore delete data mark status
        BNE     FDREADERROR            B/ error status, try to recover
*
*       We read the sector, now move the bytes
*
        BSR     SETSSBIOBUFADDRESS
        LDY     FDSECTORBASE,X         Point to write buffer
        LDA     #256/2                 PICK UP # OF LOOP ITERATIONS (ASSUME DD)
        LDB     FDDENSITY,X            IS THIS A DOUBLE DENSITY SECTOR?
*                                      SD (NBPS=128) or DD (NBPS=256)
        BNE     FDREAD4                B/ DD
        LSRA                           SD
*
*       Read the on-board I/O buffer
*
FDREAD4 LDU     SSBIOBUFFER            Get two bytes
        STU     ,Y++                   Store the two bytes
        DECA                           Done?
        BNE     FDREAD4                B/ no
        CLRA                           (CLEAR CARRY)
SETSSBIOBUFADDRESS ; CHEAP TRICK HERE THAT HAS NOTHING TO DO WITH FDREAD
        LDD     #$FFFF                 Init the floppy buffer pointer
        STD     SSBIOBUFADRHI
FDREAD5 RTS
        SETDPR  0
        IF      SDOSLOADER
        PAGE    LOADER
        IF      *<<$FE00
        ORG     $FE00
        FIN
*
*       LOADER PROGRAM FOR THE REMOTE COMPUTER
*       READS SDOS LOAD RECORD FORMATS
*
LOADINIT
        LDY     #25000
LDI1    LEAY    -1,Y
        BNE     LDI1
        LDD     #$0316
        STA     CONSOLEPORT
        STA     LOADPORT
        STB     CONSOLEPORT
        STB     LOADPORT
        BSR     LDBUFINIT
LDI2    LDA     LOADPORT
        RORA
        BCC     LDI3
        LDA     LOADPORT+1
        STA     CONSOLEPORT+1
LDI3    LDA     CONSOLEPORT
        RORA
        BCC     LDI2
        LDA     CONSOLEPORT+1
        ANDA    #$7F
        CMPA    #'@-'@
        BEQ     LDI4
        STA     LOADPORT+1
        BRA     LDI2
LDI4    LDB     LOADPORT
        BITB    #$02
        BEQ     LDI4
        LDA     #DC1
        STA     LOADPORT+1
        RTS
*
LDOUT   LDB     CONSOLEPORT
        BITB    #$02
        BEQ     LDOUT
        STA     CONSOLEPORT+1
        RTS
*
LDBUFINIT
        LDX     #$EF02
        STX     -2,X
LDBUFI1 LDA     ,X
        BSR     LDOUT
        CLR     ,X+
        CMPX    #$F000
        BNE     LDBUFI1
        RTS
*
OUTNUM  PSHS    D,X
        PSHS    D
        LDA     #'                   ;
        BSR     OUT1
        PULS    D
        BSR     OUT4
        PULS    D,X,PC
*
OUT4    PSHS    B
        BSR     OUT2
        PULS    A
OUT2    PSHS    A
        LSRA
        LSRA
        LSRA
        LSRA
        BSR     OUTD
        PULS    A
        ANDA    #$0F
OUTD    ADDA    #'0
        CMPA    #'9
        BLS     OUT1
        ADDA    #$07
OUT1    LDX     $EF00
        STA     ,X+
        STX     $EF00
        RTS
*
OUTTYPE PSHS    A
        PSHS    A
        LDA     #CR
        BSR     OUT1
        LDA     #LF
        BSR     OUT1
        LDA     #'T
        BSR     OUT1
        PULS    A
        BSR     OUTD
        PULS    A,PC
*
LOADER  BSR     LOADINIT
        BSR     GETONE
        BSR     OUTTYPE
        CMPA    #2              FIRST LOAD RECORD TYPE 2 ONLY
        BNE     L0              B/ IT ISN'T
        BSR     GETTWO          GET START ADDRESS
        BSR     OUTNUM
        PSHS    D
        BSR     GETTWO          GET CHECKSUM
        BSR     OUTNUM
        COMA
        COMB
        CMPD    0,S
        BEQ     LOADNXT         B/ START RECORD ERROR
        SWI                     START ADDRESS CHECKSUM
L0      SWI                     NOT AN SDOS 6809 LOADABLE FILE
*
*       LOAD THE RECORD, THEN GO BACK FOR MORE
*
LD2     BSR     LD2SUB          LOAD THE RECORD
LOADNXT BSR     GETONE          GET NEXT RECORD TYPE
        BSR     OUTTYPE
        CMPA    #3              LOAD AND GO?
        BEQ     LD3             B/ YES
        CMPA    #2              LOAD?
        BEQ     LD2             B/ YES
        CMPA    #0              SKIP?
        BEQ     LD0             B/ YES
        SWI                     NO, NOT A LOAD RECORD
*
*       LOAD AND GO
*       LOAD THE RECORD, SET REGISTERS, AND ENTER IDB RESET
*
*LD3     BSR     LD2SUB          LOAD THE RECORD
*        ORCC    #$FF            TURN OFF INTS
*        PSHS    CC,D,DP,X,Y,U   MAKE CONTEXT BLOCK
*        JMP     $F80A           FAKE AN NMI
*
LD3     BSR     LD2SUB
        LDD     0,S
        BSR     OUTNUM
        BRA     LDBUFINIT
*
LD2SUB  BSR     GETTWO          GET THE ADDRESS
        BSR     OUTNUM
        TFR     D,Y
        BSR     GETTWO          GET THE COUNT
        BSR     OUTNUM
        TFR     D,X
        LEAX    1,X
SUB1    LEAX    -1,X
        BEQ     SUB4
        BSR     GETONE          GET A DATA BYTE
        CMPY    #$F000
        BHS     SUB3            SKIP REMAINING RECORD
        STA     ,Y+
        BRA     SUB1
SUB2    BSR     GETONE
SUB3    LEAX    -1,X
        BNE     SUB2
SUB4    RTS
*
*       SKIP RECORD
*
LD0     BSR     GETTWO          GET THE COUNT
        BSR     OUTNUM
        TFR     D,X
        LEAX    1,X
LD01    LEAX    -1,X
        BEQ     LOADNXT
        BSR     GETONE          GET A FILL BYTE
        BRA     LD01
*
*       GETTWO
*       RETURN FIRST BYTE IN A, SECOND BYTE IN B
*
GETTWO  BSR     GETONE
        PSHS    D
        BSR     GETONE
        STA     1,S
        PULS    D,PC
*
GETONE  LDA     LOADPORT
        RORA
        BCC     GETONE
        LDA     LOADPORT+1
        RTS
        FIN     SDOSLOADER
        PAGE    LOADER
        IF      *<<$FF00
        ORG     $FF00                  RESET CODE MUST BE ABOVE $FF00
        FIN
SELECTBANK
        STA     $FFE0
        PULS    U
        CMPS    #STACKE
        BEQ     ERASEMEM
        JMP     ,U
*
RESET1  LDS     #STACKE                USE IDB STACK
        LDA     RUNNINGENCRYPTED
        BEQ     DONTZEROMEMORY         B/ NOT RUNNING ENCRYPTED
        LDA     #8-1                   NUMBER OF USER SPACES
ERASEBANK
        JSR     SELECTBANK             TURN ON USER SPACE (A)
ERASEMEM
        LDX     #$BFFF                 ZERO OUT USER MEMORY
ERASELOOP
        CLR     0,X                    MAKE IT GO AWAY
        DEX
        BNE     ERASELOOP
        DECA                           PRESERVED BY SELECT BANK
        BPL     ERASEBANK              ASSERT NUMBER OF BANKS<128
DONTZEROMEMORY
        CLR     RUNNINGENCRYPTED       MARK 'NOT RUNNING ENCRYPTED'
*
*       SET UP SYSTEM SPACE (MAP 0) WITH 15 PAGES OF MEMORY AND THE
*       I/O PAGE. NOTE THAT THE PAGES ARE ALLOCATED BACKWARDS. THIS
*       DOESN'T HURT A THING AND MAKES THIS ROUTINE TINY, THEREBY
*       CONSERVING MY PRECIOUS ROM SPACE.
*
        LDA     #14                    SET UP MAP 0 WITH 15 RAM PAGES
        LDX     #$FFF0
        CLR     -16,X                  SELECT MAP 0
RESET2  STA     ,X+                    STORE DOWN PHYSICAL PAGE NUMBER
        DECA                           DONE MAPPING THE SYSTEM SPACE?
        BPL     RESET2                 B/ NO, ALLOCATE ANOTHER PAGE
        STA     ,X
*
*       Initialize the PIA for the floppies
*
        LDD     #\$0000                Reset the PIA
        STD     SSBPIACRA              This gets CRA and CRB
*       LDD     #\$00FF                A side is input, B side is output
        CLRB
        STD     SSBPIAORA              This gets DDRA and DDRB
        LDD     #\$0404
        STD     SSBPIACRA
*
*       ???do winchester initialization here
*
*
*       INITIALIZE THE RAM VECTORS
*
        LDX     #JMPLST
        LDY     #SWI3JMP
        LDB     #JMPLSTEND-JMPLST
RESET3  LDA     ,X+
        STA     ,Y+
        DECB
        BNE     RESET3
        IF      SDOSLOADER
        JMP     LOADER
        ELSE
        JMP     DEBUG                  START THE DEBUGGER
        FIN
*
JMPLST
        JMP     NMIH                   SWI3JMP
        JMP     NMIH                   SWI2JMP
        JMP     FIRQENTRY              FIRQJMP
        JMP     NMIH                   IRQJMP
        IF      USESWIFORBREAKPOINT
        JMP     BREAKPOINT             SWIJMP
        ELSE
        JMP     NMIH                   SWIJMP
        FIN
        JMP     NMIH                   NMIJMP
JMPLSTEND
*
NMI     LDA     RUNNINGENCRYPTED
        BNE     NMIRTI
        JMP     NMIJMP
NMIRTI  RTI
*
*       SERIALNUMBER MUST NOT BE LOCATED ON TOP OF THE MAP
*
        IF      *>>$FFCE
        ? ROM CODE TOO BIG ?
        FIN
        ORG     $FFCE
RESET   JMP     RESET1
        FDB     $5500,0,0,0            8-BYTE SERIAL NUMBER
*
*       ASSIGN PAGE NUMBER IN (B) TO MAP NUMBER (USERBANK) SLOT (A)
*       RESTORES MAP TO SYSTEM SPACE WHEN FINISHED
*       CALLED FROM MT
*
ASSIGNPAGETOMAP
        SEI
        LDX     #$FFF0                 SELECT THE RIGHT MAP SLOT
        LEAX    A,X
        LDA     $F000                  USERBANK MUST BE HERE DURING MT
        STA     $FFE0                  BANK SELECT
        STB     ,X                     ASSIGN THE PAGE
        CLR     $FFE0                  SELECT SYSTEM SPACE
        CLI
        RTS
        PAGE    6809 Vectors
        IF      *>>$FFEE
        ? ROM CODE OVERWRITES RESET VECTORS ?
        FIN
        ORG     $FFEE
READSECTOR
        JMP     [READSECTORADDRESS]
        FDB     SWI3JMP
        FDB     SWI2JMP
        FDB     FIRQJMP
        FDB     IRQJMP
        FDB     SWIJMP
        FDB     NMI
        FDB     RESET
*
        ORG     GETC
        JMP     GETCHAR
        JMP     PCHAR
        JMP     PRINTASCIIZ
        JMP     OPENLOAD
        JMP     READLOAD
        JMP     CLOSELOAD
        JMP     INITIALIZE
*
        END     DEBUG
