[FE8] FreeMovement Rework

Without ExpSave version

equiped with ExpSave at here

#Tutorial Basic

  1. Include FreeMovement.event in your buildfile.

  2. Use the macro EnableFreeMovement in beginning event of the chapter, then you can enter the FreeMovement proc.

  3. Press Button A, you can interact with chest, Visit, Armory, Vendor, Scecret, Talk events. Traps can also get effect but need you work on it (I will cover it in “Tutorial Advanced”).

  4. Press Button B will end the FreeMovement and goto Enimy Phase.

  5. Press Button L will call for menu.

  6. Press Button “Select” will change unit to move.

#Tutorial Advanced

  1. You can now modify the program modularly!

  2. Functions called at each Button pressed now can be modified modularly in the file HookList.event (FMU_FunctionList_OnPressXs) :

    These On-Button-Pressed functions are defined in file /src/FreeMU_ButtonPress.c or /src/FreeMU_Event.c, both of which are defined as Bool Fuction(Proc*): if they successfully trigered, then they will return TRUE, otherwase FALSE:
    Following this format, you can define your own On-Button-Pressed functions. These functions have Prioritization:
    (For example) Once you press Button “A” and successfully RunMapEvents, then you will not trigger TalkEvents and TrapEvents this time.

  3. Traps: now FreeMU has been adapted to TrapRework… but not not fully adapted. You can use macro AddTrap(trapID,x,y) (which is defined in TrapRework) in your chapter, but to make them work properly, you need to do more:

#Toturial on Traps

  1. To determine a trap effect. You should select a trapID (Same as TrapRework), and write the effect function for your trap. For now, the effect can only defined in ASMC, not in Event Code (2021.9.17 update: Now you can use EventCaller to get EventCode invoked by asm).
    I have made an example in /Examples/_TrapExample.event, you can refer on it.

  2. Once you end up working on effect routine, you should insert it in HookList/HookListFMU_TrapList_OnPressA or HookListFMU_TrapList_Auto by using the macro FMU_SetTrap(ID,ASMC). Currently there are two types of traps defined: Triggered by pressing button A, or triggered automaticlly:

  3. Now use macro AddTrap(ID,x,y) to set traps on map. You should set this macro in BeginningScene of your chapter:

  4. Then it works:

#Problems on original version:

  1. The introduction of automaticlly save operation will cause lagging in game.

  2. Bad performance on interaction between FreeMU proc and Event Engine, including: (1) “Armory、Vendor、Scecret” cannot be triggered effectively. (2) Chests and the dialogue between villages and characters can be triggered repeatedly.

  3. Long-distance movement could not display the animation of alternate footsteps correctly:

  4. Problems exist on controling the moving speed.


  1. Reorganize the program based on C and try to ensure the readability and scalability of the program at the PROC level:

  2. Ability to Auto-Save;

  3. The 6C-MoveUnit has been fixed to achieving both auto-saving operation and avoiding operation delay .
    11 ← Before
    8 ← rework

  4. Remake the interaction to Event Engine to ensure that Location-based & Character-based event triggered correctly;

#How to use:

See Tutorials !

#Other considerations:

  1. It can interact with Event Engine correctly: chest, Visit, Armory, Vendor, Scecret and Talk events.

  2. Currently, problems still exist on Size event (I don’t know why, but it has been not triggered yet). MiscEvents has not been verified, but I think it should be effective, because MiscEvents is directly used the original assembly code ( I really have no idea how this complex assembly code to be transcribed into C… :frowning:

  3. The display problem of the menu is still not solved yet.

  4. The free movement flag is set at 0x2028924, which is not saved. Please use ExpandedModularSave to save this flag bit;



First of all, this is amazing work, and I am super excited to see what can be done with this. Great job!

Some points of feedback:

  • Commented out your MESSAGEs in the installer.

  • Moved your #define FreeMU_MovingSpeed to the installer, instead of hidden inside a folder.

  • Could we #define which byte in ram to use, please? You can provide the default suggestion, of course.

  • Commented out “Retreat” in the menu cause you might’ve made it always usable?

  • Range events & AFEVs seem to be on a timer. Would it be possible to make this not repeat until you move to a new square?

  • You can’t interact with traps such as Snags or Mines in this mode.

  • I have a lot of custom traps using Sme’s TrapRework like bushes that you have to cut down to walk through or pokeball items to pick up. How would I make them work in FreeMovement mode? They have a unit menu option that’s usable when you’re adjacent to them. Like Snags, for example.

  • Is the only way to switch back to normal mode by doing DisableFreeMovement followed by MNC2 ChapterID? If I wanted to try and make it switch freely between the modes, what should I look into?

Thank you for your time. If you can help at all, I would most appreciate it!


Thank you for your feedback! Based on that, I’m planning to update this hack in these few days and try to solve the trap, RangeEvent and closing proc issues you mentioned.

Of course (if you want), you can also try to extend the proc with your own idea by inserting (or replacing ) functions in proc. After all, the whole proc is designed to be easy to expand. Here are some instructions:

  1. The timer in proc is used for SaveData, not for Misc Ranged-based event. The initial intention of setting the Timer is to avoid wasting too much time and resources on saving data. If you look at the function “pFMU_HandleSave” in file “FreeMUcore.c”, you will find that when timer%5==0, then game get saved and timer get reset.

  2. The function that actually triggers the Misc Event is the function “pFMU_RunMiscBasedEvents” in the file “FreeMUevents.c”, which will then call for function “RunMiscBasedEvents” in the file “/asm/FreeMU.asm”. The function itself is just the same as Sme’s verson, meaning that the range-based misc events should perform as same as how it performed in original version. I wonder if the MiscEvents will work or not in Sme’s verson?

  3. I think the process of triggering the trap should be similar to the shop, both of which are Location-based events . These are triggered by the function “void FMUmisc_RunMapEvents(struct FMUProc* proc)” in the file “FreeMUevents.c” . However, I have not studied on “TrapRework” yet, so the trap has not been validated in the current program. To determine a location to be a trap, I think it needs two judgement, (1). the return value of “GetLocationEventCommandAt(x,y)” (0x8084079) and (2). the value of gMapTerrain[y][x] (0x202E4DC). Maybe I need to get your patch and test these two values.

Other problems are not difficult to solve, so in the next version, I believe that all of other miscellaneous problems can be solved.


Thank you for your work and information!

Another thing you might consider is using a buffer to make the movement feel smoother. If you speed up the movement and you try and quickly change directions, it feels very clunky. If you save what direction is being pressed while looping through your procs, then you can immediately start moving that direction. I think right now it only checks what button you are pressing when it isn’t sleeping? Or something? If I press a button or direction quickly and let go of it, it will often be ignored.

The moving speed can only set to be 10H,20H,40H and 100H,maybe the reason of the moving problem may be course of this?
If possiable, I think maybe a gif(mGBA can make it) to be uploaded could explain this problem more clearly?

I set it to 20H already.

You can see how I tap directions, but unless I hold them, they usually get dropped.

Most games use a buffer so that if you tap a button, it will do that action when it gets to that part of the cycle. (Eg. the action might only happen every 5 frames, but it is always checking for user input and saves the latest user input until the 5 frame window is up.)

Does that clarify things?


Got it。

This issue may not easy to solve,However。

If you comment out“_6C_CALL_ROUTINE(pFMU_HandleSave|1)” in proc-defination,I believe you will get a smoother operation。This is just the cost for saving the game(And that’s just what i said “wasting too much time and resources” before)。

In origin,Sme insert pulse in moving(just as fig.5 at the start of this thread ). I fixed MU6C so that the moving anime can output smoothly,but as long as you wanna save game automatically,you cannot avoid a little bit game lagging。And that’s just why I set such a low speed.

Anyway,I think there should be some way to optimize this issue。Save button press in buffer (here we just need to put it into 6C state) may be a effective way on that and I will try it。But for now,my advice is speed limitation.

Edit1: Here come up with another way: make a longer timer。
If we judge Timer%0xA,rather than Timer%0x5,I think this problem can be solved a little.

Edit2: Hold on the directional button,dont release it. Then you will find it moving more smoothly。


Besides, it’s quite a interesting hack for print button press on screen, but I failed to find it. Would you like to share a link?


Got it!

Something I just noticed - pressing Start can flash the screen.

It won’t let me make the files due to this error, so I can’t test it with a different timer.

But as you say, commenting out the saving function makes it feel a lot smoother.

1 Like

I have just post the new verson on top of thread, you can have a look.
but It’s too late now, and I can’t stay up anymore. So here is some simple instractions you may refer:

  1. You can make modular actions for each button in HookList.event (functions are at “src/FreeMU_ButtonPress.c”).
  2. you can set Delaytime/FreeMU_Flag by yourself at “/FreeMovement.event”.
  3. Traps have worked in some level, but it need to be set by yourself. I have made a template in “Examples/_TrapExample.event”.
1 Like

I have no idea on flashing, which I have not been encountered yet.
On that error for compling C, maybe you should replace “struct FMUProc*” to “struct FMUProc* proc” at line 43. That may be my writing mistake.

1 Like

Although it is not currently possible to directly call the effect function of TrapRework, but now there is some way to interact with traps! See the start of thread!

1 Like

Now you can set trap events by EventCaller


Hello. I created an explanation on how to use Free Movement in FEBuilder, it was already posted in the Discord channel but I think it’d be useful to have it here as well.

To insert the Free Movement hack, download the file in FreeMovement Rework - Modular version updated with tutorials! , and extract it

In FEBuilder, go to Run ->Insert Events via Event Assembler, click on Select File and select the FreeMovement.event file, then click Load Script

In the same folder of FreeMovement.event, FEBuilder will create FreeMovement.sym, open this file

Search for EnableFreeMovementASMC=$ in that file, there will be an address after it, in my case it’s B88871, but use whatever address appears for you instead

In the start event of the chapter that you want to enable free movement, go into the event commands and search for ASMC, then select it

Input the address found in FreeMovement.sym (in my case, B88871) in the “assembler function” field, then press insert. To disable free movement, do the same but use the address listed for DisableFreeMovementASMC=$ instead


I have uploaded a version with Expanded-Modular-Save on Git, which can be got here


What benefit does using this version have? Were there issues with saving data without the expanded modular save before?

1 Like

not any new features. just someone told me that he have no idea on how to modify FreeMU to ExpModularSave, so I add this.
For skilled hackers,it is better to write save/load function and fit to Exp Modular Save by oneself.

1 Like

I think I have got ideas on solve laggering when try saving games. Maybe we can call for saving game by parallel worker with function:

static void (*StartParallerWorkerWithParam)( void* func, int param, ProcPtr) = (const void*) 0x80ACE21;

Later I may have a try.