1 #ifndef __MICRO_IFF_H__
2 #define __MICRO_IFF_H__
3 #include <stdint.h>
4 #include <stdio.h>
5 
6 typedef int32_t IFFP;	/* Status code result from an IFF procedure */
7 	/* LONG, because must be type compatable with ID for GetChunkHdr.*/
8 	/* Note that the error codes below are not legal IDs.*/
9 #define IFF_OKAY   0L	/* Keep going...*/
10 #define END_MARK  -1L	/* As if there was a chunk at end of group.*/
11 #define IFF_DONE  -2L	/* clientProc returns this when it has READ enough.
12 			 * It means return thru all levels. File is Okay.*/
13 #define DOS_ERROR -3L
14 #define NOT_IFF   -4L	/* not an IFF file.*/
15 #define NO_FILE   -5L	/* Tried to open file, DOS didn't find it.*/
16 #define CLIENT_ERROR -6L /* Client made invalid request, for instance, write
17 			 * a negative size chunk.*/
18 #define BAD_FORM  -7L	/* A client read proc complains about FORM semantics;
19 			 * e.g. valid IFF, but missing a required chunk.*/
20 #define SHORT_CHUNK -8L	/* Client asked to IFFReadBytes more bytes than left
21 			 * in the chunk. Could be client bug or bad form.*/
22 #define BAD_IFF   -9L	/* mal-formed IFF file. [TBD] Expand this into a
23 			 * range of error codes.*/
24 #define LAST_ERROR BAD_IFF
25 
26 // Flags for calling the group find function
27 #define IFF_FIND_REWIND 1 //!< rewind before searching
28 
29 /*! \brief Four-character IDentifier builder.*/
30 #define MakeID(a,b,c,d)  ( (int32_t)(a)<<24L | (int32_t)(b)<<16L | (c)<<8 | (d) )
31 /* Standard group IDs.  A chunk with one of these IDs contains a
32    SubTypeID followed by zero or more chunks.*/
33 #define FORM MakeID('F','O','R','M')
34 #define PROP MakeID('P','R','O','P')
35 #define LIST MakeID('L','I','S','T')
36 #define CAT  MakeID('C','A','T',' ')
37 #define FILLER MakeID(' ',' ',' ',' ')
38 #define JUNK MakeID('J', 'U', 'N', 'K')
39 
40 typedef int32_t ID;	/*! \brief An ID is four printable ASCII chars
41 			 *  but stored as a int32_t for efficient copy
42 			 *  & compare.*/
43 
44 typedef struct Uiff_CTX {
45   FILE *f;
46   void *last_data; //!< last data was read here
47   ID grID; //!<group id, eg FORM
48   ID grsID; //!<group sub id, eg FORM ILBM
49   long grbgn; //!<beginning position of group *data* in file
50   long grend; //!<begin + grsz
51   int32_t grsz; //!<group size
52 
53   ID ckID; //!<id of current chunk, eg BMHD
54   long ckbgn; //!<beginning of chunk *data*
55   long ckend;
56   int32_t cksz; //!<chunk size of current chunk
57 } uiff_ctx_t;
58 
59 /*! \brief find a chunk in a file
60  *
61  * File is positioned on data. If ckID is zero then the next available
62  * chunk is found.
63  *
64  * \param ckID id of the chunk to be found
65  * \return chunk size
66  */
67 int32_t uiff_find_chunk(FILE *inf, long length, ID ckID);
68 
69 /*! \brief find a group in a file
70  *
71  * File is positioned on data. If ckID is zero then any of the default
72  * group chunks (FORM, LIST, CAT, PROP) is found.
73  *
74  * \param ckID id of the group chunk, e.g. FORM, etc.
75  * \param subID subid of the group, e.g. ILBM, etc.
76  * \return chunk size
77  */
78 int32_t uiff_find_group(FILE *inf, long length, ID ckID, ID subID);
79 
80 /*! \brief group predicate
81  *
82  */
83 int uiff_group_p(FILE *inf, ID grID, ID ckID);
84 
85 /*! \brief read chunk to allocated memory
86  *
87  * Chunk is read within current context.
88  */
89 void *uiff_reada_chunk_ctx(uiff_ctx_t *inf);
90 
91 /*! \brief read a 32-bit big endian integer from file
92  *
93  * \param inf input file
94  * \return unsigned integer 32 bit
95  */
96 uint32_t read32(FILE *inf);
97 
98 /*! \brief read a 16-bit big endian integer from file
99  *
100  * \param inf input file
101  * \return unsigned integer 16 bit
102  */
103 uint16_t read16(FILE *inf);
104 
105 uiff_ctx_t *uiff_new_ctx(FILE *f, uiff_ctx_t *ctx);
106 
107 /* \brief Get a context from a file only for true IFF files.
108  *
109  * This will rewind the file, check if it is an IFF file, and it will
110  * return a context with the stream positioned into the main group.
111  *
112  * \param f a file which is rewound and checked
113  * \param grID the group the file shall have, set to zero if any valid IFF file
114  * \param subID Which type of IFF file (ILBM, etc.)? Set to zero if any.
115  */
116 uiff_ctx_t *uiff_from_file(FILE *f, ID grID, ID subID);
117 
118 /*! \brief close an iff context and underlying file
119  *
120  * \param ctx uiff context
121  * \return IFF_OKAY on success
122  */
123 int32_t uiff_close(uiff_ctx_t *ctx);
124 
125 /*! \brief Find a group chunk
126  *
127  * If the ckID for the group is equal to zero any type of grouping
128  * chunk is found.
129  *
130  * \param ctx iff context
131  * \param flags currently only rewind
132  * \param ckID id of the grouping chunk
133  * \param subID sub id of the group
134  * \return size of the group, is , is < 0 on error
135  */
136 int32_t uiff_find_group_ctx(uiff_ctx_t *ctx, unsigned flags, ID ckID, ID subID);
137 
138 /*! \brief find a chunk in a group
139  *
140  * If the ckID for the chunk is equal to zero any type of chunk is
141  * found.
142  *
143  * \param ctx iff context
144  * \param ckID id of the chunk
145  * \return size of the group, <0 on error
146  */
147 int32_t uiff_find_chunk_ctx(uiff_ctx_t *ctx, ID ckID);
148 
149 /*! \brief find a chunk in a group with flags
150  *
151  * If the ckID for the chunk is equal to zero any type of chunk is
152  * found.
153  *
154  * Currently only IFF_FIND_REWIND is supported.
155  *
156  * \param ctx iff context
157  * \param ckID id of the chunk
158  * \return size of the group, <0 on error
159  */
160 int32_t uiff_find_chunk_wflags(uiff_ctx_t *ctx, ID ckID, unsigned flags);
161 
162 
163 /*! \brief skip to end of chunk
164  *
165  * Will skip to the end of the current chunk.
166  *
167  * \param ctx micro iff context
168  * \return number of bytes skipped or error if < 0
169  */
170 int32_t uiff_skip(uiff_ctx_t *ctx);
171 
172 /*! \brief rewind to the beginning of the group
173  */
174 void uiff_rewind_group(uiff_ctx_t *ctx);
175 #endif
176