*
* IFF-/ILBM-Saver (für nicht gepackte Bilder; Modula-Version)
*
* created on 16/10/89 14:32:16 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"

                movem.l d0-d7/a0-a6,-(SP)       * erstmal alles auf
                                                * den Stack!

*
* 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),a0
                move.l  d0,(a0)

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

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

                movem.l (SP)+,d0-d7/a0-a6       * Register zurückholen
                movem.l d0-d7/a0-a6,-(SP)       * und wieder sichern ...

                bsr     SaveIFF                 * Bild speichern!

*
* Das Ende vom Lied: Libraries schließen und zurück!
*

                move.l  IntuiBase(pc),a1
                CALLEXEC CloseLibrary

                move.l  GfxBase(pc),a1
                CALLEXEC CloseLibrary

                move.l  DosBase(pc),a1
                CALLEXEC CloseLibrary

                moveq.l #0,d0                   * das war's denn auch!
                bra     Ende

*
* Dies ist die Speicherroutine für nicht gepackte
* IFF-Bilder. Folgende Parameter müssen übergeben werden:
*
* A0: Zeiger auf den Namen der Datei
* A1: Zeiger auf den ViewPort des Bildes
* D0: x-Koordinate der linken, oberen Ecke des Ausschnittes.
* D1: y-Koordinate der linken, oberen Ecke des Ausschnittes.
* D2: x-Koordinate der rechten, unteren Ecke des Ausschnittes.
* D3: y-Koordinate der rechten, unteren Ecke des Ausschnittes.
* D4: Anzahl der zu speichernden Bitplanes
*

SaveIFF:        lea     FileName(pc),a2
                move.l  a0,(a2)                 * alle wichtigen
                lea     ViewPort(pc),a2
                move.l  a1,(a2)                 * Parameter
                lea     ColorMap(pc),a2
                move.l  4(a1),(a2)              * sichern ...
                lea     pageWidth(pc),a2
                move.w  24(a1),(a2)
                lea     pageHeight(pc),a2
                move.w  26(a1),(a2)
                lea     viewModes(pc),a2
                move.w  32(a1),(a2)
                lea     RasInfo(pc),a2
                move.l  36(a1),(a2)

                lea     x(pc),a2
                move.w  d0,(a2)
                lea     y(pc),a2
                move.w  d1,(a2)
                lea     width(pc),a2
                move.w  d2,(a2)
                lea     height(pc),a2
                move.w  d3,(a2)
                lea     nPlanes(pc),a2
                move.b  d4,(a2)

*
* Nun wird das Zielfile geöffnet.
*

                move.l  DosBase(pc),a6
                move.l  FileName(pc),d1
                move.l  #1006,d2
                jsr     _LVOOpen(a6)
                tst.l   d0
                beq     FileFault
                lea     FileHandle(pc),a2
                move.l  d0,(a2)

*
* Jetzt werden die Längen berechnet und gesetzt.
*

                moveq.l #0,d0
                move.l  RasInfo(pc),a0
                move.l  4(a0),a0
                lea     BitMap(pc),a2
                move.l  a0,(a2)                 * BitMap sichern
                move.w  0(a0),d0                * Bytes pro Zeile
                mulu.w  2(a0),d0                * mal Anzahl Zeilen
                mulu.w  d4,d0                   * mal Anzahl Planes
                lea     BODYlength(pc),a2
                move.l  d0,(a2)                 * ist gleich BODY-Länge
                add.l   #60,d0                  * + 60 (Länge aller Chunks)
                move.l  ColorMap(pc),a0         * ColorMap holen
                move.w  2(a0),d5                * Anzahl Farben
                mulu.w  #3,d5                   * mal 3 (wg. Komponenten)
                add.l   d5,d0                   * addieren
                lea     FORMlength(pc),a2
                move.l  d0,(a2)                 * und das entspricht der
                                                * FORM-Länge!

*
* Hier wird der FORM-Chunk geschrieben.
*

                move.l  FileHandle(pc),d1
                lea     FORM(pc),a2
                move.l  a2,d2
                move.l  #12,d3
                jsr     _LVOWrite(a6)

*
* Nun wird der BMHD-Chunk geschrieben.
*

                move.l  FileHandle(pc),d1
                lea     BMHD(pc),a2
                move.l  a2,d2
                move.l  #28,d3
                jsr     _LVOWrite(a6)

*
* Erstmal muß CMAP angepaßt werden.
*

                moveq.l #0,d5                   * d5 zurücksetzen
                move.l  ColorMap(pc),a0         * ColorMap laden
                move.w  2(a0),d5                * Anzahl Farben holen
                move.w  d5,d0                   * nach d0 sichern
                mulu.w  #3,d0                   * mal 3 (wg. Komponenten)
                lea     CMAPlength(pc),a2
                move.l  d0,(a2)                 * ist die CMAP-Länge

*
* An dieser Stelle wird der CMAP-Chunk geschrieben.
*

                lea     CMAP(pc),a2
                move.l  a2,d2
                move.l  FileHandle(pc),d1
                move.l  #8,d3
                jsr     _LVOWrite(a6)

*
* Nun müssen die Farben vom Amiga-Format ins
* CMAP-IFF-Format konvertiert werden.
*

                move.l  d5,d2                   * Anzahl Farben holen
                moveq.l #0,d0                   * Registerzähler auf 0

GetEntry:       movem.l d0,-(SP)                * d0 sichern
                move.l  ColorMap(pc),a0         * ColorMap holen
                move.l  GfxBase(pc),a6          * GfxBase nach a6
                jsr     _LVOGetRGB4(a6)         * Amiga-Farbe holen
                move.l  d0,d3                   * und nach d3 sichern
                movem.l (SP)+,d0                * d0 zurückholen

                move.l  d3,d4                   * d3 nach d4 kopieren
                lsr.w   #8,d4                   * durch 256 (Rotkomponente
                                                * isolieren)
                lsl.w   #4,d4                   * mal 16 (IFF-Abstufungen)
                lea     ActualRed(pc),a2
                move.b  d4,(a2)                 * und sichern!

                move.l  d3,d5                   * d3 nach d5 kopieren
                lsr.w   #4,d5                   * durch 16 (Grünkomponente
                                                * isolieren)
                lsl.w   #4,d4                   * Rot mal 16 (urspr.)
                sub.l   d4,d5                   * Rotkomponente abziehen
                lsl.w   #4,d5                   * Grün mal 16 (IFF-Abstuf.)
                lea     ActualGreen(pc),a2
                move.b  d5,(a2)                 * Grünkomponente sichern

                move.l  d3,d6                   * d3 nach d6 kopieren
                lsl.w   #4,d5                   * Grün mal 16 (urspr.)
                sub.l   d5,d6                   * von Blau abziehen
                lsl.w   #4,d4                   * Rot mal 16 (urspr.)
                sub.l   d4,d6                   * von Blau abziehen
                lsl.w   #4,d6                   * Blau mal 16 (IFF-Abstuf.)
                lea     ActualBlue(pc),a2
                move.b  d6,(a2)                 * und sichern ...

*
* An dieser Stelle wird die entsprechende Farbe
* - zerlegt in ihre Komponenten- in den CMAP geschrieben.
*

                movem.l d0/d2,-(SP)             * Register sichern
                move.l  DosBase(pc),a6          * DosBase nach a6
                move.l  FileHandle(pc),d1       * FileHandle laden
                lea     ActualRed(pc),a2
                move.l  a2,d2                   * Rotkomponente laden
                moveq.l #1,d3                   * 1 Byte schreiben
                jsr     _LVOWrite(a6)           * und ins File!
                move.l  FileHandle(pc),d1       * FileHandle laden
                lea     ActualGreen(pc),a2
                move.l  a2,d2                   * Grünkomponente laden
                moveq.l #1,d3                   * 1 Byte schreiben
                jsr     _LVOWrite(a6)           * ab in die Datei!
                move.l  FileHandle(pc),d1       * FileHandle laden
                lea     ActualBlue(pc),a2
                move.l  a2,d2                   * Blaukomponente laden
                moveq.l #1,d3                   * nur 1 Byte
                jsr     _LVOWrite(a6)           * und ab!
                movem.l (SP)+,d0/d2             * Register holen

                addq.l  #1,d0                   * Registerzähler + 1
                cmp.w   d0,d2                   * fertig?
                bne     GetEntry                * nein!

*
* Nun wird der CAMG-Chunk geschrieben.
*

                lea     CAMG(pc),a2
                move.l  a2,d2
                move.l  FileHandle(pc),d1
                move.l  #12,d3
                move.l  DosBase(pc),a6
                jsr     _LVOWrite(a6)

*
* Die ersten acht BODY-Bytes werden schon mal gesichert.
*

                lea     BODY(pc),a2
                move.l  a2,d2
                move.l  FileHandle(pc),d1
                move.l  #8,d3
                move.l  DosBase(pc),a6
                jsr     _LVOWrite(a6)

*
* Jetzt wird der gesamte BODY-Chunk gesichert.
*

                moveq.l #0,d5                   * Zeilenzähler auf 0
                move.l  BitMap(pc),a5           * BitMap laden
                move.b  nPlanes(pc),d4          * Anzahl Planes laden
                ext.w   d4                      * auf Word-Größe bringen
                lea     8(a5),a5                * Planetabelle laden

LineLoop:       moveq.w #0,d6                   * Planezähler auf 0

PlaneLoop:      asl     #2,d6                   * Planeoffset mal 4
                move.l  0(a5,d6.w),d2           * entspr. Plane holen
                asr     #2,d6                   * Offset wieder durch 4

                move.l  FileHandle(pc),d1       * FileHandle laden
                move.w  width(pc),d3            * Breite in Pixeln laden
                lsr     #3,d3                   * durch 8 (=Bytes)
                mulu.w  d5,d3                   * mal Höhe
                add.l   d3,d2                   * zur Ursprungsadresse der
                                                * entsprechenden Plane
                                                * hinzuaddieren
                move.w  width(pc),d3            * Breite in Pixeln laden
                lsr     #3,d3                   * durch 8 (=Bytes)
                jsr     _LVOWrite(a6)           * schreiben!

                addq.w  #1,d6                   * Planezähler + 1
                cmp.w   d6,d4                   * alle Planes?

                bne.s   PlaneLoop               * nein, noch nicht!

*
* Jetzt sind alle Planes einer Zeile geschrieben.
* Weiter geht's mit der nächsten Zeile ... frisch auf!
*

                addq.w  #1,d5                   * Zeilenzähler erhöhen
                cmp.w   height(pc),d5           * alle Zeilen durch?
                bne.s   LineLoop                * nö, warum auch?!

*
* Die Grafik ist nun fertig gespeichert. Ein wundersames Werk!
*

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

*
* Und zurück ...
*

FileFault:      rts

*
* Der Datenteil ...
*

FileName:       dc.l    0                       * Name des Files
FileHandle:     dc.l    0                       * FileHandle
ViewPort:       dc.l    0                       * ViewPort
ColorMap:       dc.l    0                       * ColorMap
RasInfo:        dc.l    0                       * RasInfo
BitMap:         dc.l    0                       * BitMap

GfxBase:        dc.l    0                       * GfxBase
IntuiBase:      dc.l    0                       * IntuitionBase
DosBase:        dc.l    0                       * DosBase

ActualRed:      dc.b    0                       * Rotkomponente einer Farbe
ActualGreen:    dc.b    0                       * Grünkomponente einer Farbe
ActualBlue:     dc.b    0                       * Blaukomponente einer Farbe

*
* Systemkonstanten ...
*

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

*
* Der auszugebende Text:
*

Text:           dc.b    10,"Filename: ",0
 even

Name:           ds.b    256                     * für einen Filenamen

*
* Hier stehen die Daten der einzelnen Chunks ...
*

FORM:           dc.b    "FORM"                  * FORM-Chunk
FORMlength:     dc.l    0                       * FORM-Länge
                dc.b    "ILBM"                  * IFF-Typus

*
* Der BMHD-Chunk ...
*

BMHD:           dc.b    "BMHD"                  * Kennung
                dc.l    20                      * Länge
width:          dc.w    0                       * diverse Daten
height:         dc.w    0
x:              dc.w    0
y:              dc.w    0
nPlanes:        dc.b    0,0,0,0,0,0,10,11
pageWidth:      dc.w    0
pageHeight:     dc.w    0

*
* Der CMAP-Chunk ...
*

CMAP:           dc.b    "CMAP"                  * Kennung
CMAPlength:     dc.l    0                       * Länge

*
* CAMG ...
*

CAMG:           dc.b    "CAMG"                  * CAMG-Kennung
                dc.l    4                       * CAMG-Länge
                dc.w    0                       * 1. Word (unbenutzt)
viewModes:      dc.w    0                       * 2. Word (View-Modi)

*
* Der BODY-Chunk ...
*

BODY:           dc.b    "BODY"                  * Kennung
BODYlength:     dc.l    0                       * BODY-Länge

*
* Das Ende ...
*

Ende:           movem.l (SP)+,d0-d7/a0-a6       * Register restaurieren

                END

