From e12b1713576544fdda756a3ca8831642562ea921 Mon Sep 17 00:00:00 2001
From: Treeki <treeki@gmail.com>
Date: Tue, 27 Mar 2012 21:37:54 +0200
Subject: brought Koopatlas engine up to date and compiling

---
 NewerProjectKP.yaml      | 13 ++++++++++++-
 koopatlas.yaml           |  3 +--
 src/koopatlas/camera.cpp |  8 ++++++--
 src/koopatlas/map.cpp    |  2 --
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/NewerProjectKP.yaml b/NewerProjectKP.yaml
index 3c9657b..d7d4343 100644
--- a/NewerProjectKP.yaml
+++ b/NewerProjectKP.yaml
@@ -2,8 +2,8 @@ output_dir: "NewerASM"
 code_address: 0x808D9000
 modules:
   - processed/prolog.yaml
+  - processed/magicplatform.yaml
   - processed/bugfixes.yaml
-#  - processed/worldmap.yaml
   - processed/koopatlas.yaml
   - processed/levelnames.yaml
   - processed/animtiles.yaml
@@ -16,6 +16,7 @@ modules:
   - processed/poweruphax.yaml
 #  - processed/heapbar.yaml
   - processed/randtiles.yaml
+  - processed/objkinoko.yaml
   - processed/tilegod.yaml
   - processed/linegod.yaml
   - processed/tilesetfixer.yaml
@@ -37,6 +38,16 @@ modules:
   - processed/bossRamboo.yaml
   - processed/bossBalboaWrench.yaml
   - processed/bossWrenchThrow.yaml
+  - processed/bossPodouble.yaml
+  - processed/bossTopman.yaml
+  - processed/bossCaptainBowser.yaml
   - processed/effectVideo.yaml
   - processed/fakeStarCoin.yaml
+  - processed/shyguy.yaml
+  - processed/meteor.yaml
+  - processed/topman.yaml
+  - processed/electricLine.yaml
+  - processed/makeYourOwn.yaml
+  - processed/challengeStar.yaml
+  # - processed/pengi.yaml
 #  - processed/actorlog.yaml
diff --git a/koopatlas.yaml b/koopatlas.yaml
index 37c4a3d..55c9c44 100644
--- a/koopatlas.yaml
+++ b/koopatlas.yaml
@@ -1,11 +1,10 @@
 ---
 source_files:
+  - ../src/boss.cpp # wtf is this doing in the Level Select/WorldMap stuff??
   - ../src/fileload.cpp
   - ../src/scene.S
   - ../src/levelinfo.cpp
   - ../src/levelinfo_old.cpp # backwards compatibility for LevelNames
-  - ../src/player.cpp
-  - ../src/effects.cpp
   - ../src/koopatlas/core.cpp
   - ../src/koopatlas/player.cpp
   - ../src/koopatlas/hud.cpp
diff --git a/src/koopatlas/camera.cpp b/src/koopatlas/camera.cpp
index 47b68a5..c13db56 100644
--- a/src/koopatlas/camera.cpp
+++ b/src/koopatlas/camera.cpp
@@ -69,7 +69,7 @@ int dWorldCamera_c::onExecute() {
 	int heldButtons = Remocon_GetButtons(GetActiveRemocon());
 	if (heldButtons & WPAD_MINUS) {
 		bool change = false;
-		if (heldButtons & WPAD_LEFT) {
+		/*if (heldButtons & WPAD_LEFT) {
 			currentX -= 8.0f;
 			change = true;
 		}
@@ -84,7 +84,7 @@ int dWorldCamera_c::onExecute() {
 		if (heldButtons & WPAD_DOWN) {
 			currentY -= 8.0f;
 			change = true;
-		}
+		}*/
 		if (heldButtons & WPAD_B) {
 			zoomLevel -= 0.10f;
 			change = true;
@@ -96,6 +96,10 @@ int dWorldCamera_c::onExecute() {
 		if (change) {
 		}
 	}
+	daWMPlayer_c *player = daWMPlayer_c::instance;
+	currentX = player->pos.x;
+	currentY = player->pos.y;
+
 	calculateScreenGeometry();
 	doStuff(10000.0);
 	generateCameraMatrices();
diff --git a/src/koopatlas/map.cpp b/src/koopatlas/map.cpp
index 258cf7c..5e2b813 100644
--- a/src/koopatlas/map.cpp
+++ b/src/koopatlas/map.cpp
@@ -41,8 +41,6 @@ dWMMap_c::dWMMap_c() {
 int dWMMap_c::onCreate() {
 	renderer.allocator.setup(GameHeaps[0], 0x20);
 	bool result = renderer.setup(&renderer.allocator);
-	if (result)
-	else
 
 	bgMatrix.translation(1140.0f, -2910.0f, -500.0f);
 	s16 rot = 0x4000;
-- 
cgit v1.2.3


From 5e8e92cd8f403cbfebc4469a1aee252212e42045 Mon Sep 17 00:00:00 2001
From: Treeki <treeki@gmail.com>
Date: Tue, 27 Mar 2012 21:38:52 +0200
Subject: Kamek/Newer now support dynamic linking

---
 hacksToDropbox         |  11 ++++
 hacksToDropboxKP       |  11 ++++
 kamek_configs.yaml     |   3 ++
 kamek_pal.x            |   6 ---
 makeNewer              |   4 +-
 makeNewerAll           |   6 +++
 makeNewerKP            |   4 +-
 makeNewerKPAll         |   6 +++
 src/koopatlas/core.cpp |   1 +
 src/prolog.S           |   2 +-
 tools/dumprelocs.py    |  19 +++++++
 tools/hooks.py         |  73 ++++++++++++++------------
 tools/kamek.py         | 135 ++++++++++++++++++++++++++++++++++++++++++-------
 13 files changed, 220 insertions(+), 61 deletions(-)
 create mode 100755 hacksToDropbox
 create mode 100755 hacksToDropboxKP
 create mode 100644 tools/dumprelocs.py

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! */
diff --git a/makeNewer b/makeNewer
index c9d7ee5..6e142c0 100755
--- a/makeNewer
+++ b/makeNewer
@@ -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:
-- 
cgit v1.2.3


From 053170b827defd19db852a9caa647c9a469e417b Mon Sep 17 00:00:00 2001
From: Treeki <treeki@gmail.com>
Date: Wed, 28 Mar 2012 01:23:46 +0200
Subject: fixes to WM code, and mHeap namespace

---
 include/game.h            | 9 +++++++++
 kamek_pal.x               | 6 ++++++
 src/koopatlas/core.cpp    | 3 ++-
 src/koopatlas/core.h      | 4 ++--
 src/koopatlas/map.cpp     | 9 ++++++---
 src/koopatlas/mapdata.cpp | 2 +-
 6 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/include/game.h b/include/game.h
index efe5fa6..3691fc7 100755
--- a/include/game.h
+++ b/include/game.h
@@ -2911,5 +2911,14 @@ class ClassWithCameraInfo {
 };
 
 
+namespace mHeap {
+	extern void *archiveHeap;
+	extern void *commandHeap;
+	extern void *dylinkHeap;
+	extern void *assertHeap;
+	extern void *gameHeaps[3];
+};
+
+
 #endif
 
diff --git a/kamek_pal.x b/kamek_pal.x
index 9447514..48bebf2 100644
--- a/kamek_pal.x
+++ b/kamek_pal.x
@@ -42,6 +42,12 @@ SECTIONS {
 	CosFIdx__Q24nw4r4mathFf = 0x80237D80;
 	SinCosFIdx__Q24nw4r4mathFPfPff = 0x80237DE0;
 
+	archiveHeap__5mHeap = 0x8042A72C;
+	commandHeap__5mHeap = 0x8042A730;
+	dylinkHeap__5mHeap = 0x8042A734;
+	assertHeap__5mHeap = 0x8042A738;
+	gameHeaps__5mHeap = 0x80377F48;
+
 	init__18StandOnTopColliderFP13dStageActor_cfffffsUcP7Point2d = 0x800DB270;
 	__ct__18StandOnTopColliderFv = 0x800DB220;
 	__dt__18StandOnTopColliderFv = 0x80044400;
diff --git a/src/koopatlas/core.cpp b/src/koopatlas/core.cpp
index de06453..5e15d99 100644
--- a/src/koopatlas/core.cpp
+++ b/src/koopatlas/core.cpp
@@ -230,7 +230,7 @@ bool WMInit_SetupExtra(void *ptr) {
 	wm->player->modelHandler->mdlClass->startAnimation(0, 1.2f, 10.0f, 0.0f);
 
 	dKPNode_s *cNode = wm->pathManager.currentNode;
-	wm->player->pos = (Vec){cNode->x, -cNode->y, wm->player->pos.y};
+	wm->player->pos = (Vec){cNode->x, -cNode->y, wm->player->pos.z};
 
 	// is last param correct? must check :/
 	wm->map = (dWMMap_c*)CreateParentedObject(WM_MAP, wm, 0, 0);
@@ -858,6 +858,7 @@ u32 dScKoopatlas_c::iterateMapList(u32(*callback)(u32,const char *,int,int), u32
 	while (true) {
 		u8 chr = *ptr;
 		if (chr == 13) {
+			*ptr = 0;
 			++ptr;
 			continue;
 		}
diff --git a/src/koopatlas/core.h b/src/koopatlas/core.h
index 6a76cc4..fc517b2 100644
--- a/src/koopatlas/core.h
+++ b/src/koopatlas/core.h
@@ -19,13 +19,13 @@
 #ifdef WM_DEBUGGING
 #define MapReport OSReport
 #else
-inline void MapReport(const char *str, ...) { }
+#define MapReport(...)
 #endif
 
 #ifdef WM_SPAMMY_DEBUGGING
 #define SpammyReport OSReport
 #else
-inline void SpammyReport(const char *str, ...) { }
+#define SpammyReport(...)
 #endif
 
 void NewerMapDrawFunc();
diff --git a/src/koopatlas/map.cpp b/src/koopatlas/map.cpp
index 5e2b813..fa5c120 100644
--- a/src/koopatlas/map.cpp
+++ b/src/koopatlas/map.cpp
@@ -6,18 +6,21 @@
 //#define DOODAD_DEBUGGING
 
 #ifdef TILE_DEBUGGING
+#define TileReport OSReport
 #else
-inline void TileReport(const char *str, ...) { }
+#define TileReport(...)
 #endif
 
 #ifdef BOUND_DEBUGGING
+#define BoundReport OSReport
 #else
-inline void BoundReport(const char *str, ...) { }
+#define BoundReport(...)
 #endif
 
 #ifdef DOODAD_DEBUGGING
+#define DoodadReport OSReport
 #else
-inline void DoodadReport(const char *str, ...) { }
+#define DoodadReport(...)
 #endif
 
 dWMMap_c *dWMMap_c::instance = 0;
diff --git a/src/koopatlas/mapdata.cpp b/src/koopatlas/mapdata.cpp
index eaf9c75..6838741 100644
--- a/src/koopatlas/mapdata.cpp
+++ b/src/koopatlas/mapdata.cpp
@@ -40,7 +40,7 @@ dKPMapData_c::~dKPMapData_c() {
 }
 
 bool dKPMapData_c::load(const char *filename) {
-	data = (dKPMapFile_s*)m_fileLoader.load(filename);
+	data = (dKPMapFile_s*)m_fileLoader.load(filename, 0, mHeap::archiveHeap);
 
 	if (data == 0)
 		return false;
-- 
cgit v1.2.3


From fc3975a42b30566bb542cb06bbd5f7c2da90f79a Mon Sep 17 00:00:00 2001
From: Treeki <treeki@gmail.com>
Date: Wed, 28 Mar 2012 04:41:23 +0200
Subject: support for optimised tilesets

---
 src/koopatlas/map.cpp | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/src/koopatlas/map.cpp b/src/koopatlas/map.cpp
index fa5c120..f4b953c 100644
--- a/src/koopatlas/map.cpp
+++ b/src/koopatlas/map.cpp
@@ -142,9 +142,11 @@ void dWMMap_c::renderer_c::beginRendering() {
 	GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
 	GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
 
+	// Tiles
 	GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0);
-	GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8);
+	GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
 
+	// Doodads
 	GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XY, GX_F32, 0);
 	GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8);
 
@@ -249,19 +251,28 @@ void dWMMap_c::renderer_c::renderTileLayer(dKPLayer_s *layer, dKPLayer_s::sector
 					s16 worldX = (worldSectorX | inX) * 24;
 					s16 worldY = -((worldSectorY | inY) * 24);
 
-					u8 tileX = (tileID & 0x1F) * 8;
-					u8 tileY = ((tileID & 0x1E0) / 32) * 16;
 					TileReport("Drawing tile %d at %d,%d\n", tileID, worldX, worldY);
+					
+					float tileX = (float)((tileID & 0x1F) * 28);
+					float tileY = (float)(((tileID & 0x1E0) >> 5) * 28);
+
+					float xMult = (1.0f / 896.0f);
+					float yMult = (1.0f / 448.0f);
+
+					float coordX1 = xMult * (tileX + 2.0f);
+					float coordX2 = xMult * (tileX + 26.0f);
+					float coordY1 = yMult * (tileY + 2.0f);
+					float coordY2 = yMult * (tileY + 26.0f);
 
 					GXBegin(GX_QUADS, GX_VTXFMT0, 4);
 					GXPosition2s16(worldX + 24, worldY - 24);
-					GXTexCoord2u8(tileX + 7, tileY + 14);
+					GXTexCoord2f32(coordX2, coordY2);
 					GXPosition2s16(worldX + 24, worldY);
-					GXTexCoord2u8(tileX + 7, tileY + 2);
+					GXTexCoord2f32(coordX2, coordY1);
 					GXPosition2s16(worldX, worldY);
-					GXTexCoord2u8(tileX + 1, tileY + 2);
+					GXTexCoord2f32(coordX1, coordY1);
 					GXPosition2s16(worldX, worldY - 24);
-					GXTexCoord2u8(tileX + 1, tileY + 14);//*/
+					GXTexCoord2f32(coordX1, coordY2);
 					GXEnd();
 				}
 			}
-- 
cgit v1.2.3


From 8ad6a04bb5addbcb33a3bbd65a9435069092b69b Mon Sep 17 00:00:00 2001
From: Treeki <treeki@gmail.com>
Date: Thu, 29 Mar 2012 04:14:45 +0200
Subject: magic platform hax requested by antnee

---
 kamek_pal.x           |   2 +
 magicplatform.yaml    |   2 +-
 src/magicplatform.cpp | 100 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/kamek_pal.x b/kamek_pal.x
index 48bebf2..3dedcab 100644
--- a/kamek_pal.x
+++ b/kamek_pal.x
@@ -1487,6 +1487,8 @@ SECTIONS {
 
 	SpawnThwompEffects = 0x809f6660;
 
+	HurtMarioBecauseOfBeingSquashed = 0x80056370;
+
 
 	.text : {
 		FILL (0)
diff --git a/magicplatform.yaml b/magicplatform.yaml
index 69b349c..df98819 100644
--- a/magicplatform.yaml
+++ b/magicplatform.yaml
@@ -11,5 +11,5 @@ hooks:
     addr_pal: 0x8030BDA8
     #      -ID- ----  -X Offs- -Y Offs-  -RectX1- -RectY1- -RectX2- -RectY2-  -1C- -1E- -20- -22-  Flag ----
     # Orig 00C4 0000  00000008 FFFFFFF0  00000000 00000010 00000010 00000010  0000 0000 0000 0000  0000 0000
-    data: '00C4 0000  00000000 00000000  00000000 00000000 00000100 00000100  0000 0000 0000 0000  0000 0000'
+    data: '00C4 0000  00000000 00000000  00000000 00000000 00000100 00000100  0000 0000 0000 0000  0002 0000'
 
diff --git a/src/magicplatform.cpp b/src/magicplatform.cpp
index 924d849..e9fa940 100644
--- a/src/magicplatform.cpp
+++ b/src/magicplatform.cpp
@@ -12,6 +12,10 @@ class daEnMagicPlatform_c : public dEn_c {
 		// Settings
 		u8 rectID, moveSpeed, moveDirection, moveLength;
 
+		u8 moveDelay, currentMoveDelay;
+
+		bool doesMoveInfinitely;
+
 		float moveMin, moveMax, moveDelta, moveBaseDelta;
 		float *moveTarget;
 
@@ -41,12 +45,87 @@ daEnMagicPlatform_c *daEnMagicPlatform_c::build() {
 	return c;
 }
 
+extern "C" void HurtMarioBecauseOfBeingSquashed(void *mario, dStageActor_c *squasher, int type);
+
+static void PhysCB1(daEnMagicPlatform_c *one, dStageActor_c *two) {
+	if (two->stageActorType != 1)
+		return;
+
+	// if left/right
+	if (one->moveDirection <= 1)
+		return;
+
+	if (one->pos_delta.y > 0.0f)
+		HurtMarioBecauseOfBeingSquashed(two, one, 1);
+	else
+		HurtMarioBecauseOfBeingSquashed(two, one, 9);
+}
+
+static void PhysCB2(daEnMagicPlatform_c *one, dStageActor_c *two) {
+	if (two->stageActorType != 1)
+		return;
+
+	// if left/right
+	if (one->moveDirection <= 1)
+		return;
+
+	if (one->pos_delta.y < 0.0f)
+		HurtMarioBecauseOfBeingSquashed(two, one, 2);
+	else
+		HurtMarioBecauseOfBeingSquashed(two, one, 10);
+}
+
+static void PhysCB3(daEnMagicPlatform_c *one, dStageActor_c *two, bool unkMaybeNotBool) {
+	if (two->stageActorType != 1)
+		return;
+
+	// if left/right
+	if (one->moveDirection <= 1)
+		return;
+
+	if (unkMaybeNotBool) {
+		if (one->pos_delta.x > 0.0f)
+			HurtMarioBecauseOfBeingSquashed(two, one, 6);
+		else
+			HurtMarioBecauseOfBeingSquashed(two, one, 12);
+	} else {
+		if (one->pos_delta.x < 0.0f)
+			HurtMarioBecauseOfBeingSquashed(two, one, 5);
+		else
+			HurtMarioBecauseOfBeingSquashed(two, one, 11);
+	}
+}
+
+static bool PhysCB4(daEnMagicPlatform_c *one, dStageActor_c *two) {
+	return (one->pos_delta.y > 0.0f);
+}
+
+static bool PhysCB5(daEnMagicPlatform_c *one, dStageActor_c *two) {
+	return (one->pos_delta.y < 0.0f);
+}
+
+static bool PhysCB6(daEnMagicPlatform_c *one, dStageActor_c *two, bool unkMaybeNotBool) {
+	if (unkMaybeNotBool) {
+		if (one->pos_delta.x > 0.0f)
+			return true;
+	} else {
+		if (one->pos_delta.x < 0.0f)
+			return true;
+	}
+	return false;
+}
+
 int daEnMagicPlatform_c::onCreate() {
 	rectID = settings & 0xFF;
+
 	moveSpeed = (settings & 0xF00) >> 8;
 	moveDirection = (settings & 0x3000) >> 12;
 	moveLength = ((settings & 0xF0000) >> 16) + 1;
 
+	moveDelay = ((settings & 0xF00000) >> 20) * 6;
+
+	doesMoveInfinitely = (settings & 0x10000000);
+
 	setupMovement();
 
 	findSourceArea();
@@ -56,7 +135,11 @@ int daEnMagicPlatform_c::onCreate() {
 	float fHeight = height * 16.0f;
 	physics.setup(this,
 			0.0f, 0.0f, fWidth, -fHeight,
-			0, 0, 0/*&PhysCB1, &PhysCB2, &PhysCB3*/, 1, 0, 0);
+			&PhysCB1, &PhysCB2, &PhysCB3, 1, 0, 0);
+
+	physics.callback1 = &PhysCB4;
+	physics.callback2 = &PhysCB5;
+	physics.callback3 = &PhysCB6;
 
 	physics.addToList();
 
@@ -77,6 +160,9 @@ int daEnMagicPlatform_c::onExecute() {
 	updateTilePositions();
 	physics.update();
 
+	if (doesMoveInfinitely)
+		checkZoneBoundaries(0);
+
 	return 1;
 }
 
@@ -119,6 +205,8 @@ void daEnMagicPlatform_c::setupMovement() {
 	} else {
 		isMoving = false;
 	}
+
+	currentMoveDelay = 0;
 }
 
 void daEnMagicPlatform_c::handleMovement() {
@@ -145,12 +233,21 @@ void daEnMagicPlatform_c::handleMovement() {
 	if (!isMoving)
 		return;
 
+	if (currentMoveDelay > 0) {
+		currentMoveDelay--;
+		return;
+	}
+
 	// Do it
 	bool goesForward = (moveDelta > 0.0f);
 	bool reachedEnd = false;
 
 	*moveTarget += moveDelta;
 
+	// if we're set to move infinitely, never stop
+	if (doesMoveInfinitely)
+		return;
+
 	if (goesForward) {
 		if (*moveTarget >= moveMax) {
 			*moveTarget = moveMax;
@@ -175,6 +272,7 @@ void daEnMagicPlatform_c::handleMovement() {
 		} else {
 			// Otherwise, reverse
 			moveDelta = -moveDelta;
+			currentMoveDelay = moveDelay;
 		}
 	}
 }
-- 
cgit v1.2.3


From c096add584c988d5da37a11a67c24d8368c9ca54 Mon Sep 17 00:00:00 2001
From: Treeki <treeki@gmail.com>
Date: Thu, 29 Mar 2012 06:58:27 +0200
Subject: memory leaks fixed

---
 bugfixes.yaml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/bugfixes.yaml b/bugfixes.yaml
index 63cc6a2..8dd7023 100644
--- a/bugfixes.yaml
+++ b/bugfixes.yaml
@@ -1,6 +1,10 @@
 ---
 source_files: [../src/randomcrap.S, ../src/music.S, ../src/fix38.S]
 hooks:
+  - name: FixMemoryLeaks
+    type: nop_insn
+    addr_pal: 0x800E53E0
+
   - name: MusicHax
     type: branch_insn
     src_addr_pal: 0x8008E5E4
-- 
cgit v1.2.3


From 7bbab722a388bc63ec195a48c22c7060e3fab999 Mon Sep 17 00:00:00 2001
From: Treeki <treeki@gmail.com>
Date: Thu, 29 Mar 2012 07:00:31 +0200
Subject: sigh

---
 bugfixes.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bugfixes.yaml b/bugfixes.yaml
index 8dd7023..27134b6 100644
--- a/bugfixes.yaml
+++ b/bugfixes.yaml
@@ -3,7 +3,7 @@ source_files: [../src/randomcrap.S, ../src/music.S, ../src/fix38.S]
 hooks:
   - name: FixMemoryLeaks
     type: nop_insn
-    addr_pal: 0x800E53E0
+    area_pal: 0x800E53E0
 
   - name: MusicHax
     type: branch_insn
-- 
cgit v1.2.3