diff options
Diffstat (limited to 'Source')
| -rw-r--r-- | Source/CloseIFF.S | 67 | ||||
| -rw-r--r-- | Source/CompressBlock.S | 144 | ||||
| -rw-r--r-- | Source/DecodePic.S | 232 | ||||
| -rw-r--r-- | Source/DecompressBlock.S | 107 | ||||
| -rw-r--r-- | Source/FindChunk.S | 83 | ||||
| -rw-r--r-- | Source/GetBMHD.S | 71 | ||||
| -rw-r--r-- | Source/GetColorTab.S | 94 | ||||
| -rw-r--r-- | Source/GetViewModes.S | 124 | ||||
| -rw-r--r-- | Source/IFFError.S | 140 | ||||
| -rw-r--r-- | Source/IFFLib.S | 324 | ||||
| -rw-r--r-- | Source/IFFLib.i | 54 | ||||
| -rw-r--r-- | Source/Makefile | 108 | ||||
| -rw-r--r-- | Source/ModifyFrame.S | 258 | ||||
| -rw-r--r-- | Source/OpenIFF.S | 193 | ||||
| -rw-r--r-- | Source/SaveBitMap.S | 82 | ||||
| -rw-r--r-- | Source/SaveClip.S | 490 | 
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  | 
