ResourceSizeTable.product.rsizetable: Difference between revisions

From ZeldaMods (Breath of the Wild)
Jump to navigation Jump to search
imported>Leoetlino
m (Reverted edits by BravelyPeculiar (talk) to last revision by Leoetlino)
imported>Leoetlino
No edit summary
 
(4 intermediate revisions by the same user not shown)
Line 8: Line 8:
<syntaxhighlight lang="c++">
<syntaxhighlight lang="c++">
struct RstbHeader {
struct RstbHeader {
   u32 magic;           // 'RSTB'
   char magic[4];       // 'RSTB'
   u32 crc32TableSize;  // number of entries - can be 0 to indicate there is no crc32 table
   u32 crc32TableSize;  // number of entries - can be 0 to indicate there is no crc32 table
   u32 nameTableSize;  // number of entries - can be 0 to indicate there is no name table
   u32 nameTableSize;  // number of entries - can be 0 to indicate there is no name table
Line 56: Line 56:
* VfxResourceMgr, when loading Effect/%s.esetlist files: must not be zero.
* VfxResourceMgr, when loading Effect/%s.esetlist files: must not be zero.
* bfres loading code at 0x7100FE3978 (v1.5.0): unclear, but must not be zero. It appears to check whether the file size listed in the RSTB is larger than the heap size.
* bfres loading code at 0x7100FE3978 (v1.5.0): unclear, but must not be zero. It appears to check whether the file size listed in the RSTB is larger than the heap size.
* res::ResourceMgrTask::getHeapSizeForResLoad (0x710120BDE0 in v1.5.0): called during resource load.<syntaxhighlight lang="c++">
* res::ResourceMgrTask::getHeapSizeForResLoad (0x710120BDE0 in v1.5.0): called during resource load.
<source lang="c++">
constant = 0x128 + 0x40;
constant = 0x128 + 0x40;
if (auto* entry_factory = dynamic_cast<res::EntryFactoryBase*>(factory))
if (auto* entry_factory = dynamic_cast<res::EntryFactoryBase*>(factory))
Line 68: Line 69:
else
else
   out->readHeapSize = (unsigned int)(float)(loadDataAlignment + totalSize + sizeof(void*));
   out->readHeapSize = (unsigned int)(float)(loadDataAlignment + totalSize + sizeof(void*));
</syntaxhighlight>
</source>
* 0x7100FE1630 (v1.5.0): unclear. If the file is loaded by the resource memory or loading thread, or if the file size listed in the RSTB is larger than a TempResourceLoader field, the game prints: "Texture archive size: %u MB" (translated from Japanese).
* 0x7100FE1630 (v1.5.0): unclear. If the file is loaded by the resource memory or loading thread, or if the file size listed in the RSTB is larger than a TempResourceLoader field, the game prints: "Texture archive size: %u MB" (translated from Japanese).
== Editing ==
The resource size table must be edited when making game files larger than they originally were, in order to avoid crashes.
=== Tools ===
{{tool table|category=Tools (RSTB)}}


[[Category:Content (BotW)]]
[[Category:Content (BotW)]]
[[Category:Content (BotW, product)]]
[[Category:File formats]]
[[Category:File formats]]

Latest revision as of 22:36, 27 November 2019

This resource is found in the unpacked content files.

Its canonical resource path is "System/Resource/ResourceSizeTable.product.rsizetable".

ResourceSizeTable.product.rsizetable is the file where the resource size table is stored.

Structure

Sections are listed in the order they appear in the file.

Header (optional)

struct RstbHeader {
  char magic[4];       // 'RSTB'
  u32 crc32TableSize;  // number of entries - can be 0 to indicate there is no crc32 table
  u32 nameTableSize;   // number of entries - can be 0 to indicate there is no name table
}; // sizeof() = 12

If the header is missing or if the magic is not correct, the game will assume there is simply no header. In that case, the game will use the size of the RSTB file, divide it by 8 to get the number of crc32 table entries and assume the whole file is a crc32 table.  

CRC32 table (optional)

This is a mapping of CRC32 values to resource sizes. The table must be sorted; otherwise the game will not be able to search for entries properly.

struct RstbCrc32TableEntry {
  u32 crc32;
  u32 size;
};  // sizeof() = 8

Name table (optional)

This is a mapping of resource paths (strings) to resource sizes. This table is optional and is used whenever there would be conflicts in the crc32 table. Only usable if there is a RSTB header.

struct RstbCrc32NameEntry {
  char name[128];
  u32 size;
};  // sizeof() = 132

Game usage

The table is loaded very early in the app init process by ResourceInfoContainer (part of res::ResourceMgrTask) when the resource task starts and queried by the resource system and several other subsystems afterwards.

Lookup logic

ResourceInfoContainer::getResourceSize (non official name) starts by computing the CRC32 for the resource name/path.

Note: Resources that are explicitly loaded from the add-on content file device will have Aoc/0010/ prepended to their resource path on Switch and Wii U as explained in the resource system article.

If a CRC32 table is present, the game will perform a binary search to find an entry for the calculated hash. If an entry is found, entry.size is returned.

Otherwise, if a name table is present, the game will go down the table until an entry that matches the specified resource name is found. If an entry is found, entry.size is returned.

Otherwise, the game returns 0.

Checks

The RSTB is queried by several subsystems:

  • TipsMgr and EventResource use it only to check if the file they want to load exists (by checking if ret != 0).
  • EffectResource, when loading Effect/Game.esetlist: must not be zero.
  • VfxResourceMgr, when loading Effect/%s.esetlist files: must not be zero.
  • bfres loading code at 0x7100FE3978 (v1.5.0): unclear, but must not be zero. It appears to check whether the file size listed in the RSTB is larger than the heap size.
  • res::ResourceMgrTask::getHeapSizeForResLoad (0x710120BDE0 in v1.5.0): called during resource load.
constant = 0x128 + 0x40;
if (auto* entry_factory = dynamic_cast<res::EntryFactoryBase*>(factory))
  resSize2 = entry_factory->getResourceSize(param->factory) + constant;
else
  resSize2 = sizeof(sead::DirectResource) + constant; // 0x20 + 0x168 = 0x188

totalSize = in->allocSize + resSize2;  // in this branch, in->allocSize seems to be always zero...
if (totalSize <= sizeInTable)
  out->readHeapSize = loadDataAlignment + sizeInTable + sizeof(void*);
else
  out->readHeapSize = (unsigned int)(float)(loadDataAlignment + totalSize + sizeof(void*));
  • 0x7100FE1630 (v1.5.0): unclear. If the file is loaded by the resource memory or loading thread, or if the file size listed in the RSTB is larger than a TempResourceLoader field, the game prints: "Texture archive size: %u MB" (translated from Japanese).

Editing

The resource size table must be edited when making game files larger than they originally were, in order to avoid crashes.

Tools

Tool Cross-platform Setup Known issues
rstb Yes

Install the rstb package.[CLI help]

  • Size calculation for complex resources: rstb is currently unable to calculate file sizes for complex resource classes (see Resource system for more information). The CLI will suggest deleting entries if it detects that this is the case.
Wild Bits Yes
  1. Ensure you have a 64 bit version of Python 3.7+ before continuing. Windows users must also install the latest x64 Visual C++ redistributable. You will not be able to install or launch Wild Bits otherwise. See Help:Setting_up_tools.
  2. (Optional) For best results on Windows, install cefpython3. [CLI help]
  3. Install the wildbits package. [CLI help]

On some system configurations, launching with wildbits doesn't work and you must use python -m wildbits instead.

Switch Toolbox No
  • Simply download the latest compiled release from GitHub, unzip, and launch the exe. Note that the latest release has an old date, but it is current, as it automatically rebuilds with each commit.