summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2011-03-12 23:17:12 +0100
committerTreeki <treeki@gmail.com>2011-03-12 23:17:12 +0100
commit7d4e4c0b34a613dd3c0220475ae4e448197522c1 (patch)
tree4f5cee367de3fdef4f9a7c84af59ffe76a2bb1c3 /tools
downloadkamek-7d4e4c0b34a613dd3c0220475ae4e448197522c1.tar.gz
kamek-7d4e4c0b34a613dd3c0220475ae4e448197522c1.zip
initial commit. now I can start playing with stuff!
Diffstat (limited to 'tools')
-rw-r--r--tools/__pycache__/mapfile_tool.cpython-32.pycbin0 -> 6461 bytes
-rwxr-xr-xtools/hooks.py166
-rw-r--r--tools/hooks.pycbin0 -> 5873 bytes
-rw-r--r--tools/kamek.py548
-rw-r--r--tools/license.dat23
-rw-r--r--tools/lmgr11.dllbin0 -> 1490944 bytes
-rwxr-xr-xtools/mapfile_tool.py273
-rw-r--r--tools/mapfile_tool.pycbin0 -> 5950 bytes
-rw-r--r--tools/mwasmeppc.exebin0 -> 1086812 bytes
-rw-r--r--tools/mwcceppc.exebin0 -> 4324912 bytes
-rw-r--r--tools/mwcceppc.idbbin0 -> 40820897 bytes
-rw-r--r--tools/mwldeppc.exebin0 -> 1177600 bytes
12 files changed, 1010 insertions, 0 deletions
diff --git a/tools/__pycache__/mapfile_tool.cpython-32.pyc b/tools/__pycache__/mapfile_tool.cpython-32.pyc
new file mode 100644
index 0000000..1271b22
--- /dev/null
+++ b/tools/__pycache__/mapfile_tool.cpython-32.pyc
Binary files differ
diff --git a/tools/hooks.py b/tools/hooks.py
new file mode 100755
index 0000000..13c4e19
--- /dev/null
+++ b/tools/hooks.py
@@ -0,0 +1,166 @@
+import binascii
+import struct
+
+u32 = struct.Struct('>I')
+
+def make_branch_insn(fromAddr, toAddr, branchType):
+ branchTypes = ['b', 'bl', 'ba', 'bla']
+ if branchType not in branchTypes:
+ raise ValueError, 'invalid branch type: %s' % branchType
+
+ extra = branchTypes.index(branchType)
+
+ distance = toAddr - fromAddr
+ if distance >= 0x2000000 or distance <= -0x2000000:
+ raise ValueError, 'branching too far: %08x to %08x' % (fromAddr, toAddr)
+
+ return (distance & 0x3FFFFFC) | 0x48000000 | extra
+
+
+
+class HookContext(object):
+ """Object which can be used by each hook type to hold data."""
+
+ def __init__(self):
+ self.hooks = []
+
+
+
+class Hook(object):
+ """Generic hook class"""
+
+ has_context = False
+ required_data = []
+
+ def __init__(self, builder, module, data):
+ """Sets up a hook"""
+ self.builder = builder
+ self.module = module
+ self.data = data
+
+ if self.has_context:
+ hookType = type(self)
+ self.context = builder._hook_contexts[hookType]
+ self.context.hooks.append(self)
+
+ # validate the hook's data
+ current_config_name = builder._config_short_name
+
+ for field in self.required_data:
+ field = field.replace('%CONFIG%', current_config_name)
+ if field not in data:
+ raise ValueError, 'hook %s : %s is missing the field %s' % (module.moduleName, data['name'], field)
+
+ def create_patches(self):
+ pass
+
+
+
+class BasicPatchHook(Hook):
+ """Hook that simply patches data to an address"""
+
+ required_data = ['addr_%CONFIG%', 'data']
+
+ def __init__(self, builder, module, data):
+ Hook.__init__(self, builder, module, data)
+
+ def create_patches(self):
+ addr = self.data['addr_%s' % self.builder._config_short_name]
+
+ hex_data = self.data['data']
+
+ whitespace = ' \n\r\t'
+ for char in whitespace:
+ hex_data = hex_data.replace(char, '')
+
+ patch = binascii.unhexlify(hex_data)
+
+ self.builder._add_patch(addr, patch)
+
+
+
+class BranchInsnHook(Hook):
+ """Hook that replaces the instruction at a specific address with a branch"""
+
+ required_data = ['branch_type', 'src_addr_%CONFIG%']
+
+ def __init__(self, builder, module, data):
+ Hook.__init__(self, builder, module, data)
+
+ def create_patches(self):
+ 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)
+ 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))
+
+
+
+class AddFunctionPointerHook(Hook):
+ """Hook that places a function pointer at an address"""
+
+ required_data = ['src_addr_%CONFIG%']
+
+ def __init__(self, builder, module, data):
+ Hook.__init__(self, builder, module, data)
+
+ def create_patches(self):
+ 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)
+ 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))
+
+
+
+class NopInsnHook(Hook):
+ """Hook that NOPs out the instruction(s) at an address"""
+
+ required_data = ['area_%CONFIG%']
+
+ def __init__(self, builder, module, data):
+ Hook.__init__(self, builder, module, data)
+
+ def create_patches(self):
+ area = self.data['area_%s' % self.builder._config_short_name]
+
+ if isinstance(area, list):
+ addr, end = area
+ count = (end + 4 - addr) / 4
+ nop_patch = '\x60\x00\x00\x00' * count
+ else:
+ addr = area
+ nop_patch = '\x60\x00\x00\x00'
+
+ self.builder._add_patch(addr, nop_patch)
+
+
+
+HookTypes = {
+ 'patch': BasicPatchHook,
+ 'branch_insn': BranchInsnHook,
+ 'add_func_pointer': AddFunctionPointerHook,
+ 'nop_insn': NopInsnHook,
+}
+
diff --git a/tools/hooks.pyc b/tools/hooks.pyc
new file mode 100644
index 0000000..bd0194d
--- /dev/null
+++ b/tools/hooks.pyc
Binary files differ
diff --git a/tools/kamek.py b/tools/kamek.py
new file mode 100644
index 0000000..f67f049
--- /dev/null
+++ b/tools/kamek.py
@@ -0,0 +1,548 @@
+#!/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
+
+# Requires PyYAML
+
+version_str = 'Kamek 0.1 by Treeki'
+
+import binascii
+import os
+import os.path
+import shutil
+import struct
+import subprocess
+import sys
+import tempfile
+import yaml
+
+import hooks
+
+u32 = struct.Struct('>I')
+
+verbose = True
+use_rels = True
+use_mw = False
+use_wine = False
+mw_path = ''
+gcc_path = ''
+gcc_type = 'powerpc-eabi'
+show_cmd = False
+delete_temp = True
+override_config_file = None
+only_build = None
+
+
+def parse_cmd_options():
+ global use_rels, use_mw, use_wine, show_cmd, delete_temp, only_build
+ global override_config_file, gcc_type, gcc_path, mw_path
+
+ if '--no-rels' in sys.argv:
+ use_rels = False
+
+ if '--use-mw' in sys.argv:
+ use_mw = True
+
+ if '--use-wine' in sys.argv:
+ use_wine = True
+
+ if '--show-cmd' in sys.argv:
+ show_cmd = True
+
+ if '--keep-temp' in sys.argv:
+ delete_temp = False
+
+
+
+ only_build = []
+
+ for arg in sys.argv:
+ if arg.startswith('--configs='):
+ override_config_file = arg[10:]
+
+ if arg.startswith('--build='):
+ only_build.append(arg[8:])
+
+ if arg.startswith('--gcc-type='):
+ gcc_type = arg[11:]
+
+ if arg.startswith('--gcc-path='):
+ gcc_path = arg[11:] + '/'
+
+ if arg.startswith('--mw-path='):
+ mw_path = arg[10:] + '/'
+
+ if len(only_build) == 0:
+ only_build = None
+
+
+def print_debug(s):
+ if verbose: print '* '+str(s)
+
+
+def read_configs(filename):
+ with open(filename, 'r') as f:
+ data = f.read()
+
+ return yaml.safe_load(data)
+
+
+current_unique_id = 0
+def generate_unique_id():
+ # this is used for temporary filenames, to ensure that .o files
+ # do not overwrite each other
+ global current_unique_id
+ current_unique_id += 1
+ return current_unique_id
+
+
+def align_addr_up(addr, align):
+ align -= 1
+ return (addr + align) & ~align
+
+
+def generate_riiv_mempatch(offset, data):
+ return '<memory offset="0x%08X" value="%s" />' % (offset, binascii.hexlify(data))
+
+
+def generate_ocarina_patch(destOffset, data):
+ out = []
+ count = len(data)
+
+ sourceOffset = 0
+ destOffset -= 0x80000000
+ for i in xrange(count >> 2):
+ out.append('%08X %s' % (destOffset | 0x4000000, binascii.hexlify(data[sourceOffset:sourceOffset+4])))
+ sourceOffset += 4
+ destOffset += 4
+
+ # take care
+ remainder = count % 4
+ if remainder == 3:
+ out.append('%08X 0000%s' % (destOffset | 0x2000000, binascii.hexlify(data[sourceOffset:sourceOffset+2])))
+ out.append('%08X 000000%s' % (destOffset, binascii.hexlify(data[sourceOffset+2])))
+ elif remainder == 2:
+ out.append('%08X 0000%s' % (destOffset | 0x2000000, binascii.hexlify(data[sourceOffset:sourceOffset+2])))
+ elif remainder == 1:
+ out.append('%08X 000000%s' % (destOffset, binascii.hexlify(data[sourceOffset])))
+
+ return '\n'.join(out)
+
+
+def generate_kamek_patches(patchlist):
+ kamekpatch = ''
+ for patch in patchlist:
+ if len(patch[1]) > 4:
+ # block patch
+ kamekpatch += u32.pack(align_addr_up(len(patch[1]), 4) / 4)
+ kamekpatch += u32.pack(patch[0])
+ kamekpatch += patch[1]
+ # align it
+ if len(patch[1]) % 4 != 0:
+ kamekpatch += '\0' * (4 - (len(patch[1]) % 4))
+ else:
+ # single patch
+ kamekpatch += u32.pack(patch[0])
+ kamekpatch += patch[1]
+
+ kamekpatch += u32.pack(0xFFFFFFFF)
+ return kamekpatch
+
+
+
+class KamekModule(object):
+ _requiredFields = ['source_files']
+
+
+ def __init__(self, filename):
+ # load the module data
+ self.modulePath = os.path.normpath(filename)
+ self.moduleName = os.path.basename(self.modulePath)
+ self.moduleDir = os.path.dirname(self.modulePath)
+
+ with open(self.modulePath, 'r') as f:
+ self.rawData = f.read()
+
+ self.data = yaml.safe_load(self.rawData)
+ if not isinstance(self.data, dict):
+ raise ValueError, 'the module file %s is an invalid format (it should be a YAML mapping)' % self.moduleName
+
+ # verify it
+ for field in self._requiredFields:
+ if field not in self.data:
+ raise ValueError, 'Missing field in the module file %s: %s' % (self.moduleName, field)
+
+
+
+class KamekBuilder(object):
+ def __init__(self, project, configs):
+ self.project = project
+ self.configs = configs
+
+
+ def build(self):
+ print_debug('Starting build')
+
+ self._prepare_dirs()
+
+ for config in self.configs:
+ if only_build != None and config['short_name'] not in only_build:
+ continue
+
+ self._set_config(config)
+
+ self._configTempDir = tempfile.mkdtemp()
+ print_debug('Temp files for this configuration are in: '+self._configTempDir)
+
+ self._builtCodeAddr = 0x80001800
+ if 'code_address' in self.project.data:
+ self._builtCodeAddr = self.project.data['code_address']
+
+ self._patches = []
+ self._rel_patches = []
+ self._hooks = []
+
+ # hook setup
+ self._hook_contexts = {}
+ for name, hookType in hooks.HookTypes.iteritems():
+ if hookType.has_context:
+ self._hook_contexts[hookType] = hookType.context_type()
+
+ self._create_hooks()
+ self._compile_modules()
+ self._link()
+ self._read_symbol_map()
+
+ for hook in self._hooks:
+ hook.create_patches()
+
+ self._create_patch()
+
+ if delete_temp:
+ shutil.rmtree(self._configTempDir)
+
+
+ def _prepare_dirs(self):
+ self._outDir = self.project.makeRelativePath(self.project.data['output_dir'])
+ print_debug('Project will be built in: '+self._outDir)
+
+ if not os.path.isdir(self._outDir):
+ os.makedirs(self._outDir)
+ print_debug('Created that directory')
+
+
+ def _set_config(self, config):
+ self._config = config
+ print_debug('---')
+ print_debug('Building for configuration: '+config['friendly_name'])
+
+ self._config_short_name = config['short_name']
+ self._rel_area = (config['rel_area_start'], config['rel_area_end'])
+
+
+ def _create_hooks(self):
+ print_debug('---')
+ print_debug('Creating hooks')
+
+ for m in self.project.modules:
+ if 'hooks' in m.data:
+ for hookData in m.data['hooks']:
+ assert 'name' in hookData and 'type' in hookData
+
+ print_debug('Hook: %s : %s' % (m.moduleName, hookData['name']))
+
+ if hookData['type'] in hooks.HookTypes:
+ hookType = hooks.HookTypes[hookData['type']]
+ hook = hookType(self, m, hookData)
+ self._hooks.append(hook)
+ else:
+ raise ValueError, 'Unknown hook type: %s' % hookData['type']
+
+
+ def _compile_modules(self):
+ print_debug('---')
+ print_debug('Compiling modules')
+
+ if use_mw:
+ # metrowerks setup
+ cc_command = ['%smwcceppc.exe' % mw_path, '-I.', '-I-', '-I.', '-nostdinc', '-Cpp_exceptions', 'off', '-Os', '-proc', 'gekko', '-fp', 'hard', '-enum', 'int', '-sdata', '0', '-sdata2', '0', '-g']
+ as_command = ['%smwasmeppc.exe' % mw_path, '-I.', '-I-', '-I.', '-nostdinc', '-proc', 'gekko', '-d', '__MWERKS__']
+
+ for d in self._config['defines']:
+ cc_command.append('-d')
+ cc_command.append(d)
+ as_command.append('-d')
+ as_command.append(d)
+
+ for i in self._config['include_dirs']:
+ cc_command.append('-I%s' % i)
+ #cc_command.append(i)
+ as_command.append('-I%s' % i)
+ #as_command.append(i)
+
+ if use_wine:
+ cc_command.insert(0, 'wine')
+ as_command.insert(0, 'wine')
+
+ else:
+ # gcc setup
+ cc_command = ['%s%s-g++' % (gcc_path, gcc_type), '-nodefaultlibs', '-I.', '-fno-builtin', '-Os', '-fno-exceptions', '-fno-rtti', '-mno-sdata']
+ as_command = cc_command
+
+ for d in self._config['defines']:
+ cc_command.append('-D%s' % d)
+
+ for i in self._config['include_dirs']:
+ cc_command.append('-I%s' % i)
+
+
+ self._moduleFiles = []
+ for m in self.project.modules:
+ for normal_sourcefile in m.data['source_files']:
+ print_debug('Compiling %s : %s' % (m.moduleName, normal_sourcefile))
+
+ objfile = os.path.join(self._configTempDir, '%d.o' % generate_unique_id())
+ sourcefile = os.path.join(m.moduleDir, normal_sourcefile)
+
+ # todo: better extension detection
+ if sourcefile.endswith('.s') or sourcefile.endswith('.S'):
+ command = as_command
+ else:
+ command = cc_command
+
+ new_command = command + ['-c', '-o', objfile, sourcefile]
+
+ if 'cc_args' in m.data:
+ new_command += m.data['cc_args']
+
+ if show_cmd:
+ print_debug(new_command)
+
+ errorVal = subprocess.call(new_command)
+ if errorVal != 0:
+ print 'BUILD FAILED!'
+ print 'compiler returned %d - an error occurred while compiling %s' % (errorVal, sourcefile)
+ sys.exit(1)
+
+ self._moduleFiles.append(objfile)
+
+ print_debug('Compilation complete')
+
+
+ def _link(self):
+ 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)
+
+ 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)
+ ld_command.append('-T')
+ ld_command.append(self._config['linker_script'])
+ ld_command.append('-Map')
+ ld_command.append(self._mapFile)
+ ld_command.append('--no-demangle') # for debugging
+ #ld_command.append('--verbose')
+ ld_command += self._moduleFiles
+
+ if show_cmd:
+ print_debug(ld_command)
+
+ errorVal = subprocess.call(ld_command)
+ if errorVal != 0:
+ print 'BUILD FAILED!'
+ print 'ld returned %d' % errorVal
+ sys.exit(1)
+
+ print_debug('Linked successfully')
+
+
+ def _read_symbol_map(self):
+ print_debug('---')
+ print_debug('Reading symbol map')
+
+ self._symbols = []
+
+ file = open(self._mapFile, 'r')
+
+ for line in file:
+ if '__text_start' in line:
+ self._textSegStart = int(line.split()[0],0)
+ break
+
+ # now read the individual symbols
+ # this is probably a bad method to parse it, but whatever
+ for line in file:
+ if '__text_end' in line:
+ self._textSegEnd = int(line.split()[0],0)
+ break
+
+ if not line.startswith(' '): continue
+
+ sym = line.split()
+ sym[0] = int(sym[0],0)
+ self._symbols.append(sym)
+
+ # we've found __text_end, so now we should be at the output section
+ currentEndAddress = self._textSegEnd
+
+ for line in file:
+ if line[0] == '.':
+ # probably a segment
+ data = line.split()
+ if len(data) < 3: continue
+
+ segAddr = int(data[1],0)
+ segSize = int(data[2],0)
+
+ if segAddr+segSize > currentEndAddress:
+ currentEndAddress = segAddr+segSize
+
+ self._codeStart = self._textSegStart
+ self._codeEnd = currentEndAddress
+
+ file.close()
+ print_debug('Read, %d symbol(s) parsed' % len(self._symbols))
+
+
+ # next up, run it through c++filt
+ print_debug('Running c++filt')
+ p = subprocess.Popen(gcc_type + '-c++filt', stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+
+ symbolNameList = [sym[1] for sym in self._symbols]
+ filtResult = p.communicate('\n'.join(symbolNameList))
+ filteredSymbols = filtResult[0].split('\n')
+
+ for sym, filt in zip(self._symbols, filteredSymbols):
+ sym.append(filt)
+
+ print_debug('Done. All symbols complete.')
+ print_debug('Generated code is at 0x%08X .. 0x%08X' % (self._codeStart, self._codeEnd - 4))
+
+
+ def _find_func_by_symbol(self, find_symbol):
+ for sym in self._symbols:
+ if sym[2] == find_symbol:
+ return sym[0]
+
+ raise ValueError, 'Cannot find function: %s' % find_symbol
+
+
+ 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:
+ self._patches.append((offset, data))
+
+
+ def _create_patch(self):
+ print_debug('---')
+ print_debug('Creating patch')
+
+ # convert the .rel patches to KamekPatcher format
+ if len(self._rel_patches) > 0:
+ kamekpatch = generate_kamek_patches(self._rel_patches)
+ #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)
+
+ # generate a Riivolution patch
+ riiv = open('%s/%s_riiv.xml' % (self._outDir, self._config['short_name']), 'w')
+ for patch in self._patches:
+ riiv.write(generate_riiv_mempatch(*patch) + '\n')
+
+ riiv.close()
+
+ # generate an Ocarina patch
+ ocarina = open('%s/%s_ocarina.txt' % (self._outDir, self._config['short_name']), 'w')
+ for patch in self._patches:
+ ocarina.write(generate_ocarina_patch(*patch) + '\n')
+
+ ocarina.close()
+
+ # generate a KamekPatcher patch
+ kpatch = open('%s/%s_loader.bin' % (self._outDir, self._config['short_name']), 'wb')
+ kpatch.write(generate_kamek_patches(self._patches))
+ kpatch.close()
+
+ print_debug('Patches generated')
+
+
+
+class KamekProject(object):
+ _requiredFields = ['output_dir', 'modules']
+
+
+ def __init__(self, filename):
+ # load the project data
+ self.projectPath = os.path.abspath(filename)
+ self.projectName = os.path.basename(self.projectPath)
+ self.projectDir = os.path.dirname(self.projectPath)
+
+ with open(self.projectPath, 'r') as f:
+ self.rawData = f.read()
+
+ self.data = yaml.safe_load(self.rawData)
+ if not isinstance(self.data, dict):
+ raise ValueError, 'the project file is an invalid format (it should be a YAML mapping)'
+
+ # verify it
+ for field in self._requiredFields:
+ if field not in self.data:
+ raise ValueError, 'Missing field in the project file: %s' % field
+
+ # load each module
+ self.modules = []
+ for moduleName in self.data['modules']:
+ modulePath = self.makeRelativePath(moduleName)
+ self.modules.append(KamekModule(modulePath))
+
+
+ def makeRelativePath(self, path):
+ return os.path.normpath(os.path.join(self.projectDir, path))
+
+
+ def build(self):
+ # compile everything in the project
+ builder = KamekBuilder(self, self.configs)
+ builder.build()
+
+
+
+def main():
+ print version_str
+ print
+
+ if len(sys.argv) < 2:
+ print 'No input file specified'
+ sys.exit()
+
+ parse_cmd_options()
+
+ project = KamekProject(os.path.normpath(sys.argv[1]))
+
+ if override_config_file:
+ project.configs = read_configs(override_config_file)
+ else:
+ project.configs = read_configs('kamek_configs.yaml')
+
+ project.build()
+
+
+
+if __name__ == '__main__':
+ main()
+
+
diff --git a/tools/license.dat b/tools/license.dat
new file mode 100644
index 0000000..6d83e13
--- /dev/null
+++ b/tools/license.dat
@@ -0,0 +1,23 @@
+#######################################################
+# MPC55xx MPC56xx V2.x #
+#######################################################
+INCREMENT Win32_PLUGINS_PPCCPU_MPC55xx metrowks 1.0 permanent \
+ uncounted A14591A89164 VENDOR_STRING="MPC55xx CPU Plugins" \
+ HOSTID=ANY ck=79 TS_OK
+INCREMENT Win32_CWIDE_Unlimited metrowks 5.5 permanent uncounted \
+ 0CBFB52552B1 VENDOR_STRING="CodeWarrior IDE 4.2 or later, \
+ Windows" HOSTID=ANY ck=149 TS_OK
+INCREMENT Win32_Plugins_Comp_PPC metrowks 8.0 permanent uncounted \
+ 195E3E33CA10 VENDOR_STRING="131072 bytes of code, PPC build \
+ tools" HOSTID=ANY ck=77 TS_OK
+INCREMENT WIN32_PLUGINS_PPC metrowks 8.0 permanent uncounted \
+ 120885117B48 VENDOR_STRING="EPPC Plugins" HOSTID=ANY ck=97 \
+ TS_OK
+INCREMENT Win32_Plugins_Link_PPC_128K metrowks 8.0 permanent \
+ uncounted 34FDB3A631AF VENDOR_STRING="PPC linker" HOSTID=ANY \
+ TS_OK
+
+
+#######################################################
+# Installer generated keys bellow, if any #
+#######################################################
diff --git a/tools/lmgr11.dll b/tools/lmgr11.dll
new file mode 100644
index 0000000..15038e5
--- /dev/null
+++ b/tools/lmgr11.dll
Binary files differ
diff --git a/tools/mapfile_tool.py b/tools/mapfile_tool.py
new file mode 100755
index 0000000..4ebd288
--- /dev/null
+++ b/tools/mapfile_tool.py
@@ -0,0 +1,273 @@
+# half assed
+
+# d_profile: same place
+# d_bases: same place
+# d_enemies and part of d_bases: offset by 0x20
+# d_en_boss: offset by 0x20
+
+def make_hex_offset(offs):
+ return '0x%08X' % offs
+
+def fix_offs_pal_v2(offs):
+ # do this later
+ return 0xdeadbeef
+
+def fix_offs_ntsc_v1(offs):
+ # .text section
+ if offs >= 0x800B4604 and offs <= 0x800C8E4C:
+ return offs - 0x50
+
+ if offs >= 0x800C8E50 and offs <= 0x800E4D70:
+ return offs - 0xF0
+
+ if offs >= 0x800E4EC0 and offs <= 0x8010F200:
+ return offs - 0x110
+
+ if offs >= 0x8010F430 and offs <= 0x802BB6BC:
+ return offs - 0x140
+
+ if offs >= 0x802BB6C0 and offs <= 0x802BB74C:
+ return offs - 0x150
+
+ if offs >= 0x802BB860 and offs <= 0x802BBBFC:
+ return offs - 0x260
+
+ if offs >= 0x802BBC90 and offs <= 0x802EDCC0:
+ return offs - 0x2F0
+
+ # .ctors, .dtors, .rodata, part of .data section
+ if offs >= 0x802EDCE0 and offs <= 0x80317734:
+ return offs - 0x300
+
+ # .data section
+ if offs >= 0x80317750 and offs <= 0x80322FE0:
+ return offs - 0x318
+
+ if offs >= 0x80323118 and offs <= 0x8032E77C:
+ return offs - 0x348
+
+ if offs >= 0x8032E780 and offs <= 0x8035197C:
+ return offs - 0x340
+
+ # .sdata section, part of .sbss
+ if offs >= 0x80351980 and offs <= 0x80427E87:
+ return offs - 0x300
+
+ # .sbss, .sdata2, .sbss2 sections
+ if offs >= 0x80427E88 and offs <= 0x80429563:
+ return offs - 0x310
+
+ if offs >= 0x80429564 and offs <= 0x80429D7F:
+ return offs - 0x2F8
+
+ if offs >= 0x80429D80 and offs <= 0x807684BF:
+ return offs - 0x2E0
+
+ # part of d_basesNP, d_enemiesNP, d_en_bossNP
+ if offs >= 0x8098A43C:
+ return offs + 0x20
+
+ return offs
+
+
+def fix_offs_ntsc_v2(offs):
+ offs = fix_offs_ntsc_v1(offs)
+
+ if offs >= 0x807685A0 and offs <= 0x807AAA70:
+ return offs + 0x40
+
+ if offs >= 0x807AAA74 and offs <= 0x8099081C:
+ return offs + 0x10
+
+ if offs >= 0x80990820:
+ return offs + 0x20
+
+ return offs
+
+
+def fix_offs_jpn_v1(offs):
+ # .text section
+ if offs >= 0x800B4604 and offs <= 0x800B475C:
+ return offs - 0x50
+
+ if offs >= 0x800B4760 and offs <= 0x800C8DAC:
+ return offs - 0xD0
+
+ if offs >= 0x800C8E50 and offs <= 0x800E4D6C:
+ return offs - 0x170
+
+ if offs >= 0x800E4D94 and offs <= 0x800E4EB4:
+ return offs - 0x194
+
+ if offs >= 0x800E4EB8 and offs <= 0x8010F1D0:
+ return offs - 0x190
+
+ if offs >= 0x8010F430 and offs <= 0x802BB6BC:
+ return offs - 0x330
+
+ if offs >= 0x802BB6D0 and offs <= 0x802BB74C:
+ return offs - 0x340
+
+ if offs >= 0x802BB860 and offs <= 0x802BBBFC:
+ return offs - 0x450
+
+ if offs >= 0x802BBC90 and offs <= 0x802EDCC0:
+ return offs - 0x4E0
+
+ # .ctors, .dtors, .rodata, part of .data section
+ if offs >= 0x802EDCE0 and offs <= 0x80317734:
+ return offs - 0x4E0
+
+ # .data section
+ if offs >= 0x80317750 and offs <= 0x80322FDC:
+ return offs - 0x4F8
+
+ if offs >= 0x80323118 and offs <= 0x8035197C:
+ return offs - 0x5E0
+
+ # .sdata, part of .sbss section
+ if offs >= 0x80351980 and offs <= 0x80427E5F:
+ return offs - 0x580
+
+ if offs >= 0x80427E88 and offs <= 0x8042954B:
+ return offs - 0x5A8
+
+ if offs >= 0x80429570 and offs <= 0x80429D7F:
+ return offs - 0x5C8
+
+ # part of .sdata2, .sbss2 section
+ if offs >= 0x80429D80 and offs <= 0x807684BF: # end offset is right before d_profileNP header
+ return offs - 0x5C0
+
+ # d_profileNP and d_basesNP
+ # "no change" gap ends at 8779ABC
+ if offs >= 0x80779C70 and offs <= 0x8078891F:
+ return offs - 0x130
+
+ if offs >= 0x80788AD0 and offs <= 0x80789EEF:
+ return offs - 0x260
+
+ if offs >= 0x80789F00 and offs <= 0x808D3B87:
+ return offs - 0x270
+
+ if offs >= 0x808D3BD4 and offs <= 0x808D3C1F:
+ return offs - 0x2B4
+
+ if offs >= 0x808D3C20 and offs <= 0x80940C47:
+ return offs - 0x2C0
+
+ if offs >= 0x80940F58 and offs <= 0x80943167:
+ return offs - 0x4E8
+
+ if offs >= 0x809431F8 and offs <= 0x8094329F:
+ return offs - 0x4F8
+
+ if offs >= 0x809432C0 and offs <= 0x80944E77:
+ return offs - 0x500
+
+ if offs >= 0x80945144 and offs <= 0x80945153:
+ return offs - 0x714
+
+ if offs >= 0x80945158 and offs <= 0x8098A36B:
+ return offs - 0x718
+
+ if offs >= 0x8098A478 and offs <= 0x8098F81F:
+ return offs - 0x6F8
+
+ # d_enemiesNP
+ # this offset starts at the .rel header
+ if offs >= 0x809A2CA0 and offs <= 0xDEADBEEF:
+ return offs - 0x700
+
+ if offs >= 0x8010F430 and offs <= 0xDEADBEEF:
+ return offs - 0x330
+
+ if offs >= 0x8010F430 and offs <= 0xDEADBEEF:
+ return offs - 0x330
+
+
+
+import yaml
+
+original = 'pal'
+fix_for = {
+ 'pal2': fix_offs_ntsc_v1,
+ 'ntsc': fix_offs_ntsc_v1,
+ 'ntsc2': fix_offs_ntsc_v2
+}
+
+def do_mapfile(src, dest, fix_offset):
+ map = [x.rstrip() for x in open(src, 'r')]
+ new = []
+
+ for line in map:
+ if ' = 0x80' in line:
+ pos = line.find('0x80')
+ offs = int(line[pos:pos+10], 0)
+ offs = fix_offset(offs)
+ line = line[:pos] + make_hex_offset(offs) + line[pos+10:]
+
+ new.append(line + '\n')
+
+ open(dest, 'w').writelines(new)
+
+
+def work_on_hook(hook, id, func):
+ #print 'doing %s (%s) for %s' % (hook['name'], hook['type'], id)
+
+ t = hook['type']
+
+ if t == 'patch':
+ hook['addr_%s' % id] = func(hook['addr_%s' % original])
+
+ elif t == 'branch_insn' or t == 'add_func_pointer':
+ hook['src_addr_%s' % id] = func(hook['src_addr_%s' % original])
+
+ if 'target_func_%s' % original in hook:
+ hook['target_func_%s' % id] = func(hook['target_func_%s' % original])
+
+ elif t == 'nop_insn':
+ area = hook['area_%s' % original]
+ if isinstance(area, list):
+ start = func(area[0])
+ new_area = [start, start + (area[1] - area[0])]
+ else:
+ new_area = func(area)
+
+ hook['area_%s' % id] = new_area
+
+ #if hook['name'] == 'WM_onCreate': print hook
+
+
+def do_module(src, dest):
+ m = yaml.safe_load(open(src, 'r').read())
+
+ if 'hooks' not in m:
+ return
+
+ for id, func in fix_for.iteritems():
+ for hook in m['hooks']:
+ work_on_hook(hook, id, func)
+
+ open(dest, 'w').write(yaml.dump(m))
+
+
+def do_project(f):
+ proj = yaml.safe_load(open(f, 'r').read())
+
+ for m in proj['modules']:
+ do_module(m.replace('processed/', ''), m)
+
+
+def main():
+ do_mapfile('kamek_pal.x', 'kamek_pal2.x', fix_offs_pal_v2)
+ do_mapfile('kamek_pal.x', 'kamek_ntsc.x', fix_offs_ntsc_v1)
+ do_mapfile('kamek_pal.x', 'kamek_ntsc2.x', fix_offs_ntsc_v2)
+
+ do_project('NewerProject.yaml')
+
+ do_module('anotherhax.yaml', 'processed/anotherhax.yaml')
+
+if __name__ == '__main__':
+ main()
+
diff --git a/tools/mapfile_tool.pyc b/tools/mapfile_tool.pyc
new file mode 100644
index 0000000..4d4ecc6
--- /dev/null
+++ b/tools/mapfile_tool.pyc
Binary files differ
diff --git a/tools/mwasmeppc.exe b/tools/mwasmeppc.exe
new file mode 100644
index 0000000..6e0c31a
--- /dev/null
+++ b/tools/mwasmeppc.exe
Binary files differ
diff --git a/tools/mwcceppc.exe b/tools/mwcceppc.exe
new file mode 100644
index 0000000..e4061da
--- /dev/null
+++ b/tools/mwcceppc.exe
Binary files differ
diff --git a/tools/mwcceppc.idb b/tools/mwcceppc.idb
new file mode 100644
index 0000000..c566ef2
--- /dev/null
+++ b/tools/mwcceppc.idb
Binary files differ
diff --git a/tools/mwldeppc.exe b/tools/mwldeppc.exe
new file mode 100644
index 0000000..48515e8
--- /dev/null
+++ b/tools/mwldeppc.exe
Binary files differ