*****************************************************************************
*                                                                           *
* Programma ....... FileBootBlock.asm                                       *
*                                                                           *
* Autore .......... John Veldthuis, New Zealand                             *
*                                                                           *
* Versione ........ 1.00i, 22 Novembre 1988, 29 Maggio 1990                 *
*                                                                           *
* Scopo ........... Trasformare bootblock in file e viceversa               *
*                                                                           *
* Software ........ Devpac HiSoft V2.14                                     *
*                                                                           *
* Hardware ........ Amiga 500/1000/2000/2500, Kickstart & Workbench 1.2/1.3 *
*                                                                           *
* Note ............ Traduzione ed adattamento per EAD di Luigi Callegari    *
*                                                                           *
*****************************************************************************

          incdir   "dh1:Includedevpac/"	; Modificare per propria directory
          
          include  "exec/types.i"
          include  "intuition/intuition.i"
          include  "devices/trackdisk.i"
          include  "exec/memory.i"
          include  "libraries/dosextens.i"
          include  "libraries/dos_lib.i"
          include  "intuition/intuition_lib.i"
          include  "exec/exec_lib.i"

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.w,a6
          move.l   a6,execbase(a5)
          movem.l  d0/a0,-(sp)
          move.l   $114(a6),a0           ; Trova questo task
          move.l   a0,task(a5)
          move.l   pr_COS(a0),stdout(a5) ; Salva stream di output per mess.
          moveq.l  #33,d0                ; Almeno Kickstart V1.2
          lea      DosLib(pc),a1
          jsr      _LVOOpenLibrary(a6)   ; Apre DOS.library
          movem.l  (sp)+,d1/a0
          tst.l    d0
          bne.s    Lib1
NoLib     moveq.l   #20,d0               ; Manca libreria, fermati e segnala
          rts                            ; Torna a casa, Lassie!
Lib1      move.l   d0,dosbase(a5)
          moveq    #0,d0
          move.b   d0,-1(a0,d1.w)        ; Marca fine della linea Shell
1$        move.b   (a0)+,d0
          beq      CLIErr
          and.b    #%11011111,d0         ; Trasforma in maiuscolo
          cmp.b    #'D',d0               ; Cerca la D in DFn
          bne.s    1$
          move.b   (a0)+,d0              ; Fittizio, per saltare la F
          move.b   (a0)+,d0              ; Legge il numero di unità
          sub.b    #'0',d0               ; Trasforma in numero reale
          ext.w    d0                    ; Estende a dimensione parola
          ext.l    d0                    ; Estende a dimensione longword
          move.l   d0,unit(a5)           ; Salva numero di unita'
2$        move.b   (a0)+,d0              ; Cerca la spaziatura
          cmp.b    #' ',d0
          bne.s    2$
          move.l   a0,filename(a5)       ; Salva indirizzo nomefile
          lea      Mem(pc),a0
          jsr      _LVOAllocEntry(a6)    ; Alloca tutta la memoria in una volta
          btst     #31,d0
          bne      MemErr                ; Bit 31 disattivo, errata memoria
          move.l   d0,mementry(a5)       ; Salva per successivo rilascio
          move.l   d0,a0
          add.w    #Mem1-Mem,a0
          move.l   (a0),buffer(a5)       ; Salva indirizzo buffer di I/O
          bsr      CreatePort            ; Crea porta di risposta
          tst.l    d0
          beq      PError                ; Nessuna porta di risposta
          move.l   d0,d3
          move.l   d0,port(a5)           ; Salva per successiva chiusura
          move.l   mementry(a5),a0
          add.w    #Mem2-Mem,a0
          move.l   (a0),a0               ; Crea un blocco IORequest
          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)        ; Salva indirizzo blocco IO
          move.l   unit(a5),d0
          lea      TrackName(pc),a0
          move.l   diskreq(a5),a1
          moveq.l  #0,d1
          jsr      _LVOOpenDevice(a6)    ; Apre trackdisk su unità
          tst.l    d0
          bgt      TErr                  ; Non s'apre, mostra errore
          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)          ; Legge bootblock nel buffer
          move.l   diskreq(a5),a1
          move.w   #TD_MOTOR,IO_COMMAND(a1)
          move.l   #0,IO_LENGTH(a1)
          jsr      _LVODoIO(a6)          ; Spegne il motore
          move.l   diskreq(a5),a1
          move.b   IO_ERROR(a1),d3       ; Controlla se c'era errore
          jsr      _LVOCloseDevice(a6)   ; Chiude il trackdisk.device
          cmp.b    #19,d3
          bgt      ReadErr               ; Se errore, mostralo
          move.l   buffer(a5),a0
          move.w   #$600A,(a0)           ; Cambia primo bytes in BRA.s *+$C
                                         ; per non alterare indirizzo relativo
          move.l   dosbase(a5),a6        ; Legge DOSBase
          move.l   filename(a5),d1
          move.l   #MODE_NEWFILE,d2
          jsr      _LVOOpen(a6)          ; Apre file dove mettere bootblock
          tst.l    d0
          beq      OpenErr               ; Non s'è aperto per qualche motivo
          move.l   d0,filehandle(a5)     ; Salva handler per la chiusura
          lea      table(pc),a0          ; Legge prima parte del file
          move.l   a0,d2                 ; Usato per creare un file di programma
          move.l   d0,d1                 ; Filehandle in D1
          moveq    #32,d3                ; Lunghezza dei numeri
          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)         ; Scrive il resto del file
          cmp.l    #1024,d0              ; Controllando se tutto OK
          bne.s    WriteErr

          move.l   filehandle(a5),d1
          lea      hunkend(pc),a0
          move.l   a0,d2
          moveq    #4,d3
          jsr      _LVOWrite(a6)         ; Scvrive ultimo pezzetto del file
          cmp.l    #4,d0
          bne.s    WriteErr
Fin       move.l   filehandle(a5),d1
          tst.l    d1
          beq.s    1$
          jsr      _LVOClose(a6)         ; Chiude fileaperto

1$        move.l   execbase(a5),a6
          move.l   port(a5),d0
          tst.l    d0
          beq.s    2$
          move.l   d0,a1
          bsr      DeletePort            ; Cancella eventuale porta
2$        move.l   mementry(a5),d0
          tst.l    d0
          beq.s    3$
          move.l   d0,a0
          jsr      _LVOFreeEntry(a6)     ; Cancella eventuali allocazioni
3$        move.l   dosbase(a5),a1
          jsr      _LVOCloseLibrary(a6)  ; Chiude 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               ; Se manca stream di output
          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 indica "segnale scorretto"
          bne.s    cp_sigok
          move.l   (a7)+,a2
          moveq    #0,d0        ; Indica altrimenti "nessuna porta"
          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  ; Punta a header di lista
          NEWLIST  a0         ; Inizializza nuova lista macro
          move.l   a2,d0
          move.l   (a7)+,a2   ; cc's NOT influenzato
          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           ; Nessun Hunk_Name
          dc.l     1           ; Dimensione Hunk table
          dc.l     0           ; Primo hunk
          dc.l     0           ; Ultimo hunk
          dc.l     256         ; Numero di longwords in hunk
          dc.l     $3e9        ; Hunk_Code
          dc.l     256         ; Numero di longword nell'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
