sub_812EB58; port scanline_effect
This commit is contained in:
+1
-1
@@ -1009,7 +1009,7 @@ static void FCSetup_ClearVideoRegisters(void)
|
||||
|
||||
static void FCSetup_ResetTasksAndSpriteResources(void)
|
||||
{
|
||||
remove_some_task();
|
||||
ScanlineEffect_Stop();
|
||||
ResetTasks();
|
||||
ResetSpriteData();
|
||||
dp13_810BB8C();
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ extern void MapMusicMain(void);
|
||||
extern void EnableInterrupts(u16);
|
||||
extern void sub_800DD28(void);
|
||||
extern u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void));
|
||||
extern void remove_some_task(void);
|
||||
extern void ScanlineEffect_Stop(void);
|
||||
extern void sub_80F50F4(void);
|
||||
extern bool32 sub_80F5118(void);
|
||||
extern bool8 sub_813B870(void);
|
||||
@@ -441,7 +441,7 @@ void DoSoftReset(void)
|
||||
{
|
||||
REG_IME = 0;
|
||||
m4aSoundVSyncOff();
|
||||
remove_some_task();
|
||||
ScanlineEffect_Stop();
|
||||
DmaStop(1);
|
||||
DmaStop(2);
|
||||
DmaStop(3);
|
||||
|
||||
@@ -1,14 +1,37 @@
|
||||
#include "global.h"
|
||||
#include "main.h"
|
||||
#include "task.h"
|
||||
#include "malloc.h"
|
||||
#include "gpu_regs.h"
|
||||
#include "wild_encounter.h"
|
||||
#include "palette.h"
|
||||
#include "text.h"
|
||||
#include "window.h"
|
||||
#include "text_window.h"
|
||||
#include "bg.h"
|
||||
#include "menu.h"
|
||||
#include "help_system.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "pokemon_3.h"
|
||||
#include "sound.h"
|
||||
#include "scanline_effect.h"
|
||||
#include "constants/species.h"
|
||||
|
||||
struct OakSpeechResources
|
||||
{
|
||||
u8 filler_0000[0x1F];
|
||||
u8 unk_001F;
|
||||
u8 filler_0020[0x1800];
|
||||
u8 bg2TilemapBuffer[0x400];
|
||||
u8 bg1TilemapBuffer[0x800];
|
||||
}; //size=0x2420
|
||||
|
||||
EWRAM_DATA struct OakSpeechResources * sOakSpeechResources = NULL;
|
||||
|
||||
void sub_812E9F8(u8 taskId);
|
||||
void sub_812EB58(u8 taskId);
|
||||
void sub_812EEB0(void);
|
||||
void sub_812F0B0(u8 taskId);
|
||||
|
||||
const u8 gUnknown_845FD54[][5] = {
|
||||
[SPECIES_BULBASAUR - 1] = {0x16, 0x1b, 0x30, 0x16, 0x29},
|
||||
@@ -426,6 +449,11 @@ const u8 gUnknown_845FD54[][5] = {
|
||||
[SPECIES_OLD_UNOWN_QMARK - 1] = {0x20, 0x23, 0x08, 0x20, 0x2d}
|
||||
};
|
||||
|
||||
ALIGNED(4) const u16 gUnknown_8460568[] = INCBIN_U16("data/oak_speech/unk_8460568.gbapal");
|
||||
const u32 gUnknown_84605E8[] = INCBIN_U32("data/oak_speech/unk_84605E8.4bpp.lz");
|
||||
|
||||
extern const struct BgTemplate gUnknown_8462E58[3];
|
||||
|
||||
void sub_812E944(u8 a0, u8 a1, u8 a2, u8 a3, u8 a4, u8 a5)
|
||||
{
|
||||
u8 taskId = CreateTask(sub_812E9F8, a5);
|
||||
@@ -531,3 +559,92 @@ void sub_812EB2C(void)
|
||||
CreateTask(sub_812EB58, 0);
|
||||
SetMainCallback2(sub_812EB10);
|
||||
}
|
||||
|
||||
void sub_812EB58(u8 taskId)
|
||||
{
|
||||
switch (gMain.state)
|
||||
{
|
||||
case 0:
|
||||
SetVBlankCallback(NULL);
|
||||
SetHBlankCallback(NULL);
|
||||
DmaFill16(3, 0, VRAM, VRAM_SIZE);
|
||||
DmaFill32(3, 0, OAM, OAM_SIZE);
|
||||
DmaFill16(3, 0, PLTT + sizeof(u16), PLTT_SIZE - 2);
|
||||
ResetPaletteFade();
|
||||
ScanlineEffect_Stop();
|
||||
ResetSpriteData();
|
||||
FreeAllSpritePalettes();
|
||||
reset_temp_tile_data_buffers();
|
||||
sub_812B1F0(2);
|
||||
break;
|
||||
case 1:
|
||||
sOakSpeechResources = AllocZeroed(sizeof(*sOakSpeechResources));
|
||||
sub_8044AF0(1, 1);
|
||||
break;
|
||||
case 2:
|
||||
SetGpuReg(REG_OFFSET_WIN0H, 0);
|
||||
SetGpuReg(REG_OFFSET_WIN0V, 0);
|
||||
SetGpuReg(REG_OFFSET_WIN1H, 0);
|
||||
SetGpuReg(REG_OFFSET_WIN1V, 0);
|
||||
SetGpuReg(REG_OFFSET_WININ, 0);
|
||||
SetGpuReg(REG_OFFSET_WINOUT, 0);
|
||||
SetGpuReg(REG_OFFSET_BLDCNT, 0);
|
||||
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
|
||||
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||||
break;
|
||||
case 3:
|
||||
ResetBgsAndClearDma3BusyFlags(0);
|
||||
InitBgsFromTemplates(1, gUnknown_8462E58, NELEMS(gUnknown_8462E58));
|
||||
SetBgTilemapBuffer(1, sOakSpeechResources->bg1TilemapBuffer);
|
||||
SetBgTilemapBuffer(2, sOakSpeechResources->bg2TilemapBuffer);
|
||||
ChangeBgX(1, 0, 0);
|
||||
ChangeBgY(1, 0, 0);
|
||||
ChangeBgX(2, 0, 0);
|
||||
ChangeBgY(2, 0, 0);
|
||||
gSpriteCoordOffsetX = 0;
|
||||
gSpriteCoordOffsetY = 0;
|
||||
break;
|
||||
case 4:
|
||||
gPaletteFade.bufferTransferDisabled = TRUE;
|
||||
sub_80F6C6C();
|
||||
sub_80F6C98();
|
||||
sub_80F77CC(0xD0);
|
||||
LoadPalette(gUnknown_8460568, 0x000, 0x080);
|
||||
LoadPalette(stdpal_get(2) + 15, 0x000, 0x002);
|
||||
break;
|
||||
case 5:
|
||||
sOakSpeechResources->unk_001F = sub_80F78A8();
|
||||
gTextFlags.flag_0 = TRUE;
|
||||
decompress_and_copy_tile_data_to_vram(1, gUnknown_84605E8, 0, 0, 0);
|
||||
break;
|
||||
case 6:
|
||||
if (free_temp_tile_data_buffers_if_possible())
|
||||
return;
|
||||
sub_80F6F54(0, 1);
|
||||
FillBgTilemapBufferRect_Palette0(1, 0x0000, 0, 0, 32, 32);
|
||||
CopyBgTilemapBufferToVram(1);
|
||||
break;
|
||||
case 7:
|
||||
sub_810F558(0, 30, 0, 13, 0x1C4);
|
||||
FillBgTilemapBufferRect_Palette0(1, 0xD00F, 0, 0, 30, 2);
|
||||
FillBgTilemapBufferRect_Palette0(1, 0xD002, 0, 2, 30, 1);
|
||||
FillBgTilemapBufferRect_Palette0(1, 0xD00E, 0, 19, 30, 1);
|
||||
sub_812EEB0();
|
||||
gPaletteFade.bufferTransferDisabled = FALSE;
|
||||
gTasks[taskId].data[5] = sub_8006300(0, 0xE6, 0x95, 0, 0);
|
||||
BlendPalettes(0xFFFFFFFF, 0x10, 0x00);
|
||||
break;
|
||||
case 10:
|
||||
BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
|
||||
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
||||
ShowBg(0);
|
||||
ShowBg(1);
|
||||
SetVBlankCallback(sub_812EAFC);
|
||||
PlayBGM(323);
|
||||
gTasks[taskId].func = sub_812F0B0;
|
||||
gMain.state = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
gMain.state++;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
#include "global.h"
|
||||
#include "battle.h"
|
||||
#include "task.h"
|
||||
#include "trig.h"
|
||||
#include "scanline_effect.h"
|
||||
|
||||
extern u16 gBattle_BG0_X;
|
||||
extern u16 gBattle_BG0_Y;
|
||||
extern u16 gBattle_BG1_X;
|
||||
extern u16 gBattle_BG1_Y;
|
||||
extern u16 gBattle_BG2_X;
|
||||
extern u16 gBattle_BG2_Y;
|
||||
extern u16 gBattle_BG3_X;
|
||||
extern u16 gBattle_BG3_Y;
|
||||
|
||||
static void CopyValue16Bit(void);
|
||||
static void CopyValue32Bit(void);
|
||||
|
||||
// EWRAM vars
|
||||
|
||||
// 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
|
||||
EWRAM_DATA u16 gScanlineEffectRegBuffers[2][0x3C0] = {0};
|
||||
|
||||
EWRAM_DATA struct ScanlineEffect gScanlineEffect = {0};
|
||||
EWRAM_DATA static bool8 sShouldStopWaveTask = FALSE;
|
||||
|
||||
void ScanlineEffect_Stop(void)
|
||||
{
|
||||
gScanlineEffect.state = 0;
|
||||
DmaStop(0);
|
||||
if (gScanlineEffect.waveTaskId != 0xFF)
|
||||
{
|
||||
DestroyTask(gScanlineEffect.waveTaskId);
|
||||
gScanlineEffect.waveTaskId = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void ScanlineEffect_Clear(void)
|
||||
{
|
||||
CpuFill16(0, gScanlineEffectRegBuffers, sizeof(gScanlineEffectRegBuffers));
|
||||
gScanlineEffect.dmaSrcBuffers[0] = NULL;
|
||||
gScanlineEffect.dmaSrcBuffers[1] = NULL;
|
||||
gScanlineEffect.dmaDest = NULL;
|
||||
gScanlineEffect.dmaControl = 0;
|
||||
gScanlineEffect.srcBuffer = 0;
|
||||
gScanlineEffect.state = 0;
|
||||
gScanlineEffect.unused16 = 0;
|
||||
gScanlineEffect.unused17 = 0;
|
||||
gScanlineEffect.waveTaskId = 0xFF;
|
||||
}
|
||||
|
||||
void ScanlineEffect_SetParams(struct ScanlineEffectParams params)
|
||||
{
|
||||
if (params.dmaControl == SCANLINE_EFFECT_DMACNT_16BIT) // 16-bit
|
||||
{
|
||||
// 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.dmaSrcBuffers[0] = (u16 *)gScanlineEffectRegBuffers[0] + 1;
|
||||
gScanlineEffect.dmaSrcBuffers[1] = (u16 *)gScanlineEffectRegBuffers[1] + 1;
|
||||
gScanlineEffect.setFirstScanlineReg = CopyValue16Bit;
|
||||
}
|
||||
else // assume 32-bit
|
||||
{
|
||||
// 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.dmaSrcBuffers[0] = (u32 *)gScanlineEffectRegBuffers[0] + 1;
|
||||
gScanlineEffect.dmaSrcBuffers[1] = (u32 *)gScanlineEffectRegBuffers[1] + 1;
|
||||
gScanlineEffect.setFirstScanlineReg = CopyValue32Bit;
|
||||
}
|
||||
|
||||
gScanlineEffect.dmaControl = params.dmaControl;
|
||||
gScanlineEffect.dmaDest = params.dmaDest;
|
||||
gScanlineEffect.state = params.initState;
|
||||
gScanlineEffect.unused16 = params.unused9;
|
||||
gScanlineEffect.unused17 = params.unused9;
|
||||
}
|
||||
|
||||
void ScanlineEffect_InitHBlankDmaTransfer(void)
|
||||
{
|
||||
if (gScanlineEffect.state == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (gScanlineEffect.state == 3)
|
||||
{
|
||||
gScanlineEffect.state = 0;
|
||||
DmaStop(0);
|
||||
sShouldStopWaveTask = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DmaStop(0);
|
||||
// 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.dmaSrcBuffers[gScanlineEffect.srcBuffer], gScanlineEffect.dmaDest, gScanlineEffect.dmaControl);
|
||||
// Manually set the reg for the first scanline
|
||||
gScanlineEffect.setFirstScanlineReg();
|
||||
// Swap current buffer
|
||||
gScanlineEffect.srcBuffer ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 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.dmaDest;
|
||||
u16 *src = (u16 *)&gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer];
|
||||
|
||||
*dest = *src;
|
||||
}
|
||||
|
||||
static void CopyValue32Bit(void)
|
||||
{
|
||||
u32 *dest = (u32 *)gScanlineEffect.dmaDest;
|
||||
u32 *src = (u32 *)&gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer];
|
||||
|
||||
*dest = *src;
|
||||
}
|
||||
|
||||
#define tStartLine data[0]
|
||||
#define tEndLine data[1]
|
||||
#define tWaveLength data[2]
|
||||
#define tSrcBufferOffset data[3]
|
||||
#define tFramesUntilMove data[4]
|
||||
#define tDelayInterval data[5]
|
||||
#define tRegOffset data[6]
|
||||
#define tApplyBattleBgOffsets data[7]
|
||||
|
||||
static void TaskFunc_UpdateWavePerFrame(u8 taskId)
|
||||
{
|
||||
int value = 0;
|
||||
int i;
|
||||
int offset;
|
||||
|
||||
if (sShouldStopWaveTask)
|
||||
{
|
||||
DestroyTask(taskId);
|
||||
gScanlineEffect.waveTaskId = 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gTasks[taskId].tApplyBattleBgOffsets)
|
||||
{
|
||||
switch (gTasks[taskId].tRegOffset)
|
||||
{
|
||||
case SCANLINE_EFFECT_REG_BG0HOFS:
|
||||
value = gBattle_BG0_X;
|
||||
break;
|
||||
case SCANLINE_EFFECT_REG_BG0VOFS:
|
||||
value = gBattle_BG0_Y;
|
||||
break;
|
||||
case SCANLINE_EFFECT_REG_BG1HOFS:
|
||||
value = gBattle_BG1_X;
|
||||
break;
|
||||
case SCANLINE_EFFECT_REG_BG1VOFS:
|
||||
value = gBattle_BG1_Y;
|
||||
break;
|
||||
case SCANLINE_EFFECT_REG_BG2HOFS:
|
||||
value = gBattle_BG2_X;
|
||||
break;
|
||||
case SCANLINE_EFFECT_REG_BG2VOFS:
|
||||
value = gBattle_BG2_Y;
|
||||
break;
|
||||
case SCANLINE_EFFECT_REG_BG3HOFS:
|
||||
value = gBattle_BG3_X;
|
||||
break;
|
||||
case SCANLINE_EFFECT_REG_BG3VOFS:
|
||||
value = gBattle_BG3_Y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gTasks[taskId].tFramesUntilMove != 0)
|
||||
{
|
||||
gTasks[taskId].tFramesUntilMove--;
|
||||
offset = gTasks[taskId].tSrcBufferOffset + 320;
|
||||
for (i = gTasks[taskId].tStartLine; i < gTasks[taskId].tEndLine; i++)
|
||||
{
|
||||
gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gScanlineEffectRegBuffers[0][offset] + value;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gTasks[taskId].tFramesUntilMove = gTasks[taskId].tDelayInterval;
|
||||
offset = gTasks[taskId].tSrcBufferOffset + 320;
|
||||
for (i = gTasks[taskId].tStartLine; i < gTasks[taskId].tEndLine; i++)
|
||||
{
|
||||
gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = gScanlineEffectRegBuffers[0][offset] + value;
|
||||
offset++;
|
||||
}
|
||||
|
||||
// increment src buffer offset
|
||||
gTasks[taskId].tSrcBufferOffset++;
|
||||
if (gTasks[taskId].tSrcBufferOffset == gTasks[taskId].tWaveLength)
|
||||
gTasks[taskId].tSrcBufferOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateWave(u16 *buffer, u8 frequency, u8 amplitude, u8 unused)
|
||||
{
|
||||
u16 i = 0;
|
||||
u8 theta = 0;
|
||||
|
||||
while (i < 256)
|
||||
{
|
||||
buffer[i] = (gSineTable[theta] * amplitude) / 256;
|
||||
theta += frequency;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 applyBattleBgOffsets)
|
||||
{
|
||||
int i;
|
||||
int offset;
|
||||
struct ScanlineEffectParams params;
|
||||
u8 taskId;
|
||||
|
||||
ScanlineEffect_Clear();
|
||||
|
||||
params.dmaDest = (void *)(REG_ADDR_BG0HOFS + regOffset);
|
||||
params.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT;
|
||||
params.initState = 1;
|
||||
params.unused9 = 0;
|
||||
ScanlineEffect_SetParams(params);
|
||||
|
||||
taskId = CreateTask(TaskFunc_UpdateWavePerFrame, 0);
|
||||
|
||||
gTasks[taskId].tStartLine = startLine;
|
||||
gTasks[taskId].tEndLine = endLine;
|
||||
gTasks[taskId].tWaveLength = 256 / frequency;
|
||||
gTasks[taskId].tSrcBufferOffset = 0;
|
||||
gTasks[taskId].tFramesUntilMove = delayInterval;
|
||||
gTasks[taskId].tDelayInterval = delayInterval;
|
||||
gTasks[taskId].tRegOffset = regOffset;
|
||||
gTasks[taskId].tApplyBattleBgOffsets = applyBattleBgOffsets;
|
||||
|
||||
gScanlineEffect.waveTaskId = taskId;
|
||||
sShouldStopWaveTask = FALSE;
|
||||
|
||||
GenerateWave(&gScanlineEffectRegBuffers[0][320], frequency, amplitude, endLine - startLine);
|
||||
|
||||
offset = 320;
|
||||
for (i = startLine; i < endLine; i++)
|
||||
{
|
||||
gScanlineEffectRegBuffers[0][i] = gScanlineEffectRegBuffers[0][offset];
|
||||
gScanlineEffectRegBuffers[1][i] = gScanlineEffectRegBuffers[0][offset];
|
||||
offset++;
|
||||
}
|
||||
|
||||
return taskId;
|
||||
}
|
||||
Reference in New Issue
Block a user