mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-26 03:34:15 +01:00
Document pokedex cry screen
This commit is contained in:
parent
31b0cbe9b4
commit
a495379ff0
BIN
graphics/pokedex/cry_screen_bg
Normal file
BIN
graphics/pokedex/cry_screen_bg
Normal file
Binary file not shown.
Before Width: | Height: | Size: 135 B After Width: | Height: | Size: 135 B |
@ -1,7 +1,7 @@
|
|||||||
#ifndef GUARD_POKEDEX_CRY_SCREEN_H
|
#ifndef GUARD_POKEDEX_CRY_SCREEN_H
|
||||||
#define GUARD_POKEDEX_CRY_SCREEN_H
|
#define GUARD_POKEDEX_CRY_SCREEN_H
|
||||||
|
|
||||||
struct CryRelatedStruct
|
struct CryScreenWindow
|
||||||
{
|
{
|
||||||
u16 unk0; // Assigned to val that's never read
|
u16 unk0; // Assigned to val that's never read
|
||||||
u8 unk2; // Never read
|
u8 unk2; // Never read
|
||||||
@ -12,10 +12,10 @@ struct CryRelatedStruct
|
|||||||
|
|
||||||
extern u8 gDexCryScreenState;
|
extern u8 gDexCryScreenState;
|
||||||
|
|
||||||
bool8 LoadCryWaveformWindow(struct CryRelatedStruct*, u8);
|
bool8 LoadCryWaveformWindow(struct CryScreenWindow*, u8);
|
||||||
void UpdateCryWaveformWindow(u8);
|
void UpdateCryWaveformWindow(u8);
|
||||||
void CryScreenPlayButton(u16);
|
void CryScreenPlayButton(u16);
|
||||||
bool8 LoadCryMeter(struct CryRelatedStruct*, u8);
|
bool8 LoadCryMeter(struct CryScreenWindow*, u8);
|
||||||
void FreeCryScreen(void);
|
void FreeCryScreen(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3568,14 +3568,14 @@ static void Task_LoadCryScreen(u8 taskId)
|
|||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
{
|
{
|
||||||
struct CryRelatedStruct sp4;
|
struct CryScreenWindow waveformWindow;
|
||||||
|
|
||||||
sp4.unk0 = 0x4020;
|
waveformWindow.unk0 = 0x4020;
|
||||||
sp4.unk2 = 0x1F;
|
waveformWindow.unk2 = 31;
|
||||||
sp4.paletteNo = 8;
|
waveformWindow.paletteNo = 8;
|
||||||
sp4.yPos = 0x1E;
|
waveformWindow.yPos = 30;
|
||||||
sp4.xPos = 0xC;
|
waveformWindow.xPos = 12;
|
||||||
if (LoadCryWaveformWindow(&sp4, 2))
|
if (LoadCryWaveformWindow(&waveformWindow, 2))
|
||||||
{
|
{
|
||||||
gMain.state++;
|
gMain.state++;
|
||||||
gDexCryScreenState = 0;
|
gDexCryScreenState = 0;
|
||||||
@ -3584,12 +3584,12 @@ static void Task_LoadCryScreen(u8 taskId)
|
|||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
{
|
{
|
||||||
struct CryRelatedStruct spC;
|
struct CryScreenWindow cryMeter;
|
||||||
|
|
||||||
spC.paletteNo = 9;
|
cryMeter.paletteNo = 9;
|
||||||
spC.xPos = 0x12;
|
cryMeter.xPos = 18;
|
||||||
spC.yPos = 3;
|
cryMeter.yPos = 3;
|
||||||
if (LoadCryMeter(&spC, 3))
|
if (LoadCryMeter(&cryMeter, 3))
|
||||||
gMain.state++;
|
gMain.state++;
|
||||||
CopyWindowToVram(WIN_VU_METER, 2);
|
CopyWindowToVram(WIN_VU_METER, 2);
|
||||||
CopyWindowToVram(WIN_INFO, 3);
|
CopyWindowToVram(WIN_INFO, 3);
|
||||||
|
@ -9,35 +9,53 @@
|
|||||||
#include "trig.h"
|
#include "trig.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
struct PokedexCryVolumeMeter {
|
// Cry meter needle positions
|
||||||
s8 unk0;
|
//
|
||||||
s8 unk1;
|
// 0
|
||||||
u8 unk2;
|
// 32 . . -32
|
||||||
u16 needleSpriteId;
|
// . .
|
||||||
|
// 64 . . -64
|
||||||
|
// . .
|
||||||
|
// . .
|
||||||
|
// 96 . . -96
|
||||||
|
// 127
|
||||||
|
//
|
||||||
|
#define MIN_NEEDLE_POS 32
|
||||||
|
#define MAX_NEEDLE_POS -32
|
||||||
|
|
||||||
|
#define NEEDLE_MOVE_INCREMENT 5
|
||||||
|
|
||||||
|
#define WAVEFORM_WINDOW_HEIGHT 56
|
||||||
|
|
||||||
|
struct PokedexCryMeterNeedle {
|
||||||
|
s8 rotation;
|
||||||
|
s8 targetRotation;
|
||||||
|
u8 moveIncrement;
|
||||||
|
u16 spriteId;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PokedexCryScreen
|
struct PokedexCryScreen
|
||||||
{
|
{
|
||||||
u8 unk0[16];
|
u8 cryWaveformBuffer[16];
|
||||||
u8 unk10;
|
u8 cryState;
|
||||||
u8 unk11;
|
u8 playhead;
|
||||||
u8 unk12;
|
u8 waveformPreviousY;
|
||||||
u16 unk14;
|
u16 unk; // Never read
|
||||||
u8 unk16;
|
u8 playStartPos;
|
||||||
u16 species;
|
u16 species;
|
||||||
u8 unk1A;
|
u8 cryOverrideCountdown;
|
||||||
u8 unk1B;
|
u8 cryRepeatDelay;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void PlayCryScreenCry(u16);
|
static void PlayCryScreenCry(u16);
|
||||||
static void sub_81455A8(void);
|
static void BufferCryWaveformSegment(void);
|
||||||
static void DrawWaveformFlatline(void);
|
static void DrawWaveformFlatline(void);
|
||||||
static void sub_8145648(u8);
|
static void AdvancePlayhead(u8);
|
||||||
static void DrawWaveformSegment(u8, u8);
|
static void DrawWaveformSegment(u8, u8);
|
||||||
static void sub_8145814(u8);
|
static void DrawWaveformWindow(u8);
|
||||||
static void sub_8145824(u8, s16, u8);
|
static void ShiftWaveformOver(u8, s16, bool8);
|
||||||
static void SpriteCB_CryMeterNeedle(struct Sprite *);
|
static void SpriteCB_CryMeterNeedle(struct Sprite *);
|
||||||
static void sub_8145B24(s8);
|
static void SetCryMeterNeedleTarget(s8);
|
||||||
|
|
||||||
// IWRAM common
|
// IWRAM common
|
||||||
u8 gDexCryScreenState;
|
u8 gDexCryScreenState;
|
||||||
@ -45,7 +63,7 @@ u8 gDexCryScreenState;
|
|||||||
// EWRAM vars
|
// EWRAM vars
|
||||||
static EWRAM_DATA struct PokedexCryScreen *sDexCryScreen = NULL;
|
static EWRAM_DATA struct PokedexCryScreen *sDexCryScreen = NULL;
|
||||||
static EWRAM_DATA u8 *sCryWaveformWindowTiledata = NULL;
|
static EWRAM_DATA u8 *sCryWaveformWindowTiledata = NULL;
|
||||||
static EWRAM_DATA struct PokedexCryVolumeMeter *sCryVolumeMeter = NULL;
|
static EWRAM_DATA struct PokedexCryMeterNeedle *sCryMeterNeedle = NULL;
|
||||||
|
|
||||||
static const u16 sCryMeterNeedle_Pal[] = INCBIN_U16("graphics/pokedex/cry_meter_needle.gbapal");
|
static const u16 sCryMeterNeedle_Pal[] = INCBIN_U16("graphics/pokedex/cry_meter_needle.gbapal");
|
||||||
static const u8 sCryMeterNeedle_Gfx[] = INCBIN_U8("graphics/pokedex/cry_meter_needle.4bpp");
|
static const u8 sCryMeterNeedle_Gfx[] = INCBIN_U8("graphics/pokedex/cry_meter_needle.4bpp");
|
||||||
@ -54,7 +72,7 @@ static const u16 sCryMeter_Tilemap[] = INCBIN_U16("graphics/pokedex/cry_meter_ma
|
|||||||
static const u16 sCryMeter_Pal[] = INCBIN_U16("graphics/pokedex/cry_meter.gbapal");
|
static const u16 sCryMeter_Pal[] = INCBIN_U16("graphics/pokedex/cry_meter.gbapal");
|
||||||
static const u8 sCryMeter_Gfx[] = INCBIN_U8("graphics/pokedex/cry_meter.4bpp.lz");
|
static const u8 sCryMeter_Gfx[] = INCBIN_U8("graphics/pokedex/cry_meter.4bpp.lz");
|
||||||
|
|
||||||
const u16 gUnknown_085B8770[][72] =
|
static const u16 sWaveformOffsets[][72] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C,
|
0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C,
|
||||||
@ -139,18 +157,21 @@ const u16 gUnknown_085B8770[][72] =
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u16 sCryScreenBg_Pal[] = INCBIN_U16("graphics/pokedex/85B8C10.gbapal");
|
static const u16 sCryScreenBg_Pal[] = INCBIN_U16("graphics/pokedex/cry_screen_bg.gbapal");
|
||||||
static const u8 sCryScreenBg_Gfx[] = INCBIN_U8("graphics/pokedex/85B8C10.4bpp");
|
static const u8 sCryScreenBg_Gfx[] = INCBIN_U8("graphics/pokedex/cry_screen_bg.4bpp");
|
||||||
|
|
||||||
const u8 gUnknown_085B8C30[] = {0xF0, 0x0F};
|
static const u8 sWaveformTileDataNybbleMasks[] = {0xF0, 0x0F};
|
||||||
const u8 gUnknown_085B8C32[][16] =
|
|
||||||
|
// Waveform is blue in the middle (8) grading to white at peaks (15)
|
||||||
|
// Split into two arrays for the two vertical slice halves
|
||||||
|
static const u8 sWaveformColor[][16] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
|
15, 14, 13, 12, 11, 10, 9, 8,
|
||||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
|
8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
}, {
|
}, {
|
||||||
0xF0, 0xE0, 0xD0, 0xC0, 0xB0, 0xA0, 0x90, 0x80,
|
15 << 4, 14 << 4, 13 << 4, 12 << 4, 11 << 4, 10 << 4, 9 << 4, 8 << 4,
|
||||||
0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0
|
8 << 4, 9 << 4, 10 << 4, 11 << 4, 12 << 4, 13 << 4, 14 << 4, 15 << 4,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -202,7 +223,7 @@ static const struct SpritePalette sCryMeterNeedleSpritePalettes[] =
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool8 LoadCryWaveformWindow(struct CryRelatedStruct *arg0, u8 windowId)
|
bool8 LoadCryWaveformWindow(struct CryScreenWindow *window, u8 windowId)
|
||||||
{
|
{
|
||||||
u8 i;
|
u8 i;
|
||||||
u8 finished = FALSE;
|
u8 finished = FALSE;
|
||||||
@ -216,28 +237,28 @@ bool8 LoadCryWaveformWindow(struct CryRelatedStruct *arg0, u8 windowId)
|
|||||||
sCryWaveformWindowTiledata = (u8*)GetWindowAttribute(windowId, WINDOW_TILE_DATA);
|
sCryWaveformWindowTiledata = (u8*)GetWindowAttribute(windowId, WINDOW_TILE_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
sDexCryScreen->unk14 = arg0->unk0;
|
sDexCryScreen->unk = window->unk0;
|
||||||
sDexCryScreen->unk16 = arg0->yPos;
|
sDexCryScreen->playStartPos = window->yPos;
|
||||||
sDexCryScreen->unk1A = 0;
|
sDexCryScreen->cryOverrideCountdown = 0;
|
||||||
sDexCryScreen->unk1B = 0;
|
sDexCryScreen->cryRepeatDelay = 0;
|
||||||
sDexCryScreen->unk10 = 0;
|
sDexCryScreen->cryState = 0;
|
||||||
sDexCryScreen->unk12 = 28;
|
sDexCryScreen->waveformPreviousY = WAVEFORM_WINDOW_HEIGHT / 2;
|
||||||
sDexCryScreen->unk11 = 0;
|
sDexCryScreen->playhead = 0;
|
||||||
sub_8145824(windowId, -8 * arg0->xPos, 1);
|
ShiftWaveformOver(windowId, -8 * window->xPos, TRUE); // Does nothing
|
||||||
for (i = 0; i < 224; i++)
|
for (i = 0; i < 224; i++)
|
||||||
CopyToWindowPixelBuffer(windowId, sCryScreenBg_Gfx, TILE_SIZE_4BPP, i);
|
CopyToWindowPixelBuffer(windowId, sCryScreenBg_Gfx, TILE_SIZE_4BPP, i);
|
||||||
|
|
||||||
gDexCryScreenState++;
|
gDexCryScreenState++;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
for (i = 0; i < sDexCryScreen->unk16 * 8; i++)
|
for (i = 0; i < sDexCryScreen->playStartPos * 8; i++)
|
||||||
DrawWaveformSegment(i, 0);
|
DrawWaveformSegment(i, 0);
|
||||||
|
|
||||||
gDexCryScreenState++;
|
gDexCryScreenState++;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
sub_8145814(windowId);
|
DrawWaveformWindow(windowId);
|
||||||
LoadPalette(sCryScreenBg_Pal, arg0->paletteNo * 16, 32);
|
LoadPalette(sCryScreenBg_Pal, window->paletteNo * 16, 32);
|
||||||
finished = TRUE;
|
finished = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -247,17 +268,20 @@ bool8 LoadCryWaveformWindow(struct CryRelatedStruct *arg0, u8 windowId)
|
|||||||
|
|
||||||
void UpdateCryWaveformWindow(u8 windowId)
|
void UpdateCryWaveformWindow(u8 windowId)
|
||||||
{
|
{
|
||||||
u8 var0;
|
u8 waveformIdx;
|
||||||
|
|
||||||
sub_8145814(windowId);
|
DrawWaveformWindow(windowId);
|
||||||
sub_8145648(windowId);
|
AdvancePlayhead(windowId);
|
||||||
if (sDexCryScreen->unk1B)
|
|
||||||
sDexCryScreen->unk1B--;
|
|
||||||
|
|
||||||
if (sDexCryScreen->unk1A)
|
// Cry cant be replayed until this counter is done
|
||||||
|
if (sDexCryScreen->cryRepeatDelay)
|
||||||
|
sDexCryScreen->cryRepeatDelay--;
|
||||||
|
|
||||||
|
// Once a cry replay has started, it waits for this countdown before playing
|
||||||
|
if (sDexCryScreen->cryOverrideCountdown)
|
||||||
{
|
{
|
||||||
sDexCryScreen->unk1A--;
|
sDexCryScreen->cryOverrideCountdown--;
|
||||||
if (!sDexCryScreen->unk1A)
|
if (!sDexCryScreen->cryOverrideCountdown)
|
||||||
{
|
{
|
||||||
PlayCryScreenCry(sDexCryScreen->species);
|
PlayCryScreenCry(sDexCryScreen->species);
|
||||||
DrawWaveformFlatline();
|
DrawWaveformFlatline();
|
||||||
@ -265,47 +289,51 @@ void UpdateCryWaveformWindow(u8 windowId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sDexCryScreen->unk10 == 0)
|
// No cry playing
|
||||||
|
if (sDexCryScreen->cryState == 0)
|
||||||
{
|
{
|
||||||
DrawWaveformFlatline();
|
DrawWaveformFlatline();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sDexCryScreen->unk10 == 1)
|
// Cry playing, buffer waveform
|
||||||
|
if (sDexCryScreen->cryState == 1)
|
||||||
{
|
{
|
||||||
sub_81455A8();
|
BufferCryWaveformSegment();
|
||||||
}
|
}
|
||||||
else if (sDexCryScreen->unk10 > 8)
|
else if (sDexCryScreen->cryState > 8)
|
||||||
{
|
{
|
||||||
|
// Buffered waveform exhausted, end or buffer more
|
||||||
if (!IsCryPlaying())
|
if (!IsCryPlaying())
|
||||||
{
|
{
|
||||||
DrawWaveformFlatline();
|
DrawWaveformFlatline();
|
||||||
sDexCryScreen->unk10 = 0;
|
sDexCryScreen->cryState = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub_81455A8();
|
BufferCryWaveformSegment();
|
||||||
sDexCryScreen->unk10 = 1;
|
sDexCryScreen->cryState = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var0 = 2 * (sDexCryScreen->unk10 - 1);
|
// Draw cry
|
||||||
DrawWaveformSegment(sDexCryScreen->unk16 * 8 + sDexCryScreen->unk11 - 2, sDexCryScreen->unk0[var0]);
|
waveformIdx = 2 * (sDexCryScreen->cryState - 1);
|
||||||
DrawWaveformSegment(sDexCryScreen->unk16 * 8 + sDexCryScreen->unk11 - 1, sDexCryScreen->unk0[var0 + 1]);
|
DrawWaveformSegment(sDexCryScreen->playStartPos * 8 + sDexCryScreen->playhead - 2, sDexCryScreen->cryWaveformBuffer[waveformIdx]);
|
||||||
sDexCryScreen->unk10++;
|
DrawWaveformSegment(sDexCryScreen->playStartPos * 8 + sDexCryScreen->playhead - 1, sDexCryScreen->cryWaveformBuffer[waveformIdx + 1]);
|
||||||
|
sDexCryScreen->cryState++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CryScreenPlayButton(u16 species)
|
void CryScreenPlayButton(u16 species)
|
||||||
{
|
{
|
||||||
if (gMPlayInfo_BGM.status & MUSICPLAYER_STATUS_PAUSE && !sDexCryScreen->unk1A)
|
if (gMPlayInfo_BGM.status & MUSICPLAYER_STATUS_PAUSE && !sDexCryScreen->cryOverrideCountdown)
|
||||||
{
|
{
|
||||||
if (!sDexCryScreen->unk1B)
|
if (!sDexCryScreen->cryRepeatDelay)
|
||||||
{
|
{
|
||||||
sDexCryScreen->unk1B = 4;
|
sDexCryScreen->cryRepeatDelay = 4;
|
||||||
if (IsCryPlaying() == TRUE)
|
if (IsCryPlaying() == TRUE)
|
||||||
{
|
{
|
||||||
StopCry();
|
StopCry();
|
||||||
sDexCryScreen->species = species;
|
sDexCryScreen->species = species;
|
||||||
sDexCryScreen->unk1A = 2;
|
sDexCryScreen->cryOverrideCountdown = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -317,11 +345,11 @@ void CryScreenPlayButton(u16 species)
|
|||||||
|
|
||||||
static void PlayCryScreenCry(u16 species)
|
static void PlayCryScreenCry(u16 species)
|
||||||
{
|
{
|
||||||
PlayCry2(species, 0, 0x7d, 10);
|
PlayCry2(species, 0, 125, 10);
|
||||||
sDexCryScreen->unk10 = 1;
|
sDexCryScreen->cryState = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sub_81455A8(void)
|
static void BufferCryWaveformSegment(void)
|
||||||
{
|
{
|
||||||
u8 i;
|
u8 i;
|
||||||
s8 *baseBuffer;
|
s8 *baseBuffer;
|
||||||
@ -333,102 +361,113 @@ static void sub_81455A8(void)
|
|||||||
baseBuffer = gSoundInfo.pcmBuffer + (gSoundInfo.pcmDmaPeriod + 1 - gPcmDmaCounter) * gSoundInfo.pcmSamplesPerVBlank;
|
baseBuffer = gSoundInfo.pcmBuffer + (gSoundInfo.pcmDmaPeriod + 1 - gPcmDmaCounter) * gSoundInfo.pcmSamplesPerVBlank;
|
||||||
|
|
||||||
buffer = baseBuffer + 0x630;
|
buffer = baseBuffer + 0x630;
|
||||||
for (i = 0; i < ARRAY_COUNT(sDexCryScreen->unk0); i++)
|
for (i = 0; i < ARRAY_COUNT(sDexCryScreen->cryWaveformBuffer); i++)
|
||||||
sDexCryScreen->unk0[i] = buffer[i * 2] * 2;
|
sDexCryScreen->cryWaveformBuffer[i] = buffer[i * 2] * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawWaveformFlatline(void)
|
static void DrawWaveformFlatline(void)
|
||||||
{
|
{
|
||||||
DrawWaveformSegment(sDexCryScreen->unk16 * 8 + sDexCryScreen->unk11 - 2, 0);
|
DrawWaveformSegment(sDexCryScreen->playStartPos * 8 + sDexCryScreen->playhead - 2, 0);
|
||||||
DrawWaveformSegment(sDexCryScreen->unk16 * 8 + sDexCryScreen->unk11 - 1, 0);
|
DrawWaveformSegment(sDexCryScreen->playStartPos * 8 + sDexCryScreen->playhead - 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sub_8145648(u8 windowId)
|
static void AdvancePlayhead(u8 windowId)
|
||||||
{
|
{
|
||||||
u8 i;
|
u8 i;
|
||||||
u16 offset;
|
u16 offset;
|
||||||
|
|
||||||
sub_8145824(windowId, sDexCryScreen->unk11, 0);
|
ShiftWaveformOver(windowId, sDexCryScreen->playhead, FALSE);
|
||||||
sDexCryScreen->unk11 += 2;
|
sDexCryScreen->playhead += 2;
|
||||||
offset = (sDexCryScreen->unk11 / 8 + sDexCryScreen->unk16 + 1) % 32;
|
offset = (sDexCryScreen->playhead / 8 + sDexCryScreen->playStartPos + 1) % 32;
|
||||||
for (i = 0; i < 7; i++)
|
for (i = 0; i < 7; i++)
|
||||||
CopyToWindowPixelBuffer(windowId, sCryScreenBg_Gfx, TILE_SIZE_4BPP, offset + (i * TILE_SIZE_4BPP));
|
CopyToWindowPixelBuffer(windowId, sCryScreenBg_Gfx, TILE_SIZE_4BPP, offset + (i * TILE_SIZE_4BPP));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawWaveformSegment(u8 a0, u8 a1)
|
// Waveform segments are drawn in alternate vertical slices
|
||||||
|
// Note that the waveform isnt put on screen until DrawWaveformWindow
|
||||||
|
static void DrawWaveformSegment(u8 position, u8 amplitude)
|
||||||
{
|
{
|
||||||
u8 sp0;
|
// Position is a bitfield containing the play start pos, the playhead pos, and which vertical slice half to draw
|
||||||
u8 r6;
|
#define PLAY_START_POS (position >> 3)
|
||||||
u8 r8;
|
#define PLAYHEAD_POS (position & ((1 << 3) - 1))
|
||||||
u16 offset;
|
#define VERT_SLICE (position & 1)
|
||||||
u16 r1;
|
|
||||||
u8 i;
|
|
||||||
|
|
||||||
r1 = (a1 + 127) * 256;
|
u8 currentPointY;
|
||||||
i = r1 / 1152.0;
|
u8 nybble;
|
||||||
if (i > 55)
|
u16 offset;
|
||||||
i = 55;
|
u16 temp;
|
||||||
sp0 = i;
|
u8 y;
|
||||||
r6 = a0 & 1;
|
|
||||||
if (i > sDexCryScreen->unk12)
|
temp = (amplitude + 127) * 256;
|
||||||
|
y = temp / 1152.0;
|
||||||
|
if (y > WAVEFORM_WINDOW_HEIGHT - 1)
|
||||||
|
y = WAVEFORM_WINDOW_HEIGHT - 1;
|
||||||
|
currentPointY = y;
|
||||||
|
nybble = VERT_SLICE;
|
||||||
|
if (y > sDexCryScreen->waveformPreviousY)
|
||||||
{
|
{
|
||||||
|
// Current point lower than previous point, draw point and draw line up to previous
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
offset = gUnknown_085B8770[a0 & 0x7][i] + (a0 / 8) * TILE_SIZE_4BPP;
|
offset = sWaveformOffsets[PLAYHEAD_POS][y] + PLAY_START_POS * TILE_SIZE_4BPP;
|
||||||
sCryWaveformWindowTiledata[offset] &= gUnknown_085B8C30[r6];
|
sCryWaveformWindowTiledata[offset] &= sWaveformTileDataNybbleMasks[nybble];
|
||||||
sCryWaveformWindowTiledata[offset] |= gUnknown_085B8C32[r6][((i / 3) - 1) & 0x0F];
|
sCryWaveformWindowTiledata[offset] |= sWaveformColor[nybble][((y / 3) - 1) & 0x0F];
|
||||||
i--;
|
y--;
|
||||||
} while (i > sDexCryScreen->unk12);
|
} while (y > sDexCryScreen->waveformPreviousY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Current point higher than previous point, draw point and draw line down to previous
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
offset = gUnknown_085B8770[a0 & 0x7][i] + (a0 / 8) * TILE_SIZE_4BPP;
|
offset = sWaveformOffsets[PLAYHEAD_POS][y] + PLAY_START_POS * TILE_SIZE_4BPP;
|
||||||
sCryWaveformWindowTiledata[offset] &= gUnknown_085B8C30[r6];
|
sCryWaveformWindowTiledata[offset] &= sWaveformTileDataNybbleMasks[nybble];
|
||||||
sCryWaveformWindowTiledata[offset] |= gUnknown_085B8C32[r6][((i / 3) - 1) & 0x0F];
|
sCryWaveformWindowTiledata[offset] |= sWaveformColor[nybble][((y / 3) - 1) & 0x0F];
|
||||||
i++;
|
y++;
|
||||||
} while (i < sDexCryScreen->unk12);
|
} while (y < sDexCryScreen->waveformPreviousY);
|
||||||
}
|
}
|
||||||
|
|
||||||
sDexCryScreen->unk12 = sp0;
|
sDexCryScreen->waveformPreviousY = currentPointY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sub_8145814(u8 windowId)
|
static void DrawWaveformWindow(u8 windowId)
|
||||||
{
|
{
|
||||||
CopyWindowToVram(windowId, 2);
|
CopyWindowToVram(windowId, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sub_8145824(u8 windowId, s16 arg1, u8 arg2)
|
// rsVertical is leftover from a very different version of this function in RS
|
||||||
|
// In RS, when TRUE it would use VOFS and when FALSE it would use HOFS (only FALSE was used)
|
||||||
|
// Here when TRUE it does nothing
|
||||||
|
static void ShiftWaveformOver(u8 windowId, s16 offset, bool8 rsVertical)
|
||||||
{
|
{
|
||||||
if (!arg2)
|
if (!rsVertical)
|
||||||
{
|
{
|
||||||
u8 bg = GetWindowAttribute(windowId, WINDOW_BG);
|
u8 bg = GetWindowAttribute(windowId, WINDOW_BG);
|
||||||
ChangeBgX(bg, arg1 << 8, 0);
|
ChangeBgX(bg, offset << 8, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool8 LoadCryMeter(struct CryRelatedStruct *arg0, u8 windowId)
|
bool8 LoadCryMeter(struct CryScreenWindow *window, u8 windowId)
|
||||||
{
|
{
|
||||||
bool8 finished = FALSE;
|
bool8 finished = FALSE;
|
||||||
|
|
||||||
switch (gDexCryScreenState)
|
switch (gDexCryScreenState)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if (!sCryVolumeMeter)
|
if (!sCryMeterNeedle)
|
||||||
sCryVolumeMeter = AllocZeroed(sizeof(*sCryVolumeMeter));
|
sCryMeterNeedle = AllocZeroed(sizeof(*sCryMeterNeedle));
|
||||||
|
|
||||||
CopyToWindowPixelBuffer(windowId, sCryMeter_Gfx, 0, 0);
|
CopyToWindowPixelBuffer(windowId, sCryMeter_Gfx, 0, 0);
|
||||||
LoadPalette(sCryMeter_Pal, arg0->paletteNo * 16, 32);
|
LoadPalette(sCryMeter_Pal, window->paletteNo * 16, 32);
|
||||||
gDexCryScreenState++;
|
gDexCryScreenState++;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
LoadSpriteSheets(sCryMeterNeedleSpriteSheets);
|
LoadSpriteSheets(sCryMeterNeedleSpriteSheets);
|
||||||
LoadSpritePalettes(sCryMeterNeedleSpritePalettes);
|
LoadSpritePalettes(sCryMeterNeedleSpritePalettes);
|
||||||
sCryVolumeMeter->needleSpriteId = CreateSprite(&sCryMeterNeedleSpriteTemplate, 40 + arg0->xPos * 8, 56 + arg0->yPos * 8, 1);
|
sCryMeterNeedle->spriteId = CreateSprite(&sCryMeterNeedleSpriteTemplate, 40 + window->xPos * 8, 56 + window->yPos * 8, 1);
|
||||||
sCryVolumeMeter->unk0 = 32;
|
sCryMeterNeedle->rotation = MIN_NEEDLE_POS;
|
||||||
sCryVolumeMeter->unk1 = 32;
|
sCryMeterNeedle->targetRotation = MIN_NEEDLE_POS;
|
||||||
sCryVolumeMeter->unk2 = 0;
|
sCryMeterNeedle->moveIncrement = 0;
|
||||||
finished = TRUE;
|
finished = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -438,92 +477,102 @@ bool8 LoadCryMeter(struct CryRelatedStruct *arg0, u8 windowId)
|
|||||||
|
|
||||||
void FreeCryScreen(void)
|
void FreeCryScreen(void)
|
||||||
{
|
{
|
||||||
FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(gSprites[sCryVolumeMeter->needleSpriteId].oam.paletteNum));
|
FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(gSprites[sCryMeterNeedle->spriteId].oam.paletteNum));
|
||||||
DestroySprite(gSprites + sCryVolumeMeter->needleSpriteId);
|
DestroySprite(gSprites + sCryMeterNeedle->spriteId);
|
||||||
FREE_AND_SET_NULL(sDexCryScreen);
|
FREE_AND_SET_NULL(sDexCryScreen);
|
||||||
FREE_AND_SET_NULL(sCryVolumeMeter);
|
FREE_AND_SET_NULL(sCryMeterNeedle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SpriteCB_CryMeterNeedle(struct Sprite *sprite)
|
static void SpriteCB_CryMeterNeedle(struct Sprite *sprite)
|
||||||
{
|
{
|
||||||
u16 i;
|
u16 i;
|
||||||
s8 r3;
|
s8 peakAmplitude;
|
||||||
s16 x;
|
s16 x;
|
||||||
s16 y;
|
s16 y;
|
||||||
struct ObjAffineSrcData affine;
|
struct ObjAffineSrcData affine;
|
||||||
struct OamMatrix matrix;
|
struct OamMatrix matrix;
|
||||||
u8 *var0;
|
u8 amplitude;
|
||||||
|
|
||||||
gSprites[sCryVolumeMeter->needleSpriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
|
gSprites[sCryMeterNeedle->spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
|
||||||
gSprites[sCryVolumeMeter->needleSpriteId].oam.affineParam = 0;
|
gSprites[sCryMeterNeedle->spriteId].oam.affineParam = 0;
|
||||||
switch (sDexCryScreen->unk10)
|
|
||||||
|
// While no cry is playing, cryState is 0
|
||||||
|
// While cry is playing, cryState loops 1-8
|
||||||
|
switch (sDexCryScreen->cryState)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
sCryVolumeMeter->unk1 = 32;
|
sCryMeterNeedle->targetRotation = MIN_NEEDLE_POS;
|
||||||
if (sCryVolumeMeter->unk0 > 0)
|
if (sCryMeterNeedle->rotation > 0)
|
||||||
{
|
{
|
||||||
if (sCryVolumeMeter->unk2 != 1)
|
if (sCryMeterNeedle->moveIncrement != 1)
|
||||||
sCryVolumeMeter->unk2--;
|
sCryMeterNeedle->moveIncrement--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sCryVolumeMeter->unk2 = 5;
|
{
|
||||||
|
sCryMeterNeedle->moveIncrement = NEEDLE_MOVE_INCREMENT;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
r3 = 0;
|
peakAmplitude = 0;
|
||||||
for (i = 0; i < ARRAY_COUNT(sDexCryScreen->unk0); i++)
|
for (i = 0; i < ARRAY_COUNT(sDexCryScreen->cryWaveformBuffer); i++)
|
||||||
{
|
{
|
||||||
if (r3 < sDexCryScreen->unk0[i])
|
if (peakAmplitude < sDexCryScreen->cryWaveformBuffer[i])
|
||||||
r3 = sDexCryScreen->unk0[i];
|
peakAmplitude = sDexCryScreen->cryWaveformBuffer[i];
|
||||||
}
|
}
|
||||||
sub_8145B24(r3 * 0xd0 / 0x100);
|
SetCryMeterNeedleTarget(peakAmplitude * 208 / 256);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
var0 = &sDexCryScreen->unk0[10];
|
// To introduce some randomness, needle jumps to set pos in waveform rather than peak
|
||||||
sub_8145B24(*var0 * 0xd0 / 0x100);
|
amplitude = sDexCryScreen->cryWaveformBuffer[10];
|
||||||
|
SetCryMeterNeedleTarget(amplitude * 208 / 256);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sCryVolumeMeter->unk0 == sCryVolumeMeter->unk1)
|
if (sCryMeterNeedle->rotation == sCryMeterNeedle->targetRotation)
|
||||||
{
|
{
|
||||||
// empty block
|
// Empty, needle has reached target
|
||||||
}
|
}
|
||||||
else if (sCryVolumeMeter->unk0 < sCryVolumeMeter->unk1)
|
else if (sCryMeterNeedle->rotation < sCryMeterNeedle->targetRotation)
|
||||||
{
|
{
|
||||||
sCryVolumeMeter->unk0 += sCryVolumeMeter->unk2;
|
// Rotate needle left
|
||||||
if (sCryVolumeMeter->unk0 > sCryVolumeMeter->unk1)
|
sCryMeterNeedle->rotation += sCryMeterNeedle->moveIncrement;
|
||||||
|
if (sCryMeterNeedle->rotation > sCryMeterNeedle->targetRotation)
|
||||||
{
|
{
|
||||||
sCryVolumeMeter->unk0 = sCryVolumeMeter->unk1;
|
sCryMeterNeedle->rotation = sCryMeterNeedle->targetRotation;
|
||||||
sCryVolumeMeter->unk1 = 0;
|
sCryMeterNeedle->targetRotation = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sCryVolumeMeter->unk0 -= sCryVolumeMeter->unk2;
|
// Rotate needle right
|
||||||
if (sCryVolumeMeter->unk0 < sCryVolumeMeter->unk1)
|
sCryMeterNeedle->rotation -= sCryMeterNeedle->moveIncrement;
|
||||||
|
if (sCryMeterNeedle->rotation < sCryMeterNeedle->targetRotation)
|
||||||
{
|
{
|
||||||
sCryVolumeMeter->unk0 = sCryVolumeMeter->unk1;
|
sCryMeterNeedle->rotation = sCryMeterNeedle->targetRotation;
|
||||||
sCryVolumeMeter->unk1 = 0;
|
sCryMeterNeedle->targetRotation = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
affine.xScale = 0x100;
|
affine.xScale = 256;
|
||||||
affine.yScale = 0x100;
|
affine.yScale = 256;
|
||||||
affine.rotation = sCryVolumeMeter->unk0 * 256;
|
affine.rotation = sCryMeterNeedle->rotation * 256;
|
||||||
ObjAffineSet(&affine, &matrix, 1, 2);
|
ObjAffineSet(&affine, &matrix, 1, 2);
|
||||||
SetOamMatrix(0, matrix.a, matrix.b, matrix.c, matrix.d);
|
SetOamMatrix(0, matrix.a, matrix.b, matrix.c, matrix.d);
|
||||||
x = gSineTable[((sCryVolumeMeter->unk0 + 0x7F) & 0xFF)];
|
x = gSineTable[((sCryMeterNeedle->rotation + 0x7F) & 0xFF)];
|
||||||
y = gSineTable[((sCryVolumeMeter->unk0 + 0x7F) & 0xFF) + 64];
|
y = gSineTable[((sCryMeterNeedle->rotation + 0x7F) & 0xFF) + 64];
|
||||||
sprite->pos2.x = x * 24 / 256;
|
sprite->pos2.x = x * 24 / 256;
|
||||||
sprite->pos2.y = y * 24 / 256;
|
sprite->pos2.y = y * 24 / 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sub_8145B24(s8 a0)
|
static void SetCryMeterNeedleTarget(s8 offset)
|
||||||
{
|
{
|
||||||
u16 r2 = (0x20 - a0) & 0xff;
|
u16 rotation = (MIN_NEEDLE_POS - offset) & 0xFF;
|
||||||
if (r2 > 0x20 && r2 < 0xe0)
|
|
||||||
r2 = 0xe0;
|
|
||||||
|
|
||||||
sCryVolumeMeter->unk1 = r2;
|
// Min is positive, max is negative. Make sure needle hasnt moved out of bounds
|
||||||
sCryVolumeMeter->unk2 = 5;
|
if (rotation > MIN_NEEDLE_POS && rotation < (u8)MAX_NEEDLE_POS)
|
||||||
|
rotation = (u8)MAX_NEEDLE_POS;
|
||||||
|
|
||||||
|
sCryMeterNeedle->targetRotation = rotation;
|
||||||
|
sCryMeterNeedle->moveIncrement = NEEDLE_MOVE_INCREMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user