summaryrefslogtreecommitdiff
path: root/src/scanline_effect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/scanline_effect.c')
-rw-r--r--src/scanline_effect.c170
1 files changed, 96 insertions, 74 deletions
diff --git a/src/scanline_effect.c b/src/scanline_effect.c
index e9cf0d02a..0fa5b024d 100644
--- a/src/scanline_effect.c
+++ b/src/scanline_effect.c
@@ -4,27 +4,26 @@
#include "trig.h"
#include "scanline_effect.h"
-// Control value to ransfer a single 16-bit value at HBlank
-#define HBLANK_DMA_CONTROL_16BIT (((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1)
+static void CopyValue16Bit(void);
+static void CopyValue32Bit(void);
-static void sub_80896F4(void);
-static void sub_8089714(void);
-
-extern u16 gUnknown_030041B0;
-extern u16 gBattle_BG1_Y;
-extern u16 gUnknown_030041B8;
-extern u16 gBattle_BG2_Y;
-extern u16 gBattle_BG2_X;
extern u16 gBattle_BG0_Y;
extern u16 gBattle_BG0_X;
extern u16 gBattle_BG1_X;
+extern u16 gBattle_BG1_Y;
+extern u16 gBattle_BG2_X;
+extern u16 gBattle_BG2_Y;
+extern u16 gUnknown_030041B0;
+extern u16 gUnknown_030041B8;
-extern u8 gUnknown_0202FFA4;
+EWRAM_DATA static u8 gUnknown_0202FFA4 = 0;
-extern struct ScanlineEffect gScanlineEffect;
+struct ScanlineEffect gScanlineEffect;
-// Is this a struct?
-extern u16 gUnknown_03004DE0[][0x3C0];
+// Per-scanline register values.
+// This is double buffered so that it can be safely written to at any time
+// without overwriting the buffer that the DMA is currently reading
+u16 gScanlineEffectRegBuffers[2][0x3C0];
void ScanlineEffect_Stop(void)
{
@@ -39,11 +38,11 @@ void ScanlineEffect_Stop(void)
void dp12_8087EA4(void)
{
- CpuFill16(0, gUnknown_03004DE0, 0x780 * 2);
- gScanlineEffect.src[0] = 0;
- gScanlineEffect.src[1] = 0;
- gScanlineEffect.dest = 0;
- gScanlineEffect.unkC = 0;
+ CpuFill16(0, gScanlineEffectRegBuffers, sizeof(gScanlineEffectRegBuffers));
+ gScanlineEffect.src[0] = NULL;
+ gScanlineEffect.src[1] = NULL;
+ gScanlineEffect.dmaDest = NULL;
+ gScanlineEffect.dmaControl = 0;
gScanlineEffect.srcBank = 0;
gScanlineEffect.unk15 = 0;
gScanlineEffect.unk16 = 0;
@@ -51,31 +50,35 @@ void dp12_8087EA4(void)
gScanlineEffect.taskId = 0xFF;
}
-void sub_80895F8(struct UnknownTaskStruct unk)
+void ScanlineEffect_SetParams(struct ScanlineEffectParams params)
{
- if (unk.control == HBLANK_DMA_CONTROL_16BIT) // 16 bit
+ if (params.dmaControl == SCANLINE_EFFECT_DMACNT_16BIT) // 16-bit
{
- gScanlineEffect.src[0] = &gUnknown_03004DE0[0][1];
- gScanlineEffect.src[1] = &gUnknown_03004DE0[1][1];
- gScanlineEffect.unk10 = sub_80896F4;
+ // Set the DMA src to the value for the second scanline because the
+ // first DMA transfer occurs in HBlank *after* the first scanline is drawn
+ gScanlineEffect.src[0] = (u16 *)gScanlineEffectRegBuffers[0] + 1;
+ gScanlineEffect.src[1] = (u16 *)gScanlineEffectRegBuffers[1] + 1;
+ gScanlineEffect.setFirstScanlineReg = CopyValue16Bit;
}
else // assume 32-bit
{
- gScanlineEffect.src[0] = &gUnknown_03004DE0[0][2];
- gScanlineEffect.src[1] = &gUnknown_03004DE0[1][2];
- gScanlineEffect.unk10 = sub_8089714;
+ // Set the DMA src to the value for the second scanline because the
+ // first DMA transfer occurs in HBlank *after* the first scanline is drawn
+ gScanlineEffect.src[0] = (u32 *)gScanlineEffectRegBuffers[0] + 1;
+ gScanlineEffect.src[1] = (u32 *)gScanlineEffectRegBuffers[1] + 1;
+ gScanlineEffect.setFirstScanlineReg = CopyValue32Bit;
}
- gScanlineEffect.unkC = unk.control;
- gScanlineEffect.dest = unk.dest;
- gScanlineEffect.unk15 = unk.unk8;
- gScanlineEffect.unk16 = unk.unk9;
- gScanlineEffect.unk17 = unk.unk9;
+ gScanlineEffect.dmaControl = params.dmaControl;
+ gScanlineEffect.dmaDest = params.dmaDest;
+ gScanlineEffect.unk15 = params.unk8;
+ gScanlineEffect.unk16 = params.unk9;
+ gScanlineEffect.unk17 = params.unk9;
}
-void ScanlineEffect_TransferDma(void)
+void ScanlineEffect_InitHBlankDmaTransfer(void)
{
- if (gScanlineEffect.unk15)
+ if (gScanlineEffect.unk15 != 0)
{
if (gScanlineEffect.unk15 == 3)
{
@@ -86,28 +89,44 @@ void ScanlineEffect_TransferDma(void)
else
{
DmaStop(0);
- DmaSet(0, gScanlineEffect.src[gScanlineEffect.srcBank], gScanlineEffect.dest, gScanlineEffect.unkC);
- gScanlineEffect.unk10();
+ // Set DMA to copy to dest register on each HBlank for the next frame.
+ // The HBlank DMA transfers do not occurr during VBlank, so the transfer
+ // will begin on the HBlank after the first scanline
+ DmaSet(0, gScanlineEffect.src[gScanlineEffect.srcBank], gScanlineEffect.dmaDest, gScanlineEffect.dmaControl);
+ // Manually set the reg for the first scanline
+ gScanlineEffect.setFirstScanlineReg();
+ // Swap current buffer
gScanlineEffect.srcBank ^= 1;
}
}
}
-static void sub_80896F4(void)
+// These two functions are used to copy the register for the first scanline,
+// depending whether it is a 16-bit register or a 32-bit register.
+
+static void CopyValue16Bit(void)
{
- u16 *dest = (u16 *)gScanlineEffect.dest;
- u16 *src = (u16 *)&gUnknown_03004DE0[gScanlineEffect.srcBank];
+ u16 *dest = (u16 *)gScanlineEffect.dmaDest;
+ u16 *src = (u16 *)&gScanlineEffectRegBuffers[gScanlineEffect.srcBank];
+
*dest = *src;
}
-static void sub_8089714(void)
+static void CopyValue32Bit(void)
{
- u32 *dest = (u32 *)gScanlineEffect.dest;
- u32 *src = (u32 *)&gUnknown_03004DE0[gScanlineEffect.srcBank];
+ u32 *dest = (u32 *)gScanlineEffect.dmaDest;
+ u32 *src = (u32 *)&gScanlineEffectRegBuffers[gScanlineEffect.srcBank];
+
*dest = *src;
}
-static void task00_for_dp12(u8 taskId)
+#define tStartLine data[0]
+#define tEndLine data[1]
+#define framesUntilMove data[4]
+#define tDelayInterval data[5]
+#define tRegOffset data[6]
+
+static void TaskFunc_UpdateWavePerFrame(u8 taskId)
{
int value = 0;
@@ -120,7 +139,7 @@ static void task00_for_dp12(u8 taskId)
{
if (gTasks[taskId].data[7])
{
- switch (gTasks[taskId].data[6])
+ switch (gTasks[taskId].tRegOffset)
{
case 0x0:
value = gBattle_BG0_X;
@@ -148,15 +167,16 @@ static void task00_for_dp12(u8 taskId)
break;
}
}
- if (gTasks[taskId].data[4])
+ if (gTasks[taskId].framesUntilMove != 0)
{
int i;
int offset;
- gTasks[taskId].data[4]--;
+
+ gTasks[taskId].framesUntilMove--;
offset = gTasks[taskId].data[3] + 320;
- for (i = gTasks[taskId].data[0]; i < gTasks[taskId].data[1]; i++)
+ for (i = gTasks[taskId].tStartLine; i < gTasks[taskId].tEndLine; i++)
{
- gUnknown_03004DE0[gScanlineEffect.srcBank][i] = gUnknown_03004DE0[0][offset] + value;
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBank][i] = gScanlineEffectRegBuffers[0][offset] + value;
offset++;
}
}
@@ -164,18 +184,17 @@ static void task00_for_dp12(u8 taskId)
{
int i;
int offset;
- gTasks[taskId].data[4] = gTasks[taskId].data[5];
+
+ gTasks[taskId].framesUntilMove = gTasks[taskId].tDelayInterval;
offset = gTasks[taskId].data[3] + 320;
- for (i = gTasks[taskId].data[0]; i < gTasks[taskId].data[1]; i++)
+ for (i = gTasks[taskId].tStartLine; i < gTasks[taskId].tEndLine; i++)
{
- gUnknown_03004DE0[gScanlineEffect.srcBank][i] = gUnknown_03004DE0[0][offset] + value;
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBank][i] = gScanlineEffectRegBuffers[0][offset] + value;
offset++;
}
gTasks[taskId].data[3]++;
if (gTasks[taskId].data[3] == gTasks[taskId].data[2])
- {
gTasks[taskId].data[3] = 0;
- }
}
}
}
@@ -193,44 +212,47 @@ static void GenerateWave(u16 *buffer, u8 frequency, u8 amplitude, u8 unused)
}
}
-u8 ScanlineEffect_InitWave(u8 a1, u8 a2, u8 frequency, u8 amplitude, u8 a5, u8 a6, u8 a7)
+// Initializes a background "wave" effect that affects scanlines startLine (inclusive) to endLine (exclusive).
+// 'frequency' and 'amplitude' control the frequency and amplitude of the wave.
+// 'delayInterval' controls how fast the wave travels up the screen. The wave will shift upwards one scanline every 'delayInterval'+1 frames.
+// 'regOffset' is the offset of the video register to modify.
+u8 ScanlineEffect_InitWave(u8 startLine, u8 endLine, u8 frequency, u8 amplitude, u8 delayInterval, u8 regOffset, bool8 a7)
{
int i;
int offset;
- struct UnknownTaskStruct unk;
+ struct ScanlineEffectParams params;
u8 taskId;
dp12_8087EA4();
- unk.dest = (void *)(REG_ADDR_BG0HOFS + a6);
- unk.control = HBLANK_DMA_CONTROL_16BIT;
- unk.unk8 = 1;
- unk.unk9 = 0;
-
- sub_80895F8(unk);
+ params.dmaDest = (void *)(REG_ADDR_BG0HOFS + regOffset);
+ params.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT;
+ params.unk8 = 1;
+ params.unk9 = 0;
+ ScanlineEffect_SetParams(params);
- taskId = CreateTask(task00_for_dp12, 0);
+ taskId = CreateTask(TaskFunc_UpdateWavePerFrame, 0);
- gTasks[taskId].data[0] = a1;
- gTasks[taskId].data[1] = a2;
- gTasks[taskId].data[2] = 256 / frequency;
- gTasks[taskId].data[3] = 0;
- gTasks[taskId].data[4] = a5;
- gTasks[taskId].data[5] = a5;
- gTasks[taskId].data[6] = a6;
- gTasks[taskId].data[7] = a7;
+ gTasks[taskId].tStartLine = startLine;
+ gTasks[taskId].tEndLine = endLine;
+ gTasks[taskId].data[2] = 256 / frequency;
+ gTasks[taskId].data[3] = 0;
+ gTasks[taskId].framesUntilMove = delayInterval;
+ gTasks[taskId].tDelayInterval = delayInterval;
+ gTasks[taskId].tRegOffset = regOffset;
+ gTasks[taskId].data[7] = a7;
gScanlineEffect.taskId = taskId;
gUnknown_0202FFA4 = 0;
- GenerateWave(&gUnknown_03004DE0[0][320], frequency, amplitude, a2 - a1);
+ GenerateWave(&gScanlineEffectRegBuffers[0][320], frequency, amplitude, endLine - startLine);
offset = 320;
- for (i = a1; i < a2; i++)
+ for (i = startLine; i < endLine; i++)
{
- gUnknown_03004DE0[0][i] = gUnknown_03004DE0[0][offset];
- gUnknown_03004DE0[1][i] = gUnknown_03004DE0[0][offset];
+ gScanlineEffectRegBuffers[0][i] = gScanlineEffectRegBuffers[0][offset];
+ gScanlineEffectRegBuffers[1][i] = gScanlineEffectRegBuffers[0][offset];
offset++;
}