-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
xbescanner: Adds mechanism to load save game icons.
- Loading branch information
Showing
12 changed files
with
256 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule s3tc-dxt-decompression
added at
17074c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#include "xbeInfo.h" | ||
#include "infoLog.h" | ||
|
||
XBEInfo::Icon XBEInfo::loadSaveGameIcon() const { | ||
Icon ret; | ||
if (saveGameXPROffset <= 0 || saveGameXPRSize <= 0) { | ||
return ret; | ||
} | ||
|
||
XPR0Image compressedImage; | ||
if (!loadCompressedSaveGameIcon(compressedImage)) { | ||
InfoLog::outputLine("Failed to load save game icon from %s", path.c_str()); | ||
return ret; | ||
} | ||
|
||
if (!compressedImage.decompress(ret.imageData)) { | ||
InfoLog::outputLine("Failed to decompress save game icon from %s", path.c_str()); | ||
return ret; | ||
} | ||
|
||
ret.width = compressedImage.width; | ||
ret.height = compressedImage.height; | ||
|
||
return ret; | ||
} | ||
|
||
bool XBEInfo::loadCompressedSaveGameIcon(XPR0Image& image) const { | ||
image.clear(); | ||
FILE* xbeFile = fopen(path.c_str(), "rb"); | ||
if (!xbeFile) { | ||
return false; | ||
} | ||
|
||
fseek(xbeFile, saveGameXPROffset, SEEK_SET); | ||
std::vector<uint8_t> buffer(saveGameXPRSize); | ||
size_t bytesRead = fread(buffer.data(), 1, saveGameXPRSize, xbeFile); | ||
fclose(xbeFile); | ||
|
||
if (bytesRead != saveGameXPRSize) { | ||
InfoLog::outputLine("Failed to read save game image from %s", path.c_str()); | ||
return false; | ||
} | ||
|
||
return image.parse(buffer); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#ifndef NEVOLUTIONX_XBEINFO_H | ||
#define NEVOLUTIONX_XBEINFO_H | ||
|
||
#include <string> | ||
#include <vector> | ||
#include "xpr0Image.h" | ||
|
||
class XBEInfo { | ||
public: | ||
// TODO: See if the DXT1 compressed image can be used directly by the hardware instead. | ||
struct Icon { | ||
// imageData is always 32-bit color. | ||
std::vector<unsigned char> imageData; | ||
uint32_t width{ 0 }; | ||
uint32_t height{ 0 }; | ||
}; | ||
|
||
XBEInfo(std::string xbeTitle, std::string xbePath, long xprOffset, size_t xprSize) : | ||
title(std::move(xbeTitle)), path(std::move(xbePath)), saveGameXPROffset(xprOffset), | ||
saveGameXPRSize(xprSize) {} | ||
|
||
Icon loadSaveGameIcon() const; | ||
bool loadCompressedSaveGameIcon(XPR0Image& image) const; | ||
|
||
std::string title; | ||
std::string path; | ||
|
||
private: | ||
long saveGameXPROffset{ 0 }; | ||
size_t saveGameXPRSize{ 0 }; | ||
}; | ||
|
||
#endif // NEVOLUTIONX_XBEINFO_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#include "xpr0Image.h" | ||
#include "3rdparty/s3tc-dxt-decompression/s3tc.h" | ||
#include "infoLog.h" | ||
|
||
static const uint32_t XPR0_MAGIC = 0x30525058; | ||
|
||
bool XPR0Image::parse(const std::vector<uint8_t>& buffer) { | ||
auto& header = *reinterpret_cast<XPRHeader const*>(buffer.data()); | ||
if (header.magic != XPR0_MAGIC) { | ||
InfoLog::outputLine("Unexpected magic bytes %X in XPR0", header.magic); | ||
return false; | ||
} | ||
|
||
static const uint32_t FORMAT_MASK = 0x0000FF00; | ||
format = header.resourceInfo.format & FORMAT_MASK; | ||
|
||
static const uint32_t FORMAT_DXT1 = 0x00000C00; | ||
// TODO: Investigate whether formats other than DXT1 are ever used. | ||
if (format != FORMAT_DXT1) { | ||
InfoLog::outputLine("Unexpected format %X (!=DXT1) in XPR0", header.resourceInfo.format); | ||
return false; | ||
} | ||
|
||
uint32_t dataSize = header.totalSize - header.headerSize; | ||
if (dataSize > buffer.size()) { | ||
InfoLog::outputLine("Buffer size too small (%u < %u) in XPR0", buffer.size(), dataSize); | ||
} | ||
|
||
static const uint32_t UV_SIZE_MASK = 0x0FF00000; | ||
static const uint32_t U_SHIFT = 20; | ||
static const uint32_t V_SHIFT = 24; | ||
const uint32_t sizeInfo = header.resourceInfo.format & UV_SIZE_MASK; | ||
width = 1 << ((sizeInfo >> U_SHIFT) & 0x0F); | ||
height = 1 << ((sizeInfo >> V_SHIFT) & 0x0F); | ||
|
||
auto imageDataStart = buffer.cbegin() + static_cast<int>(header.headerSize); | ||
imageData = std::vector<uint8_t>(imageDataStart, buffer.cend()); | ||
|
||
return true; | ||
} | ||
|
||
bool XPR0Image::decompress(std::vector<uint8_t>& output) const { | ||
output.resize(width * height * 4); | ||
return decompress(output.data()); | ||
} | ||
|
||
bool XPR0Image::decompress(uint8_t* output) const { | ||
BlockDecompressImageDXT1(width, height, imageData.data(), (unsigned long*)output); | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#ifndef NEVOLUTIONX_XPR0IMAGE_H | ||
#define NEVOLUTIONX_XPR0IMAGE_H | ||
|
||
#include <cstdint> | ||
#include <vector> | ||
|
||
// Encapsulates information about an XPR0 image. | ||
class XPR0Image { | ||
public: | ||
struct ResourceInfo { | ||
uint32_t common; | ||
uint32_t data; | ||
uint32_t lock; | ||
uint32_t format; | ||
uint32_t size; | ||
}; | ||
|
||
struct XPRHeader { | ||
uint32_t magic; | ||
uint32_t totalSize; | ||
uint32_t headerSize; | ||
ResourceInfo resourceInfo; | ||
uint32_t endOfHeader; // Should always == 0xFFFFFFFF | ||
}; | ||
|
||
// Populates this XPR0Image from the given data buffer. | ||
bool parse(std::vector<uint8_t> const& buffer); | ||
|
||
// Copies 32bpp decompressed image data into the given `output` buffer. | ||
// | ||
// Returns true if the operation succeded, false if there was an error. | ||
bool decompress(std::vector<uint8_t>& output) const; | ||
|
||
bool decompress(uint8_t* output) const; | ||
|
||
void clear() { | ||
width = height = format = 0; | ||
imageData.clear(); | ||
} | ||
|
||
uint32_t width{ 0 }; | ||
uint32_t height{ 0 }; | ||
uint32_t format; | ||
std::vector<uint8_t> imageData; | ||
}; | ||
|
||
#endif // NEVOLUTIONX_XPR0IMAGE_H |
Oops, something went wrong.