From c5ab0e0104ab36246c46ba141b54d6f738b21a48 Mon Sep 17 00:00:00 2001 From: RDW Date: Sat, 2 Mar 2024 22:10:37 +0100 Subject: [PATCH 1/2] Repo: Enable magic diff comments for Prism.js code blocks It's not as nice as a real git diff, but should serve to highlight the differences between versions without the need for a changelog. --- docusaurus.config.js | 12 ++++++++++++ src/css/color-theme-dark.css | 29 +++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/docusaurus.config.js b/docusaurus.config.js index 00320dcf..bc50c1e0 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -155,6 +155,18 @@ const config = { theme: lightCodeTheme, darkTheme: darkCodeTheme, additionalLanguages: ["c", "cpp", "lua", "rust", "wgsl"], + magicComments: [ + { + className: "code-block-diff-add-line", + line: "diff-add", + block: { start: "diff-add-start", end: "diff-add-end" }, + }, + { + className: "code-block-diff-remove-line", + line: "diff-remove", + block: { start: "diff-remove-start", end: "diff-remove-end" }, + }, + ], }, }), }; diff --git a/src/css/color-theme-dark.css b/src/css/color-theme-dark.css index 5a729d12..0a1995ff 100644 --- a/src/css/color-theme-dark.css +++ b/src/css/color-theme-dark.css @@ -64,3 +64,32 @@ code { font-size: 85%; border: none; } + +/* Prism.js: Better syntax highlighting for important language keywords */ +span.token.keyword { + color: blue !important; + font-weight: bold; +} + +span.token.class-name { + color: rgb(255, 0, 0) !important; +} + +/* Prism.js: Magic comments for diff highlights */ +.code-block-diff-add-line { + background-color: #ccffd8; + background-color: rgb(230, 255, 235); + background-color: rgb(220, 255, 225); + display: block; + margin: 0 calc(var(--ifm-pre-padding) * -1); + padding: 0 var(--ifm-pre-padding); +} + +.code-block-diff-remove-line { + background-color: #ffebe9; + background-color: rgb(255, 235, 235); + background-color: rgb(255, 225, 225); + display: block; + margin: 0 calc(var(--ifm-pre-padding) * -1); + padding: 0 var(--ifm-pre-padding); +} From f3cf9cede5f29490378e012a9308899f2f5e08e9 Mon Sep 17 00:00:00 2001 From: RDW Date: Sat, 2 Mar 2024 22:13:37 +0100 Subject: [PATCH 2/2] Docs: Rework the SPR format specification with diff highlights This cuts down a lot on redundancy and verbosity, while hopefully still providing all of the same information. It's mostly a test for the diff views; if this works out then the other format specifications can be reworked as well. Also added some reference implementations that are reasonably easy to understand (omitting the Unity ones because they aren't suitable for this purpose). --- docs/file-formats/SPR.md | 237 ++++++++++++++++++++++++++++----------- 1 file changed, 172 insertions(+), 65 deletions(-) diff --git a/docs/file-formats/SPR.md b/docs/file-formats/SPR.md index d2d9b8b1..52dbcd96 100644 --- a/docs/file-formats/SPR.md +++ b/docs/file-formats/SPR.md @@ -43,75 +43,182 @@ This feature isn't used for the truecolor (TGA) segments as pixels are stored in ### Transparency -Alpha values in the BMP palette are completely ignored. RGBA colors will be stored raw and not premultiplied. +Alpha values in the BMP palette should be completely ignored. RGBA colors are stored raw and not premultiplied. -The color with palette index 0 should be considered the "background color". It must be cleared manually, though. +The color with palette index 0 can be considered the "background color". It must be cleared manually on load. ## Layout -### Version 1.1 +### Versions + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +```cpp title="SPR File Format (v1.1)" +struct BitmapSprite { + uint16_t ImageWidth; + uint16_t ImageHeight; + uint8_t PaletteIndices[ImageWidth * ImageHeight]; +}; + +struct PaletteColor { + uint8_t Red; + uint8_t Green; + uint8_t Blue; + uint8_t Alpha; +}; + +struct RagnarokSPR { + char Signature[2]; + uint8_t VersionMajor; + uint8_t VersionMinor; + uint16_t BitmapImageCount; + struct BitmapSprite BitmapSprites[BitmapImageCount]; + struct PaletteColor BitmapColors[256]; +}; +``` + + + + +```cpp title="SPR File Format (v2.0)" +struct BitmapSprite { + uint16_t ImageWidth; + uint16_t ImageHeight; + uint8_t PaletteIndices[ImageWidth * ImageHeight]; +}; + +// diff-add-start +struct TrueColorPixel { + uint8_t Alpha; + uint8_t Blue; + uint8_t Green; + uint8_t Red; +}; + +struct TrueColorSprite { + uint16_t ImageWidth; + uint16_t ImageHeight; + struct TrueColorPixel PixelBuffer[ImageWidth * ImageHeight]; +}; +// diff-add-end + +struct PaletteColor { + uint8_t Red; + uint8_t Green; + uint8_t Blue; + uint8_t Alpha; +}; + +struct RagnarokSPR { + char Signature[2]; + uint8_t VersionMajor; + uint8_t VersionMinor; + uint16_t BitmapImageCount; + // diff-add + uint16_t TrueColorImageCount; + struct BitmapSprite BitmapSprites[BitmapImageCount]; + // diff-add + struct TrueColorSprite TrueColorSprites[TrueColorImageCount]; + struct PaletteColor BitmapColors[256]; +}; +``` + + + + +```cpp title="SPR File Format (v2.1)" +// diff-remove +struct BitmapSprite { +// diff-add +struct CompressedBitmapSprite { + uint16_t ImageWidth; + uint16_t ImageHeight; + // diff-remove + uint8_t PaletteIndices[ImageWidth * ImageHeight]; + // diff-add-start + uint16_t CompressedBufferSize; + uint8_t CompressedPaletteIndices[CompressedBufferSize]; + // diff-add-end +}; + +struct TrueColorPixel { + uint8_t Alpha; + uint8_t Blue; + uint8_t Green; + uint8_t Red; +}; + +struct TrueColorSprite { + uint16_t ImageWidth; + uint16_t ImageHeight; + struct TrueColorPixel PixelBuffer[ImageWidth * ImageHeight]; +}; + +struct PaletteColor { + uint8_t Red; + uint8_t Green; + uint8_t Blue; + uint8_t Alpha; +}; + +struct RagnarokSPR { + char Signature[2]; + uint8_t VersionMajor; + uint8_t VersionMinor; + uint16_t BitmapImageCount; + uint16_t TrueColorImageCount; + // diff-remove + struct BitmapSprite BitmapSprites[BitmapImageCount]; + // diff-add + struct CompressedBitmapSprite CompressedBitmapSprites[BitmapImageCount]; + struct TrueColorSprite TrueColorSprites[TrueColorImageCount]; + struct PaletteColor BitmapColors[256]; +}; +``` + + + + +### Fields + +#### Signature + +Uniquely identifies the file format. Must always be `"SP"` (ASCII-encoded, fixed-size string). + +#### Version + +Signals the presence of optional features. Version `1.1` is used only in [Arcturus](/arcturus), but not in any known build of the RO client. + +#### BitmapSprites + +Indexed-color sprite images (BMP segment). All pixels are stored as palette indices that need to be resolved on load. + +A size of `(-1, -1)` indicates an invalid image, which consists of a single blank pixel that can safely be discarded. + +#### BitmapColors + +The BMP color palette, consisting of RGBA pixels. Alpha can be discarded. Equivalent to the file contents of a [PAL](/file-formats/pal) file. + +#### TrueColorSprites + +True color sprite images (TGA segment). Pixels are stored raw in order ABGR and they do make use of the alpha channel. + +#### CompressedBitmapSprites + +Indexed-color sprite images (BMP segment). All pixels are stored as palette indices that need to be resolved on load. + +Background pixels are [RLE](#run-length-encoding)-compressed, so all pixels referring to palette index zero must be decompressed first. -This most basic variant only supports BMP sprites. It's used in [Arcturus](/arcturus), but not in any known version of the RO client. +## References + +Multiple open-source SPR decoders exist: -| Field | Offset | Length | Type | Description | -| :----------------: | :------: | :------: | :------: | :---------------------------------------------------------------------: | -| `Header` | 0 | 2 | `string` | `"SP"` as an ASCII-encoded, fixed-size string | -| `MinorVersion` | 2 | 1 | `byte` | Versioning information | -| `MajorVersion` | 3 | 1 | `byte` | Versioning information | -| `BitmapImageCount` | 4 | 2 | `ushort` | How many images are stored in the BMP segment | -| `BitmapSprites` | 6 | variable | `array` | Indexed-color sprite images; pixels are stored as palette indices | -| `ColorPalette` | variable | 1024 | `array` | RGBA pixel colors (`byte` values); always stored at the end of the file | +- [GPL-licensed implementation in JavaScript (RoBrowser)](https://github.com/MrAntares/roBrowserLegacy/blob/master/src/Loaders/Sprite.js) +- [MIT-licensed implementation in Rust (Korangar)](https://github.com/vE5li/korangar/blob/main/src/loaders/sprite/mod.rs) +- [MPL-licensed implementation in LuaJIT (RagLite SDK)](https://github.com/RagnarokResearchLab/RagLite/blob/main/Core/FileFormats/RagnarokSPR.lua) -#### Bitmap Sprites - -This repeating structure contains the raw pixel data in the form of references to palette entries that need to be resolved. - -| Field | Offset | Length | Type | Description | -| :--------------: | :----: | :------: | :-----: | :----------------------------------------------------: | -| `ImageWidth` | 0 | 2 | `short` | The width of the sprite image, given in pixels | -| `ImageHeight` | 2 | 2 | `short` | The height of the sprite image, given in pixels | -| `PaletteIndices` | 4 | variable | `array` | Array of indexed-color palette indices (`byte` values) | - -A size of `-1, -1` (`FF FF FF FF`) indicates an invalid image, which consists of a single pixel that can (probably) be discarded. - -### Version 2.0 - -This version adds the ability to store truecolor images (RGBA pixels with an alpha channel). It appears in RO and Arcturus. - -| Field | Offset | Length | Type | Description | -| :-------------------: | :------: | :------: | :------: | :---------------------------------------------------------------------: | -| `Header` | 0 | 2 | `string` | `"SP"` as an ASCII-encoded, fixed-size string | -| `MinorVersion` | 2 | 1 | `byte` | Versioning information | -| `MajorVersion` | 3 | 1 | `byte` | Versioning information | -| `BitmapImageCount` | 4 | 2 | `ushort` | How many images are stored in the BMP segment | -| `TruecolorImageCount` | 6 | 2 | `ushort` | How many images are stored in the TGA segment | -| `BitmapSprites` | 8 | variable | `array` | Indexed-color sprite images; pixels are stored as palette indices | -| `TruecolorSprites` | variable | variable | `array` | Truecolor sprite images; pixels are stored raw (in order ABGR) | -| `ColorPalette` | variable | 1024 | `array` | RGBA pixel colors (`byte` values); always stored at the end of the file | - -#### Truecolor Sprites - -This repeating structure contains the raw pixel data in an uncompressed form. - -| Field | Offset | Length | Type | Description | -| :-----------: | :----: | :------: | :-----: | :---------------------------------------------: | -| `ImageWidth` | 0 | 2 | `short` | The width of the sprite image, given in pixels | -| `ImageHeight` | 2 | 4 | `short` | The height of the sprite image, given in pixels | -| `PixelBuffer` | 6 | variable | `array` | Array of raw ABGR image data (`byte` values) | - -### Version 2.1 - -This version adds compression (via [RLE](#run-length-encoding)) for images in the BMP segment of the file. It's used in all modern RO clients. - -#### Compressed Bitmap Sprites - -The only difference here is that runs of zero palette indices (i.e., multiple background pixels) are RLE-compressed. - -| Field | Offset | Length | Type | Description | -| :------------------------: | :----: | :------: | :------: | :----------------------------------------------------------: | -| `ImageWidth` | 0 | 2 | `short` | The width of the sprite image, given in pixels | -| `ImageHeight` | 2 | 2 | `short` | The height of the sprite image, given in pixels | -| `CompressedBufferSize` | 4 | 2 | `ushort` | How many bytes to feed into the RLE decompressor | -| `CompressedPaletteIndices` | 6 | variable | `array` | RLE-compressed indexed-color palette indices (`byte` values) | - -The size of the decompressed image is still `ImageWidth * ImageHeight`, but you must read `CompressedBufferSize` bytes only. +This list only includes actively-maintained versions; [various other community projects](/community-projects) may also be of interest.