Merge branch 'DavidSM64:master' into glabels

This commit is contained in:
AntonioCastelli
2021-05-30 15:42:51 -07:00
9 changed files with 169 additions and 93 deletions
-28
View File
@@ -1,28 +0,0 @@
.include "macros.inc"
.macro .aligned_text ascii
.asciz "\ascii"
.balign 4
.endm
.section .rodata
.aligned_text "amSndPlay: Illegal sound effects table index\n"
.aligned_text "amSndPlayDirect: Somebody tried to play illegal sound %d\n"
.aligned_text "Invalid midi sequence index\n"
glabel D_800E49DC
.float 60000000.0
glabel D_800E49E0
.float 46875.0
glabel D_800E49E4
.float 46875.0
glabel D_800E49E8
.float 120000.0
glabel D_800E49EC
.float 60000000.0
-40
View File
@@ -1,40 +0,0 @@
.include "macros.inc"
.macro .aligned_text ascii
.asciz "\ascii"
.balign 4
.endm
.section .rodata
.aligned_text "audio manager: RCP audio interface bug caused DMA from bad address - move audiomgr.c in the makelist!\n"
.aligned_text "audio: ai out of samples\n"
.aligned_text "OH DEAR - No audio DMA buffers left\n"
.aligned_text "Dma not done\n"
.word 0x00000000
.aligned_text "Bad soundState: voices =%d, states free =%d, states busy =%d, type %d data %x\n"
.aligned_text "playing a playing sound\n"
.aligned_text "Nonsense sndp event\n"
.aligned_text "Sound state allocate failed - sndId %d\n"
.aligned_text "Don't worry - game should cope OK\n"
.aligned_text "WARNING: Attempt to stop NULL sound aborted\n"
glabel D_800E4BB0
.word 0x800035C4
.word 0x80003A0C
.word 0x80004090
.word 0x80003B2C
.word 0x80004090
.word 0x80004090
.word 0x80004090
.word 0x80003C8C
.word 0x80004090
.word 0x80004090
.word 0x80004090
.word 0x80004090
.word 0x80004090
.word 0x80004090
.word 0x80004090
.word 0x80003BA4
+8
View File
@@ -39,4 +39,12 @@ typedef s32 ptrdiff_t;
//#include <stddef.h>
//#endif
// Temporary until all the appropriate functions are decompiled.
typedef struct FloatLiteral {
float floatLiteral;
} FloatLiteral;
typedef struct DoubleLiteral {
double doubleLiteral;
} DoubleLiteral;
#endif
+12 -8
View File
@@ -38,14 +38,21 @@ u8 D_800DC670 = 0;
/************ .rodata ************/
extern f32 D_800E49DC;
extern f32 D_800E49EC;
extern u8 D_800EBF60;
// Debug strings
const char D_800E4950[] = "amSndPlay: Illegal sound effects table index\n";
const char D_800E4980[] = "amSndPlayDirect: Somebody tried to play illegal sound %d\n";
const char D_800E49BC[] = "Invalid midi sequence index\n";
const FloatLiteral D_800E49DC = { 60000000.0f };
const FloatLiteral D_800E49E0 = { 46875.0f };
const FloatLiteral D_800E49E4 = { 46875.0f };
const FloatLiteral D_800E49E8 = { 120000.0f };
/*********************************/
/************ .bss ************/
extern u8 D_800EBF60;
extern ALHeap gALHeap;
/* Unknown size */
@@ -539,11 +546,10 @@ void func_800014BC(f32 arg0) {
musicSetTempo((s32)((f32)(u32)(musicGetTempo() & 0xFF) * arg0));
}
void musicSetTempo(s32 tempo){
if(tempo != 0){
f32 inv_tempo = (1.0f/tempo);
alCSPSetTempo(gMusicPlayer,(s32)(inv_tempo*D_800E49DC));
alCSPSetTempo(gMusicPlayer,(s32)(inv_tempo*D_800E49DC.floatLiteral));
D_80115D30 = tempo;
}
}
@@ -557,8 +563,6 @@ u8 musicIsPlaying(void) {
}
extern f32 D_800E49E0;
extern f32 D_800E49E8;
extern f32 D_80115D34;
#if 1
@@ -617,7 +621,7 @@ void func_80001784(u8 a0){
void sfxSetTempo(s32 tempo){
f32 inv_tempo = (1.0f/tempo);
alCSPSetTempo(gSndFxPlayer,(s32)(inv_tempo*D_800E49EC));
alCSPSetTempo(gSndFxPlayer,(s32)(inv_tempo * 60000000.0f));
}
+25
View File
@@ -98,6 +98,31 @@ s32 D_800DC6C4 = 0; // Currently unknown, might be a different type.
/*******************************/
/************ .rodata ************/
// Debug strings
const char D_800E49F0[] = "audio manager: RCP audio interface bug caused DMA from bad address - move audiomgr.c in the makelist!\n";
const char D_800E4A58[] = "audio: ai out of samples\n";
const char D_800E4A74[] = "OH DEAR - No audio DMA buffers left\n";
const char D_800E4A9C[] = "Dma not done\n";
const char D_800E4AAC[] = "";
const char D_800E49B0[] = "Bad soundState: voices =%d, states free =%d, states busy =%d, type %d data %x\n";
const char D_800E4B00[] = "playing a playing sound\n";
const char D_800E4B1C[] = "Nonsense sndp event\n";
const char D_800E4B34[] = "Sound state allocate failed - sndId %d\n";
const char D_800E4B5C[] = "Don't worry - game should cope OK\n";
const char D_800E4B80[] = "WARNING: Attempt to stop NULL sound aborted\n";
// Jump table for _handleEvent
const u32 D_800E4BB0[] = {
0x800035C4, 0x80003A0C, 0x80004090, 0x80003B2C,
0x80004090, 0x80004090, 0x80004090, 0x80003C8C,
0x80004090, 0x80004090, 0x80004090, 0x80004090,
0x80004090, 0x80004090, 0x80004090, 0x80003BA4
};
/*******************************/
/************ .bss ************/
extern s32 D_80115F90;
+95 -17
View File
@@ -81,6 +81,9 @@ R_MIPS_26 = 4
R_MIPS_HI16 = 5
R_MIPS_LO16 = 6
MIPS_DEBUG_ST_STATIC = 2
MIPS_DEBUG_ST_STATIC_PROC = 14
class ElfHeader:
"""
@@ -132,14 +135,19 @@ class Symbol:
} Elf32_Sym;
"""
def __init__(self, data, strtab):
def __init__(self, data, strtab, name=None):
self.st_name, self.st_value, self.st_size, st_info, self.st_other, self.st_shndx = struct.unpack('>IIIBBH', data)
assert self.st_shndx != SHN_XINDEX, "too many sections (SHN_XINDEX not supported)"
self.bind = st_info >> 4
self.type = st_info & 15
self.name = strtab.lookup_str(self.st_name)
self.name = name if name is not None else strtab.lookup_str(self.st_name)
self.visibility = self.st_other & 3
@staticmethod
def from_parts(st_name, st_value, st_size, st_info, st_other, st_shndx, strtab, name):
header = struct.pack('>IIIBBH', st_name, st_value, st_size, st_info, st_other, st_shndx)
return Symbol(header, strtab, name)
def to_bin(self):
st_info = (self.bind << 4) | self.type
return struct.pack('>IIIBBH', self.st_name, self.st_value, self.st_size, st_info, self.st_other, self.st_shndx)
@@ -185,7 +193,7 @@ class Section:
if self.sh_entsize != 0:
assert self.sh_size % self.sh_entsize == 0
if self.sh_type == SHT_NOBITS:
self.data = ''
self.data = b''
else:
self.data = data[self.sh_offset:self.sh_offset + self.sh_size]
self.index = index
@@ -466,6 +474,9 @@ class GlobalAsmBlock:
self.fail(".ascii with no string", real_line)
return ret + num_parts if z else ret
def align2(self):
while self.fn_section_sizes[self.cur_section] % 2 != 0:
self.fn_section_sizes[self.cur_section] += 1
def align4(self):
while self.fn_section_sizes[self.cur_section] % 4 != 0:
@@ -553,6 +564,9 @@ class GlobalAsmBlock:
self.add_sized(self.count_quoted_size(line, z, real_line, output_enc), real_line)
elif line.startswith('.byte'):
self.add_sized(len(line.split(',')), real_line)
elif line.startswith('.half'):
self.align2()
self.add_sized(2*len(line.split(',')), real_line)
elif line.startswith('.'):
# .macro, ...
self.fail("asm directive not supported", real_line)
@@ -708,7 +722,7 @@ float_regexpr = re.compile(r"[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f")
def repl_float_hex(m):
return str(struct.unpack(">I", struct.pack(">f", float(m.group(0).strip().rstrip("f"))))[0])
def parse_source(f, opt, framepointer, input_enc, output_enc, print_source=None):
def parse_source(f, opt, framepointer, input_enc, output_enc, out_dependencies, print_source=None):
if opt in ['O2', 'O1']:
if framepointer:
min_instr_count = 6
@@ -741,7 +755,9 @@ def parse_source(f, opt, framepointer, input_enc, output_enc, print_source=None)
global_asm = None
asm_functions = []
output_lines = []
output_lines = [
'#line 1 "' + f.name + '"'
]
is_cutscene_data = False
@@ -770,6 +786,7 @@ def parse_source(f, opt, framepointer, input_enc, output_enc, print_source=None)
elif ((line.startswith('GLOBAL_ASM("') or line.startswith('#pragma GLOBAL_ASM("'))
and line.endswith('")')):
fname = line[line.index('(') + 2 : -2]
out_dependencies.append(fname)
global_asm = GlobalAsmBlock(fname)
with open(fname, encoding=input_enc) as f:
for line2 in f:
@@ -778,16 +795,17 @@ def parse_source(f, opt, framepointer, input_enc, output_enc, print_source=None)
output_lines[-1] = ''.join(src)
asm_functions.append(fn)
global_asm = None
elif ((line.startswith('#include "')) and line.endswith('" EARLY')):
elif line.startswith('#include "') and line.endswith('" EARLY'):
# C includes qualified with EARLY (i.e. #include "file.c" EARLY) will be
# processed recursively when encountered
fpath = os.path.dirname(f.name)
fname = line[line.index(' ') + 2 : -7]
fname = os.path.join(fpath, line[line.index(' ') + 2 : -7])
out_dependencies.append(fname)
include_src = StringIO()
with open(fpath + os.path.sep + fname, encoding=input_enc) as include_file:
parse_source(include_file, opt, framepointer, input_enc, output_enc, include_src)
with open(fname, encoding=input_enc) as include_file:
parse_source(include_file, opt, framepointer, input_enc, output_enc, out_dependencies, include_src)
include_src.write('#line ' + str(line_no + 1) + ' "' + f.name + '"')
output_lines[-1] = include_src.getvalue()
include_src.write('#line ' + str(line_no) + '\n')
include_src.close()
else:
# This is a hack to replace all floating-point numbers in an array of a particular type
@@ -842,6 +860,7 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc):
# simplicity we pad with nops/.space so that addresses match exactly, so we
# don't have to fix up relocations/symbol references.
all_text_glabels = set()
func_sizes = {}
for function in functions:
ifdefed = False
for sectype, (temp_name, size) in function.data.items():
@@ -864,6 +883,8 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc):
else:
asm.append('.space {}'.format(loc - prev_loc))
to_copy[sectype].append((loc, size, temp_name, function.fn_desc))
if function.text_glabels:
func_sizes[function.text_glabels[0]] = size
prev_locs[sectype] = loc + size
if not ifdefed:
all_text_glabels.update(function.text_glabels)
@@ -907,6 +928,7 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc):
asm_objfile = ElfFile(f.read())
# Remove some clutter from objdump output
mdebug_section = objfile.find_section('.mdebug')
objfile.drop_irrelevant_sections()
# Unify reginfo sections
@@ -1008,7 +1030,7 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc):
# Move over symbols, deleting the temporary function labels.
# Sometimes this naive procedure results in duplicate symbols, or UNDEF
# symbols that are also defined the same .o file. Hopefully that's fine.
# Skip over local symbols that aren't used relocated against, to avoid
# Skip over local symbols that aren't relocated against, to avoid
# conflicts.
new_local_syms = [s for s in objfile.symtab.local_symbols() if not is_temp_name(s.name)]
new_global_syms = [s for s in objfile.symtab.global_symbols() if not is_temp_name(s.name)]
@@ -1026,6 +1048,8 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc):
# glabel's aren't marked as functions, making objdump output confusing. Fix that.
if s.name in all_text_glabels:
s.type = STT_FUNC
if s.name in func_sizes:
s.st_size = func_sizes[s.name]
if objfile.sections[s.st_shndx].name == '.rodata' and s.st_value in moved_late_rodata:
s.st_value = moved_late_rodata[s.st_value]
s.st_name += strtab_adj
@@ -1033,6 +1057,57 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc):
new_local_syms.append(s)
else:
new_global_syms.append(s)
# Add static symbols from .mdebug, so they can be referred to from GLOBAL_ASM
local_sym_replacements = {}
if mdebug_section:
strtab_index = len(objfile.symtab.strtab.data)
new_strtab_data = []
ifd_max, cb_fd_offset = struct.unpack('>II', mdebug_section.data[18*4 : 20*4])
cb_sym_offset, = struct.unpack('>I', mdebug_section.data[9*4 : 10*4])
cb_ss_offset, = struct.unpack('>I', mdebug_section.data[15*4 : 16*4])
for i in range(ifd_max):
offset = cb_fd_offset + 18*4*i
iss_base, _, isym_base, csym = struct.unpack('>IIII', objfile.data[offset + 2*4 : offset + 6*4])
for j in range(csym):
offset2 = cb_sym_offset + 12 * (isym_base + j)
iss, value, st_sc_index = struct.unpack('>III', objfile.data[offset2 : offset2 + 12])
st = (st_sc_index >> 26)
sc = (st_sc_index >> 21) & 0x1f
if st in [MIPS_DEBUG_ST_STATIC, MIPS_DEBUG_ST_STATIC_PROC]:
symbol_name_offset = cb_ss_offset + iss_base + iss
symbol_name_offset_end = objfile.data.find(b'\0', symbol_name_offset)
assert symbol_name_offset_end != -1
symbol_name = objfile.data[symbol_name_offset : symbol_name_offset_end + 1]
symbol_name_str = symbol_name[:-1].decode('latin1')
section_name = {1: '.text', 2: '.data', 3: '.bss', 15: '.rodata'}[sc]
section = objfile.find_section(section_name)
symtype = STT_FUNC if sc == 1 else STT_OBJECT
sym = Symbol.from_parts(
st_name=strtab_index,
st_value=value,
st_size=0,
st_info=(STB_LOCAL << 4 | symtype),
st_other=STV_DEFAULT,
st_shndx=section.index,
strtab=objfile.symtab.strtab,
name=symbol_name_str)
local_sym_replacements[symbol_name_str] = len(new_local_syms)
strtab_index += len(symbol_name)
new_strtab_data.append(symbol_name)
new_local_syms.append(sym)
objfile.symtab.strtab.data += b''.join(new_strtab_data)
# To get the linker to use the local symbols, we have to get rid of UNDEF
# global ones.
newer_global_syms = []
for s in new_global_syms:
if s.st_shndx == SHN_UNDEF and s.name in local_sym_replacements:
s.new_index = local_sym_replacements[s.name]
else:
newer_global_syms.append(s)
new_global_syms = newer_global_syms
new_syms = new_local_syms + new_global_syms
for i, s in enumerate(new_syms):
s.new_index = i
@@ -1095,7 +1170,7 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc):
except:
pass
def run_wrapped(argv, outfile):
def run_wrapped(argv, outfile, functions):
parser = argparse.ArgumentParser(description="Pre-process .c files and post-process .o files to enable embedding assembly into C.")
parser.add_argument('filename', help="path to .c code")
parser.add_argument('--post-process', dest='objfile', help="path to .o file to post-process")
@@ -1118,12 +1193,15 @@ def run_wrapped(argv, outfile):
if args.objfile is None:
with open(args.filename, encoding=args.input_enc) as f:
parse_source(f, opt=opt, framepointer=args.framepointer, input_enc=args.input_enc, output_enc=args.output_enc, print_source=outfile)
deps = []
functions = parse_source(f, opt=opt, framepointer=args.framepointer, input_enc=args.input_enc, output_enc=args.output_enc, out_dependencies=deps, print_source=outfile)
return functions, deps
else:
if args.assembler is None:
raise Failure("must pass assembler command")
with open(args.filename, encoding=args.input_enc) as f:
functions = parse_source(f, opt=opt, framepointer=args.framepointer, input_enc=args.input_enc, output_enc=args.output_enc)
if functions is None:
with open(args.filename, encoding=args.input_enc) as f:
functions = parse_source(f, opt=opt, framepointer=args.framepointer, input_enc=args.input_enc, out_dependencies=[], output_enc=args.output_enc)
if not functions:
return
asm_prelude = b''
@@ -1132,9 +1210,9 @@ def run_wrapped(argv, outfile):
asm_prelude = f.read()
fixup_objfile(args.objfile, functions, asm_prelude, args.assembler, args.output_enc)
def run(argv, outfile=sys.stdout.buffer):
def run(argv, outfile=sys.stdout.buffer, functions=None):
try:
run_wrapped(argv, outfile)
return run_wrapped(argv, outfile, functions)
except Failure as e:
print("Error:", e, file=sys.stderr)
sys.exit(1)
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
set -e
set -o pipefail
INPUT="$1"
OUTPUT="${INPUT%.c}.o"
CC="$QEMU_IRIX -silent -L $IRIX_ROOT $IRIX_ROOT/usr/bin/cc"
CFLAGS="-Wab,-r4300_mul -non_shared -G 0 -Xcpluscomm -fullwarn -wlint -woff 819,820,852,821 -signed -DVERSION_JP=1 -mips2" # -I include
AS="mips-linux-gnu-as"
ASFLAGS="-march=vr4300 -mabi=32 --defsym VERSION_JP=1" # -I include
set +e
OPTFLAGS=$(grep '^// COMPILE-FLAGS: ' $INPUT | sed 's#^// COMPILE-FLAGS: ##')
set -e
if [[ -z "$OPTFLAGS" ]]; then
OPTFLAGS="-g"
fi
python3 asm_processor.py "$OPTFLAGS" "$INPUT" | $CC -c $CFLAGS include-stdin.c -o "$OUTPUT" "$OPTFLAGS"
python3 asm_processor.py "$OPTFLAGS" "$INPUT" --post-process "$OUTPUT" --assembler "$AS $ASFLAGS" --asm-prelude prelude.s
+2
View File
@@ -0,0 +1,2 @@
// (this is used for piping input to the IRIX compiler without needing to make a temporary .c file)
#include "/dev/stdin"
+8
View File
@@ -0,0 +1,8 @@
.set noat
.set noreorder
.set gp=64
.macro glabel label
.global \label
\label:
.endm