Reserach on LevelUp Screen

I’m currently trying to introduce a new attribute, “charm” to the character. But I encountered a problem when leveling up:
20210803 res和cha都是魅力增长
Everything went well, and there was no error in saving the value, However, Index=0x8 in the LevelUpScreen (which happens to be the position corresponding to the ChaUp I made) will display -1 anyway;
I spent some time figuring it out and found that the most critical problem is at 0x807EF36. When the program tries to “BL APProc_Create”, the value in r3 seems to overflow (it seems that it can only be limited to between 0x3600 and 0x360E, whereas when Charm get status up, r3 reaches 0x3610) .

Do the following fix

	ORG 	$7EF18
	SHORT	$2332	// mov r3,#0x32
	SHORT	$021B	// lsl r3, #8
	SHORT	0 0

After modifying the above code, the display bug can be corrected :

Update 2022.01.24:

I have made a C-style reaserach (maybe I could say it is a decomp) on level-up screen. Both anim-on and anim-off cases have been inloved:
MokhaLeee/FE8U-LevelUp-Screen-Anim: a C-style reaserach on LevelUp screen Anims of FE8U (

Update 2022.01.27

For now I’m still confused on the scroll of the class-name-bar.


After extending LevlUpScreen, it overflows to the top border. The problem should be in the function (Face_Display, 0x80055F2) in E_FACE of Tree4.

Set the interrupt at 80055E4, ldrh r1, [FaceProc.yPos] , If LevelUpScreen is not expanded, the value entered here each time is r1=A8->A0->98->90…; after expansion, it is r1=B8->B0->A8->A0
The reason for the abnormal display of the first two frames is also here.
I haven’t figured out any good way to solve it. So I had to just provide the following clues I found so far. Hope someone can use these clues to solve this problem.

1 Like

Make it!

	ORG 	$7EF18
	SHORT	$2332	// mov r3,#0x32
	SHORT	$021B	// lsl r3, #8
	SHORT	0 0
	ORG $7F2A0
	// ldr at $7F1F6
	// y-Pos start
	// when put LevelUpScreen on screen
	WORD $FF80	
	ORG $7F382
	// Set y-Pos end (-0x80=0xFF70 in Vanilla)
	// when put LevelUpScreen off screen
	SHORT $2080 // mov r0,#0x80

vanilla ← before
fixed ← after fixed


@Blademaster hmm I notice level ups in SGW would also do this. Maybe this would be useful for the last update as a little patch?

1 Like

This is great work! I’m the fool one who implemented this, and I gave up trying to fix the graphical bugs in the level up screen.

1 Like

It might. I’d have to see how it works with my current hacky implementation of an attempt at fixing this.

MokhaLeee/FE8U-LevelUp-Screen-Anim: a C-style reaserach on LevelUp screen Anims of FE8U (

A C-style reaserach have done, I think this will be helpful for you too.


Some preliminary conclusions:

  1. It is quite easy to handle problems with expanded table on Anim-Off, we just need to fix on SetBgPosition functions then problems will fade away.

  2. In the case of Anim-On, the screen seems to be controlled via the Ekr (I don’t know how it relates to AIS) system. (short)0x2020134 and (short)0x2020136 control screen offset of bar-of-class/lv and window-of-status. But Apparently the bar and the window both lie on BG1. So far I have no idea how does the system separate two areas in the same BG.

1 Like

IIRC, HBlank is used for this.

1 Like

HBlank! that is!
but how it works?

BTW, this function is at 0x8073E18+1,and it is a proc-function, located at 0x8759358. It is just the function called after decompress the LevelUpScreenTSA.


The argument, I’ll call it f, given to SetPrimaryHBlankCallback is a function that will be called whenever a scanline has been drawn. If I’m getting the terms right, a hardware interrupt happens, makes the CPU drop whatever it’s doing, executes f, then returns to whatever it was doing.

This allows you to apply certain effects to specific scanlines, such as the ones pertaining to the LVLup screen bar, without affecting other scanlines, like the ones displaying the window. If you trace through 0x8074834 it’ll probably make clear what’s happening.

This section in tonc goes into HBlank.

PS: Unrelated, but god does this trigger me,


Got it!I think I have understood how it works to seperate two bars. God bless Huichelaar!!


Anim-On proc

1 Like

Oh, I forgot I wrote down some notes for this.

The proc:

Proc at 0x75932C

80739E1     Makes "Level Up" text appear.
8073A4D     Does a lot of stuff to set up statpanel. More details in separate .txt file. Runs once.
8073CE9     Display_level_up_screen. Prepare statpanel Gfx. Also puts mapanim "Level Up" text in OBJ.
            Prepares char's face. Clear BG2 mapbuffer. Calls HUGE Determining_level-up_status function. Which
            seems to prepare BG2's text. Runs once.

8073E19     Sets the scrolling HBlankHandler (8074835). Enable sync BG0, 1, 2, palette. Runs once.
8073E49     Waits for timer > 50 (which it will be on first call). Resets timer and sets some other vars
            (0x2Ch, 0x44w 0x48w, 0x4Cw, 0x50w) Copies entire palette buffer to 0x20165C8. Ends loop.

8073E8D     Uses vars for easing function calls. Copies palette buffer buffer to palette buffer, then applies
            fading to select palettes. Reset timer and break loop after 0x14 iterations. During this loop, panel and face scroll in.

8073FB5     Initializes stat up efx procs for stats that change.

SLEEP 0x14

These procs use 0x2A. If 0x2A is set, flip the title card instead of changing level.
  8073FE1     Does something if 0x2Ab is set. Either way, runs once.
  8074041     Also does something if 0x2Ab is set. Either way, runs once.
  80740C9     As above.
  807401D     0x2Ab isn't set: Reset timer, Display sparkle anim for lvl (0x74D58), Change text, play sound.
              0x2Ab is set: Delete some 6C and do some other stuff, Reset timer.
              Either way, runs once.
  807419D     ends if 0x2Ab is set. Otherwise, increment timer. If timer is >0x1D wait. Timer should start at 0 

80741CD     EndLevelUpGrowthStatusAnimation. Display sparkle anim for each stat up per every 0x14 frames. 8 
            possible stat ups.

80742BD     Wait for 0x6D frames. Reset timer, Delete some proc. Sets the scrolling HBlankHandler (8074835) 
            again. Probably used to scroll out the panel and face. End loop.
80742ED     End loop. Basically YIELD.
80742F9     Basically 8073E8D but in reverse. Ends after only 0x8 iterations though.

80743C1     Does a lot of stuff. Seems to be setting screen blocks, screen sizes, BGPositions, BGPriorities, AIS 
            priorities back. Redraws plateaus. Also deletes face.

8074545     Deletes some procs, changes some vars in AISrelated procs (just like 8073A4D). Call 
            ResumeEfxWeaponIcon. Set 0x29 var, which is read by a different proc. This proc ends
            Procs_ekrLevelup as a result.


Some routine that gets called in the proc:

Procs_ekrLevelup_CallASM 0x73A4C:

Clear BG1 & BG2 MapBuffers
RegisterTileGraphics used to copy BG1 screen entries to screen base block 0xD and 0xE.
RegisterTileGraphics used to copy BG2 screen entries to screen base block 0xA and 0xB.

Does some stuff to some lvlup RAM data.
Does something if anim distance long range (move camera back?)
Changes some proc vars.
Changes right and left unit AIS OAM2. Sets priority to 3.
BG2Priority = 0.
BG1Priority = 1.
BG0Priority = 2.
BG3Priority = 3.

if 0x6FAB0 stuff, seems to affect AISes and BGPriorities. Not taken yet.

more lvlup RAM data stuff.
Set BG1 and BG2 position to 0 horizontal, 8 vertical.
BG0 screenblock = 0xC
BG1 screenblock = 0xD
BG2 screenblock = 0xA

BG1 size = 512x256
BG2 size = 512x256

  Start Procs__efxPartsofScroll, 0x7593DC. Store procstate in lvlup RAM data.

  Increment gSomeSubAnim6CCounter.
  Four loops clearing some 0x1400 sized things (why not use CPUFastSet?)
  More RAM data stuff.
  Start Procs__efxLevelupHB (HBlank?), 0x75945C

  Idk, Idc.

  Change some value in EkrGaugeProc?

  Something todo with gpSome6C_RightUnit. Using Right AIS.
  Something todo with gpSome6C_RightUnit. Using Left AIS.

Call PauseEfxWeaponIcon.

  Change some variable in some other proc.

Turns off window 0, 1 and OBJ window.

Call SetDefaultColours.

Break this proc's loop (why not just make it a call IN THE FIRST PLACE!?)

Current progress:


For now I’m still confused on the scrolling of the class-name-bar in promotion case.

It should be controled by function 0x8073FE0 and 0x80740C8.
Where r0=proc*, and:

Do you mean the part where the bar flips? That seems to be controlled by 0x8074874. I put a breakpoint on SetPrimaryHBlankHandler right before the bar would be flipped, and it was called with this function as argument.

It seems this function uses data (at 0x201FB34 and 0x201FDC0, although these are also pointers) that was prepared beforehand. You might want to see where this data was prepared.