TACT: Difference between revisions

From wowdev
Jump to navigation Jump to search
m (style → class wikitable)
 
(181 intermediate revisions by 13 users not shown)
Line 1: Line 1:
<div style="float: right; margin-left: 5px;">__TOC__</div>
TACT ('''T'''rusted '''A'''pplication '''C'''ontent '''T'''ransfer) is the name of the content transfer part of [[NGDP]]. It is often used to install games that use [[CASC]] filesystems, but also supports non-CASC based products.
TACT ('''T'''rusted '''A'''pplication '''C'''ontent '''T'''ransfer) is the name of the content transfer part of [[NGDP]]. It is often used to install games that use [[CASC]] filesystems, but also supports non-CASC based products.


=Product Information=
=Product Information=
Upon initial release, TACT used regular HTTP to retrieve information for its products. In early 2018, Blizzard started working on a new system that has superseded this. More information about the new system can be found on the [[Ribbit]] page. As of March/April 2019 Ribbit is now the primary system for retrieving version information for most products. HTTP version information has already diverged in some places and should probably only be used as a fallback.
Upon initial release, TACT used regular HTTP to retrieve information for its products. In early 2018, Blizzard started working on a new system that has superseded this. More information about the new system can be found on the [[Ribbit]] page.  
 
As of March/April 2019 Ribbit is now the primary system for retrieving version information for most products. HTTP version information has already diverged in some places and should probably only be used as a fallback.
 
As of 8.3.7 and 9.0.1 the WoW client uses Ribbit as the primary way of retrieving version information as well.


==HTTP URLs==
==HTTP URLs==
{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
''Note: These are now just wrappers over [[Ribbit#V2|Ribbit V2]].''
{| border="1" cellpadding="2" class="wikitable"
! style="width: 200px" | URL
! style="width: 200px" | URL
! style="width: 550px" | Description
! style="width: 550px" | Description
Line 25: Line 31:
The following products are known to have existed at one point. When this page refers to a product it refers to the TACT Product. Agent UIDs are specific to [[Agent]].
The following products are known to have existed at one point. When this page refers to a product it refers to the TACT Product. Agent UIDs are specific to [[Agent]].


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|Non-Games
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Non-Games
|-
|-
! width="90" | TACT Product
! width="90" | TACT Product
Line 52: Line 58:
Most games have multiple products. Tables for these are collapsed by default to not affect page length. Click Expand to see all known products for a game.  
Most games have multiple products. Tables for these are collapsed by default to not affect page length. Click Expand to see all known products for a game.  


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|Diablo III  
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Blizzard Arcade Collection
|-
! width="90" | TACT Product
! width="90" | Agent Product
! width="250" | Description
! width="200" | Status
|-
| rtro || rtro || Blizzard Arcade Collection Retail || style="color: green;" | Active
|-
| rtrodev || rtro_dev || Blizzard Arcade Collection Dev ||
|}
 
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Diablo Immortal (PC)
|-
! width="90" | TACT Product
! width="90" | Agent Product
! width="250" | Description
! width="200" | Status
|-
| anbs || anbs || Diablo Immortal Retail ||
|-
| anbsdev || anbs_dev || Diablo Immortal Dev || style="color: blue;" | Active (encrypted)
|}
 
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Diablo II: Resurrected
|-
! width="90" | TACT Product
! width="90" | Agent Product
! width="250" | Description
! width="200" | Status
|-
| osi || || Diablo II: Resurrected Retail || style="color: green;" | Active
|-
| osib || osi_beta || Diablo II: Resurrected Beta || style="color: green;" | Active
|-
| osia || osi_dev || Diablo II: Resurrected Alpha || style="color: blue;" | Active (encrypted)
|-
| osidev || osi_dev_2 || Diablo II: Resurrected Dev || style="color: blue;" | Active (encrypted)
|-
| osiv1 || osi_vendor_1 || Diablo II: Resurrected Vendor 1 || style="color: blue;" | Active (encrypted)
|-
| osiv2 || osi_vendor_2 || Diablo II: Resurrected Vendor 2 ||
|-
| osiv3 || osi_vendor_3 || Diablo II: Resurrected Vendor 3 || style="color: blue;" | Active (encrypted)
|-
| osiv4 || osi_vendor_4 || Diablo II: Resurrected Vendor 4 ||
|-
| osiv5 || osi_vendor_5 || Diablo II: Resurrected Vendor 5 ||
|-
| osiv6 || osi_vendor_6 || Diablo II: Resurrected Vendor 6 ||
|}
 
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Diablo III  
|-
|-
! width="90" | TACT Product
! width="90" | TACT Product
Line 70: Line 131:
| d3t || diablo3_ptr''(_locale)'' || Diablo 3 Test || style="color: green;" | Active
| d3t || diablo3_ptr''(_locale)'' || Diablo 3 Test || style="color: green;" | Active
|}
|}
 
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Diablo IV (aka Fenris)
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|Destiny 2
|-
|-
! width="90" | TACT Product
! width="90" | TACT Product
Line 79: Line 139:
! width="200" | Status
! width="200" | Status
|-
|-
| dst2 || destiny_2 || Destiny 2 || style="color: green;" | Active
| fenris || fenris || Diablo IV Retail || style="color: green;" | Active
|-
| fenrisb || fenris_beta || Diablo IV Beta || style="color: green;" | Active  
|-
|-
| dst2a || destiny2_alpha || Destiny 2 Alpha || style="color: blue;" | Active (encrypted)
| fenrise || fenris_event || Diablo IV Pre-Launch || style="color: red;" | Disabled (encrypted)
|-
|-
| dst2dev || destiny2_takehome || Destiny 2 "takehome" development || style="color: orange;" | Partial (encrypted?)
| fenrisdev || fenris_dev || Diablo IV Dev || style="color: red;" | Disabled (encrypted)
|-
|-
| dst2e1 || destiny2_event || Destiny 2 Event || Active; probably 1..9
| fenrisvendor || fenris_vendor || Diablo IV Vendor || style="color: blue;" | Active (encrypted), Season 1
|-
|-
| dst2igr || || Destiny 2 Internet Game Room || style="color: green;" | Active
| fenrisvendor2 || fenris_vendor2 || Diablo IV Vendor 2 || style="color: blue;" | Active (encrypted)
|-
|-
| dst2t || destiny2_ptr || Destiny 2 Public Test || style="color: green;" | Active
| fenrisvendor3 || fenris_vendor3 || Diablo IV Vendor 3 || style="color: blue;" | Active (encrypted), Season 2
|}
|}


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|Heroes of the Storm
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Heroes of the Storm
|-
|-
! width="90" | TACT Product
! width="90" | TACT Product
Line 111: Line 173:
|}
|}


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|Hearthstone
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Hearthstone
|-
|-
| hsb || hs_beta || Hearthstone Retail || style="color: green;" | Active
| hsb || hs_beta || Hearthstone Retail || style="color: green;" | Active
Line 122: Line 184:
|}
|}


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|Overwatch (aka Prometheus)
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Overwatch (aka Prometheus)
|-
|-
! width="90" | TACT Product
! width="90" | TACT Product
Line 150: Line 212:
| proc3 || prometheus_tournament3 || Overwatch Tournament (Dev) ||  
| proc3 || prometheus_tournament3 || Overwatch Tournament (Dev) ||  
|-
|-
| procr || prometheus_tournament_viewer || Overwatch Tournament Viewer ||  
| procr || prometheus_tournament_viewer || Overwatch League Stage 3 ||
|-
| procr2 || prometheus_tournament_viewer_2 || Overwatch League Stage 2 ||  
|-
|-
| prodev || prometheus_dev || Overwatch Dev || style="color: blue;" | Active (encrypted)
| prodev || prometheus_dev || Overwatch Dev || style="color: blue;" | Active (encrypted)
Line 158: Line 222:
| prot || prometheus_test || Overwatch Test || style="color: green;" | Active
| prot || prometheus_test || Overwatch Test || style="color: green;" | Active
|-
|-
| prov || prometheus_vendor || Overwatch Vendor || style="color: green;" | Active
| prov || prometheus_vendor || Overwatch Vendor || style="color: blue;" | Active (encrypted)
|-
|-
| proms || prometheus_viewer || Overwatch World Cup Viewer || style="color: orange;"| Partial
| proms || prometheus_viewer || Overwatch World Cup Viewer || style="color: orange;"| Partial
|}
|}


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|StarCraft 1
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|StarCraft 1
|-
|-
! width="90" | TACT Product
! width="90" | TACT Product
Line 179: Line 243:
|}
|}


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|StarCraft II
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|StarCraft II
|-
|-
! width="90" | TACT Product
! width="90" | TACT Product
Line 196: Line 260:
|}
|}


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|Call of Duty
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Warcraft III
|-
! width="90" | TACT Product
! width="90" | Agent Product
! width="250" | Description
! width="200" | Status
|-
| viper || viper || Call of Duty Black Ops 4 || style="color: green;" | Active
|-
| viperdev || viper_alpha || Call of Duty Black Ops 4 - Alpha || style="color: blue;" | Active (encrypted)
|-
| viperv1 || viper_vendor || Call of Duty Black Ops 4 Vendor ||
|-
| odin || || Call of Duty: Modern Warfare ||
|-
| odindev || odin_dev || Call of Duty: Modern Warfare Dev || style="color: blue;" | Active (encrypted)
|}
 
{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|Warcraft III
|-
|-
! width="90" | TACT Product
! width="90" | TACT Product
Line 228: Line 273:
|-
|-
| war3 || || Warcraft III (old) || style="color: orange;"| Partial
| war3 || || Warcraft III (old) || style="color: orange;"| Partial
|-
| w3b || w3_beta || Warcraft III: Reforged Beta ||
|}
|}


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black" class="mw-collapsible mw-collapsed wikitable"
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="background:grey; color:white; border-bottom:1.5px solid black; width: 668px;" colspan="4"|World of Warcraft
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|World of Warcraft
|-
|-
! width="90" | TACT Product
! width="90" | TACT Product
Line 242: Line 289:
| wow_beta || wow_beta || World of Warcraft Alpha/Beta || style="color: green; | Active
| wow_beta || wow_beta || World of Warcraft Alpha/Beta || style="color: green; | Active
|-
|-
| wow_classic || wow_test || World of Warcraft Classic || style="color: green; | Active
| wow_classic || wow_test, later wow_classic || World of Warcraft Classic (BCC) || style="color: green; | Active
|-
|-
| wow_classic_beta || wow_classic_beta || World of Warcraft Classic Beta || style="color: green; | Active
| wow_classic_beta || wow_classic_beta || World of Warcraft Classic (BCC) Beta || style="color: green; | Active
|-  
|-  
| wowdev || || World of Warcraft Dev || style="color: blue;" | Active (encrypted)
| wow_classic_ptr || wow_classic_ptr || World of Warcraft Classic (BCC) Test || style="color: green; | Active
|-
| wow_classic_era || wow_classic_era || World of Warcraft Classic (Vanilla) || style="color: green; | Active
|-
| wow_classic_era_beta || wow_classic_era_beta || World of Warcraft Classic (Vanilla) Beta || style="color: green; | Active
|-
| wow_classic_era_ptr || wow_classic_era_ptr || World of Warcraft Classic (Vanilla) Test || style="color: green; | Active
|-
| wowdev || wow_alpha || World of Warcraft Dev || style="color: blue;" | Active (encrypted)
|-
|-
| wowdemo || || World of Warcraft (Classic) Demo || style="color: blue;" | Active (encrypted)
| wowdemo || || World of Warcraft (Classic) Demo || style="color: blue;" | Active (encrypted)
Line 263: Line 318:
|-
|-
| wowz || wow_submission || World of Warcraft Submission (previously Vendor) || style="color: green; | Active
| wowz || wow_submission || World of Warcraft Submission (previously Vendor) || style="color: green; | Active
|}
===Non-Blizzard===
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Call of Duty
|-
! width="90" | TACT Product
! width="90" | Agent Product
! width="250" | Description
! width="200" | Status
|-
| viper || viper || Call of Duty: Black Ops 4 || style="color: green;" | Active
|-
| viperdev || viper_alpha || Call of Duty: Black Ops 4 - Alpha || style="color: blue;" | Active (encrypted)
|-
| viperv1 || viper_vendor || Call of Duty: Black Ops 4 Vendor ||
|-
| odin || odin_placeholder → odin || Call of Duty: Modern Warfare ||
|-
| odindev || odin_dev || Call of Duty: Modern Warfare Dev || style="color: blue;" | Active (encrypted)
|-
| odinv1 || odin_vendor1 || Call of Duty: Modern Warfare Vendor 4 ||
|-
| odinv2 || odin_vendor2 || Call of Duty: Modern Warfare Vendor 4 ||
|-
| odinv3 || odin_vendor3 || Call of Duty: Modern Warfare Vendor 4 ||
|-
| odinv4 || odin_vendor4 || Call of Duty: Modern Warfare Vendor 4 ||
|-
| odina || odin_alpha || another cod mw dev channel ||
|-
| odinb || odin_beta || public (paid) beta ||
|-
| odine || odin_event || tournament/event ||
|-
| lazr || lazarus || Call of Duty: MW2CR (Campaign Remastered) ||
|-
| lazrdev || lazarus_dev || Call of Duty: MW2CR Dev ||
|-
| lazrv1 || lazarus_vendor_1 || Call of Duty: MW2CR Vendor 1 ||
|-
| lazrv2 || lazarus_vendor_2 || Call of Duty: MW2CR Vendor 2 ||
|-
| zeus || zeus || Call of Duty: Black Ops Cold War || style="color: green;" | Active
|-
| fore || fore || Call of Duty: Vanguard || style="color: green;" | Active
|-
| foreb || foreb || Call of Duty: Vanguard (Public Beta) || style="color: green;" | Active
|}
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Crash Bandicoot 4
|-
! width="90" | TACT Product
! width="90" | Agent Product
! width="250" | Description
! width="200" | Status
|-
| wlby || wlby || Crash Bandicoot 4 ||
|-
| wlbydev || wlby_dev || Crash Bandicoot 4 Developing || style="color: blue;" | Active (encrypted)
|-
| wlbyv[1-6] || wlby_vendor_[1-6] || Crash Bandicoot 4 for Vendors || style="color: blue;" | Active (encrypted)
|}
{| border="1" cellpadding="2" class="mw-collapsible mw-collapsed wikitable"
! style="border-bottom:1.5px solid black; width: 668px;" colspan="4"|Destiny 2
|-
! width="90" | TACT Product
! width="90" | Agent Product
! width="250" | Description
! width="200" | Status
|-
| dst2 || destiny_2 || Destiny 2 || style="color: green;" | Active
|-
| dst2a || destiny2_alpha || Destiny 2 Alpha || style="color: blue;" | Active (encrypted)
|-
| dst2dev || destiny2_takehome || Destiny 2 "takehome" development || style="color: orange;" | Partial (encrypted?)
|-
| dst2e1 || destiny2_event || Destiny 2 Event || Active; probably 1..9
|-
| dst2igr || || Destiny 2 Internet Game Room || style="color: green;" | Active
|-
| dst2t || destiny2_ptr || Destiny 2 Public Test || style="color: green;" | Active
|}
|}


=Glossary=
=Glossary=
This page uses many terms. Here's an overview of stuff you need to know to be able to understand most of the explanations below.  
This page uses many terms. Here's an overview of stuff you need to know to be able to understand most of the explanations below.  
{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! style="width: 100px"| Term
! style="width: 100px"| Term
! style="width: 550px" | Description
! style="width: 550px" | Description
Line 295: Line 435:


Product configs referred to in the versions file are generally saved in <tt>tpr/configs</tt> for all games, but to be sure this path should be found by parsing the cdns file for the product in question.
Product configs referred to in the versions file are generally saved in <tt>tpr/configs</tt> for all games, but to be sure this path should be found by parsing the cdns file for the product in question.
It is intended behavior for some files, even recent ones, to not be available on all CDNs, you should try a different CDN from the list of CDNs in those cases. For example an archive might not be available on us.cdn.blizzard.com but instead be available on level3.blizzard.com
Some CDNs also implement rate limiting, they will return HTTP code 429 if you are exceeding requests. Exact request limits are unknown and seem to vary per region/time.
==Config Files==
==Config Files==


Line 304: Line 448:
What follows is a table for all known variables that have been seen in a buildconfig.
What follows is a table for all known variables that have been seen in a buildconfig.


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! width="140" | Value name
! width="140" | Value name
! width="650" | Description
! width="650" | Description
Line 310: Line 454:
| [[#Root|root]] || Content hash of the '''decoded''' root file, look this up in encoding to get the '''encoded''' hash.
| [[#Root|root]] || Content hash of the '''decoded''' root file, look this up in encoding to get the '''encoded''' hash.
|-
|-
| [[#Install|install]] || First key is the content hash of the '''decoded''' install file. Second key, if present, is the '''encoded''' hash; if absent, look up the content hash in encoding to get the encoded hash/CDN key.
| [[#Install_manifest|install]] || First key is the content hash of the '''decoded''' install file. Second key, if present, is the '''encoded''' hash; if absent, look up the content hash in encoding to get the encoded hash/CDN key.
|-
|-
| install-size || Install size(s) corresponding to the install hash(es). Absent in older WoW builds.
| install-size || Install size(s) corresponding to the install hash(es). Absent in older WoW builds.
|-
|-
| [[#Download|download]] || First key is the content hash of the '''decoded''' download file. Second key, if present, is the '''encoded''' hash; if absent, look up the content hash in encoding to get the encoded hash.
| [[#Download_manifest|download]] || First key is the content hash of the '''decoded''' download file. Second key, if present, is the '''encoded''' hash; if absent, look up the content hash in encoding to get the encoded hash.
|-
|-
| download-size || Download size(s) corresponding to the download hash(es). Absent in older WoW builds.
| download-size || Download size(s) corresponding to the download hash(es). Absent in older WoW builds.
|-
|-
| [[#Download Size|size]] || CKey and EKey of the download size file, respectively. Introduced in WoW build 27547.
| [[#Download_Size|size]] || CKey and EKey of the download size file, respectively. Introduced in WoW build 27547.
|-
|-
| size-size || Download size sizes corresponding to the download size keys.
| size-size || Download size sizes corresponding to the download size keys.
Line 328: Line 472:
| partial-priority-size || Unknown: always 0 if present. Present if partial-priority is present.
| partial-priority-size || Unknown: always 0 if present. Present if partial-priority is present.
|-
|-
| [[#Encoding|encoding]] || First key is the content hash of the '''decoded''' encoding file. Second key is the '''encoded''' hash. If either none or 1 is found, the game (at least Wow) switches to plain-data (?) . Seen in build 20173
| [[#Encoding_table|encoding]] || First key is the content hash of the '''decoded''' encoding file. Second key is the '''encoded''' hash. If either none or 1 is found, the game (at least Wow) switches to plain-data (?) . Seen in build 20173
|-
|-
| encoding-size || Encoding sizes corresponding to the encoding hashes.
| encoding-size || Encoding sizes corresponding to the encoding hashes.
Line 359: Line 503:
|-
|-
| build-uid || Optional? Program code (see Products)
| build-uid || Optional? Program code (see Products)
|-
| vfs-root || [[TVFS|VFS]] root
|-
| vfs-root-size || [[TVFS|VFS]] root size
|-
| vfs-i || [[TVFS|VFS]] manifest, where i is index.
|-
| vfs-i-size || [[TVFS|VFS]] manifest size, where i is index.
|}
|}


Line 364: Line 516:
Example file: <tt>http://blzddist1-a.akamaihd.net/tpr/wow/config/42/33/423364147752a596911aa1de2ff1f6a4</tt>
Example file: <tt>http://blzddist1-a.akamaihd.net/tpr/wow/config/42/33/423364147752a596911aa1de2ff1f6a4</tt>


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! width="140" | Value name
! width="140" | Value name
! width="650" | Description
! width="650" | Description
Line 389: Line 541:
===Patch Config===
===Patch Config===
Example file: <tt>http://blzddist1-a.akamaihd.net/tpr/wow/config/20/f0/20f0593dd1b9fdaeaa7a808f83d48f1d</tt>
Example file: <tt>http://blzddist1-a.akamaihd.net/tpr/wow/config/20/f0/20f0593dd1b9fdaeaa7a808f83d48f1d</tt>
This configuration file was added after all of the others. It first appeared in CASC v1 for Heroes of the Storm in August 2014. It then appeared in WoW for CASC v2 in build 19027 (October 10th, 2014).
This configuration file was added after all of the others. It first appeared in CASC v1 for Heroes of the Storm in August 2014. It then appeared in WoW for CASC v2 in build 19027 (October 10th, 2014).
The purpose of this file is to reduce redundant downloads. It achieves this by directing the system to download patch files to apply and update previously downloaded material.
The purpose of this file is to reduce redundant downloads. It achieves this by directing the system to download patch files to apply and update previously downloaded material.
The structure and purpose of all of the fields of this file requires further research.
The structure and purpose of all of the fields of this file requires further research.


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! width="140" | Value name
! width="140" | Value name
! width="650" | Description
! width="650" | Description
|-
|-
| patch-entry || Repeats 3 times with patch entries for install, download and encoding file. Builds using the partial-priority (not build-partial-priority) mechanism may additionally have a partial-priority entry.
| patch-entry || Repeats 4 times with patch entries for install, download, encoding and size file. Builds using the partial-priority (not build-partial-priority) mechanism may additionally have a partial-priority entry.
|-
|-
| patch || Patch manifest file
| patch || Patch manifest file
Line 415: Line 566:
<pre><old BLTE-encoding key> <old content size> <patch hash> <patch size></pre>
<pre><old BLTE-encoding key> <old content size> <patch hash> <patch size></pre>


This serves to pair old files to the patch needed to bring them up to date, as well as providing the information required to detect if the file is already up to date.
sorted by oldest build to newest. This serves to pair old files to the patch needed to bring them up to date, as well as providing the information required to detect if the file is already up to date.
 
These patches are stored externally to the [[#Patch]] file (which solely handles game asset patching) and are stored directly on Blizzard's CDN. These are raw ZBSDIFF1 blobs applied to the BLTE decoded contents of each file.
 
Example patch: <tt>https://blzddist1-a.akamaihd.net/tpr/wow/patch/0b/68/0b6829cdd07255fa57b6243b0eba2ee3</tt>


==Data Files==
==Data Files==
Line 424: Line 579:


==Patch Files==
==Patch Files==
[[#Patch]]


==Encoding table==
==Encoding table==
The encoding file maps content hashes <tt>C-Key</tt>s to encoded-file hashes <tt>E-Key</tt>s. In addition, there is information on how the files are [[BLTE]]-encoded by <tt>E-Spec</tt>s. Some {{Unverified|typos}} in the client refer to E key as O key.
The encoding file maps content hashes <tt>C-Key</tt>s to encoded-file hashes <tt>E-Key</tt>s. In addition, there is information on how the files are [[BLTE]]-encoded by <tt>E-Spec</tt>s.  


Blocks in this file are, in this order
Blocks in this file are, in this order
Line 470: Line 626:


In both cases, the entries in the lists have the same count, and semi-dynamic size, depending on <tt>header.hash_size_ckey</tt> and <tt>header.hash_size_ekey</tt>. Note that the page checksum size is fixed to MD5's 16 bytes. The position comments below assume the standard key size of 16 bytes.
In both cases, the entries in the lists have the same count, and semi-dynamic size, depending on <tt>header.hash_size_ckey</tt> and <tt>header.hash_size_ekey</tt>. Note that the page checksum size is fixed to MD5's 16 bytes. The position comments below assume the standard key size of 16 bytes.
'''Note''': As of 8.3, the entry count of both tables is no longer exactly the same.


  struct page_index_t {
  struct page_index_t {
Line 507: Line 665:
====Header Structure====
====Header Structure====
The file begins with a 10 byte header describing the number of tags and files listed. '''Structure names were invented by the author of this page.'''
The file begins with a 10 byte header describing the number of tags and files listed. '''Structure names were invented by the author of this page.'''
{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! width="80" | Offset (Hex)
! width="80" | Offset (Hex)
! width="70" | Type
! width="70" | Type
Line 527: Line 685:
After the header, an array with information about available tags follows. Each tag has a bitfield listing the files installed when the given tag is chosen.  
After the header, an array with information about available tags follows. Each tag has a bitfield listing the files installed when the given tag is chosen.  


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! width="70" | Type
! width="70" | Type
! width="90" | Name
! width="90" | Name
Line 542: Line 700:
The remainder of the file is populated by a list of files with their content hash, each a variable size (due to the strings). Structure names were invented by the author of this page.
The remainder of the file is populated by a list of files with their content hash, each a variable size (due to the strings). Structure names were invented by the author of this page.


{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! width="70" | Type
! width="70" | Type
! width="90" | Name
! width="90" | Name
Line 589: Line 747:


====Download Header====
====Download Header====
{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! width="120" | Type
! width="120" | Type
! width="150" | Name
! width="150" | Name
Line 608: Line 766:


====Download Entry====
====Download Entry====
{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! width="120" | Type
! width="120" | Type
! width="150" | Name
! width="150" | Name
Line 626: Line 784:


====Download Tag====
====Download Tag====
{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
{| border="1" cellpadding="2" class="wikitable"
! width="120" | Type
! width="120" | Type
! width="150" | Name
! width="150" | Name
Line 699: Line 857:
  struct Header
  struct Header
  {
  {
  char signature[2]; // "DS"
  char signature[2];     // "DS"
  uint8_t version;
  uint8_t version;       // only known: 1 (as of agent 6700)
  uint8_t ekeySize; // 9
  uint8_t ekeySize;     // 9, up to 23 possible, but agent 6700 hardcodes 9, so, uh.
  uint32_BE_t numFiles;
  uint32_BE_t numFiles;
  uint16_BE_t numTags;
  uint16_BE_t numTags;
Line 725: Line 883:


==Patch==
==Patch==
{| border="1" cellpadding="2" style="background:#FCFCFC; color:black"
 
 
{| border="1" cellpadding="2" class="wikitable"
! width="120" | Type
! width="120" | Type
! width="150" | Name
! width="150" | Name
Line 772: Line 932:
   uint8_t block_size_bits; // 12 <= block_size_bits <= 24. max block size == 2^block_size_bits
   uint8_t block_size_bits; // 12 <= block_size_bits <= 24. max block size == 2^block_size_bits
   uint16_BE_t block_count; // (file_key_size + 20) * entry_count + sizeof (PatchManifest_Header) < 0x10000
   uint16_BE_t block_count; // (file_key_size + 20) * entry_count + sizeof (PatchManifest_Header) < 0x10000
   uint8_t unk2; // flags
   uint8_t flags; // &1: plain-data mode manifest, &2: extended header
   
   
  #if encoding_information_apparently_added_after_18179
  #if encoding_information_apparently_added_after_18179
Line 805: Line 965:
       uint8_t patch_ekey[header.patch_key_size];
       uint8_t patch_ekey[header.patch_key_size];
       uint32_BE_t patch_size;
       uint32_BE_t patch_size;
       uint8_t unk; // some sort of patch index number. first entry seems to always be 1
       uint8_t patch_ordinal; // order of patch application, 1-based indexing
     } patches[num_patches];
     } patches[num_patches];
   } files[]; // count unspecified: read until the next file num_patches would be 0  
   } files[]; // count unspecified: read until the next file num_patches would be 0  
Line 814: Line 974:


=Product Specific=
=Product Specific=
In this section, the game/usage specific parts of CASC are describe. While CASC is a generic format, a lot of stuff is hardcoded, like hash sizes. Other parts are actually left up to the implementation, like root files or download tags.
In this section, the game/usage specific parts of CASC are described. While CASC is a generic format, a lot of stuff is hardcoded, like hash sizes. Other parts are actually left up to the implementation, like root files or download tags.


==World of Warcraft==
==World of Warcraft==
===Root===
===Root===
As of 8.2 there was changes to this format. The client currently parses backwards compatible. There are three changes:
As of 8.2 there was changes to this format. The client currently (last checked: 9.0.1) parses backwards compatible. There are three changes:
* The file is now chunked with the old content being in a MFST (ManiFeST) chuck.
* The file is now chunked with the old content being in a MFST (ManiFeST) chunk.
* blocks can be without name hashes and thus ID-only.  
* blocks can be without name hashes and thus ID-only.  
* the name and content hashes are no longer interleaved but two separate arrays
* the name and content hashes are no longer interleaved but two separate arrays
** In memory, the manifest is kept in a FDID → entry map, so when reverse engineering the parser one may think that fnv1a is relevant, but that’s merely the hashmap insert.  
** In memory, the manifest is kept in a FDID → entry map, so when reverse engineering the parser one may think that fnv1a is relevant, but that’s merely the hashmap insert.  
** To parse that variable format the client uses to pointers to chash/name and a stride (of 16 for key only and 24 for with name) rather than one for records. It also determines the name hash/key hash base pointers depending on format, allowing them to have one parse able to read all format versions.
** To parse that variable format the client uses two pointers to chash/name and a stride (of 16 for key only and 24 for with name) rather than one for records. It also determines the name hash/key hash base pointers depending on format, allowing them to have one parse able to read all format versions.
 
In 10.1.7.50893 3 ints were added to the header; header size, version and something that's probably padding.


  enum locale_flags : uint32_t {
  enum locale_flags : uint32_t {
Line 843: Line 1,005:
  };
  };
  enum content_flags : uint32_t {
  enum content_flags : uint32_t {
   LoadOnWindows =        0x8,            // macOS clients do not read block if flags & 0x108 != 0
  {{Unverified|Install}}            =        0x4,            // file is in install manifest
   LoadOnMacOS   =      0x10,            // windows clients do not read block if flags & 0x110 != 0
   LoadOnWindows       =        0x8,            // macOS clients do not read block if flags & 0x108 != 0
   LowViolence   =      0x80,
   LoadOnMacOS         =      0x10,            // windows clients do not read block if flags & 0x110 != 0
   {{Unverified|DoNotLoad}}   =      0x100,            // neither macOS nor windows clients read blocks with this flag set. {{Unverified|LoadOnMysteryPlatform}}?
  {{Unverified|x86_32}}            =      0x20,            // install manifest file only - load on 32 bit systems
   NoNameHash    = 0x10000000,
  {{Unverified|x86_64}}            =      0x40,            // install manifest file only - load on 64 bit systems
   Bundle       = 0x40000000,
   LowViolence         =      0x80,
   NoCompression = 0x80000000,
   {{Unverified|DoNotLoad}}         =      0x100,            // neither macOS nor windows clients read blocks with this flag set. {{Unverified|LoadOnMysteryPlatform}}?
  {{Unverified|UpdatePlugin}}      =      0x800,            // only ever set for UpdatePlugin.dll and UpdatePlugin.dylib
  {{Unverified|ARM64}}              =    0x8000,            // install manifest file only - load on ARM64 systems
  Encrypted          =  0x8000000,
   NoNameHash         = 0x10000000,
   {{Unverified|UncommonResolution}} = 0x20000000,           // denotes non-1280px wide cinematics
   Bundle             = 0x40000000,
   NoCompression       = 0x80000000,
  };
  };
  struct MD5Hash {
  struct MD5Hash {
Line 857: Line 1,026:
  if (format_version == 8.2) {
  if (format_version == 8.2) {
   uint32_t magic;                        // 'MFST'
   uint32_t magic;                        // 'MFST'
#if {{Template:Sandbox/VersionRange|min_expansionlevel=10|min_build=10.1.7.50893}}
  uint32_t header_size;
  uint32_t version;
#endif
   uint32_t total_file_count;            // sum of all blocks' num_records
   uint32_t total_file_count;            // sum of all blocks' num_records
   uint32_t named_file_count;            // sum of those blocks' num_records that have NoNameHash not set
   uint32_t named_file_count;            // sum of those blocks' num_records that have NoNameHash not set
#if {{Template:Sandbox/VersionRange|min_expansionlevel=10|min_build=10.1.7.50893}}
  uint32_t likely_padding;
#endif
  }
  }
   
   
Line 964: Line 1,140:
  prolivedev              prodev   
  prolivedev              prodev   
  provendor              prov
  provendor              prov
prolivedev2            prodev
   
   
  # World of Warcraft
  # World of Warcraft
  wowdemo                wowdemo
  wowdemo                wowdemo
  wowdevalpha            wowdev
  wowdevalpha            wowdev, wowdev2
wowdev (df press event/end of 2022)          3F 10 3E 3B A7 CA FE 90 26 2E 5C A4 3C E7 BC E5    DB 7F AD 8A  H4ID4O5HZL7JAJROLSSDZZ544XNX7LMK
  wowvendor              wowv
  wowvendor              wowv
wowdark                wowlivetest2
   
   
  # Destiny 2
  # Destiny 2
Line 982: Line 1,161:
  # Odin
  # Odin
  odinlivedev            odindev
  odinlivedev            odindev
# Orbis
orbislivedev            orbisdev
# Diablo 4
fenrisdev              fenris_dev
fenrise                fenris_event


=CDN File Organization=
=CDN File Organization=
Line 1,002: Line 1,188:
===Archive Indexes (.index)===
===Archive Indexes (.index)===
These '.index' files reveal to the user where the compressed game files are located within the archives. All indexes (except the Archive-Group index, see below) are named after their archive (only difference is these have an extension).
These '.index' files reveal to the user where the compressed game files are located within the archives. All indexes (except the Archive-Group index, see below) are named after their archive (only difference is these have an extension).
'.index' files are stored on the CDN using the standard hash naming scheme (remember they have an extension though). They are also located in the directory 'INSTALL_DIR/Data/indices/' for a WoW install.
'.index' files are stored on the CDN using the standard hash naming scheme (remember they have an extension though). They are also located in the directory 'INSTALL_DIR/Data/indices/' for a WoW install. For local indexes (.idx), see the [[CASC]] page.


====Normal Index Entry Structure====
====Normal Index Entry Structure====
Line 1,072: Line 1,258:
TACT keys are used to encrypt data in files. In most cases, TACT keys are streamed to clients when content (such as cinematics in WoW or skins in Overwatch) is unlocked.
TACT keys are used to encrypt data in files. In most cases, TACT keys are streamed to clients when content (such as cinematics in WoW or skins in Overwatch) is unlocked.


== Battle.net app==
<div class="warningbox">
key_name          key                              type      seen in
Due to long length/very frequent updates, the list has been moved to [[TACT/Keys]].
2C547F26A2613E01  37C50C102D4C9E3A5AC069F072B1417D  salsa20  Battle.net App Alpha 1.5.0
</div>
 
== Overwatch ==
Overwatch has keys included in the client/keyring, but they can also be streamed from the server.
<div class="mw-collapsible mw-collapsed toccolours ">
The key table is collapsed by default to reduce page length. Click expand on the right to expand.
<div class="mw-collapsible-content" id="mw-customcollapsible-myDivision">
key_name          key                              type    seen in        method    used for
FB680CB6A8BF81F3  62D90EFA7F36D71C398AE2F1FE37BDB9  salsa20  0.8.0.24919    keyring
402CD9D8D6BFED98  AEB0EADEA47612FE6C041A03958DF241  salsa20  0.8.0.24919    keyring
DBD3371554F60306  34E397ACE6DD30EEFDC98A2AB093CD3C  salsa20  0.8.0.24919    keyring
11A9203C9881710A  2E2CB8C397C2F24ED0B5E452F18DC267  salsa20  0.8.0.24919    keyring
A19C4F859F6EFA54  0196CB6F5ECBAD7CB5283891B9712B4B  salsa20  0.8.0.24919    keyring
87AEBBC9C4E6B601  685E86C6063DFDA6C9E85298076B3D42  salsa20  0.8.0.24919    keyring
DEE3A0521EFF6F03  AD740CE3FFFF9231468126985708E1B9  salsa20  0.8.0.24919    keyring
8C9106108AA84F07  53D859DDA2635A38DC32E72B11B32F29  salsa20  0.8.0.24919    keyring
49166D358A34D815  667868CD94EA0135B9B16C93B1124ABA  salsa20  0.8.0.24919    keyring
1463A87356778D14  69BD2A78D05C503E93994959B30E5AEC  salsa20  ≤ 1.0.3.0      keyring
5E152DE44DFBEE01  E45A1793B37EE31A8EB85CEE0EEE1B68  salsa20  ≤ 1.0.3.0      keyring
9B1F39EE592CA415  54A99F081CAD0D08F7E336F4368E894C  salsa20  ≤ 1.0.3.0      keyring
24C8B75890AD5917  31100C00FDE0CE18BBB33F3AC15B309F  salsa20  ≤ 1.0.3.0      keyring
EA658B75FDD4890F  DEC7A4E721F425D133039895C36036F8  salsa20  ≤ 1.0.3.0      keyring
026FDCDF8C5C7105  8F41809DA55366AD416D3C337459EEE3  salsa20                  keyring
CAE3FAC925F20402  98B78E8774BF275093CB1B5FC714511B  salsa20                  keyring
061581CA8496C80C  DA2EF5052DB917380B8AA6EF7A5F8E6A  salsa20                  keyring
BE2CB0FAD3698123  902A1285836CE6DA5895020DD603B065  salsa20                  keyring
57A5A33B226B8E0A  FDFC35C99B9DB11A326260CA246ACB41  salsa20  1.1.0.0.30200  keyring  Ana
42B9AB1AF5015920  C68778823C964C6F247ACC0F4A2584F8  salsa20  1.2.0.1.30684  keyring  Summer Games
4F0FE18E9FA1AC1A  89381C748F6531BBFCD97753D06CC3CD  salsa20  1.2.0.1.30684  keyring
7758B2CF1E4E3E1B  3DE60D37C664723595F27C5CDBF08BFA  salsa20  1.2.0.1.30684  keyring
E5317801B3561125  7DD051199F8401F95E4C03C884DCEA33  salsa20  1.4.0.2.32143  keyring  Halloween Terror
16B866D7BA3A8036  1395E882BF25B481F61A4D621141DA6E  salsa20  1.4.1.0.31804  keyring  Bastion Blizzcon 2016 skin
11131FFDA0D18D30  C32AD1B82528E0A456897B3CE1C2D27E  salsa20  1.5.0.1.32795  keyring  Sombra
CAC6B95B2724144A  73E4BEA145DF2B89B65AEF02F83FA260  salsa20  1.5.0.1.32795  keyring  Ecopoint: Antarctica
B7DBC693758A5C36  BC3A92BFE302518D91CC30790671BF10  salsa20  1.5.0.1.32795  keyring  Genji Oni Skin (HotS Nexus Challenge)
90CA73B2CDE3164B  5CBFF11F22720BACC2AE6AAD8FE53317  salsa20  1.6.1.0.33236  keyring  Oasis map
6DD3212FB942714A  E02C1643602EC16C3AE2A4D254A08FD9  salsa20  1.6.1.0.33236  keyring
11DDB470ABCBA130  66198766B1C4AF7589EFD13AD4DD667A  salsa20  1.6.1.0.33236  keyring  Winter Wonderland
5BEF27EEE95E0B4B  36BCD2B551FF1C84AA3A3994CCEB033E  salsa20                  keyring
9359B46E49D2DA42  173D65E7FCAE298A9363BD6AA189F200  salsa20                  keyring  Diablo's 20th anniversary
1A46302EF8896F34  8029AD5451D4BC18E9D0F5AC449DC055  salsa20  1.7.0.2.34156  keyring  Year of the Rooster
693529F7D40A064C  CE54873C62DAA48EFF27FCC032BD07E3  salsa20  1.8.0.0.34470  keyring  CTF Maps
388B85AEEDCB685D  D926E659D04A096B24C19151076D379A  salsa20  1.8.0.0.34470  keyring  Numbani Update (Doomfist teaser)
E218F69AAC6C104D  F43D12C94A9A528497971F1CBE41AD4D  salsa20  1.9.0.0.34986  keyring  Orisa
F432F0425363F250  BA69F2B33C2768F5F29BFE78A5A1FAD5  salsa20  1.10.0.0.35455  keyring  Uprising
061D52F86830B35D  D779F9C6CC9A4BE103A4E90A7338F793  salsa20  1.10.0.0.35455  keyring  D.Va Officer Skin (HotS Nexus Challenge 2)
1275C84CF113EF65  CF58B6933EAF98AF53E76F8426CC7E6C  salsa20                  keyring
D9C7C7AC0F14C868  3AFDF68E3A5D63BABA1E6821883F067D  salsa20                  keyring
BD4E42661A432951  6DE8E28C8511644D5595FC45E5351472  salsa20  1.11.0.0.36376  keyring  Anniversary event
C43CB14355249451  0EA2B44F96A269A386856D049A3DEC86  salsa20  1.12.0.0.37104  keyring  Horizon Lunar Colony
E6D914F8E4744953  C8477C289DCE66D9136507A33AA33301  salsa20  1.13.0.0.37646  keyring  Doomfist
5694C503F8C80178  7F4CF1C1FBBAD92B184336D677EBF937  salsa20  1.13.0.0.37646  keyring  Doomfist
21DBFD65F3E54269  AB580C3837CAF8A461F243A566B2AE4D  salsa20  1.13.0.0.37646  keyring  Summer Games 2017
27ABA5F88DD8D078  ????????????????????????????????  salsa20  1.13.0.0.37646  ???????  ??????
21E1F90E71D33C71  328742339162B32676C803C2255931A6  salsa20  1.14.1.0.39083  keyring  Deathmatch
D9CB055BCDD40B6E  49FB4477A4A0825327E9A73682BECD0C  salsa20  1.15.0.0.?????  keyring  Junkertown
8175CE3C694C6659  E3F3FA7726C70D26AE130D969DDDF399  salsa20  1.16.0.0.40011  keyring  Halloween 2017
B8DE51690075435A  C07E9260BB711217E7DE6FED911F4296  salsa20  1.16.0.0.?????  keyring  Winston Blizzcon 2017 skin
F6CF23955B5D437D  AEBA227328A5B0AA9F51DAE3F6A7DFE4  salsa20  1.17.0.2.41350  keyring  Moira
0E4D9426F2891F5C  9FF064C38BE52CCDF73748180F628205  salsa20  1.18.1.2.42076  keyring  Winter Wonderland 2017
9240BA6A2A0CF684  DF2E37D78B43108FA6242068B70D1F65  salsa20  1.19.1.3.42563  keyring  Overwatch League
82297FBAB7F5EB80  B534C20965852FB15AECAC17E381B417  salsa20  1.19.1.3.42563  keyring  Jan 2017 Lootbox Update
9ADF00AA1A174A69  9A4AC899261A2F1C6969F39397C358E7  salsa20  1.19.1.3.42563  keyring  Blizzard World
CFA05AA76B49F881  526DDDEF19BF373C25B629A334CD7237  salsa20  1.19.1.3.42563  keyring  WoW's Battle For Azeroth Preorder
493455579DA0B18E  C0BABF72AD2C05DFC14017D1ADBF5977  salsa20  1.19.3.1.43036  keyring  Inaugral Season Spray/Icon ??
6362C5AD65DAE686  62F603D5390F763ED51773F0164FEDB5  salsa20  1.19.3.1.43036  keyring  White/Gray OWL Skins ??
8162E5313A9C135D  F407834D9521587C5012B0A59D7E064B  salsa20  1.20.0.2.43435  keyring  Lunar New Year 2018 (Dog) / Ayutthaya / Comp CTF
68EAE8FDC008C381  ????????????????????????????????  salsa20  1.20.0.2.43435  n/a      ??
F412C6327C4BF091  6FAFC648CBF1C2115B769593C170E732  salsa20  1.20.0.2.43435  keyring  SC2 20th Anniversary (Kerrigan Skin)
3B3ED0874091B174  5D09C2688B1D9F1A4DB64602C1661D24  salsa20  1.21.?.?.?????  keyring  Brigitte
37FD04E05D2A6292  F06455E56CD144914295F2EF153D23BA  salsa20  1.21.?.?.?????  keyring  Brigitte Cosmetics
C0DDC77552BE5794  F2BB7F35990E2900CBD877B4D3A7139C  salsa20  1.22.?.?.?????  keyring  OWL away skins
68D8EB839DC15D75  29AFFECA5299C4140A12A66F954EF1E3  salsa20  1.22.?.?.?????  keyring  Archives 2018 (Retribution)
209F33BBAC9D1295  BD535438D0CDEE0E9567E0EF671C809F  salsa20  1.23.?.?.?????  ???????  Rialto
A55F8C6F20454D94  42D76285412461B0C75AB75FB52F596E  salsa20  1.23.?.?.?????  ???????  Mercy BCRF Items
3EEEDB8E7C29A09B  837AC79305E4BFBA3B2226F1B98200BF  salsa20  1.24.?.?.?????  ???????  Anniversary 2018 Map/Items
22C1AF6758F8449E  28AA1BD2B9A1E3633989B1BBF64AEAC4  salsa20  1.26.?.?.?????  ???????  Emily / Comp Season 11 / Comp 3v3 Items
11B2E01B9331799E  9A1C99303D6A58978E29C98873327A6A  salsa20  1.26.?.?.?????  ???????  Wrecking Ball
8498337C740329B3  EC73D663E3FC72416B3E467915708B4F  salsa20  1.26.?.?.?????  ???????  Wrecking Ball Cosmetics
E6E8BCABE3CC96C1  57727E52600665EAC02BD87F0692898F  salsa20  1.26.?.?.?????  ???????  OWL Grand Finals Unlocks / Lucio Emote
5D4AC0DC6F3113BA  D1C9F1FF69585D1398EBA0463481F5CF  salsa20  1.27.?.?.?????  ???????  Summer Games 2018
27F9D85973DCD5AF  C5FE1015BCE0B7848F022868AFF654D1  salsa20  1.27.?.?.?????  ???????  Summer Games 2018
67AAD845CC0F03BD  6CD8AD3F37F54ABEC7630294D49041BF  salsa20  1.27.?.?.?????  ???????  D.Va Nano Cola Challenge
CA13F0C79042A1A0  FCD89CE8812E6346076FC82DD7A92487  salsa20  1.28.?.?.?????  ???????  Busan
C4D84093A32684BD  38E182423EEDD8E3F57AC1D407B470D0  salsa20  1.28.?.?.?????  ???????  Blizzcon 2018 Sombra Demon Hunter Skin
0BFE5A2B3C606BA1  D6419B8E42820B0B24E08DA444A06822  salsa20  1.29.?.?.?????  ???????  Halloween Terror 2018
402CD9D8D6BFED98  AEB0EADEA47612FE6C041A03958DF241  salsa20  1.29.?.?.?????  keyring  ??
F1CBDF48147D26C6  4B6944695157D43D33E40B5692445ADB  salsa20  1.30.?.?.?????  ???????  1.30 + World Cup Viewer
01A48CFAE25F85CD  60D77A58062D03DC693C01954DD18021  salsa20  1.30.?.?.?????  ???????  1.30 + World Cup Viewer
FEBBF66DAEF6C9BE  4A220AE3A6808ED2697410C94C1CE970  salsa20  1.30.0.1.?????  ???????  Ashe
2AD4834DAB3986AB  EA6971F78ABEBD2AF883D46A5486F39F  salsa20  1.31.?.?.?????  ???????  Winter 2018
D89B24D62F00A04E  C3A4D010AAA7287A3EACCD45ED471345  salsa20  1.31.?.?.?????  ???????  Bastet Challenge
32DDC40236DAEA7B  2DBDE4FB9FDA776AA294870854FE9B02  salsa20  1.31.?.?.?????  ???????  Lunar New Year 2019 (Pig)
F481EFC2302EE415  37A7F2B87D0B8B700456C6A92C71D6DD  salsa20  1.33.?.?.?????  ???????  Paris Map
D1AC8C1903524D9A  D781D0AA35E5C106BCA7CF01DEBD1494  salsa20  1.34.0.1.55918  stream    Baptiste
71EEBE93590AA903  0CCD10D4553EEC7E97FD36A9E8ADF0FF  salsa20  1.34.0.1.55918  stream    Baptiste Cosmetics
</div></div>
 
== World of Warcraft ==
WoW's [[DB/TactKey|TactKey.db2]] and [[DB/TactKeyLookup|TactKeyLookup.db2]] contain keys and key_names (called lookups there) respectively. Either can be streamed from server.
These files cannot be bruteforced by requesting hotfix data (Blizzard has guards in place).
 
The id field in the table below corresponds to the id field in the db2's.
 
key_name          key                              type      id  seen in                  used for
FA505078126ACB3E  BDC51862ABED79B2DE48C8E7E66C6200  salsa20  15  WOW-20740patch7.0.1_Beta  not used between 7.0 and 7.3
FF813F7D062AC0BC  AA0B5C77F088CCC2D39049BD267F066D  salsa20  25  WOW-20740patch7.0.1_Beta  not used between 7.0 and 7.3
D1E9B5EDF9283668  8E4A2579894E38B4AB9058BA5C7328EE  salsa20  39  WOW-20740patch7.0.1_Beta  Enchanted Torch pet
B76729641141CB34  9849D1AA7B1FD09819C5C66283A326EC  salsa20  40  WOW-20740patch7.0.1_Beta  Enchanted Pen pet
FFB9469FF16E6BF8  D514BD1909A9E5DC8703F4B8BB1DFD9A  salsa20  41  WOW-20740patch7.0.1_Beta  not used between 7.0 and 7.3
23C5B5DF837A226C  1406E2D873B6FC99217A180881DA8D62  salsa20  42  WOW-20740patch7.0.1_Beta  Enchanted Cauldron pet
3AE403EF40AC3037  ????????????????????????????????  salsa20  51  WOW-21249patch7.0.3_Beta  not used between 7.0 and 7.3
E2854509C471C554  433265F0CDEB2F4E65C0EE7008714D9E  salsa20  52  WOW-21249patch7.0.3_Beta  Warcraft movie items
8EE2CB82178C995A  DA6AFC989ED6CAD279885992C037A8EE  salsa20  55  WOW-21531patch7.0.3_Beta  BlizzCon 2016 Murlocs
5813810F4EC9B005  01BE8B43142DD99A9E690FAD288B6082  salsa20  56  WOW-21531patch7.0.3_Beta  Fel Kitten
7F9E217166ED43EA  05FC927B9F4F5B05568142912A052B0F  salsa20  57  WOW-21531patch7.0.3_Beta  Legion music
C4A8D364D23793F7  D1AC20FD14957FABC27196E9F6E7024A  salsa20  58  WOW-21691patch7.0.3_Beta  Demon Hunter #1 cinematic (legion_dh1)
40A234AEBCF2C6E5  C6C5F6C7F735D7D94C87267FA4994D45  salsa20  59  WOW-21691patch7.0.3_Beta  Demon Hunter #2 cinematic (legion_dh2)
9CF7DFCFCBCE4AE5  72A97A24A998E3A5500F3871F37628C0  salsa20  60  WOW-21691patch7.0.3_Beta  Val'sharah #1 cinematic (legion_val_yd)
4E4BDECAB8485B4F  3832D7C42AAC9268F00BE7B6B48EC9AF  salsa20  61  WOW-21691patch7.0.3_Beta  Val'sharah #2 cinematic (legion_val_yx)
94A50AC54EFF70E4  C2501A72654B96F86350C5A927962F7A  salsa20  62  WOW-21691patch7.0.3_Beta  Sylvanas warchief cinematic (legion_org_vs)
BA973B0E01DE1C2C  D83BBCB46CC438B17A48E76C4F5654A3  salsa20  63  WOW-21691patch7.0.3_Beta  Stormheim Sylvanas vs Greymane cinematic (legion_sth)
494A6F8E8E108BEF  F0FDE1D29B274F6E7DBDB7FF815FE910  salsa20  64  WOW-21691patch7.0.3_Beta  Harbingers Gul'dan video (legion_hrb_g)
918D6DD0C3849002  857090D926BB28AEDA4BF028CACC4BA3  salsa20  65  WOW-21691patch7.0.3_Beta  Harbingers Khadgar video (legion_hrb_k)
0B5F6957915ADDCA  4DD0DC82B101C80ABAC0A4D57E67F859  salsa20  66  WOW-21691patch7.0.3_Beta  Harbingers Illidan video (legion_hrb_i)
794F25C6CD8AB62B  76583BDACD5257A3F73D1598A2CA2D99  salsa20  67  WOW-21846patch7.0.3_Beta  Suramar cinematic (legion_su_i)
A9633A54C1673D21  1F8D467F5D6D411F8A548B6329A5087E  salsa20  68  WOW-21846patch7.0.3_Beta  legion_su_r cinematic
5E5D896B3E163DEA  8ACE8DB169E2F98AC36AD52C088E77C1  salsa20  69  WOW-21846patch7.0.3_Beta  Broken Shore intro cinematic (legion_bs_i)
0EBE36B5010DFD7F  9A89CC7E3ACB29CF14C60BC13B1E4616  salsa20  70  WOW-21846patch7.0.3_Beta  Alliance Broken Shore cinematic (legion_bs_a)
01E828CFFA450C0F  972B6E74420EC519E6F9D97D594AA37C  salsa20  71  WOW-21846patch7.0.3_Beta  Horde Broken Shore cinematic (legion_bs_h)
4A7BD170FE18E6AE  AB55AE1BF0C7C519AFF028C15610A45B  salsa20  72  WOW-21846patch7.0.3_Beta  Khadgar & Light's Heart cinematic (legion_iq_lv)
69549CB975E87C4F  7B6FA382E1FAD1465C851E3F4734A1B3  salsa20  73  WOW-21846patch7.0.3_Beta  legion_iq_id cinematic
460C92C372B2A166  946D5659F2FAF327C0B7EC828B748ADB  salsa20  74  WOW-21952patch7.0.3_Beta  Stormheim Alliance cinematic (legion_g_a_sth)
8165D801CCA11962  CD0C0FFAAD9363EC14DD25ECDD2A5B62  salsa20  75  WOW-21952patch7.0.3_Beta  Stormheim Horde cinematic (legion_g_h_sth)
A3F1C999090ADAC9  B72FEF4A01488A88FF02280AA07A92BB  salsa20  81  WOW-22578patch7.1.0_PTR  Firecat Mount
18AFDF5191923610  ????????????????????????????????  salsa20  82  WOW-22578patch7.1.0_PTR  not used between 7.1 and 7.3
3C258426058FBD93  ????????????????????????????????  salsa20  91  WOW-23436patch7.2.0_PTR  not used between 7.2 and 7.3
094E9A0474876B98  E533BB6D65727A5832680D620B0BC10B  salsa20  92  WOW-23910patch7.2.5_PTR  shadowstalkerpanthermount, shadowstalkerpantherpet
3DB25CB86A40335E  02990B12260C1E9FDD73FE47CBAB7024  salsa20  93  WOW-23789patch7.2.0_PTR  legion_72_ots
0DCD81945F4B4686  1B789B87FB3C9238D528997BFAB44186  salsa20  94  WOW-23789patch7.2.0_PTR  legion_72_tst
486A2A3A2803BE89  32679EA7B0F99EBF4FA170E847EA439A  salsa20  95  WOW-23789patch7.2.0_PTR  legion_72_ars
71F69446AD848E06  E79AEB88B1509F628F38208201741C30  salsa20  97  WOW-24473patch7.3.0_PTR  BlizzCon 2017 Mounts (AllianceShipMount and HordeZeppelinMount)
211FCD1265A928E9  A736FBF58D587B3972CE154A86AE4540  salsa20  98  WOW-24473patch7.3.0_PTR  Shadow fox pet (store)
0ADC9E327E42E98C  017B3472C1DEE304FA0B2FF8E53FF7D6  salsa20  99  WOW-23910patch7.2.5_PTR  legion_72_tsf
BAE9F621B60174F1  38C3FB39B4971760B4B982FE9F095014  salsa20  100 WOW-24727patch7.3.0_PTR  Rejection of the Gift cinematic (legion_73_agi)
34DE1EEADC97115E  2E3A53D59A491E5CD173F337F7CD8C61  salsa20  101 WOW-24727patch7.3.0_PTR  Resurrection of Alleria Windrunner cinematic (legion_73_avt)
E07E107F1390A3DF  290D27B0E871F8C5B14A14E514D0F0D9  salsa20  102 WOW-25079patch7.3.2_PTR  Tottle battle pet, Raptor mount, Horse mount (104 files)
32690BF74DE12530  A2556210AE5422E6D61EDAAF122CB637  salsa20  103 WOW-24781patch7.3.0_PTR  legion_73_pan
BF3734B1DCB04696  48946123050B00A7EFB1C029EE6CC438  salsa20  104 WOW-25079patch7.3.2_PTR  legion_73_afn
74F4F78002A5A1BE  C14EEC8D5AEEF93FA811D450B4E46E91  salsa20  105 WOW-25079patch7.3.2_PTR  SilithusPhase01 map
423F07656CA27D23  ????????????????????????????????  salsa20  107 WOW-25600patch7.3.5_PTR  bltestmap
0691678F83E8A75D  ????????????????????????????????  salsa20  108 WOW-25600patch7.3.5_PTR  filedataid 1782602-1782603
324498590F550556  ????????????????????????????????  salsa20  109 WOW-25600patch7.3.5_PTR  filedataid 1782615-1782619
C02C78F40BEF5998  ????????????????????????????????  salsa20  110 WOW-25600patch7.3.5_PTR  test/testtexture.blp (fdid 1782613)
47011412CCAAB541  ????????????????????????????????  salsa20  111 WOW-25600patch7.3.5_PTR  unused in 25600
23B6F5764CE2DDD6  ????????????????????????????????  salsa20  112 WOW-25600patch7.3.5_PTR  unused in 25600
8E00C6F405873583  ????????????????????????????????  salsa20  113 WOW-25600patch7.3.5_PTR  filedataid 1783470-1783472
78482170E4CFD4A6  768540C20A5B153583AD7F53130C58FE  salsa20  114 WOW-25600patch7.3.5_PTR  Magni Bronzebeard VO
B1EB52A64BFAF7BF  458133AA43949A141632C4F8596DE2B0  salsa20  115 WOW-25600patch7.3.5_PTR  dogmount, 50 files
FC6F20EE98D208F6  57790E48D35500E70DF812594F507BE7  salsa20  117 WOW-25632patch7.3.5_PTR  bfa shop stuff
402CFABF2020D9B7  67197BCD9D0EF0C4085378FAA69A3264  salsa20  118 WOW-25678patch7.3.5_PTR  bfa ad texture
6FA0420E902B4FBE  27B750184E5329C4E4455CBD3E1FD5AB  salsa20  119 WOW-25744patch7.3.5_PTR  Legion epilogue cinematics
1076074F2B350A2D  88BF0CD0D5BA159AE7CB916AFBE13865  salsa20  121 WOW-26287patch8.0.1_Beta  skiff
816F00C1322CDF52  6F832299A7578957EE86B7F9F15B0188  salsa20  122 WOW-26287patch8.0.1_Beta  snowkid
DDD295C82E60DB3C  3429CC5927D1629765974FD9AFAB7580  salsa20  123 WOW-26287patch8.0.1_Beta  redbird
83E96F07F259F799  91F7D0E7A02CDE0DE0BD367FABCB8A6E  salsa20  124 WOW-26522patch8.0.1_Beta  BlizzCon 2018 (Alliance and Horde banners and cloaks)
49FBFE8A717F03D5  C7437770CF153A3135FA6DC5E4C85E65  salsa20  225 WOW-27826patch8.1.0_PTR  Meatwagon mount (Warcraft 3: Reforged)
C1E5D7408A7D4484  A7D88E52749FA5459D644523F8359651  salsa20  226 WOW-26871patch8.0.1_Beta  Sylvanas Warbringer cinematic
E46276EB9E1A9854  CCCA36E302F9459B1D60526A31BE77C8  salsa20  227 WOW-26871patch8.0.1_Beta  ltc_a, ltc_h and ltt cinematics
D245B671DD78648C  19DCB4D45A658B54351DB7DDC81DE79E  salsa20  228 WOW-26871patch8.0.1_Beta  stz, zia, kta, jnm & ja cinematics
4C596E12D36DDFC3  B8731926389499CBD4ADBF5006CA0391  salsa20  229 WOW-26871patch8.0.1_Beta  bar cinematic
0C9ABD5081C06411  25A77CD800197EE6A32DD63F04E115FA  salsa20  230 WOW-26871patch8.0.1_Beta  zcf cinematic
3C6243057F3D9B24  58AE3E064210E3EDF9C1259CDE914C5D  salsa20  231 WOW-26871patch8.0.1_Beta  ktf cinematic
7827FBE24427E27D  34A432042073CD0B51627068D2E0BD3E  salsa20  232 WOW-26871patch8.0.1_Beta  rot cinematic
FAF9237E1186CF66  AE787840041E9B4198F479714DAD562C  salsa20  233 WOW-28048patch8.1.0_PTR  encrypted db2 sections (battle pet?)
5DD92EE32BBF9ABD  ????????????????????????????????  salsa20  234 WOW-27004patch8.0.1_Subm  filedataid 2238294
0B68A7AF5F85F7EE  27AA011082F5E8BBBD71D1BA04F6ABA4  salsa20  236 WOW-28151patch8.1.0_PTR  flying pig mount
01531713C83FCC39  ????????????????????????????????  salsa20  237 WOW-28151patch8.1.0_PTR  fdid 2460009, 2460732
76E4F6739A35E8D7  ????????????????????????????????  salsa20  238 WOW-28294patch8.1.0_PTR  starts at fdid 2492654, total of 15 fdids
66033F28DC01923C  9F9519861490C5A9FFD4D82A6D0067DB  salsa20  239 WOW-28294patch8.1.0_PTR  vulpine familiar mount
FCF34A9B05AE7E6A  E7C2C8F77E30AC240F39EC23971296E5  salsa20  240 WOW-28151patch8.1.0_PTR  fdid 2468985, 2471011, 2471012, 2471014, 2471016, 2471018, 2530045
E2F6BD41298A2AB9  C5DC1BB43B8CF3F085D6986826B928EC  salsa20  241 WOW-28151patch8.1.0_PTR  fdid 2468988, 2471019, 2471020, 2471021, 2471022, 2471023, 2530046
14C4257E557B49A1  064A9709F42D50CB5F8B94BC1ACFDD5D  salsa20  242 WOW-28440patch8.1.0_PTR  dor cinematic
1254E65319C6EEFF  79D2B3D1CCB015474E7158813864B8E6  salsa20  243 WOW-28440patch8.1.0_PTR  akt cinematic
C8753773ADF1174C  ????????????????????????????????  salsa20  244 WOW-28938patch8.1.5_PTR  starts at fdid 2615771, total of 16 fdids
2170BCAA9FA96E22  ????????????????????????????????  salsa20  245 WOW-28938patch8.1.5_PTR  alpaca mount
75485627AA225F4D  ????????????????????????????????  salsa20  246 WOW-28938patch8.1.5_PTR  fdid 2741546, 2741548, 2741549
08717B15BF3C7955  4B06BF9D17663CEB3312EA3C69FBC5DD  salsa20  248 WOW-29220patch8.1.5_PTR  fdid 2823166
D19DCF7ACA8D96D6  ????????????????????????????????  salsa20  249 WOW-30080patch8.2.0_PTR  starts at fdid 2843110, total of 10 fdids
9FD609902B4B2E07  ABE0C5F9C123E6E24E7BEA43C2BF00AC  salsa20  250 WOW-29418patch8.1.5_PTR  fdid 2845773, 2845774, 2845775, 2845776, 2845777
CB26B441FAE4C8CD  ????????????????????????????????  salsa20  251 WOW-30080patch8.2.0_PTR  fdid 2888623, 2892270, 2892271, 2892272, 2892274, 2892275
A98C7594F55C02F0  ????????????????????????????????  salsa20  252 WOW-30080patch8.2.0_PTR  starts at fdid 2921871, total of 24 fdids
259EE68CD9E76DBA  ????????????????????????????????  salsa20  253 WOW-30080patch8.2.0_PTR  starts at fdid 2957406, total of 30 fdids
6A026290FBDB3754  ????????????????????????????????  salsa20  255 WOW-30080patch8.2.0_PTR  starts at fdid 2976294, total of 201 fdids
CF72FD04608D36ED  A0A889976D02FA8D00F7AF0017AD721F  salsa20  257 WOW-30262patch8.2.0_PTR  fdid 2991594, 2991595, 2991596, 2991597, 2991604
17F07C2E3A45DB3D  ????????????????????????????????  salsa20  258 WOW-30262patch8.2.0_PTR  starts at fdid 982457, total of 17 fdids
C050FA06BB0538F6  ????????????????????????????????  salsa20  260 WOW-30495patch8.2.0_PTR  fdid 3022754
AB5CDD3FC321831F  ????????????????????????????????  salsa20  261 WOW-30495patch8.2.0_PTR 
A7B7D1F12395040E  ????????????????????????????????  salsa20  262 WOW-30495patch8.2.0_PTR

Latest revision as of 17:19, 16 March 2024

TACT (Trusted Application Content Transfer) is the name of the content transfer part of NGDP. It is often used to install games that use CASC filesystems, but also supports non-CASC based products.

Product Information

Upon initial release, TACT used regular HTTP to retrieve information for its products. In early 2018, Blizzard started working on a new system that has superseded this. More information about the new system can be found on the Ribbit page.

As of March/April 2019 Ribbit is now the primary system for retrieving version information for most products. HTTP version information has already diverged in some places and should probably only be used as a fallback.

As of 8.3.7 and 9.0.1 the WoW client uses Ribbit as the primary way of retrieving version information as well.

HTTP URLs

Note: These are now just wrappers over Ribbit V2.

URL Description
http://us.patch.battle.net:1119/(product)/cdns a table of CDN domains available with game data per region
http://us.patch.battle.net:1119/(product)/versions current version, buildconfig, cdnconfig, productconfig and optionally keyring per region
http://us.patch.battle.net:1119/(product)/bgdl similar to versions, but tailored for use by the Battle.net App background downloader
http://us.patch.battle.net:1119/(product)/blobs contains InstallBlobMD5 and GameBlobMD5
http://us.patch.battle.net:1119/(product)/blob/game a blob file that regulates game functionality for the Battle.net App
http://us.patch.battle.net:1119/(product)/blob/install a blob file that regulates installer functionality for the game in the Battle.net App

Products

The following products are known to have existed at one point. When this page refers to a product it refers to the TACT Product. Agent UIDs are specific to Agent.

Non-Games
TACT Product Agent UID Description Status
agent agent Battle.net Agent Active
agent_test Probably Agent test
bna battle.net Battle.net App Active
bts Bootstrapper Partial (only versions as of now, cdnpath=tpr/bnt004)
catalogs Catalog Active
clnt Client Deprecated
demo Partial
test Deprecated

Most games have multiple products. Tables for these are collapsed by default to not affect page length. Click Expand to see all known products for a game.

Blizzard Arcade Collection
TACT Product Agent Product Description Status
rtro rtro Blizzard Arcade Collection Retail Active
rtrodev rtro_dev Blizzard Arcade Collection Dev
Diablo Immortal (PC)
TACT Product Agent Product Description Status
anbs anbs Diablo Immortal Retail
anbsdev anbs_dev Diablo Immortal Dev Active (encrypted)
Diablo II: Resurrected
TACT Product Agent Product Description Status
osi Diablo II: Resurrected Retail Active
osib osi_beta Diablo II: Resurrected Beta Active
osia osi_dev Diablo II: Resurrected Alpha Active (encrypted)
osidev osi_dev_2 Diablo II: Resurrected Dev Active (encrypted)
osiv1 osi_vendor_1 Diablo II: Resurrected Vendor 1 Active (encrypted)
osiv2 osi_vendor_2 Diablo II: Resurrected Vendor 2
osiv3 osi_vendor_3 Diablo II: Resurrected Vendor 3 Active (encrypted)
osiv4 osi_vendor_4 Diablo II: Resurrected Vendor 4
osiv5 osi_vendor_5 Diablo II: Resurrected Vendor 5
osiv6 osi_vendor_6 Diablo II: Resurrected Vendor 6
Diablo III
TACT Product Agent Product Description Status
d3 diablo3(_locale) Diablo 3 Retail Active
d3b Diablo 3 Beta (2013) Partial
d3cn d3cn Diablo 3 China Active
d3cnt Diablo 3 China Test (?) Unused (everything empty)
d3t diablo3_ptr(_locale) Diablo 3 Test Active
Diablo IV (aka Fenris)
TACT Product Agent Product Description Status
fenris fenris Diablo IV Retail Active
fenrisb fenris_beta Diablo IV Beta Active
fenrise fenris_event Diablo IV Pre-Launch Disabled (encrypted)
fenrisdev fenris_dev Diablo IV Dev Disabled (encrypted)
fenrisvendor fenris_vendor Diablo IV Vendor Active (encrypted), Season 1
fenrisvendor2 fenris_vendor2 Diablo IV Vendor 2 Active (encrypted)
fenrisvendor3 fenris_vendor3 Diablo IV Vendor 3 Active (encrypted), Season 2
Heroes of the Storm
TACT Product Agent Product Description Status
bnt Heroes of the Storm Alpha Deprecated
hero heroes Heroes of the Storm Retail Active
heroc heroes_tournament Heroes of the Storm Tournament Active
herot heroes_ptr Heroes of the Storm Test Active
storm Heroes of the Storm Deprecated
Hearthstone
hsb hs_beta Hearthstone Retail Active
hsc hs_tournament Hearthstone Chournament Active
hst Hearthstone Test Partial
Overwatch (aka Prometheus)
TACT Product Agent Product Description Status
pro prometheus Overwatch Retail Active
proc prometheus_tournament Overwatch Tournament US Active
proc_cn prometheus_tournament_cn Overwatch Tournament China Active
proc_eu prometheus_tournament_eu Overwatch Tournament Europe Active
proc_kr prometheus_tournament_kr Overwatch Tournament Korea Active
proc2 prometheus_tournament2 Overwatch Professional 2 Active
proc2_cn prometheus_tournament2_cn Overwatch Professional 2 China Active
proc2_eu prometheus_tournament2_eu Overwatch Professional 2 Europe Active
proc2_kr prometheus_tournament2_kr Overwatch Professional 2 Korea Active
proc3 prometheus_tournament3 Overwatch Tournament (Dev)
procr prometheus_tournament_viewer Overwatch League Stage 3
procr2 prometheus_tournament_viewer_2 Overwatch League Stage 2
prodev prometheus_dev Overwatch Dev Active (encrypted)
proe Not on public CDNs
prot prometheus_test Overwatch Test Active
prov prometheus_vendor Overwatch Vendor Active (encrypted)
proms prometheus_viewer Overwatch World Cup Viewer Partial
StarCraft 1
TACT Product Agent Product Description Status
s1 s1 StarCraft 1 Active
s1a Starcraft 1 Alpha Active (encrypted)
s1t s1_ptr StarCraft 1 Test Active
StarCraft II
TACT Product Agent Product Description Status
s2 s2(_locale) StarCraft II Retail Active
s2b StarCraft II Beta Deprecated
s2t s2_ptr(_locale) StarCraft II Test Deprecated
sc2 StarCraft II Deprecated
Warcraft III
TACT Product Agent Product Description Status
w3 w3 Warcraft III Active
w3t w3_ptr Warcraft III Public Test Active
war3 Warcraft III (old) Partial
w3b w3_beta Warcraft III: Reforged Beta
World of Warcraft
TACT Product Agent Product Description Status
wow wow(_locale) World of Warcraft Retail Active
wow_beta wow_beta World of Warcraft Alpha/Beta Active
wow_classic wow_test, later wow_classic World of Warcraft Classic (BCC) Active
wow_classic_beta wow_classic_beta World of Warcraft Classic (BCC) Beta Active
wow_classic_ptr wow_classic_ptr World of Warcraft Classic (BCC) Test Active
wow_classic_era wow_classic_era World of Warcraft Classic (Vanilla) Active
wow_classic_era_beta wow_classic_era_beta World of Warcraft Classic (Vanilla) Beta Active
wow_classic_era_ptr wow_classic_era_ptr World of Warcraft Classic (Vanilla) Test Active
wowdev wow_alpha World of Warcraft Dev Active (encrypted)
wowdemo World of Warcraft (Classic) Demo Active (encrypted)
wowe1 wow_event1 World of Warcraft Event 1 Active
wowe2 wow_event2 World of Warcraft Event 2 Active (partial)
wowe3 wow_event3(_locale) World of Warcraft Event 3 Active (partial)
wowt wow_ptr(_locale) World of Warcraft Test Active
wowv wow_vendor World of Warcraft Vendor Active (encrypted)
wowv2 wow_vendor2 World of Warcraft Vendor 2 (Classic) Active (encrypted)
wowz wow_submission World of Warcraft Submission (previously Vendor) Active

Non-Blizzard

Call of Duty
TACT Product Agent Product Description Status
viper viper Call of Duty: Black Ops 4 Active
viperdev viper_alpha Call of Duty: Black Ops 4 - Alpha Active (encrypted)
viperv1 viper_vendor Call of Duty: Black Ops 4 Vendor
odin odin_placeholder → odin Call of Duty: Modern Warfare
odindev odin_dev Call of Duty: Modern Warfare Dev Active (encrypted)
odinv1 odin_vendor1 Call of Duty: Modern Warfare Vendor 4
odinv2 odin_vendor2 Call of Duty: Modern Warfare Vendor 4
odinv3 odin_vendor3 Call of Duty: Modern Warfare Vendor 4
odinv4 odin_vendor4 Call of Duty: Modern Warfare Vendor 4
odina odin_alpha another cod mw dev channel
odinb odin_beta public (paid) beta
odine odin_event tournament/event
lazr lazarus Call of Duty: MW2CR (Campaign Remastered)
lazrdev lazarus_dev Call of Duty: MW2CR Dev
lazrv1 lazarus_vendor_1 Call of Duty: MW2CR Vendor 1
lazrv2 lazarus_vendor_2 Call of Duty: MW2CR Vendor 2
zeus zeus Call of Duty: Black Ops Cold War Active
fore fore Call of Duty: Vanguard Active
foreb foreb Call of Duty: Vanguard (Public Beta) Active
Crash Bandicoot 4
TACT Product Agent Product Description Status
wlby wlby Crash Bandicoot 4
wlbydev wlby_dev Crash Bandicoot 4 Developing Active (encrypted)
wlbyv[1-6] wlby_vendor_[1-6] Crash Bandicoot 4 for Vendors Active (encrypted)
Destiny 2
TACT Product Agent Product Description Status
dst2 destiny_2 Destiny 2 Active
dst2a destiny2_alpha Destiny 2 Alpha Active (encrypted)
dst2dev destiny2_takehome Destiny 2 "takehome" development Partial (encrypted?)
dst2e1 destiny2_event Destiny 2 Event Active; probably 1..9
dst2igr Destiny 2 Internet Game Room Active
dst2t destiny2_ptr Destiny 2 Public Test Active

Glossary

This page uses many terms. Here's an overview of stuff you need to know to be able to understand most of the explanations below.

Term Description
Filename The file's real filename. Note that one file in TACT can have many names referring to it - essentially, one encoding key can map to many different name hashes.
Name Hash/Lookup The filename after being hashed with the Jenkins Hash.
Content Hash/CKey The MD5 of the entire file in its uncompressed state; the purest representation of the data.
Encoding Hash/EKey MD5 hash of the potentially encoded file. For unencoded files, the content hash/CKey. For chunkless BLTE files lacking a chunk table, this hash covers the entire encoded file. For chunked BLTE files, this hash covers only the BLTE headers including chunk table, as the chunk table contains hashes of the content of each chunk. A given file can be encoded in many ways, and a single content hash may potentially have multiple encoding keys.
CDN Key The key used to lookup a file on the CDN. Same as encoding hash/EKey.

File types

Files are stored on CDNs in the following format: http://(cdnsHost)/(cdnsPath)/(pathType)/(FirstTwoHexOfHash)/(SecondTwoHexOfHash)/(FullHash)

Current list of CDNs for a specific product can be found in the http://us.patch.battle.net:1119/(product)/cdns file or via Ribbit in the v1/products/(product/)cdns endpoint. Blizzard regularly shuffles around CDNs and sometimes even adds/removes CDNs, so be sure to parse cdns to stay up to date. The CDN path found in the cdns file very rarely changes, the only known occurence is Overwatch changing from tpr/pro to tpr/ovw.

Known path types are:

  • config - contains the three types of config files: Build configs, CDN configs, and Patch configs
  • data - contains archives, indexes, and unarchived standalone files (typically binaries, mp3s, and movies and files mentioned in buildconfig like root, install and download)
  • patch - contains patch manifests, files, archives, indexes

Blizzard regularly cleans old builds from the CDN so any example files mentioned in this article might be unavailable at the time of reading (feel free to update them to something more recent if this is the case).

Product configs referred to in the versions file are generally saved in tpr/configs for all games, but to be sure this path should be found by parsing the cdns file for the product in question.

It is intended behavior for some files, even recent ones, to not be available on all CDNs, you should try a different CDN from the list of CDNs in those cases. For example an archive might not be available on us.cdn.blizzard.com but instead be available on level3.blizzard.com

Some CDNs also implement rate limiting, they will return HTTP code 429 if you are exceeding requests. Exact request limits are unknown and seem to vary per region/time.

Config Files

Build Config

Example file: http://blzddist1-a.akamaihd.net/tpr/wow/config/22/38/2238ab9c57b672457a2fa6fe2107b388

Some of the files listed in this file are explained later on in this article.

What follows is a table for all known variables that have been seen in a buildconfig.

Value name Description
root Content hash of the decoded root file, look this up in encoding to get the encoded hash.
install First key is the content hash of the decoded install file. Second key, if present, is the encoded hash; if absent, look up the content hash in encoding to get the encoded hash/CDN key.
install-size Install size(s) corresponding to the install hash(es). Absent in older WoW builds.
download First key is the content hash of the decoded download file. Second key, if present, is the encoded hash; if absent, look up the content hash in encoding to get the encoded hash.
download-size Download size(s) corresponding to the download hash(es). Absent in older WoW builds.
size CKey and EKey of the download size file, respectively. Introduced in WoW build 27547.
size-size Download size sizes corresponding to the download size keys.
build-partial-priority Content hash:block size pairs for priority non-archived files, ordered by priority. The block size appears to be the amount to request in each partial HTTP request. These files are BLTE-encoded and usually but not always split into blocks of fixed uncompressed size where the partial priority block size is a power-of-two multiple of the file's uncompressed block size. First seen in build 24116. Optional.
partial-priority Content hash of a partial download file containing priority files to download first; note that the sizes in the download file entries are download block sizes, not file sizes. First seen in build 22231, replaced by build-partial-priority in build 24116. Optional.
partial-priority-size Unknown: always 0 if present. Present if partial-priority is present.
encoding First key is the content hash of the decoded encoding file. Second key is the encoded hash. If either none or 1 is found, the game (at least Wow) switches to plain-data (?) . Seen in build 20173
encoding-size Encoding sizes corresponding to the encoding hashes.
patch The manifest of patchable data files. Does not include the metadata files e.g. encoding, whose patches are specified in the patch config file. Optional.
patch-size Size of the patch manifest, if any. Optional.
patch-config Content hash of non-encoded patch config (see Patch Config)
build-attributes Optional. Seen in agent.
build-branch Optional. Presumably the SCM branch built.
build-comments Optional.
build-creator Optional. Presumably the user who submitted the build.
build-fixed-hash Optional. Seen in S2.
build-replay-hash Optional. Seen in S2.
build-name Optional? Name of the build
build-playbuild-installer Optional? Type of installer for the Battle.net app to use
build-product Optional? Product name
build-t1-manifest-version Optional.
build-uid Optional? Program code (see Products)
vfs-root VFS root
vfs-root-size VFS root size
vfs-i VFS manifest, where i is index.
vfs-i-size VFS manifest size, where i is index.

CDN Config

Example file: http://blzddist1-a.akamaihd.net/tpr/wow/config/42/33/423364147752a596911aa1de2ff1f6a4

Value name Description
archives CDN keys of all archives (and by appending .index to the hash their indexes)
archive-group CDN key of the the combined index file (see Archive-Group Index)
file-index CDN key of .index file for unarchived files. These files have 0-byte archive offset fields. Seen in Warcraft III.
file-index-size Size of unarchived file .index.
patch-archives CDN keys of patch archives (needs research)
patch-archive-group CDN key of probably the combined patch index file (needs research)
builds List of build configs this config supports (optional)
patch-file-index CDN key of .index file for unarchived patches. These files have 0-byte archive offset fields. Seen in Warcraft III.
patch-file-index-size Size of unarchived patch .index.

Patch Config

Example file: http://blzddist1-a.akamaihd.net/tpr/wow/config/20/f0/20f0593dd1b9fdaeaa7a808f83d48f1d This configuration file was added after all of the others. It first appeared in CASC v1 for Heroes of the Storm in August 2014. It then appeared in WoW for CASC v2 in build 19027 (October 10th, 2014). The purpose of this file is to reduce redundant downloads. It achieves this by directing the system to download patch files to apply and update previously downloaded material. The structure and purpose of all of the fields of this file requires further research.

Value name Description
patch-entry Repeats 4 times with patch entries for install, download, encoding and size file. Builds using the partial-priority (not build-partial-priority) mechanism may additionally have a partial-priority entry.
patch Patch manifest file
patch-size Size of patch file (optional?)

patch-entry

The format of these strings is:

patch-entry = <type> <content hash> <content size> <BLTE-encoding key> <BLTE-encoded size> <encoding string>

followed by sets of

<old BLTE-encoding key> <old content size> <patch hash> <patch size>

sorted by oldest build to newest. This serves to pair old files to the patch needed to bring them up to date, as well as providing the information required to detect if the file is already up to date.

These patches are stored externally to the #Patch file (which solely handles game asset patching) and are stored directly on Blizzard's CDN. These are raw ZBSDIFF1 blobs applied to the BLTE decoded contents of each file.

Example patch: https://blzddist1-a.akamaihd.net/tpr/wow/patch/0b/68/0b6829cdd07255fa57b6243b0eba2ee3

Data Files

Example index: http://blzddist1-a.akamaihd.net/tpr/wow/data/00/52/0052ea9a56fd7b3b6fe7d1d906e6cdef.index

Example archive: http://blzddist1-a.akamaihd.net/tpr/wow/data/00/52/0052ea9a56fd7b3b6fe7d1d906e6cdef

Patch Files

#Patch

Encoding table

The encoding file maps content hashes C-Keys to encoded-file hashes E-Keys. In addition, there is information on how the files are BLTE-encoded by E-Specs.

Blocks in this file are, in this order

  • header
  • encoding specification data ESpec
  • content key → encoding key table CEKeyPageTable
  • encoding key → encoding spec table EKeySpecPageTable
  • encoding specification data for the encoding file itself

An incomplete/outdated 010 Editor template can be found at this gist which can be used to understand page handling.

Header

Header is a constant 0x16 bytes giving size information for the other blocks, mostly.

struct {
/*0x00*/  char signature[2];                            // "EN"
          enum {
            encoding_version_1 = 1,                     // ≥ WoD (6.0.1.18125)
          };
/*0x02*/  uint8_BE_t version;
/*0x03*/  uint8_BE_t hash_size_ckey;
/*0x04*/  uint8_BE_t hash_size_ekey;
/*0x05*/  uint16_BE_t CEKeyPageTable_page_size_kb;      // in kilo bytes. e.g. 4 in here → 4096 byte pages (default)
/*0x07*/  uint16_BE_t EKeySpecPageTable_page_size_kb;   // ^
/*0x09*/  uint32_BE_t CEKeyPageTable_page_count;
/*0x0D*/  uint32_BE_t EKeySpecPageTable_page_count;
/*0x11*/  uint8_BE_t _unknown_x11;                      // 0 -- sometimes assumed to be part of ESpec_block_size, but actually asserted to be zero by agent
/*0x12*/  uint32_BE_t ESpec_block_size;
/*0x16*/
} header;

ESpec

Encoding specification strings are just a blob of zero terminated strings referenced by EKeySpecPageTable with the accumulated size of header.ESpec_block_size (including zero terminators).

The definition of the format for these strings is described on the BLTE page.

Page Tables

The format of the two page tables is the same:

  • an index for fast key → page access, followed by
  • the actual pages with specific content

In both cases, the entries in the lists have the same count, and semi-dynamic size, depending on header.hash_size_ckey and header.hash_size_ekey. Note that the page checksum size is fixed to MD5's 16 bytes. The position comments below assume the standard key size of 16 bytes.

Note: As of 8.3, the entry count of both tables is no longer exactly the same.

struct page_index_t {
/*0x00*/  char first_Xkey[header.hash_size_Xkey];       // where X is c for CEKeyPageTable and e for EKeySpecPageTable
/*0x10*/  char page_md5[0x10];
/*0x20 usually*/
};

The pages themselves are filled as much possible with actual entry structs. They are padded to the end for alignment of pages. Pages don't actually have to be full.

CEKeyPageTable

This table maps one ckey to one or more ekeys. This means that there can be multiple representations, e.g. an encrypted and an unencrypted version. This isn't usually the case and on reading any of them can be picked, since they represent the same file content. It can be used to pick an already downloaded archive, or unencrypted one, or handle deleted archives.

struct ckey_ekey_entry_t {
/*0x00*/  uint8_BE_t keyCount;
/*0x01*/  uint40_BE_t file_size;                        // of the non-encoded version of the file
/*0x06*/  char ckey[header.hash_size_ckey];             // this ckey is represented by…
/*0x16*/  char ekey[header.hash_size_ekey][keyCount];   // …these ekeys
/*0x26 usually*/
} page_entries[];
EKeySpecPageTable

This table maps one ekey to the corresponding espec describing how the encoding happened.

struct ekey_espec_entry_t {
/*0x00*/  char ekey[header.hash_size_ekey];
/*0x10*/  uint32_BE_t espec_index;                      // not an offset but an index, assuming zero-terminated espec strings
/*0x14*/  uint40_BE_t file_size;                        // of the encoded version of the file
/*0x19 usually*/
} page_entries[];

Install manifest

File signature: "IN"

The install file lists files installed on disk. Since the install file is shared by architectures and OSs, there are also tags to select a subset of files. When using multiple tags, a binary combination of the bitfields of files to be installed can be created.

Header Structure

The file begins with a 10 byte header describing the number of tags and files listed. Structure names were invented by the author of this page.

Offset (Hex) Type Name Description
0x00 char[2] FileSignature "IN"
0x02 uint8_t Version? 1
0x03 uint8_t hash_size size of hashes used for files (usually md5 -> 16)
0x04 uint16_BE_t num_tags number of tags in header of file
0x06 uint32_BE_t num_entries The number of entries in the body of the file

Tags Structure

After the header, an array with information about available tags follows. Each tag has a bitfield listing the files installed when the given tag is chosen.

Type Name Description
char[] name
uint16_BE_t type A number shared amongst specific flags. Actual meaning is specific to products.
char[divru (header.entries, CHAR_BIT)] files A bitfield that lists which files are installed when the specified tag is installed.

Files Structure

The remainder of the file is populated by a list of files with their content hash, each a variable size (due to the strings). Structure names were invented by the author of this page.

Type Name Description
char[] FileName The name of the file.
char[header.hash_size] hash The hash of the uncompressed file. Usually MD5.
uint32_BE_t Size The size of the file.

C-like structure

char I; char N;
uint8_BE_t _unk3;
uint8_BE_t hash_size;
uint16_BE_t num_tags;
uint32_BE_t num_files;

struct {
  string name;
  uint16_BE_t type;
  char flags[divru (num_files, CHAR_BIT)];
} tags[num_tags];

struct {
  string name;
  char hash[hash_size];
  uint32_BE_t size;
} files[num_files];

Download manifest

The download file lists all files stored in the data archives. The client uses this to download files ahead of time, without it, the client will download on demand which can lead to issues. The download priority is set inside the entries with 0 being the highest and 2 the lowest however, if the game is running, missing assets in the player's vicinity take precedence.

Just like the install file, the download file is shared across all architectures and locales so utilizes the same bitfield-tag system to assess what subset of files are needed.

NOTE: partial-priority download files do not contain the actual file sizes but redefine the FileSize field to ChunkSize.

This file has this structure:

  • Header
  • Entries[Header.EntryCount]
  • Tags[Header.TagsCount]

Download Header

Type Name Description
char[2] Signature The signature for this file (always "DL")
char Version 1 < 7.3.0, 2
char ChecksumSize Always 0x10
char unk ??? Always 1
int [BE] EntryCount The amount of file entries in this file
short [BE] TagCount The amount of tag entries in this file

Download Entry

Type Name Version Added Description
char Unk 2 ??? Appears to be a boolean. Currently only set to 1 on 4 specific records
char[16] Hash 1 This hash is found in every node of the encoding file. (Reverse lookup) MD5
uint40_t [BE] FileSize 1 The compressed size of the file
char DownloadPriority 1 0 = highest, 2 = lowest; -1 for the Install since Battle
char[4] Unk 1 ???

Download Tag

Type Name Description
string Name A C-String indicating this tag's Name.
short [BE] Type Hash type
char[N] Bits an array of size N = Header.EntryCount / 8 + (Header.EntryCount % 8 > 0 ? 1 : 0); that is basically a massive bit mess. Use Schroeppel's 8 bits reverse function on it to have bits.

code-ish

struct {
/*0x00*/  char signature[2];                                // "DL"
          enum {
            download_version_1 = 1,
            download_version_2 = 2,                         // ≥ Legion (7.3.0.???)
            download_version_3 = 3,
          };
/*0x02*/  uint8_BE_t version;
/*0x03*/  uint8_BE_t hash_size_ekey;
/*0x04*/  uint8_BE_t has_checksum_in_entry;
/*0x05*/  uint32_BE_t entry_count;
/*0x09*/  uint16_BE_t tag_count;
/*0x0b*/

#if version ≥ download_version_2
    /*0x0b*/  uint8_BE_t number_of_flag_bytes;             // defaults to 0, up to 4
    /*0x0c*/

   #if version >= download_version_3
       /*0x0c*/  uint8_BE_t base_priority;                 // defaults to 0
       /*0x0d*/  char _unknown_0d[3];                       // As of 1.15.6.2-test4, this is explicitly 0. It is ignored on reading.
       /*0x10*/
   #endif
#endif
} header;

struct {
/*0x00*/  char ekey[header.hash_size_ekey];
/*0x10*/  uint40_BE_t file_size;
/*0x15*/  uint8_BE_t priority;                              // header.base_priority is subtracted on parse
/*0x16*/

#if header.has_checksum_in_entry
/*0x16*/  uint32_BE_t checksum;
/*0x1a*/
#endif

#if header.version ≥ download_version_2
          enum {
            download_flag_plugin = 1,                       // "plugin"
            download_flag_plugin_data = 2,                  // "plugin-data"
          }; 
          uint8_BE_t flags[header.number_of_flag_bytes];    // defaults to 0 if no flag bytes present
#endif

} entries[header.entry_count];

struct {
         char const name[];                                 // this string is zero terminated, no fixed size
                                                            // thus for readability we start offset at 0 here.
/*0+00*/ uint16_BE_t type;                                  // game specific. usually architecture, category, locale, os, region or alike.
/*0+02*/ char mask[divru (header.entry_count._, CHAR_BIT)]; // if bit is set, entries[bit] is part of this tag
/*0x??*/
} tag[header.tag_count];

Download Size

Build 27547 introduced the Download Size file of unknown purpose. The file is a stripped-down Download file with partial EKeys and files sorted by encoded files size. The purpose of this file is not clear.

struct Header
{
	char signature[2];     // "DS"
	uint8_t version;       // only known: 1 (as of agent 6700)
	uint8_t ekeySize;      // 9, up to 23 possible, but agent 6700 hardcodes 9, so, uh.
	uint32_BE_t numFiles;
	uint16_BE_t numTags;
	uint40_BE_t totalSize; // Size of all files combined
};

struct TagEntry
{
	char name[]; // Null-terminated
	uint16_BE_t type;
	char fileMask[(hdr.numFiles + 7) / 8];
}

struct FileEntry
{
	char ekey[hdr.ekeySize];
	uint32_BE_t esize;
};

SizeHeader hdr;
TagEntry tags[hdr.numTags];
FileEntries files[hdr.numFiles]; // Sorted descending by esize

Patch

Type Name Description
char[2] Signature The signature for this file (always "PA")
char version 1 or 2
char file_key_size <= 0x10
char size_b <= 0x10
char patch_key_size <= 0x10
char block_size_bits 2 <= block_size_bits <= 24. block size == 2^block_size_bits.
short block_count
char flags
char[16] EncodingCkey ckey for encoding file
char[16] EncodingEkey ekey for encoding file
int DecodedSize Decoded encoding file size in bytes
int EncodedSize Encoded encoding file size in bytes
char EspecLength Length of the following string
char[EspecLength] EncodingEspec espec of encoding file
char[] ??? byte array containing blocks entries, blocks, and optional patch tail

header+entries needs to be less than 0x10000 bytes (at least in wow-18179). md5sum is only checked for header+entries, file might be larger thus.

struct PatchManifest_Header
{
  uint16_BE_t magic; // 'PA'
  uint8_t version; // 1 or 2
  uint8_t file_key_size; // <= 0x10
  uint8_t size_b; // <= 0x10
  uint8_t patch_key_size; // <= 0x10
  uint8_t block_size_bits; // 12 <= block_size_bits <= 24. max block size == 2^block_size_bits
  uint16_BE_t block_count; // (file_key_size + 20) * entry_count + sizeof (PatchManifest_Header) < 0x10000
  uint8_t flags; // &1: plain-data mode manifest, &2: extended header 

#if encoding_information_apparently_added_after_18179
  uint8_t encoding_ckey[16];
  uint8_t encoding_ekey[16]; // probably since PA2
  uint32_BE_t decoded_size;
  uint32_BE_t encoded_size;
  uint8_t encoding_espec_length;
  char encoding_format[encoding_espec_length];
#endif
 } header;

struct PatchManifest_Block
{
  uint8_t last_file_ckey[header.file_key_size];
  uint8_t md5_of_block[16];
  uint32_BE_t block_offset; // in this file
} blocks[header.block_count]; // sorted ascending by key

// at positions given in PatchManifest_Block
struct block
{
  struct
  {
    uint8_t num_patches; // <= 0x10.
    uint8_t target_file_ckey[header.file_key_size];
    uint40_BE_t decoded_size;
    struct
    {
      uint8_t source_file_ekey[header.file_key_size];
      uint40_BE_t decoded_size;
      uint8_t patch_ekey[header.patch_key_size];
      uint32_BE_t patch_size;
      uint8_t patch_ordinal; // order of patch application, 1-based indexing
    } patches[num_patches];
  } files[]; // count unspecified: read until the next file num_patches would be 0 
               // OR block would exceed max block size
};

// some files have a block of data after the last block of the patch manifest (which may be shorter than max block size). this block appears to be a patch of encoding, but the format is not understood.

Product Specific

In this section, the game/usage specific parts of CASC are described. While CASC is a generic format, a lot of stuff is hardcoded, like hash sizes. Other parts are actually left up to the implementation, like root files or download tags.

World of Warcraft

Root

As of 8.2 there was changes to this format. The client currently (last checked: 9.0.1) parses backwards compatible. There are three changes:

  • The file is now chunked with the old content being in a MFST (ManiFeST) chunk.
  • blocks can be without name hashes and thus ID-only.
  • the name and content hashes are no longer interleaved but two separate arrays
    • In memory, the manifest is kept in a FDID → entry map, so when reverse engineering the parser one may think that fnv1a is relevant, but that’s merely the hashmap insert.
    • To parse that variable format the client uses two pointers to chash/name and a stride (of 16 for key only and 24 for with name) rather than one for records. It also determines the name hash/key hash base pointers depending on format, allowing them to have one parse able to read all format versions.

In 10.1.7.50893 3 ints were added to the header; header size, version and something that's probably padding.

enum locale_flags : uint32_t {
  enUS =     0x2,
  koKR =     0x4,
  frFR =    0x10,
  deDE =    0x20,
  zhCN =    0x40,
  esES =    0x80,
  zhTW =   0x100,
  enGB =   0x200,
  enCN =   0x400,
  enTW =   0x800,
  esMX =  0x1000,
  ruRU =  0x2000,
  ptBR =  0x4000,
  itIT =  0x8000,
  ptPT = 0x10000,
};
enum content_flags : uint32_t {
  Install            =        0x4,            // file is in install manifest
  LoadOnWindows       =        0x8,            // macOS clients do not read block if flags & 0x108 != 0
  LoadOnMacOS         =       0x10,            // windows clients do not read block if flags & 0x110 != 0
  x86_32             =       0x20,            // install manifest file only - load on 32 bit systems
  x86_64             =       0x40,            // install manifest file only - load on 64 bit systems
  LowViolence         =       0x80,
  DoNotLoad          =      0x100,            // neither macOS nor windows clients read blocks with this flag set. LoadOnMysteryPlatform?
  UpdatePlugin       =      0x800,            // only ever set for UpdatePlugin.dll and UpdatePlugin.dylib
  ARM64              =     0x8000,            // install manifest file only - load on ARM64 systems
  Encrypted           =  0x8000000,
  NoNameHash          = 0x10000000,
  UncommonResolution = 0x20000000,            // denotes non-1280px wide cinematics
  Bundle              = 0x40000000,
  NoCompression       = 0x80000000,
};
struct MD5Hash {
  char bytes[0x10];
};

if (format_version == 8.2) {
  uint32_t magic;                        // 'MFST'
#if ≥ DF (10.1.7.50893) 
  uint32_t header_size;
  uint32_t version;
#endif
  uint32_t total_file_count;             // sum of all blocks' num_records
  uint32_t named_file_count;             // sum of those blocks' num_records that have NoNameHash not set
#if ≥ DF (10.1.7.50893) 
  uint32_t likely_padding;
#endif
}

// bool allow_non_named_files = total_file_count ≠ named_file_count || format_version < 8.2;
// bool use_old_record_format = magic ≠ 'MFST';

struct CASBlock {
  uint32_t num_records;
  content_flags flags;
  locale_flags locale;
  int32_t fileDataIDDeltas[num_records]; // each block starts with 0, +1 is implicit per entry, so consecutive ids will have delta=0

  if (use_old_record_format) {
    struct CASRecord {
      MD5Hash content_key;               // MD5 hash of the file's raw data
      uint64_t name_hash;                // Jenkins96 (lookup3) hash of the file's path 
    } records[num_records];
  }
  else {
    MD5Hash content_key[num_records];    // MD5 hash of the file's raw data
    if (!(allow_non_named_files && flags & NoNameHash)) {
      uint64_t name_hash[num_records];   // Jenkins96 (lookup3) hash of the file's path 
    }
  }

  int32 file_data_id (size_t index) const
  {
    return index == 0
      ? fileDataIDDeltas[index]
      : file_data_id (index - 1) + 1 + fileDataIDDeltas[index];
  }
} blocks[];                              // count: fill up until end of file

hashpath

This function is used in the root file by WoW and other older MPQ-based games to calculate filename lookups.

hashpath (string path) → uint32_t
{
  string normalized = toupper (path).replace (from: '/', to: '\\')
  uint32_t pc = 0, pb = 0;
  hashlittle2 (normalized, strlen (normalized), &pc, &pb);
  return pc;
}

Tags

Values depend on versions, semantic categories are cross version.

  • Platform: The deployment target, i.e. Windows or OSX
  • Architecture: Sub-division of the deployment target, i.e. x86_32 or x86_64
  • Locale: The same as in Localization: Files specific to a single localisation of the game.
  • Region: Equivalent to the patch server regions, i.e. us, eu, kr, tw, cn.
  • Category: A replacement for the MPQ system to tag low priority downloads: speech, text
  • Alternate: A special category for censored content.

Version specific values

This section only applies to versions WoD (6.0.1.18125) … WoD (6.0.1.18761).

Architecture = 1, Locale = 2, Platform = 3

This section only applies to versions WoD (6.0.1.18764) … WoD (6.2.2.20426).

Architecture = 1, Category = 2, Locale = 3, Platform = 4, Region = 5

This section only applies to versions WoD (6.2.2.20438) … Legion.

Platform = 1, Architecture = 2, Locale = 3, Region = 4, Category = 5

This section only applies to versions ≥ Battle (8.0.1.26604). Actually alternate was just missing above but schlumpf doesn't want to verify since when.
enum {
  platform = 1,
  architecture = 2,
  locale = 3,
  region = 4,
  category = 5,
  alternate = 0x4000,
};

Shared storage

As of 8.1 both the WoW client and Battle.net app have started supporting sharing storage containers ([CASC]). There is one Data folder in the root folder with storage for multiple products. Products and product-specific data (Cache, Erros, Interface/Addons, Logs, WTF, etc) are stored in subfolders.

Root folder has a .build.info with cached build information for each product sharing the storage, each product subfolder also has a .flavor.info file with the TACT product name (e.g. wowt or wow_classic_beta, should be the same as in .build.info). Both of these files are written by the Battle.net agent and not by the clients themselves. However, if these two files are available the clients will use cached information in the .build.info file instead of getting it from remote.

Armadillo

If $program/blob/game or productconfig contains decryption_key_name, data on CDN is encrypted. The key is retrieved from the keychain or manually entered (a base32 encoded version that contains key and checksum is used). It is stored in $key_name.ak. The key file contains the key followed by a the first four bytes of the md5 hash of the key for verification purposes.

struct {
/*0x00*/  unsigned char key[0x10];
/*0x10*/  unsigned char md5_of_key[0x4];  // first four bytes only
/*0x14*/
} ak_file;

Encryption uses Salsa20. The IV is the last 8 bytes (16 characters) of the cdn hash.

Known keys

decryption_key_name     used_by              key                                                 checksum      base32

# Starcraft 1
sc1Dev                  s1a                  F6 79 DC 38 E0 C3 65 FB 48 2E 48 A7 48 90 9D 29     19 F5 BB 88   6Z45YOHAYNS7WSBOJCTUREE5FEM7LO4I

# Overwatch
pro                     pro (pre-launch)             
proc                    proc3
prolivedev              prodev  
provendor               prov
prolivedev2             prodev

# World of Warcraft
wowdemo                 wowdemo
wowdevalpha             wowdev, wowdev2
wowdev (df press event/end of 2022)          3F 10 3E 3B A7 CA FE 90 26 2E 5C A4 3C E7 BC E5     DB 7F AD 8A   H4ID4O5HZL7JAJROLSSDZZ544XNX7LMK
wowvendor               wowv
wowdark                 wowlivetest2

# Destiny 2
destiny2_openbeta       dst2
destiny_dev             dst2a (pre-alpha)
destiny_event           dst2e1
destiny_live            dst2a
dst2livedev             dst2dev

# Call of Duty: Black Ops 4
viperlivedev            viperdev

# Odin
odinlivedev             odindev

# Orbis
orbislivedev            orbisdev
# Diablo 4
fenrisdev               fenris_dev
fenrise                 fenris_event

CDN File Organization

Data for every CASC-based game exists on the CDN in one of two places at any given time. To reduce file-system and download overhead many files are packed into archives and indexed by archive indices, both of a different format than the CASC installations found on client systems; other "unarchived", "standalone", or "loose" files are stored as separate files on the CDN that must be downloaded independently. There are at least three different reasons why a particular file is found in one or the other:

  1. Small files typically incur larger filesystem overhead and benefit most from being packed into archives. A rough rule of thumb appears to be that files smaller than 2 MB or so are put in archives. Presumably larger files are not archived because they make it more difficult to minimize the number of archive files, which are limited in size (a 2 MB file limit would limit unused space in an archive to under 0.8%, given enough data to form a full archive to begin with).
  2. Key files such as encoding, partial-priority, TVFS (Warcraft 3 root), and the download, install, and patch manifests, as well as their respective patches, are typically stored loose for quick access and are rarely ever found in archives.
  3. As games evolve old files become obsolete and are removed from the CDN. However, the archive system means that archives can only be removed when every file in the archive is no longer needed, potentially wasting large amounts of space on the CDN - the exact opposite of the purpose of bundling files into archives to begin with. Thus as the amount of unused data in an archive grows over time, files still in use may be converted to loose files to allow the archive to be purged from the CDN, even when the files are unusually small to be found independently.

Previously, no official indices/manifests of loose files existed, and they could only be found by subtracting archived files from file lists in encoding or manifest files. Beginning with Warcraft 3 and subsequently being deployed more widely on 7/24/2018, new fields in the CDN config file link to index files containing "all" loose data or patch files on the current CDNs.

Archives

Archives are extensionless 256 MB files that are usually only stored on the Blizzard CDNs. Their naming follows the standard URL hash format using the '/data/' path type.

The structure of the archives is presumably just file fragment after file fragment. You will never need to parse it because you can just look up offset + size of your file fragment in the index files and then take the piece directly out of the archive.

The fragments are all BLTE encoded.

The filename is NOT the hash of the archive content but the hash of the index's footer.

Archive Indexes (.index)

These '.index' files reveal to the user where the compressed game files are located within the archives. All indexes (except the Archive-Group index, see below) are named after their archive (only difference is these have an extension). '.index' files are stored on the CDN using the standard hash naming scheme (remember they have an extension though). They are also located in the directory 'INSTALL_DIR/Data/indices/' for a WoW install. For local indexes (.idx), see the CASC page.

Normal Index Entry Structure

  • The file is divided into 4kb chunks populated by these standard index entries of 0x18 (hex) bytes. Each chunk is zero-padded to a full 4kb, though there may be more than 0x18 bytes of padding at the end of a chunk -- be sure the check for all-null EKey fields. The last chunk is a table-of-contents, listing the LAST EKey in each chunk and checksum of each block. All checksums are the first checksumSize bytes of the MD5 of the respective data. Structure names were invented by the author of this page.
struct index_entry {
  char EKey[footer.keySizeInBytes];
  uint_BE_t(footer.sizeBytes) blte_encoded_size;
  uint_BE_t(footer.offsetBytes) offset_to_blte_encoded_data_in_archive;
};

struct index_block {
  static constexpr const block_size = footer.blockSizeKb << 10;
  index_entry entries[block_size / sizeof (index_entry)];
  char padding[block_size - sizeof (entries)];
} blocks[];

struct {
  struct {
    char last_EKey[footer.keySizeInBytes]; // last EKey of a block
  } entries[num_blocks];

  struct {
    char lower_part_of_md5_of_block[footer.checksumSize]; 
  } blocks_hash[num_blocks];
} toc;

struct { // note: size comments assume 0x10 checksum size
/*0x00*/  char toc_hash[checksumSize]; // client tries to read with 0x10, then backs off in size when smaller
/*0x10*/  char version?;        // always 1
/*0x11*/  char _11;             // 0
/*0x12*/  char _12;             // 0
/*0x13*/  char blockSizeKb?;    // Normally 4. Left-shifted by 10. Believed to be block size in KB.
/*0x14*/  char offsetBytes;     // Normally 4 for archive indices, 5 for patch group indices, 6 for group indices, and 0 for loose file indices
/*0x15*/  char sizeBytes;       // Normally 4
/*0x16*/  char keySizeInBytes;  // Normally 16
/*0x17*/  char checksumSize;    // Normally 8, <= 0x10
/*0x18*/  uint32_t numElements; // BigEndian in _old_ versions (e.g. 18179)
/*0x1C*/  char footerChecksum[checksumSize];
/*0x??*/
} footer;
  • footerChecksum is calculated over the footer beginning with version when footerChecksum is zeroed
  • The archive/index name is the MD5 of the footer beginning with toc_hash

archive-group

archive-group is actually a very special .index file that is typically much larger than other indices. There is no archive attached, it is only the index. Also, the index is not found on the CDN! It is assembled by combining all index files given in the CDN config, on client side. The hash is just for verification purposes. Client side a file is assembled using the normal index file format, for caching.

It has a single difference in format to normal indices: While other indices have their offsetBytes long offset field point into the archive, for archive groups, the field also has an archiveIndex:

struct {
  uint16_BE_t archiveIndex; // Index of the archive in the CDN config's archive list
  uint32_BE_t offsetBytes;  // The offset within the specified archive
};

It does not only having the offset, but also an index into a file. Semantically that's still an offset, so no further field for size is used.

It is suggested you do not just parse indices by .index filename locally but take the config files into account. An easy heuristic is that if offsetBytes is not 4, it is a special index, either loose files or a group.

patch-archives

Patch archives are the /patch/ equivalent to the regular (data) archives on the CDN. Like archives, these are binary blobs of fragments indexed by an accompanying .index file with the same name. Again, the index is a hash, size, offset tuple, but the hash is the content hash rather than an encoding hash.

Most files in patch archives are ZBSDIFF1 blobs, though in principle any file that might be in the /patch/ namespace may be found in patch archives and must be handled accordingly.

patch-archive-group

See archive-group. There is no known difference other than the combined data being patch-archives.

TACT keys

TACT keys are used to encrypt data in files. In most cases, TACT keys are streamed to clients when content (such as cinematics in WoW or skins in Overwatch) is unlocked.

Due to long length/very frequent updates, the list has been moved to TACT/Keys.