*
* Flotter IFF-/ILBM-Lader (Modula-Version)
*
* created on 12/10/89 22:17:30 by Holger Gzella
*

                opt     p+

                incdir "asm:"
                include "exec/exec_lib.i"
                include "graphics/graphics_lib.i"
                include "intuition/intuition_lib.i"
                include "libraries/dos_lib.i"

*
* Unsere IFF-Routine wird ja nicht vom CLI gestartet,
* also brauchen wir uns um das Argument-Handling nicht
* kümmern. Das Modula-Hauptprogramm muß dem IFF-Lader
* einen Zeiger auf den Namen der zu ladenden Datei in
* A0 übergeben, dann läuft schon alles wie am Schnürchen.
*

                movem.l d0-d7/a0-a6,-(SP)       * bei Modula-INLINE-Code
                                                * sehr(!) wichtig: Register
                                                * auf den Stack retten!

                lea     FileName(pc),a1
                move.l  a0,(a1)                 * Namen sichern

*
* Hier werden die ganzen Libraries geöffnet: DOS, Graphics, Intuition
*

                lea     DosName(pc),a1          * DOS öffnen
                moveq.l #0,d0
                CALLEXEC OpenLibrary
                lea     DosBase(pc),a1
                move.l  d0,(a1)

                lea     GfxName(pc),a1          * Graphics öffnen
                moveq.l #0,d0
                CALLEXEC OpenLibrary
                lea     GfxBase(pc),a1
                move.l  d0,(a1)

                lea     IntuiName(pc),a1        * Intuition öffnen
                moveq.l #0,d0
                CALLEXEC OpenLibrary
                lea     IntuiBase(pc),a1
                move.l  d0,(a1)

*
* Nun wird das File übergebenen Namens geöffnet.
*

                move.l  DosBase(pc),a6
                move.l  FileName(pc),d1         * Namen holen
                move.l  #1005,d2                * modeOldFile
                jsr     _LVOOpen(a6)            * öffnen!
                tst.l   d0                      * hat's geklappt?
                beq     FileFault               * ne ... Mist!
                lea     FileHandle(pc),a1
                move.l  d0,(a1)                 * Handle sichern

*
* An dieser Stelle wird der FORM-Chunk eingelesen und geprüft.
*

                lea     Buffer(pc),a0           * Zwischenspeicher
                move.l  a0,d2
                moveq.l #12,d3                  * 12 Bytes
                bsr     ReadSomething           * laden
                lea     Buffer(pc),a2           * Adresse holen
                cmp.l   #"FORM",(a2)            * vergleichen
                bne     IFFault                 * kein FORM!!

                cmp.l   #"ILBM",8(a2)           * ILBM?
                bne     IFFault                 * Abbruch!

*
* Nun wird auf BMHD oder BHSM gecheckt.
*

ItsILBM:        lea     Buffer(pc),a0           * nächsten Chunk
                move.l  a0,d2
                moveq.l #8,d3                   * ein-
                bsr     ReadSomething           * laden
                lea     Buffer(pc),a2           * Zwischenspeicher holen
                cmp.l   #"BMHD",(a2)            * BMHD?
                beq     ItsBMHD                 * ja!

                cmp.l   #"BHSM",(a2)            * BHSM?
                bne     IFFault                 * nein ... Abbruch!

                lea     Buffer(pc),a0           * BHSM-Chunk
                move.l  a0,d2
                moveq.l #2,d3                   * über-
                bsr     ReadSomething           * lesen

                bra.s   ItsILBM                 * BMHD weiter suchen!

ItsBMHD:        move.l  4(a2),d3                * BMHD-Chunk
                lea     BMHD(pc),a1
                move.l  a1,d2                   * ein-
                bsr     ReadSomething           * lesen

                lea     width(pc),a0

                move.l  pageWidth(pc),d0        * Breite u. Höhe nach d0
                move.l  bmhdWidth(pc),d1
                tst.l   d0                      * überhaupt vorhanden?
                bne.s   PageDefined             * ja!

                move.l  d1,(a0)                 * Kompromiß!
                bra.s   ContPlanes              * weiter!

PageDefined:    cmp.w   d0,d1                   * SuperBitMap?
                bhi.s   SuperWidth              * ja!
                move.l  d0,(a0)                 * wenn nicht, normal
                bra.s   ContPlanes              * weiter!

SuperWidth:     move.l  d1,(a0)                 * SuperBitMap-Breite
                lea     SuperFlag(pc),a1
                move.w  #1,(a1)                 * Flag setzen

ContPlanes:     move.b  Planes(pc),d0           * Anzahl Planes
                ext.w   d0                      * auf Word-Größe bringen
                lea     depth(pc),a1
                move.w  d0,(a1)                 * und speichern

*
* Jetzt wird erstmal die CMAP gesucht.
*

SearchCMAP:     lea     Buffer(pc),a0           * CMAP-Chunk
                move.l  a0,d2
                moveq.l #8,d3                   * ein-
                bsr     ReadSomething           * lesen
                lea     Buffer(pc),a2           * ist es
                cmp.l   #"CMAP",(a2)            * CMAP?
                beq.s   ItsCMAP                 * es ist!

*
* Nun wird auf CAMG gecheckt.
*

                cmp.l   #"CAMG",(a2)            * ist es CAMG?
                bne     IFFault2                * nein - Fehler!
                moveq.l #4,d3                   * CAMG
                lea     Buffer(pc),a5
                move.l  a5,d2                   * ein-
                bsr     ReadSomething           * lesen
                lea     Buffer(pc),a0           * und ViewModes
                lea     viewModes(pc),a1
                move.l  2(a0),(a1)              * speichern

                bra     SearchCMAP              * weiter suchen

*
* Der CMAP-Chunk wurde gefunden. Nun werden die Farben gelesen.
*

ItsCMAP:        move.l  4(a2),d3                * Länge laden
                move.l  d3,d5                   * und retten
                divu    #3,d5                   * durch 3 = Farbanzahl
                subq    #1,d5                   * weniger 1

                lea     Colors(pc),a0           * Farben
                move.l  a0,d2
                bsr     ReadSomething           * einlesen

*
* An dieser Stelle wird der BODY-Chunk gesucht.
*

SearchBODY:     lea     Buffer(pc),a5           * nächsten Chunk
                move.l  a5,d2
                moveq.l #4,d3                   * ein-
                bsr     ReadSomething           * lesen
                cmp.l   #"BODY",(a5)            * ist es BODY?
                beq     FoundBODY               * ja, es ist!

*
* Jetzt werden andere Chunks überlesen oder ausgewertet.
*

SearchOther:    cmp.l   #"CRNG",(a5)            * ist es CRNG?
                bne     NoCRNG                  * nein!
                moveq.l #12,d3                  * CRNG
                lea     Buffer(pc),a5
                move.l  a5,d2                   * über-
                bsr     ReadSomething           * lesen

                bra.s   SearchBODY              * Suche fortsetzen

NoCRNG:         cmp.l   #"DPPS",(a5)            * ist es DPPS?
                bne.s   NoDPPS                  * nein!
                move.l  #114,d3                 * DPPS
                lea     Buffer(pc),a5
                move.l  a5,d2                   * interessiert uns
                bsr     ReadSomething           * nicht!

                bra.s   SearchBODY              * Suche fortsetzen

NoDPPS:         cmp.l   #"DPPV",(a5)            * ist es DPPV?
                bne.s   NoDPPV                  * nein, nein!
                move.l  #108,d3                 * DPPV
                lea     Buffer(pc),a5
                move.l  a5,d2                   * interessiert uns
                bsr     ReadSomething           * noch weniger!

                bra.s   SearchBODY              * Suche fortsetzen

NoDPPV          cmp.l   #"CAMG",(a5)            * ist hier wenigstens CAMG?
                bne.s   NoCAMG                  * nein!
                moveq.l #8,d3                   * CAMG
                lea     Buffer(pc),a5
                move.l  a5,d2                   * interessiert uns
                bsr     ReadSomething           * schon mehr!
                lea     Buffer(pc),a0           * ViewModes
                lea     viewModes(pc),a1
                move.w  6(a0),(a1)              * speichern

                bra     SearchBODY              * weiter

NoCAMG:         cmp.l   #"CCRT",(a5)            * ist es CCRT?
                bne.s   NoCCRT                  * nein - weiter!
                moveq.l #18,d3                  * CCRT
                lea     Buffer(pc),a5
                move.l  a5,d2                   * über-
                bsr     ReadSomething           * lesen.

NoCCRT:         moveq.l #4,d3                   * scheint
                lea     Buffer(pc),a5
                move.l  a5,d2                   * irgendsoein
                bsr     ReadSomething           * privater
                move.l  (a5),d3                 * Chunk zu sein,
                lea     Buffer(pc),a5
                move.l  a5,d2                   * der uns
                bsr     ReadSomething           * nichts angeht.

                bra     SearchBODY              * weiter mit der Suche

*
* Der BODY-Chunk wurde gefunden!
*

FoundBODY:      move.l  GfxBase(pc),a6          * GfxBase laden

*
* Erstmal müssen wir eine eigene BitMap initialisieren
* (wegen der Super-BitMaps) ...
*

                lea     BitMapStruc(pc),a0      * leere BitMap-Struktur
                lea     customBitMap(pc),a1
                move.l  a0,(a1)                 * in Screen-Struktur
                move.w  depth(pc),d0            * Anzahl Planes
                move.w  bmhdWidth(pc),d1        * Breite
                move.w  bmhdHeight(pc),d2       * Höhe
                jsr     _LVOInitBitMap(a6)      * und initialisieren!

*
* Als nächstes müssen wir die Planes allokieren. Damit's
* professioneller aussieht, löschen wir sie gleich mit BltClear.
*

                move.w  depth(pc),d4            * Anzahl Planes
                lsl.w   #2,d4                   * mal 4

                lea     PlaneTable(pc),a3       * Planetabelle holen
                moveq.w #0,d3                   * d3 löschen

AllocThem:      move.w  bmhdWidth(pc),d0        * Breite
                move.w  bmhdHeight(pc),d1       * und Höhe
                jsr     _LVOAllocRaster(a6)     * Plane bereitstellen!
                tst.l   d0                      * hat's geklappt?
                beq     IFFault                 * nein; schade!
                move.l  d0,0(a3,d3.w)           * Zeiger retten
                move.l  d0,a1
                move.w  bmhdWidth(pc),d0        * Breite nach d0
                lsr.w   #3,d0                   * durch 8 teilen
                mulu.w  bmhdHeight(pc),d0       * mit Höhe multiplizieren
                moveq.l #0,d1                   * Flag: normal
                jsr     _LVOBltClear(a6)        * Plane löschen
                add.w   #4,d3                   * Zähler erhöhen
                cmp.w   d3,d4                   * fertig?
                bne.s   AllocThem               * nein ... weiter!

*
* Jetzt wird anhand der Höhe auf Overscan geprüft.
*

                move.l  IntuiBase(pc),a6        * IntuiBase laden
                jsr     _LVOViewAddress(a6)     * View holen
                move.l  d0,a0                   * und nach a0 schieben
                lea     oldY(pc),a2
                lea     oldX(pc),a3
                move.w  12(a0),(a2)             * alte Offsets retten
                move.w  14(a0),(a3)

                lea     pageWidth(pc),a1        * Displaybreite laden
                cmp.w   #256,2(a1)              * größer als 256?
                ble.s   OpenIt                  * kein Overscan!

                cmp.w   #512,2(a1)              * kleiner als 512?
                ble.s   OpenIt                  * kein Overscan!

                move.w  #30,12(a0)              * dyOffset verändern
                move.w  #112,14(a0)             * dxOffset verändern
                jsr     _LVORethinkDisplay(a6)  * Display erneuern

OpenIt:         lea     ScreenDefs(pc),a0       * Screen öffnen
                jsr     _LVOOpenScreen(a6)
                tst.l   d0
                beq     IFFault

                lea     Screen(pc),a0
                move.l  d0,(a0)
                move.l  d0,a0
                lea     $2c(a0),a0
                lea     ViewPort(pc),a3
                move.l  a0,(a3)                 * ViewPort retten
                lea     RasInfo(pc),a3
                move.l  $24(a0),(a3)            * RasInfo retten
                move.l  Screen(pc),a0
                lea     $b8(a0),a0
                lea     8(a0),a0
                move.l  a0,a5                   * Plane-Tabelle holen

*
* Jetzt werden erstmal die Farben umgewandelt!
*

CompColors:     move.l  GfxBase(pc),a6
                lea     Colors(pc),a3           * Farbtabelle holen
                moveq.w #0,d6                   * bei Farbe 0 anfangen!

ColLoop:        move.b  (a3)+,d1                * Rotkomponente holen
                lsr.b   #4,d1                   * durch 16 teilen
                move.b  (a3)+,d2                * Grünkomponente holen
                lsr.b   #4,d2                   * durch 16 teilen
                move.b  (a3)+,d3                * Blaukomponente holen
                lsr.b   #4,d3                   * durch 16 teilen
                move.l  ViewPort(pc),a0         * ViewPort holen
                move.w  d6,d0                   * Nummer holen
                jsr     _LVOSetRGB4(a6)         * Farbe setzen!

                addq.w  #1,d6                   * Nummer erhöhen
                dbra    d5,ColLoop              * bis zum Ende!

*
* Nun beginnt das Lesen der eigentlichen Daten.
*

ReadThem:       lea     Buffer(pc),a0
                move.l  a0,d2                   * Chunk-Länge
                move.l  #4,d3                   * über-
                bsr     ReadSomething           * lesen

                lea     Buffer(pc),a0
                move.l  a0,d2                   * die ersten
                move.l  #1024,d3                * 1024 Bytes
                bsr     ReadSomething           * einlesen

                lea     numLines(pc),a0
                move.w  height(pc),(a0)         * Höhe = Anzahl Zeilen
                move.w  height(pc),d5           * nach d5
                move.w  width(pc),d3            * Breite nach d3
                lsr.w   #3,d3                   * durch 8 = Bytes/Zeile
                move.l  a5,a3                   * Plane-Zeiger nach a3
                lea     Buffer(pc),a2           * Zwischenspeicher nach a2
                move.w  depth(pc),d4            * Anzahl Planes nach d4

                lea     Comp(pc),a0
                cmp.b   #1,(a0)                 * gepackt?
                bne     NotPacked               * nein ... schön!

*
* Ab hier steht die Routine, die einen gepackten BODY-
* Chunk einliest und anzeigt.
*

                moveq.l #0,d1                   * erstmal d1 löschen
                moveq.l #0,d5                   * Zeilenzähler löschen
UnpackLine:     moveq.l #0,d6                   * Bitplanezähler löschen

UnpackPlane:    move.w  d3,d0                   * Bytes/Zeile
                mulu    d5,d0                   * mal Höhe
                move.l  d0,a5                   * nach a5
                asl     #2,d6                   * mal 4 (wg. Longword)
                add.l   0(a3,d6.w),a5           * zur aktuellen
                                                * Position der aktuellen
                                                * Bitplane addieren
                asr     #2,d6                   * durch 4 (normal)

                move.l  a5,a6                   * nach a6
                add.w   d3,a6                   * plus Bytes/Zeile

*
* Jetzt wird geprüft, ob das Byte kleiner als 128 ist.
*

CheckPacked:    bsr     ReadOneByte             * nächste Byte lesen
                cmp.b   #128,d0                 * ist es
                bhi.s   GoOn                    * größer als 128?
                beq.s   CheckFinished           * wenn gleich 128, wird
                                                * keine Operation
                                                * durchgeführt.

*
* Das Byte zeigt an, daß ungleiche Bytes folgen. Diese
* werden nun alle in die entsprechende Plane geschrieben.
*

                move.b  d0,d7                   * als Zähler
FinishLine:     bsr     ReadOneByte             * nächste Byte lesen
                move.b  d0,(a5)                 * ab in die Plane
                addq.l  #1,a5                   * Planeposition + 1
                subq.b  #1,d7                   * Zähler dekrementieren
                bpl.s   FinishLine              * solange, bis Zähler 0
                bra.s   CheckFinished           * weiter

*
* Hierhin wird gesprungen, wenn erkannt wurde, daß die
* folgenden Bytes gleich sind.
*

GoOn:           move.b  d0,d7                   * Zähler setzen
                bsr     ReadOneByte             * nächste Byte lesen
StoreByte:      move.b  d0,(a5)                 * in die Plane
                addq.l  #1,a5                   * Planeposition + 1
                addq.b  #1,d7                   * Zähler erhöhen
                cmp.b   #1,d7                   * ist Zähler 1?
                bne.s   StoreByte               * nein ... wiederholen

CheckFinished:  cmp.l   a5,a6                   * fertig?
                bhi.s   CheckPacked             * nein ... weiter mit
                                                * dem Lesen einzelner
                                                * Bytes

                addq    #1,d6                   * Planezähler erhöhen
                                                * (nächste Plane)
                cmp     d4,d6                   * Zeilenende erreicht?
                bne.s   UnpackPlane             * nein - weiter

                lea     Mask(pc),a0
                cmp.b   #1,(a0)                 * Maske definiert?
                bne.s   GoOnLoop                * nein - weiter

*
* Hier steht im Prinzip der gleiche Code wie oben,
* nur werden die Bytes der Maske nirgendwohin gespeichert.
*

                move.l  #0,a5                   * Planeposition löschen

CheckPacked2:   bsr     ReadOneByte             * nächste Byte lesen
                cmp.b   #128,d0                 * 128?
                bhi.s   GoOn2                   * nein, größer!
                beq.s   CheckFinished2          * gleich 128 - heißt
                                                * keine Operation!

*
* Es folgen unterschiedliche Bytes.
*

                move.b  d0,d7                   * Zähler setzen
FinishLine2:    bsr     ReadOneByte             * nächste Byte lesen
                addq.l  #1,a5                   * Planeposition + 1
                subq.b  #1,d7                   * Zähler - 1
                bpl.s   FinishLine2             * noch nicht 0?
                bra.s   CheckFinished2          * weiter!

*
* Es folgen gleiche Bytes. Diese werden sozusagen ins
* Nichts geschrieben, aber so täuschend echt, daß es
* scheint, sie würden in irgendwelche Bitplanes geschrieben.
*

GoOn2:          move.b  d0,d7                   * Zähler setzen
                bsr     ReadOneByte             * nächste Byte lesen
StoreByte2:     addq.l  #1,a5                   * Position erhöhen
                addq.b  #1,d7                   * Zähler erhöhen
                cmp.b   #1,d7                   * ist schon 1?
                bne     StoreByte2              * nein ... weiter

CheckFinished2: cmp.l   a5,d3                   * Plane fertig?
                bhi.s   CheckPacked2            * nein ... weiter

GoOnLoop:       addq    #1,d5                   * Zeilenzähler erhöhen
                                                * (nächste Zeile)
                lea     numLines(pc),a0         * Anzahl Zeilen laden
                cmp     (a0),d5                 * fertig (also war dies
                                                * die letzte Zeile)?
                bne     UnpackLine              * nein - weiterladen

                bra.s   WaitForMouse            * weiter

*
* Dies ist die Laderoutine für ungepackte IFF-Bilder.
*

NotPacked:      moveq.l #0,d1                   * d1 löschen
                moveq.l #0,d5                   * Zeilenzähler löschen
NUnpackLine:    moveq.l #0,d6                   * Planezähler löschen

NUnpackPlane:   move.w  d3,d0                   * Bytes/Zeile nach d0
                mulu    d5,d0                   * mal Höhe
                move.l  d0,a5                   * = Position
                asl     #2,d6                   * mal 4 (wg. Longword-
                                                * Adressierung
                add.l   0(a3,d6.w),a5           * zur aktuellen
                                                * Position der aktuellen
                                                * Bitplane addieren
                asr     #2,d6                   * wieder normalisieren

                move.l  a5,a6                   * nach a6
                add.w   d3,a6                   * + Bytes/Zeile

*
* Nun werden alles Bytes einer Plane eingelesen und
* an die entsprechende Stelle im Speicher kopiert.
*

                move.w  d3,d7                   * Zähler setzen
                subq    #1,d7                   * weniger 1 (wg. DBRA)
loop:           bsr     ReadOneByte             * nächste Byte lesen
                move.b  d0,(a5)                 * in die Bitplane
                addq    #1,a5                   * Planeposition + 1
                dbra    d7,loop                 * wiederholen, bis fertig

                addq    #1,d6                   * Planezähler erhöhen
                cmp     d4,d6                   * alle Planes durch?
                bne.s   NUnpackPlane            * nein - also weiter!

                lea     Mask(pc),a0
                cmp.b   #1,(a0)                 * Maske definiert?
                bne.s   GoOnNUnpacking          * nein - weiter!

*
* Und wieder das gleiche wie oben, nur wird das, was die
* Leseroutine einladen, überhaupt nicht berücksichtigt
* (so geht's also auch).
*

                move.w  d3,d7                   * Bytes/Zeile als Zähler
                subq    #1,d7                   * - 1 (wegen DBRA)
loop2:          bsr     ReadOneByte             * nächste Byte lesen
                addq    #1,a5                   * Planeposition + 1
                dbra    d7,loop2                * bis fertig!

GoOnNUnpacking: addq    #1,d5                   * Zeilenzähler erhöhen
                lea     numLines(pc),a0         * Anzahl Zeilen laden
                cmp     (a0),d5                 * sind wir fertig?
                bne.s   NUnpackLine             * nein, sind wir nicht!

*
* Das war's dann mit dem Einlesen. Jetzt wird noch auf
* Super-BitMaps geprüft und diese ggf. gescrollt.
*

WaitForMouse:   move.l  IntuiBase(pc),a6        * IntuiBase laden
                move.l  RasInfo(pc),a3          * RasInfo laden

                lea     SuperFlag(pc),a0
                cmp.w   #1,(a0)                 * haben wir eine
                                                * Super-BitMap?
                bne     WaitForEnd              * nein - schade eigentlich,
                                                * denn es geht ein wenig
                                                * Effekthascherei verloren!

                move.w  pageWidth(pc),d0        * Screenbreite nach d0
                move.w  bmhdWidth(pc),d1        * Gesamtbreite nach d1
                sub.w   d0,d1                   * Delta errechnen
                lea     xDelta(pc),a0
                move.w  d1,(a0)                 * und speichern

                move.w  pageHeight(pc),d0       * Screenhöhe nach d0
                move.w  bmhdHeight(pc),d1       * Gesamthöhe nach d1
                sub.w   d0,d1                   * Delta errechnen
                lea     yDelta(pc),a0
                move.w  d1,(a0)                 * auch speichern

*
* Es darf gescrollt werden!
*

ScrollIt:       moveq.w #0,d2                   * Scrollzähler löschen
                move.w  xDelta(pc),d3           * Delta holen

*
* Nun wird nach rechts gescrollt.
*

ScrollX:        move.w  d2,8(a3)                * rxOffset setzen
                btst.b  #6,$bfe001              * Maustaste?
                beq     IFFault2                * Ende!
                move.l  Screen(pc),a0           * Screen
                jsr     _LVOMakeScreen(a6)      * erneuern
                jsr     _LVORethinkDisplay(a6)  * Display neu berechnen
                addq.w  #1,d2                   * Scrollzähler erhöhen
                cmp.w   d2,d3                   * fertig?
                bne.s   ScrollX                 * nein, also weiter

*
* Jetzt wird nach unten gescrollt.
*

                moveq.w #0,d2                   * Scrollzähler löschen
                move.w  yDelta(pc),d3           * Delta holen

ScrollY:        move.w  d2,10(a3)               * ryOffset setzen
                btst.b  #6,$bfe001              * Maustaste?
                beq     IFFault2                * Aus und Schluß!
                move.l  Screen(pc),a0           * Screen
                jsr     _LVOMakeScreen(a6)      * neu berechnen
                jsr     _LVORethinkDisplay(a6)  * Display erneuern
                addq.w  #1,d2                   * Scrollzähler erhöhen
                cmp.w   d2,d3                   * fertig?
                bne.s   ScrollY                 * nein - weiter

*
* Es wird nach links gescrollt.
*

                move.w  xDelta(pc),d2           * Delta holen
                moveq.w #0,d3                   * Scrollzähler löschen

ScrollX2:       move.w  d2,8(a3)                * rxOffset setzen
                btst.b  #6,$bfe001              * Maustaste?
                beq     IFFault2                * Ende!
                move.l  Screen(pc),a0           * Screen
                jsr     _LVOMakeScreen(a6)      * erneuern
                jsr     _LVORethinkDisplay(a6)  * Display erneuern
                subq.w  #1,d2                   * Zähler dekrementieren
                cmp.w   d2,d3                   * fertig?
                bne.s   ScrollX2                * ne, ne!

*
* Und wieder nach oben.
*

                move.w  yDelta(pc),d2           * Delta holen
                moveq.w #0,d3                   * Zähler zurücksetzen

ScrollY2:       move.w  d2,10(a3)               * ryOffset setzen
                btst.b  #6,$bfe001              * Maustaste gedrückt?
                beq     IFFault2                * jawollja!
                move.l  Screen(pc),a0           * Screen
                jsr     _LVOMakeScreen(a6)      * neu berechnen
                jsr     _LVORethinkDisplay(a6)  * Display neu berechnen
                subq.w  #1,d2                   * Zähler dekrementieren
                cmp.w   d2,d3                   * fertig?
                bne.s   ScrollY2                * denkste!

*
* An dieser Stelle wird die (linke) Maustaste abgefragt.
*

                btst.b  #6,$bfe001              * und - was ist?
                bne     ScrollIt                * nicht gedrückt?
                                                * noch'ne Runde scrollen!
                bra.s   IFFault2                * Schluß für heut'!

*
* Hierhin wird gesprungen, wenn kein Super-BitMap und
* somit auch kein Grund für's Scrollen vorliegt.
*

WaitForEnd:     btst.b  #6,$bfe001              * Maustaste?
                bne.s   WaitForEnd              * nein!

*
* Das ist nun das Ende.
*

IFFault2:       move.l  IntuiBase(pc),a6
                jsr     _LVOViewAddress(a6)     * alte Offsets holen
                move.l  d0,a0
                move.w  oldY(pc),12(a0)
                move.w  oldX(pc),14(a0)
                jsr     _LVORethinkDisplay(a6)

                move.l  Screen(pc),a0           * Screen schließen
                jsr     _LVOCloseScreen(a6)

                move.l  GfxBase(pc),a6          * GfxBase laden

                move.w  depth(pc),d4            * Anzahl Planes
                lsl.w   #2,d4                   * mal 4

                lea     PlaneTable(pc),a3       * Planetabelle holen
                moveq.w #0,d3                   * d3 löschen

FreeThem:       move.w  bmhdWidth(pc),d0        * Breite
                move.w  bmhdHeight(pc),d1       * und Höhe
                move.l  0(a3,d3.w),a0           * Zeiger holen
                jsr     _LVOFreeRaster(a6)      * Plane freigeben!
                add.w   #4,d3                   * d3 erhöhen
                cmp.w   d3,d4                   * fertig?
                bne     FreeThem                * nein ... weiter!

IFFault:        move.l  FileHandle(pc),d1       * Datei schließen
                move.l  DosBase(pc),a6
                jsr     _LVOClose(a6)

FileFault:      move.l  IntuiBase(pc),a1        * Libraries schließen
                CALLEXEC CloseLibrary

                move.l  GfxBase(pc),a1
                CALLEXEC CloseLibrary

                move.l  DosBase(pc),a1
                CALLEXEC CloseLibrary

                moveq.l #0,d0                   * und Ende!
                bra     EndOfAll

*
* Hier stehen die Unterroutinen zum Lesen ...
*

*
* Diese Routine list ein einen ganzen Schwall Bytes direkt
* vom Massenspeicher. Die Länge wird in d3 übergeben, ein Zeiger
* auf den entsprechenden Zwischenspeicher muß in d1 stehen.
*

ReadSomething:  movem.l d1/d3/a0/a1,-(SP)       * nur das Nötigste retten!
                move.l  DosBase(pc),a6
                move.l  FileHandle(pc),d1
                jsr     _LVORead(a6)            * Bytes lesen!
                movem.l (SP)+,d1/d3/a0/a1
                rts

*
* Die Routine ReadOneByte liest ein einzelnes Byte,
* berücksichtigt aber die Zwischenspeicherung. Ein Zeiger auf
* den Zwischenspeicher muß in a2 stehen. Das geholte Byte
* steht dann in d0.
*

ReadOneByte:    move.b  0(a2,d1.w),d0           * Byte holen und in
                                                * d0 zurückgeben.
                addq.w  #1,d1                   * Länge erhöhen
                cmp.w   #1024,d1                * ist wieder ein ganzer
                                                * Schub fällig?
                bne.s   NotReadyYet             * nein, noch(!) nicht ...

                movem.l d0/d2/d3/a6,-(SP)       * das Nötigste auf den Stack
                move.l  a2,d2                   * Zwischenspeicher setzen
                move.l  #1024,d3                * Länge: 1 Kbyte
                bsr     ReadSomething           * lesen
                movem.l (SP)+,d0/d2/d3/a6       * vom Stack holen
                moveq   #0,d1                   * Länge löschen
NotReadyYet:    rts                             * zurück.

*
* Dies ist der Datenteil ...
*

*
* Hier steht die Definition eines Screens (NewScreen), der im
* Laufe des Programms initialisiert wird.
*

 even
ScreenDefs:
leftEdge:       dc.w    0
topEdge:        dc.w    0
width:          dc.w    0
height:         dc.w    0
depth:          dc.w    0
detailPen:      dc.b    1
blockPen:       dc.b    0
viewModes:      dc.w    0
type:           dc.w    $4F                     * customScreen und
                                                * customBitMap
font:           dc.l    0
defaultTitle:   dc.l    0
gadgets:        dc.l    0
customBitMap:   dc.l    0                       * BitMap-Struktur

*
* Einige Systemkonstanten.
*

GfxName:        dc.b    "graphics.library",0
 even
IntuiName:      dc.b    "intuition.library",0
 even
DosName:        dc.b    "dos.library",0
 even

*
* Hier wird Platz für eine BitMap-Struktur und Planes gelassen.
*

 even
BitMapStruc:    ds.b    8
PlaneTable:     ds.l    6

*
* Einige private (unsere!) Zeiger.
*

FileName:       dc.l    0
FileHandle:     dc.l    0
GfxBase:        dc.l    0
IntuiBase:      dc.l    0
DosBase:        dc.l    0
ViewPort:       dc.l    0
RasInfo:        dc.l    0
Screen:         dc.l    0

*
* Platz für den BMHD-Chunk, der hierhin kommt.
*

BMHD:
bmhdWidth:      dc.w    0
bmhdHeight:     dc.w    0,0,0
Planes:         dc.b    0
Mask:           dc.b    0
Comp:           dc.b    0,0
                dc.w    0,0
pageWidth:      dc.w    0
pageHeight:     dc.w    0

*
* Eigene Parameter ...
*

xDelta:         dc.w    0                       * x-Delta fürs Scrolling
yDelta:         dc.w    0                       * y-Delta fürs Scrolling

SuperFlag:      dc.w    0                       * Super-BitMap-Flag

oldX:           dc.w    0                       * alter dxOffset
oldY:           dc.w    0                       * alter dyOffset
numLines:       dc.w    0                       * Anzahl Zeilen

*
* Hier ist genug Platz für den CMAP-Chunk.
*

Colors:         ds.b    96

*
* Und das ist ein Zwischenspeicher für das zwischengespeicherte
* Einlesen von Bytes (siehe ReadOneByte).
*

Buffer:         ds.b    1024

*
* Das war's dann auch.
*

EndOfAll:       movem.l (SP)+,d0-d7/a0-a6       * Register zurückholen

                                                * an diese Stelle setzt
                                                * jetzt der Compiler 
                                                * seinen Return-Code

                END

