Skip to content

Commit 7cb3b44

Browse files
committed
sm64compress 0.2a and cleanups
Cleanup command line options, comments, dump data
1 parent aca7068 commit 7cb3b44

File tree

1 file changed

+52
-35
lines changed

1 file changed

+52
-35
lines changed

sm64compress.c

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,31 @@
66
#include "libsm64.h"
77
#include "utils.h"
88

9-
#define SM64COMPRESS_VERSION "0.1.1a"
9+
#define SM64COMPRESS_VERSION "0.2a"
1010

1111
#define MAX_REFS 64
1212

1313
typedef struct
1414
{
1515
unsigned int level; // original level script offset where referenced
1616
unsigned int offset; // offset within level script where referenced
17-
unsigned char type; // command type: 0x1A, 0x18, or 0xFF for ASM
17+
unsigned char type; // command type: 0x1A, 0x18, or 0xFF, 0xFE, 0xFD for ASM
1818
} block_ref;
1919

2020
typedef struct
2121
{
22-
unsigned int old; // starting offset in original ROM
23-
unsigned int old_end; // ending offset in original ROM
24-
unsigned int new; // starting offset in new ROM
25-
unsigned int new_end; // ending offset in new ROM
26-
block_ref refs[MAX_REFS]; // references to this block
27-
int ref_count; // number of references
22+
unsigned int old; // starting offset in original ROM
23+
unsigned int old_end; // ending offset in original ROM
24+
unsigned int new; // starting offset in new ROM
25+
unsigned int new_end; // ending offset in new ROM
26+
block_ref refs[MAX_REFS]; // references to this block
27+
int ref_count; // number of references
28+
char compressible; // if block is not currenlty, but potentially compressible
2829
enum {
2930
BLOCK_LEVEL,
3031
BLOCK_MIO0,
3132
BLOCK_RAW
3233
} type;
33-
char compressible; // whether or not block is compressible
3434
} block;
3535

3636
typedef struct
@@ -49,7 +49,7 @@ static const compress_config default_config =
4949
{
5050
NULL, // input filename
5151
NULL, // output filename
52-
16, // MIO0 alignment
52+
16, // block alignment
5353
0, // compress all MIO0 blocks
5454
0, // dump
5555
0, // f3d
@@ -58,20 +58,21 @@ static const compress_config default_config =
5858

5959
static void print_usage(void)
6060
{
61-
ERROR("Usage: sm64compress [-c] [-v] FILE [OUT_FILE]\n"
61+
ERROR("Usage: sm64compress [-a ALIGNMENT] [-c] [-d] [-f] [-g] [-v] FILE [OUT_FILE]\n"
6262
"\n"
63-
"sm64compress v" SM64COMPRESS_VERSION ": Super Mario 64 ROM compressor\n"
63+
"sm64compress v" SM64COMPRESS_VERSION ": Super Mario 64 ROM compressor and fixer\n"
6464
"\n"
6565
"Optional arguments:\n"
66-
" -a ALIGNMENT byte boundary to align MIO0 blocks (default: %d)\n"
67-
" -c compress all blocks using MIO0\n"
66+
" -a ALIGNMENT byte boundary to align blocks (default: %d)\n"
67+
" -c compress all 0x17 blocks using MIO0 (experimental)\n"
68+
" -d dump blocks to 'dump' directory\n"
6869
" -f fix F3D combine blending parameters\n"
6970
" -g fix geo layout display list layers\n"
7071
" -v verbose progress output\n"
7172
"\n"
7273
"File arguments:\n"
7374
" FILE input ROM file\n"
74-
" OUT_FILE output shrunk ROM file (default: replaces input extension with .out.z64)\n",
75+
" OUT_FILE output compressed ROM file (default: replaces input extension with .out.z64)\n",
7576
default_config.alignment);
7677
exit(1);
7778
}
@@ -342,7 +343,6 @@ static int sm64_compress_mio0(const compress_config *config,
342343
#define SEGMENT2_ROM_OFFSET 0x800000
343344
#define SEGMENT2_ROM_END 0x81BB64
344345
block block_table[MAX_BLOCKS];
345-
unsigned char *src;
346346
unsigned char *tmp_raw = NULL;
347347
unsigned char *tmp_cmp = NULL;
348348
int block_count = 0;
@@ -395,23 +395,38 @@ static int sm64_compress_mio0(const compress_config *config,
395395
blk->new = blk->old;
396396
blk->new_end = blk->old_end;
397397
} else {
398+
unsigned char *src;
398399
int src_len;
400+
int block_len = blk->old_end - blk->old;
399401
// implement fixes
400402
// TODO: this is liberally applied to all data
401403
// TODO: this assumes fake MIO0 headers
402404
if (config->fix_f3d) {
403-
fix_f3d(&in_buf[blk->old], blk->old_end - blk->old);
405+
fix_f3d(&in_buf[blk->old], block_len);
404406
}
405407
if (config->fix_geo) {
406-
fix_geo(&in_buf[blk->old], blk->old_end - blk->old);
408+
fix_geo(&in_buf[blk->old], block_len);
407409
}
408410
if (config->compress && blk->type == BLOCK_MIO0) {
409-
// TODO: this decompression step may be unnecesary if it is a fake header
411+
// decompress to remove fake header and recompress
410412
int raw_len = mio0_decode(&in_buf[blk->old], tmp_raw, NULL);
411413
int cmp_len = mio0_encode(tmp_raw, raw_len, tmp_cmp);
412414
src = tmp_cmp;
413415
src_len = cmp_len;
414-
INFO("Compressed %08X %06X=%06X => %06X\n", blk->old, blk->old_end - blk->old, raw_len, cmp_len);
416+
INFO("Compressed %08X %06X=%06X => %06X\n", blk->old, block_len, raw_len, cmp_len);
417+
} else if(config->compress && blk->compressible) {
418+
// decompress to remove fake header and recompress
419+
int cmp_len = mio0_encode(&in_buf[blk->old], block_len, tmp_cmp);
420+
src = tmp_cmp;
421+
src_len = cmp_len;
422+
INFO("Compressed %08X %06X => %06X\n", blk->old, block_len, cmp_len);
423+
for (int r = 0; r < blk->ref_count; r++) {
424+
if (blk->refs[r].type == 0x17) {
425+
blk->refs[r].type = 0x18;
426+
} else {
427+
ERROR("Block %08X ref %X:%X type = %02X\n", blk->old, blk->refs[r].level, blk->refs[r].offset, blk->refs[r].type);
428+
}
429+
}
415430
} else {
416431
src = &in_buf[blk->old];
417432
src_len = blk->old_end - blk->old;
@@ -443,15 +458,15 @@ static int sm64_compress_mio0(const compress_config *config,
443458
addr_high++;
444459
}
445460
write_u16_be(&out_buf[offset + 0x2], addr_high);
446-
write_u16_be(&out_buf[offset + 0xe], addr_low);
461+
write_u16_be(&out_buf[offset + 0xE], addr_low);
447462

448463
addr_low = blk->new_end & 0xFFFF;
449464
addr_high = (blk->new_end >> 16) & 0xFFFF;
450465
if (addr_low & 0x8000) {
451466
addr_high++;
452467
}
453468
write_u16_be(&out_buf[offset + 0x6], addr_high);
454-
write_u16_be(&out_buf[offset + 0xa], addr_low);
469+
write_u16_be(&out_buf[offset + 0xA], addr_low);
455470
INFO("Updated ASM @ %08X: %08X %08X %08X %08X\n", offset,
456471
read_u32_be(&out_buf[offset + 0]), read_u32_be(&out_buf[offset + 4]),
457472
read_u32_be(&out_buf[offset + 8]), read_u32_be(&out_buf[offset + 0xC]));
@@ -480,7 +495,7 @@ static int sm64_compress_mio0(const compress_config *config,
480495
write_u16_be(&out_buf[0xD4788 + 0x2], addr_low);
481496
INFO("Updated ASM @ %08X: %08X %08X\n", 0xD4784,
482497
read_u32_be(&out_buf[0xD4784 + 0]), read_u32_be(&out_buf[0xD4784 + 4]));
483-
} else if (blk->refs[r].type == 0xFD) { // sequence bank
498+
} else if (blk->refs[r].type == 0xFD) { // some other data
484499
unsigned addr_low = blk->new & 0xFFFF;
485500
unsigned addr_high = (blk->new >> 16) & 0xFFFF;
486501
INFO("Updating ASM @ %08X: %08X %08X %08X %08X %08X\n", 0x101BB0,
@@ -510,9 +525,10 @@ static int sm64_compress_mio0(const compress_config *config,
510525
} else {
511526
block *level = &block_table[level_idx];
512527
unsigned offset = level->new + blk->refs[r].offset;
513-
INFO("Updating @ %08X:%08X %08X-%08X to %08X-%08X\n", level->old, level->new,
514-
read_u32_be(&out_buf[offset + 4]), read_u32_be(&out_buf[offset + 8]),
515-
blk->new, blk->new_end);
528+
INFO("Updating @ %08X:%08X %02X %08X-%08X to %02X %08X-%08X\n", level->old, level->new,
529+
out_buf[offset], read_u32_be(&out_buf[offset + 4]), read_u32_be(&out_buf[offset + 8]),
530+
blk->refs[r].type, blk->new, blk->new_end);
531+
out_buf[offset] = blk->refs[r].type;
516532
write_u32_be(&out_buf[offset + 4], blk->new);
517533
write_u32_be(&out_buf[offset + 8], blk->new_end);
518534
}
@@ -527,17 +543,16 @@ static int sm64_compress_mio0(const compress_config *config,
527543
out_buf[0xd48b7] = 0x5C;
528544
}
529545

546+
#define DUMP_DIR "dump"
530547
if (config->dump) {
531-
make_dir("dump");
548+
make_dir(DUMP_DIR);
532549
for (int i = 0; i < block_count; i++) {
550+
char fname[FILENAME_MAX];
533551
block *blk = &block_table[i];
534-
if (blk->type == BLOCK_LEVEL) {
535-
char fname[512];
536-
sprintf(fname, "dump/%07X.%07X.old.bin", blk->old, blk->old);
537-
(void)write_file(fname, &in_buf[blk->old], blk->old_end - blk->old);
538-
sprintf(fname, "dump/%07X.%07X.new.bin", blk->old, blk->new);
539-
(void)write_file(fname, &out_buf[blk->new], blk->new_end - blk->new);
540-
}
552+
sprintf(fname, "%s/%07X.%07X.old.bin", DUMP_DIR, blk->old, blk->old);
553+
(void)write_file(fname, &in_buf[blk->old], blk->old_end - blk->old);
554+
sprintf(fname, "%s/%07X.%07X.new.bin", DUMP_DIR, blk->old, blk->new);
555+
(void)write_file(fname, &out_buf[blk->new], blk->new_end - blk->new);
541556
}
542557
}
543558

@@ -587,7 +602,7 @@ int main(int argc, char *argv[])
587602
// copy first 8MB from input to output
588603
memcpy(out_buf, in_buf, 8*MB);
589604

590-
// compact the SM64 MIO0 files and adjust pointers
605+
// compact the SM64 blocks and adjust pointers
591606
out_size = sm64_compress_mio0(&config, in_buf, in_size, out_buf);
592607

593608
// update N64 header CRC
@@ -600,5 +615,7 @@ int main(int argc, char *argv[])
600615
exit(1);
601616
}
602617

618+
INFO("Size: %dMB -> %dMB\n", (int)in_size/(1*MB), (int)out_size/(1*MB));
619+
603620
return 0;
604621
}

0 commit comments

Comments
 (0)