├── .gitattributes ├── .gitignore ├── 64-bit IFF.md ├── IFF docs with Commodore revisions ├── 8SVX.doc ├── 8SVX.docx ├── 8SVX.pdf ├── 8SVX.rtf ├── EA IFF 85.doc ├── EA IFF 85.docx ├── EA IFF 85.pdf ├── EA IFF 85.rtf ├── IFF Quick Intro.doc ├── IFF Quick Intro.docx ├── IFF Quick Intro.pdf ├── IFF Quick Intro.rtf ├── ILBM.doc ├── ILBM.docx ├── ILBM.pdf ├── ILBM.rtf ├── SMUS.doc ├── SMUS.docx ├── SMUS.pdf └── SMUS.rtf ├── IFF retrospective.md ├── IFF source code ├── Makefile ├── autodocs.c ├── createiffparserva.s ├── iff.c ├── iff.h ├── iff_folio.c ├── io.c ├── io.h └── linkexec.x └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac gunk 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /64-bit IFF.md: -------------------------------------------------------------------------------- 1 | "64-bit IFF" 2 | ============ 3 | 4 | -- Jerry Morrison 5 | 6 | Yes, once upon a time I did design ways to expand the file and chunk size to 64 bits and larger. 7 | 8 | It didn't go beyond a design sketch, in part because gigabyte files are already big for a sequential read/write format, at least on 2003 era hardware. It may be handier to use multiple files or an editable format like Bento. Witness the hacks people used to update RIFF properties (like user ratings) without copying the entire file. 9 | 10 | Note that the IFF standard defines a **SIGNED** 32-bit chunk-size field. It's signed for compatibility with Pascal (early Macintosh programs) and Java follows suit. (Unsigned numbers have potential issues when you subtract them.) Some developers have expanded the usage to an UNSIGNED 32-bit chunk-size, but that's not to the original specification. 11 | 12 | 13 | ## Design Proposal 1 [Not adopted] 14 | 15 | Since negative chunk sizes are technically illegal in IFF, it's theoretically safe to expand the range to *nearly* a full 32-bit unsigned value and specify that the last few values indicate a variable-size, extended size field. For developers who are already treating the chunk size as unsigned 32-bits, this would make their practice legal except for those last few values. 16 | 17 | Given the value ```n``` in the original chunk size field: 18 | 19 | * ```signed n = -1``` is kept as a temporary placeholder value when writers plan to back-patch the size after writing the chunk's contents. 20 | * ```signed n = -2``` indicates an 8 byte (64-bit) unsigned chunk size field immediately following the original chunk size field. This supports chunk sizes in ```[0 .. 2^64 - 1]``` bytes. 21 | * ```signed n = -3``` indicates a 16 byte (128-bit) unsigned chunk size field immediately following the original chunk size field. This supports chunk sizes in ```[0 .. 2^128 - 1]``` bytes. 22 | * ```signed n in [-15 .. -4]``` values are reserved. 23 | * ```unsigned n in [0 .. 2^32 - 16]``` indicates ```n``` bytes of chunk data. 24 | 25 | This allows more than one field width to store a given chunk size value but for backwards compatibility, writers would be encouraged to use narrowest chunk size field that fits. A writer that back-patches the size might still have to reserve a longer field just in case. 26 | 27 | A reader should give up on any file whose first chunk's size is too big for that reader. Check the effective chunk size value, **not** its field width. 28 | 29 | 30 | ## Design Proposal 2 [Not adopted] 31 | 32 | Use new "IFF-2003" magic signatures ```'FOR2'```, ```'LIS2'```, ```'PRO2'```, and ```'CAT2'``` to indicate that those chunks and their contained chunks have unsigned 64-bit fixed-size size fields. (```'FOR1'``` is used by the BEAM file format.) 33 | 34 | An IFF-2003 spec could also drop the pad byte that follows each odd-size IFF-85 chunk and maybe the ```'LIST'``` and ```'PROP'``` features. 35 | 36 | For backwards compatibility, writers would be encouraged to use IFF-85 when feasible. IFF-85 readers will ignore IFF-2003 files. 37 | 38 | 39 | ## Philips DSDIFF 40 | 41 | Philips created a 64-bit IFF derivative, the [Direct Stream Digital Interchange File Format: DSDIFF](https://www.sonicstudio.com/pdf/dsd/DSDIFF_1.5_Spec.pdf). It's identified via the `FRM8` tag and it keeps the 16-bit chunk padding. 42 | 43 | Also see their document [Recommended usage of DSDIFF version 1.5](https://www.sonicstudio.com/pdf/dsd/DSDIFF_1.5_RecommendedUsage.pdf). 44 | 45 | 46 | ## Notes 47 | 48 | * ["2^16-1 limit in modeler"](https://groups.google.com/forum/?hl=en#!msg/comp.graphics.apps.lightwave/Zz8HEy-eDfM/fQKtAIE1Qg8J) thread on comp.graphics.apps.lightwave. 49 | -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/8SVX.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/8SVX.doc -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/8SVX.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/8SVX.docx -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/8SVX.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/8SVX.pdf -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/EA IFF 85.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/EA IFF 85.doc -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/EA IFF 85.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/EA IFF 85.docx -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/EA IFF 85.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/EA IFF 85.pdf -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/IFF Quick Intro.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/IFF Quick Intro.doc -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/IFF Quick Intro.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/IFF Quick Intro.docx -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/IFF Quick Intro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/IFF Quick Intro.pdf -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/IFF Quick Intro.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff8\deff0\stshfdbch0\stshfloch8\stshfhich8\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f4\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Helvetica;} 2 | {\f5\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070409020205020404}Courier{\*\falt Courier New};}{\f8\fbidi \froman\fcharset0\fprq2{\*\panose 02040503060506020304}New York{\*\falt Times New Roman};} 3 | {\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f40\fbidi \fnil\fcharset77\fprq0{\*\panose 00000000000000000000}Geneva{\*\falt Arial};}{\f51\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times;} 4 | {\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} 5 | {\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} 6 | {\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} 7 | {\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f240\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} 8 | {\f241\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f243\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f244\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f245\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} 9 | {\f246\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f247\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f248\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f580\fbidi \froman\fcharset238\fprq2 Cambria Math CE;} 10 | {\f581\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f583\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f584\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f587\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;} 11 | {\f588\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}{\f750\fbidi \froman\fcharset238\fprq2 Times CE;}{\f751\fbidi \froman\fcharset204\fprq2 Times Cyr;}{\f753\fbidi \froman\fcharset161\fprq2 Times Greek;} 12 | {\f754\fbidi \froman\fcharset162\fprq2 Times Tur;}{\f755\fbidi \froman\fcharset177\fprq2 Times (Hebrew);}{\f756\fbidi \froman\fcharset178\fprq2 Times (Arabic);}{\f757\fbidi \froman\fcharset186\fprq2 Times Baltic;} 13 | {\f758\fbidi \froman\fcharset163\fprq2 Times (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 14 | {\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} 15 | {\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} 16 | {\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} 17 | {\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} 18 | {\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;} 19 | {\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} 20 | {\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} 21 | {\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} 22 | {\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} 23 | {\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} 24 | {\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} 25 | {\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} 26 | {\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} 27 | {\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} 28 | {\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} 29 | {\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} 30 | {\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} 31 | {\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} 32 | {\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} 33 | {\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0; 34 | \red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f8 }{\*\defpap 35 | \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af8\afs20\alang1025 \ltrch\fcs0 36 | \f8\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* 37 | \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv 38 | \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20\alang1025 \ltrch\fcs0 \f8\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused \sqformat Normal Table;}{ 39 | \s34\ql \li0\ri0\widctlpar\tqc\tx3\tqr\tx6\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af8\afs20\alang1025 \ltrch\fcs0 \f8\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext34 \spriority0 footer;}} 40 | {\*\rsidtbl \rsid8074388\rsid11688229\rsid12348070}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\title IFF Quick Intro}{\subject A Quick Introduction to IFF} 41 | {\author Jerry Morrison}{\operator Jerry Morrison}{\creatim\yr2013\mo11\dy5\hr14\min44}{\revtim\yr2013\mo11\dy5\hr14\min44}{\version2}{\edmins1}{\nofpages4}{\nofwords1408}{\nofchars6939}{\nofcharsws8331}{\vern32773}}{\*\xmlnstbl {\xmlns1 http://schemas.mi 42 | crosoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr720\margt720\margb720\gutter0\ltrsect 43 | \ftnbj\aenddoc\linestart65536\hyphhotz0\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1 44 | \makebackup\sprstsp\otblrul\brkfrm\sprstsm\truncex\nolead\msmcap\lytprtmet\hyphcaps0\horzdoc\dghspace120\dgvspace120\dghorigin1701\dgvorigin1984\dghshow0\dgvshow0\jexpand\viewkind1\viewscale100\bdrrlswsix\nolnhtadjtbl\nojkernpunct\rsidroot11688229 \fet0 45 | {\*\wgrffmtfilter 2450}\ilfomacatclnup0\stylesortmethod0{\*\ftnsep \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af8\afs20\alang1025 \ltrch\fcs0 46 | \f8\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af8 \ltrch\fcs0 \insrsid12348070 \chftnsep 47 | \par }}{\*\ftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af8\afs20\alang1025 \ltrch\fcs0 \f8\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af8 48 | \ltrch\fcs0 \insrsid12348070 \chftnsepc 49 | \par }}{\*\aftnsep \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af8\afs20\alang1025 \ltrch\fcs0 \f8\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af8 50 | \ltrch\fcs0 \insrsid12348070 \chftnsep 51 | \par }}{\*\aftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af8\afs20\alang1025 \ltrch\fcs0 \f8\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af8 52 | \ltrch\fcs0 \insrsid12348070 \chftnsepc 53 | \par }}\ltrpar \sectd \ltrsect\linex0\linestarts65536\endnhere\sectdefaultcl\sftnbj {\footerr \ltrpar \pard\plain \ltrpar\s34\ql \li360\ri0\widctlpar\tqc\tx3\tqr\tx6\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin360\itap0 \rtlch\fcs1 54 | \af8\afs20\alang1025 \ltrch\fcs0 \f8\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af8 \ltrch\fcs0 \f4\fs20\insrsid12348070 \chpgn }{\rtlch\fcs1 \af8 \ltrch\fcs0 \insrsid12348070 55 | \par }}{\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}} 56 | {\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8 57 | \pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\qc \li360\ri400\nowidctlpar 58 | \tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 \rtlch\fcs1 \af8\afs20\alang1025 \ltrch\fcs0 \f8\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af51\afs36 \ltrch\fcs0 59 | \f51\fs36\ul\insrsid12348070 A Quick Introduction to IFF 60 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 Jerry Morrison, Electronic Arts 61 | \par 10-17-88 62 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 63 | \par 64 | \par IFF is the Amiga-standard "Interchange File Format", designed to work across many machines. 65 | \par 66 | \par 67 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \b\f51\fs20\insrsid12348070 Why IFF? 68 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 69 | \par Did you ever have this happen to your picture file? 70 | \par 71 | \par }\pard \ltrpar\ql \fi-360\li990\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin990\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 You can't load it into another paint program. 72 | \par You need a converter to adopt to "ZooPaint" release 2.0 or a new hardware feature. 73 | \par You must "export" and "import" to use it in a page layout program. 74 | \par You can't move it to another brand of computer. 75 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 76 | \par What about interchanging musical scores, digitized audio, and other data? It seems the only thing that }{\rtlch\fcs1 \af51 \ltrch\fcs0 \i\f51\fs20\insrsid12348070 does}{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 77 | interchange well is plain ASCII text files. 78 | \par 79 | \par It's inexcusable. And yet this is "normal" in MS-DOS. 80 | \par 81 | \par 82 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \b\f51\fs20\insrsid12348070 What is IFF? 83 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 84 | \par IFF, the "Interchange File Format" standard, encourages multimedia inter 85 | change between different programs and different computers. It supports long-lived, extensible data. It's great for composite files like a page layout file that includes photos, an animation file that includes music, and a library of sound effects. 86 | \par 87 | \par IFF is a 2-level standard. The first layer is the "wrapper" or "envelope" structure for all IFF files. Technically, it's the syntax. The second layer defines particular IFF file types such as ILBM (standard raster pictures), ANIM (animation), SMUS (simple 88 | musical score), and 8SVX (8-bit sampled audio voice). 89 | \par 90 | \par IFF is also a design idea: 91 | \par }\pard \ltrpar\qc \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \i\f51\fs20\insrsid12348070 92 | programs should use interchange formats for their everyday storage 93 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 94 | \par This way, users rarely need converters and import/export commands to change software releases, application programs, or hardware. 95 | \par 96 | \par 97 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \b\f51\fs20\insrsid12348070 What's the trick? 98 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 99 | \par File compatibility is easy to achieve if programmers let go of one notion\emdash dumping internal data structures to disk. A program's internal data structures should really be suited to what the program does and how it works 100 | . What's "best" changes as the program evolves new functions and methods. But a disk format should be suited to storage and interchange. 101 | \par 102 | \par Once we design internal formats and disk formats for their own separate purposes, the rest is easy. Reading and writing become behind-the-scenes conversions. But two conversions hidden in each program is much better than a pile of conversion programs. 103 | 104 | \par 105 | \par Does this seem strange? It's what ASCII text programs do! Text editors use line tables, piece tables, gaps, and other str 106 | uctures for fast editing and searching. Text generators and consumers construct and parse files incrementally. Few programs dump text files into memory. That's why the ASCII standard works so well. 107 | \par 108 | \par Also, every file must be self-sufficient. E.g. a picture file has to include its size and number of bits/pixel. 109 | \par }{\rtlch\fcs1 \af8 \ltrch\fcs0 \f40\insrsid12348070 \page }{\rtlch\fcs1 \af51 \ltrch\fcs0 \b\f51\fs20\insrsid12348070 What's an IFF file look like? 110 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 111 | \par IFF is based on data blocks called "chunks". Here's an example color map chunk: 112 | \par 113 | \par }\pard \ltrpar\ql \li1040\ri400\nowidctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin1040\itap0\pararsid11688229 {\pard\plain \ltrpar 114 | \ql \li1040\ri400\nowidctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin1040\itap0\pararsid11688229 \rtlch\fcs1 \af51\afs20\alang1025 \ltrch\fcs0 \f51\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033\insrsid11688229 {\object\objemb 115 | \objw7801\objh1520\objscalex97\objscaley97{\*\objclass Word.Picture.8}{\*\objdata 01050000020000000f000000576f72642e506963747572652e3800000000000000000000100000 116 | d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 117 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 118 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 119 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 120 | fffffffffffffffffdffffff06000000feffffff0400000005000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 121 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 122 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 123 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 124 | ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff020000000709020000000000c000000000000046000000000000000000000000b0e7 125 | 1b8d78dace0103000000c005000000000000030050004900430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 126 | 000000000000000000000000640000000000000003004d004500540041000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0002010100000003000000ffffffff0000000000000000000000000000000000000000000000000000 127 | 0000000000000000000002000000e802000000000000030050004900430054000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000 128 | 0000000000000000000000000e000000fc0100000000000001000000feffffff030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d000000feffffff0f000000100000001100000012000000130000001400000015000000fefffffffeffffffffffffffffffffffffff 129 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 130 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 131 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 132 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6400020001000000000008004f280000db070000781e0000f005000000000000000000000000000000000000d1030000ce03000000000000000000000000000000000000000000ff00000000000000ff00000000000000ff000000000000 133 | 00ff000000000000000000000000000000000000000000000000000000000000000008004f28db0700000100090000037001000004001c0000000000050000000b0200000000050000000c024c0086010500000004010d000000050000002e01180000000500000002010100000005000000090200000000050000000102 134 | ffffff00030000001e0007000000fc020100000000000000040000002d01000008000000fa0206000200000000000000040000002d010100070000001b044b00cb0001006f0008000000fa0206000100000000000000040000002d01020004000000f001010005000000140215006f000500000013021500c90005000000 135 | 140229006f000500000013022900c9001c000000fb02f6ff0000000000009001000000000000002048656c766574696361000ab980ea6505ccdd3600d894487680014c76a41f6659040000002d0101000d00000021050e0063686172207479706549445b345d0f002c000d00000021050e00206c6f6e6720646174615369 136 | 7a6523002b000c00000021050b006368617220646174615b5d693d003c001c000000fb02f6ff00000000000090010000000000000030436f757269657200441d0aec40ea6505ccdd3600d894487680014c76a41f6659040000002d01030004000000f0010100090000002105060027434d4150270f007500070000002105 137 | 02003438230075000d00000021050e00302c20302c20302c203235352c20370075000b00000021050a003235352c203235352085430075001c000000fb02f6ff0000000000009001020000000000002048656c766574696361000aba80ea6505ccdd3600d894487680014c76a41f6659040000002d01010004000000f001 138 | 03001a00000021052700696e20616e20494c424d2066696c652c20434d4150206d65616e732022636f6c6f72206d617022000e00ce000d00000021050d0034382064617461206279746573002300ce001b00000021052900313620332d6279746520636f6c6f722076616c7565733a20626c61636b2c2077686974652c20 139 | 2e2e2e003d00ce00040000002701ffff03000000000000000000000000000000000000000000000000000000000001fc00000000004c01861101a10064000c574f524400000000004c018601000a00000000004c01860700020002300001006f004b00cb0700010001220015006f5a00220029006f5a00a10096000c0300 140 | 000001000000000000002c000c00150948656c7665746963610300150d000a2e0004000000002b2c0f0e63686172207479706549445b345da00097a10096000c030000000100000000000000280023002b0e206c6f6e67206461746153697a65a00097a10096000c0300000001000000000000002b111a0b636861722064 141 | 6174615b5da00097a10096000c0100000001000000000000002c000a001607436f757269657203001628000f00750627434d415027a00097a10096000c0100000001000000000000002a14023438a00097a10096000c0100000001000000000000002a140e302c20302c20302c203235352c202a0c0a3235352c20323535 142 | 20c9a00097a10096000c010000000100000000000000030015040228000e00ce27696e20616e20494c424d2066696c652c20434d4150206d65616e732022636f6c6f72206d617022a00097a10096000c0100000001000000000000002a150d34382064617461206279746573a00097a10096000c01000000010000000000 143 | 00002a1a29313620332d6279746520636f6c6f722076616c7565733a20626c61636b2c2077686974652c202e2e2ea00097ff00000000020003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 144 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003004f0062006a0049006e0066006f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000200ffff 145 | ffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000001600000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 146 | ffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 147 | 0000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 148 | 00000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001050000050000000d0000004d45544146494c4550494354004f28000025f8ffffe802000008004f28db070000 149 | 0100090000037001000004001c0000000000050000000b0200000000050000000c024c0086010500000004010d000000050000002e01180000000500000002010100000005000000090200000000050000000102ffffff00030000001e0007000000fc020100000000000000040000002d01000008000000fa0206000200 150 | 000000000000040000002d010100070000001b044b00cb0001006f0008000000fa0206000100000000000000040000002d01020004000000f001010005000000140215006f000500000013021500c90005000000140229006f000500000013022900c9001c000000fb02f6ff000000000000900100000000000000204865 151 | 6c766574696361000ab980ea6505ccdd3600d894487680014c76a41f6659040000002d0101000d00000021050e0063686172207479706549445b345d0f002c000d00000021050e00206c6f6e67206461746153697a6523002b000c00000021050b006368617220646174615b5d693d003c001c000000fb02f6ff00000000 152 | 000090010000000000000030436f757269657200441d0aec40ea6505ccdd3600d894487680014c76a41f6659040000002d01030004000000f0010100090000002105060027434d4150270f00750007000000210502003438230075000d00000021050e00302c20302c20302c203235352c20370075000b00000021050a00 153 | 3235352c203235352085430075001c000000fb02f6ff0000000000009001020000000000002048656c766574696361000aba80ea6505ccdd3600d894487680014c76a41f6659040000002d01010004000000f00103001a00000021052700696e20616e20494c424d2066696c652c20434d4150206d65616e732022636f6c 154 | 6f72206d617022000e00ce000d00000021050d0034382064617461206279746573002300ce001b00000021052900313620332d6279746520636f6c6f722076616c7565733a20626c61636b2c2077686974652c202e2e2e003d00ce00040000002701ffff030000000000}{\result {\rtlch\fcs1 \af51 \ltrch\fcs0 155 | \f51\fs20\insrsid11688229 {\pict\wmetafile8\picw10319\pich2011\picwgoal7800\pichgoal1520 \picscalex97\picscaley97 156 | 0100090000037001000004001c0000000000050000000b0200000000050000000c024c0086010500000004010d000000050000002e01180000000500000002010100000005000000090200000000050000000102ffffff00030000001e0007000000fc020100000000000000040000002d01000008000000fa020600020000 157 | 0000000000040000002d010100070000001b044b00cb0001006f0008000000fa0206000100000000000000040000002d01020004000000f001010005000000140215006f000500000013021500c90005000000140229006f000500000013022900c9001c000000fb02f6ff0000000000009001000000000000002048656c76 158 | 6574696361000ab980ea6505ccdd3600d894487680014c76a41f6659040000002d0101000d00000021050e0063686172207479706549445b345d0f002c000d00000021050e00206c6f6e67206461746153697a6523002b000c00000021050b006368617220646174615b5d693d003c001c000000fb02f6ff00000000000090 159 | 010000000000000030436f757269657200441d0aec40ea6505ccdd3600d894487680014c76a41f6659040000002d01030004000000f0010100090000002105060027434d4150270f00750007000000210502003438230075000d00000021050e00302c20302c20302c203235352c20370075000b00000021050a003235352c 160 | 203235352085430075001c000000fb02f6ff0000000000009001020000000000002048656c766574696361000aba80ea6505ccdd3600d894487680014c76a41f6659040000002d01010004000000f00103001a00000021052700696e20616e20494c424d2066696c652c20434d4150206d65616e732022636f6c6f72206d61 161 | 7022000e00ce000d00000021050d0034382064617461206279746573002300ce001b00000021052900313620332d6279746520636f6c6f722076616c7565733a20626c61636b2c2077686974652c202e2e2e003d00ce00040000002701ffff030000000000}}}}}\sectd \ltrsect 162 | \linex0\linestarts65536\endnhere\sectdefaultcl\sftnbj {\rtlch\fcs1 \af8 \ltrch\fcs0 \f40\insrsid12348070 163 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \i\f51\fs20\insrsid12348070 164 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 A chunk is made of a 4-character type identifier, a 32 bit data byte count, and the data bytes. It's like a Macintosh "resource" with a 32-bit size. 165 | \par 166 | \par Fine points: 167 | \par }\pard \ltrpar\ql \fi-180\li810\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin810\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 \bullet \tab 168 | Every 16- and 32-bit number is stored in 68000 byte order\emdash highest byte first. 169 | \par \tab An Intel CPU must reverse the 2- or 4-byte sequence of each number. This applies to chunk }{\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 dataSize}{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 170 | fields and to numbers inside chunk data. It does not affect character strings and byte data because you can't reverse a 1-byte sequence. But it does affect the 32-bit math used in IFF's MakeID macro. The standard does allow CPU-specific byte ordering wit 171 | hin a chunk\rquote s data, but the practice is discouraged. 172 | \par \bullet \tab Every 16- and 32-bit number is stored on an even address. 173 | \par \bullet \tab Every odd-length chunk must be followed by a 0 pad byte. This pad byte is }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\ul\insrsid12348070 not}{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 counted in }{\rtlch\fcs1 \af8 \ltrch\fcs0 174 | \f5\fs20\insrsid12348070 dataSize}{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 . 175 | \par \bullet \tab An ID is made of 4 ASCII characters in the range \'93}{\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 \'94 (space, hex 20) through \'93}{\rtlch\fcs1 \af8 \ltrch\fcs0 176 | \f5\fs20\insrsid12348070 ~}{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 \'94 (tilde, hex 7E). Leading spaces are not permitted. 177 | \par \bullet \tab IDs are compared using a quick 32-bit equality test. Case matters. 178 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 179 | \par A chunk typically holds a C struct (a Pascal record) or an array. For example, an 'ILBM' picture has a 'BMHD' bitmap header chunk (a structure) and a 'BODY' raster body chunk (an array). 180 | \par 181 | \par To construct an IFF file, just put a file type ID (like 'ILBM') into a wrapper chunk called a 'FORM' (think "FILE"). Inside that wrapper place chunks one after another (with pad bytes as needed). The chunk size, rounded up to an even number, always tells 182 | you how many more bytes you need to skip over to get to the next chunk. 183 | \par 184 | \par }\pard \ltrpar\ql \li2160\ri400\nowidctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin2160\itap0\pararsid11688229 {\pard\plain \ltrpar 185 | \ql \li2160\ri400\nowidctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin2160\itap0\pararsid11688229 \rtlch\fcs1 \af51\afs20\alang1025 \ltrch\fcs0 \f51\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033\insrsid11688229 {\object\objemb 186 | \objw5881\objh5541{\*\objclass Word.Picture.8}{\*\objdata 01050000020000000f000000576f72642e506963747572652e3800000000000000000000180000 187 | d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 188 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 189 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 190 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 191 | fffffffffffffffffdffffff0a000000feffffff040000000500000006000000070000000800000009000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 192 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 193 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 194 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 195 | ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff020000000709020000000000c000000000000046000000000000000000000000c00e 196 | 1c8d78dace0103000000000d000000000000030050004900430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 197 | 000000000000000000000000640000000000000003004d004500540041000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0002010100000003000000ffffffff0000000000000000000000000000000000000000000000000000 198 | 0000000000000000000002000000da06000000000000030050004900430054000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000 199 | 0000000000000000000000001e0000001f0500000000000001000000feffffff030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a00 200 | 00001b0000001c0000001d000000feffffff1f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffff 201 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 202 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 203 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff640002000100000000000800631e0000a11c0000f8160000a415000000000000000000000000000000000000e8030000e803000000000000000000000000000000000000000000ff00000000000000ff00000000000000ff000000000000 204 | 00ff00000000000000000000000000000000000000000000000000000000000000000800631ea11c0000010009000003690300000500360000000000050000000b0200000000050000000c02150126010500000004010d000000050000002e01180000000500000002010100000005000000090200000000050000000102 205 | ffffff00030000001e0007000000fc020000000000000000040000002d0100000500000007010100000034000000430fc600880000000700070000000000070007000a011c00280000000700000007000000010001000000000000000000c30e0000c30e0000000000000000000000000000ffffff00efff0000cfff0000 206 | c7ff000087ff000083ff000003ff000001ff000008000000fa0206000100000000000000040000002d0101000500000014020a011b000500000013020a0123000500000014020a01230005000000130212011f0005000000140212011f000500000013020a011b0036000000430fc6008800000008000800000000000800 207 | 08002c001b00280000000800000008000000010001000000000000000000c30e0000c30e0000000000000000000000000000ffffff0000ff000080ff000081ff0000c1ff0000c3ff0000e3ff0000e7ff0000f7ff000005000000140234001b0005000000130234002300050000001402340023000500000013022c001f00 208 | 0500000014022c001f0005000000130234001b000500000014020e011f0005000000130232001f001c000000fb02f6ff0000000000009001000000000000002048656c766574696361000a5b80ea6505ccdd3600d894487680014c76d81e664e040000002d0102000900000021050500323430373000a400080007000000 209 | fc020100000000000000040000002d01030008000000fa0206000200000000000000040000002d010400070000001b04c0008b0082002f00040000002d01010004000000f001040005000000140296002f0005000000130296008900050000001402aa002f00050000001302aa0089001c000000fb02f6ff000000000000 210 | 90010000000000000030436f757269657200801e0af440ea6505ccdd3600d894487680014c76d81e664e040000002d01040004000000f0010200090000002105060027434d4150279000310007000000210502003231a40035000d00000021050d00302c20302c20302c203235358500b800350008000000fa0206000200 211 | 000000000000040000002d010200070000001b0480008b0042002f00040000002d01010004000000f001020005000000140256002f00050000001302560089000500000014026a002f000500000013026a008900090000002105060027424d4844275000310007000000210502003230640035000d00000021050d003332 212 | 302c203230302c20302085007800350008000000fa0206000200000000000000040000002d010200070000001b0410018b00d2002f00040000002d01010004000000f0010200050000001402e6002f00050000001302e6008900050000001402fa002f00050000001302fa008900090000002105060027424f445927e000 213 | 31000900000021050500323430303027f40035000b00000021050900302c20302c20302085000801350007000000210501003030cc003500090000002105060027494c424d273a003100090000002105050032343037302726003500090000002105060027464f524d271000310008000000fa0206000200000000000000 214 | 040000002d010200070000001b0414018f0002002b00040000002d01010004000000f001020005000000140218002d0005000000130218008d000500000014022c002b000500000013022c008d001c000000fb02f6ff0000000000009001020000000000002048656c766574696361000a5f80ea6505ccdd3600d8944876 215 | 80014c76d81e664e040000002d01020004000000f00104001300000021051a00464f524d2069732061207370656369616c206368756e6b204944100095000e0000002105100032343037302064617461206279746573250095000f00000021051100464f524d207479706520697320494c424d0039009500140000002105 216 | 1b006120424d4844206269746d617020686561646572206368756e6b2000640095000e00000021050f00283230206461746120627974657329427000950012000000210517006120434d415020636f6c6f72206d6170206368756e6b2020a40095000e00000021050f0028323120646174612062797465732942b0009500 217 | 13000000210519006120424f44592072617374657220626f6479206368756e6b2000f40095000f00000021051200283234303030206461746120627974657329000195001500000021051d00612070616420627974652020626563617573652074686520434d41502000c70095000d00000021050d006973206f6464206c 218 | 656e67746879d3009500040000002701ffff0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000051f00000000011501261101a10064000c574f5244000000000115012601000a000000000115012684004c010a001c01110023010a001c00237fff010b002200 219 | 237fff010c001c001d7fff010d002100227fff010e001d001e7fff010f002000217fff0110001e001f7fff0111001f00207fff7fff22010a001b080023fc0823fcf8840054002c001b00340023002c001f00207fff002d001e001f7fff002e002000217fff002f001d001e7fff0030002100227fff0031001c001d7fff00 220 | 32002200237fff0033001b001c7fff0034001b00237fff7fff220034001b080023fcf823fc0820010e001f0032001fa10096000c0100000001000000000000002c000c00150948656c7665746963610300150d000a2e0004000000002b08a4053234303730a000970700020002300082002f00c0008b0700010001220096 221 | 002f5a002200aa002f5a00a10096000c0100000001000000000000002c000a001607436f757269657203001628009000310627434d415027a00097a10096000c0100000001000000000000002b0414023231a00097a10096000c0100000001000000000000002a140d302c20302c20302c20323535c9a000970700020002 222 | 300042002f0080008b0700010001220056002f5a0022006a002f5a00a10096000c01000000010000000000000028005000310627424d484427a00097a10096000c0100000001000000000000002b0414023230a00097a10096000c0100000001000000000000002a140d3332302c203230302c203020c9a0009707000200 223 | 023000d2002f0110008b07000100012200e6002f5a002200fa002f5a00a10096000c0100000001000000000000002800e000310627424f445927a00097a10096000c0100000001000000000000002b0414053234303030a00097a10096000c0100000001000000000000002a1409302c20302c203020c9a00097a1009600 224 | 0c0100000001000000000000002800cc00350130a00097a10096000c01000000010000000000000028003a00310627494c424d27a00097a10096000c0100000001000000000000002800260035053234303730a00097a10096000c01000000010000000000000028001000310627464f524d27a000970700020002300002 225 | 002b0114008f0700010001220018002d600022002c002b6200a10096000c010000000100000000000000030015040229641a464f524d2069732061207370656369616c206368756e6b204944a00097a10096000c0100000001000000000000002a151032343037302064617461206279746573a00097a10096000c010000 226 | 0001000000000000002a1411464f524d207479706520697320494c424da00097a10096000c0100000001000000000000002a2b1b6120424d4844206269746d617020686561646572206368756e6b0da00097a10096000c0100000001000000000000002a0c0f283230206461746120627974657329a00097a10096000c01 227 | 00000001000000000000002a34176120434d415020636f6c6f72206d6170206368756e6b20a00097a10096000c0100000001000000000000002a0c0f283231206461746120627974657329a00097a10096000c0100000001000000000000002a44196120424f44592072617374657220626f6479206368756e6b20a00097 228 | a10096000c0100000001000000000000002a0c12283234303030206461746120627974657329a00097a10096000c0100000001000000000000002800c700951d612070616420627974652020626563617573652074686520434d4150202a0c0d6973206f6464206c656e677468a00097ff00000000000000000000000000 229 | 000000000000000000000000000000000000000002000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 230 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 231 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003004f0062006a0049006e0066006f0000000000000000000000000000000000000000000000 232 | 000000000000000000000000000000000000000000000000000012000200ffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000330000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000 233 | 0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 234 | 00000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 235 | 000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001050000050000000d0000004d45544146494c455049435400631e0000 236 | 5fe3ffffda0600000800631ea11c0000 237 | 010009000003690300000500360000000000050000000b0200000000050000000c02150126010500000004010d000000050000002e01180000000500000002010100000005000000090200000000050000000102ffffff00030000001e0007000000fc020000000000000000040000002d01000005000000070101000000 238 | 34000000430fc600880000000700070000000000070007000a011c00280000000700000007000000010001000000000000000000c30e0000c30e0000000000000000000000000000ffffff00efff0000cfff0000c7ff000087ff000083ff000003ff000001ff000008000000fa0206000100000000000000040000002d01 239 | 01000500000014020a011b000500000013020a0123000500000014020a01230005000000130212011f0005000000140212011f000500000013020a011b0036000000430fc600880000000800080000000000080008002c001b00280000000800000008000000010001000000000000000000c30e0000c30e000000000000 240 | 0000000000000000ffffff0000ff000080ff000081ff0000c1ff0000c3ff0000e3ff0000e7ff0000f7ff000005000000140234001b0005000000130234002300050000001402340023000500000013022c001f000500000014022c001f0005000000130234001b000500000014020e011f0005000000130232001f001c00 241 | 0000fb02f6ff0000000000009001000000000000002048656c766574696361000a5b80ea6505ccdd3600d894487680014c76d81e664e040000002d0102000900000021050500323430373000a400080007000000fc020100000000000000040000002d01030008000000fa0206000200000000000000040000002d010400 242 | 070000001b04c0008b0082002f00040000002d01010004000000f001040005000000140296002f0005000000130296008900050000001402aa002f00050000001302aa0089001c000000fb02f6ff00000000000090010000000000000030436f757269657200801e0af440ea6505ccdd3600d894487680014c76d81e664e 243 | 040000002d01040004000000f0010200090000002105060027434d4150279000310007000000210502003231a40035000d00000021050d00302c20302c20302c203235358500b800350008000000fa0206000200000000000000040000002d010200070000001b0480008b0042002f00040000002d01010004000000f001 244 | 020005000000140256002f00050000001302560089000500000014026a002f000500000013026a008900090000002105060027424d4844275000310007000000210502003230640035000d00000021050d003332302c203230302c20302085007800350008000000fa0206000200000000000000040000002d0102000700 245 | 00001b0410018b00d2002f00040000002d01010004000000f0010200050000001402e6002f00050000001302e6008900050000001402fa002f00050000001302fa008900090000002105060027424f445927e00031000900000021050500323430303027f40035000b00000021050900302c20302c203020850008013500 246 | 07000000210501003030cc003500090000002105060027494c424d273a003100090000002105050032343037302726003500090000002105060027464f524d271000310008000000fa0206000200000000000000040000002d010200070000001b0414018f0002002b00040000002d01010004000000f001020005000000 247 | 140218002d0005000000130218008d000500000014022c002b000500000013022c008d001c000000fb02f6ff0000000000009001020000000000002048656c766574696361000a5f80ea6505ccdd3600d894487680014c76d81e664e040000002d01020004000000f00104001300000021051a00464f524d206973206120 248 | 7370656369616c206368756e6b204944100095000e0000002105100032343037302064617461206279746573250095000f00000021051100464f524d207479706520697320494c424d00390095001400000021051b006120424d4844206269746d617020686561646572206368756e6b2000640095000e00000021050f00 249 | 283230206461746120627974657329427000950012000000210517006120434d415020636f6c6f72206d6170206368756e6b2020a40095000e00000021050f0028323120646174612062797465732942b000950013000000210519006120424f44592072617374657220626f6479206368756e6b2000f40095000f000000 250 | 21051200283234303030206461746120627974657329000195001500000021051d00612070616420627974652020626563617573652074686520434d41502000c70095000d00000021050d006973206f6464206c656e67746879d3009500040000002701ffff030000000000}{\result {\rtlch\fcs1 \af51 251 | \ltrch\fcs0 \f51\fs20\insrsid11688229 {\pict\wmetafile8\picw7779\pich7329\picwgoal5880\pichgoal5540 252 | 010009000003690300000500360000000000050000000b0200000000050000000c02150126010500000004010d000000050000002e01180000000500000002010100000005000000090200000000050000000102ffffff00030000001e0007000000fc020000000000000000040000002d0100000500000007010100000034 253 | 000000430fc600880000000700070000000000070007000a011c00280000000700000007000000010001000000000000000000c30e0000c30e0000000000000000000000000000ffffff00efff0000cfff0000c7ff000087ff000083ff000003ff000001ff000008000000fa0206000100000000000000040000002d010100 254 | 0500000014020a011b000500000013020a0123000500000014020a01230005000000130212011f0005000000140212011f000500000013020a011b0036000000430fc600880000000800080000000000080008002c001b00280000000800000008000000010001000000000000000000c30e0000c30e000000000000000000 255 | 0000000000ffffff0000ff000080ff000081ff0000c1ff0000c3ff0000e3ff0000e7ff0000f7ff000005000000140234001b0005000000130234002300050000001402340023000500000013022c001f000500000014022c001f0005000000130234001b000500000014020e011f0005000000130232001f001c000000fb02 256 | f6ff0000000000009001000000000000002048656c766574696361000a5b80ea6505ccdd3600d894487680014c76d81e664e040000002d0102000900000021050500323430373000a400080007000000fc020100000000000000040000002d01030008000000fa0206000200000000000000040000002d010400070000001b 257 | 04c0008b0082002f00040000002d01010004000000f001040005000000140296002f0005000000130296008900050000001402aa002f00050000001302aa0089001c000000fb02f6ff00000000000090010000000000000030436f757269657200801e0af440ea6505ccdd3600d894487680014c76d81e664e040000002d01 258 | 040004000000f0010200090000002105060027434d4150279000310007000000210502003231a40035000d00000021050d00302c20302c20302c203235358500b800350008000000fa0206000200000000000000040000002d010200070000001b0480008b0042002f00040000002d01010004000000f00102000500000014 259 | 0256002f00050000001302560089000500000014026a002f000500000013026a008900090000002105060027424d4844275000310007000000210502003230640035000d00000021050d003332302c203230302c20302085007800350008000000fa0206000200000000000000040000002d010200070000001b0410018b00 260 | d2002f00040000002d01010004000000f0010200050000001402e6002f00050000001302e6008900050000001402fa002f00050000001302fa008900090000002105060027424f445927e00031000900000021050500323430303027f40035000b00000021050900302c20302c203020850008013500070000002105010030 261 | 30cc003500090000002105060027494c424d273a003100090000002105050032343037302726003500090000002105060027464f524d271000310008000000fa0206000200000000000000040000002d010200070000001b0414018f0002002b00040000002d01010004000000f001020005000000140218002d0005000000 262 | 130218008d000500000014022c002b000500000013022c008d001c000000fb02f6ff0000000000009001020000000000002048656c766574696361000a5f80ea6505ccdd3600d894487680014c76d81e664e040000002d01020004000000f00104001300000021051a00464f524d2069732061207370656369616c20636875 263 | 6e6b204944100095000e0000002105100032343037302064617461206279746573250095000f00000021051100464f524d207479706520697320494c424d00390095001400000021051b006120424d4844206269746d617020686561646572206368756e6b2000640095000e00000021050f00283230206461746120627974 264 | 657329427000950012000000210517006120434d415020636f6c6f72206d6170206368756e6b2020a40095000e00000021050f0028323120646174612062797465732942b000950013000000210519006120424f44592072617374657220626f6479206368756e6b2000f40095000f00000021051200283234303030206461 265 | 746120627974657329000195001500000021051d00612070616420627974652020626563617573652074686520434d41502000c70095000d00000021050d006973206f6464206c656e67746879d3009500040000002701ffff030000000000}}}}}\sectd \ltrsect 266 | \linex0\linestarts65536\endnhere\sectdefaultcl\sftnbj {\rtlch\fcs1 \af8 \ltrch\fcs0 \f40\insrsid12348070 267 | \par }\pard \ltrpar\ql \li2160\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin2160\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 268 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 269 | A FORM always contains one 4-character FORM type ID (a file type, in this case 'ILBM') 270 | followed by any number of data chunks. In this example, the FORM type is 'ILBM', which stands for "InterLeaved BitMap". (ILBM is an IFF standard for bitplane raster pictures.) This example has 3 chunks. Note the pad byte after the odd length chunk. 271 | \par 272 | \par Within FORMs ILBM, 'BMHD' identifies a bitmap header chunk, 'CMAP' a color map, and 'BODY' a raster body. In general, the chunk IDs in a FORM are }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\ul\insrsid12348070 local}{\rtlch\fcs1 \af51 \ltrch\fcs0 273 | \f51\fs20\insrsid12348070 to the FORM type ID. The exceptions are the 4 global chunk IDs 'FORM', 'LIST', 'CAT ', and 'PROP'. (A FORM may contain other FORM chunks. E.g. an animation FORM might contain picture FORMs and sound FORMs.) 274 | \par 275 | \par 276 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \b\f51\fs20\insrsid12348070 How to read an IFF file? 277 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 278 | \par Given the C subroutine "GetChunkHeader()": 279 | \par 280 | \par }\pard \ltrpar\ql \fi-360\li990\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin990\itap0\pararsid11688229 {\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 281 | /* Skip any remaining bytes of the current chunk, skip any pad byte, and read the next chunk header. Returns the chunk ID or END_MARK. */ 282 | \par ID GetChunkHeader(); 283 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 284 | \par we read the chunks in a FORM ILBM with a loop like this: 285 | \par 286 | \par }\pard \ltrpar\ql \fi-360\li990\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin990\itap0\pararsid11688229 {\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 do 287 | \par switch (id = GetChunkHeader()) 288 | \par \{ 289 | \par case 'CMAP': ProcessCMAP(); break; 290 | \par case 'BMHD': ProcessBMHD(); break; 291 | \par case 'BODY': ProcessBODY(); break; 292 | \par /* default: just ignore the chunk */ 293 | \par \} 294 | \par until (id == END_MARK); 295 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 296 | \par This loop processes each chunk by dispatching to a routine that reads the specific type of chunk data. We don't assume a particular order of chunks. This is a simple parser. Note that even if you have fully processed a chunk, you should respect its chunk 297 | size, even if the size is larger than you expected. 298 | \par 299 | \par This sample ignores important details like I/O errors. There are also higher-level errors to check, e.g. if we hit END_MARK without reading a BODY, we didn't get a picture. 300 | \par 301 | \par Every IFF file is a 'FORM', 'LIST', or 'CAT ' chunk. You can recognize an IFF file by those first 4 bytes. ('FORM' is far and away the most common. We'll get to LIST and CAT below.) If the file contains a FORM, dispatch on the FORM type ID to a chunk-read 302 | er loop like the one above. 303 | \par 304 | \par 305 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \b\f51\fs20\insrsid12348070 File extensibility 306 | \par }{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 307 | \par IFF files are extensible and forward/backward compatible: 308 | \par 309 | \par }\pard \ltrpar\ql \fi-180\li810\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin810\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 \bullet \tab 310 | Chunk contents should be designed for compatibility across environments and for longevity. 311 | \par \bullet \tab The standards team for a FORM type can extend one of its chunks that contains a structure by appending new, optional structure fields. 312 | \par \bullet \tab Anyone can define new FORM types as well as new chunk types within a FORM type. Storing private chunks within a FORM is ok, but be sure to register your activities with Commodore-Amiga Technical Support. 313 | \par \bullet \tab A chunk can be superseded by a new chunk type, e.g. to store more bits per RGB color register. New programs can output the old chunk (for backward compatibility) along with the new chunk. 314 | \par \bullet \tab If you must change data in an incompatible way, change the chunk ID or the FORM type ID. 315 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af8 \ltrch\fcs0 \f40\insrsid12348070 \page }{\rtlch\fcs1 \af51 \ltrch\fcs0 \b\f51\fs20\insrsid12348070 316 | Advanced Topics: CAT, LIST, and PROP}{\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 317 | \par 318 | \par Sometimes you want to put several "files" into one, such as a picture library. This is what CAT is for. It "concatenates" FORM and LIST chunks. 319 | \par 320 | \par }\pard \ltrpar\ql \li2740\ri400\nowidctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin2740\itap0\pararsid11688229 {\pard\plain \ltrpar 321 | \ql \li2740\ri400\nowidctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin2740\itap0\pararsid11688229 \rtlch\fcs1 \af51\afs20\alang1025 \ltrch\fcs0 \f51\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033\insrsid11688229 {\object\objemb 322 | \objw4681\objh4681\objscalex43\objscaley70{\*\objclass Word.Picture.8}{\*\objdata 01050000020000000f000000576f72642e506963747572652e3800000000000000000000120000 323 | d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 324 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 325 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 326 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 327 | fffffffffffffffffdffffff07000000feffffff040000000500000006000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 328 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 329 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 330 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 331 | ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff020000000709020000000000c000000000000046000000000000000000000000f083 332 | 1c8d78dace01030000000008000000000000030050004900430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 333 | 000000000000000000000000640000000000000003004d004500540041000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0002010100000003000000ffffffff0000000000000000000000000000000000000000000000000000 334 | 0000000000000000000002000000b403000000000000030050004900430054000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000 335 | 00000000000000000000000011000000770300000000000001000000feffffff030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f00000010000000feffffff12000000130000001400000015000000160000001700000018000000190000001a00 336 | 00001b0000001c0000001d0000001e000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 337 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 338 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 339 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6400020001000000000008002f1800002f180000481200004812000000000000000000000000000000000000b1010000bd02000000000000000000000000000000000000000000ff00000000000000ff00000000000000ff000000000000 340 | 00ff000000000000000000000000000000000000000000000000000000000000000008002f182f180000010009000003d601000004001c0000000000050000000b0264003201050000000c02ea00ea000500000004010d000000050000002e01180000000500000002010100000005000000090200000000050000000102 341 | ffffff00030000001e0007000000fc020100000000000000040000002d01000008000000fa0206000200000000000000040000002d010100070000001b04f6009201a400360108000000fa0206000100000000000000040000002d01020004000000f0010100050000001402b8003601050000001302b800900105000000 342 | 1402cc003601050000001302cc0090011c000000fb02f6ff00000000000090010000000000000030436f757269657200d81e0a5180ea6505ccdd3600d894487680014c76b61f665b040000002d010100090000002105060027464f524d27b20038010900000021050500323430373027c6003c0109000000210506002749 343 | 4c424d27da003c01090000002105060027494c424d279c003801090000002105050034383136302788003c0109000000210506002743415420277200380108000000fa0206000200000000000000040000002d010300070000001b044e01960164003201040000002d01020004000000f00103000500000014027a003401 344 | 0500000013027a0094010500000014028e0032010500000013028e009401050000001402e0003801050000001302e000900107000000210501008501ee003e0108000000fa0206000200000000000000040000002d010300070000001b044a019201f8003601040000002d01020004000000f00103000500000014020c01 345 | 36010500000013020c0190010500000014022001360105000000130220019001090000002105060027464f524d270601380109000000210505003234303730271a013c01090000002105060027494c424d272e013c0105000000140234013801050000001302340190010700000021050100850142013e011c000000fb02 346 | f6ff0000000000009001020000000000002048656c766574696361000abc40ea6505ccdd3600d894487680014c76b61f665b040000002d01030004000000f00101000d00000021050d00636f6e636174656e6174696f6e0073009c010e000000210510003438313630206461746120627974657388009c01130000002105 347 | 190068696e743a20636f6e7461696e7320464f524d7320494c424d009c009c010c00000021050b006120464f524d20494c424d62b3009c010f00000021051100616e6f7468657220464f524d20494c424d0006019c01040000002701ffff030000000000000000000000000000000000037700640132014e021c1101a000 348 | 8201000a0000000002d0024007000200023000a4013600f6019207000100012200b801365a002200cc01365a00a100960006050000000200a1009a0008fffd000000120000a000980300160d000a2800b201380627464f524d27a00099a00097a100960006050000000200a1009a0008fffd0000000f0000a000982b0414 349 | 053234303730a00099a00097a100960006050000000200a1009a0008fffd000000270000a000982a140627494c424d27a00099a00097a100960006050000000200a1009a0008fffd000000120000a0009828009c01380627494c424d27a00099a00097a100960006050000000200a1009a0008fffd0000000f0000a00098 350 | 280088013c053438313630a00099a00097a100960006050000000200a1009a0008fffd000000120000a00098280072013806274341542027a00099a0009707000200023000640132014e0196070001000122007a0134600022008e013262002200e001385800a100960006050000000200a1009a0008fffd0000001d0000 351 | a000982b067c01c9a00099a0009707000200023000f80136014a0192070001000122010c01365a0022012001365a00a100960006050000000200a1009a0008fffd000000120000a0009828010601380627464f524d27a00099a00097a100960006050000000200a1009a0008fffd0000000f0000a000982b041405323430 352 | 3730a00099a00097a100960006050000000200a1009a0008fffd000000120000a000982a140627494c424d27a00099a0009722013401385800a100960006050000000200a1009a0008fffd000000030000a000982b021401c9a00099a00097a100960006050000000200a1009a0008fffd000000220000a0009803001504 353 | 02280073019c0d636f6e636174656e6174696f6ea00099a00097a100960006050000000200a1009a0008fffd000000280000a000982a151034383136302064617461206279746573a00099a00097a100960006050000000200a1009a0008fffd0000003d0000a000982a141968696e743a20636f6e7461696e7320464f52 354 | 4d7320494c424da00099a00097a100960006050000000200a1009a0008fffd000000210000a000982a170b6120464f524d20494c424da00099a00097a100960006050000000200a1009a0008fffd0000002e0000a000982a5311616e6f7468657220464f524d20494c424da00099a00097a00083ff000000000000000000 355 | 0200030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003004f0062006a0049006e0066006f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 356 | 000012000200ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000001f0000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 357 | 0000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 358 | 00000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 359 | 000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001050000050000000d0000004d45544146494c4550494354002f180000d1e7ffffb403000008002f182f180000 360 | 010009000003d601000004001c0000000000050000000b0264003201050000000c02ea00ea000500000004010d000000050000002e01180000000500000002010100000005000000090200000000050000000102ffffff00030000001e0007000000fc020100000000000000040000002d01000008000000fa0206000200 361 | 000000000000040000002d010100070000001b04f6009201a400360108000000fa0206000100000000000000040000002d01020004000000f0010100050000001402b8003601050000001302b8009001050000001402cc003601050000001302cc0090011c000000fb02f6ff00000000000090010000000000000030436f 362 | 757269657200d81e0a5180ea6505ccdd3600d894487680014c76b61f665b040000002d010100090000002105060027464f524d27b20038010900000021050500323430373027c6003c01090000002105060027494c424d27da003c01090000002105060027494c424d279c00380109000000210505003438313630278800 363 | 3c0109000000210506002743415420277200380108000000fa0206000200000000000000040000002d010300070000001b044e01960164003201040000002d01020004000000f00103000500000014027a0034010500000013027a0094010500000014028e0032010500000013028e009401050000001402e00038010500 364 | 00001302e000900107000000210501008501ee003e0108000000fa0206000200000000000000040000002d010300070000001b044a019201f8003601040000002d01020004000000f00103000500000014020c0136010500000013020c019001050000001402200136010500000013022001900109000000210506002746 365 | 4f524d270601380109000000210505003234303730271a013c01090000002105060027494c424d272e013c0105000000140234013801050000001302340190010700000021050100850142013e011c000000fb02f6ff0000000000009001020000000000002048656c766574696361000abc40ea6505ccdd3600d8944876 366 | 80014c76b61f665b040000002d01030004000000f00101000d00000021050d00636f6e636174656e6174696f6e0073009c010e000000210510003438313630206461746120627974657388009c01130000002105190068696e743a20636f6e7461696e7320464f524d7320494c424d009c009c010c00000021050b006120 367 | 464f524d20494c424d62b3009c010f00000021051100616e6f7468657220464f524d20494c424d0006019c01040000002701ffff030000000000}{\result {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid11688229 {\pict\wmetafile8\picw6191\pich6191\picwgoal4680\pichgoal4680 368 | \picscalex43\picscaley70 369 | 010009000003d601000004001c0000000000050000000b0264003201050000000c02ea00ea000500000004010d000000050000002e01180000000500000002010100000005000000090200000000050000000102ffffff00030000001e0007000000fc020100000000000000040000002d01000008000000fa020600020000 370 | 0000000000040000002d010100070000001b04f6009201a400360108000000fa0206000100000000000000040000002d01020004000000f0010100050000001402b8003601050000001302b8009001050000001402cc003601050000001302cc0090011c000000fb02f6ff00000000000090010000000000000030436f7572 371 | 69657200d81e0a5180ea6505ccdd3600d894487680014c76b61f665b040000002d010100090000002105060027464f524d27b20038010900000021050500323430373027c6003c01090000002105060027494c424d27da003c01090000002105060027494c424d279c003801090000002105050034383136302788003c0109 372 | 000000210506002743415420277200380108000000fa0206000200000000000000040000002d010300070000001b044e01960164003201040000002d01020004000000f00103000500000014027a0034010500000013027a0094010500000014028e0032010500000013028e009401050000001402e0003801050000001302 373 | e000900107000000210501008501ee003e0108000000fa0206000200000000000000040000002d010300070000001b044a019201f8003601040000002d01020004000000f00103000500000014020c0136010500000013020c0190010500000014022001360105000000130220019001090000002105060027464f524d2706 374 | 01380109000000210505003234303730271a013c01090000002105060027494c424d272e013c0105000000140234013801050000001302340190010700000021050100850142013e011c000000fb02f6ff0000000000009001020000000000002048656c766574696361000abc40ea6505ccdd3600d894487680014c76b61f 375 | 665b040000002d01030004000000f00101000d00000021050d00636f6e636174656e6174696f6e0073009c010e000000210510003438313630206461746120627974657388009c01130000002105190068696e743a20636f6e7461696e7320464f524d7320494c424d009c009c010c00000021050b006120464f524d20494c 376 | 424d62b3009c010f00000021051100616e6f7468657220464f524d20494c424d0006019c01040000002701ffff030000000000}}}}}\sectd \ltrsect\linex0\linestarts65536\endnhere\sectdefaultcl\sftnbj {\rtlch\fcs1 \af8 \ltrch\fcs0 \f40\insrsid12348070 377 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 378 | \par This example CAT holds two ILBMs. It can be shown outline-style: 379 | \par 380 | \par }\pard \ltrpar\ql \fi-360\li990\ri400\nowidctlpar\tx2880\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin990\itap0\pararsid11688229 {\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 CAT ILBM 381 | \par ..FORM ILBM\tab \\ 382 | \par ....BMHD\tab | }{\rtlch\fcs1 \af51 \ltrch\fcs0 \i\f51\fs20\insrsid12348070 a complete FORM ILBM picture 383 | \par }{\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 ....CMAP\tab | 384 | \par ....BODY\tab / 385 | \par ..FORM ILBM 386 | \par ....BMHD 387 | \par ....CMAP 388 | \par ....BODY 389 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 390 | \par Sometimes you want to share the same color map across many pictures. LIST and PROP do this: 391 | \par 392 | \par }\pard \ltrpar\ql \fi-360\li990\ri400\nowidctlpar\tx2880\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin990\itap0\pararsid11688229 {\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 LIST ILBM 393 | \par ..PROP ILBM\tab }{\rtlch\fcs1 \af51 \ltrch\fcs0 \i\f51\fs20\insrsid12348070 default properties for FORMs ILBM 394 | \par }{\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 ....CMAP\tab }{\rtlch\fcs1 \af51 \ltrch\fcs0 \i\f51\fs20\insrsid12348070 an ILBM CMAP chunk (there could be a BMHD chunk here, too) 395 | \par }{\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 ..FORM ILBM 396 | \par ....BMHD\tab }{\rtlch\fcs1 \af51 \ltrch\fcs0 \i\f51\fs20\insrsid12348070 (there could be a CMAP here to override the default) 397 | \par }{\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 ....BODY 398 | \par ..FORM ILBM 399 | \par ....BMHD\tab }{\rtlch\fcs1 \af51 \ltrch\fcs0 \i\f51\fs20\insrsid12348070 (there could be a CMAP here to override the default) 400 | \par }{\rtlch\fcs1 \af8 \ltrch\fcs0 \f5\fs20\insrsid12348070 ....BODY 401 | \par }\pard \ltrpar\ql \li360\ri400\nowidctlpar\tx7380\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin400\lin360\itap0\pararsid11688229 {\rtlch\fcs1 \af51 \ltrch\fcs0 \f51\fs20\insrsid12348070 402 | \par A LIST holds PROPs and FORMs (and occasionally LISTs and CATs). A PROP ILBM contains default data (in the above example, just 403 | one CMAP chunk) for all FORMs ILBM in the LIST. Any FORM may override the PROP-defined default with its own CMAP. All PROPs must appear at the beginning of a LIST. Each FORM type standardizes (among other things) which of its chunks are "property chunks" 404 | (may appear in PROPs) and which are "data chunks" (may not appear in PROPs). 405 | \par 406 | \par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8 407 | 72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7 408 | 2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b 409 | 44d7a07a83c82f308ac7b0a0f0fbf90c2480980b58abc733615aa2d210c2e02cb04430076a7ee833dfb6ce62e3ed7e14693e8317d8cd0433bf5c60f53fea2fe7 410 | 065bd80facb647e9e25c7fc421fd2ddb526b2e9373fed4bb902e182e97b7b461e6bfad3f010000ffff0300504b030414000600080000002100a5d6a7e7c00000 411 | 00360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060abb08 412 | 84a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d94fbc 413 | 52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82fe353 414 | bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f7468 415 | 656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d592c9c 416 | 070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8d3f7 417 | 29e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f7468656d65 418 | 312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87615b8116d8 419 | a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad79482a9c04 420 | 98f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b5d8a314d3c 421 | 94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab999fb7b471 422 | 7509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9699640f671 423 | 9e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd5868b37a088d1 424 | e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d60cf03ac1a5 425 | 193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f9e7ef3f2d1 426 | 17d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be15c308d3f2 427 | 8acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a99793849c26ae6 428 | 6252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d32a423279a 429 | 668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2af074481847 430 | bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86e877f0034e 431 | 16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb44f95d843b 432 | 5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a6409fb44d0 433 | 8741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c3d9058edf2 434 | c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db02565e85f3b966 435 | 0d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276b9f7dec44b 436 | 7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8c33585b5fb 437 | 9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e51440ca2e0 438 | 088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95b21be5ceaf 439 | 8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff6dce591a26 440 | ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec69ffb9e65d0 441 | 28d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239b75a5bb1e6 442 | 345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a44959d366ad93 443 | b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e82db8df9f30 444 | 254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f74 445 | 68656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f24 446 | 51eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198 447 | 720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528 448 | a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100828abc13fa0000001c0200001300000000000000000000000000 449 | 000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000000000000000000000 450 | 002b0100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000140200007468 451 | 656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b000016000000000000000000 452 | 00000000d10200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b010000270000000000 453 | 00000000000000009b0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000960a00000000} 454 | {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 455 | 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 456 | 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 457 | 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} 458 | {\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; 459 | \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; 460 | \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; 461 | \lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; 462 | \lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; 463 | \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; 464 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; 465 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; 466 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; 467 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; 468 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; 469 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; 470 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; 471 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; 472 | \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; 473 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; 474 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; 475 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; 476 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; 477 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; 478 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; 479 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; 480 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; 481 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; 482 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; 483 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; 484 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; 485 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; 486 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; 487 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; 488 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; 489 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; 490 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; 491 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; 492 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; 493 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; 494 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; 495 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; 496 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; 497 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; 498 | \lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; 499 | \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; 500 | \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; 501 | \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 502 | 4d73786d6c322e534158584d4c5265616465722e352e3000000000000000000000060000 503 | d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 504 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 505 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 506 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 507 | fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 508 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 509 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 510 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 511 | ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f00000000000000000000000020f9 512 | 1c8d78dace01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 513 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 514 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 515 | 0000000000000000000000000000000000000000000000000105000000000000}} -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/ILBM.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/ILBM.doc -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/ILBM.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/ILBM.docx -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/ILBM.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/ILBM.pdf -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/SMUS.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/SMUS.doc -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/SMUS.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/SMUS.docx -------------------------------------------------------------------------------- /IFF docs with Commodore revisions/SMUS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1fish2/IFF/1e2aca18ed8dcf1fc822eb35d152a36a44761820/IFF docs with Commodore revisions/SMUS.pdf -------------------------------------------------------------------------------- /IFF retrospective.md: -------------------------------------------------------------------------------- 1 | 2 | IFF Retrospective 3 | ================= 4 | 5 | Jerry Morrison 6 | 2013-11-05 7 | 8 | * In the original IFF doc, I should've listed Geoff Brown of Uhuru Sound Software in the credits and referenced his use of chunked data and 4-character-codes in Deluxe Music Construction Set in "Previous Work." He provided a lot of input and experience to IFF's design even though he wasn't part of the "Standards Committee." My screw-up. Sorry, Geoff! 9 | 10 | * Keep it simple! The LIST/PROP feature and the chunk pad byte were useful but not worth the total cost when you consider explaining, learning, implementing the standard, and bug potential. The docs would've been better as a concise spec with a separate doc to explain its rationale and utility. The ILBM format interleaves raster bit-planes to enable incrementally reading and displaying a file. That was great (esp. at floppy disk speeds) but the example implementation was overcomplicated. 11 | 12 | * When you push a standard, you get a lot of pushback. Developers on 8-bit microcomputers were unhappy about 8 bytes of overhead per chunk. Developers on little-endian CPUs were unhappy having to do byte-swapping for everyday I/O even though it's simpler and faster than conditional byte-swapping. So when Greg Riker -- then at Microsoft -- asked for input on storing resource files, I recommended IFF but folded too soon on pushing Microsoft to adopt big-endian chunk lengths. Hence RIFF, the "Resource IFF" aka "Reverse IFF." Was the rift avoidable? 13 | 14 | * A sample hex dump is a good way to introduce a file format: https://groups.google.com/forum/?hl=en#!msg/comp.graphics/Jl56NJsUySE/7q7J4itrjPYJ 15 | 16 | * IFF needed a broader way to distribute the documentation and source code, long before the web. More PR, too. 17 | 18 | * AIFF is an application of the IFF standard although Apple didn't say that explicitly. 19 | 20 | * PNG was a further evolution of these design ideas. Its use of upper and lower case characters in chunk IDs is clever. 21 | -------------------------------------------------------------------------------- /IFF source code/Makefile: -------------------------------------------------------------------------------- 1 | # @(#) Makefile 96/05/19 1.11 2 | 3 | TARGET_DIRECTORY = ${MODULE_DIR} 4 | LOADERTOOL_FLAGS = -Htype=4 -e main 5 | SIGNED_MODULE = 1 6 | NO_CHDIR_MODULE = 1 7 | SHOW_MODULE_INFO = 1 8 | 9 | include ${CODEMGR_WS}/ws_root/variables/linkexec 10 | include ${CODEMGR_WS}/ws_root/rules/linkexec 11 | -------------------------------------------------------------------------------- /IFF source code/autodocs.c: -------------------------------------------------------------------------------- 1 | /* @(#) autodocs.c 96/04/29 1.23 */ 2 | 3 | /** 4 | ||| AUTODOC -class IFF -name RegisterCollectionChunks 5 | ||| Defines chunks to be collected during the parse operation. 6 | ||| 7 | ||| Synopsis 8 | ||| 9 | ||| Err RegisterCollectionChunks(IFFParser *iff, const IFFTypeID typeids[]); 10 | ||| 11 | ||| Description 12 | ||| 13 | ||| You supply this function an array of IFFTypeID structures which 14 | ||| define the chunks that should be stored as they are encountered 15 | ||| during the parse operation. The array is terminated by a structure 16 | ||| containing a Type field set to 0. 17 | ||| 18 | ||| The function installs an entry handler for chunks with the given 19 | ||| type and id so that the contents of those chunks will be stored as 20 | ||| they are encountered. This is similar to RegisterPropChunks() except 21 | ||| that more than one chunk of any given type can be stored in lists 22 | ||| which can be returned by FindCollection(). The storage of these 23 | ||| chunks still follows the property chunk scoping rules for IFF files 24 | ||| so that at any given point, stored collection chunks will be valid 25 | ||| in the current context. 26 | ||| 27 | ||| Arguments 28 | ||| 29 | ||| iff 30 | ||| Parser handle to operate on. 31 | ||| 32 | ||| typeids 33 | ||| An array of IFFTypeID structures defining which chunks should 34 | ||| be collected. The array is terminated by a structure whose Type 35 | ||| field is set to 0. 36 | ||| 37 | ||| Return Value 38 | ||| 39 | ||| Returns >= 0 for success, or a negative error code for failure. 40 | ||| Possible error codes currently include: 41 | ||| 42 | ||| IFF_ERR_NOMEM 43 | ||| There was not enough memory to perform the operation. 44 | ||| 45 | ||| Implementation 46 | ||| 47 | ||| Folio call implemented in IFF folio V27. 48 | ||| 49 | ||| Associated Files 50 | ||| 51 | ||| , System.m2/Modules/iff 52 | ||| 53 | ||| See Also 54 | ||| 55 | ||| FindCollection(), RegisterPropChunks() 56 | ||| 57 | **/ 58 | 59 | /** 60 | ||| AUTODOC -class IFF -name InstallEntryHandler 61 | ||| Adds an entry handler to the parser. 62 | ||| 63 | ||| Synopsis 64 | ||| 65 | ||| Err InstallEntryHandler(IFFParser *iff, PackedID type, PackedID id, 66 | ||| ContextInfoLocation pos, IFFCallBack cb, 67 | ||| const void *userData); 68 | ||| 69 | ||| Description 70 | ||| 71 | ||| This function installs an entry handler for a specific type of chunk 72 | ||| into the context for the given parser handle. The type and id are 73 | ||| the identifiers for the chunk to handle. 74 | ||| 75 | ||| The handler will be called whenever the parser enters a chunk of 76 | ||| the given type, so the IFF stream will be positioned to read the 77 | ||| first data byte in the chunk. 78 | ||| 79 | ||| The value your callback routine returns affects the parser 80 | ||| in two ways: 81 | ||| 82 | ||| IFF_CB_CONTINUE 83 | ||| Normal return. The parser will continue through the file. 84 | ||| 85 | ||| 86 | ||| ParseIFF() will stop parsing and return this value directly to 87 | ||| the caller. Return 0 for a normal return, and negative values 88 | ||| for errors. 89 | ||| 90 | ||| Arguments 91 | ||| 92 | ||| iff 93 | ||| The parser handle to affect. 94 | ||| 95 | ||| type 96 | ||| The ID of the container for the chunks to handle (eg: AIFF). 97 | ||| 98 | ||| id 99 | ||| The ID value for the chunks to handle. 100 | ||| 101 | ||| pos 102 | ||| Where the handler should be installed within the context 103 | ||| stack. Refer to the StoreContextInfo() for a description of 104 | ||| how this argument is used. 105 | ||| 106 | ||| cb 107 | ||| The routine to invoke whenever a chunk of the given type and 108 | ||| id is encountered. 109 | ||| 110 | ||| userData 111 | ||| A value that is passed straight through to your callback 112 | ||| routine when it is invoked. 113 | ||| 114 | ||| Return Value 115 | ||| 116 | ||| Returns >= 0 for success, or a negative error code for failure. 117 | ||| 118 | ||| Implementation 119 | ||| 120 | ||| Folio call implemented in IFF folio V27. 121 | ||| 122 | ||| Associated Files 123 | ||| 124 | ||| , System.m2/Modules/iff 125 | ||| 126 | ||| See Also 127 | ||| 128 | ||| InstallExitHandler() 129 | ||| 130 | **/ 131 | 132 | /** 133 | ||| AUTODOC -class IFF -name InstallExitHandler 134 | ||| Adds an exit handler to the parser. 135 | ||| 136 | ||| Synopsis 137 | ||| 138 | ||| Err InstallExitHandler(IFFParser *iff, PackedID type, PackedID id, 139 | ||| ContextInfoLocation pos, IFFCallBack cb, 140 | ||| const void *userData); 141 | ||| 142 | ||| Description 143 | ||| 144 | ||| This function installs an exit handler for a specific type of chunk 145 | ||| into the context for the given parser handle. The type and id are 146 | ||| the identifiers for the chunk to handle. 147 | ||| 148 | ||| The handler will be called whenever the parser is about to leave a 149 | ||| chunk of the given type. The position within the stream is 150 | ||| not constant and must be determined by looking at the cn_Offset 151 | ||| field of the current context. 152 | ||| 153 | ||| The value your callback routine returns affects the parser 154 | ||| in two ways: 155 | ||| 156 | ||| IFF_CB_CONTINUE 157 | ||| Normal return. The parser will continue through the file. 158 | ||| 159 | ||| 160 | ||| ParseIFF() will stop parsing and return this value directly to 161 | ||| the caller. Return 0 for a normal return, and negative values 162 | ||| for errors. 163 | ||| 164 | ||| Arguments 165 | ||| 166 | ||| iff 167 | ||| The parser handle to affect. 168 | ||| 169 | ||| type 170 | ||| The ID of the container for the chunks to handle (eg: AIFF). 171 | ||| 172 | ||| id 173 | ||| The ID value for the chunks to handle. 174 | ||| 175 | ||| pos 176 | ||| Where the handler should be installed within the context 177 | ||| stack. Refer to the StoreContextInfo() for a description of 178 | ||| how this argument is used. 179 | ||| 180 | ||| cb 181 | ||| The routine to invoke whenever a chunk of the given type and 182 | ||| id is about to be exited. 183 | ||| 184 | ||| userData 185 | ||| A value that is passed straight through to your callback 186 | ||| routine when it is invoked. 187 | ||| 188 | ||| Return Value 189 | ||| 190 | ||| Returns >= 0 for success, or a negative error code for failure. 191 | ||| 192 | ||| Implementation 193 | ||| 194 | ||| Folio call implemented in IFF folio V27. 195 | ||| 196 | ||| Associated Files 197 | ||| 198 | ||| , System.m2/Modules/iff 199 | ||| 200 | ||| See Also 201 | ||| 202 | ||| InstallEntryHandler() 203 | ||| 204 | **/ 205 | 206 | /** 207 | ||| AUTODOC -class IFF -name RegisterPropChunks 208 | ||| Defines property chunks to be stored during the parse operation. 209 | ||| 210 | ||| Synopsis 211 | ||| 212 | ||| Err RegisterPropChunks(IFFParser *iff, const IFFTypeID typeids[]); 213 | ||| 214 | ||| Description 215 | ||| 216 | ||| You supply this function an array of IFFTypeID structures which 217 | ||| define the chunks that should be stored as they are encountered 218 | ||| during the parse operation. The array is terminated by a structure 219 | ||| containing a Type field set to 0. 220 | ||| 221 | ||| The function installs an entry handler for chunks with the given 222 | ||| type and ID so that the contents of those chunks will be stored as 223 | ||| they are encountered. The storage of these chunks follows the 224 | ||| property chunk scoping rules for IFF files so that at any given 225 | ||| point, a stored property chunk returned by FindPropContext() will 226 | ||| be the valid property for the current context. 227 | ||| 228 | ||| Arguments 229 | ||| 230 | ||| iff 231 | ||| Parser handle to operate on. 232 | ||| 233 | ||| typeids 234 | ||| An array of IFFTypeID structures defining which chunks should 235 | ||| be stored. The array is terminated by a structure whose Type 236 | ||| field is set to 0. 237 | ||| 238 | ||| Return Value 239 | ||| 240 | ||| Returns >= 0 for success, or a negative error code for failure. 241 | ||| Possible error codes currently include: 242 | ||| 243 | ||| IFF_ERR_NOMEM 244 | ||| There was not enough memory to perform the operation. 245 | ||| 246 | ||| Implementation 247 | ||| 248 | ||| Folio call implemented in IFF folio V27. 249 | ||| 250 | ||| Associated Files 251 | ||| 252 | ||| , System.m2/Modules/iff 253 | ||| 254 | ||| See Also 255 | ||| 256 | ||| FindPropContext() 257 | ||| 258 | **/ 259 | 260 | /** 261 | ||| AUTODOC -class IFF -name RegisterStopChunks 262 | ||| Defines chunks that cause the parser to stop and return to the caller. 263 | ||| 264 | ||| Synopsis 265 | ||| 266 | ||| Err RegisterStopChunks(IFFParser *iff, const IFFTypeID typeids[]); 267 | ||| 268 | ||| Description 269 | ||| 270 | ||| You supply this function an array of IFFTypeID structures which 271 | ||| define the chunks that should cause the parser to stop and return 272 | ||| control to the caller. The array is terminated by a structure 273 | ||| containing a Type field set to 0. 274 | ||| 275 | ||| The function installs an entry handler for chunks with the given 276 | ||| type and ID so that the parser will stop as they are encountered. 277 | ||| 278 | ||| Arguments 279 | ||| 280 | ||| iff 281 | ||| Parser handle to operate on. 282 | ||| 283 | ||| typeids 284 | ||| An array of IFFTypeID structures defining which chunks should 285 | ||| cause the parser to stop. The array is terminated by a structure 286 | ||| whose Type field is set to 0. 287 | ||| 288 | ||| Return Value 289 | ||| 290 | ||| Returns >= 0 for success, or a negative error code for failure. 291 | ||| Possible failure codes include: 292 | ||| 293 | ||| IFF_ERR_NOMEM 294 | ||| There was not enough memory to perform the operation. 295 | ||| 296 | ||| Implementation 297 | ||| 298 | ||| Folio call implemented in IFF folio V27. 299 | ||| 300 | ||| Associated Files 301 | ||| 302 | ||| , System.m2/Modules/iff 303 | ||| 304 | ||| See Also 305 | ||| 306 | ||| ParseIFF() 307 | ||| 308 | **/ 309 | 310 | /** 311 | ||| AUTODOC -class IFF -name AllocContextInfo 312 | ||| Allocates and initializes a ContextInfo structure. 313 | ||| 314 | ||| Synopsis 315 | ||| 316 | ||| ContextInfo *AllocContextInfo(PackedID type, PackedID id, 317 | ||| PackedID ident, uint32 dataSize, 318 | ||| IFFCallBack cb); 319 | ||| 320 | ||| Description 321 | ||| 322 | ||| Allocates and initializes a ContextInfo structure with a specified 323 | ||| number of bytes of user data. The returned structure contains a 324 | ||| pointer to the user data buffer in the ci_Data field. The buffer 325 | ||| is automatically cleared to 0 upon allocation. 326 | ||| 327 | ||| The optional callback function argument sets a client-supplied 328 | ||| cleanup routine for disposal when the context associated with the 329 | ||| new ContextInfo is popped. The purge routine will be called when the 330 | ||| ContextNode containing this structure is popped off the context stack 331 | ||| and is about to be deleted itself. 332 | ||| 333 | ||| The purge callback you supply is called with its second argument as 334 | ||| a pointer to the ContextInfo structure being purged. The purge 335 | ||| routine is responsible for calling FreeContextInfo() on this 336 | ||| ContextInfo when it is done with it. 337 | ||| 338 | ||| Arguments 339 | ||| 340 | ||| type 341 | ||| ID of container (eg: AIFF) 342 | ||| 343 | ||| id 344 | ||| ID of context that will contain this node. 345 | ||| 346 | ||| ident 347 | ||| Identifier that represents the type of information this node 348 | ||| describes. This value is later used when searching through 349 | ||| the list of ContextInfo structures to find a particular node. 350 | ||| 351 | ||| dataSize 352 | ||| The number of bytes of data to allocate for user use. The 353 | ||| data area allocated can be found by looking at the ci_Data 354 | ||| field of the returned ContextInfo structure. 355 | ||| 356 | ||| cb 357 | ||| The routine to be called when the ContextInfo structure needs 358 | ||| to be purged. If this is NULL, the folio will simply call 359 | ||| FreeContextInfo() automatically. 360 | ||| 361 | ||| Return Value 362 | ||| 363 | ||| Returns a pointer to a new ContextInfo structure or NULL if 364 | ||| there was not enough memory. 365 | ||| 366 | ||| Associated Files 367 | ||| 368 | ||| , System.m2/Modules/iff 369 | ||| 370 | ||| See Also 371 | ||| 372 | ||| FreeContextInfo(), StoreContextInfo(), AttachContextInfo(), 373 | ||| RemoveContextInfo(), FindContextInfo() 374 | ||| 375 | **/ 376 | 377 | /** 378 | ||| AUTODOC -class IFF -name CreateIFFParser 379 | ||| Creates a new parser structure and prepares it for use. 380 | ||| 381 | ||| Synopsis 382 | ||| 383 | ||| Err CreateIFFParser(IFFParser **iff, bool writeMode, 384 | ||| const TagArg tags[]); 385 | ||| 386 | ||| Err CreateIFFParserVA(IFFParser **iff, bool writeMode, 387 | ||| uint32 tag, ...); 388 | ||| 389 | ||| Description 390 | ||| 391 | ||| This function allocates and initializes a new IFFParser structure. 392 | ||| Once created, you can use the structure to parse IFF streams 393 | ||| and get at the data in them. The streams can currently either 394 | ||| be files or a block of memory. 395 | ||| 396 | ||| Arguments 397 | ||| 398 | ||| iff 399 | ||| A pointer to a variable where a handle to the IFFParser will 400 | ||| be stored. The value is set to NULL if the parser can't be 401 | ||| created. 402 | ||| 403 | ||| writeMode 404 | ||| Specifies how the stream should be opened. TRUE means the 405 | ||| file will be written to, or FALSE if the stream is to be read. 406 | ||| 407 | ||| tags 408 | ||| A pointer to an array of tag arguments containing extra data 409 | ||| for this function. See below for a description of the tags 410 | ||| supported. 411 | ||| 412 | ||| Tag Arguments 413 | ||| 414 | ||| The following tag arguments may be supplied in array form to this 415 | ||| function. The array must be terminated with TAG_END. 416 | ||| 417 | ||| IFF_TAG_FILE (const char *) 418 | ||| This tag lets you specify the name of a file to parse. This 419 | ||| file will be opened and prepared for use automatically. 420 | ||| If you supply this tag, you may not supply the IFF_TAG_IOFUNCS 421 | ||| tag at the same time. 422 | ||| 423 | ||| IFF_TAG_IOFUNCS (IFFIOFuncs *) 424 | ||| This tag is used in conjunction with the IFF_TAG_IOFUNCS_DATA 425 | ||| tag and lets you provide custom I/O functions that are used 426 | ||| as callbacks by the folio to read and write data. This lets 427 | ||| you do things like parse an in-memory IFF image, or parse a 428 | ||| data stream coming from some place other than a file. If you 429 | ||| supply this tag, you may not supply the IFF_TAG_FILE 430 | ||| tag at the same time. You supply a pointer to a fully 431 | ||| initialized IFFIOFuncs structure, which contains function 432 | ||| pointers that the folio can use to perform I/O operations. 433 | ||| 434 | ||| IFF_TAG_IOFUNCS_DATA (void *) 435 | ||| This tag works in conjunction with the IFF_TAG_IOFUNCS tag 436 | ||| and lets you specify the parameter that is passed as the 437 | ||| openKey parameter to the IFFOpenFunc callback function. 438 | ||| 439 | ||| Return Value 440 | ||| 441 | ||| Returns >= 0 for success, or a negative error code if the 442 | ||| parser could not be created. Possible error codes currently 443 | ||| include: 444 | ||| 445 | ||| IFF_ERR_NOOPENTYPE 446 | ||| You didn't supply one of the IFF_TAG_FILE or IFF_TAG_IOFUNCS 447 | ||| tags. One of these two tags must be supplied in order to tell 448 | ||| the parser what data to parse. 449 | ||| 450 | ||| IFF_ERR_NOMEM 451 | ||| There was not enough memory. 452 | ||| 453 | ||| Implementation 454 | ||| 455 | ||| Folio call implemented in IFF folio V27. 456 | ||| 457 | ||| Associated Files 458 | ||| 459 | ||| , System.m2/Modules/iff 460 | ||| 461 | ||| See Also 462 | ||| 463 | ||| DeleteIFFParser(), ParseIFF() 464 | ||| 465 | **/ 466 | 467 | /** 468 | ||| AUTODOC -class IFF -name DeleteIFFParser 469 | ||| Deletes an IFF parser. 470 | ||| 471 | ||| Synopsis 472 | ||| 473 | ||| Err DeleteIFFParser(IFFParser *iff); 474 | ||| 475 | ||| Description 476 | ||| 477 | ||| Deletes an IFF parser previously created by CreateIFFParser(). 478 | ||| Any data left to be output is sent out, files are closed, and 479 | ||| all resources are released. 480 | ||| 481 | ||| Arguments 482 | ||| 483 | ||| iff 484 | ||| An active parser, as obtained from CreateIFFParser(). Once 485 | ||| this call is made, the parser handle becomes invalid and can 486 | ||| no longer be used. This value may be NULL, in which case this 487 | ||| function does nothing. 488 | ||| 489 | ||| Return Value 490 | ||| 491 | ||| Returns >= 0 if successful, or a negative error code if it fails. 492 | ||| Possible error codes currently include: 493 | ||| 494 | ||| IFF_ERR_BADPTR 495 | ||| An invalid parser handle was supplied. 496 | ||| 497 | ||| Implementation 498 | ||| 499 | ||| Folio call implemented in IFF folio V27. 500 | ||| 501 | ||| Associated Files 502 | ||| 503 | ||| , System.m2/Modules/iff 504 | ||| 505 | ||| See Also 506 | ||| 507 | ||| CreateIFFParser(), ParseIFF() 508 | ||| 509 | **/ 510 | 511 | /** 512 | ||| AUTODOC -class IFF -name FindCollection 513 | ||| Gets a pointer to the current list of collection chunks. 514 | ||| 515 | ||| Synopsis 516 | ||| 517 | ||| CollectionChunk *FindCollection(const IFFParser *iff, 518 | ||| PackedID type, PackedID id); 519 | ||| 520 | ||| Description 521 | ||| 522 | ||| This function returns a pointer to a list of CollectionChunk 523 | ||| structures for each of the collection chunks of the given type 524 | ||| encountered so far in the course of the parse operation. The 525 | ||| structures appearing first in the list will be the ones encountered 526 | ||| most recently. 527 | ||| 528 | ||| Arguments 529 | ||| 530 | ||| iff 531 | ||| The parsing handle to query. 532 | ||| 533 | ||| type 534 | ||| Chunk type to search for. 535 | ||| 536 | ||| id 537 | ||| Chunk id to search for. 538 | ||| 539 | ||| Return Value 540 | ||| 541 | ||| A pointer to the last CollectionChunk structure describing the 542 | ||| last collection chunk encountered. The structure contains a 543 | ||| pointer that goes back through all the collection chunks 544 | ||| encountered during the parse operation. This function returns 545 | ||| NULL if no collection chunks have been encountered so far. 546 | ||| 547 | ||| Implementation 548 | ||| 549 | ||| Folio call implemented in IFF folio V27. 550 | ||| 551 | ||| Associated Files 552 | ||| 553 | ||| , System.m2/Modules/iff 554 | ||| 555 | ||| See Also 556 | ||| 557 | ||| RegisterCollectionChunks() 558 | ||| 559 | **/ 560 | 561 | /** 562 | ||| AUTODOC -class IFF -name FindContextInfo 563 | ||| Returns a ContextInfo structure from the context stack. 564 | ||| 565 | ||| Synopsis 566 | ||| 567 | ||| ContextInfo *FindContextInfo(const IFFParser *iff, PackedID type, 568 | ||| PackedID id, PackedID ident); 569 | ||| 570 | ||| Description 571 | ||| 572 | ||| This functions searches through the context stack for a ContextInfo 573 | ||| structure with matching type, id, and ident values. The search 574 | ||| starts from the most current context backwards, so that the any 575 | ||| structure found will be the one with greatest precedence in the 576 | ||| context stack. The type, id, and ident values correspond to the 577 | ||| parameters supplied to AllocContextInfo() to create the structure. 578 | ||| 579 | ||| Arguments 580 | ||| 581 | ||| iff 582 | ||| The parse handle to search in. 583 | ||| 584 | ||| type 585 | ||| The type value to search for. 586 | ||| 587 | ||| id 588 | ||| The id value to search for. 589 | ||| 590 | ||| ident 591 | ||| The ident code to search for. 592 | ||| 593 | ||| Return Value 594 | ||| 595 | ||| Returns a pointer to a ContextInfo structure or NULL if no 596 | ||| matching structure was found. 597 | ||| 598 | ||| Implementation 599 | ||| 600 | ||| Folio call implemented in IFF folio V27. 601 | ||| 602 | ||| Associated Files 603 | ||| 604 | ||| , System.m2/Modules/iff 605 | ||| 606 | ||| See Also 607 | ||| 608 | ||| AllocContextInfo(), FreeContextInfo(), StoreContextInfo(), 609 | ||| AttachContextInfo(), RemoveContextInfo() 610 | ||| 611 | **/ 612 | 613 | /** 614 | ||| AUTODOC -class IFF -name FindPropChunk 615 | ||| Searches for a stored property chunk. 616 | ||| 617 | ||| Synopsis 618 | ||| 619 | ||| PropChunk *FindPropChunk(const IFFParser *iff, 620 | ||| PackedID type, PackedID id); 621 | ||| 622 | ||| Description 623 | ||| 624 | ||| This function searches for the stored property chunk which is valid 625 | ||| in the given context. Property chunks are automatically stored by 626 | ||| ParseIFF() when pre-declared by RegisterPropChunks(). The pc_Data 627 | ||| field of the PropChunk structure contains a pointer to the data 628 | ||| associated with the property chunk. 629 | ||| 630 | ||| The data pointed to by pc_Data is fully writable by your 631 | ||| task. It can sometimes be handy to write directly to this 632 | ||| area instead of making a local copy. 633 | ||| 634 | ||| Arguments 635 | ||| 636 | ||| iff 637 | ||| The parser handler to search in. 638 | ||| 639 | ||| type 640 | ||| The type code of the property chunk to search for. 641 | ||| 642 | ||| id 643 | ||| The id code of the property chunk to search for. 644 | ||| 645 | ||| Return Value 646 | ||| 647 | ||| Returns a pointer to a PropChunk structure that describes the 648 | ||| sought property, or NULL if no such property chunk has been 649 | ||| encountered so far. 650 | ||| 651 | ||| Implementation 652 | ||| 653 | ||| Folio call implemented in IFF folio V27. 654 | ||| 655 | ||| Associated Files 656 | ||| 657 | ||| , System.m2/Modules/iff 658 | ||| 659 | ||| See Also 660 | ||| 661 | ||| RegisterPropChunks() 662 | ||| 663 | **/ 664 | 665 | /** 666 | ||| AUTODOC -class IFF -name FindPropContext 667 | ||| Gets the parser's current property context. 668 | ||| 669 | ||| Synopsis 670 | ||| 671 | ||| ContextNode *FindPropContext(const IFFParser *iff); 672 | ||| 673 | ||| Description 674 | ||| 675 | ||| This function locates the context node which would be the 676 | ||| scoping chunk for properties in the current parsing state. This is 677 | ||| used for locating the proper scoping context for property chunks 678 | ||| (i.e. the scope from which a property would apply). This is usually 679 | ||| the FORM or LIST with the highest precedence in the context stack. 680 | ||| 681 | ||| Arguments 682 | ||| 683 | ||| iff 684 | ||| The parsing handle to search in. 685 | ||| 686 | ||| Return Value 687 | ||| 688 | ||| Returns a pointer to a ContextNode or NULL if not found. 689 | ||| 690 | ||| Implementation 691 | ||| 692 | ||| Folio call implemented in IFF folio V27. 693 | ||| 694 | ||| Associated Files 695 | ||| 696 | ||| , System.m2/Modules/iff 697 | ||| 698 | ||| See Also 699 | ||| 700 | ||| GetCurrentContext(), GetParentContext() 701 | ||| 702 | **/ 703 | 704 | /** 705 | ||| AUTODOC -class IFF -name FreeContextInfo 706 | ||| Deallocate a ContextInfo structure. 707 | ||| 708 | ||| Synopsis 709 | ||| 710 | ||| void FreeContextInfo(ContextInfo *ci); 711 | ||| 712 | ||| Description 713 | ||| 714 | ||| This function frees the memory for the ContextInfo structure and 715 | ||| any associated user memory as allocated with AllocContextInfo(). 716 | ||| User purge vectors should call this function after they have freed 717 | ||| any other resources associated with this structure. 718 | ||| 719 | ||| Note that this function does NOT call the custom purge vector 720 | ||| optionally installed through AllocContextInfo(); all it does is 721 | ||| free the structure. 722 | ||| 723 | ||| Arguments 724 | ||| 725 | ||| ci 726 | ||| The ContextInfo structure to free. This may be NULL in which 727 | ||| case this function does nothing. 728 | ||| 729 | ||| Implementation 730 | ||| 731 | ||| Folio call implemented in IFF folio V27. 732 | ||| 733 | ||| Associated Files 734 | ||| 735 | ||| , System.m2/Modules/iff 736 | ||| 737 | ||| See Also 738 | ||| 739 | ||| AllocContextInfo() 740 | ||| 741 | **/ 742 | 743 | /** 744 | ||| AUTODOC -class IFF -name GetCurrentContext 745 | ||| Gets a pointer to the ContextNode for the current chunk. 746 | ||| 747 | ||| Synopsis 748 | ||| 749 | ||| ContextNode *GetCurrentContext(const IFFParser *iff); 750 | ||| 751 | ||| Description 752 | ||| 753 | ||| Returns the top ContextNode for the given parser handle. The top 754 | ||| ContextNode corresponds to the chunk most recently pushed on the 755 | ||| context stack, which is the chunk where the stream is currently 756 | ||| positioned. 757 | ||| 758 | ||| The ContextNode structure contains information on the type of chunk 759 | ||| currently being processed, like its size and the current 760 | ||| position within the chunk. 761 | ||| 762 | ||| Arguments 763 | ||| 764 | ||| iff 765 | ||| The parser handle to query. 766 | ||| 767 | ||| Return Value 768 | ||| 769 | ||| Returns a pointer to the current ContextNode for the parser. 770 | ||| 771 | ||| Implementation 772 | ||| 773 | ||| Folio call implemented in IFF folio V27. 774 | ||| 775 | ||| Associated Files 776 | ||| 777 | ||| , System.m2/Modules/iff 778 | ||| 779 | ||| See Also 780 | ||| 781 | ||| PushChunk(), PopChunk(), ParseIFF(), GetParentContext() 782 | ||| 783 | **/ 784 | 785 | /** 786 | ||| AUTODOC -class IFF -name GetParentContext 787 | ||| Gets the nesting ContextNode for the given ContextNode. 788 | ||| 789 | ||| Synopsis 790 | ||| 791 | ||| ContextNode *GetParentContext(ContextNode *cn); 792 | ||| 793 | ||| Description 794 | ||| 795 | ||| This function returns a ContextNode for the chunk containing the 796 | ||| chunk associated with the supplied ContextNode. This function 797 | ||| effectively moves down the context stack into previously pushed 798 | ||| contexts. 799 | ||| 800 | ||| Arguments 801 | ||| 802 | ||| cn 803 | ||| The ContextNode to obtain the parent of. 804 | ||| 805 | ||| Return Value 806 | ||| 807 | ||| Returns the parent of the supplied context or NULL if the supplied 808 | ||| context has no parent. 809 | ||| 810 | ||| Implementation 811 | ||| 812 | ||| Folio call implemented in IFF folio V27. 813 | ||| 814 | ||| Associated Files 815 | ||| 816 | ||| , System.m2/Modules/iff 817 | ||| 818 | ||| See Also 819 | ||| 820 | ||| GetCurrentContext(), FindPropContext() 821 | ||| 822 | **/ 823 | 824 | /** 825 | ||| AUTODOC -class IFF -name ParseIFF 826 | ||| Parses an IFF stream. 827 | ||| 828 | ||| Synopsis 829 | ||| 830 | ||| Err ParseIFF(IFFParser *iff, ParseIFFModes control); 831 | ||| 832 | ||| Description 833 | ||| 834 | ||| This function traverses a stream opened for read by pushing chunks 835 | ||| onto the context stack and popping them off directed by the generic 836 | ||| syntax of IFF files. As it pushes each new chunk, it searches the 837 | ||| context stack for handlers to apply to chunks of that type. If it 838 | ||| finds an entry handler it will invoke it just after entering the 839 | ||| chunk. If it finds an exit handler it will invoke it just before 840 | ||| leaving the chunk. Standard handlers include entry handlers for 841 | ||| pre-declared property chunks and collection chunks and entry and 842 | ||| exit handlers for stop chunks - that is, chunks which will cause 843 | ||| the ParseIFF() function to return control to the client. Client 844 | ||| programs can also provide their own custom handlers. 845 | ||| 846 | ||| The control argument can have one of three values: 847 | ||| 848 | ||| IFF_PARSE_SCAN 849 | ||| In this normal mode, ParseIFF() will only return control to 850 | ||| the caller when either: 851 | ||| 852 | ||| 1) an error is encountered, or 853 | ||| 854 | ||| 2) a stop chunk is encountered, or 855 | ||| 856 | ||| 3) a user handler returns a value other than 1, or 857 | ||| 858 | ||| 3) the end of the logical file is reached, in which 859 | ||| case IFF_PARSE_EOF is returned. 860 | ||| 861 | ||| ParseIFF() will continue pushing and popping chunks until one 862 | ||| of these conditions occurs. If ParseIFF() is called again 863 | ||| after returning, it will continue to parse the file where it 864 | ||| left off. 865 | ||| 866 | ||| IFF_PARSE_STEP and IFF_PARSE_RAWSTEP 867 | ||| In these two modes, ParseIFF() will return control to the 868 | ||| caller after every step in the parse, specifically, after 869 | ||| each push of a context node and just before each pop. If 870 | ||| returning just before a pop, ParseIFF() will return 871 | ||| IFF_PARSE_EOC, which is not an error, per se, but is just an 872 | ||| indication that the most recent context is ending. In STEP 873 | ||| mode, ParseIFF() will invoke the handlers for chunks, if 874 | ||| any, before returning. In RAWSTEP mode, ParseIFF() will not 875 | ||| invoke any handlers and will return right away. In both 876 | ||| cases the function can be called multiple times to step 877 | ||| through the parsing of the IFF file. 878 | ||| 879 | ||| Arguments 880 | ||| 881 | ||| iff 882 | ||| The parsing handle to affect. 883 | ||| 884 | ||| control 885 | ||| Instructs how to parse. 886 | ||| 887 | ||| Return Value 888 | ||| 889 | ||| Returns >= 0 for success, or a negative error code for failure. 890 | ||| 891 | ||| Implementation 892 | ||| 893 | ||| Folio call implemented in IFF folio V27. 894 | ||| 895 | ||| Associated Files 896 | ||| 897 | ||| , System.m2/Modules/iff 898 | ||| 899 | ||| See Also 900 | ||| 901 | ||| PushChunk(), PopChunk(), InstallEntryHandler(), InstallExitHandler(), 902 | ||| RegisterPropChunks(), RegisterCollectionChunks(), RegisterStopChunks() 903 | ||| 904 | **/ 905 | 906 | /** 907 | ||| AUTODOC -class IFF -name PopChunk 908 | ||| Pops the top context node off the context stack. 909 | ||| 910 | ||| Synopsis 911 | ||| 912 | ||| Err PopChunk(IFFParser *iff); 913 | ||| 914 | ||| Description 915 | ||| 916 | ||| This function pops the top context chunk and frees all associated 917 | ||| ContextInfo structures. The function is normally only called when 918 | ||| writing files and signals the end of a chunk. 919 | ||| 920 | ||| Arguments 921 | ||| 922 | ||| iff 923 | ||| The parsing handle to affect. 924 | ||| 925 | ||| Return Value 926 | ||| 927 | ||| Returns >= 0 for success, or a negative error code for failure. 928 | ||| 929 | ||| Associated Files 930 | ||| 931 | ||| , System.m2/Modules/iff 932 | ||| 933 | ||| See Also 934 | ||| 935 | ||| PushChunk() 936 | ||| 937 | **/ 938 | 939 | /** 940 | ||| AUTODOC -class IFF -name PushChunk 941 | ||| Pushes a new context node on the context stack. 942 | ||| 943 | ||| Synopsis 944 | ||| 945 | ||| Err PushChunk(IFFParser *iff, PackedID type, PackedID id, 946 | ||| uint32 size); 947 | ||| 948 | ||| Description 949 | ||| 950 | ||| This functio pushes a new context node on the context stack by 951 | ||| reading it from the stream if this is a read stream, or by creating 952 | ||| it from the passed parameters if this is a write stream. Normally 953 | ||| this function is only called in write mode, where the type and id 954 | ||| codes specify the new chunk to create. If this is a leaf chunk 955 | ||| (i.e. a local chunk inside a FORM or PROP chunk), then the type 956 | ||| argument is ignored. 957 | ||| 958 | ||| If the size is specified then the chunk writing functions will 959 | ||| enforce this size. If the size is given as IFF_SIZE_UNKNOWN_32, the 960 | ||| chunk will expand to accommodate whatever is written into it up to 961 | ||| a maximum of (IFF_SIZE_RESERVED-1) bytes. If the size is given 962 | ||| as IFF_SIZE_UNKNOWN_64, then you can write as much data as there 963 | ||| are atoms in the universe. 964 | ||| 965 | ||| Arguments 966 | ||| 967 | ||| iff 968 | ||| The parsing handle to affect. 969 | ||| 970 | ||| type 971 | ||| The ID of the container (eg: AIFF). This is ignored in read mode, 972 | ||| and for leaf chunks. 973 | ||| 974 | ||| id 975 | ||| The chunk id speciiier. This is ignored in read mode. 976 | ||| 977 | ||| size 978 | ||| The size of the chunk to create, or IFF_SIZE_UNKNOWN_32 979 | ||| or IFF_SIZE_UNKNOWN_64. This parameter is ignored in read mode. 980 | ||| 981 | ||| Return Value 982 | ||| 983 | ||| Returns >= 0 for success, or a negative error code for failure. 984 | ||| 985 | ||| Implementation 986 | ||| 987 | ||| Folio call implemented in IFF folio V27. 988 | ||| 989 | ||| Associated Files 990 | ||| 991 | ||| , System.m2/Modules/iff 992 | ||| 993 | ||| See Also 994 | ||| 995 | ||| PopChunk(), WriteChunk() 996 | ||| 997 | **/ 998 | 999 | /** 1000 | ||| AUTODOC -class IFF -name ReadChunk 1001 | ||| Reads bytes from the current chunk into a buffer. 1002 | ||| 1003 | ||| Synopsis 1004 | ||| 1005 | ||| int32 ReadChunk(IFFParser *iff, void *buffer, uint32 numBytes); 1006 | ||| 1007 | ||| Description 1008 | ||| 1009 | ||| This function reads data from the IFF stream into the buffer for 1010 | ||| the specified number of bytes. Reads are limited to the size of the 1011 | ||| current chunk and attempts to read past the end of the chunk will 1012 | ||| truncate. 1013 | ||| 1014 | ||| Arguments 1015 | ||| 1016 | ||| iff 1017 | ||| The parsing handle to read from. 1018 | ||| 1019 | ||| buffer 1020 | ||| A pointer to where the read data should be put. 1021 | ||| 1022 | ||| numBytes 1023 | ||| The number of bytes of data to read. 1024 | ||| 1025 | ||| Return Value 1026 | ||| 1027 | ||| Returns the actual number of bytes read, or a negative error code 1028 | ||| for failure. 1029 | ||| 1030 | ||| Implementation 1031 | ||| 1032 | ||| Folio call implemented in IFF folio V27. 1033 | ||| 1034 | ||| Associated Files 1035 | ||| 1036 | ||| , System.m2/Modules/iff 1037 | ||| 1038 | ||| See Also 1039 | ||| 1040 | ||| ParseIFF(), SeekChunk(), WriteChunk() 1041 | ||| 1042 | **/ 1043 | 1044 | /** 1045 | ||| AUTODOC -disabled -class IFF -name ReadChunkCompressed 1046 | ||| Reads and decompresses bytes from the current chunk into a buffer. 1047 | ||| 1048 | ||| Synopsis 1049 | ||| 1050 | ||| int32 ReadChunkCompressed(IFFParser *iff, void *buffer, 1051 | ||| uint32 numBytes); 1052 | ||| 1053 | ||| Description 1054 | ||| 1055 | ||| This function reads data from the IFF stream into the buffer for 1056 | ||| the specified number of bytes. Reads are limited to the size of the 1057 | ||| current chunk and attempts to read past the end of the chunk will 1058 | ||| truncate. As the data is read, it is automatically decompressed 1059 | ||| using the compression folio. 1060 | ||| 1061 | ||| Arguments 1062 | ||| 1063 | ||| iff 1064 | ||| The parsing handle to read from. 1065 | ||| 1066 | ||| buffer 1067 | ||| A pointer to where the read data should be put. 1068 | ||| 1069 | ||| numBytes 1070 | ||| The number of bytes of data to read. 1071 | ||| 1072 | ||| Return Value 1073 | ||| 1074 | ||| Returns the actual number of bytes read, or a negative error code 1075 | ||| for failure. 1076 | ||| 1077 | ||| Implementation 1078 | ||| 1079 | ||| Folio call implemented in IFF folio V27. 1080 | ||| 1081 | ||| Associated Files 1082 | ||| 1083 | ||| , System.m2/Modules/iff 1084 | ||| 1085 | ||| See Also 1086 | ||| 1087 | ||| ParseIFF(), ReadChunk(), SeekChunk(), WriteChunk(), 1088 | ||| WriteChunkCompressed() 1089 | ||| 1090 | **/ 1091 | 1092 | /** 1093 | ||| AUTODOC -class IFF -name SeekChunk 1094 | ||| Moves the current position cursor within the current chunk. 1095 | ||| 1096 | ||| Synopsis 1097 | ||| 1098 | ||| Err SeekChunk(IFFParser *iff, int32 position, IFFSeekModes mode); 1099 | ||| 1100 | ||| Description 1101 | ||| 1102 | ||| This function moves the position cursor within the current chunk. 1103 | ||| The cursor determines where the next read operation will get its 1104 | ||| data from, and where the next write operation will write its data 1105 | ||| to. 1106 | ||| 1107 | ||| The cursor can be moved to a position which is relative to the 1108 | ||| start or end of the current chunk, as well as relative to the 1109 | ||| current position. The cursor is never allowed to be less than 0 or 1110 | ||| greater than the number of bytes currently in the chunk. Any attempt 1111 | ||| to do so results in the cursor being positioned to the beginning or 1112 | ||| end of the chunk, depending on which limit was exceeded. This does 1113 | ||| not result in an error. 1114 | ||| 1115 | ||| Arguments 1116 | ||| 1117 | ||| iff 1118 | ||| The parsing handle to seek in. 1119 | ||| 1120 | ||| position 1121 | ||| The position to move the cursor to. 1122 | ||| 1123 | ||| mode 1124 | ||| Describes what the position argument is relative to. 1125 | ||| 1126 | ||| The possible seek modes are: 1127 | ||| 1128 | ||| IFF_SEEK_START 1129 | ||| Indicates that the supplied position is relative to the 1130 | ||| beginning of the chunk. So a position of 10 would put the 1131 | ||| cursor at byte #10 (the eleventh byte) within the chunk. 1132 | ||| 1133 | ||| IFF_SEEK_CURRENT 1134 | ||| Indicates that the supplied position is relative to the current 1135 | ||| position within the chunk. A positive position value moves the 1136 | ||| cursor forward in the file by that many bytes, while a negative 1137 | ||| value moves the cursor back by that number of bytes. 1138 | ||| 1139 | ||| IFF_SEEK_END 1140 | ||| Indicates that the supplied position is relative to the end 1141 | ||| of the chunk. The position value should be a negative value. 1142 | ||| 1143 | ||| Return Value 1144 | ||| 1145 | ||| Returns >= 0 for success, or a negative error code for failure. 1146 | ||| 1147 | ||| Caveat 1148 | ||| 1149 | ||| It is not currently possible to seek more than 2^31 bytes in one 1150 | ||| shot. 1151 | ||| 1152 | ||| Implementation 1153 | ||| 1154 | ||| Folio call implemented in IFF folio V27. 1155 | ||| 1156 | ||| Associated Files 1157 | ||| 1158 | ||| , System.m2/Modules/iff 1159 | ||| 1160 | ||| See Also 1161 | ||| 1162 | ||| ReadChunk(), WriteChunk() 1163 | ||| 1164 | **/ 1165 | 1166 | /** 1167 | ||| AUTODOC -class IFF -name GetIFFOffset 1168 | ||| Returns the absolute seek position within the current IFF stream. 1169 | ||| 1170 | ||| Synopsis 1171 | ||| 1172 | ||| int64 GetIFFOffset(IFFParser *iff); 1173 | ||| 1174 | ||| Description 1175 | ||| 1176 | ||| This function returns the count of bytes from the beginning of the 1177 | ||| current IFF stream. This is useful to identify the exact position 1178 | ||| of a chunk or part of a chunk within an IFF file. 1179 | ||| 1180 | ||| Arguments 1181 | ||| 1182 | ||| iff 1183 | ||| The parsing handle to query. 1184 | ||| 1185 | ||| Return Value 1186 | ||| 1187 | ||| Returns the absolute seek offset from the beginning of the 1188 | ||| IFF stream to the current file cursor position, or a negative 1189 | ||| error code for failure. 1190 | ||| 1191 | ||| Implementation 1192 | ||| 1193 | ||| Folio call implemented in IFF folio V27. 1194 | ||| 1195 | ||| Associated Files 1196 | ||| 1197 | ||| , System.m2/Modules/iff 1198 | ||| 1199 | **/ 1200 | 1201 | /** 1202 | ||| AUTODOC -class IFF -name AttachContextInfo 1203 | ||| Attaches a ContextInfo structure to a given ContextNode. 1204 | ||| 1205 | ||| Synopsis 1206 | ||| 1207 | ||| void AttachContextInfo(IFFParser *iff, ContextNode *to, 1208 | ||| ContextInfo *ci); 1209 | ||| 1210 | ||| Description 1211 | ||| 1212 | ||| This function adds the ContextInfo structure to the supplied 1213 | ||| ContextNode structure. If another ContextInfo of the same type, id 1214 | ||| and ident codes is already present in the ContextNode, it will be 1215 | ||| purged and replaced with this new structure. 1216 | ||| 1217 | ||| Arguments 1218 | ||| 1219 | ||| iff 1220 | ||| The parsing handle to affect. 1221 | ||| 1222 | ||| to 1223 | ||| The ContextNode to attach the ContextInfo structure to. 1224 | ||| 1225 | ||| ci 1226 | ||| The ContextInfo structure to attach. 1227 | ||| 1228 | ||| Implementation 1229 | ||| 1230 | ||| Folio call implemented in IFF folio V27. 1231 | ||| 1232 | ||| Associated Files 1233 | ||| 1234 | ||| , System.m2/Modules/iff 1235 | ||| 1236 | ||| See Also 1237 | ||| 1238 | ||| StoreContextInfo(), RemoveContextInfo(), AllocContextInfo(), 1239 | ||| FreeContextInfo(), FindContextInfo() 1240 | ||| 1241 | **/ 1242 | 1243 | /** 1244 | ||| AUTODOC -class IFF -name RemoveContextInfo 1245 | ||| Removes a ContextInfo structure from wherever it is attached. 1246 | ||| 1247 | ||| Synopsis 1248 | ||| 1249 | ||| void RemoveContextInfo(ContextInfo *ci); 1250 | ||| 1251 | ||| Description 1252 | ||| 1253 | ||| This function removes the ContextInfo structure from any list it 1254 | ||| might currently be in. If the structure is not currently in a list, 1255 | ||| this function is a NOP. 1256 | ||| 1257 | ||| Arguments 1258 | ||| 1259 | ||| ci 1260 | ||| The ContextInfo structure to remove. 1261 | ||| 1262 | ||| Implementation 1263 | ||| 1264 | ||| Folio call implemented in IFF folio V28. 1265 | ||| 1266 | ||| Associated Files 1267 | ||| 1268 | ||| , System.m2/Modules/iff 1269 | ||| 1270 | ||| See Also 1271 | ||| 1272 | ||| AttachContextInfo(), StoreContextInfo(), AllocContextInfo(), 1273 | ||| FreeContextInfo(), FindContextInfo() 1274 | ||| 1275 | **/ 1276 | 1277 | /** 1278 | ||| AUTODOC -class IFF -name StoreContextInfo 1279 | ||| Inserts a ContextInfo structure into the context stack. 1280 | ||| 1281 | ||| Synopsis 1282 | ||| 1283 | ||| Err StoreContextInfo(IFFParser *iff, ContextInfo *ci, 1284 | ||| ContextInfoLocation pos); 1285 | ||| 1286 | ||| Description 1287 | ||| 1288 | ||| This function adds the ContextInfo structure to the list of 1289 | ||| structures for one of the ContextNodes on the context stack and 1290 | ||| purges any other structure in the same context with the same type, 1291 | ||| id and ident codes. The pos argument determines where in the stack 1292 | ||| to add the structure: 1293 | ||| 1294 | ||| IFF_CIL_BOTTOM 1295 | ||| Add the structure to the ContextNode at the bottom of the stack. 1296 | ||| 1297 | ||| IFF_CIL_TOP 1298 | ||| Add the structure to the top (current) context node. 1299 | ||| 1300 | ||| IFF_CIL_PROP 1301 | ||| Add the structure in the top property context. The top 1302 | ||| property context is either the top FORM chunk, or the top LIST 1303 | ||| chunk, whichever is closer to the top of the stack. 1304 | ||| 1305 | ||| Arguments 1306 | ||| 1307 | ||| iff 1308 | ||| The parsing stream to affect. 1309 | ||| 1310 | ||| ci 1311 | ||| The ContextInfo structure to add. 1312 | ||| 1313 | ||| pos 1314 | ||| The position where the structure should be added. 1315 | ||| 1316 | ||| Return Value 1317 | ||| 1318 | ||| Returns >= 0 for success, or a negative error code for failure. 1319 | ||| 1320 | ||| Implementation 1321 | ||| 1322 | ||| Folio call implemented in IFF folio V27. 1323 | ||| 1324 | ||| Associated Files 1325 | ||| 1326 | ||| , System.m2/Modules/iff 1327 | ||| 1328 | ||| See Also 1329 | ||| 1330 | ||| AllocContextInfo(), FreeContextInfo(), FindContextInfo(), 1331 | ||| AttachContextInfo(), RemoveContextInfo() 1332 | ||| 1333 | **/ 1334 | 1335 | /** 1336 | ||| AUTODOC -class IFF -name WriteChunk 1337 | ||| Writes data from a buffer into the current chunk. 1338 | ||| 1339 | ||| Synopsis 1340 | ||| 1341 | ||| int32 WriteChunk(IFFParser *iff, const void *buffer, 1342 | ||| uint32 numBytes); 1343 | ||| 1344 | ||| Description 1345 | ||| 1346 | ||| This function writes the requested number of bytes into the IFF 1347 | ||| stream. If the current chunk was pushed with IFF_SIZE_UNKNOWN_32 1348 | ||| or IFF_SIZE_UNKNOWN_64, the size of the chunk gets increased by the 1349 | ||| size of the buffer written. If the size was specified for this chunk, 1350 | ||| attempts to write past the end of the chunk will be truncated. 1351 | ||| 1352 | ||| Arguments 1353 | ||| 1354 | ||| iff 1355 | ||| The parsing handle to write to. 1356 | ||| 1357 | ||| buffer 1358 | ||| A pointer to the data to write to the stream. 1359 | ||| 1360 | ||| numBytes 1361 | ||| The number of bytes of data to write. 1362 | ||| 1363 | ||| Return Value 1364 | ||| 1365 | ||| Returns the number of bytes written, or a negative error code for 1366 | ||| failure. 1367 | ||| 1368 | ||| Implementation 1369 | ||| 1370 | ||| Folio call implemented in IFF folio V27. 1371 | ||| 1372 | ||| Associated Files 1373 | ||| 1374 | ||| , System.m2/Modules/iff 1375 | ||| 1376 | ||| See Also 1377 | ||| 1378 | ||| PushChunk(), PopChunk(), ReadChunk() 1379 | ||| 1380 | **/ 1381 | 1382 | /** 1383 | ||| AUTODOC -disabled -class IFF -name WriteChunkCompressed 1384 | ||| Compresses data from a buffer and writes the result to the current 1385 | ||| chunk. 1386 | ||| 1387 | ||| Synopsis 1388 | ||| 1389 | ||| int32 WriteChunkCompressed(IFFParser *iff, const void *buffer, 1390 | ||| uint32 numBytes); 1391 | ||| 1392 | ||| Description 1393 | ||| 1394 | ||| This function writes the requested number of bytes into the IFF 1395 | ||| stream. If the current chunk was pushed with IFF_SIZE_UNKNOWN_32 1396 | ||| or IFF_SIZE_UNKNOWN_64, the size of the chunk gets increased by the 1397 | ||| size of the buffer written. If the size was specified for this chunk, 1398 | ||| attempts to write past the end of the chunk will be truncated. 1399 | ||| The data is first compressed using the compression folio before 1400 | ||| being written to the chunk. 1401 | ||| 1402 | ||| Arguments 1403 | ||| 1404 | ||| iff 1405 | ||| The parsing handle to write to. 1406 | ||| 1407 | ||| buffer 1408 | ||| A pointer to the data to write to the stream. 1409 | ||| 1410 | ||| numBytes 1411 | ||| The number of bytes of data to write. 1412 | ||| 1413 | ||| Return Value 1414 | ||| 1415 | ||| Returns the number of bytes written, or a negative error code for 1416 | ||| failure. 1417 | ||| 1418 | ||| Implementation 1419 | ||| 1420 | ||| Folio call implemented in IFF folio V27. 1421 | ||| 1422 | ||| Associated Files 1423 | ||| 1424 | ||| , System.m2/Modules/iff 1425 | ||| 1426 | ||| See Also 1427 | ||| 1428 | ||| PushChunk(), PopChunk(), ReadChunk(), ReadChunkCompressed(), 1429 | ||| SeekChunk(), WriteChunk() 1430 | ||| 1431 | **/ 1432 | 1433 | /* keep the compiler happy... */ 1434 | extern int foo; 1435 | -------------------------------------------------------------------------------- /IFF source code/createiffparserva.s: -------------------------------------------------------------------------------- 1 | /* @(#) createiffparserva.s 95/07/08 1.1 */ 2 | 3 | #include 4 | 5 | DECVASTUB_2 CreateIFFParser 6 | -------------------------------------------------------------------------------- /IFF source code/iff.c: -------------------------------------------------------------------------------- 1 | /* @(#) iff.c 96/04/29 1.21 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "io.h" 8 | 9 | 10 | /*****************************************************************************/ 11 | 12 | 13 | #ifdef NO_64_BIT_SCALARS 14 | #define int64 int32 15 | #define uint64 uint32 16 | #endif 17 | 18 | 19 | /*****************************************************************************/ 20 | 21 | 22 | #define IsIFFParser(iff) ((iff && (iff->iff_Cookie == iff)) ? TRUE : FALSE) 23 | #define IsGenericID(id) ((id) == ID_FORM || (id) == ID_CAT || (id) == ID_LIST || (id) == ID_PROP) 24 | #define IsContainerID(id) ((id & '\0\0\0{') == '\0\0\0{') 25 | #define ID_PAD MAKE_ID('!', 'P','A','D') 26 | 27 | 28 | /*****************************************************************************/ 29 | 30 | 31 | /* Data attached to a ContextInfo structure which contains a handler function 32 | * to be applied when a chunk is pushed/popped. 33 | */ 34 | typedef struct ChunkHandler 35 | { 36 | IFFCallBack ch_HandlerCB; 37 | const void *ch_UserData; 38 | } ChunkHandler; 39 | 40 | 41 | /*****************************************************************************/ 42 | 43 | 44 | /* Data attached to a ContextInfo structure which contains part of 45 | * the linked list of collection properties - the ones for this 46 | * context. Only the ones for this context get purged when this 47 | * item gets purged. First is the first element for this context 48 | * level, LastPtr is the value of the Next pointer for the last 49 | * element at this level. 50 | */ 51 | typedef struct CollectionList 52 | { 53 | CollectionChunk *cl_First; 54 | CollectionChunk *cl_LastPtr; 55 | ContextNode *cl_Context; 56 | } CollectionList; 57 | 58 | 59 | /*****************************************************************************/ 60 | 61 | 62 | typedef struct Chunk 63 | { 64 | PackedID ID; 65 | uint32 Filler; 66 | uint64 Size; 67 | } Chunk; 68 | 69 | typedef struct SmallChunk 70 | { 71 | PackedID ID; 72 | uint32 Size; 73 | } SmallChunk; 74 | 75 | 76 | /*****************************************************************************/ 77 | 78 | 79 | static int32 internalWriteChunk(IFFParser *iff, ContextNode *top, 80 | const void *buf, uint32 numBytes); 81 | 82 | 83 | /*****************************************************************************/ 84 | 85 | 86 | /* Characters in [0x20 - 0x7e], no leading spaces (except for ID_NULL) */ 87 | static bool GoodID(PackedID id) 88 | { 89 | char *ptr; 90 | uint32 i; 91 | 92 | ptr = (char *)&id; 93 | if (ptr[0] == ' ') 94 | { 95 | if (id == ID_NULL) 96 | return TRUE; 97 | 98 | /* No leading spaces, except for NULL identifier */ 99 | return FALSE; 100 | } 101 | 102 | for (i = 0; i < sizeof(id); i++) 103 | { 104 | if ((ptr[i] < ' ') || (ptr[i] > '~')) 105 | return FALSE; 106 | } 107 | 108 | return TRUE; 109 | } 110 | 111 | 112 | /*****************************************************************************/ 113 | 114 | 115 | /* No lower case or punctuation allowed */ 116 | static bool GoodType(PackedID type) 117 | { 118 | char *ptr; 119 | uint32 i; 120 | 121 | if (!GoodID(type)) 122 | return (FALSE); 123 | 124 | ptr = (char *)&type; 125 | for (i = 0; i < sizeof(type); i++) 126 | { 127 | if (((ptr[i] < 'A') || (ptr[i] > 'Z')) 128 | && ((ptr[i] < '0') || (ptr[i] > '9')) 129 | && (ptr[i] != ' ')) 130 | { 131 | return FALSE; 132 | } 133 | } 134 | 135 | return TRUE; 136 | } 137 | 138 | 139 | /*****************************************************************************/ 140 | 141 | 142 | /* Function reads id and size and pushes a new context for this chunk 143 | * on to the context stack, initializing byte count to zero. 144 | * Assumes that file is positioned at the start of a chunk. 145 | */ 146 | static Err PushChunkR(IFFParser *iff, bool firstChunk) 147 | { 148 | ContextNode *top, *cn; 149 | PackedID type; 150 | Err err; 151 | Chunk chunk; 152 | SmallChunk smallChunk; 153 | 154 | top = GetCurrentContext(iff); 155 | if (!top && !firstChunk) 156 | return IFF_PARSE_EOF; 157 | 158 | type = (top ? top->cn_Type : 0); 159 | 160 | if (firstChunk) 161 | { 162 | err = IFFRead(iff, &smallChunk, sizeof(smallChunk)); 163 | if (err != sizeof(smallChunk)) 164 | { 165 | if (err >= 0) 166 | err = IFF_ERR_NOTIFF; 167 | 168 | return err; 169 | } 170 | 171 | chunk.ID = smallChunk.ID; 172 | chunk.Size = smallChunk.Size; 173 | 174 | if (chunk.Size == IFF_SIZE_64BIT) 175 | { 176 | err = IFFRead(iff, &chunk.Size, sizeof(chunk.Size)); 177 | if (err != sizeof(chunk.Size)) 178 | { 179 | if (err >= 0) 180 | err = IFF_ERR_NOTIFF; 181 | 182 | return err; 183 | } 184 | } 185 | else if (chunk.Size >= IFF_SIZE_RESERVED) 186 | { 187 | return IFF_ERR_MANGLED; 188 | } 189 | } 190 | else 191 | { 192 | /* Using ReadChunk() causes these bytes to go into the 193 | * parent's scan count 194 | */ 195 | err = ReadChunk(iff, &smallChunk, sizeof(smallChunk)); 196 | if (err != sizeof(smallChunk)) 197 | { 198 | if (err >= 0) 199 | err = IFF_ERR_PREMATURE_EOF; 200 | 201 | return err; 202 | } 203 | 204 | chunk.ID = smallChunk.ID; 205 | chunk.Size = smallChunk.Size; 206 | 207 | if (chunk.Size == IFF_SIZE_64BIT) 208 | { 209 | err = ReadChunk(iff, &chunk.Size, sizeof(chunk.Size)); 210 | if (err != sizeof(chunk.Size)) 211 | { 212 | if (err >= 0) 213 | err = IFF_ERR_PREMATURE_EOF; 214 | 215 | return err; 216 | } 217 | } 218 | else if (chunk.Size >= IFF_SIZE_RESERVED) 219 | { 220 | return IFF_ERR_MANGLED; 221 | } 222 | 223 | if (chunk.Size > top->cn_Size - top->cn_Offset) 224 | return IFF_ERR_MANGLED; 225 | } 226 | 227 | if (GoodID(chunk.ID)) 228 | { 229 | if (cn = AllocMem(sizeof(ContextNode), MEMTYPE_ANY)) 230 | { 231 | cn->cn_Type = type; 232 | cn->cn_ID = chunk.ID; 233 | cn->cn_Size = chunk.Size; 234 | cn->cn_Offset = 0; 235 | cn->cn_CurrentSize = chunk.Size; 236 | PrepList(&cn->cn_ContextInfo); 237 | AddHead(&iff->iff_Stack, (Node *)cn); 238 | 239 | return 0; 240 | } 241 | return IFF_ERR_NOMEM; 242 | } 243 | 244 | if (iff->iff_NewIO) 245 | return IFF_ERR_NOTIFF; 246 | 247 | return IFF_ERR_SYNTAX; 248 | } 249 | 250 | 251 | /*****************************************************************************/ 252 | 253 | 254 | static Err PurgeContextInfo(IFFParser *iff, ContextInfo *ci) 255 | { 256 | IFFCallBack cb; 257 | 258 | if (cb = ci->ci_PurgeCB) 259 | return (* cb)(iff, ci); 260 | 261 | FreeContextInfo(ci); 262 | return 0; 263 | } 264 | 265 | 266 | /*****************************************************************************/ 267 | 268 | 269 | /* Free memory associated with a ContextNode, calling its optional free vector 270 | * for any ContextInfo structures it contains. 271 | */ 272 | static void FreeContextNode(IFFParser *iff, ContextNode *cn) 273 | { 274 | ContextInfo *ci; 275 | 276 | RemNode((Node *)cn); 277 | 278 | /* Dispose of all local context items for this context node. 279 | * error return value is ignored for now. 280 | */ 281 | while (ci = (ContextInfo *)RemHead(&cn->cn_ContextInfo)) 282 | { 283 | ci->ci.n_Next = NULL; 284 | PurgeContextInfo(iff, ci); 285 | } 286 | 287 | FreeMem(cn, sizeof(ContextNode)); 288 | } 289 | 290 | 291 | /*****************************************************************************/ 292 | 293 | 294 | /* Pops the top chunk off the stack and skips past any unread bytes in the 295 | * chunk. Updates the new top chunk with bytes read and purges local context. 296 | */ 297 | static Err PopChunkR(IFFParser *iff) 298 | { 299 | ContextNode *top; 300 | Err err; 301 | uint64 rsize; 302 | 303 | /* Get top chunk and seek past anything un-scanned including 304 | * the optional pad byte. 305 | */ 306 | if (!(top = GetCurrentContext(iff))) 307 | return IFF_PARSE_EOF; 308 | 309 | rsize = (top->cn_Size + 1) & ~1; 310 | 311 | if (top->cn_Offset < rsize) 312 | { 313 | err = IFFSeek(iff, rsize - top->cn_Offset); 314 | if (err < 0) 315 | return err; 316 | } 317 | 318 | /* Remove and deallocate this chunk and any stored properties */ 319 | FreeContextNode(iff, top); 320 | 321 | /* Update the new top chunk, if any. */ 322 | if (top = GetCurrentContext(iff)) 323 | top->cn_Offset += rsize; 324 | 325 | return 0; 326 | } 327 | 328 | 329 | /*****************************************************************************/ 330 | 331 | 332 | int32 ReadChunk(IFFParser *iff, void *buf, uint32 numBytes) 333 | { 334 | ContextNode *top; 335 | uint32 maxBytes; 336 | int32 result; 337 | 338 | if (!(top = GetCurrentContext(iff))) 339 | return IFF_PARSE_EOF; 340 | 341 | maxBytes = top->cn_Size - top->cn_Offset; 342 | 343 | if (numBytes > maxBytes) 344 | numBytes = maxBytes; 345 | 346 | result = IFFRead(iff, buf, numBytes); 347 | if (result != numBytes) 348 | { 349 | if (result >= 0) 350 | { 351 | /* less data in the file than the header says there is */ 352 | result = IFF_ERR_PREMATURE_EOF; 353 | } 354 | } 355 | else 356 | { 357 | top->cn_Offset += (uint32)result; 358 | } 359 | 360 | return result; 361 | } 362 | 363 | 364 | /*****************************************************************************/ 365 | 366 | 367 | int32 ReadChunkCompressed(IFFParser *iff, void *buf, uint32 numBytes) 368 | { 369 | TOUCH(iff); 370 | TOUCH(buf); 371 | TOUCH(numBytes); 372 | return IFF_ERR_NOTSUPPORTED; 373 | } 374 | 375 | 376 | /*****************************************************************************/ 377 | 378 | 379 | Err SeekChunk(IFFParser *iff, int32 position, IFFSeekModes mode) 380 | { 381 | ContextNode *top; 382 | uint64 base; 383 | uint64 newOffset; 384 | uint64 pos; 385 | 386 | if (!(top = GetCurrentContext(iff))) 387 | return IFF_PARSE_EOF; 388 | 389 | /* pick offset base depending on mode */ 390 | switch (mode) 391 | { 392 | case IFF_SEEK_START: base = 0; break; 393 | case IFF_SEEK_CURRENT: base = top->cn_Offset; break; 394 | case IFF_SEEK_END: base = top->cn_Size; break; 395 | default: return IFF_ERR_BADMODE; 396 | } 397 | 398 | /* Clip position in range of -base..cn_Size-base. Result in newOffset 399 | * is in range of 0..cn_Size 400 | */ 401 | if (position >= 0) 402 | { 403 | pos = position; 404 | if (pos < top->cn_Size - base) 405 | newOffset = base + pos; 406 | else 407 | newOffset = top->cn_Size; 408 | } 409 | else 410 | { 411 | pos = -position; 412 | if (pos < base) 413 | newOffset = base - pos; 414 | else 415 | newOffset = 0; 416 | } 417 | 418 | /* seek on stream */ 419 | { 420 | const int64 seekOffset = (int32)(newOffset - top->cn_Offset); 421 | int32 oldStreamPos, newStreamPos; 422 | 423 | /* seek relative to current file position, and see if we got there */ 424 | if ((oldStreamPos = IFFSeek(iff,seekOffset)) < 0) return oldStreamPos; 425 | if ((newStreamPos = IFFSeek(iff,0)) < 0) return newStreamPos; 426 | if (newStreamPos - oldStreamPos != seekOffset) return IFF_ERR_PREMATURE_EOF; 427 | } 428 | 429 | top->cn_Offset = newOffset; 430 | return 0; 431 | } 432 | 433 | 434 | /*****************************************************************************/ 435 | 436 | 437 | int64 GetIFFOffset(IFFParser *iff) 438 | { 439 | return (int64)IFFSeek(iff,0); 440 | } 441 | 442 | 443 | /*****************************************************************************/ 444 | 445 | 446 | /* Push a chunk onto the IFF context stack for write. 447 | * Type must be specified for generic chunks. 448 | */ 449 | static Err PushChunkW(IFFParser *iff, PackedID type, PackedID id, uint64 size) 450 | { 451 | ContextNode *cn; 452 | Err err; 453 | PackedID parentType; 454 | Chunk chunk; 455 | SmallChunk smallChunk; 456 | bool firstChunk; 457 | 458 | if (cn = GetCurrentContext(iff)) 459 | { 460 | parentType = cn->cn_Type; 461 | firstChunk = FALSE; 462 | } 463 | else if (iff->iff_NewIO) 464 | { 465 | parentType = 0; 466 | firstChunk = TRUE; 467 | iff->iff_NewIO = FALSE; 468 | 469 | /* first chunk must be FORM, CAT, or LIST */ 470 | if ((id != ID_FORM) && (id != ID_CAT) && (id != ID_LIST)) 471 | return IFF_ERR_NOTIFF; 472 | } 473 | else 474 | { 475 | return IFF_PARSE_EOF; 476 | } 477 | 478 | if (!GoodID(id)) 479 | return IFF_ERR_SYNTAX; 480 | 481 | if (IsGenericID(id)) 482 | { 483 | if (id == ID_PROP) 484 | { 485 | /* the containing context for PROP must be a LIST */ 486 | if (cn->cn_ID != ID_LIST) 487 | return IFF_ERR_SYNTAX; 488 | } 489 | 490 | /* Generic ID. Check the validity of its subtype. */ 491 | if (!GoodType(type)) 492 | return IFF_ERR_NOTIFF; 493 | } 494 | else 495 | { 496 | /* Non-generic ID. Containing context must be PROP or FORM or container */ 497 | if ((cn->cn_ID != ID_FORM) 498 | && (cn->cn_ID != ID_PROP) 499 | && (!IsContainerID(cn->cn_ID))) 500 | return IFF_ERR_SYNTAX; 501 | } 502 | 503 | /* Write the chunk header: ID and size (if IFF_SIZE_UNKNOWN, it will 504 | * be patched later by PopChunkW()). 505 | */ 506 | if ((size >= IFF_SIZE_RESERVED) && (size != IFF_SIZE_UNKNOWN_32)) 507 | { 508 | chunk.ID = id; 509 | chunk.Filler = IFF_SIZE_64BIT; 510 | chunk.Size = size; 511 | if (firstChunk) 512 | { 513 | err = IFFWrite(iff, &chunk, sizeof(Chunk)); 514 | } 515 | else 516 | { 517 | /* Update parent's count of bytes written. */ 518 | err = internalWriteChunk(iff, cn, &chunk, sizeof(Chunk)); 519 | } 520 | } 521 | else 522 | { 523 | smallChunk.ID = id; 524 | smallChunk.Size = size; 525 | if (firstChunk) 526 | { 527 | err = IFFWrite(iff, &smallChunk, sizeof(smallChunk)); 528 | } 529 | else 530 | { 531 | /* Update parent's count of bytes written. */ 532 | err = internalWriteChunk(iff, cn, &smallChunk, sizeof(smallChunk)); 533 | } 534 | } 535 | 536 | if (err < 0) 537 | return err; 538 | 539 | /* Allocate and fill in a ContextNode for the new chunk */ 540 | if (!(cn = AllocMem(sizeof(ContextNode), MEMTYPE_ANY))) 541 | return IFF_ERR_NOMEM; 542 | 543 | cn->cn_ID = id; 544 | cn->cn_Size = size; 545 | cn->cn_Offset = 0; 546 | cn->cn_CurrentSize = 0; 547 | PrepList(&cn->cn_ContextInfo); 548 | AddHead(&iff->iff_Stack, (Node *)cn); 549 | 550 | /* For generic chunks, write the type out now that 551 | * the chunk context node is initialized. 552 | */ 553 | if (IsGenericID(id) || IsContainerID(id)) 554 | { 555 | if (IsGenericID(id)) 556 | { 557 | err = internalWriteChunk(iff, cn, &type, sizeof(type)); 558 | cn->cn_Type = type; 559 | } 560 | else 561 | { 562 | cn->cn_Type = 0; /* denote a Container */ 563 | } 564 | } 565 | else 566 | { 567 | cn->cn_Type = parentType; 568 | } 569 | 570 | return err; 571 | } 572 | 573 | 574 | /*****************************************************************************/ 575 | 576 | 577 | /* Pop a chunk off the context stack. Ends the chunk and sets the size (if it 578 | * has not already been set) by seeking back and fixing it up. New top chunk 579 | * gets size updated. 580 | */ 581 | static Err PopChunkW(IFFParser *iff) 582 | { 583 | ContextNode *top; 584 | int64 rsize; 585 | Err err; 586 | uint64 size; 587 | int8 pad; 588 | bool unknownSize; 589 | bool bit64; 590 | uint32 size32; 591 | uint8 padBuf[2]; 592 | uint32 alignment, padding, extra; 593 | 594 | if (!(top = GetCurrentContext(iff))) 595 | return IFF_PARSE_EOF; 596 | 597 | if (top->cn_Size == IFF_SIZE_UNKNOWN_32) 598 | { 599 | /* Size is unknown. The size is therefore however many bytes the 600 | * client wrote. 601 | */ 602 | size = top->cn_CurrentSize; 603 | bit64 = FALSE; 604 | unknownSize = TRUE; 605 | } 606 | else if (top->cn_Size == IFF_SIZE_UNKNOWN_64) 607 | { 608 | /* Size is unknown. The size is therefore however many bytes the 609 | * client wrote. 610 | */ 611 | size = top->cn_CurrentSize; 612 | bit64 = TRUE; 613 | unknownSize = TRUE; 614 | } 615 | else 616 | { 617 | /* Size is known. Compare what the client said against what actually 618 | * happened. 619 | */ 620 | size = top->cn_Size; 621 | if (size != top->cn_CurrentSize) 622 | return IFF_ERR_MANGLED; 623 | 624 | bit64 = FALSE; 625 | unknownSize = FALSE; 626 | } 627 | 628 | /* if we're not at the end of the chunk, go there */ 629 | if (top->cn_Offset != top->cn_CurrentSize) 630 | { 631 | err = IFFSeek(iff, top->cn_CurrentSize - top->cn_Offset); 632 | if (err < 0) 633 | return err; 634 | } 635 | 636 | /* Add a possible pad byte */ 637 | rsize = (size + 1) & ~1; 638 | if (rsize > size) 639 | { 640 | pad = 0; 641 | err = IFFWrite(iff, &pad, 1); 642 | if (err < 0) 643 | return err; 644 | } 645 | 646 | /* Remove and deallocate this chunk and any stored properties */ 647 | FreeContextNode(iff, top); 648 | 649 | /* If needed, seek back and fix the chunk size */ 650 | if (unknownSize) 651 | { 652 | if (bit64) 653 | { 654 | err = IFFSeek(iff, -(rsize + sizeof(size))); 655 | if (err >= 0) 656 | err = IFFWrite(iff, &size, sizeof(size)); 657 | } 658 | else 659 | { 660 | if (size >= IFF_SIZE_RESERVED) 661 | return IFF_ERR_TOOBIG; 662 | 663 | size32 = size; 664 | 665 | err = IFFSeek(iff, -(rsize + sizeof(size32))); 666 | if (err >= 0) 667 | err = IFFWrite(iff, &size32, sizeof(size32)); 668 | } 669 | 670 | if (err >= 0) 671 | err = IFFSeek(iff, rsize); 672 | 673 | if (err < 0) 674 | return err; 675 | } 676 | 677 | if (top = GetCurrentContext(iff)) 678 | { 679 | /* Update parent's count */ 680 | top->cn_Offset += rsize; 681 | top->cn_CurrentSize += rsize; 682 | if ((top->cn_Size != IFF_SIZE_UNKNOWN_32) 683 | && (top->cn_Size != IFF_SIZE_UNKNOWN_64) 684 | && (top->cn_Offset > top->cn_Size)) 685 | return IFF_ERR_MANGLED; 686 | } 687 | 688 | alignment = iff->iff_Alignment; 689 | if (padding = (rsize % alignment)) 690 | { 691 | if (8 % alignment) 692 | { 693 | padding = alignment - ((8 + padding) % alignment); 694 | } 695 | else 696 | { 697 | padding = alignment - padding; 698 | } 699 | 700 | /* Update parent's count */ 701 | top->cn_Offset += padding+8; 702 | top->cn_CurrentSize += padding+8; 703 | if ((top->cn_Size != IFF_SIZE_UNKNOWN_32) 704 | && (top->cn_Size != IFF_SIZE_UNKNOWN_64) 705 | && (top->cn_Offset > top->cn_Size)) 706 | { 707 | return IFF_ERR_MANGLED; 708 | } 709 | 710 | extra = ID_PAD; 711 | err = IFFWrite(iff, &extra, 4); 712 | if (err < 0) 713 | return err; 714 | 715 | err = IFFWrite(iff, &padding, 4); 716 | if (err < 0) 717 | return err; 718 | 719 | padBuf[0] = (uint8)(alignment >> 8); 720 | padBuf[1] = (uint8)(alignment & 0x00FF); 721 | 722 | err = IFFWrite(iff, padBuf, 2); 723 | if (err < 0) 724 | return err; 725 | 726 | padding -= 2; 727 | 728 | padBuf[0] = padBuf[1] = 0; 729 | while (padding > 0) 730 | { 731 | err = IFFWrite(iff, padBuf, 2); 732 | if (err < 0) 733 | return err; 734 | 735 | padding -= 2; 736 | } 737 | } 738 | 739 | return 0; 740 | } 741 | 742 | 743 | /*****************************************************************************/ 744 | 745 | 746 | static int32 internalWriteChunk(IFFParser *iff, ContextNode *top, 747 | const void *buf, uint32 numBytes) 748 | { 749 | uint32 maxBytes; 750 | int32 result; 751 | 752 | if ((top->cn_Size != IFF_SIZE_UNKNOWN_32) 753 | && (top->cn_Size != IFF_SIZE_UNKNOWN_64)) 754 | { 755 | maxBytes = top->cn_Size - top->cn_Offset; 756 | 757 | if (numBytes > maxBytes) 758 | numBytes = maxBytes; 759 | } 760 | 761 | if (!numBytes) 762 | return 0; 763 | 764 | result = IFFWrite(iff, buf, numBytes); 765 | if (result >= 0) 766 | { 767 | top->cn_Offset += (uint32)result; 768 | 769 | if (top->cn_Offset > top->cn_CurrentSize) 770 | top->cn_CurrentSize = top->cn_Offset; 771 | } 772 | 773 | return result; 774 | } 775 | 776 | 777 | /*****************************************************************************/ 778 | 779 | 780 | int32 WriteChunk(IFFParser *iff, const void *buf, uint32 numBytes) 781 | { 782 | ContextNode *top; 783 | 784 | if (!(top = GetCurrentContext(iff))) 785 | return IFF_PARSE_EOF; 786 | 787 | if (IsGenericID(top->cn_ID)) 788 | { 789 | /* can't write into a generic chunk, must have a non-generic chunk there */ 790 | return IFF_ERR_NOTIFF; 791 | } 792 | 793 | return internalWriteChunk(iff, top, buf, numBytes); 794 | } 795 | 796 | 797 | /*****************************************************************************/ 798 | 799 | 800 | int32 WriteChunkCompressed(IFFParser *iff, const void *buf, uint32 numBytes) 801 | { 802 | TOUCH(iff); 803 | TOUCH(buf); 804 | TOUCH(numBytes); 805 | 806 | return IFF_ERR_NOTSUPPORTED; 807 | } 808 | 809 | 810 | /*****************************************************************************/ 811 | 812 | 813 | /* Purge a collection list node and all collection items within its 814 | * scope (given by First, LastPtr). 815 | */ 816 | static int32 PurgeCollectionList(IFFParser *iff, ContextInfo *ci) 817 | { 818 | CollectionList *cl; 819 | CollectionChunk *cc, *nextcc; 820 | 821 | TOUCH(iff); 822 | 823 | cl = (CollectionList *)ci->ci_Data; 824 | 825 | for (cc = cl->cl_First; (cc != cl->cl_LastPtr) && cc; cc = nextcc) 826 | { 827 | nextcc = cc->cc_Next; 828 | FreeMem(cc, sizeof(CollectionChunk) + cc->cc_DataSize); 829 | } 830 | FreeContextInfo(ci); 831 | 832 | return 0; 833 | } 834 | 835 | 836 | /*****************************************************************************/ 837 | 838 | 839 | /* Store contents of a chunk in a buffer and return 0 or error code */ 840 | static Err BufferChunk(IFFParser *iff, uint64 size, void *buf) 841 | { 842 | Err result; 843 | 844 | result = ReadChunk(iff, buf, size); 845 | if (result != size) 846 | { 847 | if (result >= 0) 848 | result = IFF_ERR_PREMATURE_EOF; 849 | 850 | return result; 851 | } 852 | return 0; 853 | } 854 | 855 | 856 | /*****************************************************************************/ 857 | 858 | 859 | /* Encountered a collection property chunk. Store this at the head of 860 | * the appropriate list. If no CollectionList at this level, create one. 861 | */ 862 | static Err HandleCollectionChunk(IFFParser *iff, void *dummy) 863 | { 864 | CollectionList *cltop; 865 | CollectionChunk *cc; 866 | uint64 size; 867 | Err err; 868 | CollectionList *clast; 869 | ContextNode *cn; 870 | ContextNode *ctxt; 871 | ContextInfo *ci; 872 | 873 | TOUCH(dummy); 874 | 875 | /* read the chunk into a buffer and create a CollectionChunk for it */ 876 | 877 | cn = GetCurrentContext(iff); 878 | size = cn->cn_Size; 879 | if (cc = AllocMem(sizeof(CollectionChunk) + size, MEMTYPE_ANY)) 880 | { 881 | cc->cc_Container = FindPropContext(iff); 882 | cc->cc_Data = &cc[1]; 883 | cc->cc_DataSize = size; 884 | 885 | err = BufferChunk(iff, cc->cc_DataSize, cc->cc_Data); 886 | if (err >= 0) 887 | { 888 | /* locate current PROP context */ 889 | if (ctxt = cc->cc_Container) 890 | { 891 | /* find the top collection list node for this context. */ 892 | 893 | ci = FindContextInfo(iff, cn->cn_Type, cn->cn_ID, IFF_CI_COLLECTIONCHUNK); 894 | if (ci) 895 | clast = (CollectionList *)ci->ci_Data; 896 | else 897 | clast = NULL; 898 | 899 | /* If this list item is at the same level as the current chunk, 900 | * this is the node for the current chunk and the new buffer 901 | * just needs to be linked in. If this is at a different 902 | * level, or there is none at all, a new cl node for this 903 | * level needs to be created. 904 | */ 905 | if (clast && (clast->cl_Context == ctxt)) 906 | { 907 | cltop = clast; 908 | } 909 | else 910 | { 911 | if (ci = AllocContextInfo(cn->cn_Type, cn->cn_ID, IFF_CI_COLLECTIONCHUNK, 912 | sizeof(CollectionList), (IFFCallBack)PurgeCollectionList)) 913 | { 914 | cltop = (CollectionList *)ci->ci_Data; 915 | cltop->cl_Context = ctxt; 916 | cltop->cl_LastPtr = NULL; 917 | 918 | if (clast) 919 | cltop->cl_LastPtr = clast->cl_First; 920 | 921 | cltop->cl_First = cltop->cl_LastPtr; 922 | 923 | err = StoreContextInfo(iff, ci, IFF_CIL_PROP); 924 | if (err < 0) 925 | FreeContextInfo(ci); 926 | } 927 | else 928 | { 929 | err = IFF_ERR_NOMEM; 930 | cltop = NULL; 931 | } 932 | } 933 | 934 | if (err >= 0) 935 | { 936 | /* Link new CollectionChunk at head of list. */ 937 | cc->cc_Next = cltop->cl_First; 938 | cltop->cl_First = cc; 939 | 940 | /* continue parsing */ 941 | return 1; 942 | } 943 | } 944 | else 945 | { 946 | err = IFF_ERR_NOSCOPE; 947 | } 948 | } 949 | FreeMem(cc, sizeof(CollectionChunk) + size); 950 | } 951 | else 952 | { 953 | err = IFF_ERR_NOMEM; 954 | } 955 | 956 | return err; 957 | } 958 | 959 | 960 | /*****************************************************************************/ 961 | 962 | 963 | static Err HandleStopChunk(const IFFParser *iff, void *dummy) 964 | { 965 | TOUCH(iff); 966 | TOUCH(dummy); 967 | 968 | /* stop parsing and return to client */ 969 | return 0; 970 | } 971 | 972 | 973 | /*****************************************************************************/ 974 | 975 | 976 | static Err HandlePropertyChunk(IFFParser *iff, void *dummy) 977 | { 978 | ContextInfo *ci; 979 | PropChunk *pc; 980 | ContextNode *cn; 981 | Err err; 982 | 983 | TOUCH(dummy); 984 | 985 | cn = GetCurrentContext(iff); 986 | 987 | ci = AllocContextInfo(cn->cn_Type, cn->cn_ID, IFF_CI_PROPCHUNK, 988 | cn->cn_Size + sizeof(PropChunk), NULL); 989 | if (ci) 990 | { 991 | pc = (PropChunk *)ci->ci_Data; 992 | pc->pc_DataSize = cn->cn_Size; 993 | pc->pc_Data = &pc[1]; 994 | 995 | /* Store contents of property chunk in current context */ 996 | err = BufferChunk(iff, cn->cn_Size, pc->pc_Data); 997 | if (err >= 0) 998 | { 999 | err = StoreContextInfo(iff, ci, IFF_CIL_PROP); 1000 | if (err >= 0) 1001 | { 1002 | /* continue parsing */ 1003 | return 1; 1004 | } 1005 | } 1006 | FreeContextInfo(ci); 1007 | } 1008 | else 1009 | { 1010 | err = IFF_ERR_NOMEM; 1011 | } 1012 | 1013 | return err; 1014 | } 1015 | 1016 | 1017 | /*****************************************************************************/ 1018 | 1019 | 1020 | /* Install a handler node into the current context */ 1021 | static Err InstallHandler(IFFParser *iff, uint32 type, uint32 id, uint32 ident, 1022 | ContextInfoLocation pos, IFFCallBack cb, 1023 | const void *userData) 1024 | { 1025 | ContextInfo *ci; 1026 | ChunkHandler *ch; 1027 | Err err; 1028 | 1029 | if (ci = AllocContextInfo(type, id, ident, sizeof(ChunkHandler), NULL)) 1030 | { 1031 | ch = (ChunkHandler *)ci->ci_Data; 1032 | ch->ch_HandlerCB = cb; 1033 | ch->ch_UserData = userData; 1034 | 1035 | err = StoreContextInfo(iff, ci, pos); 1036 | if (err < 0) 1037 | FreeContextInfo(ci); 1038 | 1039 | return err; 1040 | } 1041 | return IFF_ERR_NOMEM; 1042 | } 1043 | 1044 | 1045 | /*****************************************************************************/ 1046 | 1047 | 1048 | /* Read and test generic type ID */ 1049 | static Err ReadGenericType(IFFParser *iff) 1050 | { 1051 | ContextNode *top; 1052 | Err result; 1053 | 1054 | if (top = GetCurrentContext(iff)) 1055 | { 1056 | result = ReadChunk(iff, &top->cn_Type, sizeof(PackedID)); 1057 | if (result == sizeof(PackedID)) 1058 | { 1059 | if (GoodType(top->cn_Type)) 1060 | return 0; 1061 | 1062 | return IFF_ERR_MANGLED; 1063 | } 1064 | 1065 | if (result >= 0) 1066 | result = IFF_ERR_PREMATURE_EOF; 1067 | 1068 | return result; 1069 | } 1070 | 1071 | return IFF_PARSE_EOF; 1072 | } 1073 | 1074 | 1075 | /*****************************************************************************/ 1076 | 1077 | 1078 | Err CreateIFFParser(IFFParser **iffp, bool writeMode, const TagArg tags[]) 1079 | { 1080 | IFFParser *iff; 1081 | Err result; 1082 | TagArg *tag; 1083 | void *openKey; 1084 | IFFIOFuncs *ioFuncs; 1085 | 1086 | result = IFF_ERR_NOMEM; 1087 | 1088 | *iffp = NULL; 1089 | 1090 | openKey = NULL; 1091 | ioFuncs = NULL; 1092 | while ((tag = NextTagArg(&tags)) != NULL) 1093 | { 1094 | switch (tag->ta_Tag) 1095 | { 1096 | case IFF_TAG_FILE : openKey = tag->ta_Arg; 1097 | ioFuncs = (IFFIOFuncs *)&fileFuncs; 1098 | break; 1099 | 1100 | case IFF_TAG_IOFUNCS : ioFuncs = (IFFIOFuncs *)tag->ta_Arg; 1101 | break; 1102 | 1103 | case IFF_TAG_IOFUNCS_DATA: openKey = (void *)tag->ta_Arg; 1104 | break; 1105 | 1106 | default : return IFF_ERR_BADTAG; 1107 | } 1108 | } 1109 | 1110 | if (ioFuncs == NULL) 1111 | return IFF_ERR_NOOPENTYPE; 1112 | 1113 | iff = AllocMem(sizeof(IFFParser), MEMTYPE_FILL); 1114 | if (iff) 1115 | { 1116 | PrepList(&iff->iff_Stack); 1117 | iff->iff_NewIO = TRUE; 1118 | iff->iff_WriteMode = writeMode; 1119 | iff->iff_IOFuncs = ioFuncs; 1120 | iff->iff_Alignment = IFF_DEFAULT_ALIGNMENT; 1121 | 1122 | /* init and attach a surrounding master context */ 1123 | PrepList(&iff->iff_TopContext.cn_ContextInfo); 1124 | AddHead(&iff->iff_Stack, (Node *)&iff->iff_TopContext); 1125 | 1126 | result = IFFOpen(iff, openKey, writeMode); 1127 | if (result >= 0) 1128 | { 1129 | iff->iff_Cookie = iff; 1130 | *iffp = iff; 1131 | 1132 | return result; 1133 | } 1134 | FreeMem(iff,sizeof(IFFParser)); 1135 | } 1136 | 1137 | return result; 1138 | } 1139 | 1140 | 1141 | /*****************************************************************************/ 1142 | 1143 | 1144 | Err DeleteIFFParser(IFFParser *iff) 1145 | { 1146 | ContextNode *top; 1147 | ContextInfo *ci; 1148 | Err result; 1149 | 1150 | if (!IsIFFParser(iff)) 1151 | return IFF_ERR_BADPTR; 1152 | 1153 | result = 0; 1154 | while (GetCurrentContext(iff)) 1155 | { 1156 | result = PopChunk(iff); 1157 | if (result < 0) 1158 | { 1159 | while (top = GetCurrentContext(iff)) 1160 | { 1161 | FreeContextNode(iff, top); 1162 | } 1163 | } 1164 | } 1165 | 1166 | /* also do the master context */ 1167 | while (ci = (ContextInfo *)RemHead(&iff->iff_TopContext.cn_ContextInfo)) 1168 | { 1169 | ci->ci.n_Next = NULL; 1170 | PurgeContextInfo(iff, ci); 1171 | } 1172 | 1173 | if (result >= 0) 1174 | result = IFFClose(iff); 1175 | else 1176 | IFFClose(iff); 1177 | 1178 | iff->iff_Cookie = NULL; 1179 | FreeMem(iff, sizeof(IFFParser)); 1180 | 1181 | return result; 1182 | } 1183 | 1184 | 1185 | /*****************************************************************************/ 1186 | 1187 | 1188 | /* Test current state and advance to the next state. State is one of: 1189 | * 1190 | * - Start of file if iff_NewIO is TRUE. 1191 | * Push initial chunk, get its info and return. 1192 | * 1193 | * - Poised at end of chunk if iff_Paused is TRUE. 1194 | * PopChunk() the current context. The top context will then be a generic 1195 | * or end of file. Return EOF if the latter. If this chunk is exhausted, 1196 | * pause again and return, otherwise push new chunk and return. 1197 | * 1198 | * - Inside a generic chunk. 1199 | * Push a new context and return. 1200 | * 1201 | * - Inside a non-generic chunk. 1202 | * Pause and return. 1203 | */ 1204 | static Err NextState(IFFParser *iff) 1205 | { 1206 | ContextNode *top; 1207 | Err err; 1208 | PackedID topid; 1209 | 1210 | /* deal with the case of the first chunk */ 1211 | if (iff->iff_NewIO) 1212 | { 1213 | err = PushChunkR(iff, TRUE); 1214 | iff->iff_NewIO = FALSE; 1215 | iff->iff_Paused = FALSE; 1216 | if (err < 0) 1217 | return err; 1218 | 1219 | top = GetCurrentContext(iff); 1220 | 1221 | if ((top->cn_ID != ID_FORM) 1222 | && (top->cn_ID != ID_CAT) 1223 | && (top->cn_ID != ID_LIST) 1224 | && (!IsContainerID(top->cn_ID))) 1225 | return IFF_ERR_NOTIFF; 1226 | 1227 | if (top->cn_Size & 1) 1228 | { 1229 | /* containers must inherently be word-aligned */ 1230 | return IFF_ERR_MANGLED; 1231 | } 1232 | 1233 | return ReadGenericType(iff); 1234 | } 1235 | 1236 | /* In the PAUSE state, do the deferred PopChunk() */ 1237 | if (iff->iff_Paused) 1238 | { 1239 | err = PopChunk(iff); 1240 | if (err < 0) 1241 | return err; 1242 | 1243 | iff->iff_Paused = FALSE; 1244 | } 1245 | 1246 | /* If no top context node then the file is exhausted. */ 1247 | if (!(top = GetCurrentContext(iff))) 1248 | return IFF_PARSE_EOF; 1249 | 1250 | topid = top->cn_ID; 1251 | 1252 | if (IsGenericID(topid) || IsContainerID(topid)) 1253 | { 1254 | /* If inside a generic chunk, and not exhausted, push a subchunk. */ 1255 | if (top->cn_Offset < top->cn_Size) 1256 | { 1257 | err = PushChunkR(iff, FALSE); 1258 | if (err < 0) 1259 | return err; 1260 | 1261 | top = GetCurrentContext(iff); 1262 | 1263 | /* If non-generic, we're done, but if the containing chunk is not 1264 | * FORM or PROP, it's an IFF syntax error. 1265 | */ 1266 | if (!IsGenericID(top->cn_ID)) 1267 | { 1268 | if ((topid != ID_FORM) 1269 | && (topid != ID_PROP) 1270 | && (!IsContainerID(topid))) 1271 | return IFF_ERR_SYNTAX; 1272 | 1273 | return 0; 1274 | } 1275 | 1276 | /* If this new chunk is generic, and is a PROP, test to see if it's 1277 | * in the right place -- containing chunk should be a LIST. 1278 | */ 1279 | if ((top->cn_ID == ID_PROP) && (topid != ID_LIST)) 1280 | return IFF_ERR_SYNTAX; 1281 | 1282 | /* since it's an ok generic, get its type and return */ 1283 | return ReadGenericType(iff); 1284 | } 1285 | else if (top->cn_Offset != top->cn_Size) 1286 | { 1287 | /* If not exhaused, this is a junky IFF file */ 1288 | return IFF_ERR_MANGLED; 1289 | } 1290 | } 1291 | 1292 | /* If the generic is exhausted, or this is a non-generic chunk, 1293 | * enter the pause state and return flag. 1294 | */ 1295 | iff->iff_Paused = TRUE; 1296 | 1297 | return IFF_PARSE_EOC; 1298 | } 1299 | 1300 | 1301 | /*****************************************************************************/ 1302 | 1303 | 1304 | /* Driver for the parse engine. Loops calling NextState() and acting 1305 | * on the next parse state. NextState() will always cause the parser 1306 | * to enter or exit (really pause before exiting) a chunk. In each case, 1307 | * either an entry handler or an exit handler will be invoked on the 1308 | * current context. A handler can cause the parser to return control 1309 | * to the calling program or it can return an error. 1310 | */ 1311 | Err ParseIFF(IFFParser *iff, ParseIFFModes control) 1312 | { 1313 | ContextNode *top; 1314 | ContextInfo *ci; 1315 | ChunkHandler *ch; 1316 | Err err; 1317 | Err eoc; 1318 | 1319 | if (!IsIFFParser(iff)) 1320 | return IFF_ERR_BADPTR; 1321 | 1322 | if ((control < 0) || (control > IFF_PARSE_RAWSTEP)) 1323 | return IFF_ERR_BADMODE; 1324 | 1325 | while (TRUE) 1326 | { 1327 | /* advance to next state and store end of chunk info. */ 1328 | eoc = NextState(iff); 1329 | if ((eoc < 0) && (eoc != IFF_PARSE_EOC)) 1330 | return eoc; 1331 | 1332 | /* user requesting manual override -- return immediately */ 1333 | if (control == IFF_PARSE_RAWSTEP) 1334 | return eoc; 1335 | 1336 | if (!(top = GetCurrentContext(iff))) 1337 | return IFF_PARSE_EOF; 1338 | 1339 | /* find chunk handlers for entering or exiting a context. */ 1340 | if (eoc == IFF_PARSE_EOC) 1341 | ci = FindContextInfo(iff, top->cn_Type, top->cn_ID, IFF_CI_EXITHANDLER); 1342 | else 1343 | ci = FindContextInfo(iff, top->cn_Type, top->cn_ID, IFF_CI_ENTRYHANDLER); 1344 | 1345 | if (ci) 1346 | { 1347 | ch = (ChunkHandler *)ci->ci_Data; 1348 | err = (* ch->ch_HandlerCB)(iff, (void *)ch->ch_UserData); 1349 | if (err != 1) 1350 | return err; 1351 | } 1352 | 1353 | if (control == IFF_PARSE_STEP) 1354 | return eoc; 1355 | } 1356 | } 1357 | 1358 | 1359 | /*****************************************************************************/ 1360 | 1361 | 1362 | Err PushChunk(IFFParser *iff, PackedID type, PackedID id, uint32 size) 1363 | { 1364 | if (iff->iff_WriteMode) 1365 | return PushChunkW(iff, type, id, size); 1366 | 1367 | return PushChunkR(iff, FALSE); 1368 | } 1369 | 1370 | 1371 | /*****************************************************************************/ 1372 | 1373 | 1374 | Err PopChunk(IFFParser *iff) 1375 | { 1376 | if (iff->iff_WriteMode) 1377 | return PopChunkW(iff); 1378 | 1379 | return PopChunkR(iff); 1380 | } 1381 | 1382 | 1383 | /*****************************************************************************/ 1384 | 1385 | 1386 | Err InstallEntryHandler(IFFParser *iff, PackedID type, PackedID id, 1387 | ContextInfoLocation pos, IFFCallBack cb, const void *userData) 1388 | { 1389 | return InstallHandler(iff, type, id, IFF_CI_ENTRYHANDLER, pos, cb, userData); 1390 | } 1391 | 1392 | 1393 | /*****************************************************************************/ 1394 | 1395 | 1396 | Err InstallExitHandler(IFFParser *iff, PackedID type, PackedID id, 1397 | ContextInfoLocation pos, IFFCallBack cb, const void *userData) 1398 | { 1399 | return InstallHandler(iff, type, id, IFF_CI_EXITHANDLER, pos, cb, userData); 1400 | } 1401 | 1402 | 1403 | /*****************************************************************************/ 1404 | 1405 | 1406 | Err RegisterPropChunks(IFFParser *iff, const IFFTypeID typeids[]) 1407 | { 1408 | Err result; 1409 | 1410 | while (typeids->Type) 1411 | { 1412 | result = InstallEntryHandler(iff, typeids->Type, typeids->ID, IFF_CIL_TOP, 1413 | HandlePropertyChunk, NULL); 1414 | if (result < 0) 1415 | return result; 1416 | 1417 | typeids++; 1418 | } 1419 | 1420 | return 0; 1421 | } 1422 | 1423 | 1424 | /*****************************************************************************/ 1425 | 1426 | 1427 | Err RegisterStopChunks(IFFParser *iff, const IFFTypeID typeids[]) 1428 | { 1429 | Err result; 1430 | 1431 | while (typeids->Type) 1432 | { 1433 | result = InstallEntryHandler(iff, typeids->Type, typeids->ID, IFF_CIL_TOP, 1434 | (IFFCallBack)HandleStopChunk, NULL); 1435 | if (result < 0) 1436 | return result; 1437 | 1438 | typeids++; 1439 | } 1440 | 1441 | return 0; 1442 | } 1443 | 1444 | 1445 | /*****************************************************************************/ 1446 | 1447 | 1448 | Err RegisterCollectionChunks(IFFParser *iff, const IFFTypeID typeids[]) 1449 | { 1450 | Err result; 1451 | 1452 | while (typeids->Type) 1453 | { 1454 | result = InstallEntryHandler(iff, typeids->Type, typeids->ID, IFF_CIL_TOP, 1455 | HandleCollectionChunk, NULL); 1456 | if (result < 0) 1457 | return result; 1458 | 1459 | typeids++; 1460 | } 1461 | 1462 | return 0; 1463 | } 1464 | 1465 | 1466 | /*****************************************************************************/ 1467 | 1468 | 1469 | PropChunk *FindPropChunk(const IFFParser *iff, PackedID type, PackedID id) 1470 | { 1471 | ContextInfo *ci; 1472 | 1473 | ci = FindContextInfo(iff, type, id, IFF_CI_PROPCHUNK); 1474 | if (ci) 1475 | return (PropChunk *)ci->ci_Data; 1476 | 1477 | return NULL; 1478 | } 1479 | 1480 | 1481 | /*****************************************************************************/ 1482 | 1483 | 1484 | CollectionChunk *FindCollection(const IFFParser *iff, PackedID type, PackedID id) 1485 | { 1486 | CollectionList *cl; 1487 | ContextInfo *ci; 1488 | 1489 | ci = FindContextInfo(iff, type, id, IFF_CI_COLLECTIONCHUNK); 1490 | if (ci) 1491 | { 1492 | cl = (CollectionList *)ci->ci_Data; 1493 | if (cl) 1494 | return cl->cl_First; 1495 | } 1496 | 1497 | return NULL; 1498 | } 1499 | 1500 | 1501 | /*****************************************************************************/ 1502 | 1503 | 1504 | void AttachContextInfo(IFFParser *iff, ContextNode *to, ContextInfo *new) 1505 | { 1506 | ContextInfo *ci; 1507 | PackedID ident, id, type; 1508 | 1509 | ident = new->ci_Ident; 1510 | id = new->ci_ID; 1511 | type = new->ci_Type; 1512 | 1513 | /* nuke duplicate context data */ 1514 | ScanList(&to->cn_ContextInfo,ci,ContextInfo) 1515 | { 1516 | if ((ci->ci_Ident == ident) 1517 | && (ci->ci_ID == id) 1518 | && (ci->ci_Type == type)) 1519 | { 1520 | RemNode((Node *)ci); 1521 | ci->ci.n_Next = NULL; 1522 | PurgeContextInfo(iff, ci); 1523 | break; 1524 | } 1525 | } 1526 | 1527 | AddHead(&to->cn_ContextInfo, (Node *)new); 1528 | } 1529 | 1530 | 1531 | /*****************************************************************************/ 1532 | 1533 | 1534 | Err StoreContextInfo(IFFParser *iff, ContextInfo *ci, ContextInfoLocation pos) 1535 | { 1536 | ContextNode *cn; 1537 | 1538 | switch (pos) 1539 | { 1540 | case IFF_CIL_BOTTOM: cn = (ContextNode *)LastNode(&iff->iff_Stack); 1541 | break; 1542 | 1543 | case IFF_CIL_TOP : cn = (ContextNode *)FirstNode(&iff->iff_Stack); 1544 | break; 1545 | 1546 | case IFF_CIL_PROP : if (cn = FindPropContext(iff)) 1547 | break; 1548 | 1549 | return IFF_ERR_NOSCOPE; 1550 | 1551 | default : return IFF_ERR_BADLOCATION; 1552 | } 1553 | 1554 | AttachContextInfo(iff, cn, ci); 1555 | 1556 | return 0; 1557 | } 1558 | 1559 | 1560 | /*****************************************************************************/ 1561 | 1562 | 1563 | void RemoveContextInfo(ContextInfo *ci) 1564 | { 1565 | if (ci->ci.n_Next) 1566 | { 1567 | RemNode((Node *)ci); 1568 | ci->ci.n_Next = NULL; 1569 | } 1570 | } 1571 | 1572 | 1573 | /*****************************************************************************/ 1574 | 1575 | 1576 | ContextNode *GetCurrentContext(const IFFParser *iff) 1577 | { 1578 | ContextNode *cn; 1579 | 1580 | cn = (ContextNode *)FirstNode(&iff->iff_Stack); 1581 | if (cn->cn.n_Next && cn->cn_ID) 1582 | return cn; 1583 | 1584 | return NULL; 1585 | } 1586 | 1587 | 1588 | /*****************************************************************************/ 1589 | 1590 | 1591 | ContextNode *GetParentContext(const ContextNode *cn) 1592 | { 1593 | ContextNode *parent; 1594 | 1595 | parent = (ContextNode *)NextNode(cn); 1596 | if (parent->cn.n_Next && parent->cn_ID) 1597 | return parent; 1598 | 1599 | return NULL; 1600 | } 1601 | 1602 | 1603 | /*****************************************************************************/ 1604 | 1605 | 1606 | ContextInfo *AllocContextInfo(PackedID type, PackedID id, PackedID ident, 1607 | uint32 dataSize, IFFCallBack cb) 1608 | { 1609 | ContextInfo *ci; 1610 | 1611 | if (ci = AllocMem(sizeof(ContextInfo) + dataSize, MEMTYPE_FILL)) 1612 | { 1613 | ci->ci_ID = id; 1614 | ci->ci_Type = type; 1615 | ci->ci_Ident = ident; 1616 | ci->ci_Data = &ci[1]; 1617 | ci->ci_DataSize = dataSize; 1618 | ci->ci_PurgeCB = cb; 1619 | } 1620 | 1621 | return ci; 1622 | } 1623 | 1624 | 1625 | /*****************************************************************************/ 1626 | 1627 | 1628 | void FreeContextInfo(ContextInfo *ci) 1629 | { 1630 | if (ci) { 1631 | FreeMem(ci,sizeof(ContextInfo) + ci->ci_DataSize); 1632 | } 1633 | } 1634 | 1635 | 1636 | /*****************************************************************************/ 1637 | 1638 | 1639 | ContextInfo *FindContextInfo(const IFFParser *iff, PackedID type, PackedID id, 1640 | PackedID ident) 1641 | { 1642 | ContextNode *cn; 1643 | ContextInfo *ci; 1644 | 1645 | ScanList(&iff->iff_Stack,cn,ContextNode) 1646 | { 1647 | ScanList(&cn->cn_ContextInfo,ci,ContextInfo) 1648 | { 1649 | if ((ci->ci_Ident == ident) 1650 | && (ci->ci_ID == id) 1651 | && (ci->ci_Type == type)) 1652 | { 1653 | return ci; 1654 | } 1655 | } 1656 | } 1657 | 1658 | return NULL; 1659 | } 1660 | 1661 | 1662 | /*****************************************************************************/ 1663 | 1664 | 1665 | ContextNode *FindPropContext(const IFFParser *iff) 1666 | { 1667 | ContextNode *cn; 1668 | 1669 | ScanList(&iff->iff_Stack,cn,ContextNode) 1670 | { 1671 | if ((cn->cn_ID == ID_FORM) 1672 | || (cn->cn_ID == ID_LIST)) 1673 | { 1674 | if (cn != (ContextNode *)FirstNode(&iff->iff_Stack)) 1675 | return cn; 1676 | } 1677 | } 1678 | 1679 | return NULL; 1680 | } 1681 | -------------------------------------------------------------------------------- /IFF source code/iff.h: -------------------------------------------------------------------------------- 1 | #ifndef __MISC_IFF_H 2 | #define __MISC_IFF_H 3 | 4 | 5 | /****************************************************************************** 6 | ** 7 | ** @(#) iff.h 96/04/29 1.27 8 | ** 9 | ** IFF file parser. 10 | ** 11 | ******************************************************************************/ 12 | 13 | 14 | #ifndef __KERNEL_TYPES_H 15 | #include 16 | #endif 17 | 18 | #ifndef __KERNEL_LIST_H 19 | #include 20 | #endif 21 | 22 | #ifndef __KERNEL_ITEM_H 23 | #include 24 | #endif 25 | 26 | #ifndef __KERNEL_OPERROR_H 27 | #include 28 | #endif 29 | 30 | 31 | /*****************************************************************************/ 32 | 33 | 34 | /* kernel interface definitions */ 35 | #define IFF_FOLIONAME "iff" 36 | 37 | 38 | /*****************************************************************************/ 39 | 40 | 41 | /* There is one ContextNode structure created for every scoping level 42 | * during a parse operation. The nodes are kept in a LIFO queue. As new 43 | * scopes are entered, new nodes get added to the queue. As contexts are 44 | * exited, the nodes get removed. 45 | * 46 | * The cn_ID, cn_Type, and cn_Size fields describe the associated chunk. 47 | * cn_Offset indicates the current offset within this chunk where 48 | * ReadChunk() and WriteChunk() are. 49 | */ 50 | typedef struct ContextNode 51 | { 52 | MinNode cn; /* Linkage in the LIFO queue */ 53 | PackedID cn_Type; /* container ID (eg: AIFF) */ 54 | PackedID cn_ID; /* chunk ID */ 55 | #ifdef NO_64_BIT_SCALARS 56 | uint32 cn_SizeHi; 57 | uint32 cn_Size; 58 | uint32 cn_OffsetHi; 59 | uint32 cn_Offset; 60 | #else 61 | uint64 cn_Size; /* chunk size */ 62 | uint64 cn_Offset; /* current offset within chunk */ 63 | #endif 64 | #ifndef EXTERNAL_RELEASE 65 | List cn_ContextInfo; 66 | #ifdef NO_64_BIT_SCALARS 67 | uint32 cn_CurrentSizeHi; 68 | uint32 cn_CurrentSize; 69 | #else 70 | uint64 cn_CurrentSize; 71 | #endif 72 | #endif 73 | } ContextNode; 74 | 75 | 76 | /*****************************************************************************/ 77 | 78 | 79 | #ifdef EXTERNAL_RELEASE 80 | /* a parsing context */ 81 | typedef struct IFFParser IFFParser; 82 | #else 83 | typedef struct IFFParser 84 | { 85 | List iff_Stack; 86 | ContextNode iff_TopContext; 87 | void *iff_IOContext; 88 | struct IFFIOFuncs *iff_IOFuncs; 89 | bool iff_WriteMode; 90 | bool iff_NewIO; 91 | bool iff_Paused; 92 | uint16 iff_Alignment; 93 | void *iff_Cookie; 94 | } IFFParser; 95 | #endif 96 | 97 | /* call back functions */ 98 | typedef Err (* IFFCallBack)(IFFParser *iff, void *userData); 99 | 100 | /* information local to an active ContextNode */ 101 | typedef struct ContextInfo 102 | { 103 | MinNode ci; 104 | #ifdef NO_64_BIT_SCALARS 105 | uint32 ci_DataSizeHi; 106 | uint32 ci_DataSize; 107 | #else 108 | uint64 ci_DataSize; 109 | #endif 110 | void *ci_Data; 111 | #ifndef EXTERNAL_RELEASE 112 | 113 | PackedID ci_ID; /* chunk ID */ 114 | PackedID ci_Type; /* container ID */ 115 | PackedID ci_Ident; 116 | IFFCallBack ci_PurgeCB; 117 | #endif 118 | } ContextInfo; 119 | 120 | 121 | /*****************************************************************************/ 122 | 123 | 124 | /* These are used for custom IO processing */ 125 | typedef Err (* IFFOpenFunc)(void **userData, void *openKey, bool writeMode); 126 | typedef Err (* IFFCloseFunc)(void *userData); 127 | typedef int32 (* IFFReadFunc)(void *userData, void *buffer, uint32 numBytes); 128 | typedef int32 (* IFFWriteFunc)(void *userData, const void *buffer, uint32 numBytes); 129 | typedef int32 (* IFFSeekFunc)(void *userData, int32 position); 130 | 131 | typedef struct IFFIOFuncs 132 | { 133 | IFFOpenFunc io_Open; 134 | IFFCloseFunc io_Close; 135 | IFFReadFunc io_Read; 136 | IFFWriteFunc io_Write; 137 | IFFSeekFunc io_Seek; 138 | } IFFIOFuncs; 139 | 140 | 141 | /*****************************************************************************/ 142 | 143 | 144 | /* to specify chunks */ 145 | typedef struct IFFTypeID 146 | { 147 | PackedID Type; /* container ID (eg: AIFF) */ 148 | PackedID ID; /* chunk ID (eg: SSND) */ 149 | } IFFTypeID; 150 | 151 | 152 | /*****************************************************************************/ 153 | 154 | 155 | /* Describes the data associated with a previously encountered property 156 | * chunk. 157 | */ 158 | typedef struct PropChunk 159 | { 160 | #ifdef NO_64_BIT_SCALARS 161 | uint32 pc_DataSizeHi; 162 | uint32 pc_DataSize; 163 | #else 164 | uint64 pc_DataSize; 165 | #endif 166 | void *pc_Data; 167 | } PropChunk; 168 | 169 | 170 | /*****************************************************************************/ 171 | 172 | 173 | /* A node in a collection list. The next pointers cross a context boundaries so 174 | * that the complete list is accessible. 175 | */ 176 | typedef struct CollectionChunk 177 | { 178 | struct CollectionChunk *cc_Next; 179 | ContextNode *cc_Container; 180 | void *cc_Data; 181 | #ifdef NO_64_BIT_SCALARS 182 | uint32 cc_DataSizeHi; 183 | uint32 cc_DataSize; 184 | #else 185 | uint64 cc_DataSize; 186 | #endif 187 | } CollectionChunk; 188 | 189 | 190 | /*****************************************************************************/ 191 | 192 | 193 | /* Error codes */ 194 | #define MakeIFFErr(svr,class,err) MakeErr(ER_FOLI,ER_IFF,svr,ER_E_SSTM,class,err) 195 | 196 | /* No memory */ 197 | #define IFF_ERR_NOMEM MakeIFFErr(ER_SEVERE,ER_C_STND,ER_NoMem) 198 | 199 | /* Unknown tag supplied */ 200 | #define IFF_ERR_BADTAG MakeIFFErr(ER_SEVERE,ER_C_STND,ER_BadTagArg) 201 | 202 | /* Bad IFFParser parameter */ 203 | #define IFF_ERR_BADPTR MakeIFFErr(ER_SEVERE,ER_C_STND,ER_BadPtr) 204 | 205 | /* Operation not supported at this time */ 206 | #define IFF_ERR_NOTSUPPORTED MakeIFFErr(ER_SEVERE,ER_C_STND,ER_NotSupported) 207 | 208 | /* No valid scope for property */ 209 | #define IFF_ERR_NOSCOPE MakeIFFErr(ER_SEVERE,ER_C_NSTND,1) 210 | 211 | /* Hit the end of file too soon */ 212 | #define IFF_ERR_PREMATURE_EOF MakeIFFErr(ER_SEVERE,ER_C_NSTND,2) 213 | 214 | /* Data in file is corrupt */ 215 | #define IFF_ERR_MANGLED MakeIFFErr(ER_SEVERE,ER_C_NSTND,3) 216 | 217 | /* IFF syntax error */ 218 | #define IFF_ERR_SYNTAX MakeIFFErr(ER_SEVERE,ER_C_NSTND,4) 219 | 220 | /* Not an IFF file */ 221 | #define IFF_ERR_NOTIFF MakeIFFErr(ER_SEVERE,ER_C_NSTND,5) 222 | 223 | /* No open type specified */ 224 | #define IFF_ERR_NOOPENTYPE MakeIFFErr(ER_SEVERE,ER_C_NSTND,6) 225 | 226 | /* Bad storage location given */ 227 | #define IFF_ERR_BADLOCATION MakeIFFErr(ER_SEVERE,ER_C_NSTND,7) 228 | 229 | /* Bad storage location given */ 230 | #define IFF_ERR_TOOBIG MakeIFFErr(ER_SEVERE,ER_C_NSTND,8) 231 | 232 | /* Bad mode parameter */ 233 | #define IFF_ERR_BADMODE MakeIFFErr(ER_SEVERE,ER_C_NSTND,9) 234 | 235 | 236 | /* Not really errors, but they look like 'em */ 237 | 238 | /* reached logical end of file */ 239 | #define IFF_PARSE_EOF MakeIFFErr(ER_INFO,ER_C_NSTND,10) 240 | 241 | /* about to leave context */ 242 | #define IFF_PARSE_EOC MakeIFFErr(ER_INFO,ER_C_NSTND,11) 243 | 244 | 245 | /*****************************************************************************/ 246 | 247 | 248 | /* Universal IFF identifiers */ 249 | #define ID_FORM MAKE_ID('F','O','R','M') 250 | #define ID_LIST MAKE_ID('L','I','S','T') 251 | #define ID_CAT MAKE_ID('C','A','T',' ') 252 | #define ID_PROP MAKE_ID('P','R','O','P') 253 | #define ID_NULL MAKE_ID(' ',' ',' ',' ') 254 | 255 | /* Identifier codes for universally recognized ContextInfo nodes */ 256 | #define IFF_CI_PROPCHUNK MAKE_ID('p','r','o','p') 257 | #define IFF_CI_COLLECTIONCHUNK MAKE_ID('c','o','l','l') 258 | #define IFF_CI_ENTRYHANDLER MAKE_ID('e','n','h','d') 259 | #define IFF_CI_EXITHANDLER MAKE_ID('e','x','h','d') 260 | 261 | 262 | /*****************************************************************************/ 263 | 264 | 265 | /* Control modes for ParseIFF() */ 266 | typedef enum ParseIFFModes 267 | { 268 | IFF_PARSE_SCAN, 269 | IFF_PARSE_STEP, 270 | IFF_PARSE_RAWSTEP 271 | } ParseIFFModes; 272 | 273 | 274 | /*****************************************************************************/ 275 | 276 | 277 | /* value that entry or exit handlers should return to keep ParseIFF() running */ 278 | #define IFF_CB_CONTINUE 1 279 | 280 | 281 | /*****************************************************************************/ 282 | 283 | 284 | /* different types of seek operations */ 285 | typedef enum IFFSeekModes 286 | { 287 | IFF_SEEK_START, /* relative to start of chunk */ 288 | IFF_SEEK_CURRENT, /* relative to current position */ 289 | IFF_SEEK_END /* relative to end of chunk */ 290 | } IFFSeekModes; 291 | 292 | 293 | /*****************************************************************************/ 294 | 295 | 296 | /* Control modes for StoreContextInfo() */ 297 | typedef enum ContextInfoLocation 298 | { 299 | IFF_CIL_BOTTOM, /* store in default context */ 300 | IFF_CIL_TOP, /* store in current context */ 301 | IFF_CIL_PROP /* store in topmost FORM or LIST */ 302 | } ContextInfoLocation; 303 | 304 | 305 | /*****************************************************************************/ 306 | 307 | 308 | /* If you pass this value as a size to PushChunk() when writing a file, the 309 | * parser will figure out the size of the chunk for you. If you know the size, 310 | * it is better to provide it as it makes things faster. 311 | * 312 | * This particular value will cause a 32-bit IFF file to be generated, which 313 | * is backwards compatible with IFF-85 readers. If you try to write more 314 | * than 0xffffffef bytes to this file, you will get an error. 315 | */ 316 | #define IFF_SIZE_UNKNOWN_32 0xffffffff 317 | 318 | /* If you pass this value as a size to PushChunk() when writing a file, the 319 | * parser will figure out the size of the chunk for you. If you know the size, 320 | * it is better to provide it as it makes things faster. 321 | * 322 | * This particular value will cause a 64-bit IFF file to be generated, which 323 | * is not backwards compatible with IFF-85 readers, but allows darn big files 324 | * to be created. 325 | */ 326 | #define IFF_SIZE_UNKNOWN_64 0xfffffffe 327 | 328 | /* Specifies that the actual size of the chunk is stored as a 64-bit 329 | * number following the normal location of the 32-bit size field. 330 | */ 331 | #define IFF_SIZE_64BIT 0xfffffffd 332 | 333 | /* Reserved size values are from this number on up to 0xffffffff. No chunk 334 | * can have a 32-bit size field in this range. 335 | */ 336 | #define IFF_SIZE_RESERVED 0xfffffff0 337 | 338 | 339 | /* default byte alignment enforced by the folio on writes */ 340 | #define IFF_DEFAULT_ALIGNMENT 4 341 | 342 | 343 | /*****************************************************************************/ 344 | 345 | 346 | /* for use with CreateIFFParser() */ 347 | typedef enum IFFParserTags 348 | { 349 | IFF_TAG_FILE = TAG_ITEM_LAST+1, /* name of file to parse */ 350 | IFF_TAG_IOFUNCS, /* callback functions to do IO */ 351 | IFF_TAG_IOFUNCS_DATA /* openKey parameter for IFFOpenFunc */ 352 | } IFFParserTags; 353 | 354 | 355 | /*****************************************************************************/ 356 | 357 | 358 | #ifdef __cplusplus 359 | extern "C" { 360 | #endif /* __cplusplus */ 361 | 362 | 363 | /* folio management */ 364 | Err OpenIFFFolio(void); 365 | Err CloseIFFFolio(void); 366 | 367 | /* parser control */ 368 | Err CreateIFFParser(IFFParser **iff, bool writeMode, const TagArg tags[]); 369 | Err CreateIFFParserVA(IFFParser **iff, bool writeMode, uint32 tag, ...); 370 | Err DeleteIFFParser(IFFParser *iff); 371 | Err ParseIFF(IFFParser *iff, ParseIFFModes control); 372 | 373 | /* chunk data IO */ 374 | int32 ReadChunk(IFFParser *iff, void *buffer, uint32 numBytes); 375 | int32 WriteChunk(IFFParser *iff, const void *buffer, uint32 numBytes); 376 | Err SeekChunk(IFFParser *iff, int32 position, IFFSeekModes mode); 377 | 378 | #ifdef NO_64_BIT_SCALARS 379 | int32 GetIFFOffset(IFFParser *iff); 380 | #else 381 | int64 GetIFFOffset(IFFParser *iff); 382 | #endif 383 | 384 | /* context entry and exit */ 385 | Err PushChunk(IFFParser *iff, PackedID type, PackedID id, uint32 size); 386 | Err PopChunk(IFFParser *iff); 387 | 388 | /* built-in chunk and property handlers */ 389 | Err RegisterPropChunks(IFFParser *iff, const IFFTypeID typeids[]); 390 | Err RegisterStopChunks(IFFParser *iff, const IFFTypeID typeids[]); 391 | Err RegisterCollectionChunks(IFFParser *iff, const IFFTypeID typeids[]); 392 | 393 | /* context utilities */ 394 | PropChunk *FindPropChunk(const IFFParser *iff, PackedID type, PackedID id); 395 | CollectionChunk *FindCollection(const IFFParser *iff, PackedID type, PackedID id); 396 | ContextNode *FindPropContext(const IFFParser *iff); 397 | ContextNode *GetCurrentContext(const IFFParser *iff); 398 | ContextNode *GetParentContext(const ContextNode *contextNode); 399 | 400 | /* ContextInfo utilities */ 401 | ContextInfo *AllocContextInfo(PackedID type, PackedID id, PackedID ident, uint32 dataSize, IFFCallBack cb); 402 | void FreeContextInfo(ContextInfo *ci); 403 | ContextInfo *FindContextInfo(const IFFParser *iff, PackedID type, PackedID id, PackedID ident); 404 | Err StoreContextInfo(IFFParser *iff, ContextInfo *ci, ContextInfoLocation pos); 405 | void AttachContextInfo(IFFParser *iff, ContextNode *to, ContextInfo *ci); 406 | void RemoveContextInfo(ContextInfo *ci); 407 | 408 | /* low-level handler installation */ 409 | Err InstallEntryHandler(IFFParser *iff, PackedID type, PackedID id, ContextInfoLocation pos, 410 | IFFCallBack cb, const void *userData); 411 | Err InstallExitHandler(IFFParser *iff, PackedID type, PackedID id, ContextInfoLocation pos, 412 | IFFCallBack cb, const void *userData); 413 | 414 | 415 | #ifdef __cplusplus 416 | } 417 | #endif /* __cplusplus */ 418 | 419 | 420 | /*****************************************************************************/ 421 | 422 | 423 | #endif /* __MISC_IFF_H */ 424 | -------------------------------------------------------------------------------- /IFF source code/iff_folio.c: -------------------------------------------------------------------------------- 1 | /* @(#) iff_folio.c 96/05/17 1.19 */ 2 | 3 | void main(void) 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /IFF source code/io.c: -------------------------------------------------------------------------------- 1 | /* @(#) io.c 96/04/19 1.5 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "io.h" 9 | 10 | 11 | /*****************************************************************************/ 12 | 13 | 14 | static Err FileOpen(RawFile **file, const char *key, bool writeMode) 15 | { 16 | FileOpenModes mode; 17 | 18 | if (writeMode) 19 | mode = FILEOPEN_WRITE_NEW; 20 | else 21 | mode = FILEOPEN_READ; 22 | 23 | return OpenRawFile(file, key, mode); 24 | } 25 | 26 | 27 | /*****************************************************************************/ 28 | 29 | 30 | static Err FileClose(RawFile *file) 31 | { 32 | return CloseRawFile(file); 33 | } 34 | 35 | 36 | /*****************************************************************************/ 37 | 38 | 39 | static int32 FileRead(RawFile *file, void *buffer, uint32 numBytes) 40 | { 41 | return ReadRawFile(file, buffer, numBytes); 42 | } 43 | 44 | 45 | /*****************************************************************************/ 46 | 47 | 48 | static int32 FileWrite(RawFile *file, const void *buffer, uint32 numBytes) 49 | { 50 | return WriteRawFile(file, buffer, numBytes); 51 | } 52 | 53 | 54 | /*****************************************************************************/ 55 | 56 | 57 | static int32 FileSeek(RawFile *file, int32 position) 58 | { 59 | return SeekRawFile(file, position, FILESEEK_CURRENT); 60 | } 61 | 62 | 63 | /*****************************************************************************/ 64 | 65 | 66 | const IFFIOFuncs fileFuncs = 67 | {(IFFOpenFunc) FileOpen, 68 | (IFFCloseFunc) FileClose, 69 | (IFFReadFunc) FileRead, 70 | (IFFWriteFunc) FileWrite, 71 | (IFFSeekFunc) FileSeek}; 72 | -------------------------------------------------------------------------------- /IFF source code/io.h: -------------------------------------------------------------------------------- 1 | /* @(#) io.h 96/04/19 1.3 */ 2 | 3 | #ifndef __IO_H 4 | #define __IO_H 5 | 6 | 7 | /*****************************************************************************/ 8 | 9 | 10 | #include 11 | #include 12 | 13 | 14 | /*****************************************************************************/ 15 | 16 | 17 | #define IFFOpen(iff,k,m) (* iff->iff_IOFuncs->io_Open)(&iff->iff_IOContext,k,m) 18 | #define IFFClose(iff) (* iff->iff_IOFuncs->io_Close)(iff->iff_IOContext) 19 | #define IFFRead(iff,b,s) (* iff->iff_IOFuncs->io_Read)(iff->iff_IOContext,b,s) 20 | #define IFFWrite(iff,b,s) (* iff->iff_IOFuncs->io_Write)(iff->iff_IOContext,b,s) 21 | #define IFFSeek(iff,p) (* iff->iff_IOFuncs->io_Seek)(iff->iff_IOContext,p) 22 | 23 | 24 | /*****************************************************************************/ 25 | 26 | 27 | extern const IFFIOFuncs fileFuncs; 28 | 29 | 30 | /*****************************************************************************/ 31 | 32 | 33 | #endif /* __IO_H */ 34 | -------------------------------------------------------------------------------- /IFF source code/linkexec.x: -------------------------------------------------------------------------------- 1 | ! @(#) linkexec.x 96/02/12 1.6 2 | ! 3 | MAGIC 9 4 | EXPORTS 0=CreateIFFParser 5 | EXPORTS 1=DeleteIFFParser 6 | EXPORTS 2=ParseIFF 7 | EXPORTS 3=ReadChunk 8 | EXPORTS 4=WriteChunk 9 | EXPORTS 5=PushChunk 10 | EXPORTS 6=PopChunk 11 | EXPORTS 7=RegisterPropChunks 12 | EXPORTS 8=RegisterStopChunks 13 | EXPORTS 9=RegisterCollectionChunks 14 | EXPORTS 10=FindPropChunk 15 | EXPORTS 11=FindCollection 16 | EXPORTS 12=FindPropContext 17 | EXPORTS 13=GetCurrentContext 18 | EXPORTS 14=GetParentContext 19 | EXPORTS 15=AllocContextInfo 20 | EXPORTS 16=FreeContextInfo 21 | EXPORTS 17=FindContextInfo 22 | EXPORTS 18=StoreContextInfo 23 | EXPORTS 19=AttachContextInfo 24 | EXPORTS 20=InstallEntryHandler 25 | EXPORTS 21=InstallExitHandler 26 | EXPORTS 22=SeekChunk 27 | EXPORTS 23=GetIFFOffset 28 | EXPORTS 24=CreateIFFParserVA 29 | EXPORTS 25=RemoveContextInfo 30 | EXPORTS 26=ReadChunkCompressed 31 | EXPORTS 27=WriteChunkCompressed 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The "EA IFF-85" Repository 2 | ========================== 3 | 4 | * **IFF docs** 5 | 6 | The original Electronic Arts IFF docs with some revisions from Commodore Business Machines. 7 | 8 | Thankfully, Commodore converted the docs from MacWrite to Word format -- the \*.doc files in this repository. I converted those to .docx (MS Word format), .pdf, and .rtf files. 9 | 10 | * [EA IFF 85.pdf](http://1fish2.github.io/IFF/IFF%20docs%20with%20Commodore%20revisions/EA%20IFF%2085.pdf): **"EA IFF 85" Standard for Interchange Format Files** defines the IFF standard and explains the strategy of saving data in an extensible interchange format rather than dumping a program's internal state in a fixed format. 11 | * [IFF Quick Intro.pdf](http://1fish2.github.io/IFF/IFF%20docs%20with%20Commodore%20revisions/IFF%20Quick%20Intro.pdf): **A Quick Introduction to IFF** is a quick introduction for programmers in the 1980's. 12 | * [ILBM.pdf](http://1fish2.github.io/IFF/IFF%20docs%20with%20Commodore%20revisions/ILBM.pdf): **"ILBM" IFF Interleaved Bitmap** defines the raster image format (interleaved bitplanes) that's used heavily on the Commodore Amiga. 13 | * [8SVX.pdf](http://1fish2.github.io/IFF/IFF%20docs%20with%20Commodore%20revisions/8SVX.pdf): **"8SVX" IFF 8-Bit Sampled Voice** defines an 8-bit sampled sound format. 14 | * [SMUS.pdf](http://1fish2.github.io/IFF/IFF%20docs%20with%20Commodore%20revisions/SMUS.pdf): **"SMUS" IFF Simple Musical Score** defines a simple musical score format. 15 | 16 | 17 | * **[IFF source code](https://github.com/1fish2/IFF/tree/master/IFF%20source%20code)** 18 | 19 | A snapshot of AmigaOS C code for reading and writing IFF files. 20 | 21 | * **[IFF retrospective](https://github.com/1fish2/IFF/blob/master/IFF%20retrospective.md)** 22 | 23 | Notes on the history of IFF. 24 | 25 | * **[64-bit IFF](https://github.com/1fish2/IFF/blob/master/64-bit%20IFF.md)** 26 | 27 | Sketches for 64-bit (and larger) IFF data sizes. Not adopted. 28 | 29 | 30 | * [IFF Standard](https://wiki.amigaos.net/wiki/IFF_Standard) docs in the **AmigaOS Documentation Wiki** 31 | * [EA IFF 85 Standard](https://wiki.amigaos.net/wiki/EA_IFF_85_Standard_for_Interchange_Format_Files) 32 | * [A Quick Introduction to IFF](https://wiki.amigaos.net/wiki/A_Quick_Introduction_to_IFF) 33 | * **[IFF FORM and Chunk Registry](https://wiki.amigaos.net/wiki/IFF_FORM_and_Chunk_Registry)** 34 | --------------------------------------------------------------------------------