Skip to content

Commit

Permalink
Add BPS support
Browse files Browse the repository at this point in the history
  • Loading branch information
snesrev committed Aug 17, 2023
1 parent 43db8cc commit fbbb3f9
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 3 deletions.
16 changes: 13 additions & 3 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,9 +811,19 @@ uint32 g_asset_sizes[kNumberOfAssets];
static void LoadAssets() {
size_t length = 0;
uint8 *data = ReadWholeFile("zelda3_assets.dat", &length);
if (!data)
data = ReadWholeFile("tables/zelda3_assets.dat", &length);
if (!data) Die("Failed to read zelda3_assets.dat. Please see the README for information about how you get this file.");
if (!data) {
size_t bps_length, bps_src_length;
uint8 *bps, *bps_src;
bps = ReadWholeFile("zelda3_assets.bps", &bps_length);
if (!bps)
Die("Failed to read zelda3_assets.dat. Please see the README for information about how you get this file.");
bps_src = ReadWholeFile("zelda3.sfc", &bps_src_length);
if (!bps_src)
Die("Missing file: zelda3.sfc");
data = ApplyBps(bps_src, bps_src_length, bps, bps_length, &length);
if (!data)
Die("Unable to apply zelda3_assets.bps. Please make sure you got the right version of 'zelda3.sfc'");
}

static const char kAssetsSig[] = { kAssets_Sig };

Expand Down
85 changes: 85 additions & 0 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,88 @@ MemBlk FindIndexInMemblk(MemBlk data, size_t i) {
return (MemBlk) { 0, 0 };
return (MemBlk) { data.ptr + left_off, right_off - left_off };
}


static uint64 BpsDecodeInt(const uint8 **src) {
uint64 data = 0, shift = 1;
while(true) {
uint8 x = *(*src)++;
data += (x & 0x7f) * shift;
if(x & 0x80) break;
shift <<= 7;
data += shift;
}
return data;
}

#define CRC32_POLYNOMIAL 0xEDB88320

static uint32 crc32(const void *data, size_t length) {
uint32 crc = 0xFFFFFFFF;
const uint8 *byteData = (const uint8 *)data;
for (size_t i = 0; i < length; i++) {
crc ^= byteData[i];
for (int j = 0; j < 8; j++)
crc = (crc >> 1) ^ ((crc & 1) * CRC32_POLYNOMIAL);
}
return crc ^ 0xFFFFFFFF;
}

uint8 *ApplyBps(const uint8 *src, size_t src_size_in,
const uint8 *bps, size_t bps_size, size_t *length_out) {
const uint8 *bps_end = bps + bps_size - 12;

if (memcmp(bps, "BPS1", 4))
return NULL;
if (crc32(src, src_size_in) != *(uint32 *)(bps_end))
return NULL;
if (crc32(bps, bps_size - 4) != *(uint32 *)(bps_end + 8))
return NULL;

bps += 4;
uint32 src_size = BpsDecodeInt(&bps);
uint32 dst_size = BpsDecodeInt(&bps);
uint32 meta_size = BpsDecodeInt(&bps);
uint32 outputOffset = 0;
uint32 sourceRelativeOffset = 0;
uint32 targetRelativeOffset = 0;
if (src_size != src_size_in)
return NULL;
*length_out = dst_size;
uint8 *dst = malloc(dst_size);
if (!dst)
return NULL;
while (bps < bps_end) {
uint32 cmd = BpsDecodeInt(&bps);
uint32 length = (cmd >> 2) + 1;
switch (cmd & 3) {
case 0:
while(length--) {
dst[outputOffset] = src[outputOffset];
outputOffset++;
}
break;
case 1:
while (length--)
dst[outputOffset++] = *bps++;
break;
case 2:
cmd = BpsDecodeInt(&bps);
sourceRelativeOffset += (cmd & 1 ? -1 : +1) * (cmd >> 1);
while (length--)
dst[outputOffset++] = src[sourceRelativeOffset++];
break;
default:
cmd = BpsDecodeInt(&bps);
targetRelativeOffset += (cmd & 1 ? -1 : +1) * (cmd >> 1);
while(length--)
dst[outputOffset++] = dst[targetRelativeOffset++];
break;
}
}
if (dst_size != outputOffset)
return NULL;
if (crc32(dst, dst_size) != *(uint32 *)(bps_end + 4))
return NULL;
return dst;
}
2 changes: 2 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,7 @@ const char *SkipPrefix(const char *big, const char *little);
void StrSet(char **rv, const char *s);
char *StrFmt(const char *fmt, ...);
char *ReplaceFilenameWithNewPath(const char *old_path, const char *new_path);
uint8 *ApplyBps(const uint8 *src, size_t src_size_in,
const uint8 *bps, size_t bps_size, size_t *length_out);

#endif // ZELDA3_UTIL_H_
1 change: 1 addition & 0 deletions zelda3.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
<TreatWarningAsError>true</TreatWarningAsError>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
Expand Down

0 comments on commit fbbb3f9

Please sign in to comment.