= Blorb: An IF Resource Collection Format Standard Andrew Plotkin // AsciiDoc Port Info: :PortVers: 1 :PortDate: 2021-01-12 :PortAuth: Tristano Ajmone :revremark: AsciiDoc Port v{PortVers} ({PortDate}) // Current Blorb Spec info: :BlorbVersion: 2.0.4 :revnumber: {BlorbVersion} :revdate: 2014-03-02 :version-label: Blorb :lang: en // Metadata: :keywords: blorb, interactive fiction, if, text adventures, standards, specification :description: pass:a,q,r[**Blorb {BlorbVersion}** -- \ Specification of Blorb, a standard format for Interactive Fictions resource \ collection.] // TOC Settings: :toc: left :toclevels: 2 // Sections Numbering: :sectnums: true :sectnumlevels: 2 // Cross References: :xrefstyle: full :section-refsig: Sec. // Misc Settings: :experimental: true :icons: font :linkattrs: true :reproducible: true :sectanchors: true // ***************************************************************************** // * * // * Document Preamble * // * * // ***************************************************************************** _Format specification version {BlorbVersion}_ + _Maintained by IFTF: _ Copyright 2020 by the https://iftechfoundation.org/[Interactive Fiction Technology Foundation^]. This specification is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License: https://creativecommons.org/licenses/by-nc-sa/3.0[^] This document and further Blorb information can be found at: https://github.com/iftechfoundation/ifarchive-if-specs[^] ================================================================================ .AsciiDoc Edition v{PortVers} ({PortDate}) [NOTE] ====================================================================== This document was built from an independent port to AsciiDoc of the https://eblong.com/zarf/blorb/Blorb-Spec.html[original HTML version^,title="View upstream source document at eblong.com"], converted and maintained by {PortAuth}: * https://github.com/tajmone/if-specs The document underwent some cosmetic adaptations to abide to AsciiDoc's idiomatic style conventions and semantics. Some paragraphs and text-asides were arbitrarily converted to admonition blocks (when their context justified doing so) to improve the reading experience. None of these changes altered nor affected the original text contents -- they are editorial choices to enhance the portability of the source document across different formats and custom templates. ====================================================================== ================================================================================ [Abstract] == Abstract This is a formal specification for a common format for storing resources associated with an interactive fiction game file. Resources are data which the game can invoke, such as sounds and pictures. In addition, the executable game file may itself be a resource in a resource file. This is a convenient way to package a game and all its resources together in one file. Blorb was originally designed solely for the Z-machine, which is capable of playing sounds (Z-machine versions 3 and up) and showing images (the V6 Z-machine). However, it has been extended for use with other IF systems. The Glk portable I/O library uses Blorb as a resource format, and therefore so does the Glulx virtual machine. (See https://eblong.com/zarf/glk/[^] and https://eblong.com/zarf/glulx/[^].) ADRIFT 5 (see http://www.adrift.org.uk/[^]) also uses Blorb, albeit with an extended format list. This format is named "`Blorb`" because it wraps your possessions up in a box, and because the common save file format was at one point named "`Gnusto`". That has been changed to "`Quetzal`", but I'm not going to let that stop me. This proposal is longer than I would have liked. However, a large percentage of it is optional stuff -- optional for either the interpreter writer, the game author, or both. That may make you feel better. I've also put in lots of examples, explication, and self-justification. //// DOCUMENT STRUCTURE/TOC: Overall Structure 1. Contents of the Resource Index Chunk 2. Picture Resource Chunks 2.1. PNG Pictures 2.2. JPEG Pictures 2.3. Placeholder Pictures 3. Sound Resource Chunks 3.1. AIFF Sounds 3.2. Ogg Sounds 3.3. MOD Sounds 3.4. Song Sounds 4. Data Resource Chunks 5. Executable Resource Chunks 5.1. Multiple Executable Chunks 6. The Game Identifier Chunk 7. The Color Palette Chunk 8. The Frontispiece Chunk 9. The Resource Description Chunk 10. Metadata 11. Chunks Specific to the Z-machine 11.1. The Release Number Chunk 11.2. The Resolution Chunk 11.3. The Adaptive Palette Chunk 11.4. The Looping Chunk 12. Other Optional Chunks 13. Deprecated Chunks 14. Presentation and Compatibility 14.1. File Suffixes 14.2. MIME Types 14.3. Z-Machine Compatibility Issues 14.4. Glk Compatibility Issues 14.5. ADRIFT 5 Compatibility Issues 15. The IFF Format 16. Other Resource Arrangements 17. Rationales and Rationalizations //// :sectnums!: == Overall Structure The overall format will be a new IFF type. The FORM type is '{wj}``IFRS``{wj}'. The first chunk in the FORM must be a resource index (chunk type '{wj}``RIdx``{wj}'.) This lists all the resources stored in the IFRS FORM. There must be exactly one resource index chunk. The resources are stored in the FORM as chunks; each resource is one chunk. They do not need to be in any particular order, since the resource index contains all the information necessary to find a particular resource. There are several optional chunks which may appear in the file: the release number (chunk type '{wj}``RelN``{wj}'), the game identifier (chunk type '{wj}``IFhd``{wj}'), and others defined hereafter. They may occur anywhere in the file after the resource index. Several optional chunks may also appear by convention in any IFF FORM: '{wj}``(c){nbsp}``{wj}', '{wj}``AUTH``{wj}', and '{wj}``ANNO``{wj}'. These may also appear anywhere in the file after the resource index. :sectnums: == Contents of the Resource Index Chunk [%autowidth] [cols="3*> later in this document. (These issues are not relevant to Glk and Glulx.) === AIFF Sounds An AIFF (Audio IFF) file has chunk type '{wj}``FORM``{wj}', and formtype '{wj}``AIFF``{wj}'. AIFF is an uncompressed digital-sample format developed in the late 1980s. The AIFF format is available at these locations: * https://www.loc.gov/preservation/digital/formats/fdd/fdd000005.shtml[^] * https://eblong.com/zarf/ftp/aiff-c.9.26.91.ps === Ogg Sounds An Ogg Vorbis file has chunk type '{wj}``OGGV``{wj}'. This is a high-quality (but lossy) audio compression format, comparable to MP3 (but without the patent concerns that encumber MP3). The Ogg format is available at: * http://www.vorbis.com[^] === MOD Sounds MOD is an Amiga-originated format for music synthesized from note samples. Over the years, other formats of this type -- generally called "`tracker`" or "`module music`" formats -- have arisen. Blorb supports four: original "`.MOD`" files, ImpulseTracker ("`.IT`"), FastTracker 2 Extended ("`.XM`"), and ScreamTracker 3 ("`.S3M`"). Because tracker-playing libraries typically handle many formats, it is most practical for Blorb to lump them all together. _Regardless of which tracker format is used,_ the chunk type will be '{wj}``MOD{nbsp}``{wj}'. The formats are described here: * https://www.loc.gov/preservation/digital/formats/fdd/fdd000126.shtml[^] This spec does not attempt to distinguish variations within the four supported formats. ("`.MOD`" is particularly ill-defined, although I have saved comments on the original MOD format at https://eblong.com/zarf/blorb/mod-spec.txt[^].) Instead, we recommend that C implementations embed libmodplug, a public-domain tracker-playing library. Its home page is: * http://modplug-xmms.sourceforge.net[^] However, some bug fixes are included in the version packaged with Windows Glk: * https://ifarchive.org/if-archive/programming/glk/implementations/[^] TIP: Note that it may be safer to compile libmodplug with the `MODPLUG_BASIC_SUPPORT` option, which eliminates many obscure tracker formats that Blorb does not support. Where libmodplug is not practical, implementations should use whatever tracker-playing library claims to support the four formats in question. We trust, perhaps beyond reason, that implementation differences will not lead game creators to their doom. === Song Sounds [NOTE] ================================================================================ _The song file format is deprecated, as of Blorb 2.0._ It is complicated, non-standard, and hard to use. Its support in interpreters should be considered optional. However, it will continue to be documented here. ================================================================================ A song file has chunk type '{wj}``SONG``{wj}'. This is similar to a MOD file, but with no built-in sample data. The samples are instead taken from AIFF sounds in the resource file. For each sample, the 22-byte sample-name field in the song should contain the string "`SND1`" to refer to sound resource 1, "`SND953`" to refer to sound resource 953, and so on. Any sound so referred to must be an AIFF, not a MOD or song. (You can experiment with fractal recursive music on your own time.) Each sample record in a MOD or song contains six fields: sample name, sample length, finetune value, volume, repeat start, repeat length. In a MOD file, the sample name is ignored by Blorb (it is traditionally used to store a banner or comments from the author.) In a song file, the sample name contains a resource reference as described above; but the sample length, repeat start, and repeat length fields are ignored. These values are inferred from the AIFF resource. (The repeat start and repeat length are taken from the `sustainLoop` of the AIFF's instrument chunk. If there is no instrument chunk, or if `sustainLoop.playMode` is `NoLooping`, there is no repeat; the repeat start and length values are then considered zero.) [TIP] ================================================================================ Note that an AIFF need not contain 8-bit sound samples, as a sound built into a MOD would. A clever sound engine may take advantage of this to generate higher-quality music. An unclever one can trim (or pad) the AIFF's data to 8 bits before playing the song. In the worst case, it is always possible to trim the AIFF data to 8 bits, append it to the song data, fill in the song's sample records (with the appropriate lengths, etc., from the AIFF data); the result is a complete MOD file, which can then be played by a standard MOD engine. ================================================================================ The intent of allowing song files is both to allow higher quality, and to save space. Note samples are the largest part of a MOD file, and if the samples are stored in resources, they can be shared between songs. (Typically note samples will be given high resource numbers, so that they do not conflict with sounds used directly by the game. However, it is legal for the game to use a note sample as a sampled-sound effect, if it wants.) == Data Resource Chunks Each data file is stored as one chunk, with chunk type '{wj}``TEXT``{wj}' or '{wj}``BINA``{wj}' (denoting text or binary data). The format and contents are up to the game to interpret. This feature was designed to support Glulx, but data resources can be accessed by any game format if the interpreter supports them. For Glulx games (and any other game format which uses the Glk API), the data format must follow the conventions described in the Glk spec. (https://eblong.com/zarf/glk/[^], "`Resource Streams`".) [TIP] ================================================================================ To summarize: if the data file is opened via `glk_stream_open_resource()`, then it will be read as a stream of bytes; text will be assumed to be encoded as Latin-1. If it is opened via `glk_stream_open_resource_uni()`, then a '{wj}``TEXT``{wj}' chunk will be assumed to be a stream of characters encoded as UTF-8; '{wj}``BINA``{wj}' will be assumed to be a stream of big-endian four-byte integers. If read by lines (`glk_get_line_stream()`, etc.), resource text should use Unix line breaks in all cases. ================================================================================ == Executable Resource Chunks There should at most one chunk with usage '{wj}``Exec``{wj}'. [.Comment]#[But see below.]# If present, its number must be zero. Its content is a VM or game executable. Its chunk type describes its format: [horizontal] '{wj}``ZCOD``{wj}' :: Z-code '{wj}``GLUL``{wj}' :: Glulx '{wj}``TAD2``{wj}' :: TADS 2 '{wj}``TAD3``{wj}' :: TADS 3 '{wj}``HUGO``{wj}' :: Hugo '{wj}``ALAN``{wj}' :: Alan '{wj}``ADRI``{wj}' :: ADRIFT '{wj}``LEVE``{wj}' :: Level 9 '{wj}``AGT{nbsp}``{wj}' :: AGT '{wj}``MAGS``{wj}' :: Magnetic Scrolls '{wj}``ADVS``{wj}' :: AdvSys '{wj}``EXEC``{wj}' :: Native executable [NOTE] ================================================================================ This list of formats is taken from the Babel format agreement. See https://babel.ifarchive.org[^] for more information. Most of these development systems do not support Blorb at the present time; the list is available for future use. Other executable formats may also be added in the future. As a convention, the chunk types should be taken from the Babel format name, converted to upper case and padded (if necessary) with spaces. ================================================================================ [WARNING] ================================================================================ The EXEC (native) chunk type is not likely to be useful, because it is underspecified. Nothing (beyond the chunk data itself) indicates what CPU or operating system the executable is intended for. Again, it is defined here following the Babel format list. ================================================================================ A resource file which contains an executable chunk contains everything needed to run the executable. An interpreter can begin interpreting when handed such a resource file; it sees that there is an executable chunk, loads it, and runs it. A resource file which does not contain an executable chunk can only be used in tandem with an executable file. The interpreter must be handed both the resource file and the executable file in order to begin interpreting. If an interpreter is handed inconsistent arguments -- that is, a resource file with no executable chunk, or a resource file with an executable chunk plus an executable file -- it should complain righteously to the user. === Multiple Executable Chunks As of this spec, no IF system puts more than one '{wj}``Exec``{wj}' chunk in a Blorb file, or has any need to. However, this could change in the future. One possible use (noted as a comment in earlier versions of this spec) is to support several loadable libraries or game segments. In such a case, chunk zero should contain the code to execute first, or at the top level. Another possibility is to distribute several versions of a game in one Blorb package. IF platforms are famed for the fragility of their save files; a player who downloads an updated game file is likely to find that it no longer loads her old saved games. This could be avoided if the updated Blorb actually contained multiple game files, one per '{wj}``Exec``{wj}' chunk. Chunk zero would be the preferred (most recent) game version, but when loading a save file, the interpreter would select whichever game version was compatible with it. == The Game Identifier Chunk This identifies which game the resources are associated with. The chunk type is '{wj}``IFhd``{wj}'. This chunk is optional; at most one should appear. If it is present, and the interpreter is given a game file along with a resource file, the interpreter can check that the game matches the IFhd chunk. If they don't, the interpreter should display an error. The interpreter may want to provide a way for the user to ignore or skip this error (for example, if the user is a game author testing changes to the game file.) If the resource file contains an executable chunk, there is little reason to have an IFhd chunk. It is legal, however, as long as the identifier matches the executable. For Z-code, the contents of the game identifier chunk are defined in the common save file format specification, section 5. This spec can be found at * https://ifarchive.org/if-archive/infocom/interpreters/specification/savefile_14.txt[^] The "`Initial PC`" field of the IFhd chunk (bytes 10 through 12) has no meaning for resource files. It should be set to zero. For Glulx, the contents of the game identifier chunk are defined in the Glulx specification. This can be found at https://eblong.com/zarf/glulx/[^]. == The Color Palette Chunk This contains information about which colors are used by picture resources in the file. The chunk type is '{wj}``Plte``{wj}'. It is optional, and should not appear if there are no '{wj}``Pict``{wj}' resources in the file. At most one color palette chunk should appear. The format is: [%autowidth] [cols="3*` tag. == Metadata Metadata is a contentious topic, with which the Blorb spec is not entirely unentangled. (The game identifier and frontispiece chunks are answers to small parts of the IF metadata problem.) Rather than entangle ourselves further, we will merely say that metadata will be stored as XML, in a chunk of type '{wj}``IFmd``{wj}'. The XML structure is documented in the Babel format agreement; see https://babel.ifarchive.org[^]. [%autowidth] [cols="3* maxratio, then R = maxratio. * If minratio ≤ ERF*stdratio ≤ maxratio, then R = ERF * stdratio. If minratio and maxratio are the same value, then R will always be this value; ERF and stdratio are ignored in this case. (This indicates a scalable image with a fixed scaling ratio.) The interpreter then knows that this image should be drawn at a scale of R screen pixels per image pixel, both vertically and horizontally. The interpreter should report this scaled size to the game if queried with `@picture_data` (as opposed to the original image size). Yes, this is an ornate system. The author is free to ignore it by not including a resolution chunk. If the author wants scaled images, or variably-scalable images, this system should suffice. Here are some examples. They're not necessarily examples of good art design, but they do demonstrate how a given set of desires translate into images and resolution values. All are for a game with a standard size of (600,400). ================================================================================ The game wishes a title image that covers the entire window, and all the resolution should be visible at the standard size. (So if the window is twice the standard size, the image will be stretched and coarse-looking; if the window is half the standard size, the image will be squashed and lose detail.) * Image size (600,400); stdratio 1.0; minratio zero; maxratio infinity. ================================================================================ ================================================================================ The game has a background image of a cave, made from a scanned photograph. At standard window size, this should cover the entire window, but not all the detail needs to be visible. If the window is larger, the image should still cover the entire window; more detail will be visible, up to twice the standard size (at which point all the resolution should be visible.) If the window is larger than twice the standard size, the image should not be stretched farther; instead the game will center it and have blank space around the edges. * Image size (1200,800); stdratio 0.5; minratio zero; maxratio 1.0. ================================================================================ ================================================================================ The game has small monochrome icons indicating different magical perceptions, which it will draw interspersed with the text. The icons should always be drawn at double size, two screen pixels per image pixel, regardless of the window size. * Image size (20,20); stdratio 1.0; minratio 2.0; maxratio 2.0. * (In this case, remember, the stdratio value is ignored.) ================================================================================ ================================================================================ The game has a graphical compass rose which it will draw in the top left corner. This should be 1/4 of the window size in the standard case, and shrink proportionally if the window is smaller. However, if the window is larger than standard, the rose should not grow; all the extra space can be allotted for text. All detail (image pixels) should be visible in the standard case. * Image size (150,100); stdratio 1.0; minratio zero; maxratio 1.0. ================================================================================ ================================================================================ The same compass rose, still to be 1/4 of the window size -- but this time it is critical that all the image detail be visible when the window is as small as half-standard (that is, when the rose is 75 by 50 pixels). At standard scale (150 by 100), it will therefore appear stretched and coarse. If the window is smaller than half the standard size, the rose should not shrink beyond 75x50, so that pixels are never lost. * Image size (75,50); stdratio 2.0; minratio 1.0; maxratio 2.0. ================================================================================ End of verbose examples. === The Adaptive Palette Chunk This chunk contains a list of pictures that change their colors according to the pictures plotted before. The chunk type is '{wj}``APal``{wj}'. It is optional. This chunk is meaningful only in Z-code resource files. This format exists to describe the legacy behavior of some V6 Infocom games (Zork Zero and Arthur). Its support in interpreters is optional, and its use is strongly discouraged for any purpose other than conversions of Infocom graphics. [%autowidth] [cols="3*