Skip to content

Instantly share code, notes, and snippets.

@shimamura-sakura
Last active January 4, 2023 10:52
Show Gist options
  • Save shimamura-sakura/8316a245232bbe781653f300e795c3e2 to your computer and use it in GitHub Desktop.
Save shimamura-sakura/8316a245232bbe781653f300e795c3e2 to your computer and use it in GitHub Desktop.
Decompress .lzs files from Kanda Alice mo Suiri suru (神田アリスも推理スル). I think they are mostly BNTX files (Nintendo Switch BNTX).
const std = @import("std");
const mem = std.mem;
const hea = std.heap.page_allocator;
pub fn main() !void {
const stderr = std.io.getStdErr().writer();
const argv = try std.process.argsAlloc(hea);
defer std.process.argsFree(hea, argv);
if (argv.len < 3)
return stderr.print("usage: '{s}' input_lzs output_file\n", .{argv[0]});
const file_i = try std.fs.cwd().openFileZ(argv[1], .{});
defer file_i.close();
const file_o = try std.fs.cwd().createFileZ(argv[2], .{});
defer file_o.close();
var bfReader = std.io.bufferedReader(file_i.reader());
const reader = bfReader.reader();
const header = try reader.readBytesNoEof(12);
const decmp_length = mem.readIntLittle(u32, header[0..4]);
const input_length = mem.readIntLittle(u32, header[4..8]);
const escaped_byte = header[8];
try stderr.print(
"output: {}, input: {}, escape: 0x{x:0>2}\n",
.{ decmp_length, input_length, escaped_byte },
);
const decmp_buffer = try hea.alloc(u8, decmp_length);
defer hea.free(decmp_buffer);
var decmp_offset: usize = 0;
while (decmp_offset < decmp_length) {
const b0 = try reader.readByte();
const b1 = if (b0 == escaped_byte) try reader.readByte() else 0;
if (b0 != escaped_byte or b1 == b0) {
decmp_buffer[decmp_offset] = b0;
decmp_offset += 1;
} else {
const copy_off = if (b1 > escaped_byte) b1 - 1 else b1;
const copy_len = try reader.readByte();
mem.copyBackwards(
u8,
decmp_buffer[decmp_offset .. decmp_offset + copy_len],
decmp_buffer[decmp_offset - copy_off .. decmp_offset - copy_off + copy_len],
);
decmp_offset += copy_len;
}
}
if (reader.readByte() != error.EndOfStream)
try stderr.print("warning: extra data after body", .{});
try file_o.writeAll(decmp_buffer);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment