
=============================================================================

                    =   =   =   IFFSupport   =   =   =

                           © Copyright  1988 by
                             Fridtjof Siebert
                               Nobileweg 67
                       7000 Stuttgart 40 (Stammheim)
                            Tel: (0)711/822509

=============================================================================


Mit den von IFFSupport exportierten Prozeduren können IFFBilder geladen,
gespeichert und Colorcycling-Bilder gezeigt werden.
Die Prozeduren zum Laden und für ColorCycling entsprechen denen von IFFLoad
(Amok#2 & 3).


Anders als bei anderen IFF-Unterstützungsroutinen (Ich habe die des
TDI-Compilers angesehen) werden hier die geladenen Daten in bekannten
Formaten (Screens, Windows und BitMaps) und nicht so, wie sie im IFF-File
vorliegen, übergeben. Dadurch vereinfacht sich die Handhabung ungemein.


------  Die Dateien:  ------


  IFFSupport.doc   : Diese Datei.

  IFFSupport.def   : Definition der IFF-Unterstützung.
  IFFSupport.mod   : Ihre Implementation.
  IFFSupport.sym   : Symbol-Datei.
  IFFSupport.obj   : Fertig compiliertes IFFSupport.
  LoadBody.asm     : Der Assembler-Quelltext der Maschinenroutine.
  LoadBody.prg     : Die PC-relativ assemblierte Maschinenroutine.
  LoadBody.code    : File, das mit EXECUTE aufgerufen wird, und aus
                     LoadBody.prg die Dateien -.def und -.mod erzeugt. Dazu
                     muß sich das Tool M2ACode in einem mit Path angegebenem
                     Directory befinden.
  LoadBody.def     : Die Definition von LoadBody.
  LoadBody.mod     : Die Implementation.
  LoadBody.sym     : Symbol-Datei.
  LoadBody.obj     : Und compiliert.


  ShowIFF          : ILBM-Ladeprogramm.
  ShowIFF.mod      : sein Quelltext.
  ShowCycling      : ILBM-Lader für Colorcycling-Bilder.
  ShowCycling.mod  : Quellcode.
  IFFBitMapDemo    : Demonstration für Laden mit Option `dontopen'.
  IFFBitMapDemo.mod: Source.
  DiaShow          : Lader für mehrere Bilder. Enthält Prozeduren zum Ein- und
                   Ausblenden von Screens.
  DiaShow.mod      : Sourcecode.
  CopyIFF          : Lädt IFF-Bild und speichert es als RAM:test.iff
  CopyIFF.mod      : Quellcode.
  SaveIFF          : Speichert Screens und Windows als IFF-Bild.
  SaveIFF.mod      : Source.


------------------------  Variablen & Typen:  -----------------------------


Von IFFSupport werden folgende Variablen und Typen exportiert:

TYPE
  IFFInfoTypePtr = POINTER TO IFFInfoType;
  IFFInfoType = RECORD
                  ...   (* Mega-Record *)
                END;

VAR
  IFFInfo: IFFInfoType;

IFFInfo enthält Informationen zum zuletzt geladenen Bild oder Informationen
für ein zu Speicherndes Bild. Wenn mehrere Bilder verwendet werden, müssen
eigene Variblen vom Typ IFFInfoType definiert werden, da bei jedem neuen
Laden IFFInfo überschrieben wird.


------


VAR
  NuScreen: NewScreen;
  NuWindow: NewWindow;

Können importiert werden, um später einen Screen mit der Grafik oder ein
Window in dem Screen zu öffnen. siehe auch ReadILBM();


------


TYPE
  IFFErrors = (iffNoErr,iffOutofMem,iffOpenScreenfailed,iffOpenWindowfailed,
               iffOpenfailed,iffWrongIFF,iffReadWritefailed);
VAR
  IFFError: IFFErrors;

IFFErrors enthält die Fehlerart, wenn das Laden oder Speichern eines Bildes
erfolglos war.

iffNoErr:            Kein Fehler
iffOutofMem:         Nicht genügend Speicher
iffOpenScreenfailed: OpenScreen ist fehlgeschlagen
iffOpenWindowfailed: Es konnte kein Fenster geöffnet werden
iffOpenfailed:       File konnte nicht geöffnet werden
iffWrongIFF:         Kein IFF-File
iffReadWritefailed:  Schreib/LeseFehler


---------------------------  Prozeduren:  ---------------------------------


------  Laden von IFF-Bildern:  ------


TYPE
  ReadILBMFlags = (front,visible,dontopen,window);
  ReadILBMFlagSet = SET OF ReadILBMFlags;

PROCEDURE ReadILBM(name: ARRAY OF CHAR; Flags: ReadILBMFlagSet;
                   VAR Screen: ScreenPtr; VAR Window: WindowPtr): BOOLEAN;

ReadILBM lädt ein IFFBild mit dem Namen name. Trat ein Fehler auf, wird
FALSE zurückgegeben.
Folgende Flags können gewählt werden:

  - front:    Wenn gesetzt, wird der Screen, in den die Grafik geladen
              wird, vor allen anderen Screens geöffnet, sonst dahinter.

  - visible:  Wenn visible nicht gesetzt ist, wird während dem Laden das
              Display mit GfxMacros.OffDisplay() ausgeschaltet. Das erhöht
              die Ladegeschwindigkeit, besonders bei Bildern mit hoher
              Auflösung und/oder vielen Farben.

  - dontopen: Wenn gesetzt wird kein Screen geöffnet. Der zurückgegebene
              ScreenPtr ist dann NIL. Die Grafik wird in eine BitMap
              geladen. Der Zeiger auf die BitMap steht in
              IFFSupport.NuScreen.customBitMap. Der Screen kann später mit
              OpenScreen geöffnet werden. Bei gewähltem dontopen muß der
              Speicher für die BitPlanes und die BitMap-Struktur später
              wieder freigegeben werden.

  - window:   Wenn gesetzt wird vor dem Laden der GrafikDaten in den Screen
              ein Fenster mit der größe der Grafik geöffnet. Dadurch können
              später Gadgets, Menüs etc. hinzugefügt werden, ohne die
              Grafik zu zerstören. Ist window gelöscht, ist der WindowPtr
              NIL.

Die Laderoutine unterstützt alle Auflösungen: Lores, Hires, Interlace, Hold
and Modify, ExtraHalfBrite. Gepackte Bilder werden entpackt. Da der
Entpacker in Maschinensprache geschrieben ist, werden gepackte Bilder
schneller geladen als ungepackte.


------  ColorCycling:  ------


PROCEDURE DoCycle(Info: IFFInfoTypePtr; Screen: ScreenPtr): BOOLEAN;

PROCEDURE EndCycle(Info: IFFInfoTypePtr);

Mit DoCycle kann das ColorCycling für eine Grafik eingeschaltet werden.
Dazu wird ein VBlank-Interrupt initialisiert. Das Cycling läuft also im
Hintergrund des eigenen Programms.

DoCycle benötigt einen ScreenPtr und die Addresse eine IFFInfoType-
Variablen. Werden mehrere Bilder gleichzeitig mit ColorCycling gezeigt,
müssen auch verschieden Variablen verwendet werden ! DoCycle() gibt FALSE
zurück, wenn ein Fehler auftrat, d.h. mehr als 32 ColorCycling-Bilder
gleichzeitig eingeschaltet sind. Da dies gewöhnlich nicht der Fall ist,
kann DoCycle mit `IF DoCycle(ADR(IFFInfo),Screen) THEN END;' aufgerufen
werden.

EndCycle() stoppt das ColorCycling wieder. Dazu wird der gleiche
IFFInfoTypePtr benötigt wie bei DoCycle. EndCycle darf nicht vergessen
werden, da die Interrupts sonst von IFFSupport nicht entfernt werden. Also
spätenstens in der TermProcedure kurz vor dem Schließen des Screens
aufrufen !!!


------  Speichern von IFF-Bildern:  ------


Zum Speichern gibt es 3 ähnliche Prozeduren:


PROCEDURE WriteILBMScreen(Name: ARRAY OF CHAR;
                          Screen: ScreenPtr;
                          Rect: RectanglePtr;
                          CompressIt: BOOLEAN): BOOLEAN;

Speichert den Screen `Screen' mit dem Namen `Name'. Trat ein Fehler
(iffOpenfailed oder iffReadWritefailed) auf, wird FALSE zurückgegeben.

Ist CompressIt TRUE, wird ein gepacktes File erzeugt.

Rect kann, wenn der ganze Screen gespeichert werden soll, NIL sein. Sonst
enthält es einen Zeiger auf ein Graphics.Rectangle. Rect^.minX/minY ist
dann die linke obere und Rect^.maxX/maxY die rechte untere Ecke des
Ausschnitts. Dabei sollte man Ausschnitte größer als der Screen oder
ähnliche Späße vermeiden. Rect^.minX und Rect^.maxX brauchen keine
Vielfachen von 16 sein. Sind sie es wird jedoch schneller gespeichert.


------


PROCEDURE WriteILBM(Name: ARRAY OF CHAR;
                    RP: RastPortPtr;
                    VP: ViewPortPtr;
                    Rect: RectanglePtr;
                    CompressIt: BOOLEAN): BOOLEAN;

Speichert wie WriteILBMScreen ein IFF-File.

Name, Rect, CompressIt und der RETURN-Wert entsprechen WriteILBMScreen.

RP zeigt auf den RastPort, der die Grafikdaten enthält.

VP zeigt auf den ViewPort. der die Farben und ViewModes etc. enthält.

Mit WriteILBM kann folgendermaßen ein Fenster gespeichert (das Fenster muß
vor allen anderen Fenstern liegen):


VAR
  Window: Intuition.WindowPtr;
  Rect: Graphics.Rectangle;
  OK: BOOLEAN;

  ...

  WITH Window^ DO
    WITH Rect DO
      minX := leftEdge;
      minY := topEdge;
      maxX := minX + width - 1;
      maxY := minY + height - 1;
    END;
    OK := NOT(WriteILBM(Name,rPort,ADR(wScreen^.viewPort),ADR(Rect),TRUE));
  END;


------


PROCEDURE InitIFFInfo(Info: IFFInfoTypePtr;
                      RP: RastPortPtr;
                      VP: ViewPortPtr;
                      Rect: RectanglePtr);

PROCEDURE WriteILBMAll(Name: ARRAY OF CHAR;
                       Info: IFFInfoTypePtr;
                       BM: BitMapPtr;
                       FirstLine, LeftOffset: INTEGER;
                       CompressIt: BOOLEAN): BOOLEAN;


WriteILBMAll kann auch Bilder mit Zusatzinformationen wie ColorCycling etc.
speichern. Dazu wird die Addresse eine initialiesierten
IFFInfoType-Variablen benötigt. Um die Initialisierung zu erleichtern, kann
die Prozedur InitIFFInfo() aufgerufen werden. Ihre Parameter entsprechen
denen von WriteILBM. Danach sind die Unterrecords BMDH, CMAP und CAMG
initialisiert und deren Flags in Info^.IFFTitle gesetzt. Weitere
Unterrecords können dann `von Hand' initialisiert und deren Flags gesetzt
werden.

BM zeigt auf die BitMap, die die zu speichernden Planes enthält. BM kann
auch extra zum speichern initialisiert werden, wenn man z.B. eine
zusätzliche MaskPlane speichern möchte.

FirstLine und LeftOffset entsprechen Rect^.minY und Rect^.minX.

CompressIt und der RETURN-Wert entsprechen WriteILBMScreen.


--------------------------  Demonstartionen:  ----------------------------


------  ShowIFF:  ------


Das Programm ShowIFF lädt und zeigt ein IFF-Bild. Es lädt das vorher auf
der Workbench angeklickte oder, beim starten vom CLI, das hinter dem Namen
angegebene Bild. Bilder, die ShowIFF als Default-Tool haben (Info), können
durch einfachen Doppelklick angezeigt werden. An diesem kurzen Programm
kann man leicht die Verwendung der Ladeprozedur studieren.


------  ShowCycle:  ------


Entspricht ShowIFF für Cycle-Bilder. Normallerweise kann es auch für
nicht-Cycle Bilder verwendet werden.


------  IFFBitMapDemo:  ------


DemoProgramm zum Laden mit der Option DontOpen. Entspricht ShowIFF, öffnet
den Screen jedoch erst nach dem Laden.


------  DiaShow:  ------


Das Programm DiaShow zeigt mehrere Bilder nacheinander an. Alle Bilder, die
gezeigt werden sollen, müssen vorher mit gedrückter SHIFT-Taste ausgewählt
werden. Danach kann man DiaShow mit Doppelklick starten (SHIFT nicht
vergessen). Die Bilder werden nacheinander ein- und ausgeblendet. Der
Zeitabstand zwischen 2 Bildern beträgt 20 Sekunden. Vorher kann man mit der
rechten Maustaste das nächste Bild ansehen, wenn dieses bereits geladen
ist.

Wenn man DiaShow vom CLI aus startet, kann man die Bilder auch
unterschiedlich lang zeigen lassen. Die Anzeigadauer gibt man jeweils nach
dem Bildnamen an. Sie gilt auch für die dahinter folgenden Bilder.

Beispiel: DiaShow Bild1 10 Bild2 30 Bild3 Bild4 20

Bild1 wird 10, Bild2 und Bild3 30 und Bild4 20 Sekunden lang gezeigt.


------  CopyIFF:  ------


Lädt ein IFF-Bild wie ShowIFF und speichert es gepackt in RAM:test.iff.


------  SaveIFF:  ------


Speichert den Inhalt eines Beliebigen Fensters oder Screens als IFF-File.

Der Screen kann im Kasten links oben und das Fenster rechts daneben
ausgewählt werden. Die Angezeigten Fenster sind immer die, die im
angewählten Screen geöffnet wurden.

Save Screen speichert den ausgewählten Screen mit dem Namen im TextGadget.

Save Window macht das gleiche mit einem Fenster. Das Fenster darf
dabei von keinem anderen Überdeckt sein.

Save GimmeZZ speichert den Inhalt eines Fensters, also den Bereich, in den
man bie GimmeZeroZero-Fenstern zeichnen kann. Damit kann man Fenster ohne
Rahmen und Titelzeile speichern.

Show IFF zeigt das IFF-Bild mit dem Namen im TextGadget.


----------------------------  Copyright:  -----------------------------------


Das Modul kann von jedem in nicht kommerziellen Programmen frei verwendet
werden. Wer genügend Geld hat, kann mir auch eine Sharewaregebühr zukommen
lassen. Mein ewiger Dank ist Ihm/Ihr dann gewiß !

Bevor ein Programm, das dieses Modul benutzt kommerziell genutzt oder
vertrieben wird, muß sich der Autor mit mir in Verbindung setzten und eine
eventuelle Vergütung aushandeln.


-----------------------------------------------------------------------------


------  IFF für jedermann und jedefrau:  ------


Da das IFF-Format fast nirgends gut erklärt wird, möchte ich
versuchen, wenigsten zum Bildformat eine einigermaßen brauchbare
Beschreibung zu geben.


------  Das IFF-Bildformat:  ------


  allgemeines:
    Eine IFF-Datei beginnt mit der Kennung "FORM". Darauf folgt die
    Länge der des Datenblocks.
    Der Datenblock enthält dann die Kennung der Daten. Bei Bildern ist
    sie "ILBM".
    Darauf folgen beliebig viele Unterdatenblöcke. Sie beginnen
    jeweils mit 4 Bytes, die die Daten Kennzeichnen. Ihnen folgt ein
    Langwort, das wieder die Länge des Datenblocks angibt.

  Der Aufbau einer ILBM-Datei (vor dem Doppelpunkt jeweils die Nummer
  des Bytes):

    0  :  "FORM"       -->  Kennzeichnet IFF-Datei.
    4  :  LONGCARD     -->  Länge des Datenblocks, entspricht
            Filelänge-8, da Daten beim 8. Byte beginnen.
    8  :  "ILBM"       -->  Kennzeichnet Grafikdatei. (interleaved Bitmap)
    12 :  Unterblock 1 -->  Die verschiedenen Daten.
    x  :  Unterblock 2
    y  :  etc.

  Die Unterblöcke:

    "BMHD", BitMapHeader:

       0  : "BMHD"       --> Kennung des Blocks.
       4  : LONGCARD(20) --> Länge der Daten: 20 Bytes.
       8  : CARDINAL(dx) --> Breite der Grafik.
       10 : CARDINAL(dy) --> Höhe der Grafik.
       12 : INTEGER(x)   --> x-Position der Grafik (LeftEdge)
       14 : INTEGER(y)   --> y-Position der Grafik (TopEdge)
       16 : UBYTE(Depth) --> Anzahl der Bitplanes
       17 : UBYTE(Masking) --> Maske für Grafik. Normalerweise keine (0).
              1: Maske vorhanden , dann enthält "BODY" eine zusätz-
                 liche Bitplane mit der Maske. Diese muß dann auch geladen
                 werden.
              2: Durchsichtige Farbe , dann steht in TransparentColor
                 eine Farbnummer, die als durchsichtig gelten soll.
              3: Eine Maske kann erzeugt werden, indem man eine Art Lasso um
                 das Image wirft. Dazu zieht man eine Linie außen um das
                 Image und füllt den Innenraum von diesem Rand mit
                 transparentColor aus. Alles, was danach die Farbe
                 transparentColor hat, ist durchsichtig.
       18 : UBYTE(Compression) --> 0: Daten nicht gepackt
                                   1: Daten gapackt, siehe "BODY"
       19:  UBYTE(0)     --> nicht benutzt, muß 0 sein.
       20:  CARDINAL(transparentColor) --> Durchsichtiga Farbe, siehe
              Making.
       22:  UBYTE(xAspect), UBYTE(yAspect) --> Verzerrung des Bildes.
                         bei 320x200 normalerweise 10:11.
       24:  INTEGER(dx)  --> Breite des Screens.
       26:  INTEGER(dy)  --> Höhe des Screens.

    "CMAP", ColorMap:

       0  : "CMAP"       --> Kennung des Blocks.
       4  : LONGCARD(x)  --> Länge des Blocks, entspricht der Zahl der
              Farben durch drei. Gewöhnlich ist die Anzahl der Farben
              gerade, weshalb kein Füllbyte eingefügt werden muß.
       8  : UBYTE(Red)   --> Rotanteil Farbe 0
       9  : UBYTE(Green) --> Grünanteil
       10 : UBYTE(Blue)  --> Blauanteil
       11 : UBYTE(Red)   --> Rotanteil Farbe 1
       12 : etc.
       x+7: UByte(Blue)  --> Blauanteil Farbe (x DIV 3)

    "GRAB" definiert einen besonderen Punkt (hot spot) in der Grafik.

       0  : "GRAB"       --> Kennung.
       4  : LONGCARD(4)  --> Länge 4 Bytes.
       8  : INTEGER(x)   --> x-Position des markierten Punktes
       10 : INTEGER(y)   --> y-Position

    "DEST", destination:
       gibt an, in welche Bitplanes die GrafikDaten geschrieben werden.

       0  : "DEST"       --> Kennung.
       4  : LONGCARD(8)  --> Länge
       8  : UBYTE(Depth) --> Anzahl Planes in Quell-Grafik
       9  : UBYTE        --> Füllbyte, 0.
       10 : CARDINAL(PlanePick)  --> siehe Intuition Ref. Manual, S.192 ff
       12 : CARDINAL(PlaneOnOff)
       14 : CARDINAL(PlaneMaks)  --> zum schreiben benutzte Bitplanes.

    "CAMG", gibt besondere ViewModes an:

       0  : "CAMG"
       4  : LONGCARD(4)
       8  : LONGSET(ViewMode) --> Entspricht nicht (!) ViewModeSet{}.
                 { 2} : Interlace
                 {10} : BoublePlayField
                 {17} : Hold and Modify
                 {31} : hires

    "CRNG", für Colorcycling:

       0  : "CRNG"
       4  : LONGCARD(8)
       8  : INTEGER       --> 0, nicht benutzt.
       10 : INTEGER(rate) --> Geschwindigkeit 60 je sec = 8000H
                          -->   30 je sec: 4000H, 1 pro sec: 8000H DIV 60...
       12 : INTEGER       --> eingeschaltet: ungleich 0
       14 : UBYTE(low)    --> unterste und
       15 : UBYTE(high)   --> oberste Grenze der Farbe.

    "BODY", enthält die eigenlichen Bilddaten:

       0  : "BODY"
       4  : LONGCARD(x)  --> Länge (Höhe*Breite*Tiefe/8)
       8  : Daten.    Je nachdem, ob in "BMHD" Compressed gewählt
                      wurde, gepackt oder nicht.

       ungepackte BitMapDaten:

           Daten der Reihe nach gespeichert: Zuerst 1. Zeile 1.
           Bitplane, dann 1. Zeile 2. Bitplane etc. Danach 2. Zeile 1.
           Bitplane, 2. Zeile 2. Bitplane etc.

       gepackte BitMapDaten:

           gepackt wird nur innerhalb einer Zeile. Die Zeilen sind der
           Reihe nach wie bei ungepackt gespeichert.
           Gepackt wird Byteweise:
           Ist ein Byte
           0..127  : bedeutet das: Die nächsten n+1 (1..128) Bytes
                     unverändert in die Grafik laden.
           129..255: Das folgende Byte wird 257-n mal hintereinanger in die
                     Grafik kopiert.
           128     : keine Funktion.

    weitere Datenblocks:
      "SPRT"    für Sprites
      "CCRT"    Graphiccraft: Colorcycling
      "CMHD"    Graphiccraft (???)
      "DPPV"    Graphiccraft (???)

      ein Ladeprogramm sollte Daten, die unbekannte Kennungen haben,
      einfach überlesen. Die Länge steht ja jeweils im folgenden
      Langwort.

  Ein ILBM-File muß die Blocks "BMHD" und "BODY" enthalten. "CMAP"
  sollte vorhanden sein. Alle anderen sind optional.

Beispiel:
  0000: 464F524D 0000567A 494C424D 424D4844    FORM..VzILBMBMHD
  0010: 00000014 014000C8 00000000 05020100    .....@..........
  0020: 00020A0B 014000C8 434D4150 00000060    .....@..CMAP...`
  0030: 00000090 10000000 00200020 30003040    ......... . 0.0@
  0040: 10305010 40602050 70305080 4060A050    .0P.@` Pp0P.@`.P
  0050: 70B06070 C07080D0 9090E0A0 A0F0C0C0    p.`p.p..........
  0060: F06020D0 5020B040 10903010 60301040    .` .P .@..0.`0.@
  0070: 20103000 000000B0 0000A000 00A00000     .0.............
  0080: A00000A0 0000A000 00A00000 A00000A0    ................
  0090: 44505056 00000068 00000000 00000000    DPPV...h........
  00A0: 01680000 014000C8 0002005A 00020000    .h...@.....Z....
  00B0: 00020000 00020000 00000000 00000000    ................
  00C0: 00000000 00000000 00000000 00000000    ................
  00D0: 00000000 00000000 00000000 00010002    ................
  00E0: 00000000 00000000 00000000 00010002    ................
  00F0: 00000000 00000000 00000000 00010002    ................
  0100: 43524E47 00000008 19961800 0002020F    CRNG............
  0110: 43524E47 00000008 29304E78 00039D26    CRNG....)0Nx...&
  0120: 43524E47 00000008 DD41AB4A FFFFFFF7    CRNG.....A.J....
  0130: 43524E47 00000008 0047FFF4 00000001    CRNG.....G......
  0140: 424F4459 00005539 11043336 01EFDC3F    BODY..U9..36...?
  0150: DCC00000 0161000D FFFF40F9 00026130    .....a....@...a0
  0160: 03FE0004 B5C0C890 E1FE0011 FDC337FF    ..............7.

  Dies ist ein Beispiel für eine Lores-Grafik mit der Auflösung 320
  mal 200 (14H: 0140H; 16H: 0C8H). Die Tiefe beträgt 5 Bitplanes
  (1CH), deshalb besteht sie aus 32 Farben (in 2CH steht 60H, durch 3
  also 20H=32). Die Daten in DPPV sollten überlesen werden. Die 4 CRNG
  Blöcke sind meist auch unwichtig.

-- Fridtjof.
