mirror of
https://github.com/n64decomp/mk64
synced 2026-08-07 01:45:40 -04:00
Add MSYS2 MinGW x64 Support (#108)
* Added MSYS2 MinGW x64 Support * Updated recomp * Updated tools
This commit is contained in:
@@ -29,7 +29,8 @@ del compile_args[out_ind]
|
||||
in_dir = os.path.split(os.path.realpath(in_file))[0]
|
||||
opt_flags = [x for x in compile_args if x in ['-g', '-O2', '-framepointer']]
|
||||
|
||||
preprocessed_file = tempfile.NamedTemporaryFile(prefix='preprocessed', suffix='.c')
|
||||
|
||||
preprocessed_file = tempfile.NamedTemporaryFile(prefix='preprocessed', suffix='.c', delete=False)
|
||||
|
||||
subprocess.check_call(asm_processor + opt_flags + [in_file], stdout=preprocessed_file)
|
||||
subprocess.check_call(compiler + compile_args + ['-I', in_dir, '-o', out_file, preprocessed_file.name])
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#define EI_DATA 5
|
||||
#define EI_NIDENT 16
|
||||
|
||||
@@ -179,6 +184,17 @@ static bool elf_get_section_range(uint8_t *file, const char *searched_name, uint
|
||||
return false;
|
||||
}
|
||||
|
||||
static FILE *mio0_open_out_file(const char *out_file) {
|
||||
if (strcmp(out_file, "-") == 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
return stdout;
|
||||
} else {
|
||||
return fopen(out_file, "wb");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Usage: %s INFILE OUTFILE\n", argv[0]);
|
||||
@@ -299,9 +315,11 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
FILE *out = fopen(argv[2], "wb");
|
||||
FILE *out = mio0_open_out_file(argv[2]);
|
||||
fwrite(file + data_offset, 1, new_size, out);
|
||||
fclose(out);
|
||||
if (out != stdout) {
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
free(file);
|
||||
return 0;
|
||||
|
||||
@@ -9,7 +9,7 @@ acpp: OPT_CFLAGS := -O2
|
||||
|
||||
RECOMP := recomp
|
||||
|
||||
ugen_c.c: RECOMP_FLAGS := --conservative
|
||||
#ugen_c.c: RECOMP_FLAGS := --conservative
|
||||
|
||||
all: cc cfe uopt ugen as1 acpp copt ujoin uld umerge usplit err.english.cc
|
||||
|
||||
@@ -17,7 +17,7 @@ clean:
|
||||
$(RM) cc* cfe* uopt* ugen* as1* acpp* copt* ujoin* uld* umerge* usplit* err.english.cc $(RECOMP) libc_impl.o
|
||||
|
||||
$(RECOMP): recomp.cpp
|
||||
$(CXX) $^ -o $@ -std=c++11 -O2 -Wno-switch `pkg-config --cflags --libs capstone`
|
||||
$(CXX) $^ -o $@ -std=c++11 -O2 -Dugen53 -Wno-switch `pkg-config --cflags --libs capstone`
|
||||
|
||||
libc_impl.o: libc_impl.c libc_impl.h
|
||||
$(CC) $< -c -fno-strict-aliasing -O2 -DIDO53
|
||||
@@ -26,10 +26,10 @@ err.english.cc: $(IRIX_ROOT)/usr/lib/err.english.cc
|
||||
cp $^ $@
|
||||
|
||||
cc_c.c: $(IRIX_ROOT)/usr/bin/cc $(RECOMP)
|
||||
./$(RECOMP) $(RECOMP_FLAGS) $< > $@
|
||||
./$(RECOMP) $< > $@
|
||||
|
||||
%_c.c: $(IRIX_ROOT)/usr/lib/% $(RECOMP)
|
||||
./$(RECOMP) $(RECOMP_FLAGS) $< > $@
|
||||
./$(RECOMP) $< > $@
|
||||
|
||||
%: %_c.c libc_impl.o
|
||||
$(CC) libc_impl.o $< -o $@ $(OPT_CFLAGS) -fno-strict-aliasing -lm -no-pie
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
param[i] = MEM_S8(param##_addr + i); \
|
||||
}
|
||||
|
||||
#if !defined(IDO53) && !defined(IDO71)
|
||||
#if !defined(IDO53) && !defined(IDO71) && !defined(IDO72)
|
||||
#define IDO71
|
||||
#endif
|
||||
|
||||
@@ -68,6 +68,15 @@
|
||||
#define LIBC_SIZE 0x3000
|
||||
#endif
|
||||
|
||||
#ifdef IDO72
|
||||
// IDO 7.2
|
||||
#define IOB_ADDR 0x0fb49454
|
||||
#define ERRNO_ADDR 0x0fb49290
|
||||
#define CTYPE_ADDR 0x0fb46db0
|
||||
#define LIBC_ADDR 0x0fb46000
|
||||
#define LIBC_SIZE 0x4000
|
||||
#endif
|
||||
|
||||
#define STDIN_ADDR IOB_ADDR
|
||||
#define STDOUT_ADDR (IOB_ADDR + 0x10)
|
||||
#define STDERR_ADDR (IOB_ADDR + 0x20)
|
||||
@@ -177,13 +186,13 @@ static char bin_dir[PATH_MAX + 1];
|
||||
#endif
|
||||
static int g_file_max = 3;
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__APPLE__)
|
||||
#ifdef __CYGWIN__
|
||||
static size_t g_Pagesize;
|
||||
#endif
|
||||
|
||||
static uint8_t *memory_map(size_t length)
|
||||
{
|
||||
#if defined(__CYGWIN__) || defined(__APPLE__)
|
||||
#ifdef __CYGWIN__
|
||||
uint8_t *mem = mmap(0, length, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
|
||||
g_Pagesize = sysconf(_SC_PAGESIZE);
|
||||
assert(((uintptr_t)mem & (g_Pagesize-1)) == 0);
|
||||
@@ -201,7 +210,7 @@ static void memory_allocate(uint8_t *mem, uint32_t start, uint32_t end)
|
||||
{
|
||||
assert(start >= MEM_REGION_START);
|
||||
assert(end <= MEM_REGION_START + MEM_REGION_SIZE);
|
||||
#if defined(__CYGWIN__) || defined(__APPLE__)
|
||||
#ifdef __CYGWIN__
|
||||
uintptr_t _start = ((uintptr_t)mem + start) & ~(g_Pagesize-1);
|
||||
uintptr_t _end = ((uintptr_t)mem + end + (g_Pagesize-1)) & ~(g_Pagesize-1);
|
||||
|
||||
@@ -1327,7 +1336,7 @@ int wrapper_ftell(uint8_t *mem, uint32_t fp_addr) {
|
||||
return res;
|
||||
}
|
||||
|
||||
void wrapper_rewind(uint8_t *mem, uint32_t fp_addr) {
|
||||
int wrapper_rewind(uint8_t *mem, uint32_t fp_addr) {
|
||||
(void)wrapper_fseek(mem, fp_addr, 0, SEEK_SET);
|
||||
struct FILE_irix *f = (struct FILE_irix *)&MEM_U32(fp_addr);
|
||||
f->_flag &= ~IOERR;
|
||||
@@ -1778,7 +1787,6 @@ int wrapper_setvbuf(uint8_t *mem, uint32_t fp_addr, uint32_t buf_addr, int mode,
|
||||
f->_ptr_addr = buf_addr;
|
||||
f->_cnt = 0;
|
||||
bufendtab[(fp_addr - IOB_ADDR) / sizeof(struct FILE_irix)] = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wrapper___semgetc(uint8_t *mem, uint32_t fp_addr) {
|
||||
@@ -2181,8 +2189,15 @@ int wrapper_pathconf(uint8_t *mem, uint32_t path_addr, int name) {
|
||||
}
|
||||
|
||||
uint32_t wrapper_getenv(uint8_t *mem, uint32_t name_addr) {
|
||||
// Return null for everything, for now
|
||||
return 0;
|
||||
STRING(name);
|
||||
const char *value = getenv(name);
|
||||
if (value == NULL) {
|
||||
return 0;
|
||||
}
|
||||
size_t value_size = strlen(value) + 1;
|
||||
uint32_t buf_addr = wrapper_malloc(mem, value_size);
|
||||
strcpy1(mem, buf_addr, value);
|
||||
return buf_addr;
|
||||
}
|
||||
|
||||
uint32_t wrapper_gettxt(uint8_t *mem, uint32_t msgid_addr, uint32_t default_str_addr) {
|
||||
@@ -2355,7 +2370,19 @@ int wrapper_mkstemp(uint8_t *mem, uint32_t name_addr) {
|
||||
|
||||
uint32_t wrapper_tmpfile(uint8_t *mem) {
|
||||
// create and fopen a temporary file that is removed when the program exits
|
||||
char name[] = "/tmp/copt_temp_XXXXXX";
|
||||
const char *tmpdir = getenv("TMPDIR");
|
||||
if (tmpdir == NULL) {
|
||||
tmpdir = "/tmp";
|
||||
}
|
||||
|
||||
char name[PATH_MAX + 1] = {0};
|
||||
int n = snprintf(name, sizeof(name), "%s/copt_temp_XXXXXX", tmpdir);
|
||||
if (n < 0 || n >= sizeof(name)) {
|
||||
// This isn't the best errno code, but it is one that can be returned by tmpfile
|
||||
MEM_U32(ERRNO_ADDR) = EACCES;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd = mkstemp(name);
|
||||
if (fd < 0) {
|
||||
MEM_U32(ERRNO_ADDR) = errno;
|
||||
|
||||
@@ -49,7 +49,7 @@ uint32_t wrapper_freopen(uint8_t *mem, uint32_t path_addr, uint32_t mode_addr, u
|
||||
int wrapper_fclose(uint8_t *mem, uint32_t fp_addr);
|
||||
int wrapper_fflush(uint8_t *mem, uint32_t fp_addr);
|
||||
int wrapper_ftell(uint8_t *mem, uint32_t fp_addr);
|
||||
void wrapper_rewind(uint8_t *mem, uint32_t fp_addr);
|
||||
int wrapper_rewind(uint8_t *mem, uint32_t fp_addr);
|
||||
int wrapper_fseek(uint8_t *mem, uint32_t fp_addr, int offset, int origin);
|
||||
int wrapper_lseek(uint8_t *mem, int fd, int offset, int whence);
|
||||
int wrapper_dup(uint8_t *mem, int fd);
|
||||
|
||||
@@ -4,13 +4,16 @@
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <capstone/capstone.h>
|
||||
#else
|
||||
#include <capstone.h>
|
||||
#endif
|
||||
|
||||
#include "elf.h"
|
||||
|
||||
@@ -20,8 +23,15 @@
|
||||
#define TRACE 0
|
||||
#endif
|
||||
|
||||
#ifndef ugen53
|
||||
#define ugen53 0
|
||||
#endif
|
||||
|
||||
#define LABELS_64_BIT 1
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define u32be(x) (uint32_t)(((x & 0xff) << 24) + ((x & 0xff00) << 8) + ((x & 0xff0000) >> 8) + ((uint32_t)(x) >> 24))
|
||||
#define u16be(x) (uint16_t)(((x & 0xff) << 8) + ((x & 0xff00) >> 8))
|
||||
#define read_u32_be(buf) (uint32_t)(((buf)[0] << 24) + ((buf)[1] << 16) + ((buf)[2] << 8) + ((buf)[3]))
|
||||
@@ -71,8 +81,6 @@ struct Function {
|
||||
bool referenced_by_function_pointer;
|
||||
};
|
||||
|
||||
static bool conservative;
|
||||
|
||||
static csh handle;
|
||||
|
||||
static const uint8_t *text_section;
|
||||
@@ -162,7 +170,7 @@ static const struct {
|
||||
{"freopen", "pppp"},
|
||||
{"fclose", "ip"},
|
||||
{"ftell", "ip"},
|
||||
{"rewind", "vp"},
|
||||
{"rewind", "ip"},
|
||||
{"fseek", "ipii"},
|
||||
{"lseek", "iiii"},
|
||||
{"fflush", "ip"},
|
||||
@@ -278,31 +286,24 @@ static const struct {
|
||||
static void disassemble(void) {
|
||||
csh handle;
|
||||
cs_insn *disasm;
|
||||
size_t disasm_size = 0;
|
||||
static size_t disasm_size;
|
||||
assert(cs_open(CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN), &handle) == CS_ERR_OK);
|
||||
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
|
||||
insns.reserve(1 + text_section_len / sizeof(uint32_t)); // +1 for dummy instruction
|
||||
while (text_section_len > disasm_size * sizeof(uint32_t)) {
|
||||
size_t disasm_len = disasm_size * sizeof(uint32_t);
|
||||
size_t remaining = text_section_len - disasm_len;
|
||||
size_t current_len = std::min<size_t>(remaining, 1024);
|
||||
size_t cur_disasm_size = cs_disasm(handle, &text_section[disasm_len], current_len, text_vaddr + disasm_len, 0, &disasm);
|
||||
disasm_size += cur_disasm_size;
|
||||
for (size_t i = 0; i < cur_disasm_size; i++) {
|
||||
insns.push_back(Insn());
|
||||
Insn& insn = insns.back();
|
||||
insn.id = disasm[i].id;
|
||||
insn.mnemonic = disasm[i].mnemonic;
|
||||
insn.op_str = disasm[i].op_str;
|
||||
if (disasm[i].detail != nullptr && disasm[i].detail->mips.op_count > 0) {
|
||||
insn.op_count = disasm[i].detail->mips.op_count;
|
||||
memcpy(insn.operands, disasm[i].detail->mips.operands, sizeof(insn.operands));
|
||||
}
|
||||
insn.is_jump = cs_insn_group(handle, &disasm[i], MIPS_GRP_JUMP) || insn.id == MIPS_INS_JAL || insn.id == MIPS_INS_BAL || insn.id == MIPS_INS_JALR;
|
||||
insn.linked_insn = -1;
|
||||
disasm_size = cs_disasm(handle, text_section, text_section_len, text_vaddr, 0, &disasm);
|
||||
for (size_t i = 0; i < disasm_size; i++) {
|
||||
insns.push_back(Insn());
|
||||
Insn& insn = insns.back();
|
||||
insn.id = disasm[i].id;
|
||||
insn.mnemonic = disasm[i].mnemonic;
|
||||
insn.op_str = disasm[i].op_str;
|
||||
if (disasm[i].detail != nullptr && disasm[i].detail->mips.op_count > 0) {
|
||||
insn.op_count = disasm[i].detail->mips.op_count;
|
||||
memcpy(insn.operands, disasm[i].detail->mips.operands, sizeof(insn.operands));
|
||||
}
|
||||
cs_free(disasm, cur_disasm_size);
|
||||
insn.is_jump = cs_insn_group(handle, &disasm[i], MIPS_GRP_JUMP) || insn.id == MIPS_INS_JAL || insn.id == MIPS_INS_BAL || insn.id == MIPS_INS_JALR;
|
||||
insn.linked_insn = -1;
|
||||
}
|
||||
cs_free(disasm, disasm_size);
|
||||
cs_close(&handle);
|
||||
|
||||
{
|
||||
@@ -339,7 +340,7 @@ static void link_with_lui(int offset, uint32_t reg, int mem_imm)
|
||||
#define MAX_LOOKBACK 128
|
||||
// don't attempt to compute addresses for zero offset
|
||||
// end search after some sane max number of instructions
|
||||
int end_search = std::max(0, offset - MAX_LOOKBACK);
|
||||
int end_search = MAX(0, offset - MAX_LOOKBACK);
|
||||
for (int search = offset - 1; search >= end_search; search--) {
|
||||
// use an `if` instead of `case` block to allow breaking out of the `for` loop
|
||||
if (insns[search].id == MIPS_INS_LUI) {
|
||||
@@ -426,7 +427,7 @@ static void link_with_lui(int offset, uint32_t reg, int mem_imm)
|
||||
static void link_with_jalr(int offset)
|
||||
{
|
||||
// end search after some sane max number of instructions
|
||||
int end_search = std::max(0, offset - MAX_LOOKBACK);
|
||||
int end_search = MAX(0, offset - MAX_LOOKBACK);
|
||||
for (int search = offset - 1; search >= end_search; search--) {
|
||||
if (insns[search].operands[0].reg == MIPS_REG_T9) {
|
||||
if (insns[search].id == MIPS_INS_LW || insns[search].id == MIPS_INS_LI) {
|
||||
@@ -1639,7 +1640,7 @@ static void dump_instr(int i) {
|
||||
printf("++cnt; printf(\"pc=0x%08x%s%s\\n\"); ", text_vaddr + i * 4, symbol_name ? " " : "", symbol_name ? symbol_name : "");
|
||||
}
|
||||
Insn& insn = insns[i];
|
||||
if (!insn.is_jump && !conservative) {
|
||||
if (!insn.is_jump && !ugen53) {
|
||||
switch (insn_to_type(insn)) {
|
||||
case TYPE_1S:
|
||||
if (!(insn.f_livein & map_reg(insn.operands[0].reg))) {
|
||||
@@ -2337,16 +2338,16 @@ static void dump_c(void) {
|
||||
uint32_t max_addr = 0;
|
||||
|
||||
if (data_section_len > 0) {
|
||||
min_addr = std::min(min_addr, data_vaddr);
|
||||
max_addr = std::max(max_addr, data_vaddr + data_section_len);
|
||||
min_addr = MIN(min_addr, data_vaddr);
|
||||
max_addr = MAX(max_addr, data_vaddr + data_section_len);
|
||||
}
|
||||
if (rodata_section_len > 0) {
|
||||
min_addr = std::min(min_addr, rodata_vaddr);
|
||||
max_addr = std::max(max_addr, rodata_vaddr + rodata_section_len);
|
||||
min_addr = MIN(min_addr, rodata_vaddr);
|
||||
max_addr = MAX(max_addr, rodata_vaddr + rodata_section_len);
|
||||
}
|
||||
if (bss_section_len) {
|
||||
min_addr = std::min(min_addr, bss_vaddr);
|
||||
max_addr = std::max(max_addr, bss_vaddr + bss_section_len);
|
||||
min_addr = MIN(min_addr, bss_vaddr);
|
||||
max_addr = MAX(max_addr, bss_vaddr + bss_section_len);
|
||||
}
|
||||
|
||||
min_addr = min_addr & ~0xfff;
|
||||
@@ -2357,7 +2358,7 @@ static void dump_c(void) {
|
||||
stack_bottom -= 16; // for main's stack frame
|
||||
|
||||
printf("#include \"header.h\"\n");
|
||||
if (conservative) {
|
||||
if (ugen53) {
|
||||
printf("static uint32_t s0, s1, s2, s3, s4, s5, s6, s7, fp;\n");
|
||||
}
|
||||
printf("static const uint32_t rodata[] = {\n");
|
||||
@@ -2485,7 +2486,7 @@ static void dump_c(void) {
|
||||
dump_function_signature(f, start_addr);
|
||||
printf(" {\n");
|
||||
printf("const uint32_t zero = 0;\n");
|
||||
if (!conservative) {
|
||||
if (!ugen53) {
|
||||
printf("uint32_t at = 0, v1 = 0, t0 = 0, t1 = 0, t2 = 0,\n");
|
||||
printf("t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, s0 = 0, s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0,\n");
|
||||
printf("s6 = 0, s7 = 0, t8 = 0, t9 = 0, gp = 0, fp = 0, s8 = 0, ra = 0;\n");
|
||||
@@ -2910,14 +2911,8 @@ size_t read_file(const char *file_name, uint8_t **data) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *filename = argv[1];
|
||||
if (strcmp(filename, "--conservative") == 0) {
|
||||
conservative = true;
|
||||
filename = argv[2];
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len = read_file(filename, &data);
|
||||
size_t len = read_file(argv[1], &data);
|
||||
parse_elf(data, len);
|
||||
assert(cs_open(CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN), &handle) == CS_ERR_OK);
|
||||
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
|
||||
|
||||
+4
-1
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "libmio0.h"
|
||||
#include "utils.h"
|
||||
|
||||
// defines
|
||||
|
||||
#define MIO0_VERSION "0.1"
|
||||
@@ -271,6 +270,7 @@ int mio0_encode(const unsigned char *in, unsigned int length, unsigned char *out
|
||||
// compute final sizes and offsets
|
||||
// +7 so int division accounts for all bits
|
||||
bit_length = ((bit_idx + 7) / 8);
|
||||
|
||||
// compressed data after control bits and aligned to 4-byte boundary
|
||||
comp_offset = ALIGN(MIO0_HEADER_LENGTH + bit_length, 4);
|
||||
uncomp_offset = comp_offset + comp_idx;
|
||||
@@ -282,7 +282,10 @@ int mio0_encode(const unsigned char *in, unsigned int length, unsigned char *out
|
||||
write_u32_be(&out[8], comp_offset);
|
||||
write_u32_be(&out[12], uncomp_offset);
|
||||
// output data
|
||||
memset(&out[MIO0_HEADER_LENGTH], 0, MIO0_HEADER_LENGTH + bit_length);
|
||||
memcpy(&out[MIO0_HEADER_LENGTH], bit_buf, bit_length);
|
||||
|
||||
//print_hex(bit_buf, bit_length);
|
||||
memcpy(&out[comp_offset], comp_buf, comp_idx);
|
||||
memcpy(&out[uncomp_offset], uncomp_buf, uncomp_idx);
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
#include "libtkmk00.h"
|
||||
#include "utils.h"
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#define TKMK00_VERSION "0.1"
|
||||
|
||||
|
||||
+9
-7
@@ -238,6 +238,7 @@ int ia2raw(uint8_t *raw, const ia *img, int width, int height, int depth)
|
||||
{
|
||||
int size = (width * height * depth + 7) / 8;
|
||||
INFO("Converting IA%d %dx%d to raw\n", depth, width, height);
|
||||
memset(raw, 0, size);
|
||||
|
||||
switch (depth) {
|
||||
case 16:
|
||||
@@ -290,6 +291,7 @@ int i2raw(uint8_t *raw, const ia *img, int width, int height, int depth)
|
||||
{
|
||||
int size = (width * height * depth + 7) / 8;
|
||||
INFO("Converting I%d %dx%d to raw\n", depth, width, height);
|
||||
memset(raw, 0, size);
|
||||
|
||||
switch (depth) {
|
||||
case 8:
|
||||
@@ -849,11 +851,11 @@ int main(int argc, char *argv[])
|
||||
if (config.mode == MODE_IMPORT) {
|
||||
if (0 == strcmp("-", config.bin_filename)) {
|
||||
bin_fp = stdout;
|
||||
} else {
|
||||
} else {
|
||||
if (config.bin_truncate) {
|
||||
bin_fp = fopen(config.bin_filename, "w");
|
||||
bin_fp = fopen(config.bin_filename, "wb");
|
||||
} else {
|
||||
bin_fp = fopen(config.bin_filename, "r+");
|
||||
bin_fp = fopen(config.bin_filename, "r+b");
|
||||
}
|
||||
}
|
||||
if (!bin_fp) {
|
||||
@@ -904,9 +906,9 @@ int main(int argc, char *argv[])
|
||||
int pal_length;
|
||||
|
||||
if (config.pal_truncate) {
|
||||
pal_fp = fopen(config.pal_filename, "w");
|
||||
pal_fp = fopen(config.pal_filename, "wb");
|
||||
} else {
|
||||
pal_fp = fopen(config.pal_filename, "r+");
|
||||
pal_fp = fopen(config.pal_filename, "r+b");
|
||||
}
|
||||
if (!pal_fp) {
|
||||
ERROR("Error opening \"%s\"\n", config.pal_filename);
|
||||
@@ -988,7 +990,7 @@ int main(int argc, char *argv[])
|
||||
ERROR("Error: must set position width and height for export\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
bin_fp = fopen(config.bin_filename, "r");
|
||||
bin_fp = fopen(config.bin_filename, "rb");
|
||||
if (!bin_fp) {
|
||||
ERROR("Error opening \"%s\"\n", config.bin_filename);
|
||||
return -1;
|
||||
@@ -1025,7 +1027,7 @@ int main(int argc, char *argv[])
|
||||
INFO("Extracting %s offset 0x%X, pal.offset 0x%0X, pal.format %s\n", format2str(&config.format),
|
||||
config.bin_offset, config.pal_offset, format2str(&config.pal_format));
|
||||
|
||||
pal_fp = fopen(config.pal_filename, "r");
|
||||
pal_fp = fopen(config.pal_filename, "rb");
|
||||
if (!pal_fp) {
|
||||
ERROR("Error opening \"%s\"\n", config.bin_filename);
|
||||
return EXIT_FAILURE;
|
||||
|
||||
+36
-12
@@ -61,24 +61,48 @@ int fprint_write_output(FILE *fp, write_encoding encoding, const uint8_t *raw, i
|
||||
int flength = 0;
|
||||
const encoding_format *fmt = &enc_fmt[encoding];
|
||||
switch (encoding) {
|
||||
case ENCODING_RAW:
|
||||
flength = fwrite(raw, 1, length, fp);
|
||||
break;
|
||||
case ENCODING_U8:
|
||||
case ENCODING_U16:
|
||||
case ENCODING_U32:
|
||||
case ENCODING_U64:
|
||||
case ENCODING_RAW:
|
||||
flength = fwrite(raw, 1, length, fp);
|
||||
break;
|
||||
case ENCODING_U8:
|
||||
case ENCODING_U16:
|
||||
case ENCODING_U32:
|
||||
case ENCODING_U64:
|
||||
for (int w = 0; w < length; w += fmt->bytes_per_val) {
|
||||
flength += fprintf(fp, "0x");
|
||||
for (int b = 0; b < fmt->bytes_per_val; b++) {
|
||||
int off = w + b;
|
||||
flength += fprintf(fp, "%02x", off < length ? raw[off] : 0x00);
|
||||
int off = w + b;
|
||||
flength += fprintf(fp, "%02x", off < length ? raw[off] : 0x00);
|
||||
}
|
||||
flength += fprintf(fp, "%s%c", fmt->suffix, (w < length - fmt->bytes_per_val) ? ',' : '\n');
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return flength;
|
||||
}
|
||||
|
||||
void fprint_hex(FILE *fp, const unsigned char *buf, int length)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
fprint_byte(fp, buf[i]);
|
||||
fputc(' ', fp);
|
||||
}
|
||||
return flength;
|
||||
}
|
||||
|
||||
void fprint_hex_source(FILE *fp, const unsigned char *buf, int length)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
if (i > 0) fputs(", ", fp);
|
||||
fputs("0x", fp);
|
||||
fprint_byte(fp, buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void print_hex(const unsigned char *buf, int length)
|
||||
{
|
||||
fprint_hex(stdout, buf, length);
|
||||
}
|
||||
|
||||
void swap_bytes(unsigned char *data, long length)
|
||||
|
||||
+15
-3
@@ -40,6 +40,15 @@
|
||||
(buf)[1] = ((val)) & 0xFF; \
|
||||
} while(0)
|
||||
|
||||
// print nibbles and bytes
|
||||
#define fprint_nibble(FP, NIB_) fputc((NIB_) < 10 ? ('0' + (NIB_)) : ('A' + (NIB_) - 0xA), FP)
|
||||
#define fprint_byte(FP, BYTE_) do { \
|
||||
fprint_nibble(FP, (BYTE_) >> 4); \
|
||||
fprint_nibble(FP, (BYTE_) & 0x0F); \
|
||||
} while(0)
|
||||
#define print_nibble(NIB_) fprint_nibble(stdout, NIB_)
|
||||
#define print_byte(BYTE_) fprint_byte(stdout, BYTE_)
|
||||
|
||||
// Windows compatibility
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#include <direct.h>
|
||||
@@ -72,6 +81,7 @@ extern int g_verbosity;
|
||||
|
||||
#define ERROR(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define INFO(...) if (g_verbosity) printf(__VA_ARGS__)
|
||||
#define INFO_HEX(...) if (g_verbosity) print_hex(__VA_ARGS__)
|
||||
|
||||
// functions
|
||||
|
||||
@@ -85,12 +95,14 @@ float read_f32_be(unsigned char *buf);
|
||||
// returns 1 if val is power of 2, 0 otherwise
|
||||
int is_power2(unsigned int val);
|
||||
|
||||
// print buffer as raw binary, hex u8, hex u16, hex u32, hex u64. pads to encoding size
|
||||
// print buffer as hex bytes
|
||||
// fp: file pointer
|
||||
// encoding: encoding type to use (see write_encoding)
|
||||
// buf: buffer to read bytes from
|
||||
// length: length of buffer to print
|
||||
int fprint_write_output(FILE *fp, write_encoding encoding, const uint8_t *buf, int length);
|
||||
int fprint_write_output(FILE *fp, write_encoding, const uint8_t *buf, int length);
|
||||
void fprint_hex(FILE *fp, const unsigned char *buf, int length);
|
||||
void fprint_hex_source(FILE *fp, const unsigned char *buf, int length);
|
||||
extern void print_hex(const unsigned char *buf, int length);
|
||||
|
||||
// perform byteswapping to convert from v64 to z64 ordering
|
||||
void swap_bytes(unsigned char *data, long length);
|
||||
|
||||
Reference in New Issue
Block a user