diff options
author | Treeki <treeki@gmail.com> | 2012-03-27 21:38:52 +0200 |
---|---|---|
committer | Treeki <treeki@gmail.com> | 2012-03-27 21:38:52 +0200 |
commit | 5e8e92cd8f403cbfebc4469a1aee252212e42045 (patch) | |
tree | 316022f62e20bbb066550ab541dfb7290d8ca6e5 | |
parent | e12b1713576544fdda756a3ca8831642562ea921 (diff) | |
download | kamek-5e8e92cd8f403cbfebc4469a1aee252212e42045.tar.gz kamek-5e8e92cd8f403cbfebc4469a1aee252212e42045.zip |
Kamek/Newer now support dynamic linking
Diffstat (limited to '')
-rwxr-xr-x | hacksToDropbox | 11 | ||||
-rwxr-xr-x | hacksToDropboxKP | 11 | ||||
-rw-r--r-- | kamek_configs.yaml | 3 | ||||
-rw-r--r-- | kamek_pal.x | 6 | ||||
-rwxr-xr-x | makeNewer | 4 | ||||
-rwxr-xr-x | makeNewerAll | 6 | ||||
-rwxr-xr-x | makeNewerKP | 4 | ||||
-rwxr-xr-x | makeNewerKPAll | 6 | ||||
-rw-r--r-- | src/koopatlas/core.cpp | 1 | ||||
-rw-r--r-- | src/prolog.S | 2 | ||||
-rw-r--r-- | tools/dumprelocs.py | 19 | ||||
-rwxr-xr-x | tools/hooks.py | 73 | ||||
-rw-r--r-- | tools/kamek.py | 135 |
13 files changed, 220 insertions, 61 deletions
diff --git a/hacksToDropbox b/hacksToDropbox new file mode 100755 index 0000000..5077946 --- /dev/null +++ b/hacksToDropbox @@ -0,0 +1,11 @@ +path=/home/me/Dropbox/NEWERsmbw/Test\ Pack/NewerTestPack/SysSelect +cp NewerASM/pal_loader.bin "$path/SystemEU_1.bin" +cp NewerASM/pal_dlcode.bin "$path/DLCodeEU_1.bin" +cp NewerASM/pal_dlrelocs.bin "$path/DLRelocsEU_1.bin" +cp NewerASM/ntsc_loader.bin "$path/SystemUS_1.bin" +cp NewerASM/ntsc_dlcode.bin "$path/DLCodeUS_1.bin" +cp NewerASM/ntsc_dlrelocs.bin "$path/DLRelocsUS_1.bin" +cp NewerASM/ntsc2_loader.bin "$path/SystemUS_2.bin" +cp NewerASM/ntsc2_dlcode.bin "$path/DLCodeUS_2.bin" +cp NewerASM/ntsc2_dlrelocs.bin "$path/DLRelocsUS_2.bin" + diff --git a/hacksToDropboxKP b/hacksToDropboxKP new file mode 100755 index 0000000..419de5b --- /dev/null +++ b/hacksToDropboxKP @@ -0,0 +1,11 @@ +path=/home/me/Dropbox/NEWERsmbw/Test\ Pack/NewerTestPack/SysMap +cp NewerASM/pal_loader.bin "$path/SystemEU_1.bin" +cp NewerASM/pal_dlcode.bin "$path/DLCodeEU_1.bin" +cp NewerASM/pal_dlrelocs.bin "$path/DLRelocsEU_1.bin" +cp NewerASM/ntsc_loader.bin "$path/SystemUS_1.bin" +cp NewerASM/ntsc_dlcode.bin "$path/DLCodeUS_1.bin" +cp NewerASM/ntsc_dlrelocs.bin "$path/DLRelocsUS_1.bin" +cp NewerASM/ntsc2_loader.bin "$path/SystemUS_2.bin" +cp NewerASM/ntsc2_dlcode.bin "$path/DLCodeUS_2.bin" +cp NewerASM/ntsc2_dlrelocs.bin "$path/DLRelocsUS_2.bin" + diff --git a/kamek_configs.yaml b/kamek_configs.yaml index 06dd6c3..a65f321 100644 --- a/kamek_configs.yaml +++ b/kamek_configs.yaml @@ -4,6 +4,7 @@ defines: [REGION_PAL, VERSION_1]
include_dirs: ['include', 'src']
linker_script: kamek_pal.x
+ dynamic_link: true
rel_area_start: 0x807684C0
rel_area_end: 0x80B75CA8
@@ -12,6 +13,7 @@ defines: [REGION_NTSC, VERSION_1]
include_dirs: ['include', 'src']
linker_script: kamek_ntsc.x
+ dynamic_link: true
rel_area_start: 0x807684C0
rel_area_end: 0x80B8E33C
@@ -20,6 +22,7 @@ defines: [REGION_NTSC, VERSION_2]
include_dirs: ['include', 'src']
linker_script: kamek_ntsc2.x
+ dynamic_link: true
rel_area_start: 0x807684C0
rel_area_end: 0x80B8E33C
diff --git a/kamek_pal.x b/kamek_pal.x index 9839dec..9447514 100644 --- a/kamek_pal.x +++ b/kamek_pal.x @@ -1,9 +1,3 @@ -OUTPUT_FORMAT ("binary") - -/*MEMORY { - loader_section : ORIGIN = 0x80001800, LENGTH = 0x1800 -}*/ - SECTIONS { /* Scrolling is annoying, clown car goes here! */ @@ -8,7 +8,7 @@ else fi cp NewerASM/pal_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemEU_1.bin -cp NewerASM/ntsc_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_1.bin -cp NewerASM/ntsc2_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_2.bin +cp NewerASM/pal_dlcode.bin ~/Games/Newer/DolphinPatch/NewerRes/DLCodeEU_1.bin +cp NewerASM/pal_dlrelocs.bin ~/Games/Newer/DolphinPatch/NewerRes/DLRelocsEU_1.bin echo Built PAL! diff --git a/makeNewerAll b/makeNewerAll index ec5fc35..cceea26 100755 --- a/makeNewerAll +++ b/makeNewerAll @@ -8,7 +8,13 @@ else fi cp NewerASM/pal_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemEU_1.bin +cp NewerASM/pal_dlcode.bin ~/Games/Newer/DolphinPatch/NewerRes/DLCodeEU_1.bin +cp NewerASM/pal_dlrelocs.bin ~/Games/Newer/DolphinPatch/NewerRes/DLRelocsEU_1.bin cp NewerASM/ntsc_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_1.bin +cp NewerASM/ntsc_dlcode.bin ~/Games/Newer/DolphinPatch/NewerRes/DLCodeUS_1.bin +cp NewerASM/ntsc_dlrelocs.bin ~/Games/Newer/DolphinPatch/NewerRes/DLRelocsUS_1.bin cp NewerASM/ntsc2_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_2.bin +cp NewerASM/ntsc2_dlcode.bin ~/Games/Newer/DolphinPatch/NewerRes/DLCodeUS_2.bin +cp NewerASM/ntsc2_dlrelocs.bin ~/Games/Newer/DolphinPatch/NewerRes/DLRelocsUS_2.bin echo Built all! diff --git a/makeNewerKP b/makeNewerKP index 21f6db8..36cb034 100755 --- a/makeNewerKP +++ b/makeNewerKP @@ -8,7 +8,7 @@ else fi cp NewerASM/pal_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemEU_1.bin -cp NewerASM/ntsc_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_1.bin -cp NewerASM/ntsc2_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_2.bin +cp NewerASM/pal_dlcode.bin ~/Games/Newer/DolphinPatch/NewerRes/DLCodeEU_1.bin +cp NewerASM/pal_dlrelocs.bin ~/Games/Newer/DolphinPatch/NewerRes/DLRelocsEU_1.bin echo Built PAL! diff --git a/makeNewerKPAll b/makeNewerKPAll index 065735f..7d10af6 100755 --- a/makeNewerKPAll +++ b/makeNewerKPAll @@ -8,7 +8,13 @@ else fi cp NewerASM/pal_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemEU_1.bin +cp NewerASM/pal_dlcode.bin ~/Games/Newer/DolphinPatch/NewerRes/DLCodeEU_1.bin +cp NewerASM/pal_dlrelocs.bin ~/Games/Newer/DolphinPatch/NewerRes/DLRelocsEU_1.bin cp NewerASM/ntsc_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_1.bin +cp NewerASM/ntsc_dlcode.bin ~/Games/Newer/DolphinPatch/NewerRes/DLCodeUS_1.bin +cp NewerASM/ntsc_dlrelocs.bin ~/Games/Newer/DolphinPatch/NewerRes/DLRelocsUS_1.bin cp NewerASM/ntsc2_loader.bin ~/Games/Newer/DolphinPatch/NewerRes/SystemUS_2.bin +cp NewerASM/ntsc2_dlcode.bin ~/Games/Newer/DolphinPatch/NewerRes/DLCodeUS_2.bin +cp NewerASM/ntsc2_dlrelocs.bin ~/Games/Newer/DolphinPatch/NewerRes/DLRelocsUS_2.bin echo Built all! diff --git a/src/koopatlas/core.cpp b/src/koopatlas/core.cpp index f7acf00..de06453 100644 --- a/src/koopatlas/core.cpp +++ b/src/koopatlas/core.cpp @@ -175,6 +175,7 @@ bool WMInit_LoadResources2(void *ptr) { wm->mapPath = wm->getMapNameForIndex(wm->currentMapID); if (wm->mapPath == 0) wm->mapPath = wm->getMapNameForIndex(0); + OSReport("Load map: %s\n", wm->mapPath); } return wm->mapData.load(wm->mapPath); diff --git a/src/prolog.S b/src/prolog.S index 38bcb6b..e86bfa3 100644 --- a/src/prolog.S +++ b/src/prolog.S @@ -61,7 +61,7 @@ startLoop: .data PMsg: - .string "Newer Super Mario Bros. Wii - Hacks by Treeki and Tempus 2009-2011\n.ctors: %p - %p\n" + .string "Newer Super Mario Bros. Wii - Hacks by Treeki and Tempus 2009-2012\n.ctors: %p - %p\n" PMsg2: .string "%d inits called\n" diff --git a/tools/dumprelocs.py b/tools/dumprelocs.py new file mode 100644 index 0000000..d5773e3 --- /dev/null +++ b/tools/dumprelocs.py @@ -0,0 +1,19 @@ +import struct +up = struct.Struct('>II').unpack +u32 = struct.Struct('>I').unpack + +data = open('NewerASM/pal_dlrelocs.bin', 'rb').read() +addr_offset = struct.unpack('>xxxxxxxxI', data[0:0xC])[0] - 0xC +data = data[0xC:] + +reloc_count = addr_offset / 8 + +for i in xrange(reloc_count): + entry = up(data[i*8:i*8+8]) + reltype = entry[0] >> 24 + addr_id = entry[0] & 0xFFFFFF + offset = entry[1] + + offs = addr_offset+(addr_id*4) + print "%2d: %08x => %08x" % (reltype, offset, u32(data[offs:offs+4])[0]) + diff --git a/tools/hooks.py b/tools/hooks.py index 13c4e19..388efcb 100755 --- a/tools/hooks.py +++ b/tools/hooks.py @@ -3,14 +3,18 @@ import struct u32 = struct.Struct('>I')
+BRANCH_TYPES = ['b', 'bl', 'ba', 'bla']
def make_branch_insn(fromAddr, toAddr, branchType):
- branchTypes = ['b', 'bl', 'ba', 'bla']
- if branchType not in branchTypes:
+ if branchType not in BRANCH_TYPES:
raise ValueError, 'invalid branch type: %s' % branchType
- extra = branchTypes.index(branchType)
+ extra = BRANCH_TYPES.index(branchType)
- distance = toAddr - fromAddr
+ if toAddr == -1:
+ distance = 0 # placeholder, will be added later by relocs
+ else:
+ distance = toAddr - fromAddr
+
if distance >= 0x2000000 or distance <= -0x2000000:
raise ValueError, 'branching too far: %08x to %08x' % (fromAddr, toAddr)
@@ -44,7 +48,7 @@ class Hook(object): self.context.hooks.append(self)
# validate the hook's data
- current_config_name = builder._config_short_name
+ current_config_name = builder.config_short_name
for field in self.required_data:
field = field.replace('%CONFIG%', current_config_name)
@@ -65,7 +69,7 @@ class BasicPatchHook(Hook): Hook.__init__(self, builder, module, data)
def create_patches(self):
- addr = self.data['addr_%s' % self.builder._config_short_name]
+ addr = self.data['addr_%s' % self.builder.config_short_name]
hex_data = self.data['data']
@@ -75,7 +79,7 @@ class BasicPatchHook(Hook): patch = binascii.unhexlify(hex_data)
- self.builder._add_patch(addr, patch)
+ self.builder.add_patch(addr, patch)
@@ -91,19 +95,23 @@ class BranchInsnHook(Hook): try:
target_func = self.data['target_func']
except KeyError:
- target_func = self.data['target_func_%s' % self.builder._config_short_name]
-
- if isinstance(target_func, str):
- target_func = self.builder._find_func_by_symbol(target_func)
+ target_func = self.data['target_func_%s' % self.builder.config_short_name]
+
+ src_addr = self.data['src_addr_%s' % self.builder.config_short_name]
+ is_symbol_name = isinstance(target_func, str)
+
+ if is_symbol_name:
+ target_func = self.builder.find_func_by_symbol(target_func)
+
+ if is_symbol_name and self.builder.dynamic_link:
+ branch_insn = make_branch_insn(src_addr, -1, self.data['branch_type'])
+ self.builder.add_patch(src_addr, u32.pack(branch_insn))
+
+ dylink = self.builder.dynamic_link
+ dylink.add_reloc(dylink.R_PPC_REL24, src_addr, target_func)
else:
- # assume it's an address
- pass
-
-
- src_addr = self.data['src_addr_%s' % self.builder._config_short_name]
- branch_insn = make_branch_insn(src_addr, target_func, self.data['branch_type'])
-
- self.builder._add_patch(src_addr, u32.pack(branch_insn))
+ branch_insn = make_branch_insn(src_addr, target_func, self.data['branch_type'])
+ self.builder.add_patch(src_addr, u32.pack(branch_insn))
@@ -119,18 +127,19 @@ class AddFunctionPointerHook(Hook): try:
target_func = self.data['target_func']
except KeyError:
- target_func = self.data['target_func_%s' % self.builder._config_short_name]
-
- if isinstance(target_func, str):
- target_func = self.builder._find_func_by_symbol(target_func)
+ target_func = self.data['target_func_%s' % self.builder.config_short_name]
+
+ src_addr = self.data['src_addr_%s' % self.builder.config_short_name]
+ is_symbol_name = isinstance(target_func, str)
+
+ if is_symbol_name:
+ target_func = self.builder.find_func_by_symbol(target_func)
+
+ if is_symbol_name and self.builder.dynamic_link:
+ dylink = self.builder.dynamic_link
+ dylink.add_reloc(dylink.R_PPC_ADDR32, src_addr, target_func)
else:
- # assume it's an address
- pass
-
-
- src_addr = self.data['src_addr_%s' % self.builder._config_short_name]
-
- self.builder._add_patch(src_addr, u32.pack(target_func))
+ self.builder.add_patch(src_addr, u32.pack(target_func))
@@ -143,7 +152,7 @@ class NopInsnHook(Hook): Hook.__init__(self, builder, module, data)
def create_patches(self):
- area = self.data['area_%s' % self.builder._config_short_name]
+ area = self.data['area_%s' % self.builder.config_short_name]
if isinstance(area, list):
addr, end = area
@@ -153,7 +162,7 @@ class NopInsnHook(Hook): addr = area
nop_patch = '\x60\x00\x00\x00'
- self.builder._add_patch(addr, nop_patch)
+ self.builder.add_patch(addr, nop_patch)
diff --git a/tools/kamek.py b/tools/kamek.py index 97b02cf..43b4556 100644 --- a/tools/kamek.py +++ b/tools/kamek.py @@ -1,12 +1,12 @@ #!/usr/bin/env python # Kamek - build tool for custom C++ code in New Super Mario Bros. Wii -# All rights reserved (c) Treeki 2010 -# Some function definitions by megazig +# All rights reserved (c) Treeki 2010 - 2012 +# Header files compiled by Treeki, Tempus and megazig -# Requires PyYAML +# Requires PyYAML and pyelftools -version_str = 'Kamek 0.1 by Treeki' +version_str = 'Kamek 0.2 by Treeki' import binascii import os @@ -18,6 +18,8 @@ import sys import tempfile import yaml +import elftools.elf.elffile + import hooks u32 = struct.Struct('>I') @@ -151,6 +153,78 @@ def generate_kamek_patches(patchlist): return kamekpatch +class DyLinkCreator(object): + R_PPC_ADDR32 = 1 + R_PPC_ADDR16_LO = 4 + R_PPC_ADDR16_HI = 5 + R_PPC_ADDR16_HA = 6 + R_PPC_REL24 = 10 + + VALID_RELOCS = set([1, 4, 5, 6, 10]) + + def __init__(self): + self._relocs = [] + + self._targets = [] + self._target_lookups = {} + + self.elf = None + + def set_elf(self, stream): + if self.elf != None: + raise ValueError('ELF already set') + + self.elf = elftools.elf.elffile.ELFFile(stream) + self.code = self.elf.get_section_by_name('.text').data() + + self._add_relocs(self.elf.get_section_by_name('.rela.text')) + + def _add_relocs(self, section): + sym_values = {} + sym_section = self.elf.get_section_by_name('.symtab') + + for reloc in section.iter_relocations(): + entry = reloc.entry + #print entry + + sym_id = entry['r_info_sym'] + try: + sym_value = sym_values[sym_id] + except KeyError: + sym = sym_section.get_symbol(sym_id) + sym_value = sym.entry['st_value'] + sym_values[sym_id] = sym_value + #print hex(sym_value) + + self.add_reloc(entry['r_info_type'], entry['r_offset'], sym_value+entry['r_addend']) + + def add_reloc(self, reltype, addr, target): + if reltype not in self.VALID_RELOCS: + raise ValueError('Unknown/unsupported rel type: %d (%x => %x)' % (reltype, addr, target)) + + try: + target_id = self._target_lookups[target] + except KeyError: + target_id = len(self._targets) + self._target_lookups[target] = target_id + self._targets.append(target) + + self._relocs.append((reltype, addr, target_id)) + + def build_reloc_data(self): + header_struct = struct.Struct('>8sI') + + rel_struct_pack = struct.Struct('>II').pack + target_struct_pack = struct.Struct('>I').pack + + rel_data = map(lambda x: rel_struct_pack((x[0] << 24) | x[2], x[1]), self._relocs) + target_data = map(target_struct_pack, self._targets) + + header = header_struct.pack('NewerREL', 12 + (len(self._relocs) * 8)) + + return header + ''.join(rel_data) + ''.join(target_data) + + class KamekModule(object): _requiredFields = ['source_files'] @@ -195,6 +269,11 @@ class KamekBuilder(object): self._configTempDir = tempfile.mkdtemp() print_debug('Temp files for this configuration are in: '+self._configTempDir) + + if 'dynamic_link' in self._config and self._config['dynamic_link']: + self.dynamic_link = DyLinkCreator() + else: + self.dynamic_link = None self._builtCodeAddr = 0x80001800 if 'code_address' in self.project.data: @@ -214,6 +293,9 @@ class KamekBuilder(object): self._compile_modules() self._link() self._read_symbol_map() + + if self.dynamic_link: + self.dynamic_link.set_elf(open(self._outFile, 'rb')) for hook in self._hooks: hook.create_patches() @@ -238,7 +320,7 @@ class KamekBuilder(object): print_debug('---') print_debug('Building for configuration: '+config['friendly_name']) - self._config_short_name = config['short_name'] + self.config_short_name = config['short_name'] self._rel_area = (config['rel_area_start'], config['rel_area_end']) @@ -338,14 +420,20 @@ class KamekBuilder(object): print_debug('---') print_debug('Linking project') - self._mapFile = '%s/%s_linkmap.map' % (self._outDir, self._config_short_name) - self._outFile = '%s/%s_out.bin' % (self._outDir, self._config_short_name) + self._mapFile = '%s/%s_linkmap.map' % (self._outDir, self.config_short_name) + outname = 'object.plf' if self.dynamic_link else 'object.bin' + self._outFile = '%s/%s_%s' % (self._outDir, self.config_short_name, outname) ld_command = ['%s%s-ld' % (gcc_path, gcc_type), '-L.'] ld_command.append('-o') ld_command.append(self._outFile) - ld_command.append('-Ttext') - ld_command.append('0x%08X' % self._builtCodeAddr) + if self.dynamic_link: + ld_command.append('-r') + ld_command.append('--oformat=elf32-powerpc') + else: + ld_command.append('--oformat=binary') + ld_command.append('-Ttext') + ld_command.append('0x%08X' % self._builtCodeAddr) ld_command.append('-T') ld_command.append(self._config['linker_script']) ld_command.append('-Map') @@ -429,7 +517,7 @@ class KamekBuilder(object): print_debug('Generated code is at 0x%08X .. 0x%08X' % (self._codeStart, self._codeEnd - 4)) - def _find_func_by_symbol(self, find_symbol): + def find_func_by_symbol(self, find_symbol): for sym in self._symbols: #if show_cmd: # out = "0x%08x - %s - %s" % (sym[0], sym[1], sym[2]) @@ -440,7 +528,7 @@ class KamekBuilder(object): raise ValueError, 'Cannot find function: %s' % find_symbol - def _add_patch(self, offset, data): + def add_patch(self, offset, data): if offset >= self._rel_area[0] and offset <= self._rel_area[1] and use_rels: self._rel_patches.append((offset, data)) else: @@ -457,13 +545,24 @@ class KamekBuilder(object): #self._patches.append((0x817F4800, kamekpatch)) self._patches.append((0x80002F60, kamekpatch)) - # add the outfile as a patch - file = open(self._outFile, 'rb') - patch = (self._codeStart, file.read()) - file.close() - - self._patches.append(patch) - + if self.dynamic_link: + # put together the dynamic link files + dlcode = open('%s/%s_dlcode.bin' % (self._outDir, self._config['short_name']), 'wb') + dlcode.write(self.dynamic_link.code) + dlcode.close() + + dlrelocs = open('%s/%s_dlrelocs.bin' % (self._outDir, self._config['short_name']), 'wb') + dlrelocs.write(self.dynamic_link.build_reloc_data()) + dlrelocs.close() + + else: + # add the outfile as a patch if not using dynamic linking + file = open(self._outFile, 'rb') + patch = (self._codeStart, file.read()) + file.close() + + self._patches.append(patch) + # generate a Riivolution patch riiv = open('%s/%s_riiv.xml' % (self._outDir, self._config['short_name']), 'w') for patch in self._patches: |