Resource system: Difference between revisions

no edit summary
imported>Leoetlino
No edit summary
imported>Leoetlino
No edit summary
 
(11 intermediate revisions by 3 users not shown)
Line 1: Line 1:
In ''Breath of the Wild'', the '''resource system''' is a subsystem that is responsible for managing resources, i.e. content files. It is composed of [[ResourceMgrTask]], [[ResourceSystem]] and a few ancillary classes (such as "resource binders" and "handles").
In ''Breath of the Wild'', the '''resource system''' is a subsystem that is responsible for managing resources, i.e. content files. It is composed of [[ResourceMgrTask]], [[ResourceSystem]] and a few ancillary classes (such as "resource binders" and "handles").
BotW's resource system is also used in ''[[wikipedia:Animal Crossing: New Horizons|Animal Crossing: New Horizons]]'' and called "ares" or "ARes".


== Concepts ==
== Concepts ==
Line 21: Line 23:


Note that:
Note that:
* For ResourceLoadArg3 (used in model/bfres related code), the factory is hardcoded to be the ResourceBase factory.
* For ResourceLoadArg3 (used in model/bfres related code), the factory is hardcoded to be the ResourceBase factory.
* For ResourceLoadArg2 (used for actor resources and physics stuff) and ResourceLoadArg (everything else), the factory is determined from the file extension.
* For ResourceLoadArg2 (used for actor resources and physics stuff) and ResourceLoadArg (everything else), the factory is determined from the file extension.
Line 33: Line 36:


Exceptions: bfevfl, bcamanim and barslist are always loaded uncompressed<ref>See 0x710120A9F4 in Switch 1.5.0</ref>.
Exceptions: bfevfl, bcamanim and barslist are always loaded uncompressed<ref>See 0x710120A9F4 in Switch 1.5.0</ref>.
'''Warning''': This behaviour can be overridden by passing some flags to the resource load functions.


=== Archives ===
=== Archives ===
The resource system can be configured to try loading from an [[SARC]] archive first.
The resource system can be configured to try loading from an [[SARC]] archive first.


To load from an archive, the global resource pack pointer (<code>res::ResourceMgrTask::sInstance->packRes</code> @ this+0x9c06f0 in Switch 1.5.0) must be set to an archive resource handle. Files in the archive can then be accessed as if they were at the root of the romfs/content partition. For example, if <code>EventFlow/Test.bfevfl</code> is a file in <code>Pack/TitleBG.pack</code>, the path that should be used for loading is <code>EventFlow/Test.bfevfl</code>, not <code>Pack/TitleBG.pack/EventFlow/Test.bfevfl</code>.
To load from an archive, a pointer to the archive resource handle should be set in <code>ResourceLoadArg::packRes</code> @ 0x58. If it is null, and if ResourceMgrTask's flag 2 is not set<ref>0x71012087EC</ref>, packRes will automatically be set to the global resource pack pointer (<code>res::ResourceMgrTask::sInstance->packRes</code> @ this+0x9c06f0 in Switch 1.5.0). Files in the archive can then be accessed as if they were at the root of the romfs/content partition. For example, if <code>EventFlow/Test.bfevfl</code> is a file in <code>Pack/TitleBG.pack</code>, the path that is for loading is <code>EventFlow/Test.bfevfl</code>, not <code>Pack/TitleBG.pack/EventFlow/Test.bfevfl</code>.


Calls to any of the resource loading functions will automatically check whether the specified resource exists in the archive. If it does exist, it will be loaded from the archive. If the file cannot be found in the archive, the game will ignore the active resource pack and load from the usual file device.
Calls to any of the resource loading functions will automatically check whether the specified resource exists in the archive. If it does exist, it will be loaded from the archive. If the file cannot be found in the archive, the game will ignore the active resource pack and load from the usual file device.
Line 52: Line 57:
==== Cases where the AoC file device is used ====
==== Cases where the AoC file device is used ====
If the AoC version is >= 0x200 (in most cases) or >= 0x300 (for DLC Pack 2 content), and if the canonical resource name (without the <code>Aoc/0010/</code> prefix) matches any of the below patterns:
If the AoC version is >= 0x200 (in most cases) or >= 0x300 (for DLC Pack 2 content), and if the canonical resource name (without the <code>Aoc/0010/</code> prefix) matches any of the below patterns:
* <code>Terrain/A/AocField*</code>
* <code>Terrain/A/AocField*</code>
* Any dungeon pack (<code>Pack/%s.pack</code>): shrines, divine beasts, Final Trial (for shrines, the dungeon number must be > 119)
* Any dungeon pack (<code>Pack/%s.pack</code>): shrines, divine beasts, Final Trial (for shrines, the dungeon number must be > 119)
Line 70: Line 76:
* <code>Voice/*/Stream_Demo6*/*.bfstm</code>
* <code>Voice/*/Stream_Demo6*/*.bfstm</code>
* <code>System/AocVersion.txt</code>
* <code>System/AocVersion.txt</code>
There are two other situations where the <code>Aoc/0010/</code> prefix is supposed to be prepended:
There are two other situations where the <code>Aoc/0010/</code> prefix is supposed to be prepended:
* If the load file device is set to the <code>Pack/AocMainField.pack</code> archive file device explicitly
* If the load file device is set to the <code>Pack/AocMainField.pack</code> archive file device explicitly
* If the global resource pack is an AoC dungeon pack
* If the global resource pack is an AoC dungeon pack
However, the first case is irrelevant because that archive only contains Map/MainField/ (a case that is already handled by the path checks) and the second check appears to never pass.
However, the first case is irrelevant because that archive only contains Map/MainField/ (a case that is already handled by the path checks) and the second check appears to never pass.


Line 82: Line 91:
=== Heap size ===
=== Heap size ===
The size of the resource loading heap the system allocates every time a resource is loaded depends on the value that is listed in the [[#Resource size table]] (RSTB). If lookup fails, the game will fall back to the following formula (Switch on 1.5.0):
The size of the resource loading heap the system allocates every time a resource is loaded depends on the value that is listed in the [[#Resource size table]] (RSTB). If lookup fails, the game will fall back to the following formula (Switch on 1.5.0):
<syntaxhighlight lang="C++">
<syntaxhighlight lang="C++">
alignedFileSize = (actualFileSize + 31) & -32;
alignedFileSize = (actualFileSize + 31) & -32;
Line 93: Line 101:
+ 0x750
+ 0x750
</syntaxhighlight>
</syntaxhighlight>
'''Warning''': Failure to add entries to the RSTB for a large number of resources may result in system instability. The purpose of this fallback appears to be to allow loading resources during development even without an entry in the resource size table. As such, the system will often allocate way more memory than needed to account for any dynamic allocation that the resource class may do.  
'''Warning''': Failure to add entries to the RSTB for a large number of resources may result in system instability. The purpose of this fallback appears to be to allow loading resources during development even without an entry in the resource size table. As such, the system will often allocate way more memory than needed to account for any dynamic allocation that the resource class may do.  


Line 105: Line 112:


==== Resource size calculation ====
==== Resource size calculation ====
It is currently unknown how Nintendo has determined the values in the RSTB. However by REing the resource system it was found that the resource loading heap is, for most factories, only used to allocate the file loading buffer (which is as large as the file to load), the C++ resource class, extra allocations depending on the resource class and some extra bytes to ensure data is aligned correctly in memory.
According to an internal source, Nintendo automatically generates the Resource Size Table using development builds of the game that are believed to contain instrumentation code (perhaps in the [[Patrol]] component) This is consistent with the fact that the RSTB asset has the "product" suffix in its name, which is used for machine-generated files, and also with the fact that a similar solution is used for actor instance heap size measurement.
 
The resource loading heap is, for most factories, only used to allocate the file loading buffer (which is as large as the file to load), the C++ resource class, extra allocations depending on the resource class and some extra bytes to ensure data is aligned correctly in memory.


Therefore, the following formula should give a correct size value for all resource types:
Therefore, the following formula should give a correct size value for all resource types:
  (size rounded up to multiple of 32) + CONSTANT + sizeof(ResourceClass) + PARSE_SIZE
  (size rounded up to multiple of 32) + CONSTANT + sizeof(ResourceClass) + PARSE_SIZE
CONSTANT is 0x168 in the Switch version and 0xe4 on Wii U.
CONSTANT is 0x168 in the Switch version and 0xe4 on Wii U.


Line 116: Line 123:


[[Category:Internals]]
[[Category:Internals]]
[[Category:Subsystems (BotW)]]
<references />
Anonymous user