diff options
-rw-r--r-- | Programmer/iff.h | 167 | ||||
-rw-r--r-- | Programmer/iff.i | 94 | ||||
-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 |
18 files changed, 2832 insertions, 0 deletions
diff --git a/Programmer/iff.h b/Programmer/iff.h new file mode 100644 index 0000000..d62bc05 --- /dev/null +++ b/Programmer/iff.h @@ -0,0 +1,167 @@ +#ifndef LIBRARIES_IFF_H +#define LIBRARIES_IFF_H +/* +** +** $Id: $ +** $Revision: $ +** +** $Filename: iff.h $ +** $Author: Christian A. Weber $ +** $Release: 19.1 $ +** $Date: 90/10/09 22:32:54 $ +** +** Standard header file for programs using iff.library +** +** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2, +** CH-8037 ZUERICH, SWITZERLAND. +** THIS FILE MAY BE FREELY DISTRIBUTED. USE AT YOUR OWN RISK. +** +*/ + +#ifndef EXEC_TYPES_H +#include <exec/types.h> +#endif + +#define IFFNAME "iff.library" +#define IFFVERSION 19L /* Current library version */ + +typedef void *IFFFILE; /* The IFF 'FileHandle' structure */ + + +/************** FUNCTION DECLARATIONS ***********************************/ + +#ifdef AZTEC_C +#define __ARGS(a) () /* Remove this for Aztec C V5.x */ +#define NO_PRAGMAS +#else +#define __ARGS(a) a +#endif + +IFFFILE OpenIFF __ARGS((char *)); +void CloseIFF __ARGS((IFFFILE)); +void *FindChunk __ARGS((IFFFILE,LONG)); +struct BitMapHeader *GetBMHD __ARGS((IFFFILE)); +LONG GetColorTab __ARGS((IFFFILE,WORD *)); +BOOL DecodePic __ARGS((IFFFILE,struct BitMap *)); +BOOL SaveBitMap __ARGS((char *,struct BitMap *,WORD *,LONG)); +BOOL SaveClip __ARGS((char *,struct BitMap *,WORD *,LONG,LONG,LONG,LONG,LONG)); +LONG IFFError __ARGS((void)); +ULONG GetViewModes __ARGS((IFFFILE)); /* ULONG since V18.1 */ +APTR NewOpenIFF __ARGS((char *,LONG)); /* Since V16.1 */ +BOOL ModifyFrame __ARGS((void *,struct BitMap *)); /* Since V18.1 */ +IFFFILE PPOpenIFF __ARGS((char *,char *)); + + +/************** ERROR-CODES *********************************************/ + +#define IFF_BADTASK -1 /* IFFError() called by wrong task */ + +#define IFF_CANTOPENFILE 16 /* File not found */ +#define IFF_READERROR 17 /* Error reading file */ +#define IFF_NOMEM 18 /* Not enough memory */ +#define IFF_NOTIFF 19 /* File is not an IFF file */ +#define IFF_WRITEERROR 20 /* Error writing file */ + +#define IFF_NOILBM 24 /* IFF file is not of type ILBM */ +#define IFF_NOBMHD 25 /* BMHD chunk not found */ +#define IFF_NOBODY 26 /* BODY chunk not found */ +#define IFF_TOOMANYPLANES 27 /* Obsolete since V18.6 */ +#define IFF_UNKNOWNCOMPRESSION 28 /* Unknown compression type */ + +#define IFF_NOANHD 29 /* ANHD chunk not found (since V18.1) */ +#define IFF_NODLTA 30 /* DLTA chunk not found (since V18.1) */ + + +/************** COMMON IFF IDs ******************************************/ + +#define MakeID(a,b,c,d) ((ULONG)(a)<<24L|(ULONG)(b)<<16L|(c)<<8|(d)) + +/* List of the most useful IDs, NOT complete, to be continued */ + +#define ID_FORM MakeID('F','O','R','M') +#define ID_PROP MakeID('P','R','O','P') +#define ID_LIST MakeID('L','I','S','T') +#define ID_CAT MakeID('C','A','T',' ') + +#define ID_ANIM MakeID('A','N','I','M') +#define ID_ANHD MakeID('A','N','H','D') +#define ID_BMHD MakeID('B','M','H','D') +#define ID_BODY MakeID('B','O','D','Y') +#define ID_CAMG MakeID('C','A','M','G') +#define ID_CLUT MakeID('C','L','U','T') +#define ID_CMAP MakeID('C','M','A','P') +#define ID_CRNG MakeID('C','R','N','G') +#define ID_CTBL MakeID('C','T','B','L') +#define ID_DLTA MakeID('D','L','T','A') +#define ID_ILBM MakeID('I','L','B','M') +#define ID_SHAM MakeID('S','H','A','M') + +#define ID_8SVX MakeID('8','S','V','X') +#define ID_ATAK MakeID('A','T','A','K') +#define ID_NAME MakeID('N','A','M','E') +#define ID_RLSE MakeID('R','L','S','E') +#define ID_VHDR MakeID('V','H','D','R') + + +/************** STRUCTURES **********************************************/ + +struct Chunk /* Generic IFF chunk structure */ +{ + LONG ckID; + LONG ckSize; +/* UBYTE ckData[ckSize] (variable sized data) */ +}; + +struct BitMapHeader /* BMHD chunk for ILBM files */ +{ + UWORD w,h; + WORD x,y; + UBYTE nPlanes; + UBYTE masking; + UBYTE compression; + UBYTE pad1; + UWORD transparentColor; + UBYTE xAspect,yAspect; + WORD pageWidth,pageHeight; +}; + +struct AnimHeader /* ANHD chunk for ANIM files */ +{ + UBYTE Operation; + UBYTE Mask; + UWORD W; + UWORD H; + WORD X; + WORD Y; + ULONG AbsTime; + ULONG RelTime; + UBYTE Interleave; + UBYTE pad0; + ULONG Bits; + UBYTE pad[16]; +}; + + +/************** PRAGMAS FOR LATTICE C V5.x ******************************/ + +/* Pragmas generated with: 'fd2pragma iff_lib.fd iffpragmas.h' */ + +#ifndef NO_PRAGMAS +extern struct Library *IFFBase; +#pragma libcall IFFBase OpenIFF 1e 801 +#pragma libcall IFFBase CloseIFF 24 901 +#pragma libcall IFFBase FindChunk 2a 0902 +#pragma libcall IFFBase GetBMHD 30 901 +#pragma libcall IFFBase GetColorTab 36 8902 +#pragma libcall IFFBase DecodePic 3c 8902 +#pragma libcall IFFBase SaveBitMap 42 0a9804 +#pragma libcall IFFBase SaveClip 48 43210A9808 +#pragma libcall IFFBase IFFError 4e 0 +#pragma libcall IFFBase GetViewModes 54 901 +#pragma libcall IFFBase NewOpenIFF 5a 0802 +#pragma libcall IFFBase ModifyFrame 60 8902 +#pragma libcall IFFBase PPOpenIFF 66 9802 +#endif + +#endif !LIBRARIES_IFF_H + diff --git a/Programmer/iff.i b/Programmer/iff.i new file mode 100644 index 0000000..4c1bf11 --- /dev/null +++ b/Programmer/iff.i @@ -0,0 +1,94 @@ + IFND LIBRARIES_IFF_I +LIBRARIES_IFF_I SET 1 +** +** $Id: $ +** $Revision: $ +** +** $Filename: iff.i $ +** $Author: Christian A. Weber $ +** $Release: 19.1 $ +** $Date: 90/10/09 22:32:54 $ +** +** Standard header file for programs using iff.library +** +** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2, +** CH-8037 ZUERICH, SWITZERLAND. +** THIS FILE MAY BE FREELY DISTRIBUTED. USE AT YOUR OWN RISK. +** + + XREF _IFFBase + +IFFVERSION: EQU 19 ; Use this for the OpenLibrary() call + +IFF: MACRO + movea.l _IFFBase,a6 + jsr \1(a6) + ENDM + + +*************** LIBRARY OFFSETS ****************************************** + +_LVOOpenIFF: EQU -30 ; (filename) (A0) +_LVOCloseIFF: EQU -36 ; (ifffile) (A1) +_LVOFindChunk: EQU -42 ; (ifffile,chunkname) (A1,D0) +_LVOGetBMHD: EQU -48 ; (ifffile) (A1) +_LVOGetColorTab: EQU -54 ; (ifffile,colortable) (A1/A0) +_LVODecodePic: EQU -60 ; (ifffile,bitmap) (A1/A0) +_LVOSaveBitMap: EQU -66 ; (name,bmap,ctab,crmd) (A0-A2,D0) +_LVOSaveClip: EQU -72 ; (name,bmap,ctab,crmd,x,y,w,h) (A0-A2,D0-D4) +_LVOIFFError: EQU -78 ; () () +_LVOGetViewModes: EQU -84 ; (ifffile) (A1) +_LVONewOpenIFF: EQU -90 ; (filename,memtype) (A0,D0) +_LVOModifyFrame: EQU -96 ; (modifyform,bitmap) (A1/A0) + + +*************** ERROR CODES ********************************************** + +IFF_BADTASK: EQU -1 ; IffError() called by wrong task + +IFF_CANTOPENFILE: EQU 16 ; File not found +IFF_READERROR: EQU 17 ; Error reading file +IFF_NOMEM: EQU 18 ; Not enough memory +IFF_NOTIFF: EQU 19 ; File is not an IFF file +IFF_WRITEERROR: EQU 20 ; Error writing file + +IFF_NOILBM: EQU 24 ; IFF file is not of type ILBM +IFF_NOBMHD: EQU 25 ; BMHD chunk not found +IFF_NOBODY: EQU 26 ; BODY chunk not found +IFF_TOOMANYPLANES: EQU 27 ; Obsolete since V18.6 +IFF_UNKNOWNCOMPRESSION: EQU 28 ; Unknown compression type + +IFF_NOANHD: EQU 29 ; ANHD chunk not found (since V18.1) +IFF_NODLTA: EQU 30 ; DLTA chunk not found (since V18.1) + + +bmh_Width: EQU 0 ; struct BitMapHeader +bmh_Height: EQU $2 +bmh_XPos: EQU $4 +bmh_YPos: EQU $6 +bmh_nPlanes: EQU $8 +bmh_Masking: EQU $9 +bmh_Compression: EQU $A +bmh_Pad1: EQU $B +bmh_TranspCol: EQU $C +bmh_XAspect: EQU $E +bmh_YAspect: EQU $F +bmh_PageWidth: EQU $10 +bmh_PageHeight: EQU $12 +bmh_SIZEOF: EQU $14 + +anh_Operation: EQU 0 ; struct AnimHeader +anh_Mask: EQU $1 +anh_W: EQU $2 +anh_H: EQU $4 +anh_X: EQU $6 +anh_Y: EQU $8 +anh_AbsTime: EQU $A +anh_RelTime: EQU $E +anh_Interleave: EQU $12 +anh_pad0: EQU $13 +anh_Bits: EQU $14 +anh_pad: EQU $18 +anh_SIZEOF: EQU $28 + + ENDC 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 |