mirror of https://github.com/zeldaret/mm.git
git subrepo pull tools/z64compress --force
subrepo: subdir: "tools/z64compress" merged: "43035d97f" upstream: origin: "https://github.com/z64me/z64compress.git" branch: "main" commit: "43035d97f" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
parent
768094b1a8
commit
2e487b5008
|
@ -0,0 +1,3 @@
|
|||
[submodule "src/enc/libdeflate"]
|
||||
path = src/enc/libdeflate
|
||||
url = https://github.com/ebiggers/libdeflate
|
|
@ -6,7 +6,7 @@
|
|||
[subrepo]
|
||||
remote = https://github.com/z64me/z64compress.git
|
||||
branch = main
|
||||
commit = 5da3132606e4fd427a8d72b8428e4f921cd6e56f
|
||||
parent = 837eb1c80687fe9b57a3c7b841547c33feeed6c7
|
||||
commit = 43035d97f2e750332d9644438bc4f687f073a4dd
|
||||
parent = 768094b1a889b2253b3e905b99792efaecd3e879
|
||||
method = merge
|
||||
cmdver = 0.4.3
|
||||
|
|
|
@ -24,10 +24,12 @@ endif
|
|||
|
||||
OBJ_DIR := o/$(TARGET)
|
||||
|
||||
$(OBJ_DIR)/src/enc/%.o: CFLAGS := -DNDEBUG -s -Ofast -flto -Wall
|
||||
$(OBJ_DIR)/src/enc/%.o: CFLAGS := -DNDEBUG -s -Ofast -flto -Wall -Isrc/enc/libdeflate
|
||||
|
||||
SRC_DIRS := $(shell find src -type d)
|
||||
C_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||
C_DIRS := $(shell find src -type d -not -path "src/enc/libdeflate/*")
|
||||
C_FILES := $(foreach dir,$(C_DIRS),$(wildcard $(dir)/*.c))
|
||||
C_FILES += src/enc/libdeflate/lib/deflate_compress.c src/enc/libdeflate/lib/utils.c
|
||||
O_FILES := $(foreach f,$(C_FILES:.c=.o),$(OBJ_DIR)/$f)
|
||||
|
||||
# Make build directories
|
||||
|
@ -38,7 +40,7 @@ $(shell mkdir -p $(foreach dir,$(SRC_DIRS),$(OBJ_DIR)/$(dir)))
|
|||
all: z64compress
|
||||
|
||||
z64compress: $(O_FILES)
|
||||
$(CC) $(TARGET_CFLAGS) $(CFLAGS) $(O_FILES) -lm -lpthread $(TARGET_LIBS) -o z64compress
|
||||
$(CC) $(TARGET_CFLAGS) $(CFLAGS) $(O_FILES) -lm -lpthread -lz $(TARGET_LIBS) -o z64compress
|
||||
|
||||
$(OBJ_DIR)/%.o: %.c
|
||||
$(CC) -c $(TARGET_CFLAGS) $(CFLAGS) $< -o $@
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
`z64compress` is a program for compressing Zelda 64 roms: be they retail, hacked traditionally, or custom-built from the [`Ocarina of Time`](https://github.com/zeldaret/oot) or [`Majora's Mask`](https://github.com/zeldaret/mm) reverse engineering projects. It is written in highly efficient C and leverages the power of multithreading to make compression as fast as possible. To reduce overhead on subsequent compressions, an optional cache directory can be specified.
|
||||
|
||||
In addition to the default `yaz`, it supports some faster and more compact algorithms such as `lzo`, `ucl`, and `aplib`. In order to use these, grab patches or code from my [`z64enc` repository](https://github.com/z64me/z64enc).
|
||||
In addition to the default `yaz`, it supports some faster and more compact algorithms such as `DEFLATE`, `lzo`, `ucl`, and `aplib`. In order to use these, grab patches or code from my [`z64enc` repository](https://github.com/z64me/z64enc).
|
||||
|
||||
If you add an algorithm, please make sure `valgrind` reports no memory leaks or other errors before making a pull request. Thank you!
|
||||
|
||||
|
@ -59,6 +59,7 @@ This is a command line application. Learn from these common examples and adapt t
|
|||
yaz
|
||||
ucl
|
||||
lzo
|
||||
zlib
|
||||
aplib
|
||||
* to use non-yaz codecs, find patches
|
||||
and code on my z64enc repo
|
||||
|
@ -89,6 +90,13 @@ This is a command line application. Learn from these common examples and adapt t
|
|||
```
|
||||
|
||||
## Building
|
||||
I have included shell scripts for building Linux and Windows binaries. Windows binaries are built using a cross compiler ([I recommend `MXE`](https://mxe.cc/)).
|
||||
First, clone the repository and initialize its submodules:
|
||||
```
|
||||
git clone https://github.com/z64me/z64compress.git
|
||||
cd z64compress
|
||||
git submodule update --init
|
||||
```
|
||||
|
||||
Alternatively, a Makefile-based build system is provided. Choose the target platform with `make TARGET=linux64|linux32|win32`, default is linux64. If building for windows with a cross compiler, specify the compiler executable with `make TARGET=win32 CC=/path/to/executable`.
|
||||
A Makefile-based build system is provided. Choose the target platform with `make TARGET=linux64|linux32|win32`, default is linux64. If building for windows with a cross compiler, specify the compiler executable with `make TARGET=win32 CC=/path/to/executable`.
|
||||
|
||||
Alternatively, I have included shell scripts for building Linux and Windows binaries. Windows binaries are built using a cross compiler ([I recommend `MXE`](https://mxe.cc/)).
|
||||
|
|
|
@ -4,7 +4,7 @@ mkdir -p o
|
|||
mv *.o o
|
||||
|
||||
# build everything else
|
||||
gcc -o z64compress -DNDEBUG src/*.c o/*.o -Wall -Wextra -s -Os -flto -lpthread -march=native -mtune=native
|
||||
gcc -o z64compress -DNDEBUG src/*.c o/*.o src/enc/libdeflate/lib/deflate_compress.c src/enc/libdeflate/lib/utils.c -Isrc/enc/libdeflate -Wall -Wextra -s -Os -flto -lpthread -lz -march=native -mtune=native
|
||||
|
||||
# move to bin directory
|
||||
mkdir -p bin/linux64
|
||||
|
|
|
@ -4,7 +4,7 @@ mkdir -p o
|
|||
mv *.o o
|
||||
|
||||
# build everything else
|
||||
gcc -m32 -o z64compress -DNDEBUG src/*.c o/*.o -Wall -Wextra -s -Os -flto -lpthread -march=native -mtune=native
|
||||
gcc -m32 -o z64compress -DNDEBUG src/*.c o/*.o src/enc/libdeflate/lib/deflate_compress.c src/enc/libdeflate/lib/utils.c -Isrc/enc/libdeflate -Wall -Wextra -s -Os -flto -lpthread -lz -march=native -mtune=native
|
||||
|
||||
# move to bin directory
|
||||
mkdir -p bin/linux32
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# build compression functions (slow)
|
||||
~/c/mxe/usr/bin/i686-w64-mingw32.static-gcc -DNDEBUG -s -Ofast -flto -lm -c -Wall src/enc/*.c src/enc/lzo/*.c src/enc/ucl/comp/*.c src/enc/apultra/*.c
|
||||
i686-w64-mingw32.static-gcc -DNDEBUG -s -Ofast -flto -lm -c -Wall src/enc/*.c src/enc/lzo/*.c src/enc/ucl/comp/*.c src/enc/apultra/*.c
|
||||
mkdir -p o
|
||||
mv *.o o
|
||||
|
||||
# build everything else
|
||||
~/c/mxe/usr/bin/i686-w64-mingw32.static-gcc -o z64compress.exe -DNDEBUG src/*.c o/*.o -Wall -Wextra -s -Os -flto -lpthread -mconsole -municode
|
||||
i686-w64-mingw32.static-gcc -o z64compress.exe -DNDEBUG src/*.c o/*.o src/enc/libdeflate/lib/deflate_compress.c src/enc/libdeflate/lib/utils.c -Isrc/enc/libdeflate -Wall -Wextra -s -Os -flto -lpthread -lz -mconsole -municode
|
||||
|
||||
# move to bin directory
|
||||
mkdir -p bin/win32
|
||||
|
|
|
@ -21,8 +21,8 @@ aplenc(
|
|||
int nMaxCompressedSize = apultra_get_max_compressed_size(src_sz);
|
||||
apultra_stats stats;
|
||||
|
||||
int hlen = 8; /* header length; required due to MM's archives */
|
||||
memset(dst, 0, hlen);
|
||||
extern int g_hlen; /* header length */
|
||||
memset(dst, 0, g_hlen);
|
||||
memcpy(dst, "APL0", 4);
|
||||
dst[4] = (src_sz >> 24);
|
||||
dst[5] = (src_sz >> 16);
|
||||
|
@ -31,7 +31,7 @@ aplenc(
|
|||
|
||||
*dst_sz = apultra_compress(
|
||||
src
|
||||
, dst + hlen
|
||||
, dst + g_hlen
|
||||
, src_sz
|
||||
, nMaxCompressedSize
|
||||
, 0 /* flags */
|
||||
|
@ -41,7 +41,7 @@ aplenc(
|
|||
, &stats
|
||||
);
|
||||
|
||||
*dst_sz = *dst_sz + hlen;
|
||||
*dst_sz = *dst_sz + g_hlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,15 @@ int zx7enc(
|
|||
, void *_ctx
|
||||
);
|
||||
|
||||
int
|
||||
zlibenc(
|
||||
void *_src
|
||||
, unsigned src_sz
|
||||
, void *_dst
|
||||
, unsigned *dst_sz
|
||||
, void *_ctx
|
||||
);
|
||||
|
||||
int aplenc(
|
||||
void *_src
|
||||
, unsigned src_sz
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 6c095314d0c49061f41e1e40be2625dfc2253afa
|
|
@ -33,8 +33,8 @@ lzoenc(
|
|||
unsigned char *wrkmem = _ctx;
|
||||
lzo_uint result_sz = 0;
|
||||
|
||||
int hlen = 8; /* header length; required due to MM's archives */
|
||||
memset(dst, 0, hlen);
|
||||
extern int g_hlen; /* header length */
|
||||
memset(dst, 0, g_hlen);
|
||||
memcpy(dst, "LZO0", 4);
|
||||
dst[4] = (src_sz >> 24);
|
||||
dst[5] = (src_sz >> 16);
|
||||
|
@ -46,9 +46,9 @@ lzoenc(
|
|||
|
||||
memset(wrkmem, 0, LZO1X_999_MEM_COMPRESS);
|
||||
|
||||
lzo1x_999_compress(src, src_sz, dst + hlen, &result_sz, wrkmem);
|
||||
lzo1x_999_compress(src, src_sz, dst + g_hlen, &result_sz, wrkmem);
|
||||
|
||||
*dst_sz = result_sz + hlen;
|
||||
*dst_sz = result_sz + g_hlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ uclenc(
|
|||
int level = 10;
|
||||
ucl_uint result_sz;
|
||||
|
||||
int hlen = 8; /* header length; required due to MM's archives */
|
||||
memset(dst, 0, hlen);
|
||||
extern int g_hlen; /* header length */
|
||||
memset(dst, 0, g_hlen);
|
||||
memcpy(dst, "UCL0", 4);
|
||||
dst[4] = (src_sz >> 24);
|
||||
dst[5] = (src_sz >> 16);
|
||||
|
@ -29,7 +29,7 @@ uclenc(
|
|||
r = ucl_nrv2b_99_compress(
|
||||
src /* in */
|
||||
, src_sz /* in size */
|
||||
, dst + hlen /* out */
|
||||
, dst + g_hlen /* out */
|
||||
, &result_sz /* out size */
|
||||
, NULL /* callback */
|
||||
, level /* level */
|
||||
|
@ -43,7 +43,7 @@ uclenc(
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
*dst_sz = result_sz + hlen;
|
||||
*dst_sz = result_sz + g_hlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
/* <z64.me> yar.c: decode and encode MM yaz archives */
|
||||
|
||||
/*
|
||||
* this file can also be compiled as a standalone program for
|
||||
* decompressing the contents of a MM yaz archive like so:
|
||||
* gcc -o unyar -Wall -Wextra -std=c99 -pedantic -DYAR_MAIN_TEST=1 yar.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
@ -231,7 +238,7 @@ yar_reencode(
|
|||
ss += 4;
|
||||
item += 1;
|
||||
|
||||
} while (ss - src < end);
|
||||
} while ((unsigned)(ss - src) < end);
|
||||
|
||||
/* update progress display */
|
||||
if (name)
|
||||
|
@ -277,7 +284,7 @@ yar_reencode(
|
|||
|
||||
/* yaz decoder, courtesy of spinout182 */
|
||||
static
|
||||
int spinout_yaz_dec(void *_src, void *_dst, int dstSz)
|
||||
int spinout_yaz_dec(void *_src, void *_dst, unsigned dstSz, unsigned *srcSz)
|
||||
{
|
||||
unsigned char *src = _src;
|
||||
unsigned char *dst = _dst;
|
||||
|
@ -328,7 +335,7 @@ int spinout_yaz_dec(void *_src, void *_dst, int dstSz)
|
|||
}
|
||||
|
||||
/*copy run*/
|
||||
int i;
|
||||
unsigned int i;
|
||||
for(i = 0; i < numBytes; ++i)
|
||||
{
|
||||
dst[dstPlace] = dst[copySource];
|
||||
|
@ -343,12 +350,14 @@ int spinout_yaz_dec(void *_src, void *_dst, int dstSz)
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
(void)srcSz;
|
||||
}
|
||||
|
||||
|
||||
/* encodes decompressed data, storing result in dst */
|
||||
static
|
||||
int encode(void *src, int srcSz, void *_dst, int *dstSz, void *ctx)
|
||||
int encode(void *src, unsigned srcSz, void *_dst, unsigned *dstSz, void *ctx)
|
||||
{
|
||||
unsigned char *dst = _dst;
|
||||
|
||||
|
@ -368,15 +377,22 @@ int encode(void *src, int srcSz, void *_dst, int *dstSz, void *ctx)
|
|||
*dstSz = srcSz + 0x10;
|
||||
|
||||
return 0;
|
||||
|
||||
(void)ctx;
|
||||
}
|
||||
|
||||
/* checks if data has already been encoded */
|
||||
/* if it does, dst is filled with that data and 1 is returned */
|
||||
/* 0 is returned otherwise */
|
||||
static
|
||||
int exist(void *src, int srcSz, void *dst, int *dstSz)
|
||||
int exist(void *src, unsigned srcSz, void *dst, unsigned *dstSz)
|
||||
{
|
||||
return 0;
|
||||
|
||||
(void)src;
|
||||
(void)srcSz;
|
||||
(void)dst;
|
||||
(void)dstSz;
|
||||
}
|
||||
|
||||
/* unsafe but it's a test program so it's fine */
|
||||
|
@ -412,17 +428,39 @@ file_read(char *fn, unsigned *sz)
|
|||
return raw;
|
||||
}
|
||||
|
||||
/* minimal file writer
|
||||
* returns 0 on failure
|
||||
* returns non-zero on success
|
||||
*/
|
||||
int savefile(const char *fn, const void *dat, const size_t sz)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
/* rudimentary error checking returns 0 on any error */
|
||||
if (
|
||||
!fn
|
||||
|| !sz
|
||||
|| !dat
|
||||
|| !(fp = fopen(fn, "wb"))
|
||||
|| fwrite(dat, 1, sz, fp) != sz
|
||||
|| fclose(fp)
|
||||
)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned char *raw;
|
||||
void *raw;
|
||||
unsigned int raw_sz;
|
||||
|
||||
unsigned char *out;
|
||||
unsigned char *imm;
|
||||
void *out;
|
||||
void *imm;
|
||||
unsigned int out_sz = 0;
|
||||
|
||||
if (argc != 2)
|
||||
FERR("args: unyar in.yar > out.yar");
|
||||
if (argc != 3)
|
||||
FERR("args: unyar in.yar out.yar");
|
||||
|
||||
raw = file_read(argv[1], &raw_sz);
|
||||
fprintf(stderr, "input file %s:\n", argv[1]);
|
||||
|
@ -432,18 +470,21 @@ int main(int argc, char *argv[])
|
|||
imm = malloc(1024 * 1024 * 64);
|
||||
|
||||
yar_reencode(
|
||||
raw, raw_sz, out, &out_sz, 12, "Yaz0", imm
|
||||
raw, raw_sz, out, &out_sz, 16, argv[1], "Yaz0", imm, 0
|
||||
, spinout_yaz_dec
|
||||
, encode
|
||||
, exist
|
||||
);
|
||||
|
||||
/* write output to stdout */
|
||||
fwrite(out, 1, out_sz, stdout);
|
||||
|
||||
/* write output file */
|
||||
if (!savefile(argv[2], out, out_sz))
|
||||
FERR("failed to write output file");
|
||||
|
||||
free(raw);
|
||||
free(out);
|
||||
free(imm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* YAR_MAIN_TEST */
|
||||
|
|
|
@ -272,16 +272,24 @@ uint32_t encode(struct yazCtx *ctx, uint8_t *data, uint32_t data_size, uint8_t *
|
|||
// block and stream differentiation
|
||||
// Yay is block, Yaz is stream
|
||||
int mode_block=1, mode_stream=1; // temporary, for testing
|
||||
#ifdef YAZ_MAIN_TEST
|
||||
int g_hlen = 8;
|
||||
#else
|
||||
extern int g_hlen;
|
||||
#endif
|
||||
mode_block=!strcmp(mode,"Yay0");
|
||||
if (mode_block ) {
|
||||
uint32_t l = (sb_count(ctx->cmds) << 2) + 16;
|
||||
uint32_t o = (sb_count(ctx->ctrl) << 1) + l;
|
||||
if (g_hlen) {
|
||||
memcpy(output, mode, 4);
|
||||
U32wr(output+4, sz);
|
||||
} else
|
||||
output -= 8; /* headerless */
|
||||
if (mode_block) {
|
||||
uint32_t l = (sb_count(ctx->cmds) << 2) + 16;
|
||||
uint32_t o = (sb_count(ctx->ctrl) << 1) + l;
|
||||
U32wr(output+8, l);
|
||||
U32wr(output+12, o);
|
||||
|
||||
uint32_t output_position = 16;
|
||||
uint32_t output_position = g_hlen + 8;
|
||||
uint32_t x;
|
||||
for (x=0; x<sb_count(ctx->cmds); x++) {
|
||||
U32wr(output+output_position, ctx->cmds[x]);
|
||||
|
@ -296,8 +304,6 @@ uint32_t encode(struct yazCtx *ctx, uint8_t *data, uint32_t data_size, uint8_t *
|
|||
}
|
||||
return output_position;
|
||||
} else if(mode_stream) {
|
||||
memcpy(output, mode, 4);
|
||||
U32wr(output+4, sz);
|
||||
U32wr(output+8, 0);
|
||||
U32wr(output+12, 0);
|
||||
|
||||
|
@ -315,8 +321,8 @@ uint32_t encode(struct yazCtx *ctx, uint8_t *data, uint32_t data_size, uint8_t *
|
|||
sb_push(ctx->back, (ctx->ctrl[x]>>8)&0xFF);
|
||||
sb_push(ctx->back, (ctx->ctrl[x])&0xFF);
|
||||
}
|
||||
output_position = _enc_z_from_tables(ctx, ctx->ctl, ctx->back, ctx->raws, output+16, data_size, mode);
|
||||
return 16 + output_position;
|
||||
output_position = _enc_z_from_tables(ctx, ctx->ctl, ctx->back, ctx->raws, output+g_hlen+8, data_size, mode);
|
||||
return output_position + g_hlen + 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
#include "libdeflate/libdeflate.h"
|
||||
|
||||
#define CAPACITY (1024 * 1024 * 4) /* output buffer max (4 mb) */
|
||||
|
||||
int
|
||||
zlibenc(
|
||||
void *_src
|
||||
, unsigned src_sz
|
||||
, void *_dst
|
||||
, unsigned *dst_sz
|
||||
, void *_ctx
|
||||
)
|
||||
{
|
||||
unsigned char *src = _src;
|
||||
unsigned char *dst = _dst;
|
||||
unsigned result_sz;
|
||||
|
||||
extern int g_hlen; /* header length */
|
||||
memset(dst, 0, g_hlen);
|
||||
memcpy(dst, "ZLIB", 4);
|
||||
dst[4] = (src_sz >> 24);
|
||||
dst[5] = (src_sz >> 16);
|
||||
dst[6] = (src_sz >> 8);
|
||||
dst[7] = (src_sz >> 0);
|
||||
|
||||
/* zlib and gzip have different header lengths
|
||||
* https://stackoverflow.com/a/68538037
|
||||
*/
|
||||
#if 1
|
||||
|
||||
#if 0 /* zlib */
|
||||
z_stream stream = {0};
|
||||
int r;
|
||||
stream.avail_in = src_sz;
|
||||
stream.next_in = src;
|
||||
stream.avail_out = CAPACITY;
|
||||
stream.next_out = dst + g_hlen;
|
||||
#define HEADER_LEN 2
|
||||
if ((r = deflateInit(&stream, Z_BEST_COMPRESSION)) != Z_OK)
|
||||
{
|
||||
fprintf(stderr, "[!] fatal compression error %d\n", r);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((r = deflate(&stream, Z_FINISH)) == Z_STREAM_ERROR)
|
||||
{
|
||||
fprintf(stderr, "[!] Z_STREAM_ERROR\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
deflateEnd(&stream);
|
||||
|
||||
result_sz = CAPACITY - stream.avail_out;
|
||||
#else /* libdeflate */
|
||||
#define HEADER_LEN 0
|
||||
int level = 12;
|
||||
struct libdeflate_compressor *compressor;
|
||||
compressor = libdeflate_alloc_compressor(level);
|
||||
result_sz = libdeflate_deflate_compress(
|
||||
compressor
|
||||
, src, src_sz
|
||||
, dst + g_hlen
|
||||
, CAPACITY
|
||||
);
|
||||
libdeflate_free_compressor(compressor);
|
||||
#endif
|
||||
#else
|
||||
/* this gzip code was left in for testing purposes; it may
|
||||
* be useful if matching ique recompression is ever revisited;
|
||||
* ique matches (except for one byte...) when compressed using
|
||||
* gzip 1.2.4 or 1.2.4a (they produce identical results),
|
||||
* available here: https://ftp.gnu.org/gnu/gzip/
|
||||
* this is not a compression error, because decompressing the
|
||||
* recompressed rom produces a rom identical to the original
|
||||
* decompressed ique rom;
|
||||
* TODO: find out why that byte doesn't match on recompression;
|
||||
* TODO: once that's working, add --codec ique for those wanting
|
||||
* matching ique recompression; otherwise, modern zlib works great!
|
||||
*/
|
||||
#define HEADER_LEN 10
|
||||
FILE *fp = fopen("tmp.bin", "wb");
|
||||
fwrite(src, 1, src_sz, fp);
|
||||
fclose(fp);
|
||||
system("./gzip -c -9 -n tmp.bin > tmp.bin.gzip");
|
||||
fp = fopen("tmp.bin.gzip", "rb");
|
||||
fseek(fp, 0, SEEK_END);
|
||||
result_sz = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
fread(dst, 1, result_sz, fp);
|
||||
fclose(fp);
|
||||
#endif
|
||||
*dst_sz = result_sz + g_hlen;
|
||||
|
||||
/* trim zlib/gzip header */
|
||||
memmove(dst + g_hlen, dst + g_hlen + HEADER_LEN, result_sz);
|
||||
*dst_sz -= HEADER_LEN;
|
||||
|
||||
return 0;
|
||||
(void)_ctx; /* -Wunused-parameter */
|
||||
}
|
||||
|
|
@ -16,20 +16,20 @@ zx7enc(
|
|||
unsigned char *src = _src;
|
||||
unsigned char *dst = _dst;
|
||||
|
||||
int hlen = 8; /* header length; required due to MM's archives */
|
||||
memset(dst, 0, hlen);
|
||||
extern int g_hlen; /* header length */
|
||||
memset(dst, 0, g_hlen);
|
||||
memcpy(dst, "ZX70", 4);
|
||||
dst[4] = (src_sz >> 24);
|
||||
dst[5] = (src_sz >> 16);
|
||||
dst[6] = (src_sz >> 8);
|
||||
dst[7] = (src_sz >> 0);
|
||||
|
||||
*dst_sz = ZX7Compress(src, src_sz, dst + hlen);
|
||||
*dst_sz = ZX7Compress(src, src_sz, dst + g_hlen);
|
||||
|
||||
if (!*dst_sz)
|
||||
return 1;
|
||||
|
||||
*dst_sz += hlen;
|
||||
*dst_sz += g_hlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "rom.h"
|
||||
|
||||
FILE* printer;
|
||||
int g_hlen = 8;
|
||||
|
||||
static void compress(struct rom *rom, int start, int end)
|
||||
{
|
||||
|
@ -167,6 +168,7 @@ static void usage(void)
|
|||
fprintf(printer, " yaz\n");
|
||||
fprintf(printer, " ucl\n");
|
||||
fprintf(printer, " lzo\n");
|
||||
fprintf(printer, " zlib\n");
|
||||
fprintf(printer, " aplib\n");
|
||||
fprintf(printer, " * to use non-yaz codecs, find patches\n");
|
||||
fprintf(printer, " and code on my z64enc repo\n");
|
||||
|
@ -184,6 +186,8 @@ static void usage(void)
|
|||
fprintf(printer, "\n");
|
||||
fprintf(printer, " --skip disable compression on specified files\n");
|
||||
fprintf(printer, "\n");
|
||||
fprintf(printer, " --headerless don't write file headers (for iQue)\n");
|
||||
fprintf(printer, "\n");
|
||||
fprintf(printer, " --repack handles Majora's Mask archives\n");
|
||||
fprintf(printer, "\n");
|
||||
fprintf(printer, " --threads optional multithreading;\n");
|
||||
|
@ -209,6 +213,7 @@ wow_main
|
|||
int Athreads = 0;
|
||||
bool Amatching = false;
|
||||
bool Aonly_stdout = false;
|
||||
bool Aheaderless = false;
|
||||
wow_main_argv;
|
||||
|
||||
printer = stderr;
|
||||
|
@ -253,6 +258,15 @@ wow_main
|
|||
i--;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(arg, "--headerless"))
|
||||
{
|
||||
if (Aheaderless)
|
||||
die("--headerless arg provided more than once");
|
||||
Aheaderless = true;
|
||||
g_hlen = 0;
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* arguments with additional parameters */
|
||||
|
||||
|
|
|
@ -462,6 +462,14 @@ static const struct encoder *encoder(const char *name)
|
|||
|
||||
return &zx7;
|
||||
}*/
|
||||
else if (!strcmp(name, "zlib"))
|
||||
{
|
||||
static const struct encoder zlib = {
|
||||
.encfunc = zlibenc
|
||||
};
|
||||
|
||||
return &zlib;
|
||||
}
|
||||
else if (!strcmp(name, "aplib"))
|
||||
{
|
||||
static const struct encoder aplib = {
|
||||
|
@ -1112,7 +1120,7 @@ void rom_compress(struct rom *rom, int mb, int numThreads, bool matching)
|
|||
comp_total += sz16;
|
||||
|
||||
if (mb != 0 && dma->Pend > compsz)
|
||||
die("ran out of compressed rom space");
|
||||
die("ran out of compressed rom space (try increasing --mb)");
|
||||
}
|
||||
|
||||
/* adaptive final size */
|
||||
|
@ -1660,6 +1668,14 @@ struct rom *rom_new(const char *fn)
|
|||
/* propagate rom file */
|
||||
dst->data = file_load(fn, &dst->data_sz);
|
||||
|
||||
/* double its bounds just in case compressed rom is larger
|
||||
* (this can happen if, say, a 23mb rom is provided,
|
||||
* gets compressed to 17mb, and is rounded up to 24mb)
|
||||
* (retail rom sizes always use increments of 8)
|
||||
*/
|
||||
dst->data_sz *= 2;
|
||||
dst->data = realloc(dst->data, dst->data_sz);
|
||||
|
||||
/* back up load file name */
|
||||
dst->fn = strdup_safe(fn);
|
||||
|
||||
|
|
Loading…
Reference in New Issue