[FE7] Exceed the Portrait Hackbox

The engine patch
The testing portrait I made:

There are 2 extra 16x16p tiles in the rightbottom corner. They can be displayed at any position. I added these parameters to the entry in the pointer table for controlling them.

the 17th byte : x-coordinate of the left tile
the 18th byte : y-coordinate of the left tile
the 19th byte : x-coordinate of the right tile
the 20th byte : y-coordinate of the right tile
the 27th byte : the flag which indicates whether the hackbox needs exceeding (1-yes 0-no)

the src

attribute((section(".displayPortrait")))
int displayPortrait(int a1)
{
int v1,v3,v4,v5,v6;
__int16 v2;

v1 = a1;
v2 = sub(0x8006D9C)(a1);
sub(0x8006A34)(
*(_BYTE *)(v1 + 65),
*(_WORD )(v1 + 52) & 0x1FF,
((-(v2 & 0x400) >> 31) & 0x400) + (
(_WORD *)(v1 + 54) & 0xFF),
*(_DWORD *)(v1 + 56),
*(_WORD )(v1 + 60));
if(
(_BYTE )((_DWORD *)(v1 + 44) + 26) == 1)
{
v3 = 4 - *(_BYTE )((_DWORD *)(v1 + 44) + 16);
if ( !(sub(0x8006D9C)(v1) & 1) )
v3 = -v3;
v5 = (8 * v3 + *(_WORD *)(v1 + 52) - 16) & 0x1FF;
if ( sub(0x8006D9C)(v1) & 1 )
// LOWORD(v5) = v5 + 0x1000;
LOWORD(v5) = v5 + 0x1000 + 16;
v6 = sub(0x8006D9C)(v1);
sub(0x8006A34)(
*(_BYTE *)(v1 + 65),
v5,
((-(v6 & 0x400) >> 31) & 0x400)

  • ((*(_WORD *)(v1 + 54) + 8 * *(_BYTE )((_DWORD *)(v1 + 44) + 17)) & 0xFF),
    0x8B905B8,
    *(_WORD *)(v1 + 60)+0x5C);
    v3 = 4 - *(_BYTE )((_DWORD *)(v1 + 44) + 18);
    if ( !(sub(0x8006D9C)(v1) & 1) )
    v3 = -v3;
    v5 = (8 * v3 + *(_WORD *)(v1 + 52) - 16) & 0x1FF;
    if ( sub(0x8006D9C)(v1) & 1 )
    // LOWORD(v5) = v5 + 0x1000;
    LOWORD(v5) = v5 + 0x1000 + 16;
    sub(0x8006A34)(
    *(_BYTE *)(v1 + 65),
    v5,
    ((-(v6 & 0x400) >> 31) & 0x400)
  • ((*(_WORD *)(v1 + 54) + 8 * *(_BYTE )((_DWORD *)(v1 + 44) + 19)) & 0xFF),
    0x8B905B8,
    *(_WORD *)(v1 + 60)+0x5E);
    }
    return v4;
    }

attribute((section(".displayPortraitInBox")))
int displayPortraitInBox(int a1, unsigned __int16 a2, int a3)
{
int v3;
unsigned __int16 v4;
int v5;
int v6;
int v7;
int v9;

v3 = a1;
v4 = a2;
v5 = *(_BYTE *)(a3 + 20) - 1;
v6 = *(_BYTE *)(a3 + 21);
sub(0x80C57B4)(a1, 0x8195680, a2);
v7 = 2 * (32 * v6 + v5) + v3;
*(_WORD *)v7 = v4 + 28;
*(_WORD *)(v7 + 2) = v4 + 29;
*(_WORD *)(v7 + 4) = v4 + 30;
*(_WORD *)(v7 + 6) = v4 + 31;
*(_WORD *)(v7 + 64) = v4 + 60;
*(_WORD *)(v7 + 66) = v4 + 61;
*(_WORD *)(v7 + 68) = v4 + 62;
*(_WORD )(v7 + 70) = v4 + 63;
if(
(_BYTE *)(a3 + 26) == 1)
{
v5 = *(_BYTE *)(a3 + 16) - 1;
v6 = *(_BYTE *)(a3 + 17);
v7 = 2 * (32 * v6 + v5) + v3;
if(v5 > -1 && v5 < 10 && v6 >= 0 && v6 < 9)
*(_WORD *)v7 = v4 + 92;
if(v5 > -2 && v5 < 9 && v6 >= 0 && v6 < 9)
*(_WORD *)(v7 + 2) = v4 + 93;
if(v5 > -1 && v5 < 10 && v6 >= -1 && v6 < 8)
*(_WORD *)(v7 + 64) = v4 + 124;
if(v5 > -2 && v5 < 9 && v6 >= -1 && v6 < 8)
*(_WORD *)(v7 + 66) = v4 + 125;
v5 = *(_BYTE *)(a3 + 18) - 1;
v6 = *(_BYTE *)(a3 + 19);
v7 = 2 * (32 * v6 + v5) + v3;
if(v5 > -1 && v5 < 10 && v6 >= 0 && v6 < 9)
*(_WORD *)v7 = v4 + 94;
if(v5 > -2 && v5 < 9 && v6 >= 0 && v6 < 9)
*(_WORD *)(v7 + 2) = v4 + 95;
if(v5 > -1 && v5 < 10 && v6 >= -1 && v6 < 8)
*(_WORD *)(v7 + 64) = v4 + 126;
if(v5 > -2 && v5 < 9 && v6 >= -1 && v6 < 8)
*(_WORD *)(v7 + 66) = v4 + 127;
}
return v9;
}

attribute((section(".displayPortraitInBox2")))
int displayPortraitInBox2(int a1, unsigned __int16 a2, int a3)
{
int v3;
unsigned __int16 v4;
int v5;
int v6;
int v7;
int v9;

v3 = a1;
v4 = a2;
v5 = *(_BYTE *)(a3 + 20) - 1;
v6 = *(_BYTE *)(a3 + 21) - 1;
sub(0x80C57B4)(a1, 0x8195738, a2);
v7 = 2 * (32 * v6 + v5) + v3;
*(_WORD *)v7 = v4 + 28;
*(_WORD *)(v7 + 2) = v4 + 29;
*(_WORD *)(v7 + 4) = v4 + 30;
*(_WORD *)(v7 + 6) = v4 + 31;
*(_WORD *)(v7 + 64) = v4 + 60;
*(_WORD *)(v7 + 66) = v4 + 61;
*(_WORD *)(v7 + 68) = v4 + 62;
*(_WORD )(v7 + 70) = v4 + 63;
if(
(_BYTE *)(a3 + 26) == 1)
{
v5 = *(_BYTE *)(a3 + 16) - 1;
v6 = *(_BYTE *)(a3 + 17) - 1;
v7 = 2 * (32 * v6 + v5) + v3;
if(v5 > -1 && v5 < 10 && v6 >= 0 && v6 < 9)
*(_WORD *)v7 = v4 + 92;
if(v5 > -2 && v5 < 9 && v6 >= 0 && v6 < 9)
*(_WORD *)(v7 + 2) = v4 + 93;
if(v5 > -1 && v5 < 10 && v6 >= -1 && v6 < 8)
*(_WORD *)(v7 + 64) = v4 + 124;
if(v5 > -2 && v5 < 9 && v6 >= -1 && v6 < 8)
*(_WORD *)(v7 + 66) = v4 + 125;
v5 = *(_BYTE *)(a3 + 18) - 1;
v6 = *(_BYTE *)(a3 + 19) - 1;
v7 = 2 * (32 * v6 + v5) + v3;
if(v5 > -1 && v5 < 10 && v6 >= 0 && v6 < 9)
*(_WORD *)v7 = v4 + 94;
if(v5 > -2 && v5 < 9 && v6 >= 0 && v6 < 9)
*(_WORD *)(v7 + 2) = v4 + 95;
if(v5 > -1 && v5 < 10 && v6 >= -1 && v6 < 8)
*(_WORD *)(v7 + 64) = v4 + 126;
if(v5 > -2 && v5 < 9 && v6 >= -1 && v6 < 8)
*(_WORD *)(v7 + 66) = v4 + 127;
}
return v9;
}

attribute((section(".cutPortraitInBox")))
int cutPortraitInBox(int a1, int a2, int a3, int a4)
{
int v4; // r9@1
int v5; // r5@1
int v6; // r6@1
int v7; // r7@1
int *v8; // r4@2
int v9; // r0@6
signed int v10; // r1@6
// int v12; // [sp+18h] [bp-4h]@0

v4 = a1;
v5 = a2;
v6 = a3;
v7 = a4;
if ( a2 )
{
v8 = sub(0x8006B20)(a2);
sub(0x8001084)(v8[2], 32 * v7, 32);
if ( *v8 )
{
sub(0x8013168)((_BYTE *)v8, 32 * v6 + 100663296);
sub(0x8001084)(v8[2], 32 * v7, 32);
if ( sub(0x800721C)(v5) << 24 )
sub(0x80071C4)(v4, ((_WORD)v7 << 12) + (v6 & 0x3FF), (int)v8);
else
sub(0x8007170)(v4, ((_WORD)v7 << 12) + (v6 & 0x3FF), (int)v8);
v9 = v4;
v10 = 5;
do
{
if(
(_WORD *)v9 == 0xD0E7)
*(_WORD )v9 = 0;
if(
(_WORD *)(v9 + 18) == 0xD0E7)
*(_WORD *)(v9 + 18) = 0;
v9 += 64;
–v10;
}
while ( v10 >= 0 );
}
else
{
sub(0x8013168)((_BYTE *)v8[4], 32 * v6 + 100663296);
sub(0x801331C)(v4, (v7 << 12) + (v6 & 0x3FF), 10, 9);
}
}
// return v12;
return 1;
}

13 Likes

2017 looks like it’s off to a roaring start around here, I’d say. Wow!

Hoooooly shit

This. Changes. Everything.


Still a long way before it’s comparable to FEXNA.

It’d be nice if there were two extra blocks, so that way we could turn the hackbox into a full square without having to crop shoulders.

2 Likes

I like how this character changes size, fur shape, and his ethnicity between images.

First thought: okay…that seems cool, but not very useful…?

A couple days later: omg this is awesome i just have a few questions
Are x and y in blocks or pixels?
What about negative values, like placing one of these above or to the left of a sprite?
Any plans for a FE8 version? ‘3’

This is amazing! You know, the vanilla FE devs really could’ve used this to make it so Roland, Selena, and Gheb don’t have cut-off parts on their portraits.

WOW this is really helpful. Even if it’s only just 2 16x16p tiles, it allows more dynamic portraits!

The same as the eye/mouth. Blocks.

I remember someone saying that he expects to port it himself when I ported it from FE7J to FE7US. Now he has a chance.

MOD EDIT: no scripts

Bug Fix.