 ttl UniFLEX Disk Formatter
 sttl X-12+ Floppy Bootstrap Loader
 pag
 info Bootstrap for X-12+ Version 2.00; 5/13/83

* UniFLEX Bootstrap Loader for 6809 X-12+

 global uboot,ubflgs

* Special locations

corcnt equ $13
lstmem equ $14

DATMAP equ $F40A Map for $A000
BLKHOLE equ $FF Black hole in map
DATSENSE equ $00 Sense of data in DAT

*
old_org equ $B000 org of loader as loaded by ROM
new_org equ $B800 new org of loader

* Buffers

 base new_org+512
buffer rmb 512
map rmb 512
*
ffmap equ 17 file map offset in fdn
bhxfr equ 10 transfer address offset in header
BHDSIZ equ 24 binary file header size

* System equates for single sector read

seclen     equ     512                 sector length
busy       equ     1                   busy mask
ORB29      equ     $E8A0               funny drq status
ORA29      equ     $E8A1               drive sel / density bits
COM1797    equ     $E8C0               1797 command register
TRK1797    equ     $E8C1
SEC1797    equ     $E8C2
DAT1797    equ     $E8C3
*   ORA equates
P09229     equ     %10000000
hltogg     equ     %01000000           low to toggle head timer
fdsingden  equ     %00100000           act high for single density
mini9229   equ     %00010000
fdmotor    equ     %00001000           floppy disk motor on (act high)

fdsel0     equ     %00000000           floppy disk drive select 0


rdcmnd     equ     $8C                 read command
skcmnd     equ     $19


* Temporary storage

 base $00E0
btdate rmb 4
direct rmb 1
mapptr rmb 2
entrys rmb 2
xfradr rmb 2
sdslct rmb 1

********************************************
* Start of program
********************************************

 data

* Lookup "uniflex" in directory

uboot lbra uboot0 skip disk type bytes

ubflgs fcb 0,0
**************************************************
*** double sided and double density flags
*** special technique to assemble at wrong address
dside equ new_org+$0004
dnsity equ new_org+$0003
**************************************************

uboot0
*
* Relocate loader from "old_org" to "new_org"
*
 ldx #old_org
 ldu #new_org
00 ldd ,x++ move loader text
 std ,u++
 cmpx #old_org+512
 blo 00b
 lbra (uboot1-old_org)+new_org
*
uboot1
 lda $010A check block $A000 mapped in
 cmpa #BLKHOLE black hole?
 bne uboot2
 dec corcnt decrease number of pages available
 ldx lstmem pick up last page pointer
 lda ,-x get a page
 stx lstmem
 sta $010A set up map
 sta DATMAP
uboot2
 ldd #1 root directory fdn no.
 lbsr fdnblk read in fdn
 ldd 7,y find size of directory
 bsr divby8
 lsra
 rorb
 std entrys save entry count
read1 lbsr rdblk read data block
 lbne noboot exit if error
lookup leax 2,u point to filespec
 ldd 0,u valid entry?
 beq nxtent no - skip deleted file
 leay btname,pcr point to boot file name
 ldb #14 set name length
cmpnam lda 0,x+
 cmpa 0,y+ is this boot file entry?
 bne nxtent if not, skip to next
 decb
 bne cmpnam
 ldd 0,u found it, get fdn
 bra load go load uniflex
nxtent ldx entrys
 leax -1,x decrement count
 stx entrys end of directory?
 beq noboot error if so
 leau 16,u point to next entry
 cmpu #buffer+512 past current block?
 bne lookup check entry if not
 bra read1 else, get another block

* Load UniFLEX

load bsr fdnblk read in uniflex fdn
 ldx mapptr point to fdn map
 leax 13*3,x skip map
 ldd ,x++ copy fdn date
 std btdate
 ldd ,x++
 std btdate+2
 bsr rdblk read 1st block of the file
 bne noboot exit if error
 ldd bhxfr,u get transfer address
 std xfradr save it
 leau BHDSIZ,u skip binary file header
getrc1 bsr getchr get record length in x
 tfr b,a
 bsr getchr
 pshs d terminator?
 ldx ,s++
 beq done start uniflex if so
 bsr getchr get load address in y
 tfr b,a
 bsr getchr
 tfr d,y
getrc2 bsr getchr get a data byte
 stb 0,y+ put in memory
 leax -1,x decrement the count
 bne getrc2 loop if not end of record
 bra getrc1 else, get next record

* Uniflex is loaded, begin execution

done ldu $5002 boot date vector
 ldd btdate copy boot date vector
 std ,u++
 ldd btdate+2
 std ,u++
 jmp [xfradr] jump to transfer address

* Divide contents of D by 8

divby8 lsra
 rorb
 lsra
 rorb
 lsra
 rorb
 rts

* Get single character from binary file

getchr cmpu #buffer+512 more data in buffer?
 bne getch2 skip if so
 pshs a,x,y
 bsr rdblk else, read another block
 puls a,x,y
 bne nbootx exit if error
getch2 ldb 0,u+ get character, advance ptr
 rts

* Uniflex file was not found

nbootx puls d fix stack
noboot rts return to monitor ROM

* Read fdn specified in D

fdnblk pshs d save fdn number
 addd #15 convert to block number
 bsr divby8
 bsr mread read a block
 puls d restore fdn number
 bne nbootx exit if error
 decb calculate buffer offset
 andb #$07
 lda #64
 mul offset=(fdn&7)*64
 addd #map
 tfr d,y fdn pointer in y
 addd #9 point to ffmap
 std mapptr save map pointer
 lda #10 get direct block count
 sta direct initialize indirect flag
 rts

* Read a block from file

rdblk tst direct a direct block?
 beq chgind change to indirect
 dec direct dec. direct count
 ldx mapptr get file map pointer
 ldd 1,x block address in d
 leax 3,x point to next
 stx mapptr
 bsr blkts convert block to trk & sct
 ldx #buffer setup buffer address
 bra xread read the sector

chgind ldx mapptr get file map pointer
 ldd 1,x address of indirect block
 bsr mread read block of indirects
 bne nbootx exit if error
 stu mapptr reset file map pointer
 lda #128 set new direct count
 sta direct
 bra rdblk now read data block

* Convert block number in D to track & sector

blkts clr sdslct assume side 0
 tst dnsity check for double density
 bne dbkts skip if so
 pshs b
 bsr divby8 get track number in A
 tfr b,a
 puls b
 andb #$07 get sector number in B
 incb no sector 0
 tst dside double sided disk?
 beq blkts8 skip if not
 lsra correct the track number
 bcc blkts8 skip if on side 0
 addb #8 else fix sector number
 bra blkts6
dbkts pshs b
 lbsr divby8 divide block # by 16
 lsra
 rorb
 tfr b,a get track
 puls b
 andb #$f
dbkts4 incb no sector 0
 tst dside double sided?
 beq blkts8 skip if not
 lsra correct the track number
 bcc blkts8 skip if on side 0
 addb #16 else, fix sector number
blkts6 inc sdslct show side #1
blkts8 rts

* Read the specified map block

mread bsr blkts convert block to trk & sct
 ldx #map address of buffer for block

****************************************************

* read a single sector

xread      stb     SEC1797             set sector
           leau    0,x                 save buffer start
           cmpa    TRK1797             check new track
           beq     seek4
           sta     DAT1797             setup wd reg
           lbsr    del                 delay
           lda     #skcmnd             setup command
           sta     COM1797             issue command
           lbsr    del                 delay
seek4      bsr     xwait
* select proper side and density
           ldb     #(fdmotor+hltogg+fdsel0+P09229)  def to side 0 drive 0
seek6      tst     dnsity              see if double density
           bne     seek8               skip if so
           orb     #(fdsingden)        set single density
seek8
           stb     ORA29               do select
config     lda     #rdcmnd             setup command
           tst     sdslct              side 1?
           beq     leave0
           ora     #02                 set side 1 bit in read command
leave0
           sta     COM1797
           bsr     del
*   Command is fired off. Loop for data or errors
           pshs    dp                  retain the dir page register
           lda     #$E8                set dp for disk controller
           tfr     a,dp
           setdp   $E8                 tell the assembler also
           ldy     #seclen             set for 512 byte sector
fread      lda     ORB29               poll the funny status latch
           bmi     ddrdata             branch if drq bit is set
           beq     fread               loop if busy but no drq
           bra     fakethru            exit if no longer busy

ddrdata    lda     DAT1797             load the fd data register
           sta     0,x+                and store in the buffer
           leay    -1,y                decrement the byte count
           bne     fread               and loop if not finished
           bra     fakethru            terminate if finished

fakethru   puls    dp                  get the map stuff back
           setdp   $00
           ldb     COM1797             get the ending status
           bitb    #$FC                mask certain errors
           rts                         return


* xwait

xwait      ldb     COM1797             get status
           bitb    #busy               check if busy
           bne     xwait
xwait2     rts                         return

* delay

del        lda     #$20
del2       deca
           bne     del2
           rts

****************************************************


* filename for booting

btname fcc 'uniflex'
 fcb 0,0,0,0,0,0,0

 if (*-uboot)>512
 err Bootstrap Overflow!
 else
 rzb 512-(*-uboot)
 endif

 end
