**    Heres a little utility that I have just made.
**    I thought what I wanted was on a fish disk but that program
**    only saved dumps of boot blocks into files that disassemblers can
**    read. So I decided to write one myself. Here it is
**    The command to use on this is
**    FileBootBlock df?: filename
**    there must be only one space between the drive specifier of your
**    filename will end up starting with spaces
**    It will read the blocks 0 and 1 of the drive given and save it as
**    a program file that can be run (heaven forbid) or disassembled
**    by programs like DIS and DSM
**    The only modifying it does is the the first 2 bytes of the block.
**    As all program file must start with a valid instruction I have
**    changed the first 2 bytes from 'DO' to $600A. This makes it into the
**    instruction BRA.S *+$C which will get to the start of the proper code

**    Have fun

**    John Veldthuis
**    21 Ngatai Street
**    Manaia, Taranaki
**    New Zealand
**    22 November 1988
**    Placed into the Public domain on this date


   include  "exec/types.i"
   include  "intuition/intuition.i"
   include  "devices/trackdisk.i"
   include  "exec/memory.i"
   include  "libraries/dosextens.i"

   xref     _LVOOpenLibrary
   xref     _LVOCloseLibrary
   xref     _LVODoIO
   xref     _LVOOpenDevice
   xref     _LVOCloseDevice

   xref     _LVOAllocEntry
   xref     _LVOFreeEntry
   xref     _LVOOpen
   xref     _LVOClose
   xref     _LVOWrite
   xref     _LVOAllocSignal
   xref     _LVOFreeSignal

Offsets     macro
\1          equ   soffset
soffset     set   soffset+\2
            endm
soffset     set   0

            Offsets  dosbase,4
            Offsets  execbase,4
            Offsets  filehandle,4
            Offsets  buffer,4
            Offsets  port,4
            Offsets  filename,4
            Offsets  diskreq,4
            Offsets  task,4
            Offsets  mementry,4
            Offsets  unit,4
            Offsets  stdout,4


Start:
      lea      BASE(pc),a5
      move.l   4,a6
      move.l   a6,execbase(a5)
      movem.l  d0/a0,-(sp)
      move.l   $114(a6),a0           ;find our task
      move.l   a0,task(a5)
      move.l   pr_COS(a0),stdout(a5) ;save output stream for messages
      moveq.l  #33,d0                ;version 33 or greater
      lea      DosLib(pc),a1
      jsr      _LVOOpenLibrary(a6)   ;open dos.library
      movem.l  (sp)+,d1/a0
      tst.l    d0
      bne.s    Lib1
NoLib move.l   #20,d0                ;no library, indicate error and stop
      rts
Lib1  move.l   d0,dosbase(a5)
      moveq    #0,d0
      move.b   d0,-1(a0,d1.w)        ;zero end of Command line
1$    move.b   (a0)+,d0
      beq      CLIErr
      and.b    #%11011111,d0         ;change to uppercase
      cmp.b    #'D',d0               ;look for the D in DF?:
      bne.s    1$
      move.b   (a0)+,d0              ;dummy read to skip the F
      move.b   (a0)+,d0              ;get unit number
      sub.b    #'0',d0               ;make into a real number
      ext.w    d0                    ;sign extend to a word
      ext.l    d0                    ;sign extend to a long
      move.l   d0,unit(a5)           ;save unit number
2$    move.b   (a0)+,d0              ;search for space
      cmp.b    #' ',d0
      bne.s    2$
      move.l   a0,filename(a5)       ;save address of filename
      lea      Mem(pc),a0
      jsr      _LVOAllocEntry(a6)    ;allocate all memory in one go
      btst     #31,d0
      bne      MemErr                ;if bit 31 set then error getting mem
      move.l   d0,mementry(a5)       ;save for release
      move.l   d0,a0
      add.w    #Mem1-Mem,a0
      move.l   (a0),buffer(a5)       ;save address of read/write buffer
      bsr      CreatePort            ;create a reply port
      tst.l    d0
      beq      PError                ;no message port
      move.l   d0,d3
      move.l   d0,port(a5)           ;save for closing later
      move.l   mementry(a5),a0
      add.w    #Mem2-Mem,a0
      move.l   (a0),a0               ;make an IORequest block
      move.b   #NT_MESSAGE,LN_TYPE(a0)
      move.w   #IOSTD_SIZE,MN_LENGTH(a0)
      move.l   d3,MN_REPLYPORT(a0)
      move.l   a0,diskreq(a5)        ;save IO block address
      move.l   unit(a5),d0
      lea      TrackName(pc),a0
      move.l   diskreq(a5),a1
      moveq.l  #0,d1
      jsr      _LVOOpenDevice(a6)    ;open trackdisk on unit
      tst.l    d0
      bgt      TErr                  ;won't open, display error
      move.l   diskreq(a5),a1
      move.w   #CMD_READ,IO_COMMAND(a1)
      move.l   buffer(a5),IO_DATA(a1)
      move.l   #1024,IO_LENGTH(a1)
      move.l   #0,IO_OFFSET(a1)
      jsr      _LVODoIO(a6)          ;read boot block into buffer
      move.l   diskreq(a5),a1
      move.w   #TD_MOTOR,IO_COMMAND(a1)
      move.l   #0,IO_LENGTH(a1)
      jsr      _LVODoIO(a6)          ;turn motor off
      move.l   diskreq(a5),a1
      move.b   IO_ERROR(a1),d3       ;see what error there was
      jsr      _LVOCloseDevice(a6)   ;close trackdisk down
      cmp.b    #19,d3
      bgt      ReadErr               ;if an error display error
      move.l   buffer(a5),a0
      move.w   #$600A,(a0)           ;change first to bytes to BRA.S  *+$C
                                     ;so as not to upset relative addresses
      move.l   dosbase(a5),a6        ;get dosbase
      move.l   filename(a5),d1
      move.l   #MODE_NEWFILE,d2
      jsr      _LVOOpen(a6)          ;open file that bootblock goes in
      tst.l    d0
      beq      OpenErr               ;didn't open for some reason
      move.l   d0,filehandle(a5)     ;save for closing
      lea      table(pc),a0          ;get first part of file
      move.l   a0,d2                 ;used to create a program file
      move.l   d0,d1                 ;filehandle into d1
      moveq    #32,d3                ;length of numbers
      jsr      _LVOWrite(a6)
      cmp.l    #32,d0
      bne      WriteErr
      move.l   buffer(a5),d2
      move.l   filehandle(a5),d1
      move.l   #1024,d3
      jsr      _LVOWrite(a6)         ;write out rest of block to file
      cmp.l    #1024,d0              ;see if it all got written out
      bne      WriteErr
      move.l   filehandle(a5),d1
      lea      hunkend(pc),a0
      move.l   a0,d2
      moveq    #4,d3
      jsr      _LVOWrite(a6)         ;write last bit of file
      cmp.l    #4,d0
      bne.s    WriteErr
Fin   move.l   filehandle(a5),d1
      tst.l    d1
      beq.s    1$
      jsr      _LVOClose(a6)         ;close file if it opened
1$    move.l   execbase(a5),a6
      move.l   port(a5),d0
      tst.l    d0
      beq.s    2$
      move.l   d0,a1
      bsr      DeletePort            ;delete port if one got made
2$    move.l   mementry(a5),d0
      tst.l    d0
      beq.s    3$
      move.l   d0,a0
      jsr      _LVOFreeEntry(a6)     ;freememory if any got allocated
3$    move.l   dosbase(a5),a1
      jsr      _LVOCloseLibrary(a6)  ;close dos.library
      rts


MemErr:
      lea      MemMess(pc),a0
      move.l   a0,d2
      moveq    #47,d3
      bra.s    Err
Error:
CLIErr:
      lea      CLIMess(pc),a0
      move.l   a0,d2
      moveq    #36,d3
      bra.s    Err
ReadErr:
      lea      ReadMess(pc),a0
      move.l   a0,d2
      moveq    #36,d3
      bra.s    Err
WriteErr:
      lea      WriteMess(pc),a0
      move.l   a0,d2
      moveq    #28,d3
      bra.s    Err
OpenErr:
      lea      OpenMess(pc),a0
      move.l   a0,d2
      moveq    #25,d3
      bra.s    Err
PError:
      lea      PMess(pc),a0
      move.l   a0,d2
      moveq    #41,d3
      bra.s    Err
TErr
      lea      TMess(pc),a0
      move.l   a0,d2
      moveq    #39,d3
Err   move.l   stdout(a5),d1
      tst.l    d1
      beq      Fin               ;if no output stream
      move.l   dosbase(a5),a6
      jsr      _LVOWrite(a6)
      bra      Fin

CreatePort:
      move.l   a2,-(a7)
      move.l   mementry(a5),a2
      add.w    #Mem3-Mem,a2
      move.l   (a2),a2
      moveq    #-1,d0
      jsr      _LVOAllocSignal(a6)
      moveq    #-1,d1
      cmp.l    d0,d1   ;-1 indicates bad signal
      bne.s    cp_sigok
      move.l   (a7)+,a2
      moveq    #0,d0        ;otherwise indicate no port
      rts
cp_sigok:
      move.b   d0,MP_SIGBIT(a2)
      move.b   #PA_SIGNAL,MP_FLAGS(a2)
      move.b   #NT_MSGPORT,LN_TYPE(a2)
      clr.b    LN_PRI(a2)
      move.l   task(a5),d0
      move.l   d0,MP_SIGTASK(a2)
      lea.l    MP_MSGLIST(a2),a0  ;Point to list header
      NEWLIST  a0      ;Init new list macro
      move.l   a2,d0
      move.l   (a7)+,a2   ;cc's NOT affected
      rts

DeletePort:
      moveq    #-1,d0
      move.b   d0,LN_TYPE(a1)
      move.l   d0,MP_MSGLIST+LH_HEAD(a1)
      moveq    #0,d0
      move.b   MP_SIGBIT(a1),d0
      jsr      _LVOFreeSignal(a6)
      rts

table:
      dc.l     $3f3        ;Hunk_Header
      dc.l     0           ;no Hunk_Name
      dc.l     1           ;size of hunk table
      dc.l     0           ;first hunk
      dc.l     0           ;last hunk
      dc.l     256         ;number of longwords in hunk
      dc.l     $3e9        ;Hunk_Code
      dc.l     256         ;number of longwords in hunk

hunkend
      dc.l     $3f2        ;hunk end

BASE:
Dosbase     dc.l  0
Execbase    dc.l  0
Filehandle  dc.l  0
Buffer      dc.l  0
Port        dc.l  0
FileName    dc.l  0
DiskReq     dc.l  0
Task        dc.l  0
MemEntry    dc.l  0
Unit        dc.l  0
Stdout      dc.l  0

Mem         ds.b  LN_SIZE
            dc.w  3
Mem1        dc.l  MEMF_CHIP!MEMF_CLEAR
            dc.l  1024
Mem2        dc.l  MEMF_PUBLIC!MEMF_CLEAR
            dc.l  IOSTD_SIZE
Mem3        dc.l  MEMF_PUBLIC!MEMF_CLEAR
            dc.l  MP_SIZE

DosLib      dc.b  'dos.library',0
TrackName   dc.b  'trackdisk.device',0
MemMess     dc.b  'Not enough Memory to allocate required buffers',10
CLIMess     dc.b  'Usage:  FileBootBlock df?: filename',10
ReadMess    dc.b  'Disk Error while reading Boot Block',10
WriteMess   dc.b  'Error while writing to file',10
OpenMess    dc.b  'Error while opening file',10
PMess       dc.b  'Couldn''t create message port for disk IO',10
TMess       dc.b  'Couldn''t get access to specified drive',10

      end
