Skip to content

Commit e0071b9

Browse files
committed
Add support for BND2 version 5
1 parent 861c470 commit e0071b9

File tree

10 files changed

+753
-358
lines changed

10 files changed

+753
-358
lines changed

README.md

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
# Purpose of this project
2-
This project is aimed at reading BUNDLE archives used in Burnout Paradise.
3-
The project is used in [libapt2](https://github.com/Bo98/libapt2) but might be helpful for others for usage.
1+
# libbndl
42

5-
# Build status
6-
[![Build Status](https://travis-ci.org/Bo98/libbndl.svg?branch=master)](https://travis-ci.org/Bo98/libbndl)
7-
[![Build status](https://ci.appveyor.com/api/projects/status/9ek63lhv0inwcxxr?svg=true)](https://ci.appveyor.com/project/Bo98/libbndl)
3+
A library to read Bundle archives used in titles made by Criterion Games, such as Burnout Paradise, Need For Speed: Hot Pursuit (2010) and Need for Speed: Most Wanted (2012).
84

95
# How to build
106

@@ -18,18 +14,27 @@ $ cmake --build .
1814

1915
```c++
2016
#include <libbndl/bundle.hpp>
21-
#include <iostream>
2217

23-
int main(int argc,char** argv)
18+
int main(int argc, char **argv)
2419
{
2520
// Create a bundle instance
26-
libbndl::Bundle arch;
21+
libbndl::Bundle bundle;
22+
2723
// Load the archive
28-
arch.Load(argv[1]);
29-
// Load an entry from the archive
30-
EntryData *entry = arch.GetBinary(argv[2]);
31-
// etc.
32-
// Remember to delete the EntryData and its data members.
33-
// ...
24+
if (!bundle.Load(argv[1]))
25+
return -1;
26+
27+
// Load a resource from the archive
28+
const auto resource = bundle.GetResource(argv[2]);
29+
if (!resource)
30+
return -2;
31+
32+
// Get the data from the resource binary that's assigned to main memory
33+
const auto buffer = resource->GetBinary(libbndl::MemoryType::MainMemory);
34+
35+
// On the buffer you can use operator[], standard iterator functions or call GetData() to get the underlying pointer.
36+
// Consider using https://github.com/Bo98/libbinaryio to parse the underlying data structures in the resource.
3437
}
3538
```
39+
40+
You can also create new bundles or modify existing ones. See [bundle.hpp](include/libbndl/bundle.hpp) for more information.

include/libbndl/bundle.hpp

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ namespace libbndl
3131
BND2 = 2
3232
};
3333

34-
enum class Platform : uint32_t
34+
enum class Platform : uint16_t
3535
{
3636
PC = 1, // (or PS4/XB1)
3737
Xbox360 = 2,
38-
PS3 = 3
38+
PS3 = 3,
39+
PSVita = 4,
40+
WiiU = 5
3941
};
4042

4143
namespace ResourceType
@@ -307,9 +309,11 @@ namespace libbndl
307309
MainMemory = 0,
308310

309311
GraphicsSystem = 1, // PS3
310-
Physical = 1, // X360
312+
Physical = 1, // Xbox 360
313+
Mem1 = 1, // Wii U
311314

312315
GraphicsLocal = 2, // PS3
316+
GraphicsMem2 = 2, // Wii U
313317

314318
Disposable = 3 // PC in Burnout, all in NFS
315319
};
@@ -326,7 +330,8 @@ namespace libbndl
326330
HasDebugData = 0x8,
327331
NonAsynchFixupRequired = 0x10,
328332
MultistreamBundle = 0x20,
329-
DeltaBundle = 0x40
333+
DeltaBundle = 0x40,
334+
ContainsDefaultResource = 0x80
330335
};
331336

332337
public:
@@ -391,16 +396,18 @@ namespace libbndl
391396
DeltaBundle = 0xC0
392397
};
393398

399+
constexpr ResourceID() noexcept : m_id(0) {}
394400
constexpr ResourceID(uint32_t id, uint16_t type, uint8_t index, EIDType idType) noexcept
395401
: m_id(id | (static_cast<uint64_t>(type) << 32) | (static_cast<uint64_t>(index) << 48) || (static_cast<uint64_t>(idType) << 56)) {}
396402
constexpr explicit ResourceID(UnderlyingType id) noexcept : m_id(id) {}
397403

404+
[[nodiscard]] constexpr bool operator==(const ResourceID &id) const noexcept = default;
398405
[[nodiscard]] constexpr auto operator<=>(const ResourceID &flags) const noexcept = default;
399406
[[nodiscard]] constexpr auto operator==(UnderlyingType id) const noexcept { return m_id == id; };
400407

401408
[[nodiscard]] constexpr uint32_t GetGameChangerID() const noexcept { return m_id & 0xFFFFFFFF; }
402409
[[nodiscard]] constexpr uint32_t GetID32() const noexcept { return GetGameChangerID(); }
403-
[[nodiscard]] constexpr uint16_t GetTypeID() const noexcept { return (m_id >> 32) & 0xFFFF; }
410+
[[nodiscard]] constexpr uint16_t GetResourceTypeID() const noexcept { return (m_id >> 32) & 0xFFFF; }
404411
[[nodiscard]] constexpr uint8_t GetIndex() const noexcept { return (m_id >> 48) & 0xFF; }
405412
[[nodiscard]] constexpr EIDType GetIDType() const noexcept { return static_cast<EIDType>((m_id >> 56) & 0xFF); }
406413

@@ -488,59 +495,62 @@ namespace libbndl
488495
class Resource
489496
{
490497
public:
491-
Resource(std::array<Buffer, 4> buffers, std::vector<Import> imports, uint8_t streamIndex) : m_buffers(std::move(buffers)), m_imports(std::move(imports)), m_streamIndex(streamIndex) {}
498+
Resource(std::array<Buffer, 4> buffers, std::vector<Import> imports) : m_buffers(std::move(buffers)), m_imports(std::move(imports)) {}
492499

493500
[[nodiscard]] constexpr const Buffer &GetBinary(MemoryType block) const { return m_buffers[LIBBNDL_TO_UNDERLYING(block)]; }
494501
[[nodiscard]] constexpr const std::vector<Import> GetImports() const { return m_imports; }
495-
[[nodiscard]] constexpr const uint8_t GetStreamIndex() const { return m_streamIndex; }
496502

497503
void ReplaceBinary(MemoryType block, Buffer &&buffer) { m_buffers[LIBBNDL_TO_UNDERLYING(block)] = std::move(buffer); }
498504

499505
private:
500506
std::array<Buffer, 4> m_buffers;
501507
std::vector<Import> m_imports;
502-
uint8_t m_streamIndex;
503508
};
504509

505510
class Bundle
506511
{
507512
public:
508513
LIBBNDL_EXPORT Bundle();
509-
LIBBNDL_EXPORT Bundle(MagicNumber magicNumber, uint32_t version, Platform platform, Flags flags); // For creating new bundles
514+
LIBBNDL_EXPORT Bundle(MagicNumber magicNumber, uint16_t version, Platform platform, Flags flags); // For creating new bundles
510515
LIBBNDL_EXPORT ~Bundle();
511516

512517
LIBBNDL_EXPORT bool Load(const std::string &name);
513518
LIBBNDL_EXPORT bool Save(const std::string &name);
514519

515-
LIBBNDL_EXPORT [[nodiscard]] MagicNumber GetMagicNumber() const;
516-
LIBBNDL_EXPORT [[nodiscard]] uint32_t GetVersion() const;
517-
LIBBNDL_EXPORT [[nodiscard]] Platform GetPlatform() const;
518-
LIBBNDL_EXPORT [[nodiscard]] Flags GetFlags() const;
520+
[[nodiscard]] LIBBNDL_EXPORT MagicNumber GetMagicNumber() const;
521+
[[nodiscard]] LIBBNDL_EXPORT uint16_t GetVersion() const;
522+
[[nodiscard]] LIBBNDL_EXPORT Platform GetPlatform() const;
523+
[[nodiscard]] LIBBNDL_EXPORT Flags GetFlags() const;
519524

520-
LIBBNDL_EXPORT [[nodiscard]] bool IsBurnoutEra() const;
521-
LIBBNDL_EXPORT [[nodiscard]] bool IsNeedForSpeedEra() const;
525+
[[nodiscard]] LIBBNDL_EXPORT bool IsBurnoutEra() const;
526+
[[nodiscard]] LIBBNDL_EXPORT bool IsNeedForSpeedEra() const;
522527

523-
LIBBNDL_EXPORT [[nodiscard]] std::optional<ResourceDebugInfo> GetResourceDebugInfo(const std::string &resourceName) const;
524-
LIBBNDL_EXPORT [[nodiscard]] std::optional<ResourceDebugInfo> GetResourceDebugInfo(ResourceID resourceID) const;
525-
LIBBNDL_EXPORT [[nodiscard]] std::optional<uint32_t> GetResourceType(const std::string &resourceName) const;
526-
LIBBNDL_EXPORT [[nodiscard]] std::optional<uint32_t> GetResourceType(ResourceID resourceID) const;
527-
LIBBNDL_EXPORT [[nodiscard]] std::optional<Resource> GetResource(const std::string &resourceName) const;
528-
LIBBNDL_EXPORT [[nodiscard]] std::optional<Resource> GetResource(ResourceID resourceID) const;
529-
LIBBNDL_EXPORT [[nodiscard]] Buffer GetBinary(const std::string &resourceName, MemoryType memoryType) const;
530-
LIBBNDL_EXPORT [[nodiscard]] Buffer GetBinary(ResourceID resourceID, MemoryType memoryType) const;
528+
[[nodiscard]] LIBBNDL_EXPORT std::optional<ResourceDebugInfo> GetResourceDebugInfo(const std::string &resourceName, uint8_t streamIndex = 0) const;
529+
[[nodiscard]] LIBBNDL_EXPORT std::optional<ResourceDebugInfo> GetResourceDebugInfo(ResourceID resourceID, uint8_t streamIndex = 0) const;
530+
[[nodiscard]] LIBBNDL_EXPORT std::optional<uint32_t> GetResourceType(const std::string &resourceName, uint8_t streamIndex = 0) const;
531+
[[nodiscard]] LIBBNDL_EXPORT std::optional<uint32_t> GetResourceType(ResourceID resourceID, uint8_t streamIndex = 0) const;
532+
[[nodiscard]] LIBBNDL_EXPORT std::optional<Resource> GetResource(const std::string &resourceName, uint8_t streamIndex = 0) const;
533+
[[nodiscard]] LIBBNDL_EXPORT std::optional<Resource> GetResource(ResourceID resourceID, uint8_t streamIndex = 0) const;
534+
[[nodiscard]] LIBBNDL_EXPORT Buffer GetBinary(const std::string &resourceName, MemoryType memoryType, uint8_t streamIndex = 0) const;
535+
[[nodiscard]] LIBBNDL_EXPORT Buffer GetBinary(ResourceID resourceID, MemoryType memoryType, uint8_t streamIndex = 0) const;
531536

532-
LIBBNDL_EXPORT bool AddResource(const std::string &resourceName, const Resource &data, uint32_t resourceType);
533-
LIBBNDL_EXPORT bool AddResource(ResourceID resourceID, const Resource &data, uint32_t resourceType);
534-
LIBBNDL_EXPORT bool AddResourceDebugInfo(const std::string &resourceName, const std::string &name, const std::string &type);
535-
LIBBNDL_EXPORT bool AddResourceDebugInfo(ResourceID resourceID, const std::string &name, const std::string &type);
537+
LIBBNDL_EXPORT bool AddResource(const std::string &resourceName, const Resource &data, uint32_t resourceType, uint8_t streamIndex = 0);
538+
LIBBNDL_EXPORT bool AddResource(ResourceID resourceID, const Resource &data, uint32_t resourceType, uint8_t streamIndex = 0);
539+
LIBBNDL_EXPORT bool AddResourceDebugInfo(const std::string &resourceName, const std::string &name, const std::string &type, uint8_t streamIndex = 0);
540+
LIBBNDL_EXPORT bool AddResourceDebugInfo(ResourceID resourceID, const std::string &name, const std::string &type, uint8_t streamIndex = 0);
536541

537-
LIBBNDL_EXPORT bool ReplaceResource(const std::string &resourceName, const Resource &data);
538-
LIBBNDL_EXPORT bool ReplaceResource(ResourceID resourceID, const Resource &data);
542+
LIBBNDL_EXPORT bool ReplaceResource(const std::string &resourceName, const Resource &data, uint8_t streamIndex = 0);
543+
LIBBNDL_EXPORT bool ReplaceResource(ResourceID resourceID, const Resource &data, uint8_t streamIndex = 0);
539544

540-
LIBBNDL_EXPORT [[nodiscard]] std::vector<ResourceID> GetResourceIDs() const;
541-
LIBBNDL_EXPORT [[nodiscard]] std::map<uint32_t, std::vector<ResourceID>> GetResourceIDsByType() const;
545+
[[nodiscard]] LIBBNDL_EXPORT std::vector<ResourceID> GetResourceIDs() const;
546+
[[nodiscard]] LIBBNDL_EXPORT std::map<uint32_t, std::vector<ResourceID>> GetResourceIDsByType() const;
547+
[[nodiscard]] LIBBNDL_EXPORT std::vector<uint8_t> GetResourceStreamIndices(ResourceID resourceID) const;
542548

543-
LIBBNDL_EXPORT [[nodiscard]] std::vector<MemoryType> GetMemoryTypes() const;
549+
[[nodiscard]] LIBBNDL_EXPORT ResourceID GetDefaultResourceID() const;
550+
[[nodiscard]] LIBBNDL_EXPORT int32_t GetDefaultResourceStreamIndex() const;
551+
[[nodiscard]] LIBBNDL_EXPORT std::string GetStreamName(uint8_t index) const;
552+
553+
[[nodiscard]] LIBBNDL_EXPORT std::vector<MemoryType> GetMemoryTypes() const;
544554

545555
private:
546556
std::unique_ptr<Formats::Base> m_impl;

src/bundle.cpp

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ using namespace libbndl;
1212

1313
Bundle::Bundle() = default;
1414

15-
Bundle::Bundle(MagicNumber magicNumber, uint32_t version, Platform platform, Flags flags)
15+
Bundle::Bundle(MagicNumber magicNumber, uint16_t version, Platform platform, Flags flags)
1616
{
1717
switch (magicNumber)
1818
{
@@ -86,7 +86,7 @@ MagicNumber Bundle::GetMagicNumber() const
8686
return m_impl->GetMagicNumber();
8787
}
8888

89-
uint32_t Bundle::GetVersion() const
89+
uint16_t Bundle::GetVersion() const
9090
{
9191
return m_impl->GetVersion();
9292
}
@@ -117,78 +117,78 @@ ResourceID Bundle::HashResourceName(std::string resourceName) const
117117
return ResourceID(crc32_z(0, reinterpret_cast<const Bytef *>(resourceName.c_str()), resourceName.length()));
118118
}
119119

120-
std::optional<Resource> Bundle::GetResource(const std::string &resourceName) const
120+
std::optional<Resource> Bundle::GetResource(const std::string &resourceName, uint8_t streamIndex) const
121121
{
122-
return GetResource(HashResourceName(resourceName));
122+
return GetResource(HashResourceName(resourceName), streamIndex);
123123
}
124124

125-
std::optional<Resource> Bundle::GetResource(ResourceID resourceID) const
125+
std::optional<Resource> Bundle::GetResource(ResourceID resourceID, uint8_t streamIndex) const
126126
{
127-
return m_impl->GetResource(resourceID);
127+
return m_impl->GetResource({ resourceID, streamIndex });
128128
}
129129

130-
Buffer Bundle::GetBinary(const std::string &resourceName, MemoryType memoryType) const
130+
Buffer Bundle::GetBinary(const std::string &resourceName, MemoryType memoryType, uint8_t streamIndex) const
131131
{
132-
return GetBinary(HashResourceName(resourceName), memoryType);
132+
return GetBinary(HashResourceName(resourceName), memoryType, streamIndex);
133133
}
134134

135-
Buffer Bundle::GetBinary(ResourceID resourceID, MemoryType memoryType) const
135+
Buffer Bundle::GetBinary(ResourceID resourceID, MemoryType memoryType, uint8_t streamIndex) const
136136
{
137-
return m_impl->GetBinary(resourceID, memoryType);
137+
return m_impl->GetBinary({ resourceID, streamIndex }, memoryType);
138138
}
139139

140-
std::optional<ResourceDebugInfo> Bundle::GetResourceDebugInfo(const std::string &resourceName) const
140+
std::optional<ResourceDebugInfo> Bundle::GetResourceDebugInfo(const std::string &resourceName, uint8_t streamIndex) const
141141
{
142-
return GetResourceDebugInfo(HashResourceName(resourceName));
142+
return GetResourceDebugInfo(HashResourceName(resourceName), streamIndex);
143143
}
144144

145-
std::optional<ResourceDebugInfo> Bundle::GetResourceDebugInfo(ResourceID resourceID) const
145+
std::optional<ResourceDebugInfo> Bundle::GetResourceDebugInfo(ResourceID resourceID, uint8_t streamIndex) const
146146
{
147-
const auto &internalDebugInfo = m_impl->GetResourceDebugInfo(resourceID);
148-
if (!internalDebugInfo.has_value())
147+
const auto &internalDebugInfo = m_impl->GetResourceDebugInfo({ resourceID, streamIndex });
148+
if (!internalDebugInfo)
149149
return {};
150150

151151
return ResourceDebugInfo{ internalDebugInfo->name, internalDebugInfo->typeName };
152152
}
153153

154-
std::optional<uint32_t> Bundle::GetResourceType(const std::string &resourceName) const
154+
std::optional<uint32_t> Bundle::GetResourceType(const std::string &resourceName, uint8_t streamIndex) const
155155
{
156-
return GetResourceType(HashResourceName(resourceName));
156+
return GetResourceType(HashResourceName(resourceName), streamIndex);
157157
}
158158

159-
std::optional<uint32_t> Bundle::GetResourceType(ResourceID resourceID) const
159+
std::optional<uint32_t> Bundle::GetResourceType(ResourceID resourceID, uint8_t streamIndex) const
160160
{
161-
return m_impl->GetResourceType(resourceID);
161+
return m_impl->GetResourceType({ resourceID, streamIndex });
162162
}
163163

164-
bool Bundle::AddResource(const std::string &resourceName, const Resource &resource, uint32_t resourceType)
164+
bool Bundle::AddResource(const std::string &resourceName, const Resource &resource, uint32_t resourceType, uint8_t streamIndex)
165165
{
166-
return AddResource(HashResourceName(resourceName), resource, resourceType);
166+
return AddResource(HashResourceName(resourceName), resource, resourceType, streamIndex);
167167
}
168168

169-
bool Bundle::AddResource(ResourceID resourceID, const Resource &resource, uint32_t resourceType)
169+
bool Bundle::AddResource(ResourceID resourceID, const Resource &resource, uint32_t resourceType, uint8_t streamIndex)
170170
{
171-
return m_impl->AddResource(resourceID, resource, resourceType);
171+
return m_impl->AddResource({ resourceID, streamIndex }, resource, resourceType);
172172
}
173173

174-
bool Bundle::AddResourceDebugInfo(const std::string &resourceName, const std::string &name, const std::string &type)
174+
bool Bundle::AddResourceDebugInfo(const std::string &resourceName, const std::string &name, const std::string &type, uint8_t streamIndex)
175175
{
176-
return AddResourceDebugInfo(HashResourceName(resourceName), name, type);
176+
return AddResourceDebugInfo(HashResourceName(resourceName), name, type, streamIndex);
177177
}
178178

179-
bool Bundle::AddResourceDebugInfo(ResourceID resourceID, const std::string &name, const std::string &type)
179+
bool Bundle::AddResourceDebugInfo(ResourceID resourceID, const std::string &name, const std::string &type, uint8_t streamIndex)
180180
{
181-
return m_impl->AddResourceDebugInfo(resourceID, name, type);
181+
return m_impl->AddResourceDebugInfo({ resourceID, streamIndex }, name, type);
182182
}
183183

184-
bool Bundle::ReplaceResource(const std::string &resourceName, const Resource &resource)
184+
bool Bundle::ReplaceResource(const std::string &resourceName, const Resource &resource, uint8_t streamIndex)
185185
{
186-
return ReplaceResource(HashResourceName(resourceName), resource);
186+
return ReplaceResource(HashResourceName(resourceName), resource, streamIndex);
187187
}
188188

189-
bool Bundle::ReplaceResource(ResourceID resourceID, const Resource &resource)
189+
bool Bundle::ReplaceResource(ResourceID resourceID, const Resource &resource, uint8_t streamIndex)
190190
{
191-
return m_impl->ReplaceResource(resourceID, resource);
191+
return m_impl->ReplaceResource({ resourceID, streamIndex }, resource);
192192
}
193193

194194
std::vector<ResourceID> Bundle::GetResourceIDs() const
@@ -201,6 +201,26 @@ std::map<uint32_t, std::vector<ResourceID>> Bundle::GetResourceIDsByType() const
201201
return m_impl->GetResourceIDsByType();
202202
}
203203

204+
std::vector<uint8_t> Bundle::GetResourceStreamIndices(ResourceID resourceID) const
205+
{
206+
return m_impl->GetResourceStreamIndices(resourceID);
207+
}
208+
209+
ResourceID Bundle::GetDefaultResourceID() const
210+
{
211+
return m_impl->GetDefaultResourceID();
212+
}
213+
214+
int32_t Bundle::GetDefaultResourceStreamIndex() const
215+
{
216+
return m_impl->GetDefaultResourceStreamIndex();
217+
}
218+
219+
std::string Bundle::GetStreamName(uint8_t index) const
220+
{
221+
return m_impl->GetStreamName(index);
222+
}
223+
204224
std::vector<MemoryType> Bundle::GetMemoryTypes() const
205225
{
206226
return m_impl->GetMemoryTypes();

0 commit comments

Comments
 (0)