; ***************************************************************
; *                Addperreset 1.2 (13.12.89)                   *
; *                                                             *
; * Bindet FastRam waehrend des Resets ein.                     *
; * Nur ab Kickstart V1.3 !!!!!!!!                              *
; *                                                             *
; *          Written by :  Jörg von Frantzius                   *
; *            Greetings & Thanks to Albert !                   *
; ***************************************************************
; Problemlos zu Assemblieren mit Profimat.
; Wer im Besitz der Original-Commodore Includes ist, kann es sich
; sparen die folgenden Struktur-Offsets einzutippen. Stattdessen
; ist dann folgendes einzutippen (fuer die Besitzer der Includes):
;
;       INCLUDE "includes/exec/memory.i"
;       INCLUDE "includes/exec/resident.i"

; Struktur-Offsets: die benoetigten Offsets aus obigen Includes

LN_NAME       = $0A            ; Node
LN_PRED       = $04            ; (Vorgängerzeiger)

NT_MEMORY     = $0A            ; NodeType

ML_NUMENTRIES = $0E            ; MemoryList
ML_ME         = $10

ME_ADDR       = 0              ; MemEntry
ME_LENGTH     = $04

RT_MATCHTAG   = $02            ; Resident
RT_ENDSKIP    = $06
RT_NAME       = $0E
RT_IDSTRING   = $12
RT_INIT       = $16

; Library-Offsets
OpenLibrary     equ    -552            ; exec
SumKickData     equ    -612
Allocmem        equ    -198
AddMemList      equ    -618
KickMemPtr      equ    546             ; Pointer in ExecBase
KickTagPtr      equ    550
KickCheckSum    equ    554
Output          equ    -60             ; Dos
IsInteractive   equ    -216
Write           equ    -48


        move.l  4,a6                   ; ExecBase nach a6

        lea     dosname,a1             ; a1 auf Name zeigen lassen
        move.l  #34,d0
        jsr     OpenLibrary(a6)        ; Library oeffnen
        tst.l   d0                     ; war d0 = 0 ?
        bne     ok                     ; nein : ok, ist 1.3
        moveq.l #0,d0                  ; ja: Dos oeffnen,
        jsr     OpenLibrary(a6)        ; egal welche Version.
        move.l  d0,dosbase             ; dosbase retten
        moveq.l #2,d0                  ; 3. Text ausgeben: ..
        jsr     ausgabe                ; ..falsche Kick-Version
        moveq.l #0,d0
        rts                            ; beenden
ok:     move.l  d0,dosbase             ; dosbase retten

        lea     $200000,a0             ; moeglicher FastRam Anfang
        move.b  #%10101010,d1          ; irgendeinen Wert nach d1
suchen:
        move.b  (a0),d0                ; Byte nach d0 retten
        move.b  d1,(a0)                ; d1 in Test-Byte schreiben
        move.b  (a0),d2                ; Byte wieder lesen
        move.b  d0,(a0)                ; gerettetes Byte zurueck
        cmp.b   d1,d2                  ; geschriebenes=gelesenesByte ?
        beq     gefunden               ; ja -> FastRam gefunden
        add.l   #$fffff/4+1,a0         ; 256kB weiter gehen
        move.l  a0,d0                  ; a0 nach d0 wegen Flags
        cmp.l   #$a00000,d0            ; am Ende angekommen ?
        beq     nichtsda               ; ja->kein FastRam da, fertig
        bra     suchen                 ; nein: weitersuchen
nichtsda:
        moveq.l #1,d0                  ; 2. Text ausgeben lassen: ..
        jsr     ausgabe                ; .. kein FastMem vorhanden !
        rts
gefunden:
        move.l  a0,a3                  ; Basis von FastRam retten
        jsr     ende_suchen            ; Ende von FastRam suchen
        sub.l   a3,a0                  ; FastRamEnde - FastRamBasis ..
        move.l  a0,FastMemLength       ; .. ergibt FastRam-Laenge
        move.l  a3,FastMemBasis        ; Laenge+Basis fuer die Reset-
                                       ; -Routine speichern
        move.l  #$10002,d1             ; d1: CHIP+CLEAR fuer allocmem
        move.l  #Blockende-Block,d0    ; Laenge nach d0
        jsr     AllocMem(a6)           ; Speicher belegen
        tst.l   d0                     ; war d0 = 0 ?
        beq     raus                   ; ja : raus hier
        move.l  d0,Memory              ; Adresse retten

        move.l  d0,a1                  ; Zieladresse nach a1
        lea     block,a0               ; Ursprungsadresse nach a0
        move.l  #Blockende-Block-1,d0  ; Laenge nach d0
COPY:   move.b  (a0)+,(a1)+            ; ein Byte kopieren
        dbra    d0,copy                ; und nochmal das Ganze

        move.l  memory,d0              ; Adresse von Kopie nach d0
        move.l  memory,a0              ; Adresse von Kopie nach a0
        move.l  d0,rt_Matchtag(a0)             ; Matchtag  setzen
        add.l   #Resident_Name-Resident,d0     ; Zeiger auf Ende..
        move.l  d0,rt_EndSkip(a0)              ; .. von Resid. setzen
        move.l  d0,rt_Name(a0)                 ; zugleich Adr. von Name
        add.l   #Resident_Id-Resident_Name,d0  ; Zeiger auf Idstring ..
        move.l  d0,rt_IdString(a0)             ; .. setzen
        add.l   #Addmem-Resident_Id,d0         ; Zeiger auf  Routine ..
        move.l  d0,rt_Init(a0)                 ; .. setzen
        move.l  a0,d0                          ; Blockadr. nach d0
        add.l   #MemList-Block,a0              ; a0: MemList der Kopie
        move.l  a0,MList                       ; Zeiger retten
        move.l  d0,ml_me+me_Addr(a0)           ; in MemList Zeiger auf
                                               ; zu schuetzenden
                                               ; Speicherblock setzen.
        add.l   #NodeName-Resident,d0          ; Zeiger auf NodeName ..
        move.l  d0,ln_Name(a0)                 ; .. in MemList setzen
        move.l  memory,a0                      ; Adresse der Kopie ..
        move.l  memory,d0                      ; .. wieder nach a0 & d0
        add.l   #ResTab-Resident,a0            ; a0 -> ResTabelle
        move.l  d0,(a0)                        ; ResTab initialisieren
        move.l  a0,RList

;Memorylist und Resident Tabelle an evtl. vorhandene anhängen

        move.l  KickMemPtr(a6),a0              ;
        move.l  a0,d0                          ; wegen Flags
        bne     schon_belegt                   ; >0: bereits belegt
        move.l  MList,KickMemPtr(a0)           ; =0: selber belegen
        bra     TagStuff                       ; bei KickTag weiter
schon_belegt:
        move.l  (a0),d0                        ; ln_Succ holen
        beq     angekommen                     ; =0: letzte MemList
        move.l  (a0),a0                        ; <>0: bei der nächsten
        bra     schon_belegt                   ; MemList weitermachen
angekommen:
        move.l  MList,(a0)             ; ln_Succ belegen
        move.l  d0,ml_ln_pred          ; eigenen ln_Pred belegen...
                                       ; mit der letzten MemList
TagStuff:
        move.l  KickTagPtr(a6),d0      ; Zeiger auf Tabelle
        bne     Tag_belegt             ; <>0: bereits belegt
        move.l  RList,KickTagPtr(a6)   ; =0: selber belegen
        bra     fastfertig             ; bei Checksumme weitermachen
Tag_belegt:
        move.l  d0,a0                  ; KickTag nach a0
such_Hasso:
        move.l  (a0),d0                ; Listeneintrag nach d0
        move.l  (a0)+,d1               ; dito nach d1, und a0 inc.
        beq     null_gefunden          ; Endemarkierung gefunden
        and.l   #$80000000,d1          ; auf Bit 31 testen
        beq     such_Hasso             ; nicht gesetzt: weitersuchen
        move.l  d0,a0                  ; war gesetzt: ab Verkettung weiter
        bra     such_Hasso             ; weiter suchen
null_gefunden:                         ; wenn Endemark. gefunden
        move.l  RList,d2               ; Adr. der eigenen ResTab nach d2
        or.l    #$80000000,d2          ; Bit 31 setzen
        subq.l  #4,a0                  ; a0 dec, da ein Eintrag zu hoch
        move.l  d2,(a0)                ; Verkettungszeiger in bereits vor-
                                       ; handene ResTab eintragen
fastfertig:
        jsr     SumKickData(a6)        ; Checksum. der  Zeiger berechnen
        move.l  d0,KickCheckSum(a6)    ; Checksumme eintragen
; Checksumme fuer 16 Eintraege der Exec-Base berechnen
        moveq.l #0,d1                  ; Zielregister fuer Checksumme
        moveq.l #$16,d0                ; 16 Eintraege aus exec-base
        lea     34(a6),a0              ; ab dem 34. Eintrag
sum:
        add.w   (a0)+,d1               ; auf d1 drauaddieren
        dbra    d0,sum                 ; nochmal das Ganze
        not.w   d1                     ; aus Kickstart  (ab $fc043e)
        move.w  d1,82(a6)              ; exec-Checksum setzen

        moveq.l #0,d0                  ; 1. Text ausgeben lassen: ..
        jsr     ausgabe                ; .. alles ok.
raus:
        rts                            ; fertig !

ende_suchen:
        move.b  #%10101010,d1          ; irgendein Wert nach d1
suche_weiter:
        add.l   #$fffff/4+1,a0         ; einen 256kB Schritt weiter
        move.l  a0,d0                  ; a0 nach d0 wegen Flags
        cmp.l   #$a00000,d0            ; schon am Ende angekommen ?
        beq     ende_gefunden          ; ja : gefunden
        move.b  (a0),d0                ; Byte aus FastRam retten
        move.b  d1,(a0)                ; Test-Byte schreiben
        move.b  (a0),d2                ; Test-Byte wieder lesen
        move.b  d0,(a0)                ; gerettetes Byte zurueck
        cmp.b   d1,d2                  ; sind beide Test-Bytes gleich ?
        bne     ende_gefunden          ; nein: Ende von FastRam erreicht
        bra     suche_weiter           ; ja: immer noch FastRam
ende_gefunden:
        subq.l  #1,a0                  ; Zaehler auf letztes Byte ..
                                       ; .. von FastRam setzen
        rts

Memory: dc.l    0      ; gerettete Adresse von Speicherblock
MList:  dc.l    0      ; gerettete Adresse der Memory-List
RList:  dc.l    0      ; gerettete Adresse der Resident-Tabelle

ausgabe:
        move.l  d0,d6                  ; Ausgabe-Nummer retten
        move.l  dosbase,a6             ; dosbase nach a6
        jsr     Output(a6)             ; Ausgabe-handler holen
        move.l  d0,handler             ; handler retten
        move.l  d0,d1                  ; Handler nach d1
        jsr     IsInteractive(a6)      ; testen ob interactive
        tst.l   d0                     ; ist interaktiv ?
        beq     warnix                 ; nein: schluss machen
        move.l  dosbase,a6             ; dos wird gebraucht
        move.l  handler,d1             ; handler nach d1
        tst.l   d6                     ; war Ausgabe-Nr. <> 0 ?
        bne     nicht_gefunden         ; ja: 2. Text ausgeben
        move.l  #msg,d2                ; Adr. des 1. Text nach d2
        move.l  #msg_end-msg,d3        ; Laenge des Text nach d3
        jsr     Write(a6)              ; Text ausgeben
        rts                            ; zurueck
nicht_gefunden:
        cmp.l   #2,d6
        beq     version
        move.l  #msg2,d2               ; Adr. des 2. Text nach d2
        move.l  #msg2_end-msg2,d3      ; Laenge des 2. Text nach d3
        jsr     Write(a6)              ; 2. Text ausgeben
        rts
version:
        move.l  #msg3,d2               ; Adr. des 3. Text nach d2
        move.l  #msg3_end-msg3,d3      ; Laenge des 3. Text nach d3
        jsr     Write(a6)              ; ausgeben
warnix:
        rts                            ; zurueck

handler:dc.l    0
dosbase:dc.l    0

msg: dc.b    $a,"Das FastRam wird beim naechsten Reset eingebunden.",$a
     dc.b    $a,"Wenn FastRam nicht eingebunden werden soll : ",$a
     dc.b    "beim Reset linke Maustaste druecken !",$a,0
msg_end:
msg2:   dc.b    "Konnte kein FastRam finden !",$a,0
msg2_end:
msg3:   dc.b    "Funktioniert nur ab Kick 1.3 !",$a,0
msg3_end:
        even
dosname:dc.b    "dos.library",0
        even

Block:                 ; Anfang des zu kopierenden Blockes

Resident:
my_rt_MatchWord:   dc.w   $4afc        ; Kennung fuer Resident
my_rt_MatchTag:    dc.l   0            ; Zeiger auf Anfang
my_rt_EndSkip:     dc.l   0            ; Zeiger auf Ende der Struktur
my_rt_Flags:       dc.b   %00000001    ; Flags: auszufuehrendes Modul
my_rt_Version:     dc.b   33           ; Versionsnummer
my_rt_Type:        dc.b   0            ; Befehl (ist hier egal)
my_rt_pri:         dc.b   119          ; Prioritaet: nach ExecLib
my_rt_Name:        dc.l   0            ; Zeiger auf Modul-Name
my_rt_IdString:    dc.l   0            ; Zeiger auf Erklaerungs-string
my_rt_init:        dc.l   0            ; Zeiger auf Anfang von Prg-Code
Resident_Name:  dc.b   "Joergs-addmem-resident",0
                even
Resident_Id:    dc.b   "Linkt FastRam während des Resets in MemList ein",0
                even
End_of_Resident:

MemList:
ml_ln_Succ:     dc.l   0               ; Node-Eintraege fuer Liste
ml_ln_Pred:     dc.l   0               ;   "     "        "    "
ml_ln_type:     dc.b   10              ; Typ : Memory-Node
ml_ln_Pri:      dc.b   0               ; Prioritaet egal
ml_ln_Name:     dc.l   0               ; wird nachher eingetragen
My_ml_NumEntries:  dc.w   1            ; Anzahl Eintraege (fuer Bloecke)
ml_me_Addr:     dc.l   0               ; wird nachher eingetragen
ml_me_Length:   dc.l   Blockende-Block ; Laenge des Speicherblocks
NodeName:       dc.b   "FastMem-Node",0
End_of_MemList:
        even
ResTab:
        dc.l    0  ; hier wird die Adr. der Resident-Strktr eingetragen
        dc.l    0  ; die Tabelle MUSS mit 0 abgeschlossen werden

addmem:
        movem.l d0-d2/a0-a5,-(a7)      ; Register retten
        btst    #6,$bfe001             ; linke Maustaste gedrueckt ?
        beq     no_mem                 ; ja: raus hier
        move.l  4,a6                   ; exec-base nach a6
        move.l  FastMemLength(pc),d0   ; d0: Laenge des FastRam
        moveq.l #5,d1                  ; d1: Eigenschaft (FAST+PUBLIC)
        moveq.l #0,d2                  ; d2: Prioritaet (0 = Fast)
        move.l  FastMemBasis(pc),a0    ; a0: Beginn des FastRam
        lea     name(pc),a1            ; a1: Zeiger auf Name
; Folgende Funktion existiert offiziell erst ab Kick 1.3 !!
        jsr     AddMemList(a6)         ; FastRam einbinden lassen
        lea     $dff000,a5
        moveq.l #6,d1                  ; d1: Zaehler auessere Schleife
        moveq.l #0,d0                  ; d0 loeschen
nochens:
        move.w  #$fff,d0               ; fff = weiss
immawieda:
        move.w  6(a5),d2               ; vertikale Strahlenposition
        and.w   #%1111111100000000,d2  ; LSB loeschen
        ror.w   #8,d2                  ; MSB -> LSB fuer Farbregister
        move.w  d2,$180(a5)            ; ins Farbregister Nr.1 schreiben
        dbra    d0,immawieda           ; d0 erniedrigen und wiederholen
        dbra    d1,nochens             ; selbiges mit d1
no_mem:
        movem.l (a7)+,d0-d2/a0-a5      ; Register zurueckholen
        rts

FastMemBasis:   dc.l   0               ; Anfang des FastRam
FastMemLength:  dc.l   0               ; Laenge des FastRam

name:   dc.b    "bestes FastRam!",0

        even
AddMemEnd:      

Blockende:
        END

