diff --git a/include/sysutil.h b/include/sysutil.h index f7df4728..f245112e 100644 --- a/include/sysutil.h +++ b/include/sysutil.h @@ -150,13 +150,14 @@ void NewSysboxText(int vobj_offset, int pal, const char * str, int line, int del void EndAllProcChildren(ProcPtr proc); void nop_80ADDF8(void); -/* Some objects scalling routine */ -void sub_80ADDFC(u8 layer, s16 angle, s16, s16, s16, s16); -void sub_80ADE90(u8, s16, s16); -void sub_80ADEE0(u8, s16, s16, s16, s16); -void sub_80ADF48(u8 layer, int angle, int a, int b, int c, int d); -void sub_80ADFBC(u8 layer, int a, int b); -void sub_80ADFFC(u8 layer, int a, int b, int c, int d); +/* Bg-affin rot/scale */ +void BgAffinRotScaling(u8 bg, s16 angle, s16 x_center, s16 y_center, s16 sx, s16 sy); +void BgAffinScaling(u8 bg, s16 sy, s16 sx); +void BgAffinAnchoring(u8 bg, s16 q0_x, s16 q0_y, s16 p0_x, s16 p0_y); + +void BgAffinRotScalingHighPrecision(u8 bg, int angle, int texX, int texY, int sx, int sy); +void BgAffinScalingHighPrecision(u8 bg, int sy, int sx); +void BgAffinAnchoringHighPrecision(u8 bg, int q0_x, int q0_y, int p0_x, int p0_y); /* No idea, maybe some tile map or palette modication */ void sub_80AE044(int a, u16 * buf, int c, int d, int e, int f, int g, int h); diff --git a/src/chapterintrofx.c b/src/chapterintrofx.c index 9c72aa9c..9565d2e5 100644 --- a/src/chapterintrofx.c +++ b/src/chapterintrofx.c @@ -611,9 +611,9 @@ void ChapterIntro_LightBurst_Loop(struct ChapterIntroFXProc* proc) { } if (proc->unk_4C <= 0xFF) { - sub_80ADDFC(2, 0, 0, 0, 0x180, 0x180); - sub_80ADE90(2, (u16)proc->unk_4C + 0xF0, (u16)proc->unk_4C + 0xF0); - sub_80ADEE0(2, 0x70, 0x58, 0x4C, 0x4C); + BgAffinRotScaling(2, 0, 0, 0, 0x180, 0x180); + BgAffinScaling(2, (u16)proc->unk_4C + 0xF0, (u16)proc->unk_4C + 0xF0); + BgAffinAnchoring(2, 0x70, 0x58, 0x4C, 0x4C); FlushLCDControl(); if (proc->unk_66 != 0) { diff --git a/src/opinfo.c b/src/opinfo.c index 559be348..4e1ae9a7 100644 --- a/src/opinfo.c +++ b/src/opinfo.c @@ -751,11 +751,11 @@ void ClassIntroFlare_Loop(struct OpInfoFlareProc* proc) { unkC = Interpolate(0, 0, 0xD6, proc->unk_4c, 0x3C); unkD = Interpolate(0, 0x10, 0x80, proc->unk_4c, 0x3C); - sub_80ADDFC(2, (s16)proc->unk_4e, 0, 0, (s16)(unkA * 5 + 0x80), (s16)(unkA * 5 + 0x80)); + BgAffinRotScaling(2, (s16)proc->unk_4e, 0, 0, (s16)(unkA * 5 + 0x80), (s16)(unkA * 5 + 0x80)); - sub_80ADE90(2, 0x100, 0x100); + BgAffinScaling(2, 0x100, 0x100); - sub_80ADEE0(2, unkC, unkD, 0x50, 0x48); + BgAffinAnchoring(2, unkC, unkD, 0x50, 0x48); proc->unk_4e -= 0x40; diff --git a/src/opsubtitle.c b/src/opsubtitle.c index 0b7158aa..cf1ba799 100644 --- a/src/opsubtitle.c +++ b/src/opsubtitle.c @@ -238,9 +238,9 @@ void Subtitle_LightFlareFx_Loop(struct OpSubtitleProc* proc) { c = Interpolate(0, 0, 214, proc->unk_4c, 60); d = Interpolate(0, 16, 128, proc->unk_4c, 60); - sub_80ADDFC(2, proc->unk_4e, 0, 0, a * 5 + 0x80, a * 5 + 0x80); - sub_80ADE90(2, 0x100, 0x100); - sub_80ADEE0(2, c, d, 80, 72); + BgAffinRotScaling(2, proc->unk_4e, 0, 0, a * 5 + 0x80, a * 5 + 0x80); + BgAffinScaling(2, 0x100, 0x100); + BgAffinAnchoring(2, c, d, 80, 72); proc->unk_4e -= 64; diff --git a/src/sysutil.c b/src/sysutil.c index b647b5d0..ba386855 100644 --- a/src/sysutil.c +++ b/src/sysutil.c @@ -893,23 +893,23 @@ void nop_80ADDF8(void) return; } -void sub_80ADDFC(u8 bg, s16 angle, s16 c, s16 d, s16 e, s16 f) +void BgAffinRotScaling(u8 bg, s16 angle, s16 x_center, s16 y_center, s16 sx, s16 sy) { struct BgAffineSrcData data; struct BgAffineDstData * dst; - if (e <= 4) - e = 4; + if (sx <= 4) + sx = 4; - if (f <= 4) - f = 4; + if (sy <= 4) + sy = 4; - data.texX = c * 0x100; - data.texY = d * 0x100; + data.texX = x_center * 0x100; + data.texY = y_center * 0x100; data.scrX = 0; data.scrY = 0; - data.sx = 0x10000 / e; - data.sy = 0x10000 / f; + data.sx = 0x10000 / sx; + data.sy = 0x10000 / sy; data.alpha = angle * 0x10; dst = &gLCDControlBuffer.bg3affin; @@ -919,45 +919,64 @@ void sub_80ADDFC(u8 bg, s16 angle, s16 c, s16 d, s16 e, s16 f) BgAffineSet(&data, dst, 1); } -void sub_80ADE90(u8 bg, s16 a, s16 b) +void BgAffinScaling(u8 bg, s16 sy, s16 sx) { struct BgAffineDstData * affin = NULL; if (bg == BG_2) affin = &gLCDControlBuffer.bg2affin; - affin->pb = (affin->pb * a) >> 8; - affin->pd = (affin->pd * a) >> 8; - affin->pa = (affin->pa * b) >> 8; - affin->pc = (affin->pc * b) >> 8; -} - -void sub_80ADEE0(u8 bg, s16 a, s16 b, s16 c, s16 d) -{ + /** + * y = y * (1 / sy) + * x = x * (1 / sx) + * + * Both of which are 8.8 fixed point numbers: + * a halfword with 8 integer bits and 8 fractional bits. + * + * See tonc 10.4.1: https://www.coranac.com/tonc/text/affine.htm + */ + + affin->pb = (affin->pb * sy) >> 8; + affin->pd = (affin->pd * sy) >> 8; + affin->pa = (affin->pa * sx) >> 8; + affin->pc = (affin->pc * sx) >> 8; +} + +void BgAffinAnchoring(u8 bg, s16 q0_x, s16 q0_y, s16 p0_x, s16 p0_y) +{ + /** + * vector q0: origin in screen space + * vector p0: origin in texture space + * + * See tonc 12.3: https://www.coranac.com/tonc/text/affbg.htm: + * + * bgaff->dx= asx->tex_x - (pa*asx->scr_x + pb*asx->scr_y); + * bgaff->dy= asx->tex_y - (pc*asx->scr_x + pd*asx->scr_y); + */ struct BgAffineDstData * affin = NULL; if (bg == BG_2) affin = &gLCDControlBuffer.bg2affin; - affin->dx = affin->pa * (-a) + affin->pb * (-b) + c * 0x100; - affin->dy = affin->pc * (-a) + affin->pd * (-b) + d * 0x100; + affin->dx = affin->pa * (-q0_x) + affin->pb * (-q0_y) + p0_x * 0x100; + affin->dy = affin->pc * (-q0_x) + affin->pd * (-q0_y) + p0_y * 0x100; } -void sub_80ADF48(u8 bg, int angle, int a, int b, int c, int d) +void BgAffinRotScalingHighPrecision(u8 bg, int angle, int texX, int texY, int sx, int sy) { struct BgAffineSrcData data; struct BgAffineDstData * dst; - if (c <= 0x400) - c = 0x400; + if (sx <= 0x400) + sx = 0x400; - if (d <= 0x400) - d = 0x400; + if (sy <= 0x400) + sy = 0x400; - data.texX = a; - data.texY = b; + data.texX = texX; + data.texY = texY; data.scrX = 0; data.scrY = 0; - data.sx = 0x1000000 / c; - data.sy = 0x1000000 / d; + data.sx = 0x1000000 / sx; + data.sy = 0x1000000 / sy; data.alpha = angle >> 4; dst = &gLCDControlBuffer.bg3affin; @@ -967,26 +986,26 @@ void sub_80ADF48(u8 bg, int angle, int a, int b, int c, int d) BgAffineSet(&data, dst, 1); } -void sub_80ADFBC(u8 bg, int a, int b) +void BgAffinScalingHighPrecision(u8 bg, int sy, int sx) { struct BgAffineDstData * affin = NULL; if (bg == BG_2) affin = &gLCDControlBuffer.bg2affin; - affin->pb = (affin->pb * a) >> 0x10; - affin->pd = (affin->pd * a) >> 0x10; - affin->pa = (affin->pa * b) >> 0x10; - affin->pc = (affin->pc * b) >> 0x10; + affin->pb = (affin->pb * sy) >> 0x10; + affin->pd = (affin->pd * sy) >> 0x10; + affin->pa = (affin->pa * sx) >> 0x10; + affin->pc = (affin->pc * sx) >> 0x10; } -void sub_80ADFFC(u8 bg, int a, int b, int c, int d) +void BgAffinAnchoringHighPrecision(u8 bg, int q0_x, int q0_y, int p0_x, int p0_y) { struct BgAffineDstData * affin = NULL; if (bg == BG_2) affin = &gLCDControlBuffer.bg2affin; - affin->dx = ((affin->pa * (-a) + affin->pb * (-b)) >> 8) + c; - affin->dy = ((affin->pc * (-a) + affin->pd * (-b)) >> 8) + d; + affin->dx = ((affin->pa * (-q0_x) + affin->pb * (-q0_y)) >> 8) + p0_x; + affin->dy = ((affin->pc * (-q0_x) + affin->pd * (-q0_y)) >> 8) + p0_y; } void sub_80AE044(int a, u16 * buf, int c, int d, int e, int f, int g, int h)