*************************************************************
;                                                           *
; This is Public Domain !!! Do with it what you like !!!!!!!!
;                                                           *
*************************************************************
; SaveKick.s  speichert den Kickstart Speicher ab $F80000
;             auf Disk DF0:
;                      ~~~~
;             ==> Kickstart Disk fuer A1000
;
;             Autor :
;                          Sascha Groening
;                          Blaustr.:    13
;                          8360 Deggendorf
;                          West-Germany
;
;
;
; ACHTUNG :   alle Daten auf der Disk werden ueberschrieben
;
;             benoetigt $40000+$200 ( =262656) Byte freies Chip-Memory
;                                                          ----
;             ==> Prg am besten auf zukuenftiger Kickstartdisk
;                 Bootfaehig installieren
;
;                 ==> install df0:
;                     copy SaveKick df0:
;                     s:startup-sequence = "SaveKick"
;
; Programm wurde fuer den   A68K  Public Domain Assembler
;                           BLINK Public Domain Linker       geschrieben
;
;       (A68K :Fish Disk Nr.:110 )
;       (BLINK:Fish Disk Nr.: 40 )
;
;
; Assemblieren :     A68K SaveKick.s
;                    BLINK SaveKick.o
;
;
; Nutzen :
;
; SaveKick erzeugt Kickstart Disk fuer Amiga 1000 indem es den Kickstart
;          Speicher auf Disk schreibt und in den Bootblock die
;          Kennung 'KICK' eintraegt.
;
;          ==> A1000 Besitzer koennen sich von jedem A500 mit Kickstart Rom
;              eine Kickstart Disk erzeugen lassen .
;
;          ACHTUNG: Copyright Bestimmungen beachten !!!!!
;



SysBase   equ 4
AllocMem equ -198
FreeMem equ -210
FindTask equ -294
AllocSignal equ -330
FreeSignal equ -336
AddPort equ -354
RemPort equ -360
OldOpenLibrary equ -408
CloseLibrary equ -414
OpenDevice equ -444
CloseDevice equ -450
DoIO equ -456


Open equ -30
Close equ -36
Read equ -42
Write equ -48
Input equ -54
Output equ -60


MODE_READWRITE equ 1004
MODE_OLDFILE   equ 1005
MODE_NEWFILE   equ 1006
MODE_READONLY  equ MODE_OLDFILE

MEMF_PUBLIC  equ $1
MEMF_CHIP    equ $2
MEMF_FAST    equ $4
MEMF_CLEAR   equ $10000
MEMF_LARGEST equ $20000


CALLEXEC macro
         movea.l SysBase,a6
         jsr    \1(a6)
         endm

CALLDOS  macro
         movea.l DOSBase,a6
         jsr    \1(a6)
         endm

buffersize   equ $00000200

;
; *********** MainProg **********


_main
    move.l a7,stapel

    lea.l dosname,a1
    CALLEXEC OldOpenLibrary        ;Open DOSLibrary
    move.l d0,DOSBase
    beq    fini

    CALLDOS Output         ;LVOOutput
    move.l d0,OutHandle

    CALLDOS Input
    move.l d0,InHandle

    move.l OutHandle,d1
    move.l #Message1,d2
    move.l #len4,d3
    CALLDOS Write

    move.l InHandle,d1
    move.l #Message1,d2  ;Warte auf Taste
    moveq.l #1,d3
    CALLDOS Read


;    movem.l d0-d2/a0-a1,-(a7)
;    move.l #_main,d2
;    lea.l  hbuf,a0
;    move.b #10,8(a0)
;    bsr    hexasc
;    move.l OutHandle,d1
;    move.l #hbuf,d2
;    moveq.l #9,d3
;    CALLDOS Write
;    movem.l (a7)+,d0-d2/a0-a1

;
;  SIGNAL besetzen
;
    moveq.l #-1,d0
    CALLEXEC AllocSignal        ;AllocSignal
    move.b d0,SIGNAL
    bmi    SignalFehler    ;D0=-1 =>Fehler
;
;   Msg-Port Struktur initialisieren
;
    move.b d0,mp_SigBit
    suba.l  a1,a1
    CALLEXEC FindTask         ;Find own Task
    move.l d0,mp_SigTask
    lea.l  MsgPort,a1
    CALLEXEC AddPort          ;AddPort
;
;**** Speicher allokieren ***
;
    move.l #buffersize,d0             ;groesse des Speichers
    move.l #MEMF_CHIP!MEMF_CLEAR,d1   ;allokierten Speicher mit $00 fuellen
    CALLEXEC AllocMem

    move.l d0,DATA   ; Buffer fuer Bootblock
    beq    nomem

    move.l #$40000,d0     ;groesse des KickstartROM/RAMs
    move.l #MEMF_CHIP!MEMF_CLEAR,d1      ;allokierten Speicher mit $00 fuellen
    CALLEXEC AllocMem

    move.l d0,kickbuffer   ; Buffer fuer Bootblock
    beq    nomem


;
; TrackDiskDevice oeffnen
;

    lea.l  TD_Name,a0
    lea.l  IOExtReq,a1
    clr.l  d0
    clr.l  d1
    CALLEXEC OpenDevice         ;OpenDevice
    tst.l  d0
    bne    LeseFehler

    lea.l MsgPort,a1
    move.l a1,mn_ReplyPort2

***** MAIN



    bsr   installBB   ;installiere Block 0 mit 'KICK'-string
    bsr   copykick    ;kopiere Kickstart Speicher ins CHIP Memory
    bsr   savekick    ;kopiere diesen Speicher auf Disk
                      ;(direkt geht's nicht ,da das trackdisk.device nur
                      ; auf das CHIP-Memory zugreifen kann !!)

    bsr   motoroff    ;Motor abstellen





CloseAll
closedev
    movea.l stapel,a7
    lea.l  IOExtReq,a1
    CALLEXEC  CloseDevice        ;CloseDevice

memfree1
    tst.l   kickbuffer
    beq     memfree2
    movea.l kickbuffer,a1  ;Speicher wieder freigeben
    move.l  #$40000,d0
    CALLEXEC  FreeMem

memfree2
    movea.l stapel,a7
    movea.l DATA,a1
    move.l  #buffersize,d0
    CALLEXEC  FreeMem

ClosePort
    movea.l stapel,a7
    lea.l  MsgPort,a1
    CALLEXEC RemPort        ;RemPort

FreeSig
    movea.l stapel,a7
    clr.l   d0
    move.b  SIGNAL,d0
    CALLEXEC FreeSignal        ;FreeSignal

closedos
    movea.l DOSBase,a1
    CALLEXEC CloseLibrary        ;CloseLibrary
    clr.l  d0
fini rts



************************
***** SubProgs
************************



installBB
    movea.l DATA,A0
    move.l #$4B49434B,(A0)+

installBB2
    move.l DATA,IO_DATA2    ;DATA
    move.l #0,IO_OFFSET2
    move.l #$00000200,IO_LENGTH2
    move.w #3,IO_COMMAND2        ;IO_COMMAND2 = FORMATIEREN
    bra    SchreibeBlock


SchreibeBlock
    lea.l  IOExtReq,a1
    CALLEXEC DoIO           ;Kommando ausfuehren
    move.b IO_ERROR2,d0
    bne    LeseFehler
    lea.l  IOExtReq,a1
    move.w #4,IO_COMMAND2
    CALLEXEC DoIO
    rts

copykick
    move.l #$FFFF,d1    ;(Laenge des Kickstart Speichers in LWords)-1
    move.l #$F80000,a0  ;Anfang des Kickstart Speichers
    move.l kickbuffer,a1 ;Kopierziel

loop3
    move.l (a0)+,(a1)+
    dbra   d1,loop3

    rts

;
; Speichert $40000 Bytes von kickbuffer nach Block 1 bis x
;

savekick
    move.l kickbuffer,IO_DATA2
    move.l #512,IO_OFFSET2      ;Block 1
    move.l #$40000,IO_LENGTH2
    move.w #3,IO_COMMAND2        ;IO_COMMAND2 = CMD_WRITE
    bra    SchreibeBlock

;
; Schaltet den Motor ab
;

motoroff
    move.w #$0009,IO_COMMAND2  ;Motorstatus aendern
    move.l #$0000,IO_LENGTH2   ;0==> Motor abschalten

    lea.l  IOExtReq,a1
    CALLEXEC DoIO           ;Kommando ausfuehren
    rts


;
; Konvertiere d2.l in ASCII-String ab (a0)
;

hexasc
    moveq   #7,d0                       ;8 Nibble (=Halbbyte) wandeln
    adda.l  #8,a0                       ;Pos der letzten Stelle im Buffer+1
loop5
    moveq   #15,d1                      ;
    and.l   d2,d1                       ;1 Nibble isolieren
    asr.l   #4,d2                       ;naechstes Nibble an 1.Pos
    addi.b  #48,d1                      ;isol. Nibble+48=Zahl in ASCII
    cmp.b   #57,d1                      ;war Zahl >9 ?
    bls     cont4
    addq.l  #7,d1                       ;wenn ja noch 7 dazu ==> A-F
cont4
    move.b  d1,-(a0)                    ;in Buffer eintragen
    dbra    d0,loop5                    ;naechstes Nibble wandeln
    rts





SignalFehler
    move.l OutHandle,d1
    move.l #Fehler1,d2
    moveq.l #len1,d3
    CALLDOS Write     ;LVOWrite
    bra    closedos

LeseFehler
    move.l d0,d2
    lea.l  hbuf,a0
    move.b #10,8(a0)               ;LineFeed anfuegen
    bsr    hexasc
    move.l OutHandle,d1
    move.l #Fehler2,d2     ;FehlerMeldung ausgeben
    moveq.l #len2,d3
    CALLDOS Write

    move.l OutHandle,d1
    move.l #hbuf,d2
    moveq.l #9,d3
    CALLDOS Write          ;Fehlercode ausgeben

    bsr   motoroff
    bra   CloseAll


nomem
    move.l OutHandle,d1
    move.l #Fehler3,d2
    moveq.l #len3,d3
    CALLDOS Write     ;LVOWrite
    bra    memfree1


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

 DATA constants

            cnop 0,2
Name        dc.b 'SaveKickPort',0    ;Name des Msg-Ports
            cnop 0,2
MsgPort
ln_Succ     dc.l 0  ;Message-Port Struktur
            cnop 0,2
ln_Pred     dc.l 0
ln_Type     dc.b 4
ln_Pri      dc.b 0
ln_Name     dc.l Name
mp_Flags    dc.b 0
mp_SigBit   dc.b 0
mp_SigTask  dc.l 0
lh_Head     dc.l 0
lh_Tail     dc.l 0
lh_TailPred dc.l 0
lh_Type     dc.b 0
            dc.b 0  ;gerade Adr schaffen
            cnop 0,2
IOExtReq
ln_Succ2    dc.l 0
            cnop 0,2
ln_Pred2    dc.l 0
ln_Type2    dc.b 5
ln_Pri2     dc.b 0
ln_Name2    dc.l Name2
mn_ReplyPort2   dc.l 0
mn_Length2  dc.w $0038
IO_DEVICE2  dc.l 0
IO_UNIT2    dc.l 0
IO_COMMAND2 dc.w 0
IO_FLAGS2   dc.b 0
IO_ERROR2   dc.b 0
IO_ACTUAL2  dc.l 0
IO_LENGTH2  dc.l $0200
IO_DATA2    dc.l 0
IO_OFFSET2  dc.l 0
IOTD_COUNT  dc.l 0
IOTD_SECLABEL dc.l 0

Name2       dc.b 'SaveKickMsg',0,0
            cnop 0,2
Fehler1     dc.b 'SigBitFehler',10       ;der Stern (*) ist der Location
len1        equ  *-Fehler1            ;Counter des Assembler (LC)
            cnop 0,2                  ;er enthaelt im Gegensatz zum
Fehler2     dc.b 'Read/Write error:'        ;Program Counter (PC) der CPU
len2        equ  *-Fehler2            ;die relative Adr (relativ zum
            cnop 0,2                  ;Programmanfang) der aktuellen
Fehler3     dc.b 'not enough Memory  !',10  ;Zeile !!!
len3        equ  *-Fehler3
            cnop 0,2
Message1    dc.b 'SaveKick   by Sascha Groening',10
            dc.b 'This is Public Domain ! Do with it what you like !',10
            dc.b 'Please insert disk in DF0: to copy Kickstart-Memory on',10
            dc.b 'ATTENTION : this will erase all DATA on this Disk !!',10
            dc.b '            $40200 (=262656) Byte FREE Chip-Memory is needed !',10
            dc.b 'Press any key ...'
len4        equ  *-Message1
            cnop 0,2
dosname     dc.b 'dos.library',0
            cnop 0,2
TD_Name     dc.b 'trackdisk.device',0
            cnop 0,2

 BSS storage

SIGNAL      ds.l 1
DATA        ds.l 1
kickbuffer  ds.l 1
stapel      ds.l 1
DOSBase     ds.l 1
OutHandle   ds.l 1
InHandle    ds.l 1
hbuf        ds.l 3


            END



