summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm/field_screen_effect.s138
-rw-r--r--asm/overworld.s2
-rw-r--r--data/field_weather.s2
-rw-r--r--ld_script.txt1
-rw-r--r--src/field_screen_effect.c75
5 files changed, 95 insertions, 123 deletions
diff --git a/asm/field_screen_effect.s b/asm/field_screen_effect.s
index f6e1c2f05..6e5a0dc5f 100644
--- a/asm/field_screen_effect.s
+++ b/asm/field_screen_effect.s
@@ -5,112 +5,8 @@
.text
- thumb_func_start sub_807EE00
-sub_807EE00: @ 807EE00
- push {lr}
- cmp r1, 0xA0
- bhi _0807EE28
- cmp r2, 0
- bge _0807EE0C
- movs r2, 0
-_0807EE0C:
- cmp r2, 0xFF
- ble _0807EE12
- movs r2, 0xFF
-_0807EE12:
- cmp r3, 0
- bge _0807EE18
- movs r3, 0
-_0807EE18:
- cmp r3, 0xFF
- ble _0807EE1E
- movs r3, 0xFF
-_0807EE1E:
- lsls r1, 1
- adds r1, r0
- lsls r0, r2, 8
- orrs r0, r3
- strh r0, [r1]
-_0807EE28:
- pop {r0}
- bx r0
- thumb_func_end sub_807EE00
-
- thumb_func_start sub_807EE2C
-sub_807EE2C: @ 807EE2C
- push {r4-r7,lr}
- mov r7, r10
- mov r6, r9
- mov r5, r8
- push {r5-r7}
- sub sp, 0x4
- str r0, [sp]
- mov r10, r1
- mov r9, r2
- adds r6, r3, 0
- mov r8, r6
- movs r7, 0
- cmp r6, 0
- blt _0807EEA8
-_0807EE48:
- mov r0, r9
- subs r1, r0, r7
- mov r0, r10
- subs r4, r0, r6
- adds r5, r0, r6
- ldr r0, [sp]
- adds r2, r4, 0
- adds r3, r5, 0
- bl sub_807EE00
- mov r0, r9
- adds r1, r0, r7
- ldr r0, [sp]
- adds r2, r4, 0
- adds r3, r5, 0
- bl sub_807EE00
- mov r0, r9
- subs r1, r0, r6
- mov r0, r10
- subs r4, r0, r7
- adds r5, r0, r7
- ldr r0, [sp]
- adds r2, r4, 0
- adds r3, r5, 0
- bl sub_807EE00
- mov r0, r9
- adds r1, r0, r6
- ldr r0, [sp]
- adds r2, r4, 0
- adds r3, r5, 0
- bl sub_807EE00
- mov r1, r8
- adds r1, 0x1
- lsls r0, r7, 1
- subs r1, r0
- mov r8, r1
- adds r7, 0x1
- cmp r1, 0
- bge _0807EEA4
- subs r1, r6, 0x1
- lsls r0, r1, 1
- add r8, r0
- adds r6, r1, 0
-_0807EEA4:
- cmp r6, r7
- bge _0807EE48
-_0807EEA8:
- add sp, 0x4
- pop {r3-r5}
- mov r8, r3
- mov r9, r4
- mov r10, r5
- pop {r4-r7}
- pop {r0}
- bx r0
- thumb_func_end sub_807EE2C
-
- thumb_func_start sub_807EEB8
-sub_807EEB8: @ 807EEB8
+ thumb_func_start UpdateFlashLevelEffect
+UpdateFlashLevelEffect: @ 807EEB8
push {r4-r6,lr}
lsls r0, 24
lsrs r5, r0, 24
@@ -148,7 +44,7 @@ _0807EEE6:
ldrsh r2, [r4, r3]
movs r5, 0x6
ldrsh r3, [r4, r5]
- bl sub_807EE2C
+ bl SetFlashScanlineEffectWindowBoundaries
movs r0, 0x1
strh r0, [r4]
b _0807EF76
@@ -169,7 +65,7 @@ _0807EF14:
ldrsh r2, [r4, r3]
movs r6, 0x6
ldrsh r3, [r4, r6]
- bl sub_807EE2C
+ bl SetFlashScanlineEffectWindowBoundaries
movs r0, 0
strh r0, [r4]
ldrh r0, [r4, 0xA]
@@ -205,14 +101,14 @@ _0807EF76:
pop {r4-r6}
pop {r0}
bx r0
- thumb_func_end sub_807EEB8
+ thumb_func_end UpdateFlashLevelEffect
thumb_func_start sub_807EF7C
sub_807EF7C: @ 807EF7C
push {r4,lr}
lsls r0, 24
lsrs r4, r0, 24
- ldr r0, _0807EFA0 @ =sub_807EEB8
+ ldr r0, _0807EFA0 @ =UpdateFlashLevelEffect
bl FuncIsActiveTask
lsls r0, 24
cmp r0, 0
@@ -225,7 +121,7 @@ _0807EF98:
pop {r0}
bx r0
.align 2, 0
-_0807EFA0: .4byte sub_807EEB8
+_0807EFA0: .4byte UpdateFlashLevelEffect
thumb_func_end sub_807EF7C
thumb_func_start sub_807EFA4
@@ -262,7 +158,7 @@ sub_807EFC8: @ 807EFC8
ldr r0, [sp, 0x20]
lsls r0, 24
lsrs r7, r0, 24
- ldr r0, _0807F00C @ =sub_807EEB8
+ ldr r0, _0807F00C @ =UpdateFlashLevelEffect
movs r1, 0x50
bl CreateTask
lsls r0, 24
@@ -284,7 +180,7 @@ sub_807EFC8: @ 807EFC8
strh r7, [r1, 0xA]
b _0807F018
.align 2, 0
-_0807F00C: .4byte sub_807EEB8
+_0807F00C: .4byte UpdateFlashLevelEffect
_0807F010: .4byte gTasks+0x8
_0807F014:
negs r0, r7
@@ -314,7 +210,7 @@ sub_807F028: @ 807F028
bne _0807F042
movs r5, 0x1
_0807F042:
- ldr r1, _0807F070 @ =gUnknown_83C68D4
+ ldr r1, _0807F070 @ =sFlashLevelPixelRadii
lsls r0, 1
adds r0, r1
ldrh r2, [r0]
@@ -334,25 +230,25 @@ _0807F042:
pop {r0}
bx r0
.align 2, 0
-_0807F070: .4byte gUnknown_83C68D4
+_0807F070: .4byte sFlashLevelPixelRadii
thumb_func_end sub_807F028
- thumb_func_start sub_807F074
-sub_807F074: @ 807F074
+ thumb_func_start WriteFlashScanlineEffectBuffer
+WriteFlashScanlineEffectBuffer: @ 807F074
push {r4,lr}
lsls r0, 24
lsrs r0, 24
cmp r0, 0
beq _0807F0A2
ldr r4, _0807F0A8 @ =gScanlineEffectRegBuffers
- ldr r1, _0807F0AC @ =gUnknown_83C68D4
+ ldr r1, _0807F0AC @ =sFlashLevelPixelRadii
lsls r0, 1
adds r0, r1
ldrh r3, [r0]
adds r0, r4, 0
movs r1, 0x78
movs r2, 0x50
- bl sub_807EE2C
+ bl SetFlashScanlineEffectWindowBoundaries
movs r0, 0xF0
lsls r0, 3
adds r1, r4, r0
@@ -366,8 +262,8 @@ _0807F0A2:
bx r0
.align 2, 0
_0807F0A8: .4byte gScanlineEffectRegBuffers
-_0807F0AC: .4byte gUnknown_83C68D4
- thumb_func_end sub_807F074
+_0807F0AC: .4byte sFlashLevelPixelRadii
+ thumb_func_end WriteFlashScanlineEffectBuffer
thumb_func_start sub_807F0B0
sub_807F0B0: @ 807F0B0
diff --git a/asm/overworld.s b/asm/overworld.s
index 21fce8cac..47c5d26af 100644
--- a/asm/overworld.s
+++ b/asm/overworld.s
@@ -3949,7 +3949,7 @@ sub_8056A34: @ 8056A34
lsrs r0, 24
cmp r0, 0
beq _08056A52
- bl sub_807F074
+ bl WriteFlashScanlineEffectBuffer
ldr r2, _08056A58 @ =gUnknown_826D330
ldr r0, [r2]
ldr r1, [r2, 0x4]
diff --git a/data/field_weather.s b/data/field_weather.s
index 890f0fef6..090c19f6b 100644
--- a/data/field_weather.s
+++ b/data/field_weather.s
@@ -391,5 +391,5 @@ gUnknown_83C68B8::
gUnknown_83C68BC:: @ 83C68BC
spr_template 4613, 4608, gOamData_AffineOff_ObjNormal_8x8, gUnknown_83C68B8, NULL, gDummySpriteAffineAnimTable, unc_0807DAB4
-gUnknown_83C68D4:: @ 83C68D4
+sFlashLevelPixelRadii:: @ 83C68D4
.2byte 0x00c8, 0x0048, 0x0038, 0x0028, 0x0018, 0x0000
diff --git a/ld_script.txt b/ld_script.txt
index bc926bf3c..afc559688 100644
--- a/ld_script.txt
+++ b/ld_script.txt
@@ -121,6 +121,7 @@ SECTIONS {
asm/field_weather.o(.text);
asm/field_weather_effects.o(.text);
src/field_fadetransition.o(.text);
+ src/field_screen_effect.o(.text);
asm/field_screen_effect.o(.text);
src/battle_setup.o(.text);
asm/cable_club.o(.text);
diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c
new file mode 100644
index 000000000..19ed25950
--- /dev/null
+++ b/src/field_screen_effect.c
@@ -0,0 +1,75 @@
+#include "global.h"
+
+void SetFlashScanlineEffectWindowBoundary(u16 *dest, u32 y, s32 left, s32 right)
+{
+ if (y <= 160)
+ {
+ if (left < 0)
+ left = 0;
+ if (left > 255)
+ left = 255;
+ if (right < 0)
+ right = 0;
+ if (right > 255)
+ right = 255;
+ dest[y] = (left << 8) | right;
+ }
+}
+
+/*
+ * Draws a circle by approximating xy² + yx² = radius².
+ *
+ * error is approximately xy² - yx². Negative values mean the circle is
+ * slightly too large, and positive values mean the circle is slightly
+ * too small. By decreasing xy whenever the error becomes negative the
+ * code slightly under-approximates the size of the circle.
+ *
+ * The subtractive terms compute yx² - (yx - 1)², and therefore the sum
+ * is yx² - 1:
+ * yx | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
+ * (yx * 2) - 1 | -1 | 1 | 3 | 5 | 7 | 9 | 11 | 13
+ * yx² - (yx - 1)² | -1 | 1 | 3 | 5 | 7 | 9 | 11 | 13
+ * cumulative error | -1 | 0 | 3 | 8 | 15 | 24 | 35 | 48
+ * yx² | 0 | 1 | 4 | 9 | 16 | 25 | 36 | 49
+ *
+ * The additive terms compute xy² - (xy - 1)² - 1, and therefore the sum
+ * (badly) approximates Σi² - (i - 1)², i ∈ (xy, r), consider r = 18:
+ * xy | 18 | 17 | 16 | 15 | 14 | 13 | ... | 0
+ * xy² - (xy - 1)² | 35 | 33 | 31 | 29 | 27 | 25 | ... | -1
+ * 2 * (xy - 1) | 34 | 32 | 30 | 28 | 26 | 24 | ... | -2
+ * cumulative error | 34 | 66 | 96 | 124 | 150 | 174 | ... | 304
+ * Σi² - (i - 1)² | 35 | 68 | 99 | 128 | 155 | 180 | ... | 323
+ * 18² = 324, so if the iterations ran until xy = 0 the cumulative error
+ * would be xy² - r.
+ *
+ * The error is initialized to r, which corrects for the error in the
+ * additive terms. In practice all r iterations don't occur because we
+ * early-exit when yx > xy, so it's half-way between a fix for that
+ * error and an approximation of the midpoint between r² and (r + 1)².
+ *
+ * The algorithm takes advantage of symmetry to compute boundaries in
+ * both directions out from centerY (using yx for y), and also both
+ * directions *in* from centerY ± radius (using xy for y). Because xy
+ * doesn't change on every iteration, we will frequently overwrite
+ * boundaries set in the previous iteration.
+ */
+void SetFlashScanlineEffectWindowBoundaries(u16 *dest, s32 centerX, s32 centerY, s32 radius)
+{
+ s32 xy = radius;
+ s32 error = radius;
+ s32 yx = 0;
+ while (xy >= yx)
+ {
+ SetFlashScanlineEffectWindowBoundary(dest, centerY - yx, centerX - xy, centerX + xy);
+ SetFlashScanlineEffectWindowBoundary(dest, centerY + yx, centerX - xy, centerX + xy);
+ SetFlashScanlineEffectWindowBoundary(dest, centerY - xy, centerX - yx, centerX + yx);
+ SetFlashScanlineEffectWindowBoundary(dest, centerY + xy, centerX - yx, centerX + yx);
+ error -= (yx * 2) - 1;
+ yx++;
+ if (error < 0)
+ {
+ error += 2 * (xy - 1);
+ xy--;
+ }
+ }
+}