zxt:format
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
zxt:format [2021/07/07 22:05] – asie | zxt:format [2021/08/10 13:00] (current) – asie | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== ZXT Extended World Format ====== | + | ====== ZXT Extension |
<WRAP center round important 50%> | <WRAP center round important 50%> | ||
- | This is a draft! | + | This page is for draft work! For the latest official version of the ZXT specification, please |
- | + | ||
- | To discuss | + | |
</ | </ | ||
+ | |||
+ | Version ?.?.? | ||
+ | |||
+ | By Adrian " | ||
+ | |||
+ | Special thanks: endgame, GreaseMonkey, | ||
+ | |||
+ | The specification follows a MAJOR.MINOR.PATCH numbering scheme, where: | ||
+ | |||
+ | * Changes to the MAJOR number are expected to introduce breaking changes, resulting in a change of the extension header magic number; | ||
+ | * Changes to the MINOR number are expected to introduce changes which don't break backwards compatibility, | ||
+ | * Changes to the PATCH number are expected to introduce changes which don't impact the meaning of the specification, | ||
+ | |||
+ | For example, a ZXT 1.1.x world which doesn' | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | Over the past thirty years, many ideas have been theorized and approaches tried with regards to extending | + | Extending |
- | A common format | + | * The lack of source code greatly increased the difficulty of performing non-trivial modifications. |
+ | * The requirement | ||
+ | * No consistent means of signaling required | ||
- | * Creating forks and source ports of ZZT which support a more complete set of the diversified (non-ZZT 3.2-strict) | + | However, the release |
- | * Mixing | + | |
- | * Broader editor support for handling extended worlds. | + | |
- | The game world types that the ZXT format considers are as follows: | + | The following use cases were considered: |
- | * Creating | + | * Creating |
- | * Creating games which can benefit from enhanced functionality, | + | * Mixing and matching extensions from various creators within worlds, |
+ | * Usage of extensions within typical ZZT game operations (playing, saving, editing). | ||
+ | |||
+ | The following categories of worlds were considered: | ||
+ | |||
+ | * Completely | ||
+ | * Creating games which can benefit from enhanced functionality, | ||
* Standardizing pre-fork games which modify ZZT or Super ZZT in an incompatible way. Example: "ZZT Enhancer", | * Standardizing pre-fork games which modify ZZT or Super ZZT in an incompatible way. Example: "ZZT Enhancer", | ||
- | * Standardizing pre-fork games which modify ZZT or Super ZZT in partially or fully compatible | + | * Standardizing pre-fork games which modify ZZT or Super ZZT in ways which are technically compatible. Example: " |
+ | |||
+ | ===== Coverage ===== | ||
+ | |||
+ | The specification covers: | ||
+ | |||
+ | * The format of extension header data and resulting world files, | ||
+ | * Rules for processing extension data and handling identified edge cases, | ||
+ | * Expectations placed upon game engines implementing the specification. | ||
+ | |||
+ | Notably, the specification currently does **NOT** cover: | ||
+ | |||
+ | * The format of save (.SAV) files. We have decided not to mandate this at this time. | ||
+ | * The format of board (.BRD) files. This is due to the niche nature of the subject, and is likely to be expanded upon in a future version of the specification. | ||
===== Definitions ===== | ===== Definitions ===== | ||
Line 43: | Line 74: | ||
* **plstring** - a Pascal-style long string; a length u16 (N, of range between 0 and 65535) followed by N characters. | * **plstring** - a Pascal-style long string; a length u16 (N, of range between 0 and 65535) followed by N characters. | ||
- | Things marked "// | + | Where the specification |
- | ===== File Types ===== | + | ===== File Format |
+ | |||
+ | ==== Attachment | ||
The extension data can be provided in one of two ways: | The extension data can be provided in one of two ways: | ||
Line 52: | Line 85: | ||
* Providing a .ZXT file, being formed as a concatenation of an Extension Header and a world file ('' | * Providing a .ZXT file, being formed as a concatenation of an Extension Header and a world file ('' | ||
- | This is done because neither solution is strictly superior: | + | The two approaches are made with specific intents in mind, but may be used in any way the creator sees fit: |
- | * .ZAX files can be used to extend games with additional functionality (keybind shortcuts, metadata, etc.) without | + | * The intent of .ZAX files is to extend games with additional functionality (keybind shortcuts, metadata, etc.), while preserving compatibility with the ZZT game engine. (They can also serve as patches on top of an otherwise unmodified |
- | * A .ZXT file cannot be understood | + | * The intent of .ZXT files is to contain a modified ZZT game within one world file. This is especially useful for games which cannot be supported |
- | * Distributing | + | |
- | Notably, this does not cover save files. Saves are NOT guaranteed by the specification to be interchangeable between different implementations of the engine. (However, the authors expect a lot of implementations to simply follow | + | If a .ZXT file is being loaded, a .ZAX file should |
- | ===== Extension Header | + | The behaviour of multiple concatenated extension headers contained within one .ZXT or .ZAX file is undefined; distributed .ZXT or .ZAX files MUST NOT rely on it. |
+ | |||
+ | ==== Extension Header ==== | ||
The extension header' | The extension header' | ||
Line 72: | Line 106: | ||
^ Offset ^ Type ^ Name ^ Description ^ | ^ Offset ^ Type ^ Name ^ Description ^ | ||
| 0 | u16 | flags | Extension flags; defined below. | | | 0 | u16 | flags | Extension flags; defined below. | | ||
- | | 2 | u32 | owner_id | Extension owner ID | | + | | 2 | u32 | owner_id | Extension owner ID. | |
- | | 6 | u16 | selector_id | Extension selector ID | | + | | 6 | u16 | selector_id | Extension selector ID. | |
- | | 8 | u8 | reserved_0 | Reserved. | | + | | 8 | u8 | reserved_0 | Reserved; must be set to 0. | |
- | | 9 | u16 | field_length | Field length. | + | | 9 | u16 | field_length | Field length. |
| 11 | u8[field_length] | field_data | Field data. Extension-defined. | | | 11 | u8[field_length] | field_data | Field data. Extension-defined. | | ||
Line 90: | Line 124: | ||
| 5 | editing_should | Recommended for editing. | If set, an implementation which does not understand this extension SHOULD signal this to the end user if an attempt at editing the world is made. An engine does not have to make any effort to support such a world further. | Non-format-breaking (format-breaking go into writing_must, | | 5 | editing_should | Recommended for editing. | If set, an implementation which does not understand this extension SHOULD signal this to the end user if an attempt at editing the world is made. An engine does not have to make any effort to support such a world further. | Non-format-breaking (format-breaking go into writing_must, | ||
| 6 | preserve_should | Recommended to preserve on resave. | If set, an implementation SHOULD preserve the extension unchanged upon resave; if cleared, an implementation MUST NOT do so, and MUST discard the extension. | Generally, you want this set to 1 - unless the field data relies on other board, world or extension data outside itself. Meant in particular for metadata. | | | 6 | preserve_should | Recommended to preserve on resave. | If set, an implementation SHOULD preserve the extension unchanged upon resave; if cleared, an implementation MUST NOT do so, and MUST discard the extension. | Generally, you want this set to 1 - unless the field data relies on other board, world or extension data outside itself. Meant in particular for metadata. | | ||
- | | 7 | vanilla_behavior | Is this extension something ZZT 3.2 does anyway? | If set, an implementation of ZZT 3.2 or Super ZZT 2.0 compliant with the considerations set out in the specification | + | | 7 | vanilla_behavior | Is this extension something ZZT does anyway? | If set, an unmodified |
| 8 .. 15 | reserved | Reserved. | If set, an implementation MUST NOT continue parsing of the extension block. | | | | 8 .. 15 | reserved | Reserved. | If set, an implementation MUST NOT continue parsing of the extension block. | | | ||
- | It is important to note that the flags can be distinct from the ID pair; for instance, the same ZZT-OOP extension can be defined as " | + | It is important to note that the flags can be distinct from the ID pair; for instance, the same ZZT-OOP extension can be defined as " |
- | ===== Interactions between multiple | + | ===== Extension IDs ===== |
+ | |||
+ | Extension IDs are allocated on a per-owner ID basis. Within one owner ID, selector IDs SHOULD be used in a "one per extension" | ||
+ | |||
+ | ==== Owner ID Ranges ==== | ||
+ | |||
+ | * The range '' | ||
+ | * The range '' | ||
+ | * The range '' | ||
+ | |||
+ | ===== Interactions ===== | ||
+ | |||
+ | ==== Cross-Extension Interactions | ||
* **Extension Order:** Extensions MAY depend on their order of definition in the file. Implementations MUST, as such, preserve the order of extension definition when writing a ZXT file. | * **Extension Order:** Extensions MAY depend on their order of definition in the file. Implementations MUST, as such, preserve the order of extension definition when writing a ZXT file. | ||
- | * **Repeated Extensions: | + | * **Repeated Extensions: |
- | Any interactions not listed above are undefined behaviour and MUST NOT be relied upon. Here's an example | + | Any interactions not explicitly defined and not part of any enabled extension' |
* One extension is defined as " | * One extension is defined as " | ||
Line 106: | Line 152: | ||
* It is not certain what should happen if both extensions are in place, unless additional detail is provided. One could interpret it as only allowing the seven vanilla ZZT Keys to be held multiple at a time, or as allowing all sixteen to do so. | * It is not certain what should happen if both extensions are in place, unless additional detail is provided. One could interpret it as only allowing the seven vanilla ZZT Keys to be held multiple at a time, or as allowing all sixteen to do so. | ||
- | ===== Impact on world/board parsing ===== | + | ==== World Format |
* **Header/ | * **Header/ | ||
Line 113: | Line 159: | ||
* If a ZXT or ZAX file is present, the implementation MUST ignore the world ID present in the file itself, and trust the ZXT/ZAX file instead. | * If a ZXT or ZAX file is present, the implementation MUST ignore the world ID present in the file itself, and trust the ZXT/ZAX file instead. | ||
- | ===== Reserved extension owner IDs ==== | + | ==== Engine Extension Scope ==== |
- | * The range '' | + | * ZXT standard compliance concerns only the game engine's operation. The user interface and other external factors not impacting gameplay or game presentation are not in scope. |
- | * The range '' | + | * An implementation MAY choose to be compatible only with ZXT worlds containing certain |
- | ===== Considerations for .ZXT worlds and engines ===== | + | ==== Engine Accuracy |
- | ==== Scope ==== | + | Engines are expected to be accurate to the ZZT game engine' |
- | | + | * Implementations MUST emulate the Black Key. The behaviour, including the gem value change and the message duration, MUST be preserved, although the specific text message emitted MAY be changed. |
- | * An implementation MAY only be compatible with ZXT worlds containing certain extensions. Compatibility with un-extended ZZT 3.2 worlds is not a requirement. | + | * Implementations MUST support reading the state of stat -1. While the state of stat -1 in ZZT may change in rare circumstances, |
- | + | ||
- | ==== Accuracy ==== | + | |
- | + | ||
- | * An implementation consuming a .ZXT world, or a world with a .ZAX file, MUST NOT be expected to preserve ZZT's memory or stack layout exactly when running on a ZXT-compliant implementation. | + | |
- | * Most out-of-bounds memory reads and writes, as such, are not guaranteed to work correctly. | + | |
- | * The argTile2 trick pioneered in "Wake Up and Unlock The Door" counts as reliance on stack layout. | + | |
- | * If you're relying on such behaviours, consider making an extension standard for it instead! | + | |
- | * Certain behaviours have been grandfathered due to widespread usage pre-Reconstruction of ZZT. Extensions may change or disable their emulation. These are listed below: | + | |
- | | + | |
- | * Implementations MUST support reading the state of stat -1. While the state of stat -1 in ZZT may change in rare circumstances, | + | |
^ Field ^ Value ^ | ^ Field ^ Value ^ | ||
Line 150: | Line 186: | ||
| Data Len | 1 | | | Data Len | 1 | | ||
- | * A .ZXT world, or a world with a .ZAX file, MUST treat any feature which crashes regular ZZT (or causes double-frees, | + | Note that any feature which crashes regular ZZT (or causes double-frees, |
- | * That is to say, ZXT-compliant | + | |
+ | Of course, any of the assumptions in this section can be overridden by an extension. | ||
+ | |||
+ | ===== Best Practices ===== | ||
+ | |||
+ | This is not a formal part of the specification - it's more of an " | ||
+ | |||
+ | ==== World Developers ==== | ||
+ | |||
+ | * Distributing the world as a single .ZXT allows for greater user-friendliness than having | ||
+ | * Once you opt into the .ZXT format, ZZT tricks relying on memory/ | ||
+ | * Most out-of-bounds memory reads and writes, | ||
+ | * The argTile2 trick pioneered in “Wake Up and Unlock The Door" | ||
+ | |||
+ | ==== Extension Specification Authors ==== | ||
+ | |||
+ | * As soon as your extension is used by publicly-released worlds or implemented in publicly-released | ||
+ | * Use an ID inside the area of private use extensions while the extension' | ||
+ | * Mark your public specification as " | ||
+ | * If your extension is intended to work only with ZZT or Super ZZT, but not the other, it's a good idea to mention that explicitly in the specification. | ||
+ | |||
+ | ==== Engine Developers ==== | ||
- | ===== Unfinalized questions ===== | + | * Not every ZXT-compliant engine implementation must provide every extension! Don't fall neck-deep into code bloat, especially on your first try. Focus on the ones you care about, or which games you enjoy utilize. |
+ | * Remember that your save files need to be aware of which extensions ought to be enabled in order to correctly restore a gameplay session. An easy way for this is to do what ZZT itself does, and share the code for creating world files and save files. | ||
- | These questions/ | + | ===== Side Notes ===== |
- | - < | + | This is not a formal part of the specification |
- | - < | + | |
- | - < | + | |
- | * Defining save files as implementation-specific | + | |
- | * Low-memory platforms may be hindered by requiring to load a lot of unnecessary extension data and keep it in memory. (For example, character sets.) | + | |
- | * However, so long as the complete data is unnecessary to play the world, does it really hurt a //save file//? | + | |
- | * Maybe we could allow a save file to be augmented with a .ZXT or .ZAX to restore blocks which are missing? | + | |
- | * This would be best done with a " | + | |
- | * The compromise route, with no clear drawbacks, is to define save file rules as a SHOULD but not a MUST, allowing implementation-specific variants but encouraging a route for typical implementations. | + | |
- | - < | + | |
- | * Proposal A: | + | |
- | * Define a world ID (f.e. 0xE227) which means "this world file requires a ZXT header or ZAX file to be correctly parsed", | + | |
- | * Implementations must ignore the world ID if ZXT/ZAX information is present. | + | |
- | * The drawback is that using a valid, but incorrect ZAX will break loading... but a valid, but incorrect ZAX is possible anyway (OOP changes, element changes, etc). | + | |
- | * Proposal B: | + | |
- | * Allow extensions to define acceptable world IDs. | + | |
- | * Drawback: doesn' | + | |
- | | + | |
- | * Proposal A: In order of definition (see " | + | |
- | * Proposal B: In ascending order of extension IDs | + | |
- | - < | + | |
- | * The current ones are solely to not force implementations to emulate the entire ZZT 3.2 data segment; while Roton (commendably) tries to do it, it is a very large amount of effort that is also difficult to accomplish efficiently on some lower-end platforms. | + | |
- | - How should boards be prefixed? They can be of any size and don't have a magic number. | + | |
- | * Proposal A: Boards are not defined by the standard. | + | |
- | * Super ZZT and ZZT .BRD files use the same extension, but are not interchangeable. This wouldn' | + | |
- | * Proposal B: ZXT Boards start with two " | + | |
- | - Which extensions should be stored as part of a .BRD file? How to handle conflicts on import/ | + | |
- | - Should the specification make it clear that preference goes from last (most preferred) to first (least preferred) extension? (Think extensions which overwrite the same thing, but in increasingly more complex ways. For example, sound replacement could go from #PLAY -> FM data -> MIDI, or something.) | + | |
- | ===== Implementations ===== | + | * I am aware that the " |
+ | * A linear ID allocation system would most likely cause conflicts; | ||
+ | * A string-based ID system would increase implementation difficult, particularly on older compilers; | ||
+ | * The owner/ | ||
+ | * Save files are not mandated by the specification for two key reasons: | ||
+ | * Some extensions may require data specific to save files, and implementations may wish to have the freedom to decide how to store them in this case; | ||
+ | * Some implementations may store ZZT data in a custom format internally, and removing this requirement can make their code simpler. | ||
+ | * Multiple concatenated extension headers may be used as a feature in the future - for example, for faciliating multi-patch application for ZZT worlds. | ||
- | ==== Final specification | + | ===== Future Suggestions ===== |
- | As the specification has not been finalized, no such implementations exist yet. | + | ==== ZXT 2.0 ==== |
- | ==== Draft specification | + | ==== ZXT 1.1 ==== |
- | * [[https://github.com/ | + | * Unified way of handling external file dependencies (for example, large music files). |
- | * [[http:// | + | * Approach A: Add a bit which signifies that the data of an extension block is actually the filename of the file containing the real data. |
+ | * Approach B: Add a single extension with a list of external filenames used by the world. | ||
+ | * Approach C: Add a set of extensions to allocate "asset IDs" or "asset names", which may point to in-file data or out-of-file assets. | ||
+ | * Approach D: Do nothing. | ||
+ | * Only approach A would need to be discussed as part of a spec update. | ||
+ | * Add a bit which signifies "if this extension is not supported, the immediately following extension may be used as its substitute." | ||
+ | * Rationale: For example, multiple charset sizes (8x14, 6x8, 4x6, etc.) for different platforms. | ||
===== Comments ===== | ===== Comments ===== | ||
~~DISCUSSION~~ | ~~DISCUSSION~~ |
zxt/format.1625695535.txt.gz · Last modified: 2021/07/07 22:05 by asie