lyn
: “convert” .elf object files to EA events
(If you don’t get it yet keep reading it gets interesting)
(Actually if you never got into asm you can stop now but otherwise bear with me)
Usage:
lyn [-nolink/-linkabs/-linkall] [-longcalls] [-raw] [-printtemp] [-autohook] <elf...>
Note: this is still fairly WIP: not a lot of testing have been done, and it will get at least a few extra updates to include extra functionnalities (see end of post for planned features list).
This tool is fairly simple at first glance: it takes an elf file as argument, and outputs EA code to stdout. But there’s a few things it does that will (hopefully) really change the way we’d go about asm hacking with EA.
But first, let’s clarify a few things:
What’s an elf?
ELF (Executable and Linkable Format) files are what your assembler or compiler will spit out, and what linkers will take to form executables. It contains various useful information, such as of course the compiled asm, but also a bunch more such as symbols and relocations that are specifically useful for linking.
The “old” method of inserting asm into the ROM with EA was simply to extract from that elf the assembled binary part and #incbin
ing it. While this worked, it also invoked the need to write a bunch of other instructions around that to properly link the asm to the rest of the hack/game (labels, post-asm literals, etc), and also was somehow limited (only one routine per file, cannot use relative jumps between files (such as bl
s), etc).
What lyn
tries to do is to bring the functionalities of a proper linker to EA. That is (for now): defining elf global symbols as labels, and “converting” relocations (for example, a BL to SomeSymbol
) to EA code (same example: BL(SomeSymbol)
).
Why “lyn”?
linker>link>lin>lyn? Since Lyn a FE character & EA is a FE hacking tool it felt somewhat fitting. I probably wanted to it to be a special snowflake and not to be named elf2ea
or something like every other tool ¯\_(ツ)_/¯
How2use???
On its own
You can in theory just drop your elf file onto the lyn
executable, but what that will do is just write the output to a console and immediately close said console. What you can do is write a bat file that will call lyn
for the argument file, and output the whole thing to another file (probably using redirections). Here’s an example windows batch file (assumes lyn
is in the same folder):
@echo off
"%~dp0lyn" "%~1" > "%~n1.event"
pause
Save that as a .bat file (again, in a folder with lyn
in it) and drop an elf onto it to generate a corresponding .event file.
Using EA inctext
Quick reminder: what #inctext
does is include the result of the invoked command as EA code (as opposed to #incext
that includes it as raw binary data).
First we want to have the lyn
executable in the <Event Assembler>/Tools
folder, alongside the other tools like Png2Dmp, ParseFile, PFinder, etc.
Then we can simply in any event code use the following code to include the EA-ified elf file:
#inctext lyn "relative/path/to/some/file.elf"
Example of small asm hack that uses lyn
Ok so here I will walk us through remaking my “LolStats” hack by using lyn
(“LolStats” was a quick experiment hack that changes the way stat increase/growth work)
First, here’s the asm code I used (it’s a straight replacement for the routine at 0x02B9A0, that I labelled “GetStatIncrease”)
ASM
.thumb
.set NextRN_100, 0x08000C64
@ Arguments: r0 = Growth
@ Returns: r0 = Stat Increase
GetStatIncrease:
push {r4-r5, lr}
mov r4, r0
mov r5, #0
Continue:
ldr r3, =NextRN_100
mov lr, r3
.short 0xF800
sub r4, r0 @ r4 = (r4 - RN100)
blt End @ if (r4 < 0) goto End;
add r5, #1 @ stat++
b Continue
End:
mov r0, r5
pop {r4-r5}
pop {r1}
bx r1
Contains some labels, standard push/pop, a blh to a vanilla routine, etc… Fairly standard. Next, here’s the event file I used up until now:
Events
#include "Extensions/Hack Installation.txt"
{
PUSH; ORG 0x2B9A0
replaceWithHack(GetStatIncrease)
POP
ALIGN 4
GetStatIncrease:
#incbin "asm/GetStatIncrease.bin"
}
The first thing we are going to do is replace the whole Label: #incbin
stuff by a #inctext
to lyn:
Events but now with lyn
#include "Extensions/Hack Installation.txt"
{
PUSH; ORG 0x2B9A0
replaceWithHack(GetStatIncrease)
POP
ALIGN 4
#inctext lyn "asm/GetStatIncrease.elf"
}
Note: Hack Installation is required for lyn to work too! This may change in the future tho
BUT if you only do that, you’ll get an error from EA saying that GetStatIncrease isn’t in scope, which is normal, since we need to tell our assembler to “expose” the label. So back to our asm source, and add the following:
.global GetStatIncrease
.type GetStatIncrease, %function
Whereever you put it, it doesn’t really matter. What it does is that is tells the symbol GetStatIncrease
is global
and is of type “function
”. This is required information for lyn (and any proper linker really) to know which symbol to expose (make as label) and in what way.
If you add that, assemble to elf, and assemble the events, and it should have worked! You could use the GetStatIncrease
label defined in the asm source from EA! Of course that’s not all lyn does, since it also applies relocations: that means is that if you used in another asm source included through lyn the operation bl GetStatIncrease
, it would have worked!
And… what if I told you that using lyn would also allow use to make use of elf files generated by something that’s not a straight assembler with way more ease… Anyway that’s probably a story for another time.
Here is the final & complete version of my “lyn-ified” LolStats hack.
See next post for follow-up guide stuff:
BONUS: How to get an elf?
Here's your usual Assemble ARM.bat
@echo off
SET startDir=%~p0\devkitARM\bin\
@rem Assemble into an elf
SET as="%startDir%arm-none-eabi-as"
%as% -g -mcpu=arm7tdmi -mthumb-interwork %1 -o "%~n1.elf"
@rem Extract raw assembly binary (text section) from elf
SET objcopy="%startDir%arm-none-eabi-objcopy"
%objcopy% -S "%~n1.elf" -O binary "%~n1.dmp"
echo y | del "%~n1.elf"
pause
You can see there’s a specific part that generates an elf. Isolate that and you’re good! See:
There
@echo off
SET startDir=%~p0\devkitARM\bin\
@rem Assemble into an elf
SET as="%startDir%arm-none-eabi-as"
%as% -g -mcpu=arm7tdmi -mthumb-interwork %1 -o "%~n1.elf"
pause
Known Limitations
Because of how EA handles pointers & offsets, I cannot make lyn
relocate to anything that isn’t in the ROM (I’m mainly thinking RAM data), this is a problem that would probably be less of one once I add the ability for “anticipated linking” between elfs (we’d then just need to add an elf that contains absolute symbols pointing to said RAM data).
Planned features
- Bugfixes
- Support more relocations (such as ARM ones)
- More if ideas or suggestions come (feel free to suggest!)
As always, if you have any question, bug report or anything to ask/tell me, feel free to do so in this thread or on the FEU Discord!
Thanks to @MisakaMikoto and his thread of notes on asm calls for helping me understand some things faster and give me an idea of how to implement some extra functionalities later.
Other references used in coding the thing:
Have a great day! - StanH_