Refresh 14

This commit is contained in:
n64
2021-07-12 23:17:54 -04:00
parent ecd3d152fb
commit f9982e0ef5
251 changed files with 7496 additions and 5757 deletions

2
tools/.gitignore vendored
View File

@@ -6,7 +6,7 @@
/n64cksum
/n64graphics
/n64graphics_ci
/patch_libultra_math
/patch_elf_32bit
/skyconv
/tabledesign
/textconv

View File

@@ -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

View File

@@ -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>

View File

@@ -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:

View File

@@ -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("")

View File

@@ -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);

View File

@@ -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;

View File

@@ -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("")

View File

@@ -1,5 +0,0 @@
#!/usr/bin/env python3
import sys
for line in sys.stdin:
if line.strip():
print('#include "{}"'.format(line.strip()))

View File

@@ -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;
}

View File

@@ -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")