    NAM BOOT
***********************************************************
* Extracted from the book:
* "CP/68, an M6800 Operating System" by Jack E. Hemenway
*
* Scott LaBombard
* labomb@rochester.rr.com
* 02/29/2019
***********************************************************
*
* PERCOM CP/68 BOOTSTRAP PROGRAM
* ASSUMES SYSTEM FILE LINKED AS FOLLOWS:
*
*      TRACK 0, SECTOR 1, BYTE 250-FIRST TRACK
*                              251-FIRST SECTOR
*                              252-LAST TRACK
*                              253-LAST SECTOR
*                              254,5 FREE-SPACE HEADER
*
* BOOTS SYSTEM FROM DRIVE 0:
*
* DEFINE DISK-DRIVE INTERFACE ADDRESSING
*
INITRK  EQU $C027
RDSECX  EQU $C00C
*
DRV     EQU $0000
TRK     EQU $0001 
SCTR    EQU $0002
TW      EQU $0016
SECSIZ  EQU 256
*
* NOTE: ALL VARIABLES IN COMMON, CODE IS ROM-ABLE
*
STACK   RMB 16      (CMN STACK,16)
BUFFER  RMB SECSIZ  (CMN BUFFER,SECSIZ)
FTS     RMB 2       (CMN FTS,2)
LTS     RMB 2       (CMN LTS,2)
PTS     RMB 2       (CMN PTS,2)
INDEX   RMB 2       (CMN INDEX,2)
SAVEX   RMB 2       (CMN SAVEX,2)
ADDRES  RMB 2       (CMN ADDRES,2)
FCNT    RMB 1       (CMN FCNT,1)
*
* ERROR JUMP VECTOR
*
ERROR EQU $E113
*
* BEGIN BOOT HERE
*
START LDS #STACK+15 INIT. STACK POINTER
    JSR INITRK      INIT. DRIVES
*
* NOW GET SYSTEM LINK INFORMATION
*
    LDA A #1
    LDA B #0        TRACK 0, SECTOR 1
    LDX #BUFFER
    JSR RDSEC       READ LINK SECTOR
    LDX #BUFFER
    LDA A SECSIZ-6,X    GET FIRST T/S 
    LDA B SECSIZ-5,X
    STA A FTS
    STA B FTS+1
    LDA A SECSIZ-4,X    GET LAST T/S 
    LDA B SECSIZ-3,X
    STA A LTS 
    STA B LTS+1
    LDX #BUFFER+4
    STX INDEX       INIT. BUFFER INDEX
    LDA A FTS+1
    LDA B FTS
    STA A PTS+1     INIT. PRESENT T/S
    STA B PTS
    LDX #BUFFER
    JSR RDSEC       READ FIRST SECTOR
*
* NOW LOAD SYSTEM FILE INTO MEMORY
*
BOOT1 BSR GETBYT    GET A DATA BYTE FROM FILE
    CMP A #$16      TRANSFER-ADDRESS?
    BNE BOOT2       NO
*
    BSR GETBYT
    STA A ADDRES    GET TRANSFER ADDRESS
    BSR GETBYT
    STA A ADDRES+1
    BRA BOOT1       GET NEW DATA FRAME
*
BOOT2 CMP A #$02    DATA FRAME?
    BNE BOOT4       NO
*
    BSR GETBYT
    STA A SAVEX     GET ADDRESS
    BSR GETBYT
    STA A SAVEX+1
    BSR GETBYT
    STA A FCNT      GET FRAME COUNTER
*
BOOT3 BSR GETBYT    GET DATA BYTE
    LDX SAVEX
    STA A 0,X       STORE BYTE
    INX
    STX SAVEX
    DEC FCNT        COUNT DOWN
    BNE BOOT3
*
    BRA BOOT1       GET NEW DATA FRAME
*
BOOT4 LDX ADDRES    GET TRANSFER ADDRESS
    JMP 0,X         GO THERE
*
* READ A DATA BYTE FROM SYSTEM FILE
* RETURN BYTE IN 'A' REGISTER 
*
GETBYT LDX INDEX
    CPX #BUFFER+256 NEED NEW SECTOR?
    BEQ GETSEC      YES
*
    LDA A 0,X       GET BYTE
    INX
    STX INDEX       MOVE POINTER
    RTS
*
GETSEC LDA B PTS
    LDA A PTS+1     CHECK FOR LAST SECTOR
    CMP A LTS+1
    BNE GETS2       NOT LAST
*
    CMP B LTS
    BNE GETS2       NOT LAST
*
    BRA BOOT4       EOF-GO TO TRANSFER ADDRESS
*
GETS2 LDX #BUFFER
    LDA B 0,X       GET FORWARD T/S LINK
    LDA A 1,X
    STA B PTS       UPDATE PRESENT T/S
    STA A PTS+1
    BSR RDSEC       READ NEW SECTOR
    LDX #BUFFER+4
    LDA A 0,X       GET DATA BYTE
    INX
    STX INDEX       RE-INIT. INDEX
    RTS
*
* SINGLE-SECTOR READ ROUTINE
*
*   DRIVE=0
*   TRACK='B'
*   SECTOR='A'
*   BUFFER='X'
*
RDSEC DEC A         OFFSET OF SECTOR=-1
    STA A SCTR 
    STA B TRK
    STX TW          SAVE BUFFER ADDRESS
    LDA A #$40      INIT. DRIVE
    STA A DRV
    JSR RDSECX
    BCC *+5         ERROR?
*
    JMP ERROR       YES
*
    RTS             NO
*
    END
