Skip to content

Commit fbbb3f9

Browse files
committed
Add BPS support
1 parent 43db8cc commit fbbb3f9

File tree

4 files changed

+101
-3
lines changed

4 files changed

+101
-3
lines changed

src/main.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -811,9 +811,19 @@ uint32 g_asset_sizes[kNumberOfAssets];
811811
static void LoadAssets() {
812812
size_t length = 0;
813813
uint8 *data = ReadWholeFile("zelda3_assets.dat", &length);
814-
if (!data)
815-
data = ReadWholeFile("tables/zelda3_assets.dat", &length);
816-
if (!data) Die("Failed to read zelda3_assets.dat. Please see the README for information about how you get this file.");
814+
if (!data) {
815+
size_t bps_length, bps_src_length;
816+
uint8 *bps, *bps_src;
817+
bps = ReadWholeFile("zelda3_assets.bps", &bps_length);
818+
if (!bps)
819+
Die("Failed to read zelda3_assets.dat. Please see the README for information about how you get this file.");
820+
bps_src = ReadWholeFile("zelda3.sfc", &bps_src_length);
821+
if (!bps_src)
822+
Die("Missing file: zelda3.sfc");
823+
data = ApplyBps(bps_src, bps_src_length, bps, bps_length, &length);
824+
if (!data)
825+
Die("Unable to apply zelda3_assets.bps. Please make sure you got the right version of 'zelda3.sfc'");
826+
}
817827

818828
static const char kAssetsSig[] = { kAssets_Sig };
819829

src/util.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,88 @@ MemBlk FindIndexInMemblk(MemBlk data, size_t i) {
193193
return (MemBlk) { 0, 0 };
194194
return (MemBlk) { data.ptr + left_off, right_off - left_off };
195195
}
196+
197+
198+
static uint64 BpsDecodeInt(const uint8 **src) {
199+
uint64 data = 0, shift = 1;
200+
while(true) {
201+
uint8 x = *(*src)++;
202+
data += (x & 0x7f) * shift;
203+
if(x & 0x80) break;
204+
shift <<= 7;
205+
data += shift;
206+
}
207+
return data;
208+
}
209+
210+
#define CRC32_POLYNOMIAL 0xEDB88320
211+
212+
static uint32 crc32(const void *data, size_t length) {
213+
uint32 crc = 0xFFFFFFFF;
214+
const uint8 *byteData = (const uint8 *)data;
215+
for (size_t i = 0; i < length; i++) {
216+
crc ^= byteData[i];
217+
for (int j = 0; j < 8; j++)
218+
crc = (crc >> 1) ^ ((crc & 1) * CRC32_POLYNOMIAL);
219+
}
220+
return crc ^ 0xFFFFFFFF;
221+
}
222+
223+
uint8 *ApplyBps(const uint8 *src, size_t src_size_in,
224+
const uint8 *bps, size_t bps_size, size_t *length_out) {
225+
const uint8 *bps_end = bps + bps_size - 12;
226+
227+
if (memcmp(bps, "BPS1", 4))
228+
return NULL;
229+
if (crc32(src, src_size_in) != *(uint32 *)(bps_end))
230+
return NULL;
231+
if (crc32(bps, bps_size - 4) != *(uint32 *)(bps_end + 8))
232+
return NULL;
233+
234+
bps += 4;
235+
uint32 src_size = BpsDecodeInt(&bps);
236+
uint32 dst_size = BpsDecodeInt(&bps);
237+
uint32 meta_size = BpsDecodeInt(&bps);
238+
uint32 outputOffset = 0;
239+
uint32 sourceRelativeOffset = 0;
240+
uint32 targetRelativeOffset = 0;
241+
if (src_size != src_size_in)
242+
return NULL;
243+
*length_out = dst_size;
244+
uint8 *dst = malloc(dst_size);
245+
if (!dst)
246+
return NULL;
247+
while (bps < bps_end) {
248+
uint32 cmd = BpsDecodeInt(&bps);
249+
uint32 length = (cmd >> 2) + 1;
250+
switch (cmd & 3) {
251+
case 0:
252+
while(length--) {
253+
dst[outputOffset] = src[outputOffset];
254+
outputOffset++;
255+
}
256+
break;
257+
case 1:
258+
while (length--)
259+
dst[outputOffset++] = *bps++;
260+
break;
261+
case 2:
262+
cmd = BpsDecodeInt(&bps);
263+
sourceRelativeOffset += (cmd & 1 ? -1 : +1) * (cmd >> 1);
264+
while (length--)
265+
dst[outputOffset++] = src[sourceRelativeOffset++];
266+
break;
267+
default:
268+
cmd = BpsDecodeInt(&bps);
269+
targetRelativeOffset += (cmd & 1 ? -1 : +1) * (cmd >> 1);
270+
while(length--)
271+
dst[outputOffset++] = dst[targetRelativeOffset++];
272+
break;
273+
}
274+
}
275+
if (dst_size != outputOffset)
276+
return NULL;
277+
if (crc32(dst, dst_size) != *(uint32 *)(bps_end + 4))
278+
return NULL;
279+
return dst;
280+
}

src/util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,7 @@ const char *SkipPrefix(const char *big, const char *little);
3535
void StrSet(char **rv, const char *s);
3636
char *StrFmt(const char *fmt, ...);
3737
char *ReplaceFilenameWithNewPath(const char *old_path, const char *new_path);
38+
uint8 *ApplyBps(const uint8 *src, size_t src_size_in,
39+
const uint8 *bps, size_t bps_size, size_t *length_out);
3840

3941
#endif // ZELDA3_UTIL_H_

zelda3.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@
202202
<TreatWarningAsError>true</TreatWarningAsError>
203203
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
204204
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
205+
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
205206
</ClCompile>
206207
<Link>
207208
<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>

0 commit comments

Comments
 (0)