405 lines
14 KiB
C
405 lines
14 KiB
C
#include "global.h"
|
|
#include "gflib.h"
|
|
#include "menu_indicators.h"
|
|
#include "new_menu_helpers.h"
|
|
#include "mevent.h"
|
|
#include "mystery_gift_menu.h"
|
|
#include "menu.h"
|
|
#include "link_rfu.h"
|
|
#include "list_menu.h"
|
|
#include "constants/mystery_gift.h"
|
|
|
|
enum {
|
|
WIN_TITLE,
|
|
WIN_BODY,
|
|
WIN_COUNT
|
|
};
|
|
|
|
#define TAG_ARROWS 0x1000
|
|
|
|
struct WonderNewsData
|
|
{
|
|
struct WonderNews news;
|
|
const struct WonderGraphics * gfx;
|
|
bool8 verticalScrollDisabled:1;
|
|
u8 enterExitState:7;
|
|
u8 arrowTaskId;
|
|
bool8 scrolling:1;
|
|
u8 scrollIncrement:7;
|
|
bool8 scrollingDown:1;
|
|
u8 scrollTotal:7;
|
|
u16 scrollEnd;
|
|
u16 scrollOffset;
|
|
u16 windowIds[WIN_COUNT];
|
|
u8 unused[2];
|
|
u8 titleText[WONDER_NEWS_TEXT_LENGTH + 1];
|
|
u8 bodyText[WONDER_NEWS_BODY_TEXT_LINES][WONDER_NEWS_TEXT_LENGTH + 1];
|
|
struct ScrollArrowsTemplate arrowsTemplate;
|
|
u8 bgTilemapBuffer[0x1000];
|
|
};
|
|
|
|
static EWRAM_DATA struct WonderNewsData * sWonderNewsData = NULL;
|
|
|
|
static void BufferNewsText(void);
|
|
static void DrawNewsWindows(void);
|
|
static void UpdateNewsScroll(void);
|
|
|
|
static const u8 sTextColorTable[][3] = {
|
|
{0, 2, 3},
|
|
{0, 1, 2}
|
|
};
|
|
static const struct WindowTemplate sWindowTemplates[] = {
|
|
[WIN_TITLE] = {
|
|
.bg = 0,
|
|
.tilemapLeft = 1,
|
|
.tilemapTop = 0,
|
|
.width = 28,
|
|
.height = 3,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x000
|
|
},
|
|
[WIN_BODY] = {
|
|
.bg = 2,
|
|
.tilemapLeft = 1,
|
|
.tilemapTop = 3,
|
|
.width = 28,
|
|
.height = 20,
|
|
.paletteNum = 15,
|
|
.baseBlock = 0x000
|
|
}
|
|
};
|
|
static const struct ScrollArrowsTemplate sArrowsTemplate = {
|
|
.firstArrowType = SCROLL_ARROW_UP,
|
|
.firstX = 232,
|
|
.firstY = 24,
|
|
.secondArrowType = SCROLL_ARROW_DOWN,
|
|
.secondX = 232,
|
|
.secondY = 152,
|
|
.fullyUpThreshold = 0,
|
|
.fullyDownThreshold = 2,
|
|
.tileTag = TAG_ARROWS,
|
|
.palTag = TAG_ARROWS,
|
|
.palNum = 0
|
|
};
|
|
|
|
static const u16 sNews0Pal[] = INCBIN_U16("graphics/wonder_news/bg0.gbapal");
|
|
static const u16 sNews6Pal[] = INCBIN_U16("graphics/wonder_news/bg6.gbapal");
|
|
static const u16 sNews7Pal[] = INCBIN_U16("graphics/wonder_news/bg7.gbapal");
|
|
static const u8 sNews0Gfx[] = INCBIN_U8("graphics/wonder_news/bg0.4bpp.lz");
|
|
static const u8 sNews0Map[] = INCBIN_U8("graphics/wonder_news/bg0.bin.lz");
|
|
static const u8 sNews1Gfx[] = INCBIN_U8("graphics/wonder_news/bg1.4bpp.lz");
|
|
static const u8 sNews1Map[] = INCBIN_U8("graphics/wonder_news/bg1.bin.lz");
|
|
static const u8 sNews2Gfx[] = INCBIN_U8("graphics/wonder_news/bg2.4bpp.lz");
|
|
static const u8 sNews2Map[] = INCBIN_U8("graphics/wonder_news/bg2.bin.lz");
|
|
static const u8 sNews6Gfx[] = INCBIN_U8("graphics/wonder_news/bg6.4bpp.lz");
|
|
static const u8 sNews6Map[] = INCBIN_U8("graphics/wonder_news/bg6.bin.lz");
|
|
static const u8 sNews7Gfx[] = INCBIN_U8("graphics/wonder_news/bg7.4bpp.lz");
|
|
static const u8 sNews7Map[] = INCBIN_U8("graphics/wonder_news/bg7.bin.lz");
|
|
|
|
static const struct WonderGraphics sNewsGraphics[NUM_WONDER_BGS] = {
|
|
{.titleTextPal = 1, .bodyTextPal = 0, .tiles = sNews0Gfx, .map = sNews0Map, .pal = sNews0Pal},
|
|
{.titleTextPal = 1, .bodyTextPal = 0, .tiles = sNews1Gfx, .map = sNews1Map, .pal = gCard1Pal},
|
|
{.titleTextPal = 1, .bodyTextPal = 0, .tiles = sNews2Gfx, .map = sNews2Map, .pal = gCard2Pal},
|
|
{.titleTextPal = 1, .bodyTextPal = 0, .tiles = sNews2Gfx, .map = sNews2Map, .pal = gCard3Pal},
|
|
{.titleTextPal = 1, .bodyTextPal = 0, .tiles = sNews2Gfx, .map = sNews2Map, .pal = gCard4Pal},
|
|
{.titleTextPal = 1, .bodyTextPal = 0, .tiles = sNews2Gfx, .map = sNews2Map, .pal = gCard5Pal},
|
|
{.titleTextPal = 1, .bodyTextPal = 0, .tiles = sNews6Gfx, .map = sNews6Map, .pal = sNews6Pal},
|
|
{.titleTextPal = 1, .bodyTextPal = 0, .tiles = sNews7Gfx, .map = sNews7Map, .pal = sNews7Pal}
|
|
};
|
|
|
|
bool32 WonderNews_Init(const struct WonderNews * news)
|
|
{
|
|
if (news == NULL)
|
|
return FALSE;
|
|
sWonderNewsData = AllocZeroed(sizeof(*sWonderNewsData));
|
|
if (sWonderNewsData == NULL)
|
|
return FALSE;
|
|
sWonderNewsData->news = *news;
|
|
if (sWonderNewsData->news.bgType >= NUM_WONDER_BGS)
|
|
sWonderNewsData->news.bgType = 0;
|
|
sWonderNewsData->gfx = &sNewsGraphics[sWonderNewsData->news.bgType];
|
|
sWonderNewsData->arrowTaskId = TASK_NONE;
|
|
return TRUE;
|
|
}
|
|
|
|
void WonderNews_Destroy(void)
|
|
{
|
|
if (sWonderNewsData != NULL)
|
|
{
|
|
*sWonderNewsData = (struct WonderNewsData){};
|
|
FREE_AND_SET_NULL(sWonderNewsData);
|
|
}
|
|
}
|
|
|
|
s32 WonderNews_Enter(void)
|
|
{
|
|
if (sWonderNewsData == NULL)
|
|
return -1;
|
|
|
|
switch (sWonderNewsData->enterExitState)
|
|
{
|
|
case 0:
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
|
break;
|
|
case 1:
|
|
if (UpdatePaletteFade())
|
|
return 0;
|
|
ChangeBgY(0, 0, BG_COORD_SET);
|
|
ChangeBgY(1, 0, BG_COORD_SET);
|
|
ChangeBgY(2, 0, BG_COORD_SET);
|
|
ChangeBgY(3, 0, BG_COORD_SET);
|
|
SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(0, DISPLAY_WIDTH));
|
|
SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(26, 152));
|
|
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ);
|
|
SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG0 | WINOUT_WIN01_BG1 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ);
|
|
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
|
|
break;
|
|
case 2:
|
|
FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
|
|
FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
|
|
FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 20);
|
|
FillBgTilemapBufferRect_Palette0(3, 0x000, 0, 0, 30, 20);
|
|
CopyBgTilemapBufferToVram(0);
|
|
CopyBgTilemapBufferToVram(1);
|
|
CopyBgTilemapBufferToVram(2);
|
|
CopyBgTilemapBufferToVram(3);
|
|
DecompressAndCopyTileDataToVram(3, sWonderNewsData->gfx->tiles, 0, 8, 0);
|
|
sWonderNewsData->windowIds[WIN_TITLE] = AddWindow(&sWindowTemplates[WIN_TITLE]);
|
|
sWonderNewsData->windowIds[WIN_BODY] = AddWindow(&sWindowTemplates[WIN_BODY]);
|
|
break;
|
|
case 3:
|
|
if (FreeTempTileDataBuffersIfPossible())
|
|
return 0;
|
|
gPaletteFade.bufferTransferDisabled = TRUE;
|
|
LoadPalette(sWonderNewsData->gfx->pal, 0x10, 0x20);
|
|
LZ77UnCompWram(sWonderNewsData->gfx->map, sWonderNewsData->bgTilemapBuffer);
|
|
CopyRectToBgTilemapBufferRect(1, sWonderNewsData->bgTilemapBuffer, 0, 0, 30, 3, 0, 0, 30, 3, 1, 8, 0);
|
|
CopyRectToBgTilemapBufferRect(3, sWonderNewsData->bgTilemapBuffer, 0, 3, 30, 23, 0, 3, 30, 23, 1, 8, 0);
|
|
CopyBgTilemapBufferToVram(1);
|
|
CopyBgTilemapBufferToVram(3);
|
|
break;
|
|
case 4:
|
|
BufferNewsText();
|
|
break;
|
|
case 5:
|
|
DrawNewsWindows();
|
|
CopyBgTilemapBufferToVram(0);
|
|
CopyBgTilemapBufferToVram(2);
|
|
break;
|
|
case 6:
|
|
ShowBg(1);
|
|
ShowBg(2);
|
|
ShowBg(3);
|
|
gPaletteFade.bufferTransferDisabled = FALSE;
|
|
sWonderNewsData->arrowTaskId = AddScrollIndicatorArrowPair(&sWonderNewsData->arrowsTemplate, &sWonderNewsData->scrollOffset);
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
|
|
UpdatePaletteFade();
|
|
break;
|
|
default:
|
|
if (UpdatePaletteFade())
|
|
return 0;
|
|
sWonderNewsData->enterExitState = 0;
|
|
return 1;
|
|
}
|
|
|
|
sWonderNewsData->enterExitState++;
|
|
return 0;
|
|
}
|
|
|
|
s32 WonderNews_Exit(bool32 useCancel)
|
|
{
|
|
if (sWonderNewsData == NULL)
|
|
return -1;
|
|
switch (sWonderNewsData->enterExitState)
|
|
{
|
|
case 0:
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
|
|
break;
|
|
case 1:
|
|
if (UpdatePaletteFade())
|
|
return 0;
|
|
ChangeBgY(2, 0, BG_COORD_SET);
|
|
SetGpuReg(REG_OFFSET_WIN0H, 0);
|
|
SetGpuReg(REG_OFFSET_WIN0V, 0);
|
|
SetGpuReg(REG_OFFSET_WININ, 0);
|
|
SetGpuReg(REG_OFFSET_WINOUT, 0);
|
|
ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
|
|
break;
|
|
case 2:
|
|
FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
|
|
FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
|
|
FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 24);
|
|
FillBgTilemapBufferRect_Palette0(3, 0x000, 0, 0, 30, 24);
|
|
CopyBgTilemapBufferToVram(0);
|
|
CopyBgTilemapBufferToVram(1);
|
|
CopyBgTilemapBufferToVram(2);
|
|
CopyBgTilemapBufferToVram(3);
|
|
break;
|
|
case 3:
|
|
HideBg(1);
|
|
HideBg(2);
|
|
RemoveWindow(sWonderNewsData->windowIds[WIN_BODY]);
|
|
RemoveWindow(sWonderNewsData->windowIds[WIN_TITLE]);
|
|
break;
|
|
case 4:
|
|
ChangeBgY(2, 0, BG_COORD_SET);
|
|
ChangeBgY(3, 0, BG_COORD_SET);
|
|
if (sWonderNewsData->arrowTaskId != TASK_NONE)
|
|
{
|
|
RemoveScrollIndicatorArrowPair(sWonderNewsData->arrowTaskId);
|
|
sWonderNewsData->arrowTaskId = TASK_NONE;
|
|
}
|
|
break;
|
|
case 5:
|
|
PrintMysteryGiftOrEReaderTopMenu(gGiftIsFromEReader, useCancel);
|
|
break;
|
|
case 6:
|
|
MG_DrawCheckerboardPattern();
|
|
CopyBgTilemapBufferToVram(0);
|
|
CopyBgTilemapBufferToVram(3);
|
|
BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
|
|
break;
|
|
default:
|
|
if (UpdatePaletteFade())
|
|
return 0;
|
|
sWonderNewsData->enterExitState = 0;
|
|
return 1;
|
|
}
|
|
++sWonderNewsData->enterExitState;
|
|
return 0;
|
|
}
|
|
|
|
void WonderNews_RemoveScrollIndicatorArrowPair(void)
|
|
{
|
|
if (!sWonderNewsData->verticalScrollDisabled && sWonderNewsData->arrowTaskId != TASK_NONE)
|
|
{
|
|
RemoveScrollIndicatorArrowPair(sWonderNewsData->arrowTaskId);
|
|
sWonderNewsData->arrowTaskId = TASK_NONE;
|
|
sWonderNewsData->verticalScrollDisabled = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
void WonderNews_AddScrollIndicatorArrowPair(void)
|
|
{
|
|
if (sWonderNewsData->verticalScrollDisabled)
|
|
{
|
|
sWonderNewsData->arrowTaskId = AddScrollIndicatorArrowPair(&sWonderNewsData->arrowsTemplate, &sWonderNewsData->scrollOffset);
|
|
sWonderNewsData->verticalScrollDisabled = FALSE;
|
|
}
|
|
}
|
|
|
|
u32 WonderNews_GetInput(u16 input)
|
|
{
|
|
if (sWonderNewsData->scrolling)
|
|
{
|
|
UpdateNewsScroll();
|
|
return NEWS_INPUT_NONE;
|
|
}
|
|
switch (input)
|
|
{
|
|
case A_BUTTON:
|
|
return NEWS_INPUT_A;
|
|
case B_BUTTON:
|
|
return NEWS_INPUT_B;
|
|
case DPAD_UP:
|
|
if (sWonderNewsData->scrollOffset == 0)
|
|
return NEWS_INPUT_NONE;
|
|
if (sWonderNewsData->verticalScrollDisabled)
|
|
return NEWS_INPUT_NONE;
|
|
sWonderNewsData->scrollingDown = FALSE;
|
|
break;
|
|
case DPAD_DOWN:
|
|
if (sWonderNewsData->scrollOffset == sWonderNewsData->scrollEnd)
|
|
return NEWS_INPUT_NONE;
|
|
if (sWonderNewsData->verticalScrollDisabled)
|
|
return NEWS_INPUT_NONE;
|
|
sWonderNewsData->scrollingDown = TRUE;
|
|
break;
|
|
default:
|
|
return NEWS_INPUT_NONE;
|
|
}
|
|
|
|
// Init scroll
|
|
sWonderNewsData->scrolling = TRUE;
|
|
sWonderNewsData->scrollIncrement = 2;
|
|
sWonderNewsData->scrollTotal = 0;
|
|
if (!sWonderNewsData->scrollingDown)
|
|
return NEWS_INPUT_SCROLL_UP;
|
|
else
|
|
return NEWS_INPUT_SCROLL_DOWN;
|
|
}
|
|
|
|
static void BufferNewsText(void)
|
|
{
|
|
u8 i = 0;
|
|
|
|
// Copy title text
|
|
memcpy(sWonderNewsData->titleText, sWonderNewsData->news.titleText, WONDER_NEWS_TEXT_LENGTH);
|
|
sWonderNewsData->titleText[WONDER_NEWS_TEXT_LENGTH] = EOS;
|
|
|
|
// Copy body text
|
|
for (; i < WONDER_NEWS_BODY_TEXT_LINES; i++)
|
|
{
|
|
memcpy(sWonderNewsData->bodyText[i], sWonderNewsData->news.bodyText[i], WONDER_NEWS_TEXT_LENGTH);
|
|
sWonderNewsData->bodyText[i][WONDER_NEWS_TEXT_LENGTH] = EOS;
|
|
if (i > 7 && sWonderNewsData->bodyText[i][0] != EOS)
|
|
sWonderNewsData->scrollEnd++;
|
|
}
|
|
sWonderNewsData->arrowsTemplate = sArrowsTemplate;
|
|
sWonderNewsData->arrowsTemplate.fullyDownThreshold = sWonderNewsData->scrollEnd;
|
|
}
|
|
|
|
static void DrawNewsWindows(void)
|
|
{
|
|
u8 i = 0;
|
|
s32 x;
|
|
PutWindowTilemap(sWonderNewsData->windowIds[WIN_TITLE]);
|
|
PutWindowTilemap(sWonderNewsData->windowIds[WIN_BODY]);
|
|
FillWindowPixelBuffer(sWonderNewsData->windowIds[WIN_TITLE], 0);
|
|
FillWindowPixelBuffer(sWonderNewsData->windowIds[WIN_BODY], 0);
|
|
|
|
// Print title text
|
|
x = (224 - GetStringWidth(FONT_3, sWonderNewsData->titleText, GetFontAttribute(FONT_3, FONTATTR_LETTER_SPACING))) / 2;
|
|
if (x < 0)
|
|
x = 0;
|
|
AddTextPrinterParameterized3(sWonderNewsData->windowIds[WIN_TITLE], FONT_3, x, 6, sTextColorTable[sWonderNewsData->gfx->titleTextPal], 0, sWonderNewsData->titleText);
|
|
|
|
// Print body text
|
|
for (; i < WONDER_NEWS_BODY_TEXT_LINES; ++i)
|
|
{
|
|
AddTextPrinterParameterized3(sWonderNewsData->windowIds[WIN_BODY], FONT_3, 0,
|
|
16 * i + 2,
|
|
sTextColorTable[sWonderNewsData->gfx->bodyTextPal],
|
|
0, sWonderNewsData->bodyText[i]);
|
|
}
|
|
CopyWindowToVram(sWonderNewsData->windowIds[WIN_TITLE], COPYWIN_FULL);
|
|
CopyWindowToVram(sWonderNewsData->windowIds[WIN_BODY], COPYWIN_FULL);
|
|
}
|
|
|
|
static void UpdateNewsScroll(void)
|
|
{
|
|
u16 bgMove = sWonderNewsData->scrollIncrement;
|
|
bgMove *= 256;
|
|
if (sWonderNewsData->scrollingDown)
|
|
{
|
|
ChangeBgY(2, bgMove, BG_COORD_ADD);
|
|
ChangeBgY(3, bgMove, BG_COORD_ADD);
|
|
}
|
|
else
|
|
{
|
|
ChangeBgY(2, bgMove, BG_COORD_SUB);
|
|
ChangeBgY(3, bgMove, BG_COORD_SUB);
|
|
}
|
|
sWonderNewsData->scrollTotal += sWonderNewsData->scrollIncrement;
|
|
if (sWonderNewsData->scrollTotal > 15)
|
|
{
|
|
if (sWonderNewsData->scrollingDown)
|
|
sWonderNewsData->scrollOffset++;
|
|
else
|
|
sWonderNewsData->scrollOffset--;
|
|
sWonderNewsData->scrolling = FALSE;
|
|
sWonderNewsData->scrollTotal = 0;
|
|
}
|
|
}
|