You've already forked ultrasm64-2
mirror of
https://github.com/HackerN64/ultrasm64-2.git
synced 2026-01-21 10:38:08 -08:00
Refresh 14
This commit is contained in:
2
tools/.gitignore
vendored
2
tools/.gitignore
vendored
@@ -6,7 +6,7 @@
|
||||
/n64cksum
|
||||
/n64graphics
|
||||
/n64graphics_ci
|
||||
/patch_libultra_math
|
||||
/patch_elf_32bit
|
||||
/skyconv
|
||||
/tabledesign
|
||||
/textconv
|
||||
|
||||
@@ -7,7 +7,7 @@ CC := gcc
|
||||
CXX := g++
|
||||
CFLAGS := -I . -Wall -Wextra -Wno-unused-parameter -pedantic -O2 -s
|
||||
LDFLAGS := -lm
|
||||
ALL_PROGRAMS := armips n64graphics n64graphics_ci mio0 n64cksum textconv patch_libultra_math aifc_decode aiff_extract_codebook vadpcm_enc tabledesign extract_data_for_mio skyconv
|
||||
ALL_PROGRAMS := armips n64graphics n64graphics_ci mio0 n64cksum textconv patch_elf_32bit aifc_decode aiff_extract_codebook vadpcm_enc tabledesign extract_data_for_mio skyconv
|
||||
LIBAUDIOFILE := audiofile/libaudiofile.a
|
||||
|
||||
# Only build armips from tools if it is not found on the system
|
||||
@@ -32,7 +32,7 @@ n64cksum_CFLAGS := -DN64CKSUM_STANDALONE
|
||||
|
||||
textconv_SOURCES := textconv.c utf8.c hashtable.c
|
||||
|
||||
patch_libultra_math_SOURCES := patch_libultra_math.c
|
||||
patch_elf_32bit_SOURCES := patch_elf_32bit.c
|
||||
|
||||
aifc_decode_SOURCES := aifc_decode.c
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Create an ADPCM codebook either by extracting it from an AIFF section, or
|
||||
* by executing tabledesign.
|
||||
*/
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -659,7 +659,7 @@ def serialize_ctl(bank, base_ser, is_shindou):
|
||||
base_ser.add(ser.finish())
|
||||
|
||||
return pack(
|
||||
"BBBB", bank.sample_bank.index, 0xFF, len(json["instrument_list"]), len(drums)
|
||||
"hh", (bank.sample_bank.index << 8) | 0xFF, (len(json["instrument_list"]) << 8) | len(drums)
|
||||
)
|
||||
|
||||
|
||||
@@ -704,7 +704,8 @@ def serialize_seqfile(
|
||||
ser = ReserveSerializer()
|
||||
ser.add(pack("H", len(entries)))
|
||||
ser.align(16)
|
||||
sh_magic = 0x0204 if magic == TYPE_TBL else 0x0203
|
||||
medium = 0x02 # cartridge
|
||||
sh_magic = 0x04 if magic == TYPE_TBL else 0x03
|
||||
|
||||
# Ignore entry_list and loop over all entries instead. This makes a
|
||||
# difference for sample banks, where US/JP/EU doesn't use a normal
|
||||
@@ -712,9 +713,9 @@ def serialize_seqfile(
|
||||
# sample bank offset/length. Shindou uses a normal header and makes the
|
||||
# mapping part of the sound bank header instead (part of entry_meta).
|
||||
for i in range(len(entries)):
|
||||
ser.add(pack("PIH", entry_offsets[i], entry_lens[i], sh_magic))
|
||||
ser.add(pack("PIbb", entry_offsets[i], entry_lens[i], medium, sh_magic))
|
||||
ser.add(entry_meta[i] or b"\0\0\0\0")
|
||||
ser.align(16)
|
||||
ser.align(WORD_BYTES)
|
||||
|
||||
if out_header_filename:
|
||||
with open(out_header_filename, "wb") as f:
|
||||
|
||||
@@ -62,7 +62,7 @@ def main():
|
||||
structdef.append("u8 " + item["name"] + "[" + str(len(demobytes)) + "];")
|
||||
structobj.append("{" + ",".join(hex(x) for x in demobytes) + "},")
|
||||
|
||||
print("#include \"types.h\"")
|
||||
print("#include \"game/memory.h\"")
|
||||
print("#include <stddef.h>")
|
||||
print("")
|
||||
|
||||
|
||||
@@ -177,13 +177,13 @@ static char bin_dir[PATH_MAX + 1];
|
||||
#endif
|
||||
static int g_file_max = 3;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#if defined(__CYGWIN__) || defined(__APPLE__)
|
||||
static size_t g_Pagesize;
|
||||
#endif
|
||||
|
||||
static uint8_t *memory_map(size_t length)
|
||||
{
|
||||
#ifdef __CYGWIN__
|
||||
#if defined(__CYGWIN__) || defined(__APPLE__)
|
||||
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 +201,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);
|
||||
#ifdef __CYGWIN__
|
||||
#if defined(__CYGWIN__) || defined(__APPLE__)
|
||||
uintptr_t _start = ((uintptr_t)mem + start) & ~(g_Pagesize-1);
|
||||
uintptr_t _end = ((uintptr_t)mem + end + (g_Pagesize-1)) & ~(g_Pagesize-1);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@@ -21,9 +22,6 @@
|
||||
|
||||
#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]))
|
||||
@@ -280,24 +278,31 @@ static const struct {
|
||||
static void disassemble(void) {
|
||||
csh handle;
|
||||
cs_insn *disasm;
|
||||
static size_t disasm_size;
|
||||
size_t disasm_size = 0;
|
||||
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);
|
||||
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));
|
||||
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;
|
||||
}
|
||||
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, cur_disasm_size);
|
||||
}
|
||||
cs_free(disasm, disasm_size);
|
||||
cs_close(&handle);
|
||||
|
||||
{
|
||||
@@ -334,7 +339,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 = MAX(0, offset - MAX_LOOKBACK);
|
||||
int end_search = std::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) {
|
||||
@@ -421,7 +426,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 = MAX(0, offset - MAX_LOOKBACK);
|
||||
int end_search = std::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) {
|
||||
@@ -2332,16 +2337,16 @@ static void dump_c(void) {
|
||||
uint32_t max_addr = 0;
|
||||
|
||||
if (data_section_len > 0) {
|
||||
min_addr = MIN(min_addr, data_vaddr);
|
||||
max_addr = MAX(max_addr, data_vaddr + data_section_len);
|
||||
min_addr = std::min(min_addr, data_vaddr);
|
||||
max_addr = std::max(max_addr, data_vaddr + data_section_len);
|
||||
}
|
||||
if (rodata_section_len > 0) {
|
||||
min_addr = MIN(min_addr, rodata_vaddr);
|
||||
max_addr = MAX(max_addr, rodata_vaddr + rodata_section_len);
|
||||
min_addr = std::min(min_addr, rodata_vaddr);
|
||||
max_addr = std::max(max_addr, rodata_vaddr + rodata_section_len);
|
||||
}
|
||||
if (bss_section_len) {
|
||||
min_addr = MIN(min_addr, bss_vaddr);
|
||||
max_addr = MAX(max_addr, bss_vaddr + 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_addr & ~0xfff;
|
||||
|
||||
@@ -136,7 +136,7 @@ try:
|
||||
structdef.append("{} {}[{}];".format(type, name, len(arr)))
|
||||
structobj.append("{" + ",".join(arr) + "},")
|
||||
|
||||
print("#include \"types.h\"")
|
||||
print("#include \"game/memory.h\"")
|
||||
print("#include <stddef.h>")
|
||||
print("")
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
for line in sys.stdin:
|
||||
if line.strip():
|
||||
print('#include "{}"'.format(line.strip()))
|
||||
@@ -3,6 +3,9 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
|
||||
/* from elf.h */
|
||||
|
||||
/* Type for a 16-bit quantity. */
|
||||
@@ -78,13 +81,36 @@ struct ar_header {
|
||||
//These constants found by inspecting output of objdump
|
||||
#define FLAGS_MIPS3 0x20
|
||||
#define FLAGS_O32ABI 0x100000
|
||||
int main(int argc, char **argv) {
|
||||
FILE *f = fopen(argv[1], "r+");
|
||||
|
||||
if (f == NULL) {
|
||||
printf("Failed to open file! %s\n", argv[1]);
|
||||
int fix_mips_elf(FILE *f, size_t filesize)
|
||||
{
|
||||
Elf32_Ehdr hdr;
|
||||
if (filesize < sizeof(hdr) || (1 != fread(&hdr, sizeof(hdr), 1, f))) {
|
||||
printf("Failed to read ELF header\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncmp((const char *) hdr.e_ident, ELFMAG, SELFMAG) == 0) {
|
||||
// found an ELF file.
|
||||
if (hdr.e_ident[EI_CLASS] != ELFCLASS32 || hdr.e_ident[EI_DATA] != ELFDATA2MSB) {
|
||||
printf("Expected 32bit big endian object files\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((hdr.e_flags & 0xFF) == FLAGS_MIPS3 && (hdr.e_flags & FLAGS_O32ABI) == 0) {
|
||||
hdr.e_flags |= FLAGS_O32ABI;
|
||||
fseek(f, -(long)sizeof(hdr), SEEK_CUR);
|
||||
if (1 != fwrite(&hdr, sizeof(hdr), 1, f)) {
|
||||
printf("Failed to write back ELF header after patching.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fix_mips_ar(FILE *f)
|
||||
{
|
||||
struct ar_header current_header;
|
||||
fseek(f, 0x8, SEEK_SET); // skip header, this is safe enough given that we check to make sure the
|
||||
// file header is valid
|
||||
@@ -95,32 +121,41 @@ int main(int argc, char **argv) {
|
||||
return -1;
|
||||
}
|
||||
size_t filesize = atoi(current_header.file_size_in_bytes);
|
||||
Elf32_Ehdr hdr;
|
||||
if (filesize < sizeof(hdr) || (1 != fread(&hdr, sizeof(hdr), 1, f))) {
|
||||
printf("Failed to read ELF header\n");
|
||||
if (fix_mips_elf(f, filesize)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncmp((const char *) hdr.e_ident, ELFMAG, SELFMAG) == 0) {
|
||||
// found an ELF file.
|
||||
if (hdr.e_ident[EI_CLASS] != ELFCLASS32 || hdr.e_ident[EI_DATA] != ELFDATA2MSB) {
|
||||
printf("Expected 32bit big endian object files\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((hdr.e_flags & 0xFF) == FLAGS_MIPS3 && (hdr.e_flags & FLAGS_O32ABI) == 0) {
|
||||
hdr.e_flags |= FLAGS_O32ABI;
|
||||
fseek(f, -sizeof(hdr), SEEK_CUR);
|
||||
if (1 != fwrite(&hdr, sizeof(hdr), 1, f)) {
|
||||
printf("Failed to write back ELF header after patching.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filesize % 2 == 1)
|
||||
filesize++;
|
||||
fseek(f, filesize - sizeof(hdr), SEEK_CUR);
|
||||
fseek(f, filesize - sizeof(Elf32_Ehdr), SEEK_CUR);
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *f = fopen(argv[1], "r+b");
|
||||
uint8_t magic[8];
|
||||
int status = 0;
|
||||
|
||||
if (f == NULL) {
|
||||
printf("Failed to open file! %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
if (1 != fread(&magic, sizeof(magic), 1, f)) {
|
||||
printf("Failed to read file magic\n");
|
||||
return -1;
|
||||
}
|
||||
rewind(f);
|
||||
if (!memcmp(ARMAG, magic, SARMAG)) {
|
||||
status = fix_mips_ar(f);
|
||||
} else if (!memcmp(ELFMAG, magic, SELFMAG)) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t filesize = ftell(f);
|
||||
rewind(f);
|
||||
status = fix_mips_elf(f, filesize);
|
||||
} else {
|
||||
printf("Unknown file magic: %02x%02x%02X%02X\n", magic[0], magic[1], magic[2], magic[3]);
|
||||
status = -1;
|
||||
}
|
||||
fclose(f);
|
||||
return status;
|
||||
}
|
||||
@@ -162,8 +162,8 @@ if len(sys.argv) != 2:
|
||||
sys.exit(0)
|
||||
|
||||
if sys.argv[1] == "--emit-asm-macros":
|
||||
print("# Macros for disassembled sequence files. This file was automatically generated by seq_decoder.py.")
|
||||
print("# To regenerate it, run: ./tools/seq_decoder.py --emit-asm-macros >seq_macros.inc")
|
||||
print("// Macros for disassembled sequence files. This file was automatically generated by seq_decoder.py.")
|
||||
print("// To regenerate it, run: ./tools/seq_decoder.py --emit-asm-macros > include/seq_macros.inc")
|
||||
print()
|
||||
def print_hword(x):
|
||||
print(f" .byte {x} >> 8, {x} & 0xff")
|
||||
@@ -219,7 +219,7 @@ if sys.argv[1] == "--emit-asm-macros":
|
||||
print(".endm\n")
|
||||
|
||||
for key in ['seq', 'chan', 'layer']:
|
||||
print(f"# {key} commands\n")
|
||||
print(f"// {key} commands\n")
|
||||
if key == 'layer':
|
||||
cmds = commands['layer_large']
|
||||
for op in sorted(commands['layer_small'].keys()):
|
||||
@@ -267,31 +267,31 @@ if sys.argv[1] == "--emit-asm-macros":
|
||||
emit_cmd(key, 0xc0, ['delay_long', 'var_long'])
|
||||
emit_cmd(key, 0x40, ['note1_long', 'bits:4', 'var_long', 'u8'])
|
||||
if eu_sh or us_jp or sh or non_sh:
|
||||
print(".ifdef VERSION_SH\n")
|
||||
print("#ifdef VERSION_SH\n")
|
||||
for (op, cmd) in eu_sh:
|
||||
emit_cmd(key, op, cmd)
|
||||
for (op, cmd) in sh:
|
||||
emit_cmd(key, op, cmd)
|
||||
print(".else\n")
|
||||
print("#else\n")
|
||||
for (op, cmd) in non_sh:
|
||||
emit_cmd(key, op, cmd)
|
||||
print(".ifdef VERSION_EU\n")
|
||||
print("#ifdef VERSION_EU\n")
|
||||
for (op, cmd) in eu_sh:
|
||||
emit_cmd(key, op, cmd)
|
||||
print(".else\n")
|
||||
print("#else\n")
|
||||
for (op, cmd) in us_jp:
|
||||
emit_cmd(key, op, cmd)
|
||||
print(".endif\n")
|
||||
print(".endif\n")
|
||||
print("#endif\n")
|
||||
print("#endif\n")
|
||||
|
||||
print("# envelope commands\n")
|
||||
print("// envelope commands\n")
|
||||
emit_env_cmd(0, ['disable', 'u16'])
|
||||
emit_env_cmd(2**16-1, ['hang', 'u16:ign'])
|
||||
emit_env_cmd(2**16-2, ['goto', 'u16'])
|
||||
emit_env_cmd(2**16-3, ['restart', 'u16:ign'])
|
||||
emit_env_cmd(None, ['line', 'u16', 'u16'])
|
||||
|
||||
print("# other commands\n")
|
||||
print("// other commands\n")
|
||||
print(".macro var_long x")
|
||||
print(" .byte (0x80 | (\\x & 0x7f00) >> 8), (\\x & 0xff)")
|
||||
print(".endm\n")
|
||||
|
||||
Reference in New Issue
Block a user