summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CloseIFF.S67
-rw-r--r--Source/CompressBlock.S144
-rw-r--r--Source/DecodePic.S232
-rw-r--r--Source/DecompressBlock.S107
-rw-r--r--Source/FindChunk.S83
-rw-r--r--Source/GetBMHD.S71
-rw-r--r--Source/GetColorTab.S94
-rw-r--r--Source/GetViewModes.S124
-rw-r--r--Source/IFFError.S140
-rw-r--r--Source/IFFLib.S324
-rw-r--r--Source/IFFLib.i54
-rw-r--r--Source/Makefile108
-rw-r--r--Source/ModifyFrame.S258
-rw-r--r--Source/OpenIFF.S193
-rw-r--r--Source/SaveBitMap.S82
-rw-r--r--Source/SaveClip.S490
16 files changed, 2571 insertions, 0 deletions
diff --git a/Source/CloseIFF.S b/Source/CloseIFF.S
new file mode 100644
index 0000000..b463eaa
--- /dev/null
+++ b/Source/CloseIFF.S
@@ -0,0 +1,67 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: CloseIFF.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_CloseIFF
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_CloseIFF
+ SECTION text,CODE
+
+ INCLUDE "IffLib.i"
+
+ XREF ClearError
+ XDEF CloseIFFFunc
+
+
+******* iff.library/IFFLib_CloseIFF *****************************************
+*
+* NAME
+* IFFLib_CloseIFF -- Close an IFF-file and deallocate buffers
+*
+* SYNOPSIS
+* IFFLib_CloseIFF( ifffile )
+* A1
+*
+* void IFFLib_CloseIFF( IFFFILE )
+*
+* FUNCTION
+* Returns the memory previously allocated by OpenIFF().
+*
+* INPUTS
+* ifffile - IFF file pointer, from OpenIFF()
+*
+* RESULTS
+* For now, always results TRUE (this may change in the future).
+*
+* SEE ALSO
+* IFFLib_OpenIFF()
+*
+*****************************************************************************
+
+CloseIFFFunc: movem.l a5-a6,-(SP)
+ movea.l a6,a5 ; IFFBase für ClearError()
+
+ move.l a1,d0 ; Ist a1 == NULL ?
+ beq.s 1$ ; ja ---> don't free anything
+ move.l -(a1),d0 ; Grösse des reservierten Bereichs
+ movea.l ib_SysBase(a5),a6
+ JSRLIB FreeMem
+1$: bsr ClearError ; IFFError zurücksetzen, D0 := 1
+
+ movem.l (SP)+,a5-a6
+ rts
+
+ END
diff --git a/Source/CompressBlock.S b/Source/CompressBlock.S
new file mode 100644
index 0000000..14984ec
--- /dev/null
+++ b/Source/CompressBlock.S
@@ -0,0 +1,144 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: CompressBlock.S $
+** $Author: Christian A. Weber $
+** $Release: $
+** $Date: 92/05/12 22:26:30 $
+**
+** iff.library/IFFLib_CompressBlock
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_CompressBlock
+ SECTION text,CODE
+
+ INCLUDE "IffLib.i"
+
+ XREF ClearError
+ XDEF CompressBlockFunc
+
+
+******* iff.library/IFFLib_CompressBlock ************************************
+*
+* NAME
+* IFFLib_CompressBlock -- Compress a memory block
+*
+* SYNOPSIS
+* result = IFFLib_CompressBlock( source, destination, size, mode )
+* A0 A1 D0 D1
+*
+* ULONG IFFLib_CompressBlock( APTR, APTR, ULONG, ULONG )
+*
+* FUNCTION
+* Compress the memory block using the appropriate compression mode.
+* If the compressed data would become longer than the uncompressed,
+* an error is returned.
+*
+* INPUTS
+* source - Pointer to data to compress
+* destination - Target address for compression
+* size - Number of data bytes to compress
+* mode - Compression mode. Currently, the following modes
+* are supported:
+* $$$
+*
+* RESULTS
+* Length of compressed data or 0 if an error occurred.
+*
+* SEE ALSO
+* IFFLib_DecompressBlock()
+*
+*****************************************************************************
+
+CompressBlockFunc:
+ tst.l d1 ; Modus == 0 ?
+ beq.b Mode_Copy
+ subq.l #1,d1 ; Modus == 1 ?
+ beq.b Mode_CmpByteRun1
+ moveq.l #0,d0
+ rts
+
+*****************************************************************************
+** Kopiermodus
+
+Mode_Copy: movem.l d0/a6,-(SP)
+ movea.l ib_SysBase(a6),a6
+ JSRLIB CopyMem
+ movem.l (SP)+,d0/a6
+ rts
+
+*****************************************************************************
+** CmpByteRun1 komprimieren
+
+Mode_CmpByteRun1:
+ movem.l d2-d3/a2-a3,-(SP)
+ lea (a0,d0.l),a2 ; A2 : Source-Endadresse
+ moveq #0,d3 ; Byte-Zähler
+
+crunchloop: bsr.b CountEq ; wieviele gleiche Bytes folgen ?
+ cmp.w #3,d0 ; genug gleiche Bytes zum runnen ?
+ blt.b countdump ; nee, lohnt sich nicht -> Dumpen
+
+ addq.l #2,d3 ; Markierbyte & Anzahl
+ move.b (a0),d1 ; Wert
+ adda.w d0,a0 ; Source anpassen
+ subq.w #1,d0 ; muss .w sein und nicht .b !!!!!!!
+ neg.b d0 ; negieren (= "Run"-Code)
+ move.b d0,(a1)+ ; und eintragen
+ move.b d1,(a1)+ ; Wert eintragen
+ bra.b crunchcont ; weitermachen
+
+countdump: movea.l a0,a3 ; Source-Pointer retten
+ moveq #0,d2 ; D2 : Länge des Dump-Blocks
+1$: addq.b #1,d2
+ bmi.b 2$ ; höchstens 127 Bytes pro Block
+ addq.l #1,a0
+ cmpa.l a2,a0 ; Ende der Linie erreicht ?
+ bge.b 3$ ; ja -> abbrechen
+ bsr.b CountEq
+ cmp.w #3,d0 ; Ende des Dump-Blocks ?
+ blt.b 1$ ; noch nicht
+ bra.b 3$ ; Ende
+2$: moveq #127,d2
+3$: movea.l a3,a0 ; Source-Pointer restaurieren
+
+ add.l d2,d3 ; zur Gesamtanzahl dazuzählen
+ addq.l #1,d3 ; Markierbyte nicht vergessen
+ subq.w #1,d2 ; aus 1..128 mach 0..127
+ move.b d2,(a1)+ ; Markierbyte eintragen
+4$: move.b (a0)+,(a1)+ ; Datenbytes eintragen
+ dbf d2,4$
+
+
+crunchcont: cmpa.l a2,a0 ; Ende der Linie erreicht ?
+ blt.b crunchloop ; noch nicht!
+
+ move.l d3,d0 ; Return: Anzahl Destination-Bytes
+ movem.l (SP)+,d2-d3/a2-a3
+ rts
+
+ *** Anzahl gleicher Zeichen ab (a0) zählen und nach D0
+
+CountEq: move.l a0,-(SP)
+ moveq #1,d0 ; D0 : Anzahl gleiche Bytes
+1$: move.b (a0)+,d1 ; erstes Byte
+2$: cmp.b (a0)+,d1 ; Byte gleich wie letztes Byte ?
+ bne.b 3$ ; nein -> abbrechen
+ cmp.w #128,d0
+ bge.b 3$ ; höchstens 128 gleiche
+ addq.w #1,d0 ; Anzahl erhöhen
+ cmpa.l a2,a0 ; Ende der Linie erreicht ?
+ blt.b 2$ ; noch nicht -> weiterzählen
+3$: move.l (SP)+,a0
+ rts
+
+ END
+
diff --git a/Source/DecodePic.S b/Source/DecodePic.S
new file mode 100644
index 0000000..e8877a5
--- /dev/null
+++ b/Source/DecodePic.S
@@ -0,0 +1,232 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: DecodePic.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_DecodePic
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_DecodePic
+ SECTION text,CODE
+
+ INCLUDE "IFFLib.i"
+
+ XREF ClearError,SetError,GetBMHDFunc,FindChunkFunc
+ XDEF DecodePicFunc
+
+
+******* iff.library/IFFLib_DecodePic ****************************************
+*
+* NAME
+* IFFLib_DecodePic -- decode the BODY of an ILBM file into a BitMap
+*
+* SYNOPSIS
+* success = IFFLib_DecodePic( ifffile, bitmap )
+* D0 A1 A0
+*
+* BOOL IFFLib_DecodePic( IFFFILE, struct BitMap * )
+*
+* FUNCTION
+* Decodes and decompresses a picture into the user supplied BitMap.
+* If the picture is larger than your BitMap's planes, it will be
+* truncated. If your BitMap is larger than the picture, the picture
+* will be drawn into the top left corner of your BitMap.
+* If the picture has less planes than the BitMap, the unused planes
+* are NOT touched by this routine, so you may wish to clear them
+* before calling IFFLib_DecodePic(). If the picture has more planes
+* than your BitMap, the surplus planes of the picture are ignored.
+*
+* INPUTS
+* ifffile - IFF file pointer, from IFFLib_OpenIFF()
+* bitmap - Pointer to a properly initialized BitMap structure:
+* bm_Planes[] must point to valid BitPlanes,
+* bm_Depth contains the number of planes.
+* bm_Width and bm_Height must be set according to the
+* size of your bit planes.
+*
+* RESULTS
+* Non-zero if OK, 0 if error, Call IFFError() to know the reason
+* of the failure
+*
+* NOTE
+* This routine needs at least 620 bytes of stack space
+*
+* SEE ALSO
+*
+*****************************************************************************
+
+ STRUCTURE DecodePicStackFrame,0
+ STRUCT WorkPlanes,24*4 ; muß am Anfang sein
+ STRUCT LineBuffer,400 ; max 3200 pixel bei stencil
+ LABEL LINKSIZE
+
+DecodePicFunc: movem.l d2-d7/a2-a6,-(SP)
+ lea -LINKSIZE(SP),SP ; Lokalen Datenraum schaffen
+ movea.l a6,a5 ; A5: IFFBase für SetError()
+ movea.l a0,a3 ; A3: BitMap
+ movea.l a1,a4 ; A4: IFFFile
+
+ *** Testen ob ILBM-File
+
+ cmpi.l #'ILBM',8(a4) ; ist's überhaupt ein ILBM-File ?
+ beq.s 1$ ; ja --->
+ moveq #IFF_NOILBM,d0 ; Fehlernummer
+ bra .Error
+1$:
+ *** BitMapHeader suchen und nach A2
+
+ bsr GetBMHDFunc ; BitMapHeader suchen
+ ;; tst.l d0
+ bne.s 2$ ; gefunden --->
+ moveq #IFF_NOBMHD,d0 ; Fehlernummer
+ bra .Error
+2$: movea.l d0,a2 ; A2: BitMapHeader
+
+ *** Testen ob Bild-Depth <= BitMap Depth
+
+ move.b bmh_nPlanes(a2),d2 ; D2: Depth (Minimum)
+ beq .Okay ; Bild hat 0 planes --->
+3$:
+ *** Planes in Arbeitsbereich kopieren
+
+ moveq.l #23,d0 ; Max. 24 Bitplanes
+ lea bm_Planes(a3),a0 ; Source
+ lea WorkPlanes(SP),a1 ; Destination
+.CopyLoop: move.l (a0)+,(a1)+
+ dbf d0,.CopyLoop
+
+ *** BODY-Chunk suchen und nach A0, BODY-Ende nach A4
+
+ move.l #'BODY',d0
+ movea.l a4,a1 ; IFF-File
+ bsr FindChunkFunc
+ ;; tst.l d0
+ bne.s 4$ ; gefunden --->
+ moveq #IFF_NOBODY,d0 ; Fehlernummer
+ bra .Error
+4$:
+ movea.l d0,a0 ; A0 : Body-Adresse
+ addq.l #4,a0 ; 'BODY' überspringen
+ movea.l (a0)+,a4 ; Chunk-size
+ adda.l a0,a4 ; A4 : Body-Endadresse
+
+ *** Compression testen und entsprechende Routine nach A6
+
+ move.b bmh_Compression(a2),d0
+ bne.s 5$
+ lea CopyRow(PC),a6 ; Not crunched
+ bra.s 7$ ; --->
+5$:
+ cmpi.b #1,d0 ; CmpByteRun1 ?
+ bne.s 6$ ; ja --->
+ lea DecrunchRow(PC),a6 ; CmpByteRun1
+ bra.s 7$ ; --->
+6$:
+ moveq #IFF_UNKNOWNCOMPRESSION,d0
+ bra.s .Error
+7$:
+ *** Masking testen und wenn 'hasmask' (Stencil) D7.B:=$FF, sonst $00
+
+ cmpi.b #1,bmh_Masking(a2) ; 'mskHasMask' ?
+ seq d7 ; wenn ja: D7 := $FF
+
+ *** Modulos setzen etc.
+
+.doit: moveq.l #0,d4 ; D4 : Source-Modulo
+ move.w bmh_Width(a2),d4
+ add.w #15,d4 ; auf WORD aufrunden
+ lsr.l #3,d4
+ bclr #0,d4 ; auf WORD aufrunden
+
+ moveq.l #0,d5
+ move.w bm_BytesPerRow(a3),d5 ; D5 : Destination-Modulo
+
+ moveq.l #0,d6
+ move.w bm_Rows(a3),d6 ; D6 : Max. Anzahl Zeilen
+ cmp.w bmh_Height(a2),d6 ; BitMap zu groß ?
+ ble.s 8$ ; nein --->
+ move.w bmh_Height(a2),d6 ; Sonst Höhe aus bmh nehmen
+8$:
+ bra.s .CheckCond ; ---> für dbf
+
+ *** Hauptschleife
+
+.body1: moveq #0,d3 ; Init plane-counter
+ lea WorkPlanes(SP),a2 ; A2 : Arbeitskopie der Planes
+
+.body2: move.l d4,d0 ; Source bytes per row
+ cmp.b bm_Depth(a3),d3 ; Is there a dest-plane ?
+ bhs.s .NoDest ; nope ---> skip it
+ movea.l (a2),a1 ; Adrese der aktuellen Plane
+ add.l d5,(a2)+ ; Plane auf nächste Linie
+ bra.s 9$
+.NoDest: lea LineBuffer(SP),a1 ; Plane ins NIL kopieren
+9$: jsr (a6) ; Linie copyren / decrunchen
+ addq.b #1,d3 ; INC planecounter
+ cmp.b d2,d3
+ blt.s .body2 ; ---> Nächste Plane
+
+ tst.b d7 ; Maske zu überhüpfen ?
+ beq.s .NoMask ; nein --->
+ move.l d4,d0 ; Source bytes per row
+ lea LineBuffer(SP),a1 ; Maske zur Hölle schicken
+ jsr (a6) ; Linie copyren / decrunchen
+.NoMask:
+.CheckCond: cmpa.l a4,a0 ; fertig ?
+ dbhs d6,.body1 ; wenn nicht: nächste Linie
+
+.Okay: bsr ClearError ; IFFError rücksetzen, D0 := 1
+ bra.s .Ende
+
+.Error: bsr SetError ; IFFError setzen, clr.l d0
+
+.Ende: lea LINKSIZE(SP),SP
+ movem.l (SP)+,d2-d7/a2-a6
+ rts
+
+
+*************** 1 Linie kopieren *****************************************
+
+copyloop: move.b (a0)+,(a1)+
+CopyRow: dbf d0,copyloop
+ rts
+
+
+*************** 1 Linie decrunchen ***************************************
+
+DecrunchRow: move.l d2,-(SP)
+
+1$: moveq.l #0,d1
+ move.b (a0)+,d1 ; D1 : nächstes Kommando-Byte
+ bmi.s 2$ ; crunched --->
+
+.CopyLoop: move.b (a0)+,(a1)+ ; D1+1 Bytes normal kopieren
+ subq.w #1,d0 ; DEC ColumnCounter
+ dble d1,.CopyLoop
+ bra.s 3$ ; --->
+2$:
+ neg.b d1
+ bmi.s 3$ ; ~$80 (== $80) ist 'NOP'
+ move.b (a0)+,d2 ; Zu repetierender Wert
+.RepLoop: move.b d2,(a1)+
+ subq.w #1,d0 ; DEC ColumnCounter
+ dble d1,.RepLoop
+3$:
+ tst.w d0 ; Linie fertig ?
+ bgt.s 1$ ; noch nicht ---> Loop
+
+ move.l (SP)+,d2
+ rts
+
+ END
diff --git a/Source/DecompressBlock.S b/Source/DecompressBlock.S
new file mode 100644
index 0000000..f6c8ec5
--- /dev/null
+++ b/Source/DecompressBlock.S
@@ -0,0 +1,107 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: DecompressBlock.S $
+** $Author: Christian A. Weber $
+** $Release: $
+** $Date: 92/05/12 22:26:30 $
+**
+** iff.library/IFFLib_DecompressBlock
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_DecompressBlock
+ SECTION text,CODE
+
+ INCLUDE "IffLib.i"
+
+ XREF ClearError
+ XDEF DecompressBlockFunc
+
+
+******* iff.library/IFFLib_DecompressBlock ************************************
+*
+* NAME
+* IFFLib_DecompressBlock -- Decompress a memory block
+*
+* SYNOPSIS
+* result = IFFLib_DecompressBlock( source, destination, size, mode )
+* A0 A1 D0 D1
+*
+* ULONG IFFLib_DecompressBlock( APTR, APTR, ULONG, ULONG )
+*
+* FUNCTION
+* Decompress the memory block using the appropriate Decompression mode.
+* If the Decompressed data would become longer than the unDecompressed,
+* an error is returned.
+*
+* INPUTS
+* source - Pointer to data to decompress
+* destination - Target address for decompression
+* size - Number of data bytes to decompress
+* mode - Compression mode. Currently, the following modes
+* are supported:
+* $$$
+*
+* RESULTS
+* Length of uncompressed data or 0 if an error occurred.
+*
+* SEE ALSO
+* IFFLib_CompressBlock()
+*
+*****************************************************************************
+
+DecompressBlockFunc:
+ tst.l d1 ; Modus == 0 ?
+ beq.b Mode_Copy
+ subq.l #1,d1 ; Modus == 1 ?
+ beq.b Mode_CmpByteRun1
+ moveq.l #0,d0
+ rts
+
+*****************************************************************************
+** Kopiermodus
+
+Mode_Copy: movem.l d0/a6,-(SP)
+ movea.l ib_SysBase(a6),a6
+ JSRLIB CopyMem
+ movem.l (SP)+,d0/a6
+ rts
+
+*****************************************************************************
+** CmpByteRun1 dekomprimieren
+
+Mode_CmpByteRun1:
+ move.l d2,-(SP)
+
+1$: moveq.l #0,d1
+ move.b (a0)+,d1 ; D1 : nächstes Kommando-Byte
+ bmi.b 2$ ; crunched --->
+
+.CopyLoop: move.b (a0)+,(a1)+ ; D1+1 Bytes normal kopieren
+ subq.l #1,d0 ; DEC length counter
+ dble d1,.CopyLoop
+ bra.b 3$ ; --->
+2$:
+ neg.b d1
+ bmi.b 3$ ; ~$80 (== $80) ist 'NOP'
+ move.b (a0)+,d2 ; Zu repetierender Wert
+.RepLoop: move.b d2,(a1)+
+ subq.l #1,d0 ; DEC ColumnCounter
+ dble d1,.RepLoop
+3$:
+ tst.l d0 ; Linie fertig ? (Braucht's das tst??)
+ bgt.b 1$ ; noch nicht ---> Loop
+
+ move.l (SP)+,d2
+ rts
+
+ END
+
diff --git a/Source/FindChunk.S b/Source/FindChunk.S
new file mode 100644
index 0000000..2ddea63
--- /dev/null
+++ b/Source/FindChunk.S
@@ -0,0 +1,83 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: FindChunk.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_FindChunk
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_FindChunk
+ SECTION text,CODE
+
+ INCLUDE "IffLib.i"
+
+ XDEF FindChunkFunc
+
+
+******* iff.library/IFFLib_FindChunk ****************************************
+*
+* NAME
+* IFFLib_FindChunk -- find an IFF-chunk
+*
+* SYNOPSIS
+* chunk = IFFLib_FindChunk( ifffile, chunkname )
+* D0 A1 D0
+*
+* APTR IFFLib_FindChunk( IFFFILE, ULONG )
+*
+* FUNCTION
+* Find a specific chunk in an IFF file
+*
+* INPUTS
+* ifffile - pointer to a FORM, normally the result of OpenIFF()
+* chunkname - 4 characters packed ASCII ('BODY', 'VHDR' ...)
+* if chunkname is 0, FindChunk() returns a pointer to the
+* first byte after the end of the current FORM. This can
+* be used byANIM readers for jumping from FORM to FORM.
+*
+* RESULTS
+* Pointer to the beginning of the chunk (that means to the chunk
+* name itself, followed by the chunk size); zero if chunk not found
+*
+* BUGS
+* none known
+*
+* SEE ALSO
+* IFFLib_GetBMHD(), IFFLib_GetColorTab()
+*
+*****************************************************************************
+
+FindChunkFunc: movea.l 4(a1),a0 ; FORM-Länge
+ addq.l #8,a1 ; FORM.... überspringen
+ adda.l a1,a0 ; A0 zeigt jetzt ans Ende
+ addq.l #4,a1 ; FORM-Typ überspringen
+ tst.l d0 ; Chunk-ID == 0 ?
+ bne.s 1$ ; nein --->
+ movea.l a0,a1 ; Sonst Ende des FORMs
+ bra.s 99$ ; zurückgeben
+
+1$: cmp.l (a1),d0 ; Chunk gefunden ?
+ beq.s 99$ ; ja!
+ move.l 4(a1),d1 ; Länge dieses Chunks
+ addq.l #1,d1 ; auf WORD ...
+ bclr #0,d1 ; ... aufrunden
+ lea 8(a1,d1.l),a1 ; Name & Länge dazu und zu A1 dazu
+ cmpa.l a0,a1 ; FORM-Ende erreicht ?
+ bcs.s 1$ ; noch nicht --->
+ suba.l a1,a1 ; Code für "nicht gefunden"
+99$:
+ move.l a1,d0 ; Resultat nach D0, set/reset Z-Flag
+ rts
+
+ END
diff --git a/Source/GetBMHD.S b/Source/GetBMHD.S
new file mode 100644
index 0000000..35aec40
--- /dev/null
+++ b/Source/GetBMHD.S
@@ -0,0 +1,71 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: GetBMHD.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_GetBMHD
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_GetBMHD
+ SECTION text,CODE
+
+ INCLUDE "IffLib.i"
+
+ XREF SetError,ClearError,FindChunkFunc
+ XDEF GetBMHDFunc
+
+
+******* iff.library/IFFLib_GetBMHD ******************************************
+*
+* NAME
+* IFFLib_GetBMHD -- find a BitMapHeader of an IFF-file
+*
+* SYNOPSIS
+* header = IFFLib_GetBMHD( ifffile )
+* D0 A1
+*
+* struct BitMapHeader *IFFLib_GetBMHD( IFFFILE )
+*
+* FUNCTION
+* Returns a pointer to a 'BitMapHeader' structure as defined in
+* iff.h and iff.i
+*
+* INPUTS
+* ifffile - IFF file pointer, returned by IFFLib_OpenIFF()
+*
+* RESULTS
+* Pointer to the BitMapHeader, or NULL if no BMHD chunk found
+*
+* SEE ALSO
+* IFFLib_FindChunk(), IFFLib_GetColorTab()
+*
+*****************************************************************************
+
+GetBMHDFunc: movem.l d2/a5-a6,-(SP)
+ movea.l a6,a5 ; IFFBase für ClearError()
+ move.l #'BMHD',d0
+ bsr FindChunkFunc ; setzt Z-Flag wenn not found
+ bne.s 1$ ; Chunk gefunden --->
+ moveq.l #IFF_NOBMHD,d0
+ bsr SetError
+ bra.s 99$
+1$:
+ addq.l #8,d0 ; BMHD.... überspringen
+ move.l d0,d2
+ bsr ClearError
+ move.l d2,d0
+99$: movem.l (SP)+,d2/a5-a6
+ rts
+
+ END
diff --git a/Source/GetColorTab.S b/Source/GetColorTab.S
new file mode 100644
index 0000000..e7adcb6
--- /dev/null
+++ b/Source/GetColorTab.S
@@ -0,0 +1,94 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: GetColorTab.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_GetColorTab
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_GetColorTab
+ SECTION text,CODE
+
+ INCLUDE "IFFLib.i"
+
+ XREF FindChunkFunc
+ XDEF GetColorTabFunc
+
+
+******* iff.library/IFFLib_GetColorTab **************************************
+*
+* NAME
+* IFFLib_GetColorTab -- find a CMAP and convert it to a ColorTable
+*
+* SYNOPSIS
+* count = IFFLib_GetColorTab( ifffile, colortable )
+* D0 A1 A0
+*
+* FUNCTION
+* Searches the CMAP chunk of an IFF file and converts it, if it's
+* there, to an Amiga color table structure. This colortable can
+* directly be used as a parameter for the LoadRGB4() function.
+*
+* INPUTS
+* ifffile - IFF file pointer, returned by IFFLib_OpenIFF()
+* colortable - Pointer to a block of memory which must be large
+* enough to hold the colortable (2 bytes per color).
+* Must be WORD aligned.
+*
+* RESULT
+* Number of colors actually found, or zero if the file has no
+* CMAP chunk
+*
+* SEE ALSO
+* IFFLib_FindChunk(), IFFLib_GetBMHD()
+*
+*****************************************************************************
+
+GetColorTabFunc:
+ movem.l d2-d5/a2,-(SP)
+ movea.l a0,a2 ; Ziel-Adresse
+
+ move.l #'CMAP',d0
+ bsr FindChunkFunc
+ ;; tst.l d0
+ beq.s 99$ ; nicht gefunden --->
+ movea.l d0,a0
+
+ addq.l #4,a0 ; Chunk-Namen überlesen
+ move.l (a0)+,d4 ; Chunk-size
+ divs #3,d4 ; Anzahl Farben
+ ext.l d4 ; für D0
+ move.l d4,d0 ; Resultat: Anzahl Farben
+
+ moveq #256-$f0,d5 ; Color-Maske $f0
+ neg.b d5 ; Toebes-Optimierlung
+ bra.s 1$ ; Für dbf
+
+.Loop: move.b (a0)+,d1 ; rot
+ and.w d5,d1 ; Nur Bits 7-4 benützen
+ move.b (a0)+,d2 ; grün
+ and.w d5,d2 ; Nur Bits 7-4 benützen
+ move.b (a0)+,d3 ; blau
+ and.w d5,d3 ; Nur Bits 7-4 benützen
+ lsl.w #4,d1 ; rot << 4
+ lsr.w #4,d3 ; blau >> 4
+ or.w d2,d1
+ or.w d3,d1
+ move.w d1,(a2)+ ; in Farbtabelle eintragen
+1$: dbf d4,.Loop
+99$:
+ movem.l (SP)+,d2-d5/a2
+ rts
+
+ END
diff --git a/Source/GetViewModes.S b/Source/GetViewModes.S
new file mode 100644
index 0000000..e6a10c6
--- /dev/null
+++ b/Source/GetViewModes.S
@@ -0,0 +1,124 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: GetViewModes.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_GetViewModes
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_GetViewModes
+ SECTION text,CODE
+
+ INCLUDE "IffLib.i"
+
+ XREF FindChunkFunc,GetBMHDFunc
+ XDEF CalcViewModes ; für SaveClip.S
+ XDEF GetViewModesFunc
+
+
+******* iff.library/IFFLib_GetViewModes **************************************
+*
+* NAME
+* IFFLib_GetViewModes() -- Get Amiga-specific ViewModes
+*
+* SYNOPSIS
+* viewmodes = IFFLib_GetViewModes( ifffile )
+* D0 A1
+*
+* ULONG IFFLib_GetViewModes( IFFFILE )
+*
+* FUNCTION
+* Searches the IFF file for a 'CAMG' chunk which holds the view modes
+* information. If there is no CAMG chunk, the view modes are calcu-
+* lated using the information in the BitMapHeader structure.
+* You can directly put the low WORD of the result of a GetViewModes()
+* call into the ns_ViewModes field of a NewScreen structure. All
+* forbidden bits are masked out, as suggested by CBM.
+*
+* INPUTS
+* ifffile - IFF file pointer, returned from OpenIFF()
+*
+* RESULT
+* viewmodes - LONG containing the view modes (HAM, LACE, HIRES ...)
+* Under Kickstart V1.3, only the lower WORD is used.
+*
+* BUGS
+* If the IFF file has no CAMG chunk and 6 bitplanes, the HAM bit
+* will be set. This is not always correct since the picture could
+* be in the Extra Halfbrite mode. You can load such Halfbrite
+* pictures into DPaint III and save them again, DPaint will generate
+* the correct CAMG chunk.
+*
+* SEE ALSO
+*
+*****************************************************************************
+
+ *** Flags, die nur in graphics/view.h aber nicht .i sind (!)
+
+HAM: EQU $0800
+SPRITES: EQU $4000
+VP_HIDE: EQU $2000
+GENLOCK_AUDIO: EQU $0100
+GENLOCK_VIDEO: EQU $0002
+EXTRA_HALFBRITE: EQU $0080
+
+MODESMASK: EQU ~(SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO)
+
+GetViewModesFunc:
+ move.l a2,-(SP)
+
+ movea.l a1,a2 ; A2 : IFFFile
+ move.l #'CAMG',d0
+ bsr FindChunkFunc ; setzt Z-Flag wenn not found
+ beq.s CalcEm ; not found ---> Berechnen
+ movea.l d0,a0 ; Zeiger auf CAMG....
+ move.l 8(a0),d0 ; ViewModes
+ andi.l #MODESMASK,d0 ; Verbotene Bits ausmaskieren
+ bra.s Ende ; --->
+
+ *** ViewModes aus BMHD berechnen, 0 falls kein CAMG
+
+CalcEm: movea.l a2,a1 ; IFFFile
+ bsr GetBMHDFunc ; BitMapHeader suchen
+ ;; tst.l d0 ; nicht gefunden?
+ beq.s Ende ; dann 0 zurückgeben
+ movea.l d0,a0 ; A0 : BMHD-Struktur
+ bsr.s CalcViewModes ; ViewModes nach D0
+
+ cmpi.b #6,bmh_nPlanes(a0) ; 6 Bitplanes ?
+ blt.s Ende ; nein --->
+ bset #11,d0 ; ViewModes |= HAM
+Ende:
+ movea.l (SP)+,a2
+ rts
+
+ *** ViewModes berechnen, A0 = struct BitMapHeader
+ *** Diese Routine wird auch von SaveClip() benutzt
+
+CalcViewModes: moveq.l #0,d0 ; D0 : ViewModes
+
+ cmpi.b #4,bmh_nPlanes(a0) ; mehr als 4 Planes ?
+ bgt.s NotHiRes ; ja ---> nicht HiRes
+
+ cmpi.w #400,bmh_Width(a0) ; Bildbreite > 400 ?
+ ble.s NotHiRes ; nein --->
+ bset #15,d0 ; ViewModes |= HiRes
+NotHiRes:
+ cmpi.w #320,bmh_Height(a0) ; Bildhöhe > 320 ?
+ blt.s NotInterlace ; nein --->
+ bset #2,d0 ; ViewModes |= Interlace
+NotInterlace:
+ rts
+
+ END
diff --git a/Source/IFFError.S b/Source/IFFError.S
new file mode 100644
index 0000000..3472f59
--- /dev/null
+++ b/Source/IFFError.S
@@ -0,0 +1,140 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: IFFError.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_IFFError
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_IFFError
+ SECTION text,CODE
+
+ INCLUDE "IFFLib.i"
+
+ XDEF FindOurNode,SetError,ClearError
+ XDEF IFFErrorFunc
+
+
+******* iff.library/IFFLib_IFFError *****************************************
+*
+* NAME
+* IFFLib_IFFError -- Get detailed error descrpition
+*
+* SYNOPSIS
+* error = IFFLib_IFFError()
+* D0
+*
+* LONG IFFLib_IFFError( void )
+*
+* FUNCTION
+* If one of the above functions returns zero, you can call
+* IFFLib_IFFError() to know the reason for the failure. An error
+* code is returned, please refer to the files 'iff.h' or 'iff.i'
+* for the complete list of errors.
+*
+* INPUTS
+* none
+*
+* RESULT
+* Error-number generated by the latest function call, or zero if
+* no error
+*
+* Cuurently the following numbers are used:
+*
+* Nr. Symbol Function Description
+*
+* 16 IFF_CANTOPENFILE OpenIFF() File not found
+* 17 IFF_READERROR OpenIFF() Read() returned an error
+* 18 IFF_NOMEM OpenIFF() Not enough memory for the file
+* 19 IFF_NOTIFF OpenIFF() File is not IFF
+* 20 IFF_WRITEERROR SaveBitMap() Cannot write the file
+*
+* 24 IFF_NOILBM DecodePic() IFF file is not an ILBM file
+* 25 IFF_NOBMHD DecodePic() BMHD chunk not found
+* 26 IFF_NOBODY DecodePic() BODY chunk not found
+* 27 IFF_TOOMANYPLANES DecodePic() Picture has more planes than the
+* BitMap (OBSOLETE SINCE 18.7!)
+* 28 IFF_UNKNOWNCOMPRESSION " Unknown compression type
+* 29 IFF_NOANHD ModifyFrame() ANHD chunk not found
+* 30 IFF_NODLTA ModifyFrame() DLTA chunk not found
+*
+* -1 IFF_BADTASK A task which did not open the IFF library
+* tried to call IFFError(). Since the IFF
+* library is capable of multi-tasking, the
+* error-values are stored for each task
+* separately.
+*
+* BUGS
+* If you don't close the IFF library at the end of your program
+* (using CloseLibrary()) the error node will not be freed. The
+* same task will then not be able to re-open the iff.library.
+* (This is not a bug, it's a feature ;-))
+*
+* SEE ALSO
+*
+*****************************************************************************
+
+ *** Unseren Node nach D0 und A0 bringen, Set Z-Flag if not found
+
+FindOurNode: movea.l ib_SysBase(a5),a6
+ move.l ThisTask(a6),d1
+ move.l ib_ErrList(a5),d0 ; 1. Node in Error Liste
+
+.findloop: movea.l d0,a0 ; next node
+ move.l LN_SUCC(a0),d0
+ beq.s .findend ; ---> Ende (Z-Flag gesetzt)
+ cmp.l er_Task(a0),d1 ; Unser Node ?
+ bne.s .findloop
+ move.l a0,d0 ; unser Node, Clear Z-Flag
+.findend: rts
+
+
+*****************************************************************************
+
+ClearError: bsr FindOurNode ; Node nach D0 und A0
+ ;; tst.l d0
+ beq.s 1$ ; no node ---> nichts eintragen
+ clr.l er_Error(a0)
+1$: moveq #1,d0 ; Code für 'OK'
+ rts
+
+*****************************************************************************
+
+SetError: move.l d0,-(SP) ; Error-Nummer retten
+ bsr FindOurNode ; Node nach D0 und A0
+ ;; tst.l d0
+ beq.s 1$ ; no node ---> nichts eintragen
+ move.l (SP),er_Error(a0)
+1$:
+ addq.l #4,SP
+ moveq #0,d0 ; Code für 'Error'
+ rts
+
+
+*****************************************************************************
+
+IFFErrorFunc: movem.l a5-a6,-(SP)
+ movea.l a6,a5 ; IFFBase
+ bsr FindOurNode ; Node nach D0 und A0
+ ;; tst.l d0
+ beq.s 1$ ; kein Node ---> Fehler!!
+ move.l er_Error(a0),d0
+ clr.l er_Error(a0) ; Error rücksetzen
+2$: movem.l (SP)+,a5-a6
+ rts
+1$:
+ moveq #IFF_BADTASK,d0
+ bra.s 2$
+
+ END
diff --git a/Source/IFFLib.S b/Source/IFFLib.S
new file mode 100644
index 0000000..2150632
--- /dev/null
+++ b/Source/IFFLib.S
@@ -0,0 +1,324 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: IFFLib.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** Disk-resident library for simple IFF file I/O. Does not handle
+** nested PROPs and CATs. Contains special ILBM support routines.
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+** Modification history
+** --------------------
+**
+** Date Version Modification
+**
+** 14-Sep-87 V 1.0 Created this file!
+** 24-Oct-87 V 6.1 Writing crunched ILBMs now works
+** 27-Nov-87 V 7.1 Fully multi-tasking compatible and reentrant
+** 14-Dec-87 V 8.1 SaveClip() fixed
+** 07-Feb-88 V 9.1 bmhd.Width is now WORD aligned, for DPaint
+** 20-Feb-88 V 10.1 IffError() implemented, Source split into files
+** 06-Mar-88 V 11.1 Stencil pictures are correctly decoded
+** 08-Mar-88 V 12.1 GetViewModes() implemented
+** 24-Mar-88 V 14.1 8SVX files go automatically to CHIP RAM
+** 30-Jun-88 V 15.1 CMAP size bug fixed (3*64 instead of 2*32)
+** 30-Jun-88 V 15.2 SaveClip() now generates CAMG chunks
+** 20-Jul-88 V 15.3 Closes DOS library if started as a command
+** 16-Nov-88 V 15.4 GetViewModes(): upto 384 pixels is now LoRes
+** 30-Nov-88 V 15.5 DecodePic() rounds bmhd.width up to WORDs
+** 01-Dec-88 V 16.1 NewOpenIFF() with MemType added
+** 03-Mar-89 V 16.2 GetBMHD now sets IFFError (0 or IFF_NOBMHD)
+** 18-Mar-89 V 16.3 GetViewModes(): upto 400 LoRes, 320 hor. NoLace
+** 16-May-89 V 16.4 Code cleaned up, labels capitalized etc.
+** 21-Feb-90 V 18.1 Uses CBM include files, GetColorTab() fixed
+** 25-Feb-90 V 18.2 ModifyFrame() added
+** 26 Feb-90 V 18.3 Decruncher handles corrupt pics & height=0
+** 28-Feb-90 V 18.4 DecodePic() handles depth=1 again
+** 12-Mar-90 V 18.5 OpenIFF() liest nicht mehr 4 Bytes zuviel ein
+** 11-Apr-90 V 18.6 DecodePic geht auch wenn bm.Depth < bmh.Depth
+** 13-Apr-90 V 18.7 DecodePic geht bis 24 Bitplanes
+** 07-Oct-90 V 19.1 SaveClip() speichert 256 Farben bei 24 Planes
+** An neue 2.0 Includefiles angepasst (JSRLIB..)
+
+ IDNT IFFLib
+ SECTION text,CODE
+
+* PP_VERSION
+
+ INCLUDE "IFFLib.i"
+
+ XREF FindOurNode ; Error-Node finden
+
+ XREF OpenIFFFunc
+ XREF CloseIFFFunc
+ XREF FindChunkFunc
+ XREF GetBMHDFunc
+ XREF GetColorTabFunc
+ XREF DecodePicFunc
+ XREF SaveBitMapFunc
+ XREF SaveClipFunc
+ XREF IFFErrorFunc
+ XREF GetViewModesFunc
+ XREF NewOpenIFFFunc
+ XREF ModifyFrameFunc
+ IFD PP_VERSION
+ XREF PPOpenIFFFunc
+ ENDC
+
+
+ IFD PP_VERSION
+VERSION: EQU 100 ; D0 bei OpenLibrary
+REVISION: EQU 3 ; jedesmal um 1 erhöhen
+ ELSEIF
+VERSION: EQU 19 ; D0 bei OpenLibrary
+REVISION: EQU 1 ; jedesmal um 1 erhöhen
+ ENDC
+
+
+*************** C O D E *****************************************************
+
+FirstByte:
+ bra.s 1$
+ dc.b "CHW!"
+1$:
+ *** wird aufgerufen, wenn mann die Library vom CLI aus startet
+
+ lea DOSName(PC),a1 ; dos.library öffnen
+ movea.l 4.W,a6
+ JSRLIB OldOpenLibrary
+ movea.l d0,a6 ; DosBase
+ JSRLIB Output
+ move.l d0,d1 ; file: stdout
+ lea MyLibInfo(PC),a0 ; Adresse des ID-Strings
+ move.l a0,d2
+ IFD PP_VERSION
+ moveq.l #65,d3 ; Länge des ID-Strings
+ ELSEIF
+ moveq.l #45,d3 ; Länge des ID-Strings
+ ENDC
+ JSRLIB Write
+ movea.l a6,a1
+ movea.l 4.W,a6
+ JSRLIB CloseLibrary ; For Chris
+ moveq.l #5,d0 ; return-code: WARN
+ rts
+
+*****************************************************************************
+
+MyROMTag: DC.W RTC_MATCHWORD
+ DC.L MyROMTag ; RT_MATCHTAG
+ DC.L EndCode ; Ende der Library
+ DC.B RTF_AUTOINIT
+ DC.B VERSION
+ DC.B NT_LIBRARY
+ DC.B 0 ; Priorität
+ DC.L MyLibName ; Name der Bibliothek
+ DC.L MyLibInfo ; Name, Version, Revision etc.
+ DC.L Init ; Zeiger auf Init-Struktur
+
+ IFD PP_VERSION
+MyLibName: DC.B "iffpp.library",0
+MyLibInfo: DC.B "IFFPP 100.3 (01-Jul-1990) Copyright © 1990 by Christian A. Weber",10,0
+ ELSEIF
+MyLibName: DC.B "iff.library",0
+MyLibInfo: DC.B "IFF 19.1 (09-Oct-1990) by Christian A. Weber",10,0
+ ENDC
+
+DOSName: DC.B "dos.library",0
+
+ EVEN
+Init: DC.L ib_SIZEOF ; data space size
+ DC.L FuncTable ; Zeiger auf Funktions-Initializers
+ DC.L DataTable ; Zeiger auf Data-Initializers
+ DC.L InitRoutine ; Initialisierungs-Routine
+
+
+FuncTable: ;; DC.W -1 ; Switch to WORD-Offset-Mode
+
+ *** Die 4 Standard Library Routinen:
+
+ DC.L OpenFunc ; Offset -6
+ DC.L CloseFunc ; Offset -12
+ DC.L ExpungeFunc ; Offset -18
+ DC.L ExtFunc ; Offset -24
+
+ *** Jetzt unsere IFF-Routinen:
+
+ DC.L OpenIFFFunc ; Offset -30
+ DC.L CloseIFFFunc ; Offset -36
+ DC.L FindChunkFunc ; Offset -42
+ DC.L GetBMHDFunc ; Offset -48
+ DC.L GetColorTabFunc ; Offset -54
+ DC.L DecodePicFunc ; Offset -60
+ DC.L SaveBitMapFunc ; Offset -66
+ DC.L SaveClipFunc ; Offset -72
+ DC.L IFFErrorFunc ; Offset -78
+ DC.L GetViewModesFunc ; Offset -84
+ DC.L NewOpenIFFFunc ; Offset -90
+ DC.L ModifyFrameFunc ; Offset -96
+ IFD PP_VERSION
+ DC.L PPOpenIFFFunc ; Offset -102
+ ENDC
+
+ DC.L -1 ; End-Markierung
+
+ *** Daten zur Initialisierung der Library-Struktur
+
+DataTable: INITBYTE LN_TYPE,NT_LIBRARY
+ INITLONG LN_NAME,MyLibName
+ INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
+ INITWORD LIB_VERSION,VERSION
+ INITWORD LIB_REVISION,REVISION
+ INITLONG LIB_IDSTRING,MyLibInfo
+ DC.L 0
+
+*****************************************************************************
+
+ *** D0: Library Base, A0: Segment list, A6: SysBase
+
+InitRoutine: movem.l d0-d1/a0-a1/a5,-(SP)
+ movea.l d0,a5 ; Library pointer
+ move.l a6,ib_SysBase(a5) ; Save SysBase
+ move.l a0,ib_SegList(a5) ; Save SegList
+
+ *** Dos-Library öffnen
+
+ lea DOSName(PC),a1 ; dos.library öffnen
+ JSRLIB OldOpenLibrary
+ move.l d0,ib_DOSBase(a5) ; DosBase merken
+
+ *** Error-Liste initialisieren
+
+ lea ib_ErrList(a5),a0
+ move.l a0,(a0) ; NewList
+ addq.l #4,(a0)
+ clr.l 4(a0)
+ move.l a0,8(a0)
+
+ movem.l (SP)+,d0-d1/a0-a1/a5 ; d0/a5 wiederherstellen
+ rts ; Library jetzt benutzbar
+
+*****************************************************************************
+
+ *** wird jedesmal bei OpenLibrary() aufgerufen, A6: IFFBase
+
+OpenFunc: movem.l d1/a0-a2/a5-a6,-(SP)
+ movea.l a6,a5 ; A5 : IFFBase
+
+ *** Testen ob schon ein Node für uns vorhanden ist
+
+ bsr FindOurNode ; Set Z bit if not found
+ bne.s .OpenError ; Schon vorhanden ---> Error
+
+ *** Speicher für neuen Error-Node reservieren
+
+ moveq.l #er_SIZEOF,d0 ; Amount
+ move.l #MEMF_PUBLIC|MEMF_CLEAR,d1 ; Requirements
+ movea.l ib_SysBase(a5),a6
+ JSRLIB AllocMem
+ tst.l d0
+ beq.s .OpenError ; Error ---> 0 zurückgeben
+ movea.l d0,a2 ; A2 :  ErrorNode
+
+ *** Error-Node initialisieren: Task eintragen
+
+ move.l ThisTask(a6),er_Task(a2)
+
+ *** Error-Node an Liste anhängen
+
+ lea ib_ErrList(a5),a0 ; Liste
+ movea.l a2,a1 ; Node
+ JSRLIB AddTail
+
+ *** Normales Library-Zeug
+
+ addq.w #1,LIB_OPENCNT(a5)
+ bclr.b #LIBB_DELEXP,LIB_FLAGS(a5)
+ move.l a5,d0 ; Return IFFBase
+99$:
+ movem.l (SP)+,d1/a0-a2/a5-a6
+ rts ; Library ist jetzt offen
+
+.OpenError: moveq.l #0,d0 ; ERROR!
+ bra.s 99$
+
+*****************************************************************************
+
+ *** Wird jedesmal bei CloseLibrary() aufgerufen, A6: IFFBase
+
+CloseFunc: movem.l a2/a5-a6,-(SP)
+ movea.l a6,a5 ; IFFBase
+
+ *** Error-Node suchen und entfernen
+
+ bsr FindOurNode ; our error-node nach D0 & A0
+ beq.s 1$ ; nicht gefunden --->
+ movea.l d0,a2 ; ErrorNode retten
+ movea.l d0,a1
+ movea.l ib_SysBase(a5),a6
+ JSRLIB Remove
+
+ moveq.l #er_SIZEOF,d0
+ movea.l a2,a1
+ JSRLIB FreeMem
+1$: movem.l (SP)+,a2/a5-a6
+
+ *** Normales Library-Zeugs
+
+ moveq.l #0,d0 ; return-code
+ subq.w #1,LIB_OPENCNT(a6)
+ bne.s 2$ ; jemand hat sie noch offen
+
+ btst.b #LIBB_DELEXP,LIB_FLAGS(a6) ; haben wir delayed Expunge?
+ beq.s 2$ ; neenee --->
+ bsr.s ExpungeFunc ; sonst Expunge
+2$:
+ rts ; Library ist jetzt zu
+
+*****************************************************************************
+
+ *** Wird beim letzten CloseLibrary aufgerufen, A6: IFFBase
+
+ExpungeFunc: movem.l d2/a5-a6,-(SP)
+ movea.l a6,a5 ; IFFBase
+
+ tst.w LIB_OPENCNT(a5) ; sind wir noch offen?
+ beq.s 1$ ; nein
+ bset.b #LIBB_DELEXP,LIB_FLAGS(a5)
+ moveq.l #0,d0 ; return-code
+ bra.s 99$
+1$:
+ movea.l a5,a1 ; LibPtr (zeigt auf NODE)
+ movea.l ib_SysBase(a5),a6
+ JSRLIB Remove ; Library aus Liste entfernen
+
+ movea.l ib_DOSBase(a5),a1 ; dos.library schliessen
+ JSRLIB CloseLibrary
+ move.l ib_SegList(a5),d2 ; Segmentliste retten
+
+ moveq.l #0,d0
+ movea.l a5,a1 ; LibPtr
+ move.w LIB_NEGSIZE(a5),d0 ; Grösse der Sprungtabelle
+ sub.w d0,a1 ; A1 := Anfang der Sprungtab.
+ add.w LIB_POSSIZE(a5),d0 ; D0 := Lib-Grösse gesamt
+ JSRLIB FreeMem ; freigeben
+ move.l d2,d0 ; return-code: Segmentliste
+
+99$: movem.l (SP)+,d2/a5-a6
+
+ExtFunc: rts ; wird aufgerufen bei Offset -24
+
+*****************************************************************************
+
+EndCode: ; muss hier am Schluss stehen, siehe ROMTag-Struktur
+
+ END
diff --git a/Source/IFFLib.i b/Source/IFFLib.i
new file mode 100644
index 0000000..4c0bc8a
--- /dev/null
+++ b/Source/IFFLib.i
@@ -0,0 +1,54 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: IFFLib.i $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** Include-File für alle Module der IFF-Library
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+ OPT O+
+ OPT OW-
+
+ INCLUDE "exec/types.i"
+ INCLUDE "exec/memory.i"
+ INCLUDE "exec/nodes.i"
+ INCLUDE "exec/libraries.i"
+ INCLUDE "exec/resident.i"
+ INCLUDE "exec/initializers.i"
+ INCLUDE "exec/macros.i"
+ INCLUDE "exec/execbase.i"
+ INCLUDE "dos/dos.i"
+ INCLUDE "graphics/gfx.i"
+
+ INCLUDE "h:iff.i" ; Standard IFF include file
+
+*****************************************************************************
+
+ STRUCTURE IFFBaseStructure,LIB_SIZE
+
+ APTR ib_SysBase
+ APTR ib_DOSBase
+ APTR ib_SegList
+ STRUCT ib_ErrList,LH_SIZE
+
+ LABEL ib_SIZEOF
+
+*****************************************************************************
+
+ STRUCTURE ErrorNode,LN_SIZE
+
+ APTR er_Task
+ LONG er_Error
+
+ LABEL er_SIZEOF
+
diff --git a/Source/Makefile b/Source/Makefile
new file mode 100644
index 0000000..73af717
--- /dev/null
+++ b/Source/Makefile
@@ -0,0 +1,108 @@
+##
+## $Id: $
+## $Revision: $
+##
+## $Filename: Makefile $
+## $Author: Christian A. Weber $
+## $Release: 19.1 $
+## $Date: 92/05/11 21:11:27 $
+##
+## Makefile to build iff.library and utilities
+##
+## COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+## CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+## OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+## IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+## MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+##
+
+LIBDEST = SYS:Libs-User/
+
+#############################################################################
+## Allgemeine Flags
+
+CFLAGS = -cfustq -fid -ms -v -rr -s -O
+AFLAGS = -iINCLUDE:
+LFLAGS = ADDSYM
+
+# -b0 = Nicht a4-relativ
+# -cf = prototypes testen
+# -cr = Register-Parameter mit prototypes
+# -cs = Gleiche Strings nur einmal nehmen
+# -ct = Warnung bei undef'd structure tags
+# -cu = Alle chars sind unsigned
+# -d2 = voll debug info, DEBUG-Symbol wird definiert
+# -ff = FFP
+# -fi = IEEEDoubBas
+# -f8 = 68881 direkt
+# -fd = alle floats sind double
+# -m0 = 68000er Code
+# -m2 = 68020er Code
+# -ms = Code reducing optimization
+# -mt = Time reducing optimization
+# -O = Optimizer on
+# -rr = Argument passing immer in Registers
+# -s = Section names angeben (text/data/udata)
+# -v = Stack checking ausschalten
+# -w = 16 Bit ints
+
+
+#############################################################################
+## Regeln
+
+.s.o:
+ Genim2 -l -iINCLUDE: $*.S
+.c.o:
+ LC $(CFLAGS) $*.c
+
+
+#############################################################################
+## Files
+
+all: iff.library iffpp.library
+
+
+#############################################################################
+## iff.library
+
+IFFLIB_MODS = \
+ ifflib.o openiff.o closeiff.o findchunk.o getbmhd.o\
+ getcolortab.o decodepic.o savebitmap.o saveclip.o ifferror.o\
+ getviewmodes.o modifyframe.o
+
+$(IFFLIB_MODS): IFFLib.i
+
+iff.library: $(IFFLIB_MODS)
+ BLINK FROM $(IFFLIB_MODS) TO T:___iff LIB LIB:small.lib
+ @AbsLoad >NIL: -©oiff.library T:___iff
+ @Delete T:___iff
+ @Protect iff.library rwd
+# @Echo "Copying library to $(LIBDEST)"
+# @Copy iff.library $(LIBDEST)
+ FlushLibs
+ @FlushLibs
+# @iff.library
+
+
+#############################################################################
+## iffpp.library
+
+IFFPPLIB_MODS = $(IFFLIB_MODS) ppopeniff.o ppopeniffc.o
+
+iffpp.library: $(IFFPPLIB_MODS)
+ BLINK FROM $(IFFPPLIB_MODS) TO T:___iff LIB LIB:small.lib
+ @AbsLoad >NIL: -©oiffpp.library T:___iff
+ @Delete T:___iff
+ @Protect iffpp.library rwd
+# @Echo "Copying library to $(LIBDEST)"
+# @Copy iffpp.library $(LIBDEST)
+ FlushLibs
+ @FlushLibs
+# @iffpp.library
+
+ppopeniffc.o: ppopeniffc.c
+ lc -v -b0 $*.c
+
+
+#############################################################################
+
diff --git a/Source/ModifyFrame.S b/Source/ModifyFrame.S
new file mode 100644
index 0000000..46fe5ec
--- /dev/null
+++ b/Source/ModifyFrame.S
@@ -0,0 +1,258 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: ModifyFrame.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_ModifyFrame
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_ModifyFrame
+ SECTION text,CODE
+
+ INCLUDE "IFFLib.i"
+
+ XREF ClearError,SetError,FindChunkFunc
+ XDEF ModifyFrameFunc
+
+
+******* iff.library/IFFLib_ModifyFrame **************************************
+*
+* NAME
+* IFFLib_ModifyFrame -- Modify an anim frame using a DLTA chunk
+*
+* SYNOPSIS
+* success = IFFLib_ModifyFrame( modifyform, bitmap )
+* D0 A1 A0
+*
+* BOOL IFFLib_ModifyFrame( void *, struct BitMap * )
+*
+* FUNCTION
+* Uses the DLTA chunk of the supplied FORM to modify the planes-data
+* of the bitmap. Usually, playback of ANIMs will require two buffers,
+* and double-buffering between them. So the data in the bitmap must
+* be two frames back, and the DLTA chunk is used to modify the hidden
+* frame to the next frame to be shown.
+*
+* INPUTS
+* modifyform - pointer to the FORM containing the actual DLTA chunk
+* bitmap - Pointer to a properly initialized BitMap structure,
+* the planes must contain the image which was displayed
+* to frames back (using double-buffering)
+*
+* RESULT
+* Non-zero if OK, 0 if error; call IFFError() to know the reason
+* of the failure
+*
+* RESTRICTIONS
+* Currently, only compression type 5 (Byte Vertical Delta Mode) is
+* implemented. If you have animations which use modes 1 to 4, try
+* loading them with DPaint III and saving them again.
+* Sculpt-Animate pictures do not work, because I have no documentation
+* about the compression scheme they use.
+* I will implement some more compression types upon request.
+*
+* WARNINGS
+* This routine needs at least 820 bytes of stack.
+* The size of the bitmap is not checked by this routine, the planes
+* must have at least the size described in the BMHD of the anim
+* file.
+*
+* BUGS
+*
+*****************************************************************************
+
+ModifyFrameFunc:
+ movem.l d2-d7/a2-a6,-(SP)
+ movea.l a6,a5 ; A5: IFFBase für SetError()
+ movea.l a1,a4 ; A4: IFFFile
+ move.w bm_BytesPerRow(a0),d3 ; D3: BytesPerRow
+ move.w bm_Rows(a0),d4 ; D4: Rows
+ moveq.l #0,d5
+ move.b bm_Depth(a0),d5 ; D5: Depth
+ lea bm_Planes(a0),a3 ; A3: Plane-Array
+
+ *** Multiplikations-Tabelle aufbauen
+
+ move.w d4,d7 ; bm_Rows
+ add.w d7,d7 ; D7: StackFrameSize
+ suba.w d7,SP ; StackFrame erstellen
+
+ movea.l SP,a0 ; MultTable
+ moveq.l #0,d0 ; Reset offset
+ move.w d4,d1 ; bm_Rows
+ bra.s 2$ ; Für dbf
+1$: move.w d0,(a0)+
+ add.w d3,d0 ; Offset += BytesPerRow
+2$: dbf d1,1$
+
+ *** Testen ob's ein ILBM-FORM ist
+
+ cmpi.l #'ILBM',8(a4) ; ILBM-Form ?
+ beq.s 3$ ; ja --->
+ moveq #IFF_NOILBM,d0 ; Fehlernummer
+ bra .Error
+3$:
+ *** AnimHeader suchen und nach A2
+
+ move.l #'ANHD',d0
+ movea.l a4,a1 ; IFF-File
+ bsr FindChunkFunc
+ ;; tst.l d0
+ bne.s 4$ ; gefunden --->
+ moveq #IFF_NOANHD,d0 ; Fehlernummer
+ bra .Error
+4$:
+ addq.l #8,d0 ; ANHD.... überhüpfen
+ movea.l d0,a2 ; A2: AnimHeader
+
+ *** Compression-Mode testen und entsprechende Routine nach A6
+
+ move.b anh_Operation(a2),d0
+ cmpi.b #5,d0 ; SuperDuperZapperMode ?
+ bne.s 5$ ; nein --->
+ lea MakePlane(PC),a6
+ bra.s 6$
+5$:
+ moveq #IFF_UNKNOWNCOMPRESSION,d0
+ bra.s .Error
+6$:
+ *** DLTA-Chunk finden und nach A4
+
+ movea.l a4,a1 ; IFFFile
+ move.l #'DLTA',d0
+ bsr FindChunkFunc ; Start der Daten
+ bne.s 7$ ; gefunden --->
+ moveq #IFF_NODLTA,d0 ; Fehlernummer
+ bra .Error
+7$:
+ addq.l #8,d0 ; DLTA.... überhüpfen
+ movea.l d0,a4 ; A4: Delta-Chunk
+
+ *** Alle Planes verändern
+
+ movea.l SP,a2 ; Y-Multiplikationstabelle
+ moveq.l #0,d2 ; D2: Offset-Zeiger (hmm..)
+ bra.s 9$ ; Für dbf
+.PlaneLoop: move.l 0(a4,d2.w),d0 ; n-ter Offset
+ beq.s 8$ ; Null ---> Plane bleibt
+ movea.l a4,a0 ; Delta-Daten-Start
+ adda.l d0,a0 ; Offset dazu
+ movea.l (a3),a1 ; nächste Destination-Plane
+ move.w d3,d0 ; BytesPerRow für Decruncher
+ jsr (a6) ; Tada, Plane verändern
+8$: addq.w #4,d2 ; Offset erhöhen
+ addq.l #4,a3 ; Next Plane
+9$: dbf d5,.PlaneLoop
+
+ bsr ClearError ; IFFError rücksetzen, D0:=1
+ bra.s .Ende ; --->
+.Error: bsr SetError ; IFFError setzen, clr.l d0
+.Ende: adda.w d7,SP ; Stack aufräumen
+ movem.l (SP)+,d2-d7/a2-a6
+ rts
+
+*****************************************************************************
+
+ *** Mit Daten (A0) Plane (A1) verändern, A2=Multiplikationstabelle
+
+MakePlane: movem.l d0-d5/a0-a1/a3,-(SP)
+ move.w d0,d2 ; BytesPerRow
+ move.w d2,d4 ; Kolonnen-Zähler
+ bra ColumnDbf ; für dbf
+
+ColumnLoop: movea.l a1,a3 ; Destination-Pointer
+ moveq.l #0,d0
+ move.b (a0)+,d0 ; # Befehle dieser Kolonne
+ bra OpLoopDbf ; für dbf
+
+OpLoop: moveq.l #0,d1
+ move.b (a0)+,d1 ; Nächster Befehl
+ bmi CopyBytes ; CopyBytes-Run --->
+ beq RepByte ; RepeatByte-Run --->
+
+ *** SkipLines-Befehl
+
+ add.w d1,d1 ; Anzahl Linien zu überhüpfen
+ adda.w 0(a2,d1.w),a3 ; Destination neu setzen
+ bra OpLoopDbf ; ---> Nächster Befehl
+
+ *** RepeatByte-Befehl
+
+RepByte: move.b (a0)+,d1 ; Anzahl
+ move.b (a0)+,d3 ; Zu repetierender Wert
+ move.w d1,d5 ; Anzahl Durchläufe ..
+ asr.w #3,d5
+ andi.w #7,d1 ; .. und Rest berechnen
+ add.w d1,d1
+ add.w d1,d1
+ neg.w d1
+ jmp 32+RepLoop(PC,d1.w) ; 8*sizeof move/add
+RepLoop: move.b d3,(a3)
+ adda.w d2,a3
+ move.b d3,(a3)
+ adda.w d2,a3
+ move.b d3,(a3)
+ adda.w d2,a3
+ move.b d3,(a3)
+ adda.w d2,a3
+ move.b d3,(a3)
+ adda.w d2,a3
+ move.b d3,(a3)
+ adda.w d2,a3
+ move.b d3,(a3)
+ adda.w d2,a3
+ move.b d3,(a3)
+ adda.w d2,a3
+ dbf d5,RepLoop
+ bra OpLoopDbf ; ---> Nächster Befehl
+
+ *** CopyBytes-Befehl
+
+CopyBytes: andi.w #$7f,d1 ; Anzahl Bytes zu kopieren
+ move.w d1,d5 ; Anzahl Durchläufe ..
+ asr.w #3,d5
+ andi.w #7,d1 ; .. und Rest berechnen
+ add.w d1,d1
+ add.w d1,d1
+ neg.w d1
+ jmp 32+CopyBytesLoop(PC,d1.w)
+CopyBytesLoop: move.b (a0)+,(a3)
+ adda.w d2,a3
+ move.b (a0)+,(a3)
+ adda.w d2,a3
+ move.b (a0)+,(a3)
+ adda.w d2,a3
+ move.b (a0)+,(a3)
+ adda.w d2,a3
+ move.b (a0)+,(a3)
+ adda.w d2,a3
+ move.b (a0)+,(a3)
+ adda.w d2,a3
+ move.b (a0)+,(a3)
+ adda.w d2,a3
+ move.b (a0)+,(a3)
+ adda.w d2,a3
+ dbf d5,CopyBytesLoop
+
+OpLoopDbf: dbf d0,OpLoop
+
+ColumnCont: addq.l #1,a1 ; Destination erhöhen
+ColumnDbf: dbf d4,ColumnLoop ; Nächste Kolonne --->
+
+ movem.l (SP)+,d0-d5/a0-a1/a3
+ rts
+
+*****************************************************************************
+
+ END
diff --git a/Source/OpenIFF.S b/Source/OpenIFF.S
new file mode 100644
index 0000000..2b0d026
--- /dev/null
+++ b/Source/OpenIFF.S
@@ -0,0 +1,193 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: OpenIFF.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_OpenIFF
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_OpenIFF
+ SECTION text,CODE
+
+ INCLUDE "IFFLib.i"
+
+ XREF SetError,ClearError
+ XDEF OpenIFFFunc,NewOpenIFFFunc
+
+
+******* iff.library/IFFLib_NewOpenIFF ***************************************
+*
+* NAME
+* IFFLib_NewOpenIFF -- allocate memory for an IFF-file and read it
+*
+* SYNOPSIS
+* ifffile = IFFLib_NewOpenIFF( filename, memattr )
+* D0 A0 D0
+*
+* IFFFILE IFFLib_OpenIFF( char * )
+*
+* FUNCTION
+* This function opens a file on a disk and looks whether it's an IFF
+* file or not. If it is an IFF file, memory is allocated and the file
+* is read into memory. The 'memattr' argument is taken to define the
+* memory type. Normally memattr is set to MEMF_ANY or MEMF_PUBLIC.
+* If an error occurs, NULL is returned, and you can call
+* IFFLib_IFFError() to get the error number.
+*
+* INPUTS
+* filename - Pointer to a null-terminated string
+* memattr - Memory requirements as used for Exec's AllocMem(),
+* such as MEMF_CHIP, MEMF_PUBLIC ...
+* (MEMF_CLEAR is not necessary)
+*
+* RESULT
+* ifffile - 'FileHandle', points to the beginning of the IFF file
+* ("FORM...."), Zero if unsuccessful. Call IFFLib_IFFError() to get
+* the reason of the failure.
+*
+* SEE ALSO
+* IFFLib_OpenIFF(), IFFLib_CloseIFF(), IFFLib_IFFError()
+*
+* BUGS
+* None known
+*
+*****************************************************************************
+
+OpenIFFFunc: movem.l d2-d6/a2/a5-a6,-(SP)
+ moveq.l #-1,d6 ; Kein MemType angegeben
+ bra.s DoCont
+
+
+
+******* iff.library/IFFLib_OpenIFF ******************************************
+*
+* NAME
+* IFFLib_OpenIFF -- allocate memory for an IFF-file and read it
+*
+* SYNOPSIS
+* ifffile = IFFLib_OpenIFF( filename )
+* D0 A0
+*
+* IFFFILE IFFLib_OpenIFF( char * )
+*
+* FUNCTION
+* This function does the same as the IFFLib_NewOpenIFF() routine
+* above, except that you cannot specify the type of memory which is
+* allocated for the file. Normally the type is 0 which means 'any
+* memory', but if the IFF file type is '8SVX', the file is ALWAYS
+* loaded into CHIP memory. If you wish to override these defaults,
+* use IFFLib_NewOpenIFF() instead of IFFLib_OpenIFF().
+*
+* INPUTS
+* filename - Pointer to a null-terminated string
+*
+* RESULT
+* ifffile - 'FileHandle', points to the beginning of the IFF file
+* ("FORM...."), 0 if unsuccessful. Call IFFError() to get the
+* reason of the failure.
+*
+* BUGS
+* None
+*
+* SEE ALSO
+* IFFLib_NewOpenIFF(), IFFLib_CloseIFF(), IFFLib_IFFError()
+*
+*****************************************************************************
+
+NewOpenIFFFunc: movem.l d2-d6/a2/a5-a6,-(SP)
+ move.l d0,d6 ; D6 : MemType
+DoCont: movea.l a6,a5 ; IFFBase
+ lea -12(SP),SP ; Arbeitsspeicher reservieren
+ moveq.l #0,d5 ; Fehlernummer rücksetzen
+
+ *** File öffnen
+
+ move.l a0,d1 ; Name
+ move.l #MODE_OLDFILE,d2 ; accessmode
+ movea.l ib_DOSBase(a5),a6
+ JSRLIB Open
+ move.l d0,d4 ; D4 := FileHandle
+ bne.s 1$
+ moveq #IFF_CANTOPENFILE,d5
+ bra.s .Error2 ; --->
+1$:
+ *** Erste 12 Bytes lesen, testen ob 'FORM'
+
+ move.l d4,d1 ; File
+ move.l SP,d2 ; Adr
+ moveq.l #12,d3 ; Len
+ JSRLIB Read ; erste 3 Longwords lesen
+ cmpi.l #'FORM',(SP)
+ beq.s 2$
+ moveq #IFF_NOTIFF,d5
+ bra.s .Error1 ; --->
+2$:
+ *** Testen ob Chip-Speicher erwünscht (bei 8SVX-Files)
+
+ move.l d6,d1 ; Default-Requirements
+ bpl.s 3$ ; sind gültig --->
+ moveq.l #MEMF_PUBLIC,d1
+ cmpi.l #'8SVX',8(SP) ; 8SVX-File ?
+ bne.s 3$ ; nein --->
+ moveq.l #MEMF_CHIP|MEMF_PUBLIC,d1 ; sonst CHIP-Memory!
+3$:
+ *** Speicher für File reservieren
+
+ moveq.l #12,d2 ; 'Remember' + FORM....
+ move.l 4(SP),d3 ; D3 : FORM-Länge
+ add.l d3,d2 ; D2 : Gesamtlänge
+ subq.l #4,d3 ; FUCK!!! IFF-Typ ist ja schon gelesen!
+ move.l d2,d0
+ movea.l ib_SysBase(a5),a6
+ JSRLIB AllocMem ; requirements von D1
+ movea.l d0,a2 ; A2 : IFFFile-Adresse
+ tst.l d0
+ bne.s 4$ ; OK --->
+ moveq #IFF_NOMEM,d5
+ bra.s .Error1 ; --->
+4$:
+ *** File einladen
+
+ move.l d2,(a2)+ ; Länge des reserv. Bereichs
+ move.l d4,d1 ; File
+ move.l a2,d2 ; Adr
+ addq.l #8,d2 ; FORM.... schon gelesen!
+ addq.l #4,d2 ; IFF-Typ schon gelesen
+ movea.l ib_DOSBase(a5),a6
+ JSRLIB Read ; D3 war schon Länge
+ tst.l d0
+ bpl.s 5$ ; OK --->
+ moveq #IFF_READERROR,d5
+ bra.s .Error1
+5$:
+ movem.l (SP),d0-d2 ; FORM, Länge und Type
+ movem.l d0-d2,(a2) ; IFF-Filetyp
+
+.Error1: move.l d4,d1 ; File
+ movea.l ib_DOSBase(a5),a6
+ JSRLIB Close
+
+.Error2: move.l d5,d0 ; Error ?
+ beq.s 6$ ; nein --->
+ bsr SetError ; Löscht auch D0
+ bra.s Ende
+6$:
+ bsr ClearError
+ move.l a2,d0 ; Adresse als Return-Code
+Ende:
+ lea 12(SP),SP ; Lokalen Speicher freigeben
+ movem.l (SP)+,d2-d6/a2/a5-a6
+ rts
+
+ END
diff --git a/Source/SaveBitMap.S b/Source/SaveBitMap.S
new file mode 100644
index 0000000..15607c3
--- /dev/null
+++ b/Source/SaveBitMap.S
@@ -0,0 +1,82 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: SaveBitMap.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_SaveBitMap
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_SaveBitMap
+ SECTION text,CODE
+
+ INCLUDE "IFFLib.i"
+
+ XREF SaveClipFunc
+ XDEF SaveBitMapFunc
+
+
+******* iff.library/IFFLib_SaveBitMap ***************************************
+*
+* NAME
+* IFFLib_SaveBitMap -- save the planes of a BitMap as an IFF-file
+*
+* SYNOPSIS
+* result = IFFLib_SaveBitMap( filename, bitmap, colortable, flags )
+* D0 A0 A1 A2 D0
+*
+* BOOL IFFLib_SaveBitMap(char *, struct BitMap *, UWORD *, ULONG )
+*
+* FUNCTION
+* Save the planes of a BitMap as an IFF-file, optionally with a
+* colortable. The IFF file will contain the following chunks:
+*
+* FORM - The IFF header, with the type ILBM
+* BMHD - The BitMap Header structre
+* CMAP - The color map, this chunk is omitted if colortable is zero
+* CAMG - The Amiga ViewModes word, contains the special ViewModes
+* information (HAM, LACE, HIRES ...)
+* BODY - The (crunched or uncompressed) picture
+*
+* INPUTS
+* filename - Name of the IFF file to create
+* bitmap - Pointer to the BitMap holding your picture
+* colortable - Pointer to an Amiga ColorTable structure or zero
+* (if colortable = 0, no CMAP chunk will be generated).
+* flags - Bit 0: 1 = Use the "CmpByteRun1" compression algorythm,
+* 0 = Save the file uncompressed
+* Bit 7: 1 = This is a HAM (Hold and modify) picture
+* 0 = This is a normal or Extra-Halfbrite picture
+*
+* RESULT
+* Non-zero if successful, 0 if error, Call IFFLib_IFFError() to know
+* more about the reason of the failure
+*
+* NOTE
+* This routine needs 620 bytes of stack space
+*
+* SEE ALSO
+* SaveClip
+*
+*****************************************************************************
+
+SaveBitMapFunc: movem.l d2-d4,-(SP)
+ moveq #0,d1 ; X-Offset : 0
+ moveq #0,d2 ; Y-Offset : 0
+ move.w bm_BytesPerRow(a1),d3 ; Breite : maximal
+ move.w bm_Rows(a1),d4 ; Höhe : maximal
+ bsr SaveClipFunc ; als Ausschnitt speichern
+ movem.l (SP)+,d2-d4
+ rts
+
+ END
diff --git a/Source/SaveClip.S b/Source/SaveClip.S
new file mode 100644
index 0000000..eb2fbaf
--- /dev/null
+++ b/Source/SaveClip.S
@@ -0,0 +1,490 @@
+**
+** $Id: $
+** $Revision: $
+**
+** $Filename: SaveClip.S $
+** $Author: Christian A. Weber $
+** $Release: 19.1 $
+** $Date: 92/05/11 21:11:27 $
+**
+** iff.library/IFFLib_SaveClip
+**
+** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2,
+** CH-8037 ZUERICH, SWITZERLAND. ALL RIGHTS RESERVED. NO PART
+** OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
+** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PER-
+** MISSION OF THE AUTHOR. USE AT YOUR OWN RISK.
+**
+
+
+ IDNT IFFLib_SaveClip
+ SECTION text,CODE
+
+ INCLUDE "IFFLib.i"
+
+ XREF SetError,ClearError,CalcViewModes
+ XDEF SaveClipFunc
+
+
+******* iff.library/IFFLib_SaveClip *****************************************
+*
+* NAME
+* IFFLib_SaveClip -- save a part of a BitMap as an IFF-file
+*
+* SYNOPSIS
+* result = IFFLib_SaveClip
+* D0 ( filename, bitmap, coltab, flags, xoff, yoff, width, height )
+* A0 A1 A2 D0 D1 D2 D3 D4
+*
+* FUNCTION
+* Save a part of a BitMap as an IFF file
+*
+* INPUTS
+* filename - Name of the IFF file to create
+* bitmap - Pointer to the BitMap holding your picture
+* colortable - Pointer to an Amiga ColorTable structure or zero
+* (if colortable = 0, no CMAP chunk will be generated).
+* flags - Bit 0: 1 = Use the "CmpByteRun1" compression algorythm,
+* 0 = Save the file uncompressed
+* Bit 7: 1 = This is a HAM (Hold and modify) picture
+* 0 = This is a normal or Extra-Halfbrite picture
+* xoff - X offset of the clip to be saved (bytes from the left)
+* yoff - Y offset of the clip to be saved (lines from the top)
+* width - width in bytes of the rectangle
+* height - height in lines of the rectangle
+*
+* RESULTS
+* Non-zero if successful, 0 if error, Call IFFLib_IFFError() to
+* know more about the reason of the failure
+*
+* NOTE
+* This routine needs 620 bytes of stack space
+*
+* BUGS
+* The width of the rectangle will be rounded to WORD boundaries,
+* because DPAINT wants it!
+*
+* SEE ALSO
+* IFFLib_SaveBitMap()
+*
+*****************************************************************************
+
+MAXPLANES: EQU 24 ; Höchstens 24 Bitplanes
+
+iffhd: equ 0 ; FORM
+iffsize: equ 4 ; .... ILBM
+
+bmhdchunk: equ iffsize+8 ; BMHD
+bmhdsize: equ bmhdchunk+4 ; ....
+bmhd: equ bmhdsize+4 ; bmhd-Struktur
+
+camgchunk: equ bmhd+bmh_SIZEOF ; CAMG
+camgsize: equ camgchunk+4 ; ....
+camg: equ camgsize+4 ; 0000ViewModes
+
+cmapchunk: equ camg+4 ; CMAP
+cmapsize: equ cmapchunk+4 ; ....
+cmap: equ cmapsize+4 ; Farbwerte
+
+bodychunk: equ cmap+(3*512) ; BODY
+bodysize: equ bodychunk+4 ; ....
+
+xoffset: equ bodysize+4
+yoffset: equ xoffset+2
+width: equ yoffset+2
+height: equ width+2
+
+sb_datasize: equ height+2 ; Gesamt-Datengrösse
+
+
+SaveClipFunc: movem.l d2-d7/a2-a6,-(SP)
+ suba.w #sb_datasize,SP ; Speicher reservieren
+ movea.l a6,a5 ; IFFBase
+ move.l a0,d6 ; D6 : Filename
+ movea.l a1,a3 ; A3 : BitMap
+ movea.l SP,a4 ; A4 : wird BitMapHeader
+
+ move.w d1,xoffset(SP)
+ move.w d2,yoffset(SP)
+ bclr #0,d3 ; Breite WORD align für DPaint
+ move.w d3,width(SP)
+ move.w d4,height(SP)
+
+ *** FORM....ILBM-Header & BMHD-Chunk initialisieren (im Speicher)
+
+ move.l #'FORM',(a4)+ ; Ein IFF-Formular
+ moveq.l #cmap,d7 ; 'ILBM'+BMHD+CAMG+CMAP+BODY
+ move.l d7,(a4)+ ; eintragen
+ move.l #'ILBM',(a4)+ ; File-Typ
+
+ move.l #'BMHD',(a4)+ ; Chunk-Name eintragen
+ moveq.l #bmh_SIZEOF,d7
+ move.l d7,(a4)+ ; Chunk-Size eintragen
+ move.b d0,bmh_Compression(a4) ; Cruncher-Typ merken
+
+ clr.b bmh_Masking(a4)
+ clr.b bmh_Pad1(a4)
+ clr.w bmh_TranspCol(a4)
+ move.w xoffset(SP),d0
+ lsl.w #3,d0 ; Pixel
+ move.w d0,bmh_XPos(a4) ; X-Position
+ move.w yoffset(SP),bmh_YPos(a4) ; X-Position
+ move.w #$0A0B,bmh_XAspect(a4) ; X- und Y-Aspect zusammen!
+ move.b bm_Depth(a3),bmh_nPlanes(a4)
+
+ lsl.w #3,d3 ; Breite mal 8
+ move.w d3,bmh_Width(a4) ; gibt Breite in Pixel
+ move.w d3,bmh_PageWidth(a4)
+
+ move.w d4,bmh_Height(a4) ; Bildhöhe eintragen
+ move.w d4,bmh_PageHeight(a4)
+
+ *** CAMG-Chunk generieren (immer)
+
+ move.l #'CAMG',camgchunk(SP) ; Chunk-Name
+ moveq #4,d7
+ move.l d7,camgsize(SP) ; Chunk-Size
+ movea.l a4,a0 ; struct BitMapHeader
+ bsr CalcViewModes ; ViewModes nach d0
+ bclr.b #7,bmh_Compression(a4) ; HAM gewünscht ?
+ beq.s 1$ ; nein --->
+ bset #11,d0 ; HAM-Bit setzen
+1$: move.l d0,camg(SP) ; ViewModes eintragen
+
+ *** CMAP-Chunk generieren, falls notwendig (im Speicher)
+
+ move.l #-8,cmapsize(SP) ; falls no CMAP: -'CMAP....'
+
+ move.l a2,d0 ; tst.l a2
+ beq.s nocmap
+
+ lea cmapchunk(SP),a1 ; Hierhin will ich den Chunk
+ move.l #'CMAP',(a1)+ ; Chunkname
+ moveq #1,d0
+ moveq #0,d1
+ move.b bm_Depth(a3),d1
+ cmpi.b #24,d1 ; Ist's ein 24-Bitplane-Bild ?
+ bne.s .No24 ; nein --->
+ moveq #8,d1 ; Sonst immer 256 Farben
+.No24:
+ lsl.w d1,d0 ; d0 := 2 ^ D1 = Anzahl Farben
+ move.w d0,d2 ; D2 : Anzahl Farben
+ mulu.w #3,d0 ; 3 Bytes pro Farbe
+ addq.l #2,d0
+ andi.w #~3,d0 ; auf LONG alignen
+ move.l d0,(a1)+ ; Chunklänge
+
+ subq.w #1,d2 ; für dbf
+3$: move.w (a2)+,d0
+ lsl.w #4,d0
+ move.b d0,2(a1) ; blau
+ lsr.w #4,d0
+ andi.b #$f0,d0
+ move.b d0,1(a1) ; grün
+ lsr.w #4,d0
+ andi.b #$f0,d0
+ move.b d0,(a1) ; rot
+ addq.w #3,a1
+ dbf d2,3$
+
+ *** File öffnen, IFF-Header auf Disk schreiben (vorläufig!)
+
+nocmap: move.l d6,d1 ; FileName
+ move.l #MODE_NEWFILE,d2
+ movea.l ib_DOSBase(a5),a6
+ JSRLIB Open
+ move.l d0,d7 ; D7 : FileHandle
+ beq writeerror
+
+ move.l cmapsize(SP),d0 ; CMAP-Grösse
+ add.l d0,iffsize(SP) ; zu Header-Grösse dazu
+
+ move.l d7,d1 ; File
+ move.l SP,d2 ; Adr : IFF-Header
+ moveq #cmap+8,d3 ; Länge des Headers + 8
+ add.l cmapsize(SP),d3 ; Plus Länge des CMAP-Chunks
+ JSRLIB Write ; schreiben
+ tst.l d0 ; Fehler ?
+ bmi.s writeerror ; ja!
+
+ *** BODY-Daten schreiben, evtl. komprimiert
+
+ tst.b bmh_Compression(a4) ; compacten ?
+ bne.s 1$ ; ja!
+ bsr VanillaSave
+ bra.s 2$
+1$: bsr CrunchSave
+2$: tst.l d0 ; Fehler ?
+ bmi.s writeerror ; ja!
+
+ move.l d0,d3 ; Body-Länge
+ addq.l #3,d3 ; auf nächstes LONG aufrunden
+ and.b #%11111100,d3 ; und LONG-alignen
+ move.l d3,bodysize(SP) ; aligned BODY-Grösse
+ add.l d3,iffsize(SP) ; zu Header-Grösse dazu
+ sub.l d0,d3 ; D3 := Wieviele Bytes zuviel
+
+ tst.l d3 ; Align-Grösse = 0 ?
+ beq.s 3$ ; ja -> nichts schreiben
+ move.l d7,d1 ; File
+ clr.l -(SP) ; Nullen machen
+ move.l SP,d2 ; adr
+ JSRLIB Write ; schreiben
+ addq.l #4,SP ; Stack cleanen
+ tst.l d0 ; Fehler ?
+ bmi.s writeerror ; ja!
+
+ *** IFF-Header nochmals schreiben & BODY-Header, diesmal korrekt
+
+3$: move.l d7,d1 ; File
+ moveq.l #0,d2 ; Position
+ moveq.l #OFFSET_BEGINNING,d3 ; Modus
+ JSRLIB Seek
+
+ move.l d7,d1 ; File
+ move.l SP,d2 ; Adr : IFF-Header
+ moveq.l #cmap,d3 ; Länge des Headers
+ add.l cmapsize(SP),d3 ; Plus Länge des CMAP-Chunks
+ JSRLIB Write ; schreiben
+ tst.l d0 ; Fehler ?
+ bmi.s writeerror ; ja!
+
+ lea bodychunk(SP),a0
+ move.l #'BODY',(a0) ; Chunk-Namen eintragen
+ move.l d7,d1 ; File
+ move.l a0,d2 ; Adr
+ moveq #8,d3 ; Len
+ JSRLIB Write ; Body-Header schreiben
+ tst.l d0 ; Fehler ?
+ bmi.s writeerror ; ja!
+
+ move.l d7,d1 ; File
+ JSRLIB Close
+ ;; moveq.l #0,d7 ; File ungültig
+
+ bsr ClearError ; Error löschen, D0 := 1
+ bra.s SaveClip_End
+
+writeerror: move.l d7,d1 ; File
+ beq.s 1$ ; schon / nochzu!
+ JSRLIB Close
+1$: moveq #IFF_WRITEERROR,d0
+ bsr SetError ; Error setzen, D0 := 0
+
+SaveClip_End: adda.w #sb_datasize,SP ; Speicher wirder freigeben
+ movem.l (SP)+,d2-d7/a2-a6
+ rts
+
+
+***************************************************************************
+************** V A N I L L A S A V E ************************************
+***************************************************************************
+
+vs_planes: equ 0 ; ARRAY[0..MAXPLANES-1] OF PlanePtr
+vs_chunksize: equ vs_planes+4*MAXPLANES
+vs_linksize: equ vs_chunksize+4
+
+VanillaSave: movem.l d2-d6/a2-a4,-(SP) ; 8 Register retten
+ lea 8*4+4(SP),a4 ; A4 : Global data Ptr
+ suba.w #vs_linksize,SP ; lokalen Datenraum schaffen
+
+ *** Chunk-Grösse berechnen und merken
+
+ move.w width(a4),d0 ; Breite in Bytes
+ moveq #0,d1
+ move.b bm_Depth(a3),d1
+ mulu d1,d0 ; mal Anzahl Planes
+ move.w height(a4),d1
+ mulu d1,d0 ; mal Anzahl Linien
+ move.l d0,vs_chunksize(SP) ; merken
+
+ *** PlanePtrs kopieren & X,Y-Offsets dazuaddieren
+
+ move.w yoffset(a4),d1 ; Y-Offset im Bild
+ mulu bm_BytesPerRow(a3),d1 ; mal Bildbreite
+ moveq #0,d0
+ move.w xoffset(a4),d0
+ add.l d0,d1 ; plus X-Offset
+
+ lea bm_Planes(a3),a0 ; Source
+ move.l SP,a1 ; Destination
+ moveq #MAXPLANES-1,d0 ; Alle PlanePtrs
+1$: move.l (a0)+,d2 ; PlanePtr
+ add.l d1,d2 ; Offset dazu
+ move.l d2,(a1)+ ; speichern
+ dbf d0,1$
+
+ moveq #0,d3
+ moveq #0,d4
+ moveq #0,d5
+ move.w bm_BytesPerRow(a3),d5 ; D5 : BytesPerRow (linesize)
+ move.b bm_Depth(a3),d3 ; move.b ea,Ax geht ja nicht
+ move.w d3,a3 ; A3 : Depth (lieber D8 als A3)
+ move.w width(a4),d3 ; D3 : BytesPerRow (to write)
+ move.w height(a4),d4 ; D4 : Rows (to write)
+
+ subq.w #1,d4 ; für dbf
+ subq.w #1,a3 ; für dbf
+vs_loop1: movea.l SP,a2 ; Zeiger auf Planes
+ move.l a3,d6 ; d6 : Depth für dbf
+
+vs_loop2: move.l d7,d1 ; File
+ move.l (a2),d2 ; Adr : Nächste Linie/Plane
+ JSRLIB Write ; (len ist schon in D3)
+ tst.l d0 ; Fehler ?
+ bmi.s vs_error ; ja!
+ add.l d5,(a2)+ ; auf nächste Linie
+ dbf d6,vs_loop2 ; next plane
+ dbf d4,vs_loop1 ; next row
+
+ move.l vs_chunksize(SP),d0 ; Return-Wert: Chunk-Länge
+vs_error: adda.w #vs_linksize,SP ; Datenraum freigeben
+ movem.l (SP)+,d2-d6/a2-a4
+ rts
+
+
+***************************************************************************
+************** C R U N C H S A V E **************************************
+***************************************************************************
+
+cs_planes: equ 0 ; ARRAY[0..MAXPLANES-1] OF PlanePtr
+cs_buffer: equ cs_planes+4*MAXPLANES ; ARRAY[0..511] OF BYTE
+cs_bodysize: equ cs_buffer+512 ; LONG bodysize
+cs_linksize: equ cs_bodysize+4
+
+CrunchSave: movem.l d2-d6/a2-a4,-(SP) ; 8 Register retten
+ lea 8*4+4(SP),a4 ; A4 : Global data Ptr
+ suba.w #cs_linksize,SP ; lokalen Datenraum schaffen
+
+ clr.l cs_bodysize(SP)
+
+ *** PlanePtrs kopieren & X,Y-Offsets dazuaddieren
+
+ move.w yoffset(a4),d1 ; Y-Offset im Bild
+ mulu bm_BytesPerRow(a3),d1 ; mal Bildbreite
+ moveq #0,d0
+ move.w xoffset(a4),d0
+ add.l d0,d1 ; plus X-Offset
+
+ lea bm_Planes(a3),a0 ; Source
+ movea.l SP,a1 ; Destination (unsauber!)
+ moveq #MAXPLANES-1,d0 ; Alle Planeptrs
+1$: move.l (a0)+,d2 ; PlanePtr
+ add.l d1,d2 ; Offset dazu
+ move.l d2,(a1)+ ; speichern
+ dbf d0,1$
+
+ moveq #0,d3
+ moveq #0,d4
+ moveq #0,d5
+ move.w bm_BytesPerRow(a3),d5 ; D5 : BytesPerRow (linesize)
+ move.b bm_Depth(a3),d3 ; move.b ea,Ax geht ja nicht
+ move.l d3,a3 ; A3 : Depth (lieber D8 als A3)
+ move.w width(a4),d3 ; D3 : BytesPerRow (to write)
+ move.w height(a4),d4 ; D4 : Rows (to write)
+
+ subq.w #1,d4 ; für dbf
+ subq.l #1,a3 ; für dbf
+
+cs_loop1: move.l SP,a2 ; PlanePtr
+ move.l a3,d6 ; d6 : Depth für dbf
+
+cs_loop2: move.w d3,d0 ; Len für CrunchRow()
+ move.l (a2),a0 ; Source für CrunchRow()
+ lea cs_buffer(SP),a1 ; Destination für CrunchRow()
+ bsr.s CrunchRow
+ add.l d0,cs_bodysize(SP) ; für calcbodysize()
+
+ move.l d7,d1 ; File
+ lea cs_buffer(SP),a1 ; Daten-Puffer
+ move.l a1,d2 ; Adr : cs_buffer(SP)
+ move.l d3,-(SP)
+ move.l d0,d3 ; Länge, von CrunchRow()
+ JSRLIB Write
+ move.l (SP)+,d3
+ tst.l d0 ; Fehler ?
+ bmi.s cs_error ; ja!
+
+ add.l d5,(a2)+ ; auf nächste Linie
+ dbf d6,cs_loop2 ; next plane
+ dbf d4,cs_loop1 ; next row
+
+ move.l cs_bodysize(SP),d0 ; return-value
+cs_error: adda.w #cs_linksize,SP ; Speicher freigeben
+ movem.l (SP)+,d2-d6/a2-a4
+ rts
+
+
+*********************************************************************
+** **
+** C R U N C H R O W - eine Zeile CmpByteRun1 crunchen **
+** **
+** Parameter : A0.L : Zeiger auf Source-Adresse in Plane **
+** A1.L : Zeiger auf Destination-Buffer **
+** D0.W : Anzahl Bytes einer Source-Linie **
+** Resultat : D0.L : Anzahl gecrunchte Bytes **
+** **
+*********************************************************************
+
+CrunchRow: movem.l d2-d3/a2-a3,-(SP)
+ lea (a0,d0.w),a2 ; A2 : Source-Endadresse der Linie
+ moveq #0,d3 ; Byte-Zähler
+
+crunchloop: bsr.s CountEq ; wieviele gleiche Bytes folgen ?
+ cmp.w #3,d0 ; genug gleiche Bytes zum runnen ?
+ blt.s countdump ; nee, lohnt sich nicht -> Dumpen
+
+ addq.l #2,d3 ; Markierbyte & Anzahl
+ move.b (a0),d1 ; Wert
+ adda.w d0,a0 ; Source anpassen
+ subq.w #1,d0 ; muss .w sein und nicht .b !!!!!!!
+ neg.b d0 ; negieren (= "Run"-Code)
+ move.b d0,(a1)+ ; und eintragen
+ move.b d1,(a1)+ ; Wert eintragen
+ bra.s crunchcont ; weitermachen
+
+countdump: movea.l a0,a3 ; Source-Pointer retten
+ moveq #0,d2 ; D2 : Länge des Dump-Blocks
+1$: addq.b #1,d2
+ bmi.s 2$ ; höchstens 127 Bytes pro Block
+ addq.l #1,a0
+ cmpa.l a2,a0 ; Ende der Linie erreicht ?
+ bge.s 3$ ; ja -> abbrechen
+ bsr.s CountEq
+ cmp.w #3,d0 ; Ende des Dump-Blocks ?
+ blt.s 1$ ; noch nicht
+ bra.s 3$ ; Ende
+2$: moveq #127,d2
+3$: movea.l a3,a0 ; Source-Pointer restaurieren
+
+ add.l d2,d3 ; zur Gesamtanzahl dazuzählen
+ addq.l #1,d3 ; Markierbyte nicht vergessen
+ subq.w #1,d2 ; aus 1..128 mach 0..127
+ move.b d2,(a1)+ ; Markierbyte eintragen
+4$: move.b (a0)+,(a1)+ ; Datenbytes eintragen
+ dbf d2,4$
+
+
+crunchcont: cmpa.l a2,a0 ; Ende der Linie erreicht ?
+ blt.s crunchloop ; noch nicht!
+
+ move.l d3,d0 ; Return: Anzahl Destination-Bytes
+ movem.l (SP)+,d2-d3/a2-a3
+ rts
+
+ *** Anzahl gleicher Zeichen ab (a0) zählen und nach D0
+
+CountEq: move.l a0,-(SP)
+ moveq #1,d0 ; D0 : Anzahl gleiche Bytes
+1$: move.b (a0)+,d1 ; erstes Byte
+2$: cmp.b (a0)+,d1 ; Byte gleich wie letztes Byte ?
+ bne.s 3$ ; nein -> abbrechen
+ cmp.w #128,d0
+ bge.s 3$ ; höchstens 128 gleiche
+ addq.w #1,d0 ; Anzahl erhöhen
+ cmpa.l a2,a0 ; Ende der Linie erreicht ?
+ blt.s 2$ ; noch nicht -> weiterzählen
+3$: move.l (SP)+,a0
+ rts
+
+ END