Merge pull request #92 from DavidSM64/dkr_rodata

Moved .rodata in unknown_001050 from asm to C.
This commit is contained in:
David Benepe
2021-05-29 15:58:15 -05:00
committed by GitHub
7 changed files with 141 additions and 53 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
+5
View File
@@ -39,4 +39,9 @@ typedef s32 ptrdiff_t;
//#include <stddef.h>
//#endif
// Temporary until all the appropriate functions are decompiled.
typedef struct FloatLiteral {
float floatLiteral;
} FloatLiteral;
#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;
// Unused 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));
}
+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