summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorultima-soul <akshayjhanji@hotmail.com>2019-04-28 16:55:43 -0700
committerultima-soul <akshayjhanji@hotmail.com>2019-04-28 16:55:43 -0700
commite833d3742325698846eb3d394b41a556a76af711 (patch)
tree68d45add4b819898d3d99064e78a09dbd5ba1c48 /src
parent57603a0d46c785d845a3fa168f94c01dc8b0b253 (diff)
parent523c53506da69eccebb95af1d1cb76803d0fb88f (diff)
Merge branch 'master' into fldeff
Diffstat (limited to 'src')
-rw-r--r--src/blit.c212
-rw-r--r--src/m4a.c1779
-rw-r--r--src/m4a_2.c912
-rw-r--r--src/m4a_4.c545
-rw-r--r--src/menews_jisan.c4
-rw-r--r--src/mevent.c86
-rw-r--r--src/mevent_8145654.c28
-rw-r--r--src/mevent_server.c92
-rw-r--r--src/mystery_gift_menu.c1756
-rw-r--r--src/script.c4
-rw-r--r--src/seagallop.c460
-rw-r--r--src/text.c2
-rw-r--r--src/window.c6
-rw-r--r--src/window_8bpp.c4
14 files changed, 4317 insertions, 1573 deletions
diff --git a/src/blit.c b/src/blit.c
new file mode 100644
index 000000000..969f89900
--- /dev/null
+++ b/src/blit.c
@@ -0,0 +1,212 @@
+#include "global.h"
+#include "blit.h"
+
+void BlitBitmapRect4BitWithoutColorKey(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height)
+{
+ BlitBitmapRect4Bit(src, dst, srcX, srcY, dstX, dstY, width, height, 0xFF);
+}
+
+void BlitBitmapRect4Bit(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey)
+{
+ s32 xEnd;
+ s32 yEnd;
+ s32 multiplierSrcY;
+ s32 multiplierDstY;
+ s32 loopSrcY, loopDstY;
+ s32 loopSrcX, loopDstX;
+ const u8 *pixelsSrc;
+ u8 *pixelsDst;
+ s32 toOrr;
+ s32 toAnd;
+ s32 toShift;
+
+ if (dst->width - dstX < width)
+ xEnd = (dst->width - dstX) + srcX;
+ else
+ xEnd = srcX + width;
+
+ if (dst->height - dstY < height)
+ yEnd = (dst->height - dstY) + srcY;
+ else
+ yEnd = height + srcY;
+
+ multiplierSrcY = (src->width + (src->width & 7)) >> 3;
+ multiplierDstY = (dst->width + (dst->width & 7)) >> 3;
+
+ if (colorKey == 0xFF)
+ {
+ for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
+ {
+ for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
+ {
+ pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1B);
+ pixelsDst = dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX >> 3) << 5) + (((loopDstY >> 3) * multiplierDstY) << 5) + ((u32)(loopDstY << 0x1d) >> 0x1B);
+ toOrr = ((*pixelsSrc >> ((loopSrcX & 1) << 2)) & 0xF);
+ toShift = ((loopDstX & 1) << 2);
+ toOrr <<= toShift;
+ toAnd = 0xF0 >> (toShift);
+ *pixelsDst = toOrr | (*pixelsDst & toAnd);
+ }
+ }
+ }
+ else
+ {
+ for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
+ {
+ for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
+ {
+ pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1B);
+ pixelsDst = dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX >> 3) << 5) + (((loopDstY >> 3) * multiplierDstY) << 5) + ((u32)(loopDstY << 0x1d) >> 0x1B);
+ toOrr = ((*pixelsSrc >> ((loopSrcX & 1) << 2)) & 0xF);
+ if (toOrr != colorKey)
+ {
+ toShift = ((loopDstX & 1) << 2);
+ toOrr <<= toShift;
+ toAnd = 0xF0 >> (toShift);
+ *pixelsDst = toOrr | (*pixelsDst & toAnd);
+ }
+ }
+ }
+ }
+}
+
+void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue)
+{
+ s32 xEnd;
+ s32 yEnd;
+ s32 multiplierY;
+ s32 loopX, loopY;
+
+ xEnd = x + width;
+ if (xEnd > surface->width)
+ xEnd = surface->width;
+
+ yEnd = y + height;
+ if (yEnd > surface->height)
+ yEnd = surface->height;
+
+ multiplierY = (surface->width + (surface->width & 7)) >> 3;
+
+ for (loopY = y; loopY < yEnd; loopY++)
+ {
+ for (loopX = x; loopX < xEnd; loopX++)
+ {
+ u8 *pixels = surface->pixels + ((loopX >> 1) & 3) + ((loopX >> 3) << 5) + (((loopY >> 3) * multiplierY) << 5) + ((u32)(loopY << 0x1d) >> 0x1B);
+ if ((loopX & 1) != 0)
+ {
+ *pixels &= 0xF;
+ *pixels |= fillValue << 4;
+ }
+ else
+ {
+ *pixels &= 0xF0;
+ *pixels |= fillValue;
+ }
+ }
+ }
+}
+
+void BlitBitmapRect4BitTo8Bit(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey, u8 paletteOffset)
+{
+ s32 palOffsetBits;
+ s32 xEnd;
+ s32 yEnd;
+ s32 multiplierSrcY;
+ s32 multiplierDstY;
+ s32 loopSrcY, loopDstY;
+ s32 loopSrcX, loopDstX;
+ const u8 *pixelsSrc;
+ u8 *pixelsDst;
+ s32 colorKeyBits;
+
+ palOffsetBits = (u32)(paletteOffset << 0x1C) >> 0x18;
+ colorKeyBits = (u32)(colorKey << 0x1C) >> 0x18;
+
+ if (dst->width - dstX < width)
+ xEnd = (dst->width - dstX) + srcX;
+ else
+ xEnd = width + srcX;
+
+ if (dst->height - dstY < height)
+ yEnd = (srcY + dst->height) - dstY;
+ else
+ yEnd = srcY + height;
+
+ multiplierSrcY = (src->width + (src->width & 7)) >> 3;
+ multiplierDstY = (dst->width + (dst->width & 7)) >> 3;
+
+ if (colorKey == 0xFF)
+ {
+ for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
+ {
+ pixelsSrc = src->pixels + ((srcX >> 1) & 3) + ((srcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
+ for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
+ {
+ pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a);
+ if (loopSrcX & 1)
+ {
+ *pixelsDst = palOffsetBits + (*pixelsSrc >> 4);
+ }
+ else
+ {
+ pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
+ *pixelsDst = palOffsetBits + (*pixelsSrc & 0xF);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
+ {
+ pixelsSrc = src->pixels + ((srcX >> 1) & 3) + ((srcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
+ for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
+ {
+ if (loopSrcX & 1)
+ {
+ if ((*pixelsSrc & 0xF0) != colorKeyBits)
+ {
+ pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a);
+ *pixelsDst = palOffsetBits + (*pixelsSrc >> 4);
+ }
+ }
+ else
+ {
+ pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b);
+ if ((*pixelsSrc & 0xF) != colorKey)
+ {
+ pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a);
+ *pixelsDst = palOffsetBits + (*pixelsSrc & 0xF);
+ }
+ }
+ }
+ }
+ }
+}
+
+void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue)
+{
+ s32 xEnd;
+ s32 yEnd;
+ s32 multiplierY;
+ s32 loopX, loopY;
+
+ xEnd = x + width;
+ if (xEnd > surface->width)
+ xEnd = surface->width;
+
+ yEnd = y + height;
+ if (yEnd > surface->height)
+ yEnd = surface->height;
+
+ multiplierY = (surface->width + (surface->width & 7)) >> 3;
+
+ for (loopY = y; loopY < yEnd; loopY++)
+ {
+ for (loopX = x; loopX < xEnd; loopX++)
+ {
+ u8 *pixels = surface->pixels + (loopX & 7) + ((loopX >> 3) << 6) + (((loopY >> 3) * multiplierY) << 6) + ((u32)(loopY << 0x1d) >> 0x1a);
+ *pixels = fillValue;
+ }
+ }
+}
diff --git a/src/m4a.c b/src/m4a.c
new file mode 100644
index 000000000..7b4441ca4
--- /dev/null
+++ b/src/m4a.c
@@ -0,0 +1,1779 @@
+#include "gba/m4a_internal.h"
+
+extern const u8 gCgb3Vol[];
+
+#define BSS_CODE __attribute__((section(".bss.code")))
+
+BSS_CODE ALIGNED(4) char SoundMainRAM_Buffer[0x800] = {0};
+
+struct SoundInfo gSoundInfo;
+struct PokemonCrySong gPokemonCrySongs[MAX_POKEMON_CRIES];
+struct MusicPlayerInfo gPokemonCryMusicPlayers[MAX_POKEMON_CRIES];
+void *gMPlayJumpTable[36];
+struct CgbChannel gCgbChans[4];
+struct MusicPlayerTrack gPokemonCryTracks[MAX_POKEMON_CRIES * 2];
+struct PokemonCrySong gPokemonCrySong;
+struct MusicPlayerInfo gMPlayInfo_BGM;
+struct MusicPlayerInfo gMPlayInfo_SE1;
+struct MusicPlayerInfo gMPlayInfo_SE2;
+struct MusicPlayerInfo gMPlayInfo_SE3;
+u8 gMPlayMemAccArea[0x10];
+
+u32 MidiKeyToFreq(struct WaveData *wav, u8 key, u8 fineAdjust)
+{
+ u32 val1;
+ u32 val2;
+ u32 fineAdjustShifted = fineAdjust << 24;
+
+ if (key > 178)
+ {
+ key = 178;
+ fineAdjustShifted = 255 << 24;
+ }
+
+ val1 = gScaleTable[key];
+ val1 = gFreqTable[val1 & 0xF] >> (val1 >> 4);
+
+ val2 = gScaleTable[key + 1];
+ val2 = gFreqTable[val2 & 0xF] >> (val2 >> 4);
+
+ return umul3232H32(wav->freq, val1 + umul3232H32(val2 - val1, fineAdjustShifted));
+}
+
+void UnusedDummyFunc(void)
+{
+}
+
+void MPlayContinue(struct MusicPlayerInfo *mplayInfo)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void MPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->fadeOC = speed;
+ mplayInfo->fadeOI = speed;
+ mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aSoundInit(void)
+{
+ s32 i;
+
+ CpuCopy32((void *)((s32)SoundMainRAM & ~1), SoundMainRAM_Buffer, sizeof(SoundMainRAM_Buffer));
+
+ SoundInit(&gSoundInfo);
+ MPlayExtender(gCgbChans);
+ m4aSoundMode(SOUND_MODE_DA_BIT_8
+ | SOUND_MODE_FREQ_13379
+ | (12 << SOUND_MODE_MASVOL_SHIFT)
+ | (5 << SOUND_MODE_MAXCHN_SHIFT));
+
+ for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
+ {
+ struct MusicPlayerInfo *mplayInfo = gMPlayTable[i].info;
+ MPlayOpen(mplayInfo, gMPlayTable[i].track, gMPlayTable[i].unk_8);
+ mplayInfo->unk_B = gMPlayTable[i].unk_A;
+ mplayInfo->memAccArea = gMPlayMemAccArea;
+ }
+
+ memcpy(&gPokemonCrySong, &gPokemonCrySongTemplate, sizeof(struct PokemonCrySong));
+
+ for (i = 0; i < MAX_POKEMON_CRIES; i++)
+ {
+ struct MusicPlayerInfo *mplayInfo = &gPokemonCryMusicPlayers[i];
+ struct MusicPlayerTrack *track = &gPokemonCryTracks[i * 2];
+ MPlayOpen(mplayInfo, track, 2);
+ track->chan = 0;
+ }
+}
+
+void m4aSoundMain(void)
+{
+ SoundMain();
+}
+
+void m4aSongNumStart(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ MPlayStart(mplay->info, song->header);
+}
+
+void m4aSongNumStartOrChange(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader != song->header)
+ {
+ MPlayStart(mplay->info, song->header);
+ }
+ else
+ {
+ if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0
+ || (mplay->info->status & MUSICPLAYER_STATUS_PAUSE))
+ {
+ MPlayStart(mplay->info, song->header);
+ }
+ }
+}
+
+void m4aSongNumStartOrContinue(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader != song->header)
+ MPlayStart(mplay->info, song->header);
+ else if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0)
+ MPlayStart(mplay->info, song->header);
+ else if (mplay->info->status & MUSICPLAYER_STATUS_PAUSE)
+ MPlayContinue(mplay->info);
+}
+
+void m4aSongNumStop(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader == song->header)
+ m4aMPlayStop(mplay->info);
+}
+
+void m4aSongNumContinue(u16 n)
+{
+ const struct MusicPlayer *mplayTable = gMPlayTable;
+ const struct Song *songTable = gSongTable;
+ const struct Song *song = &songTable[n];
+ const struct MusicPlayer *mplay = &mplayTable[song->ms];
+
+ if (mplay->info->songHeader == song->header)
+ MPlayContinue(mplay->info);
+}
+
+void m4aMPlayAllStop(void)
+{
+ s32 i;
+
+ for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
+ m4aMPlayStop(gMPlayTable[i].info);
+
+ for (i = 0; i < MAX_POKEMON_CRIES; i++)
+ m4aMPlayStop(&gPokemonCryMusicPlayers[i]);
+}
+
+void m4aMPlayContinue(struct MusicPlayerInfo *mplayInfo)
+{
+ MPlayContinue(mplayInfo);
+}
+
+void m4aMPlayAllContinue(void)
+{
+ s32 i;
+
+ for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
+ MPlayContinue(gMPlayTable[i].info);
+
+ for (i = 0; i < MAX_POKEMON_CRIES; i++)
+ MPlayContinue(&gPokemonCryMusicPlayers[i]);
+}
+
+void m4aMPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ MPlayFadeOut(mplayInfo, speed);
+}
+
+void m4aMPlayFadeOutTemporarily(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->fadeOC = speed;
+ mplayInfo->fadeOI = speed;
+ mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT) | TEMPORARY_FADE;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayFadeIn(struct MusicPlayerInfo *mplayInfo, u16 speed)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->fadeOC = speed;
+ mplayInfo->fadeOI = speed;
+ mplayInfo->fadeOV = (0 << FADE_VOL_SHIFT) | FADE_IN;
+ mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayImmInit(struct MusicPlayerInfo *mplayInfo)
+{
+ s32 trackCount = mplayInfo->trackCount;
+ struct MusicPlayerTrack *track = mplayInfo->tracks;
+
+ while (trackCount > 0)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ if (track->flags & MPT_FLG_START)
+ {
+ Clear64byte(track);
+ track->flags = MPT_FLG_EXIST;
+ track->bendRange = 2;
+ track->volX = 64;
+ track->lfoSpeed = 22;
+ track->tone.type = 1;
+ }
+ }
+
+ trackCount--;
+ track++;
+ }
+}
+
+void MPlayExtender(struct CgbChannel *cgbChans)
+{
+ struct SoundInfo *soundInfo;
+ u32 ident;
+
+ REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
+ | SOUND_4_ON
+ | SOUND_3_ON
+ | SOUND_2_ON
+ | SOUND_1_ON;
+ REG_SOUNDCNT_L = 0; // set master volume to zero
+ REG_NR12 = 0x8;
+ REG_NR22 = 0x8;
+ REG_NR42 = 0x8;
+ REG_NR14 = 0x80;
+ REG_NR24 = 0x80;
+ REG_NR44 = 0x80;
+ REG_NR30 = 0;
+ REG_NR50 = 0x77;
+
+ soundInfo = SOUND_INFO_PTR;
+
+ ident = soundInfo->ident;
+
+ if (ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ gMPlayJumpTable[8] = ply_memacc;
+ gMPlayJumpTable[17] = ply_lfos;
+ gMPlayJumpTable[19] = ply_mod;
+ gMPlayJumpTable[28] = ply_xcmd;
+ gMPlayJumpTable[29] = ply_endtie;
+ gMPlayJumpTable[30] = SampleFreqSet;
+ gMPlayJumpTable[31] = TrackStop;
+ gMPlayJumpTable[32] = FadeOutBody;
+ gMPlayJumpTable[33] = TrkVolPitSet;
+
+ soundInfo->cgbChans = (struct CgbChannel *)cgbChans;
+ soundInfo->CgbSound = CgbSound;
+ soundInfo->CgbOscOff = CgbOscOff;
+ soundInfo->MidiKeyToCgbFreq = MidiKeyToCgbFreq;
+ soundInfo->maxLines = MAX_LINES;
+
+ CpuFill32(0, cgbChans, sizeof(struct CgbChannel) * 4);
+
+ cgbChans[0].ty = 1;
+ cgbChans[0].panMask = 0x11;
+ cgbChans[1].ty = 2;
+ cgbChans[1].panMask = 0x22;
+ cgbChans[2].ty = 3;
+ cgbChans[2].panMask = 0x44;
+ cgbChans[3].ty = 4;
+ cgbChans[3].panMask = 0x88;
+
+ soundInfo->ident = ident;
+}
+
+void MusicPlayerJumpTableCopy(void)
+{
+ asm("swi 0x2A");
+}
+
+void ClearChain(void *x)
+{
+ void (*func)(void *) = *(&gMPlayJumpTable[34]);
+ func(x);
+}
+
+void Clear64byte(void *x)
+{
+ void (*func)(void *) = *(&gMPlayJumpTable[35]);
+ func(x);
+}
+
+void SoundInit(struct SoundInfo *soundInfo)
+{
+ soundInfo->ident = 0;
+
+ if (REG_DMA1CNT & (DMA_REPEAT << 16))
+ REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ if (REG_DMA2CNT & (DMA_REPEAT << 16))
+ REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ REG_DMA1CNT_H = DMA_32BIT;
+ REG_DMA2CNT_H = DMA_32BIT;
+ REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
+ | SOUND_4_ON
+ | SOUND_3_ON
+ | SOUND_2_ON
+ | SOUND_1_ON;
+ REG_SOUNDCNT_H = SOUND_B_FIFO_RESET | SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
+ | SOUND_A_FIFO_RESET | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
+ | SOUND_ALL_MIX_FULL;
+ REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | 0x40;
+
+ REG_DMA1SAD = (s32)soundInfo->pcmBuffer;
+ REG_DMA1DAD = (s32)&REG_FIFO_A;
+ REG_DMA2SAD = (s32)soundInfo->pcmBuffer + PCM_DMA_BUF_SIZE;
+ REG_DMA2DAD = (s32)&REG_FIFO_B;
+
+ SOUND_INFO_PTR = soundInfo;
+ CpuFill32(0, soundInfo, sizeof(struct SoundInfo));
+
+ soundInfo->maxChans = 8;
+ soundInfo->masterVolume = 15;
+ soundInfo->plynote = (u32)ply_note;
+ soundInfo->CgbSound = DummyFunc;
+ soundInfo->CgbOscOff = (void (*)(u8))DummyFunc;
+ soundInfo->MidiKeyToCgbFreq = (u32 (*)(u8, u8, u8))DummyFunc;
+ soundInfo->ExtVolPit = (u32)DummyFunc;
+
+ MPlayJumpTableCopy(gMPlayJumpTable);
+
+ soundInfo->MPlayJumpTable = (u32)gMPlayJumpTable;
+
+ SampleFreqSet(SOUND_MODE_FREQ_13379);
+
+ soundInfo->ident = ID_NUMBER;
+}
+
+void SampleFreqSet(u32 freq)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ freq = (freq & 0xF0000) >> 16;
+ soundInfo->freq = freq;
+ soundInfo->pcmSamplesPerVBlank = gPcmSamplesPerVBlankTable[freq - 1];
+ soundInfo->pcmDmaPeriod = PCM_DMA_BUF_SIZE / soundInfo->pcmSamplesPerVBlank;
+
+ // LCD refresh rate 59.7275Hz
+ soundInfo->pcmFreq = (597275 * soundInfo->pcmSamplesPerVBlank + 5000) / 10000;
+
+ // CPU frequency 16.78Mhz
+ soundInfo->divFreq = (16777216 / soundInfo->pcmFreq + 1) >> 1;
+
+ // Turn off timer 0.
+ REG_TM0CNT_H = 0;
+
+ // cycles per LCD fresh 280896
+ REG_TM0CNT_L = -(280896 / soundInfo->pcmSamplesPerVBlank);
+
+ m4aSoundVSyncOn();
+
+ while (*(vu8 *)REG_ADDR_VCOUNT == 159)
+ ;
+
+ while (*(vu8 *)REG_ADDR_VCOUNT != 159)
+ ;
+
+ REG_TM0CNT_H = TIMER_ENABLE | TIMER_1CLK;
+}
+
+void m4aSoundMode(u32 mode)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ u32 temp;
+
+ if (soundInfo->ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ temp = mode & (SOUND_MODE_REVERB_SET | SOUND_MODE_REVERB_VAL);
+
+ if (temp)
+ soundInfo->reverb = temp & SOUND_MODE_REVERB_VAL;
+
+ temp = mode & SOUND_MODE_MAXCHN;
+
+ if (temp)
+ {
+ struct SoundChannel *chan;
+
+ soundInfo->maxChans = temp >> SOUND_MODE_MAXCHN_SHIFT;
+
+ temp = MAX_DIRECTSOUND_CHANNELS;
+ chan = &soundInfo->chans[0];
+
+ while (temp != 0)
+ {
+ chan->status = 0;
+ temp--;
+ chan++;
+ }
+ }
+
+ temp = mode & SOUND_MODE_MASVOL;
+
+ if (temp)
+ soundInfo->masterVolume = temp >> SOUND_MODE_MASVOL_SHIFT;
+
+ temp = mode & SOUND_MODE_DA_BIT;
+
+ if (temp)
+ {
+ temp = (temp & 0x300000) >> 14;
+ REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | temp;
+ }
+
+ temp = mode & SOUND_MODE_FREQ;
+
+ if (temp)
+ {
+ m4aSoundVSyncOff();
+ SampleFreqSet(temp);
+ }
+
+ soundInfo->ident = ID_NUMBER;
+}
+
+void SoundClear(void)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ s32 i;
+ void *chan;
+
+ if (soundInfo->ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ i = MAX_DIRECTSOUND_CHANNELS;
+ chan = &soundInfo->chans[0];
+
+ while (i > 0)
+ {
+ ((struct SoundChannel *)chan)->status = 0;
+ i--;
+ chan = (void *)((s32)chan + sizeof(struct SoundChannel));
+ }
+
+ chan = soundInfo->cgbChans;
+
+ if (chan)
+ {
+ i = 1;
+
+ while (i <= 4)
+ {
+ soundInfo->CgbOscOff(i);
+ ((struct CgbChannel *)chan)->sf = 0;
+ i++;
+ chan = (void *)((s32)chan + sizeof(struct CgbChannel));
+ }
+ }
+
+ soundInfo->ident = ID_NUMBER;
+}
+
+void m4aSoundVSyncOff(void)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ if (soundInfo->ident >= ID_NUMBER && soundInfo->ident <= ID_NUMBER + 1)
+ {
+ soundInfo->ident += 10;
+
+ if (REG_DMA1CNT & (DMA_REPEAT << 16))
+ REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ if (REG_DMA2CNT & (DMA_REPEAT << 16))
+ REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
+
+ REG_DMA1CNT_H = DMA_32BIT;
+ REG_DMA2CNT_H = DMA_32BIT;
+
+ CpuFill32(0, soundInfo->pcmBuffer, sizeof(soundInfo->pcmBuffer));
+ }
+}
+
+void m4aSoundVSyncOn(void)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ u32 ident = soundInfo->ident;
+
+ if (ident == ID_NUMBER)
+ return;
+
+ REG_DMA1CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
+ REG_DMA2CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
+
+ soundInfo->pcmDmaCounter = 0;
+ soundInfo->ident = ident - 10;
+}
+
+void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tracks, u8 trackCount)
+{
+ struct SoundInfo *soundInfo;
+
+ if (trackCount == 0)
+ return;
+
+ if (trackCount > MAX_MUSICPLAYER_TRACKS)
+ trackCount = MAX_MUSICPLAYER_TRACKS;
+
+ soundInfo = SOUND_INFO_PTR;
+
+ if (soundInfo->ident != ID_NUMBER)
+ return;
+
+ soundInfo->ident++;
+
+ Clear64byte(mplayInfo);
+
+ mplayInfo->tracks = tracks;
+ mplayInfo->trackCount = trackCount;
+ mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
+
+ while (trackCount != 0)
+ {
+ tracks->flags = 0;
+ trackCount--;
+ tracks++;
+ }
+
+ if (soundInfo->func != 0)
+ {
+ mplayInfo->func = soundInfo->func;
+ mplayInfo->intp = soundInfo->intp;
+ soundInfo->func = 0;
+ }
+
+ soundInfo->intp = (u32)mplayInfo;
+ soundInfo->func = (u32)MPlayMain;
+ soundInfo->ident = ID_NUMBER;
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader)
+{
+ s32 i;
+ u8 unk_B;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ unk_B = mplayInfo->unk_B;
+
+ if (!unk_B
+ || ((!mplayInfo->songHeader || !(mplayInfo->tracks[0].flags & MPT_FLG_START))
+ && ((mplayInfo->status & MUSICPLAYER_STATUS_TRACK) == 0
+ || (mplayInfo->status & MUSICPLAYER_STATUS_PAUSE)))
+ || (mplayInfo->priority <= songHeader->priority))
+ {
+ mplayInfo->ident++;
+ mplayInfo->status = 0;
+ mplayInfo->songHeader = songHeader;
+ mplayInfo->tone = songHeader->tone;
+ mplayInfo->priority = songHeader->priority;
+ mplayInfo->clock = 0;
+ mplayInfo->tempoD = 150;
+ mplayInfo->tempoI = 150;
+ mplayInfo->tempoU = 0x100;
+ mplayInfo->tempoC = 0;
+ mplayInfo->fadeOI = 0;
+
+ i = 0;
+ track = mplayInfo->tracks;
+
+ while (i < songHeader->trackCount && i < mplayInfo->trackCount)
+ {
+ TrackStop(mplayInfo, track);
+ track->flags = MPT_FLG_EXIST | MPT_FLG_START;
+ track->chan = 0;
+ track->cmdPtr = songHeader->part[i];
+ i++;
+ track++;
+ }
+
+ while (i < mplayInfo->trackCount)
+ {
+ TrackStop(mplayInfo, track);
+ track->flags = 0;
+ i++;
+ track++;
+ }
+
+ if (songHeader->reverb & 0x80)
+ m4aSoundMode(songHeader->reverb);
+
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayStop(struct MusicPlayerInfo *mplayInfo)
+{
+ s32 i;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+ mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+
+ while (i > 0)
+ {
+ TrackStop(mplayInfo, track);
+ i--;
+ track++;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void FadeOutBody(struct MusicPlayerInfo *mplayInfo)
+{
+ s32 i;
+ struct MusicPlayerTrack *track;
+ u16 fadeOV;
+#ifdef NONMATCHING
+ u16 mask;
+#else
+ register u16 mask asm("r2");
+#endif // NONMATCHING
+
+ if (mplayInfo->fadeOI == 0)
+ return;
+
+ mplayInfo->fadeOC--;
+ mask = 0xFFFF;
+
+ if (mplayInfo->fadeOC != 0)
+ return;
+
+ mplayInfo->fadeOC = mplayInfo->fadeOI;
+
+ if (mplayInfo->fadeOV & FADE_IN)
+ {
+ mplayInfo->fadeOV += (4 << FADE_VOL_SHIFT);
+
+ if ((u16)(mplayInfo->fadeOV & mask) >= (64 << FADE_VOL_SHIFT))
+ {
+ mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
+ mplayInfo->fadeOI = 0;
+ }
+ }
+ else
+ {
+ mplayInfo->fadeOV -= (4 << FADE_VOL_SHIFT);
+
+ if ((s16)(mplayInfo->fadeOV & mask) <= 0)
+ {
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+
+ while (i > 0)
+ {
+ u32 val;
+
+ TrackStop(mplayInfo, track);
+
+ val = TEMPORARY_FADE;
+ fadeOV = mplayInfo->fadeOV;
+ val &= fadeOV;
+
+ if (!val)
+ track->flags = 0;
+
+ i--;
+ track++;
+ }
+
+ if (mplayInfo->fadeOV & TEMPORARY_FADE)
+ mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
+ else
+ mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
+
+ mplayInfo->fadeOI = 0;
+ return;
+ }
+ }
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+
+ while (i > 0)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ fadeOV = mplayInfo->fadeOV;
+
+ track->volX = (fadeOV >> FADE_VOL_SHIFT);
+ track->flags |= MPT_FLG_VOLCHG;
+ }
+
+ i--;
+ track++;
+ }
+}
+
+void TrkVolPitSet(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ if (track->flags & MPT_FLG_VOLSET)
+ {
+ s32 x;
+ s32 y;
+
+ x = (u32)(track->vol * track->volX) >> 5;
+
+ if (track->modT == 1)
+ x = (u32)(x * (track->modM + 128)) >> 7;
+
+ y = 2 * track->pan + track->panX;
+
+ if (track->modT == 2)
+ y += track->modM;
+
+ if (y < -128)
+ y = -128;
+ else if (y > 127)
+ y = 127;
+
+ track->volMR = (u32)((y + 128) * x) >> 8;
+ track->volML = (u32)((127 - y) * x) >> 8;
+ }
+
+ if (track->flags & MPT_FLG_PITSET)
+ {
+ s32 bend = track->bend * track->bendRange;
+ s32 x = (track->tune + bend)
+ * 4
+ + (track->keyShift << 8)
+ + (track->keyShiftX << 8)
+ + track->pitX;
+
+ if (track->modT == 0)
+ x += 16 * track->modM;
+
+ track->keyM = x >> 8;
+ track->pitM = x;
+ }
+
+ track->flags &= ~(MPT_FLG_PITSET | MPT_FLG_VOLSET);
+}
+
+u32 MidiKeyToCgbFreq(u8 chanNum, u8 key, u8 fineAdjust)
+{
+ if (chanNum == 4)
+ {
+ if (key <= 20)
+ {
+ key = 0;
+ }
+ else
+ {
+ key -= 21;
+ if (key > 59)
+ key = 59;
+ }
+
+ return gNoiseTable[key];
+ }
+ else
+ {
+ s32 val1;
+ s32 val2;
+
+ if (key <= 35)
+ {
+ fineAdjust = 0;
+ key = 0;
+ }
+ else
+ {
+ key -= 36;
+ if (key > 130)
+ {
+ key = 130;
+ fineAdjust = 255;
+ }
+ }
+
+ val1 = gCgbScaleTable[key];
+ val1 = gCgbFreqTable[val1 & 0xF] >> (val1 >> 4);
+
+ val2 = gCgbScaleTable[key + 1];
+ val2 = gCgbFreqTable[val2 & 0xF] >> (val2 >> 4);
+
+ return val1 + ((fineAdjust * (val2 - val1)) >> 8) + 2048;
+ }
+}
+
+void CgbOscOff(u8 chanNum)
+{
+ switch (chanNum)
+ {
+ case 1:
+ REG_NR12 = 8;
+ REG_NR14 = 0x80;
+ break;
+ case 2:
+ REG_NR22 = 8;
+ REG_NR24 = 0x80;
+ break;
+ case 3:
+ REG_NR30 = 0;
+ break;
+ default:
+ REG_NR42 = 8;
+ REG_NR44 = 0x80;
+ }
+}
+
+static inline int CgbPan(struct CgbChannel *chan)
+{
+ u32 rightVolume = chan->rightVolume;
+ u32 leftVolume = chan->leftVolume;
+
+ if ((rightVolume = (u8)rightVolume) >= (leftVolume = (u8)leftVolume))
+ {
+ if (rightVolume / 2 >= leftVolume)
+ {
+ chan->pan = 0x0F;
+ return 1;
+ }
+ }
+ else
+ {
+ if (leftVolume / 2 >= rightVolume)
+ {
+ chan->pan = 0xF0;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void CgbModVol(struct CgbChannel *chan)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ if ((soundInfo->mode & 1) || !CgbPan(chan))
+ {
+ chan->pan = 0xFF;
+ chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4;
+ }
+ else
+ {
+ // Force chan->rightVolume and chan->leftVolume to be read from memory again,
+ // even though there is no reason to do so.
+ // The command line option "-fno-gcse" achieves the same result as this.
+ asm("" : : : "memory");
+
+ chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4;
+ if (chan->eg > 15)
+ chan->eg = 15;
+ }
+
+ chan->sg = (chan->eg * chan->su + 15) >> 4;
+ chan->pan &= chan->panMask;
+}
+
+void CgbSound(void)
+{
+ s32 ch;
+ struct CgbChannel *channels;
+ s32 evAdd;
+ s32 prevC15;
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+ vu8 *nrx0ptr;
+ vu8 *nrx1ptr;
+ vu8 *nrx2ptr;
+ vu8 *nrx3ptr;
+ vu8 *nrx4ptr;
+
+ // Most comparision operations that cast to s8 perform 'and' by 0xFF.
+ int mask = 0xff;
+
+ if (soundInfo->c15)
+ soundInfo->c15--;
+ else
+ soundInfo->c15 = 14;
+
+ for (ch = 1, channels = soundInfo->cgbChans; ch <= 4; ch++, channels++)
+ {
+ if (!(channels->sf & 0xc7))
+ continue;
+
+ switch (ch)
+ {
+ case 1:
+ nrx0ptr = (vu8 *)(REG_ADDR_NR10);
+ nrx1ptr = (vu8 *)(REG_ADDR_NR11);
+ nrx2ptr = (vu8 *)(REG_ADDR_NR12);
+ nrx3ptr = (vu8 *)(REG_ADDR_NR13);
+ nrx4ptr = (vu8 *)(REG_ADDR_NR14);
+ break;
+ case 2:
+ nrx0ptr = (vu8 *)(REG_ADDR_NR10+1);
+ nrx1ptr = (vu8 *)(REG_ADDR_NR21);
+ nrx2ptr = (vu8 *)(REG_ADDR_NR22);
+ nrx3ptr = (vu8 *)(REG_ADDR_NR23);
+ nrx4ptr = (vu8 *)(REG_ADDR_NR24);
+ break;
+ case 3:
+ nrx0ptr = (vu8 *)(REG_ADDR_NR30);
+ nrx1ptr = (vu8 *)(REG_ADDR_NR31);
+ nrx2ptr = (vu8 *)(REG_ADDR_NR32);
+ nrx3ptr = (vu8 *)(REG_ADDR_NR33);
+ nrx4ptr = (vu8 *)(REG_ADDR_NR34);
+ break;
+ default:
+ nrx0ptr = (vu8 *)(REG_ADDR_NR30+1);
+ nrx1ptr = (vu8 *)(REG_ADDR_NR41);
+ nrx2ptr = (vu8 *)(REG_ADDR_NR42);
+ nrx3ptr = (vu8 *)(REG_ADDR_NR43);
+ nrx4ptr = (vu8 *)(REG_ADDR_NR44);
+ break;
+ }
+
+ prevC15 = soundInfo->c15;
+ evAdd = *nrx2ptr;
+
+ if (channels->sf & 0x80)
+ {
+ if (!(channels->sf & 0x40))
+ {
+ channels->sf = 3;
+ channels->mo = 3;
+ CgbModVol(channels);
+ switch (ch)
+ {
+ case 1:
+ *nrx0ptr = channels->sw;
+ // fallthrough
+ case 2:
+ *nrx1ptr = ((u32)channels->wp << 6) + channels->le;
+ goto loc_82E0E30;
+ case 3:
+ if ((u32)channels->wp != channels->cp)
+ {
+ *nrx0ptr = 0x40;
+ REG_WAVE_RAM0 = channels->wp[0];
+ REG_WAVE_RAM1 = channels->wp[1];
+ REG_WAVE_RAM2 = channels->wp[2];
+ REG_WAVE_RAM3 = channels->wp[3];
+ channels->cp = (u32)channels->wp;
+ }
+ *nrx0ptr = 0;
+ *nrx1ptr = channels->le;
+ if (channels->le)
+ channels->n4 = -64;
+ else
+ channels->n4 = -128;
+ break;
+ default:
+ *nrx1ptr = channels->le;
+ *nrx3ptr = (u32)channels->wp << 3;
+ loc_82E0E30:
+ evAdd = channels->at + 8;
+ if (channels->le)
+ channels->n4 = 64;
+ else
+ channels->n4 = 0;
+ break;
+ }
+ channels->ec = channels->at;
+ if ((s8)(channels->at & mask))
+ {
+ channels->ev = 0;
+ goto EC_MINUS;
+ }
+ else
+ {
+ goto loc_82E0F96;
+ }
+ }
+ else
+ {
+ goto loc_82E0E82;
+ }
+ }
+ else if (channels->sf & 0x04)
+ {
+ channels->echoLength--;
+ if ((s8)(channels->echoLength & mask) <= 0)
+ {
+ loc_82E0E82:
+ CgbOscOff(ch);
+ channels->sf = 0;
+ goto LAST_LABEL;
+ }
+ goto loc_82E0FD6;
+ }
+ else if ((channels->sf & 0x40) && (channels->sf & 0x03))
+ {
+ channels->sf &= 0xfc;
+ channels->ec = channels->re;
+ if ((s8)(channels->re & mask))
+ {
+ channels->mo |= 1;
+ if (ch != 3)
+ {
+ evAdd = channels->re;
+ }
+ goto EC_MINUS;
+ }
+ else
+ {
+ goto loc_82E0F02;
+ }
+ }
+ else
+ {
+ loc_82E0ED0:
+ if (channels->ec == 0)
+ {
+ if (ch == 3)
+ {
+ channels->mo |= 1;
+ }
+ CgbModVol(channels);
+ if ((channels->sf & 0x3) == 0)
+ {
+ channels->ev--;
+ if ((s8)(channels->ev & mask) <= 0)
+ {
+ loc_82E0F02:
+ channels->ev = ((channels->eg * channels->echoVolume) + 0xFF) >> 8;
+ if (channels->ev)
+ {
+ channels->sf |= 0x4;
+ channels->mo |= 1;
+ if (ch != 3)
+ {
+ evAdd = 8;
+ }
+ goto loc_82E0FD6;
+ }
+ else
+ {
+ goto loc_82E0E82;
+ }
+ }
+ else
+ {
+ channels->ec = channels->re;
+ }
+ }
+ else if ((channels->sf & 0x3) == 1)
+ {
+ loc_82E0F3A:
+ channels->ev = channels->sg;
+ channels->ec = 7;
+ }
+ else if ((channels->sf & 0x3) == 2)
+ {
+ int ev, sg;
+
+ channels->ev--;
+ ev = (s8)(channels->ev & mask);
+ sg = (s8)(channels->sg);
+ if (ev <= sg)
+ {
+ loc_82E0F5A:
+ if (channels->su == 0)
+ {
+ channels->sf &= 0xfc;
+ goto loc_82E0F02;
+ }
+ else
+ {
+ channels->sf--;
+ channels->mo |= 1;
+ if (ch != 3)
+ {
+ evAdd = 8;
+ }
+ goto loc_82E0F3A;
+ }
+ }
+ else
+ {
+ channels->ec = channels->de;
+ }
+ }
+ else
+ {
+ channels->ev++;
+ if ((u8)(channels->ev & mask) >= channels->eg)
+ {
+ loc_82E0F96:
+ channels->sf--;
+ channels->ec = channels->de;
+ if ((u8)(channels->ec & mask))
+ {
+ channels->mo |= 1;
+ channels->ev = channels->eg;
+ if (ch != 3)
+ {
+ evAdd = channels->de;
+ }
+ }
+ else
+ {
+ goto loc_82E0F5A;
+ }
+ }
+ else
+ {
+ channels->ec = channels->at;
+ }
+ }
+ }
+ }
+
+ EC_MINUS:
+ channels->ec--;
+ if (prevC15 == 0)
+ {
+ prevC15--;
+ goto loc_82E0ED0;
+ }
+
+ loc_82E0FD6:
+ if (channels->mo & 0x2)
+ {
+ if (ch < 4 && (channels->ty & 0x08))
+ {
+ int biasH = REG_SOUNDBIAS_H;
+
+ if (biasH < 64)
+ {
+ channels->fr = (channels->fr + 2) & 0x7fc;
+ }
+ else if (biasH < 128)
+ {
+ channels->fr = (channels->fr + 1) & 0x7fe;
+ }
+ }
+ if (ch != 4)
+ {
+ *nrx3ptr = channels->fr;
+ }
+ else
+ {
+ *nrx3ptr = (*nrx3ptr & 0x08) | channels->fr;
+ }
+ channels->n4 = (channels->n4 & 0xC0) + (*((u8*)(&channels->fr) + 1));
+ *nrx4ptr = (s8)(channels->n4 & mask);
+ }
+
+ if (channels->mo & 1)
+ {
+ REG_NR51 = (REG_NR51 & ~channels->panMask) | channels->pan;
+ if (ch == 3)
+ {
+ *nrx2ptr = gCgb3Vol[channels->ev];
+ if (channels->n4 & 0x80)
+ {
+ *nrx0ptr = 0x80;
+ *nrx4ptr = channels->n4;
+ channels->n4 &= 0x7f;
+ }
+ }
+ else
+ {
+ evAdd &= 0xf;
+ *nrx2ptr = (channels->ev << 4) + evAdd;
+ *nrx4ptr = channels->n4 | 0x80;
+ if (ch == 1 && !(*nrx0ptr & 0x08))
+ {
+ *nrx4ptr = channels->n4 | 0x80;
+ }
+ }
+ }
+
+ LAST_LABEL:
+ channels->mo = 0;
+ }
+}
+
+void m4aMPlayTempoControl(struct MusicPlayerInfo *mplayInfo, u16 tempo)
+{
+ if (mplayInfo->ident == ID_NUMBER)
+ {
+ mplayInfo->ident++;
+ mplayInfo->tempoU = tempo;
+ mplayInfo->tempoI = (mplayInfo->tempoD * mplayInfo->tempoU) >> 8;
+ mplayInfo->ident = ID_NUMBER;
+ }
+}
+
+void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->volX = volume / 4;
+ track->flags |= MPT_FLG_VOLCHG;
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void m4aMPlayPitchControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s16 pitch)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->keyShiftX = pitch >> 8;
+ track->pitX = pitch;
+ track->flags |= MPT_FLG_PITCHG;
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void m4aMPlayPanpotControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s8 pan)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->panX = pan;
+ track->flags |= MPT_FLG_VOLCHG;
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void ClearModM(struct MusicPlayerTrack *track)
+{
+ track->lfoSpeedC = 0;
+ track->modM = 0;
+
+ if (track->modT == 0)
+ track->flags |= MPT_FLG_PITCHG;
+ else
+ track->flags |= MPT_FLG_VOLCHG;
+}
+
+void m4aMPlayModDepthSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 modDepth)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->mod = modDepth;
+
+ if (!track->mod)
+ ClearModM(track);
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+void m4aMPlayLFOSpeedSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 lfoSpeed)
+{
+ s32 i;
+ u32 bit;
+ struct MusicPlayerTrack *track;
+
+ if (mplayInfo->ident != ID_NUMBER)
+ return;
+
+ mplayInfo->ident++;
+
+ i = mplayInfo->trackCount;
+ track = mplayInfo->tracks;
+ bit = 1;
+
+ while (i > 0)
+ {
+ if (trackBits & bit)
+ {
+ if (track->flags & MPT_FLG_EXIST)
+ {
+ track->lfoSpeed = lfoSpeed;
+
+ if (!track->lfoSpeed)
+ ClearModM(track);
+ }
+ }
+
+ i--;
+ track++;
+ bit <<= 1;
+ }
+
+ mplayInfo->ident = ID_NUMBER;
+}
+
+#define MEMACC_COND_JUMP(cond) \
+if (cond) \
+ goto cond_true; \
+else \
+ goto cond_false; \
+
+void ply_memacc(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 op;
+ u8 *addr;
+ u8 data;
+
+ op = *track->cmdPtr;
+ track->cmdPtr++;
+
+ addr = mplayInfo->memAccArea + *track->cmdPtr;
+ track->cmdPtr++;
+
+ data = *track->cmdPtr;
+ track->cmdPtr++;
+
+ switch (op)
+ {
+ case 0:
+ *addr = data;
+ return;
+ case 1:
+ *addr += data;
+ return;
+ case 2:
+ *addr -= data;
+ return;
+ case 3:
+ *addr = mplayInfo->memAccArea[data];
+ return;
+ case 4:
+ *addr += mplayInfo->memAccArea[data];
+ return;
+ case 5:
+ *addr -= mplayInfo->memAccArea[data];
+ return;
+ case 6:
+ MEMACC_COND_JUMP(*addr == data)
+ return;
+ case 7:
+ MEMACC_COND_JUMP(*addr != data)
+ return;
+ case 8:
+ MEMACC_COND_JUMP(*addr > data)
+ return;
+ case 9:
+ MEMACC_COND_JUMP(*addr >= data)
+ return;
+ case 10:
+ MEMACC_COND_JUMP(*addr <= data)
+ return;
+ case 11:
+ MEMACC_COND_JUMP(*addr < data)
+ return;
+ case 12:
+ MEMACC_COND_JUMP(*addr == mplayInfo->memAccArea[data])
+ return;
+ case 13:
+ MEMACC_COND_JUMP(*addr != mplayInfo->memAccArea[data])
+ return;
+ case 14:
+ MEMACC_COND_JUMP(*addr > mplayInfo->memAccArea[data])
+ return;
+ case 15:
+ MEMACC_COND_JUMP(*addr >= mplayInfo->memAccArea[data])
+ return;
+ case 16:
+ MEMACC_COND_JUMP(*addr <= mplayInfo->memAccArea[data])
+ return;
+ case 17:
+ MEMACC_COND_JUMP(*addr < mplayInfo->memAccArea[data])
+ return;
+ default:
+ return;
+ }
+
+cond_true:
+ {
+ void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[1]);
+ func(mplayInfo, track);
+ return;
+ }
+
+cond_false:
+ track->cmdPtr += 4;
+}
+
+void ply_xcmd(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 n = *track->cmdPtr;
+ track->cmdPtr++;
+
+ gXcmdTable[n](mplayInfo, track);
+}
+
+void ply_xxx(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[0]);
+ func(mplayInfo, track);
+}
+
+#define READ_XCMD_BYTE(var, n) \
+{ \
+ u32 byte = track->cmdPtr[(n)]; \
+ byte <<= n * 8; \
+ (var) &= ~(0xFF << (n * 8)); \
+ (var) |= byte; \
+}
+
+void ply_xwave(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 wav;
+
+ READ_XCMD_BYTE(wav, 0) // UB: uninitialized variable
+ READ_XCMD_BYTE(wav, 1)
+ READ_XCMD_BYTE(wav, 2)
+ READ_XCMD_BYTE(wav, 3)
+
+ track->tone.wav = (struct WaveData *)wav;
+ track->cmdPtr += 4;
+}
+
+void ply_xtype(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.type = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xatta(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.attack = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xdeca(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.decay = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xsust(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.sustain = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xrele(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.release = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xiecv(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->echoVolume = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xiecl(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->echoLength = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xleng(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.length = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xswee(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ track->tone.pan_sweep = *track->cmdPtr;
+ track->cmdPtr++;
+}
+
+void ply_xcmd_0C(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 unk;
+
+ READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
+ READ_XCMD_BYTE(unk, 1)
+
+ if (track->unk_3A < (u16)unk)
+ {
+ track->unk_3A++;
+ track->cmdPtr -= 2;
+ track->wait = 1;
+ }
+ else
+ {
+ track->unk_3A = 0;
+ track->cmdPtr += 2;
+ }
+}
+
+void ply_xcmd_0D(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
+{
+ u32 unk;
+
+ READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
+ READ_XCMD_BYTE(unk, 1)
+ READ_XCMD_BYTE(unk, 2)
+ READ_XCMD_BYTE(unk, 3)
+
+ track->unk_3C = unk;
+ track->cmdPtr += 4;
+}
+
+void DummyFunc(void)
+{
+}
+
+struct MusicPlayerInfo *SetPokemonCryTone(struct ToneData *tone)
+{
+ u32 maxClock = 0;
+ s32 maxClockIndex = 0;
+ s32 i;
+ struct MusicPlayerInfo *mplayInfo;
+
+ for (i = 0; i < MAX_POKEMON_CRIES; i++)
+ {
+ struct MusicPlayerTrack *track = &gPokemonCryTracks[i * 2];
+
+ if (!track->flags && (!track->chan || track->chan->track != track))
+ goto start_song;
+
+ if (maxClock < gPokemonCryMusicPlayers[i].clock)
+ {
+ maxClock = gPokemonCryMusicPlayers[i].clock;
+ maxClockIndex = i;
+ }
+ }
+
+ i = maxClockIndex;
+
+start_song:
+ mplayInfo = &gPokemonCryMusicPlayers[i];
+ mplayInfo->ident++;
+
+#define CRY ((s32)&gPokemonCrySongs + i * sizeof(struct PokemonCrySong))
+#define CRY_OFS(field) offsetof(struct PokemonCrySong, field)
+
+ memcpy((void *)CRY, &gPokemonCrySong, sizeof(struct PokemonCrySong));
+
+ *(u32 *)(CRY + CRY_OFS(tone)) = (u32)tone;
+ *(u32 *)(CRY + CRY_OFS(part)) = CRY + CRY_OFS(part0);
+ *(u32 *)(CRY + CRY_OFS(part) + 4) = CRY + CRY_OFS(part1);
+ *(u32 *)(CRY + CRY_OFS(gotoTarget)) = CRY + CRY_OFS(cont);
+
+#undef CRY_OFS
+#undef CRY
+
+ mplayInfo->ident = ID_NUMBER;
+
+ MPlayStart(mplayInfo, (struct SongHeader *)(&gPokemonCrySongs[i]));
+
+ return mplayInfo;
+}
+
+void SetPokemonCryVolume(u8 val)
+{
+ gPokemonCrySong.volumeValue = val & 0x7F;
+}
+
+void SetPokemonCryPanpot(s8 val)
+{
+ gPokemonCrySong.panValue = (val + C_V) & 0x7F;
+}
+
+void SetPokemonCryPitch(s16 val)
+{
+ s16 b = val + 0x80;
+ u8 a = gPokemonCrySong.tuneValue2 - gPokemonCrySong.tuneValue;
+ gPokemonCrySong.tieKeyValue = (b >> 8) & 0x7F;
+ gPokemonCrySong.tuneValue = (b >> 1) & 0x7F;
+ gPokemonCrySong.tuneValue2 = (a + ((b >> 1) & 0x7F)) & 0x7F;
+}
+
+void SetPokemonCryLength(u16 val)
+{
+ gPokemonCrySong.unkCmd0CParam = val;
+}
+
+void SetPokemonCryRelease(u8 val)
+{
+ gPokemonCrySong.releaseValue = val;
+}
+
+void SetPokemonCryProgress(u32 val)
+{
+ gPokemonCrySong.unkCmd0DParam = val;
+}
+
+int IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo)
+{
+ struct MusicPlayerTrack *track = mplayInfo->tracks;
+
+ if (track->chan && track->chan->track == track)
+ return 1;
+ else
+ return 0;
+}
+
+void SetPokemonCryChorus(s8 val)
+{
+ if (val)
+ {
+ gPokemonCrySong.trackCount = 2;
+ gPokemonCrySong.tuneValue2 = (val + gPokemonCrySong.tuneValue) & 0x7F;
+ }
+ else
+ {
+ gPokemonCrySong.trackCount = 1;
+ }
+}
+
+void SetPokemonCryStereo(u32 val)
+{
+ struct SoundInfo *soundInfo = SOUND_INFO_PTR;
+
+ if (val)
+ {
+ REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
+ | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
+ | SOUND_ALL_MIX_FULL;
+ soundInfo->mode &= ~1;
+ }
+ else
+ {
+ REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT | SOUND_B_RIGHT_OUTPUT
+ | SOUND_A_TIMER_0 | SOUND_A_LEFT_OUTPUT | SOUND_A_RIGHT_OUTPUT
+ | SOUND_B_MIX_HALF | SOUND_A_MIX_HALF | SOUND_CGB_MIX_FULL;
+ soundInfo->mode |= 1;
+ }
+}
+
+void SetPokemonCryPriority(u8 val)
+{
+ gPokemonCrySong.priority = val;
+}
diff --git a/src/m4a_2.c b/src/m4a_2.c
deleted file mode 100644
index 0625f05d1..000000000
--- a/src/m4a_2.c
+++ /dev/null
@@ -1,912 +0,0 @@
-#include "gba/m4a_internal.h"
-
-#define BSS_CODE __attribute__((section(".bss.code")))
-
-BSS_CODE ALIGNED(4) char SoundMainRAM_Buffer[0x800] = {0};
-
-struct SoundInfo gSoundInfo;
-struct PokemonCrySong gPokemonCrySongs[MAX_POKEMON_CRIES];
-struct MusicPlayerInfo gPokemonCryMusicPlayers[MAX_POKEMON_CRIES];
-void *gMPlayJumpTable[36];
-struct CgbChannel gCgbChans[4];
-struct MusicPlayerTrack gPokemonCryTracks[MAX_POKEMON_CRIES * 2];
-struct PokemonCrySong gPokemonCrySong;
-struct MusicPlayerInfo gMPlayInfo_BGM;
-struct MusicPlayerInfo gMPlayInfo_SE1;
-struct MusicPlayerInfo gMPlayInfo_SE2;
-struct MusicPlayerInfo gMPlayInfo_SE3;
-u8 gMPlayMemAccArea[0x10];
-
-u32 MidiKeyToFreq(struct WaveData *wav, u8 key, u8 fineAdjust)
-{
- u32 val1;
- u32 val2;
- u32 fineAdjustShifted = fineAdjust << 24;
-
- if (key > 178)
- {
- key = 178;
- fineAdjustShifted = 255 << 24;
- }
-
- val1 = gScaleTable[key];
- val1 = gFreqTable[val1 & 0xF] >> (val1 >> 4);
-
- val2 = gScaleTable[key + 1];
- val2 = gFreqTable[val2 & 0xF] >> (val2 >> 4);
-
- return umul3232H32(wav->freq, val1 + umul3232H32(val2 - val1, fineAdjustShifted));
-}
-
-void UnusedDummyFunc()
-{
-}
-
-void MPlayContinue(struct MusicPlayerInfo *mplayInfo)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void MPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->fadeOC = speed;
- mplayInfo->fadeOI = speed;
- mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aSoundInit(void)
-{
- s32 i;
-
- CpuCopy32((void *)((s32)SoundMainRAM & ~1), SoundMainRAM_Buffer, sizeof(SoundMainRAM_Buffer));
-
- SoundInit(&gSoundInfo);
- MPlayExtender(gCgbChans);
- m4aSoundMode(SOUND_MODE_DA_BIT_8
- | SOUND_MODE_FREQ_13379
- | (12 << SOUND_MODE_MASVOL_SHIFT)
- | (5 << SOUND_MODE_MAXCHN_SHIFT));
-
- for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
- {
- struct MusicPlayerInfo *mplayInfo = gMPlayTable[i].info;
- MPlayOpen(mplayInfo, gMPlayTable[i].track, gMPlayTable[i].unk_8);
- mplayInfo->unk_B = gMPlayTable[i].unk_A;
- mplayInfo->memAccArea = gMPlayMemAccArea;
- }
-
- memcpy(&gPokemonCrySong, &gPokemonCrySongTemplate, sizeof(struct PokemonCrySong));
-
- for (i = 0; i < MAX_POKEMON_CRIES; i++)
- {
- struct MusicPlayerInfo *mplayInfo = &gPokemonCryMusicPlayers[i];
- struct MusicPlayerTrack *track = &gPokemonCryTracks[i * 2];
- MPlayOpen(mplayInfo, track, 2);
- track->chan = 0;
- }
-}
-
-void m4aSoundMain(void)
-{
- SoundMain();
-}
-
-void m4aSongNumStart(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- MPlayStart(mplay->info, song->header);
-}
-
-void m4aSongNumStartOrChange(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- if (mplay->info->songHeader != song->header)
- {
- MPlayStart(mplay->info, song->header);
- }
- else
- {
- if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0
- || (mplay->info->status & MUSICPLAYER_STATUS_PAUSE))
- {
- MPlayStart(mplay->info, song->header);
- }
- }
-}
-
-void m4aSongNumStartOrContinue(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- if (mplay->info->songHeader != song->header)
- MPlayStart(mplay->info, song->header);
- else if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0)
- MPlayStart(mplay->info, song->header);
- else if (mplay->info->status & MUSICPLAYER_STATUS_PAUSE)
- MPlayContinue(mplay->info);
-}
-
-void m4aSongNumStop(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- if (mplay->info->songHeader == song->header)
- m4aMPlayStop(mplay->info);
-}
-
-void m4aSongNumContinue(u16 n)
-{
- const struct MusicPlayer *mplayTable = gMPlayTable;
- const struct Song *songTable = gSongTable;
- const struct Song *song = &songTable[n];
- const struct MusicPlayer *mplay = &mplayTable[song->ms];
-
- if (mplay->info->songHeader == song->header)
- MPlayContinue(mplay->info);
-}
-
-void m4aMPlayAllStop(void)
-{
- s32 i;
-
- for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
- m4aMPlayStop(gMPlayTable[i].info);
-
- for (i = 0; i < MAX_POKEMON_CRIES; i++)
- m4aMPlayStop(&gPokemonCryMusicPlayers[i]);
-}
-
-void m4aMPlayContinue(struct MusicPlayerInfo *mplayInfo)
-{
- MPlayContinue(mplayInfo);
-}
-
-void m4aMPlayAllContinue(void)
-{
- s32 i;
-
- for (i = 0; i < NUM_MUSIC_PLAYERS; i++)
- MPlayContinue(gMPlayTable[i].info);
-
- for (i = 0; i < MAX_POKEMON_CRIES; i++)
- MPlayContinue(&gPokemonCryMusicPlayers[i]);
-}
-
-void m4aMPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed)
-{
- MPlayFadeOut(mplayInfo, speed);
-}
-
-void m4aMPlayFadeOutTemporarily(struct MusicPlayerInfo *mplayInfo, u16 speed)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->fadeOC = speed;
- mplayInfo->fadeOI = speed;
- mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT) | TEMPORARY_FADE;
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aMPlayFadeIn(struct MusicPlayerInfo *mplayInfo, u16 speed)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->fadeOC = speed;
- mplayInfo->fadeOI = speed;
- mplayInfo->fadeOV = (0 << FADE_VOL_SHIFT) | FADE_IN;
- mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE;
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aMPlayImmInit(struct MusicPlayerInfo *mplayInfo)
-{
- s32 trackCount = mplayInfo->trackCount;
- struct MusicPlayerTrack *track = mplayInfo->tracks;
-
- while (trackCount > 0)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- if (track->flags & MPT_FLG_START)
- {
- Clear64byte(track);
- track->flags = MPT_FLG_EXIST;
- track->bendRange = 2;
- track->volX = 64;
- track->lfoSpeed = 22;
- track->tone.type = 1;
- }
- }
-
- trackCount--;
- track++;
- }
-}
-
-void MPlayExtender(struct CgbChannel *cgbChans)
-{
- struct SoundInfo *soundInfo;
- u32 ident;
-
- REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
- | SOUND_4_ON
- | SOUND_3_ON
- | SOUND_2_ON
- | SOUND_1_ON;
- REG_SOUNDCNT_L = 0; // set master volume to zero
- REG_NR12 = 0x8;
- REG_NR22 = 0x8;
- REG_NR42 = 0x8;
- REG_NR14 = 0x80;
- REG_NR24 = 0x80;
- REG_NR44 = 0x80;
- REG_NR30 = 0;
- REG_NR50 = 0x77;
-
- soundInfo = SOUND_INFO_PTR;
-
- ident = soundInfo->ident;
-
- if (ident != ID_NUMBER)
- return;
-
- soundInfo->ident++;
-
- gMPlayJumpTable[8] = ply_memacc;
- gMPlayJumpTable[17] = ply_lfos;
- gMPlayJumpTable[19] = ply_mod;
- gMPlayJumpTable[28] = ply_xcmd;
- gMPlayJumpTable[29] = ply_endtie;
- gMPlayJumpTable[30] = SampleFreqSet;
- gMPlayJumpTable[31] = TrackStop;
- gMPlayJumpTable[32] = FadeOutBody;
- gMPlayJumpTable[33] = TrkVolPitSet;
-
- soundInfo->cgbChans = (struct CgbChannel *)cgbChans;
- soundInfo->CgbSound = CgbSound;
- soundInfo->CgbOscOff = CgbOscOff;
- soundInfo->MidiKeyToCgbFreq = MidiKeyToCgbFreq;
- soundInfo->maxLines = MAX_LINES;
-
- CpuFill32(0, cgbChans, sizeof(struct CgbChannel) * 4);
-
- cgbChans[0].ty = 1;
- cgbChans[0].panMask = 0x11;
- cgbChans[1].ty = 2;
- cgbChans[1].panMask = 0x22;
- cgbChans[2].ty = 3;
- cgbChans[2].panMask = 0x44;
- cgbChans[3].ty = 4;
- cgbChans[3].panMask = 0x88;
-
- soundInfo->ident = ident;
-}
-
-void MusicPlayerJumpTableCopy(void)
-{
- asm("swi 0x2A");
-}
-
-void ClearChain(void *x)
-{
- void (*func)(void *) = *(&gMPlayJumpTable[34]);
- func(x);
-}
-
-void Clear64byte(void *x)
-{
- void (*func)(void *) = *(&gMPlayJumpTable[35]);
- func(x);
-}
-
-void SoundInit(struct SoundInfo *soundInfo)
-{
- soundInfo->ident = 0;
-
- if (REG_DMA1CNT & (DMA_REPEAT << 16))
- REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
-
- if (REG_DMA2CNT & (DMA_REPEAT << 16))
- REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
-
- REG_DMA1CNT_H = DMA_32BIT;
- REG_DMA2CNT_H = DMA_32BIT;
- REG_SOUNDCNT_X = SOUND_MASTER_ENABLE
- | SOUND_4_ON
- | SOUND_3_ON
- | SOUND_2_ON
- | SOUND_1_ON;
- REG_SOUNDCNT_H = SOUND_B_FIFO_RESET | SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
- | SOUND_A_FIFO_RESET | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
- | SOUND_ALL_MIX_FULL;
- REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | 0x40;
-
- REG_DMA1SAD = (s32)soundInfo->pcmBuffer;
- REG_DMA1DAD = (s32)&REG_FIFO_A;
- REG_DMA2SAD = (s32)soundInfo->pcmBuffer + PCM_DMA_BUF_SIZE;
- REG_DMA2DAD = (s32)&REG_FIFO_B;
-
- SOUND_INFO_PTR = soundInfo;
- CpuFill32(0, soundInfo, sizeof(struct SoundInfo));
-
- soundInfo->maxChans = 8;
- soundInfo->masterVolume = 15;
- soundInfo->plynote = (u32)ply_note;
- soundInfo->CgbSound = DummyFunc;
- soundInfo->CgbOscOff = (void (*)(u8))DummyFunc;
- soundInfo->MidiKeyToCgbFreq = (u32 (*)(u8, u8, u8))DummyFunc;
- soundInfo->ExtVolPit = (u32)DummyFunc;
-
- MPlayJumpTableCopy(gMPlayJumpTable);
-
- soundInfo->MPlayJumpTable = (u32)gMPlayJumpTable;
-
- SampleFreqSet(SOUND_MODE_FREQ_13379);
-
- soundInfo->ident = ID_NUMBER;
-}
-
-void SampleFreqSet(u32 freq)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
-
- freq = (freq & 0xF0000) >> 16;
- soundInfo->freq = freq;
- soundInfo->pcmSamplesPerVBlank = gPcmSamplesPerVBlankTable[freq - 1];
- soundInfo->pcmDmaPeriod = PCM_DMA_BUF_SIZE / soundInfo->pcmSamplesPerVBlank;
-
- // LCD refresh rate 59.7275Hz
- soundInfo->pcmFreq = (597275 * soundInfo->pcmSamplesPerVBlank + 5000) / 10000;
-
- // CPU frequency 16.78Mhz
- soundInfo->divFreq = (16777216 / soundInfo->pcmFreq + 1) >> 1;
-
- // Turn off timer 0.
- REG_TM0CNT_H = 0;
-
- // cycles per LCD fresh 280896
- REG_TM0CNT_L = -(280896 / soundInfo->pcmSamplesPerVBlank);
-
- m4aSoundVSyncOn();
-
- while (*(vu8 *)REG_ADDR_VCOUNT == 159)
- ;
-
- while (*(vu8 *)REG_ADDR_VCOUNT != 159)
- ;
-
- REG_TM0CNT_H = TIMER_ENABLE | TIMER_1CLK;
-}
-
-void m4aSoundMode(u32 mode)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
- u32 temp;
-
- if (soundInfo->ident != ID_NUMBER)
- return;
-
- soundInfo->ident++;
-
- temp = mode & (SOUND_MODE_REVERB_SET | SOUND_MODE_REVERB_VAL);
-
- if (temp)
- soundInfo->reverb = temp & SOUND_MODE_REVERB_VAL;
-
- temp = mode & SOUND_MODE_MAXCHN;
-
- if (temp)
- {
- struct SoundChannel *chan;
-
- soundInfo->maxChans = temp >> SOUND_MODE_MAXCHN_SHIFT;
-
- temp = MAX_DIRECTSOUND_CHANNELS;
- chan = &soundInfo->chans[0];
-
- while (temp != 0)
- {
- chan->status = 0;
- temp--;
- chan++;
- }
- }
-
- temp = mode & SOUND_MODE_MASVOL;
-
- if (temp)
- soundInfo->masterVolume = temp >> SOUND_MODE_MASVOL_SHIFT;
-
- temp = mode & SOUND_MODE_DA_BIT;
-
- if (temp)
- {
- temp = (temp & 0x300000) >> 14;
- REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | temp;
- }
-
- temp = mode & SOUND_MODE_FREQ;
-
- if (temp)
- {
- m4aSoundVSyncOff();
- SampleFreqSet(temp);
- }
-
- soundInfo->ident = ID_NUMBER;
-}
-
-void SoundClear(void)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
- s32 i;
- void *chan;
-
- if (soundInfo->ident != ID_NUMBER)
- return;
-
- soundInfo->ident++;
-
- i = MAX_DIRECTSOUND_CHANNELS;
- chan = &soundInfo->chans[0];
-
- while (i > 0)
- {
- ((struct SoundChannel *)chan)->status = 0;
- i--;
- chan = (void *)((s32)chan + sizeof(struct SoundChannel));
- }
-
- chan = soundInfo->cgbChans;
-
- if (chan)
- {
- i = 1;
-
- while (i <= 4)
- {
- soundInfo->CgbOscOff(i);
- ((struct CgbChannel *)chan)->sf = 0;
- i++;
- chan = (void *)((s32)chan + sizeof(struct CgbChannel));
- }
- }
-
- soundInfo->ident = ID_NUMBER;
-}
-
-void m4aSoundVSyncOff(void)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
-
- if (soundInfo->ident >= ID_NUMBER && soundInfo->ident <= ID_NUMBER + 1)
- {
- soundInfo->ident += 10;
-
- if (REG_DMA1CNT & (DMA_REPEAT << 16))
- REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
-
- if (REG_DMA2CNT & (DMA_REPEAT << 16))
- REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4;
-
- REG_DMA1CNT_H = DMA_32BIT;
- REG_DMA2CNT_H = DMA_32BIT;
-
- CpuFill32(0, soundInfo->pcmBuffer, sizeof(soundInfo->pcmBuffer));
- }
-}
-
-void m4aSoundVSyncOn(void)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
- u32 ident = soundInfo->ident;
-
- if (ident == ID_NUMBER)
- return;
-
- REG_DMA1CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
- REG_DMA2CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT;
-
- soundInfo->pcmDmaCounter = 0;
- soundInfo->ident = ident - 10;
-}
-
-void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tracks, u8 trackCount)
-{
- struct SoundInfo *soundInfo;
-
- if (trackCount == 0)
- return;
-
- if (trackCount > MAX_MUSICPLAYER_TRACKS)
- trackCount = MAX_MUSICPLAYER_TRACKS;
-
- soundInfo = SOUND_INFO_PTR;
-
- if (soundInfo->ident != ID_NUMBER)
- return;
-
- soundInfo->ident++;
-
- Clear64byte(mplayInfo);
-
- mplayInfo->tracks = tracks;
- mplayInfo->trackCount = trackCount;
- mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
-
- while (trackCount != 0)
- {
- tracks->flags = 0;
- trackCount--;
- tracks++;
- }
-
- if (soundInfo->func != 0)
- {
- mplayInfo->func = soundInfo->func;
- mplayInfo->intp = soundInfo->intp;
- soundInfo->func = 0;
- }
-
- soundInfo->intp = (u32)mplayInfo;
- soundInfo->func = (u32)MPlayMain;
- soundInfo->ident = ID_NUMBER;
- mplayInfo->ident = ID_NUMBER;
-}
-
-void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader)
-{
- s32 i;
- u8 unk_B;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- unk_B = mplayInfo->unk_B;
-
- if (!unk_B
- || ((!mplayInfo->songHeader || !(mplayInfo->tracks[0].flags & MPT_FLG_START))
- && ((mplayInfo->status & MUSICPLAYER_STATUS_TRACK) == 0
- || (mplayInfo->status & MUSICPLAYER_STATUS_PAUSE)))
- || (mplayInfo->priority <= songHeader->priority))
- {
- mplayInfo->ident++;
- mplayInfo->status = 0;
- mplayInfo->songHeader = songHeader;
- mplayInfo->tone = songHeader->tone;
- mplayInfo->priority = songHeader->priority;
- mplayInfo->clock = 0;
- mplayInfo->tempoD = 150;
- mplayInfo->tempoI = 150;
- mplayInfo->tempoU = 0x100;
- mplayInfo->tempoC = 0;
- mplayInfo->fadeOI = 0;
-
- i = 0;
- track = mplayInfo->tracks;
-
- while (i < songHeader->trackCount && i < mplayInfo->trackCount)
- {
- TrackStop(mplayInfo, track);
- track->flags = MPT_FLG_EXIST | MPT_FLG_START;
- track->chan = 0;
- track->cmdPtr = songHeader->part[i];
- i++;
- track++;
- }
-
- while (i < mplayInfo->trackCount)
- {
- TrackStop(mplayInfo, track);
- track->flags = 0;
- i++;
- track++;
- }
-
- if (songHeader->reverb & 0x80)
- m4aSoundMode(songHeader->reverb);
-
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aMPlayStop(struct MusicPlayerInfo *mplayInfo)
-{
- s32 i;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
- mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
-
- while (i > 0)
- {
- TrackStop(mplayInfo, track);
- i--;
- track++;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void FadeOutBody(struct MusicPlayerInfo *mplayInfo)
-{
- s32 i;
- struct MusicPlayerTrack *track;
- u16 fadeOI = mplayInfo->fadeOI;
- register u32 temp asm("r3");
- register u16 mask asm("r2");
-
- if (fadeOI == 0)
- return;
-
- mplayInfo->fadeOC--;
-
- temp = 0xFFFF;
- mask = temp;
-
- if (mplayInfo->fadeOC != 0)
- return;
-
- mplayInfo->fadeOC = fadeOI;
-
- if (mplayInfo->fadeOV & FADE_IN)
- {
- mplayInfo->fadeOV += (4 << FADE_VOL_SHIFT);
-
- if ((u16)(mplayInfo->fadeOV & mask) >= (64 << FADE_VOL_SHIFT))
- {
- mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT);
- mplayInfo->fadeOI = 0;
- }
- }
- else
- {
- mplayInfo->fadeOV -= (4 << FADE_VOL_SHIFT);
-
- if ((s16)(mplayInfo->fadeOV & mask) <= 0)
- {
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
-
- while (i > 0)
- {
- register u32 fadeOV asm("r7");
- u32 val;
-
- TrackStop(mplayInfo, track);
-
- val = TEMPORARY_FADE;
- fadeOV = mplayInfo->fadeOV;
- val &= fadeOV;
-
- if (!val)
- track->flags = 0;
-
- i--;
- track++;
- }
-
- if (mplayInfo->fadeOV & TEMPORARY_FADE)
- mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE;
- else
- mplayInfo->status = MUSICPLAYER_STATUS_PAUSE;
-
- mplayInfo->fadeOI = 0;
- return;
- }
- }
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
-
- while (i > 0)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->volX = (mplayInfo->fadeOV >> FADE_VOL_SHIFT);
- track->flags |= MPT_FLG_VOLCHG;
- }
-
- i--;
- track++;
- }
-}
-
-void TrkVolPitSet(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- if (track->flags & MPT_FLG_VOLSET)
- {
- s32 x;
- s32 y;
-
- x = (u32)(track->vol * track->volX) >> 5;
-
- if (track->modT == 1)
- x = (u32)(x * (track->modM + 128)) >> 7;
-
- y = 2 * track->pan + track->panX;
-
- if (track->modT == 2)
- y += track->modM;
-
- if (y < -128)
- y = -128;
- else if (y > 127)
- y = 127;
-
- track->volMR = (u32)((y + 128) * x) >> 8;
- track->volML = (u32)((127 - y) * x) >> 8;
- }
-
- if (track->flags & MPT_FLG_PITSET)
- {
- s32 bend = track->bend * track->bendRange;
- register s32 x asm("r1") = track->tune;
- x += bend;
- x *= 4;
- x += (track->keyShift << 8);
- x += (track->keyShiftX << 8);
- x += track->pitX;
-
- if (track->modT == 0)
- x += 16 * track->modM;
-
- track->keyM = x >> 8;
- track->pitM = x;
- }
-
- track->flags &= ~(MPT_FLG_PITSET | MPT_FLG_VOLSET);
-}
-
-u32 MidiKeyToCgbFreq(u8 chanNum, u8 key, u8 fineAdjust)
-{
- if (chanNum == 4)
- {
- if (key <= 20)
- {
- key = 0;
- }
- else
- {
- key -= 21;
- if (key > 59)
- key = 59;
- }
-
- return gNoiseTable[key];
- }
- else
- {
- s32 val1;
- s32 val2;
-
- if (key <= 35)
- {
- fineAdjust = 0;
- key = 0;
- }
- else
- {
- key -= 36;
- if (key > 130)
- {
- key = 130;
- fineAdjust = 255;
- }
- }
-
- val1 = gCgbScaleTable[key];
- val1 = gCgbFreqTable[val1 & 0xF] >> (val1 >> 4);
-
- val2 = gCgbScaleTable[key + 1];
- val2 = gCgbFreqTable[val2 & 0xF] >> (val2 >> 4);
-
- return val1 + ((fineAdjust * (val2 - val1)) >> 8) + 2048;
- }
-}
-
-void CgbOscOff(u8 chanNum)
-{
- switch (chanNum)
- {
- case 1:
- REG_NR12 = 8;
- REG_NR14 = 0x80;
- break;
- case 2:
- REG_NR22 = 8;
- REG_NR24 = 0x80;
- break;
- case 3:
- REG_NR30 = 0;
- break;
- default:
- REG_NR42 = 8;
- REG_NR44 = 0x80;
- }
-}
-
-static inline int CgbPan(struct CgbChannel *chan)
-{
- u32 rightVolume = chan->rightVolume;
- u32 leftVolume = chan->leftVolume;
-
- if ((rightVolume = (u8)rightVolume) >= (leftVolume = (u8)leftVolume))
- {
- if (rightVolume / 2 >= leftVolume)
- {
- chan->pan = 0x0F;
- return 1;
- }
- }
- else
- {
- if (leftVolume / 2 >= rightVolume)
- {
- chan->pan = 0xF0;
- return 1;
- }
- }
-
- return 0;
-}
-
-void CgbModVol(struct CgbChannel *chan)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
-
- if ((soundInfo->mode & 1) || !CgbPan(chan))
- {
- chan->pan = 0xFF;
- chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4;
- }
- else
- {
- // Force chan->rightVolume and chan->leftVolume to be read from memory again,
- // even though there is no reason to do so.
- // The command line option "-fno-gcse" achieves the same result as this.
- asm("" : : : "memory");
-
- chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4;
- if (chan->eg > 15)
- chan->eg = 15;
- }
-
- chan->sg = (chan->eg * chan->su + 15) >> 4;
- chan->pan &= chan->panMask;
-}
diff --git a/src/m4a_4.c b/src/m4a_4.c
deleted file mode 100644
index 2e1d140b4..000000000
--- a/src/m4a_4.c
+++ /dev/null
@@ -1,545 +0,0 @@
-#include "gba/m4a_internal.h"
-
-void m4aMPlayTempoControl(struct MusicPlayerInfo *mplayInfo, u16 tempo)
-{
- if (mplayInfo->ident == ID_NUMBER)
- {
- mplayInfo->ident++;
- mplayInfo->tempoU = tempo;
- mplayInfo->tempoI = (mplayInfo->tempoD * mplayInfo->tempoU) >> 8;
- mplayInfo->ident = ID_NUMBER;
- }
-}
-
-void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->volX = volume / 4;
- track->flags |= MPT_FLG_VOLCHG;
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void m4aMPlayPitchControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s16 pitch)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->keyShiftX = (s16)pitch >> 8;
- track->pitX = pitch;
- track->flags |= MPT_FLG_PITCHG;
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void m4aMPlayPanpotControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s8 pan)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->panX = pan;
- track->flags |= MPT_FLG_VOLCHG;
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void ClearModM(struct MusicPlayerTrack *track)
-{
- track->lfoSpeedC = 0;
- track->modM = 0;
-
- if (track->modT == 0)
- track->flags |= MPT_FLG_PITCHG;
- else
- track->flags |= MPT_FLG_VOLCHG;
-}
-
-void m4aMPlayModDepthSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 modDepth)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->mod = modDepth;
-
- if (!track->mod)
- ClearModM(track);
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-void m4aMPlayLFOSpeedSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 lfoSpeed)
-{
- s32 i;
- u32 bit;
- struct MusicPlayerTrack *track;
-
- if (mplayInfo->ident != ID_NUMBER)
- return;
-
- mplayInfo->ident++;
-
- i = mplayInfo->trackCount;
- track = mplayInfo->tracks;
- bit = 1;
-
- while (i > 0)
- {
- if (trackBits & bit)
- {
- if (track->flags & MPT_FLG_EXIST)
- {
- track->lfoSpeed = lfoSpeed;
-
- if (!track->lfoSpeed)
- ClearModM(track);
- }
- }
-
- i--;
- track++;
- bit <<= 1;
- }
-
- mplayInfo->ident = ID_NUMBER;
-}
-
-#define MEMACC_COND_JUMP(cond) \
-if (cond) \
- goto cond_true; \
-else \
- goto cond_false; \
-
-void ply_memacc(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 op;
- u8 *addr;
- u8 data;
-
- op = *track->cmdPtr;
- track->cmdPtr++;
-
- addr = mplayInfo->memAccArea + *track->cmdPtr;
- track->cmdPtr++;
-
- data = *track->cmdPtr;
- track->cmdPtr++;
-
- switch (op)
- {
- case 0:
- *addr = data;
- return;
- case 1:
- *addr += data;
- return;
- case 2:
- *addr -= data;
- return;
- case 3:
- *addr = mplayInfo->memAccArea[data];
- return;
- case 4:
- *addr += mplayInfo->memAccArea[data];
- return;
- case 5:
- *addr -= mplayInfo->memAccArea[data];
- return;
- case 6:
- MEMACC_COND_JUMP(*addr == data)
- return;
- case 7:
- MEMACC_COND_JUMP(*addr != data)
- return;
- case 8:
- MEMACC_COND_JUMP(*addr > data)
- return;
- case 9:
- MEMACC_COND_JUMP(*addr >= data)
- return;
- case 10:
- MEMACC_COND_JUMP(*addr <= data)
- return;
- case 11:
- MEMACC_COND_JUMP(*addr < data)
- return;
- case 12:
- MEMACC_COND_JUMP(*addr == mplayInfo->memAccArea[data])
- return;
- case 13:
- MEMACC_COND_JUMP(*addr != mplayInfo->memAccArea[data])
- return;
- case 14:
- MEMACC_COND_JUMP(*addr > mplayInfo->memAccArea[data])
- return;
- case 15:
- MEMACC_COND_JUMP(*addr >= mplayInfo->memAccArea[data])
- return;
- case 16:
- MEMACC_COND_JUMP(*addr <= mplayInfo->memAccArea[data])
- return;
- case 17:
- MEMACC_COND_JUMP(*addr < mplayInfo->memAccArea[data])
- return;
- default:
- return;
- }
-
-cond_true:
- {
- void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[1]);
- func(mplayInfo, track);
- return;
- }
-
-cond_false:
- track->cmdPtr += 4;
-}
-
-void ply_xcmd(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 n = *track->cmdPtr;
- track->cmdPtr++;
-
- gXcmdTable[n](mplayInfo, track);
-}
-
-void ply_xxx(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[0]);
- func(mplayInfo, track);
-}
-
-#define READ_XCMD_BYTE(var, n) \
-{ \
- u32 byte = track->cmdPtr[(n)]; \
- byte <<= n * 8; \
- (var) &= ~(0xFF << (n * 8)); \
- (var) |= byte; \
-}
-
-void ply_xwave(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 wav;
-
- READ_XCMD_BYTE(wav, 0) // UB: uninitialized variable
- READ_XCMD_BYTE(wav, 1)
- READ_XCMD_BYTE(wav, 2)
- READ_XCMD_BYTE(wav, 3)
-
- track->tone.wav = (struct WaveData *)wav;
- track->cmdPtr += 4;
-}
-
-void ply_xtype(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.type = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xatta(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.attack = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xdeca(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.decay = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xsust(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.sustain = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xrele(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.release = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xiecv(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->echoVolume = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xiecl(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->echoLength = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xleng(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.length = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xswee(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- track->tone.pan_sweep = *track->cmdPtr;
- track->cmdPtr++;
-}
-
-void ply_xcmd_0C(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 unk;
-
- READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
- READ_XCMD_BYTE(unk, 1)
-
- if (track->unk_3A < (u16)unk)
- {
- track->unk_3A++;
- track->cmdPtr -= 2;
- track->wait = 1;
- }
- else
- {
- track->unk_3A = 0;
- track->cmdPtr += 2;
- }
-}
-
-void ply_xcmd_0D(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track)
-{
- u32 unk;
-
- READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable
- READ_XCMD_BYTE(unk, 1)
- READ_XCMD_BYTE(unk, 2)
- READ_XCMD_BYTE(unk, 3)
-
- track->unk_3C = unk;
- track->cmdPtr += 4;
-}
-
-void DummyFunc(void)
-{
-}
-
-struct MusicPlayerInfo *SetPokemonCryTone(struct ToneData *tone)
-{
- u32 maxClock = 0;
- s32 maxClockIndex = 0;
- s32 i;
- struct MusicPlayerInfo *mplayInfo;
-
- for (i = 0; i < MAX_POKEMON_CRIES; i++)
- {
- struct MusicPlayerTrack *track = &gPokemonCryTracks[i * 2];
-
- if (!track->flags && (!track->chan || track->chan->track != track))
- goto start_song;
-
- if (maxClock < gPokemonCryMusicPlayers[i].clock)
- {
- maxClock = gPokemonCryMusicPlayers[i].clock;
- maxClockIndex = i;
- }
- }
-
- i = maxClockIndex;
-
-start_song:
- mplayInfo = &gPokemonCryMusicPlayers[i];
- mplayInfo->ident++;
-
-#define CRY ((s32)&gPokemonCrySongs + i * sizeof(struct PokemonCrySong))
-#define CRY_OFS(field) offsetof(struct PokemonCrySong, field)
-
- memcpy((void *)CRY, &gPokemonCrySong, sizeof(struct PokemonCrySong));
-
- *(u32 *)(CRY + CRY_OFS(tone)) = (u32)tone;
- *(u32 *)(CRY + CRY_OFS(part)) = CRY + CRY_OFS(part0);
- *(u32 *)(CRY + CRY_OFS(part) + 4) = CRY + CRY_OFS(part1);
- *(u32 *)(CRY + CRY_OFS(gotoTarget)) = CRY + CRY_OFS(cont);
-
-#undef CRY_OFS
-#undef CRY
-
- mplayInfo->ident = ID_NUMBER;
-
- MPlayStart(mplayInfo, (struct SongHeader *)(&gPokemonCrySongs[i]));
-
- return mplayInfo;
-}
-
-void SetPokemonCryVolume(u8 val)
-{
- gPokemonCrySong.volumeValue = val & 0x7F;
-}
-
-void SetPokemonCryPanpot(s8 val)
-{
- gPokemonCrySong.panValue = (val + C_V) & 0x7F;
-}
-
-void SetPokemonCryPitch(s16 val)
-{
- s16 b = val + 0x80;
- u8 a = gPokemonCrySong.tuneValue2 - gPokemonCrySong.tuneValue;
- gPokemonCrySong.tieKeyValue = (b >> 8) & 0x7F;
- gPokemonCrySong.tuneValue = (b >> 1) & 0x7F;
- gPokemonCrySong.tuneValue2 = (a + ((b >> 1) & 0x7F)) & 0x7F;
-}
-
-void SetPokemonCryLength(u16 val)
-{
- gPokemonCrySong.unkCmd0CParam = val;
-}
-
-void SetPokemonCryRelease(u8 val)
-{
- gPokemonCrySong.releaseValue = val;
-}
-
-void SetPokemonCryProgress(u32 val)
-{
- gPokemonCrySong.unkCmd0DParam = val;
-}
-
-int IsPokemonCryPlaying(struct MusicPlayerInfo *mplayInfo)
-{
- struct MusicPlayerTrack *track = mplayInfo->tracks;
-
- if (track->chan && track->chan->track == track)
- return 1;
- else
- return 0;
-}
-
-void SetPokemonCryChorus(s8 val)
-{
- if (val)
- {
- gPokemonCrySong.trackCount = 2;
- gPokemonCrySong.tuneValue2 = (val + gPokemonCrySong.tuneValue) & 0x7F;
- }
- else
- {
- gPokemonCrySong.trackCount = 1;
- }
-}
-
-void SetPokemonCryStereo(u32 val)
-{
- struct SoundInfo *soundInfo = SOUND_INFO_PTR;
-
- if (val)
- {
- REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT
- | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT
- | SOUND_ALL_MIX_FULL;
- soundInfo->mode &= ~1;
- }
- else
- {
- REG_SOUNDCNT_H = SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT | SOUND_B_RIGHT_OUTPUT
- | SOUND_A_TIMER_0 | SOUND_A_LEFT_OUTPUT | SOUND_A_RIGHT_OUTPUT
- | SOUND_B_MIX_HALF | SOUND_A_MIX_HALF | SOUND_CGB_MIX_FULL;
- soundInfo->mode |= 1;
- }
-}
-
-void SetPokemonCryPriority(u8 val)
-{
- gPokemonCrySong.priority = val;
-}
diff --git a/src/menews_jisan.c b/src/menews_jisan.c
index 530762990..0d406e66a 100644
--- a/src/menews_jisan.c
+++ b/src/menews_jisan.c
@@ -10,7 +10,7 @@ static u32 sub_8146E0C(struct MysteryEventStruct *);
static void sub_8146DA0(struct MysteryEventStruct *);
static void sub_8146D94(struct MysteryEventStruct *);
-void sub_8146C30(u32 a0)
+void GenerateRandomNews(u32 a0)
{
struct MysteryEventStruct *r5 = sub_8143D94();
@@ -59,7 +59,7 @@ u16 sub_8146CE8(void)
struct MysteryEventStruct *r4 = sub_8143D94();
u16 r5;
- if (!sub_806E2BC() || !sub_8143E1C())
+ if (!sub_806E2BC() || !ValidateReceivedWonderNews())
return 0;
r5 = sub_8146E0C(r4);
diff --git a/src/mevent.c b/src/mevent.c
index a62286f21..4d625987e 100644
--- a/src/mevent.c
+++ b/src/mevent.c
@@ -240,7 +240,7 @@ u32 sub_8143770(u8 * r4, u16 * r5)
return 0;
}
-void sub_81438A0(void)
+void task_add_00_ereader(void)
{
u8 taskId = CreateTask(sub_8143910, 0);
struct MEventTaskData1 *data = (struct MEventTaskData1 *)gTasks[taskId].data;
@@ -279,7 +279,7 @@ void sub_8143910(u8 taskId)
switch (data->t08)
{
case 0:
- if (mevent_0814257C(&data->t09, gUnknown_841DE52))
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE52))
data->t08 = 1;
break;
case 1:
@@ -294,16 +294,16 @@ void sub_8143910(u8 taskId)
case 3:
if (!sub_814374C())
{
- sub_80098B8();
+ CloseLink();
data->t08 = 4;
}
else
data->t08 = 13;
break;
case 4:
- if (mevent_0814257C(&data->t09, gUnknown_841DE53))
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE53))
{
- sub_8142504(gUnknown_841DE54);
+ AddTextPrinterToWindow1(gUnknown_841DE54);
sub_81438E8(&data->t00);
data->t08 = 5;
}
@@ -325,36 +325,36 @@ void sub_8143910(u8 taskId)
if (JOY_NEW(B_BUTTON))
{
PlaySE(SE_SELECT);
- sub_80098B8();
+ CloseLink();
sub_81438E8(&data->t00);
data->t08 = 23;
}
else if (GetLinkPlayerCount_2() > 1)
{
sub_81438E8(&data->t00);
- sub_80098B8();
+ CloseLink();
data->t08 = 7;
}
else if (sub_81436EC())
{
PlaySE(SE_SELECT);
- sub_80098B8();
+ CloseLink();
sub_81438E8(&data->t00);
data->t08 = 8;
}
else if (sub_81438F0(&data->t00, 10))
{
- sub_80098B8();
+ CloseLink();
sub_81436BC();
sub_81438E8(&data->t00);
}
break;
case 7:
- if (mevent_0814257C(&data->t09, gUnknown_841DE7C))
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE7C))
data->t08 = 4;
break;
case 8:
- sub_8142504(gUnknown_841DE95);
+ AddTextPrinterToWindow1(gUnknown_841DE95);
sub_81435DC(&gUnknown_3005ED0, gUnknownSerialData_End - gUnknownSerialData_Start, gUnknownSerialData_Start);
data->t08 = 9;
break;
@@ -370,7 +370,7 @@ void sub_8143910(u8 taskId)
else if (data->t0E == 1)
{
sub_81438E8(&data->t00);
- sub_8142504(gUnknown_841DE9B);
+ AddTextPrinterToWindow1(gUnknown_841DE9B);
data->t08 = 11;
}
else
@@ -382,7 +382,7 @@ void sub_8143910(u8 taskId)
break;
case 12:
sub_81436BC();
- sub_8142504(gUnknown_841DE98);
+ AddTextPrinterToWindow1(gUnknown_841DE98);
data->t08 = 13;
break;
case 13:
@@ -391,21 +391,21 @@ void sub_8143910(u8 taskId)
case 0:
break;
case 2:
- sub_8142504(gUnknown_841DE95);
+ AddTextPrinterToWindow1(gUnknown_841DE95);
data->t08 = 14;
break;
case 1:
PlaySE(SE_SELECT);
- sub_80098B8();
+ CloseLink();
data->t08 = 23;
break;
case 5:
- sub_80098B8();
+ CloseLink();
data->t08 = 21;
break;
case 3:
case 4:
- sub_80098B8();
+ CloseLink();
data->t08 = 20;
break;
}
@@ -413,7 +413,7 @@ void sub_8143910(u8 taskId)
case 14:
if (HasLinkErrorOccurred())
{
- sub_80098B8();
+ CloseLink();
data->t08 = 20;
}
else if (GetBlockReceivedStatus())
@@ -439,7 +439,7 @@ void sub_8143910(u8 taskId)
case 17:
if (sub_815D794(gDecompressionBuffer))
{
- sub_8142504(gUnknown_841DE99);
+ AddTextPrinterToWindow1(gUnknown_841DE99);
sub_81438E8(&data->t00);
data->t08 = 18;
}
@@ -449,7 +449,7 @@ void sub_8143910(u8 taskId)
case 18:
if (sub_81438F0(&data->t00, 120))
{
- sub_8142504(gUnknown_841DE9A);
+ AddTextPrinterToWindow1(gUnknown_841DE9A);
PlayFanfare(258);
data->t08 = 19;
}
@@ -459,26 +459,26 @@ void sub_8143910(u8 taskId)
data->t08 = 26;
break;
case 23:
- if (mevent_0814257C(&data->t09, gUnknown_841DE7D))
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE7D))
data->t08 = 26;
break;
case 20:
- if (mevent_0814257C(&data->t09, gUnknown_841DE96))
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE96))
data->t08 = 0;
break;
case 21:
- if (mevent_0814257C(&data->t09, gUnknown_841DE97))
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE97))
data->t08 = 0;
break;
case 22:
- if (mevent_0814257C(&data->t09, gUnknown_841DE9C))
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->t09, gUnknown_841DE9C))
data->t08 = 0;
break;
case 26:
sub_812B484();
Free(data->t10);
DestroyTask(taskId);
- SetMainCallback2(sub_81422FC);
+ SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
break;
}
}
@@ -490,12 +490,12 @@ void sub_8143D24(void)
sub_80BDE28();
}
-struct MEventBuffer_3120_Sub * sub_8143D58(void)
+struct MEventBuffer_3120_Sub * GetSavedWonderNews(void)
{
return &gSaveBlock1Ptr->unk_3120.buffer_000.data;
}
-struct MEventBuffer_32E0_Sub * sav1_get_mevent_buffer_1(void)
+struct MEventBuffer_32E0_Sub * GetSavedWonderCard(void)
{
return &gSaveBlock1Ptr->unk_3120.buffer_1c0.data;
}
@@ -515,7 +515,7 @@ u16 * sub_8143DA8(void)
return gSaveBlock1Ptr->unk_3120.unk_338;
}
-void sub_8143DBC(void)
+void DestroyWonderNews(void)
{
sub_8143E9C();
}
@@ -530,7 +530,7 @@ bool32 sub_8143DC8(const struct MEventBuffer_3120_Sub * src)
return TRUE;
}
-bool32 sub_8143E1C(void)
+bool32 ValidateReceivedWonderNews(void)
{
if (CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_3120.buffer_000.data, sizeof(struct MEventBuffer_3120_Sub)) != gSaveBlock1Ptr->unk_3120.buffer_000.crc)
return FALSE;
@@ -546,7 +546,7 @@ bool32 sub_8143E64(const struct MEventBuffer_3120_Sub * data)
return TRUE;
}
-bool32 sub_8143E78(void)
+bool32 WonderNews_Test_Unk_02(void)
{
const struct MEventBuffer_3120_Sub * data = &gSaveBlock1Ptr->unk_3120.buffer_000.data;
if (data->unk_02 == 0)
@@ -556,7 +556,7 @@ bool32 sub_8143E78(void)
void sub_8143E9C(void)
{
- CpuFill32(0, sub_8143D58(), sizeof(gSaveBlock1Ptr->unk_3120.buffer_000.data));
+ CpuFill32(0, GetSavedWonderNews(), sizeof(gSaveBlock1Ptr->unk_3120.buffer_000.data));
gSaveBlock1Ptr->unk_3120.buffer_000.crc = 0;
}
@@ -570,7 +570,7 @@ bool32 sub_8143EF4(const u8 * src)
{
const u8 * r5 = (const u8 *)&gSaveBlock1Ptr->unk_3120.buffer_000.data;
u32 i;
- if (!sub_8143E1C())
+ if (!ValidateReceivedWonderNews())
return FALSE;
for (i = 0; i < sizeof(struct MEventBuffer_3120_Sub); i++)
{
@@ -580,7 +580,7 @@ bool32 sub_8143EF4(const u8 * src)
return TRUE;
}
-void sub_8143F38(void)
+void DestroyWonderCard(void)
{
sub_814407C();
sub_81440B4();
@@ -597,7 +597,7 @@ bool32 sub_8143F68(const struct MEventBuffer_32E0_Sub * data)
struct MEventBuffer_32E0_Sub * r1;
if (!sub_8144018(data))
return FALSE;
- sub_8143F38();
+ DestroyWonderCard();
memcpy(&gSaveBlock1Ptr->unk_3120.buffer_1c0.data, data, sizeof(struct MEventBuffer_32E0_Sub));
gSaveBlock1Ptr->unk_3120.buffer_1c0.crc = CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_3120.buffer_1c0.data, sizeof(struct MEventBuffer_32E0_Sub));
r2 = &gSaveBlock1Ptr->unk_3120.buffer_310.data;
@@ -606,7 +606,7 @@ bool32 sub_8143F68(const struct MEventBuffer_32E0_Sub * data)
return TRUE;
}
-bool32 sub_8143FC8(void)
+bool32 ValidateReceivedWonderCard(void)
{
if (gSaveBlock1Ptr->unk_3120.buffer_1c0.crc != CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_3120.buffer_1c0.data, sizeof(struct MEventBuffer_32E0_Sub)))
return FALSE;
@@ -632,7 +632,7 @@ bool32 sub_8144018(const struct MEventBuffer_32E0_Sub * data)
return TRUE;
}
-bool32 sub_8144054(void)
+bool32 WonderCard_Test_Unk_08_6(void)
{
const struct MEventBuffer_32E0_Sub * data = &gSaveBlock1Ptr->unk_3120.buffer_1c0.data;
if (data->unk_08_6 == 0)
@@ -654,7 +654,7 @@ void sub_81440B4(void)
u16 sub_81440E8(void)
{
- if (sub_8143FC8())
+ if (ValidateReceivedWonderCard())
return gSaveBlock1Ptr->unk_3120.buffer_1c0.data.unk_00;
return 0;
}
@@ -672,7 +672,7 @@ bool32 sub_8144124(u16 a0)
return FALSE;
}
-bool32 sub_8144144(void)
+bool32 CheckReceivedGiftFromWonderCard(void)
{
u16 value = sub_81440E8();
if (!sub_8144124(value))
@@ -721,7 +721,7 @@ bool32 sub_81441F0(const u16 * data)
s32 sub_8144218(void)
{
struct MEventBuffer_32E0_Sub * data;
- if (!sub_8143FC8())
+ if (!ValidateReceivedWonderCard())
return 0;
data = &gSaveBlock1Ptr->unk_3120.buffer_1c0.data;
if (data->unk_08_0 != 1)
@@ -759,11 +759,11 @@ void sub_81442CC(struct MEventStruct_Unk1442CC * data)
data->unk_08 = 1;
data->unk_0C = 1;
data->unk_10 = 1;
- if (sub_8143FC8())
+ if (ValidateReceivedWonderCard())
{
- data->unk_14 = sav1_get_mevent_buffer_1()->unk_00;
+ data->unk_14 = GetSavedWonderCard()->unk_00;
data->unk_20 = *sav1_get_mevent_buffer_2();
- data->unk_44 = sav1_get_mevent_buffer_1()->unk_09;
+ data->unk_44 = GetSavedWonderCard()->unk_09;
}
else
data->unk_14 = 0;
@@ -945,7 +945,7 @@ bool32 sub_81446D0(u16 a0)
gUnknown_203F3BC = FALSE;
if (a0 == 0)
return FALSE;
- if (!sub_8143FC8())
+ if (!ValidateReceivedWonderCard())
return FALSE;
if (gSaveBlock1Ptr->unk_3120.buffer_1c0.data.unk_00 != a0)
return FALSE;
diff --git a/src/mevent_8145654.c b/src/mevent_8145654.c
index 65f515d1b..af3024bff 100644
--- a/src/mevent_8145654.c
+++ b/src/mevent_8145654.c
@@ -126,7 +126,7 @@ const struct UnkStruct_8467FB8 gUnknown_8467FB8[8] = {
{1, 0, 0, 7, gUnknown_8467A7C, gUnknown_8467CAC, gUnknown_846716C}
};
-bool32 sub_8145654(struct MEventBuffer_32E0_Sub * r5, struct MEventBuffer_3430_Sub * r6)
+bool32 InitWonderCardResources(struct MEventBuffer_32E0_Sub * r5, struct MEventBuffer_3430_Sub * r6)
{
if (r5 == NULL || r6 == NULL)
return FALSE;
@@ -145,7 +145,7 @@ bool32 sub_8145654(struct MEventBuffer_32E0_Sub * r5, struct MEventBuffer_3430_S
return TRUE;
}
-void sub_81456F0(void)
+void DestroyWonderCardResources(void)
{
if (gUnknown_203F3C8 != NULL)
{
@@ -155,7 +155,7 @@ void sub_81456F0(void)
}
}
-s32 sub_814571C(void)
+s32 FadeToWonderCardMenu(void)
{
if (gUnknown_203F3C8 == NULL)
return -1;
@@ -219,7 +219,7 @@ s32 sub_814571C(void)
return 0;
}
-s32 sub_814593C(bool32 flag)
+s32 FadeOutFromWonderCard(bool32 flag)
{
if (gUnknown_203F3C8 == NULL)
return -1;
@@ -252,7 +252,7 @@ s32 sub_814593C(bool32 flag)
FreeMonIconPalettes();
break;
case 5:
- sub_8142344(gUnknown_203F3B8, flag);
+ PrintMysteryGiftOrEReaderTopMenu(gGiftIsFromEReader, flag);
break;
case 6:
CopyBgTilemapBufferToVram(0);
@@ -508,7 +508,7 @@ const struct UnkStruct_8467FB8 gUnknown_8468720[] = {
{1, 0, 0, 0, gUnknown_84685B4, gUnknown_8468644, gUnknown_84680A0}
};
-bool32 sub_8146288(const struct MEventBuffer_3120_Sub * a0)
+bool32 InitWonderNewsResources(const struct MEventBuffer_3120_Sub * a0)
{
if (a0 == NULL)
return FALSE;
@@ -523,7 +523,7 @@ bool32 sub_8146288(const struct MEventBuffer_3120_Sub * a0)
return TRUE;
}
-void sub_81462EC(void)
+void DestroyWonderNewsResources(void)
{
if (gUnknown_203F3CC != NULL)
{
@@ -533,7 +533,7 @@ void sub_81462EC(void)
}
}
-s32 sub_8146318(void)
+s32 FadeToWonderNewsMenu(void)
{
if (gUnknown_203F3CC == NULL)
return -1;
@@ -608,7 +608,7 @@ s32 sub_8146318(void)
return 0;
}
-s32 sub_8146604(bool32 flag)
+s32 FadeOutFromWonderNews(bool32 flag)
{
if (gUnknown_203F3CC == NULL)
return -1;
@@ -653,10 +653,10 @@ s32 sub_8146604(bool32 flag)
}
break;
case 5:
- sub_8142344(gUnknown_203F3B8, flag);
+ PrintMysteryGiftOrEReaderTopMenu(gGiftIsFromEReader, flag);
break;
case 6:
- sub_8142420();
+ MG_DrawCheckerboardPattern();
CopyBgTilemapBufferToVram(0);
CopyBgTilemapBufferToVram(3);
BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0);
@@ -671,7 +671,7 @@ s32 sub_8146604(bool32 flag)
return 0;
}
-void sub_81467EC(void)
+void MENews_RemoveScrollIndicatorArrowPair(void)
{
if (!gUnknown_203F3CC->unk_01C0_0 && gUnknown_203F3CC->unk_01C1 != 0xFF)
{
@@ -682,7 +682,7 @@ void sub_81467EC(void)
}
-void sub_8146834(void)
+void MENews_AddScrollIndicatorArrowPair(void)
{
if (gUnknown_203F3CC->unk_01C0_0)
{
@@ -691,7 +691,7 @@ void sub_8146834(void)
}
}
-u8 sub_8146884(u16 input)
+u32 MENews_GetInput(u16 input)
{
if (gUnknown_203F3CC->unk_01C2_0)
{
diff --git a/src/mevent_server.c b/src/mevent_server.c
index 5e384ae0b..1c2dc4ced 100644
--- a/src/mevent_server.c
+++ b/src/mevent_server.c
@@ -11,12 +11,12 @@
#include "mevent.h"
#include "mevent_server.h"
-EWRAM_DATA struct mevent_srv_ish * s_mevent_srv_ish_ptr = NULL;
+EWRAM_DATA struct mevent_client * s_mevent_client_ptr = NULL;
EWRAM_DATA struct mevent_srv_common * s_mevent_srv_common_ptr = NULL;
-static void mevent_srv_ish_init(struct mevent_srv_ish *, u32, u32);
-static u32 mevent_srv_ish_exec(struct mevent_srv_ish *);
-static void mevent_srv_ish_free_resources(struct mevent_srv_ish *);
+static void mevent_client_init(struct mevent_client *, u32, u32);
+static u32 mevent_client_exec(struct mevent_client *);
+static void mevent_client_free_resources(struct mevent_client *);
static void mevent_srv_init_common(struct mevent_srv_common *, const void *, u32, u32);
static void mevent_srv_free_resources(struct mevent_srv_common *);
static u32 mevent_srv_exec_common(struct mevent_srv_common *);
@@ -25,44 +25,44 @@ extern const u8 gUnknown_84687E0[];
extern const struct mevent_cmd gUnknown_8468B6C[];
extern const struct mevent_cmd gUnknown_8468BCC[];
-void mevent_srv_ish_do_init(void)
+void mevent_client_do_init(void)
{
- s_mevent_srv_ish_ptr = AllocZeroed(sizeof(struct mevent_srv_ish));
- mevent_srv_ish_init(s_mevent_srv_ish_ptr, 1, 0);
+ s_mevent_client_ptr = AllocZeroed(sizeof(struct mevent_client));
+ mevent_client_init(s_mevent_client_ptr, 1, 0);
}
-u32 mevent_srv_ish_do_exec(u16 * a0)
+u32 mevent_client_do_exec(u16 * a0)
{
u32 result;
- if (s_mevent_srv_ish_ptr == NULL)
+ if (s_mevent_client_ptr == NULL)
return 6;
- result = mevent_srv_ish_exec(s_mevent_srv_ish_ptr);
+ result = mevent_client_exec(s_mevent_client_ptr);
if (result == 6)
{
- *a0 = s_mevent_srv_ish_ptr->param;
- mevent_srv_ish_free_resources(s_mevent_srv_ish_ptr);
- Free(s_mevent_srv_ish_ptr);
- s_mevent_srv_ish_ptr = NULL;
+ *a0 = s_mevent_client_ptr->param;
+ mevent_client_free_resources(s_mevent_client_ptr);
+ Free(s_mevent_client_ptr);
+ s_mevent_client_ptr = NULL;
}
return result;
}
-void mevent_srv_ish_inc_flag(void)
+void mevent_client_inc_flag(void)
{
- s_mevent_srv_ish_ptr->flag++;
+ s_mevent_client_ptr->flag++;
}
-void * mevent_srv_ish_get_buffer(void)
+void * mevent_client_get_buffer(void)
{
- return s_mevent_srv_ish_ptr->buffer;
+ return s_mevent_client_ptr->buffer;
}
-void mevent_srv_ish_set_param(u32 a0)
+void mevent_client_set_param(u32 a0)
{
- s_mevent_srv_ish_ptr->param = a0;
+ s_mevent_client_ptr->param = a0;
}
-static void mevent_srv_ish_init(struct mevent_srv_ish * svr, u32 sendPlayerNo, u32 recvPlayerNo)
+static void mevent_client_init(struct mevent_client * svr, u32 sendPlayerNo, u32 recvPlayerNo)
{
svr->unk_00 = 0;
svr->mainseqno = 0;
@@ -74,7 +74,7 @@ static void mevent_srv_ish_init(struct mevent_srv_ish * svr, u32 sendPlayerNo, u
mevent_srv_sub_init(&svr->manager, sendPlayerNo, recvPlayerNo);
}
-static void mevent_srv_ish_free_resources(struct mevent_srv_ish * svr)
+static void mevent_client_free_resources(struct mevent_client * svr)
{
Free(svr->sendBuffer);
Free(svr->recvBuffer);
@@ -82,20 +82,20 @@ static void mevent_srv_ish_free_resources(struct mevent_srv_ish * svr)
Free(svr->buffer);
}
-static void mevent_srv_ish_jmp_buffer(struct mevent_srv_ish * svr)
+static void mevent_client_jmp_buffer(struct mevent_client * svr)
{
memcpy(svr->cmdBuffer, svr->recvBuffer, ME_SEND_BUF_SIZE);
svr->cmdidx = 0;
}
-static void mevent_srv_ish_send_word(struct mevent_srv_ish * svr, u32 ident, u32 word)
+static void mevent_client_send_word(struct mevent_client * svr, u32 ident, u32 word)
{
CpuFill32(0, svr->sendBuffer, ME_SEND_BUF_SIZE);
*(u32 *)svr->sendBuffer = word;
mevent_srv_sub_init_send(&svr->manager, ident, svr->sendBuffer, sizeof(u32));
}
-static u32 ish_mainseq_0(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_0(struct mevent_client * svr)
{
// init
memcpy(svr->cmdBuffer, gUnknown_84687E0, ME_SEND_BUF_SIZE);
@@ -105,13 +105,13 @@ static u32 ish_mainseq_0(struct mevent_srv_ish * svr)
return 0;
}
-static u32 ish_mainseq_1(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_1(struct mevent_client * svr)
{
// done
return 6;
}
-static u32 ish_mainseq_2(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_2(struct mevent_client * svr)
{
// do recv
if (mevent_srv_sub_recv(&svr->manager))
@@ -122,7 +122,7 @@ static u32 ish_mainseq_2(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_3(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_3(struct mevent_client * svr)
{
// do send
if (mevent_srv_sub_send(&svr->manager))
@@ -133,7 +133,7 @@ static u32 ish_mainseq_3(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_4(struct mevent_client * svr)
{
// process command
struct mevent_cmd_ish * cmd = &svr->cmdBuffer[svr->cmdidx];
@@ -162,20 +162,20 @@ static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
svr->flag = 0;
break;
case 19:
- mevent_srv_ish_send_word(svr, 0x12, GetGameStat(cmd->parameter));
+ mevent_client_send_word(svr, 0x12, GetGameStat(cmd->parameter));
svr->mainseqno = 3;
svr->flag = 0;
break;
case 6:
if (svr->param == 0)
- mevent_srv_ish_jmp_buffer(svr);
+ mevent_client_jmp_buffer(svr);
break;
case 7:
if (svr->param == 1)
- mevent_srv_ish_jmp_buffer(svr);
+ mevent_client_jmp_buffer(svr);
break;
case 4:
- mevent_srv_ish_jmp_buffer(svr);
+ mevent_client_jmp_buffer(svr);
break;
case 5:
memcpy(svr->buffer, svr->recvBuffer, 0x40);
@@ -201,7 +201,7 @@ static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
mevent_srv_sub_init_send(&svr->manager, 0x11, svr->sendBuffer, sizeof(struct MEventStruct_Unk1442CC));
break;
case 14:
- mevent_srv_ish_send_word(svr, 0x13, svr->param);
+ mevent_client_send_word(svr, 0x13, svr->param);
break;
case 10:
sub_8143F68(svr->recvBuffer);
@@ -210,10 +210,10 @@ static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
if (!sub_8143EF4(svr->recvBuffer))
{
sub_8143DC8(svr->recvBuffer);
- mevent_srv_ish_send_word(svr, 0x13, 0);
+ mevent_client_send_word(svr, 0x13, 0);
}
else
- mevent_srv_ish_send_word(svr, 0x13, 1);
+ mevent_client_send_word(svr, 0x13, 1);
break;
case 15:
svr->mainseqno = 6;
@@ -239,7 +239,7 @@ static u32 ish_mainseq_4(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_5(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_5(struct mevent_client * svr)
{
// wait flag
if (svr->flag)
@@ -250,7 +250,7 @@ static u32 ish_mainseq_5(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_6(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_6(struct mevent_client * svr)
{
// ???
switch (svr->flag)
@@ -270,7 +270,7 @@ static u32 ish_mainseq_6(struct mevent_srv_ish * svr)
return 1;
}
-static u32 ish_mainseq_7(struct mevent_srv_ish * svr)
+static u32 ish_mainseq_7(struct mevent_client * svr)
{
// exec arbitrary code
u32 (*func)(u32 *, struct SaveBlock2 *, struct SaveBlock1 *) = (void *)gDecompressionBuffer;
@@ -282,9 +282,9 @@ static u32 ish_mainseq_7(struct mevent_srv_ish * svr)
return 1;
}
-static u32 mevent_srv_ish_exec(struct mevent_srv_ish * svr)
+static u32 mevent_client_exec(struct mevent_client * svr)
{
- u32 (*funcs[])(struct mevent_srv_ish *) = {
+ u32 (*funcs[])(struct mevent_client *) = {
ish_mainseq_0,
ish_mainseq_1,
ish_mainseq_2,
@@ -297,19 +297,19 @@ static u32 mevent_srv_ish_exec(struct mevent_srv_ish * svr)
return funcs[svr->mainseqno](svr);
}
-void mevent_srv_common_do_init_1(void)
+void mevent_srv_init_wnews(void)
{
s_mevent_srv_common_ptr = AllocZeroed(sizeof(struct mevent_srv_common));
mevent_srv_init_common(s_mevent_srv_common_ptr, gUnknown_8468B6C, 0, 1);
}
-void mevent_srv_common_do_init_2(void)
+void mevent_srv_new_wcard(void)
{
s_mevent_srv_common_ptr = AllocZeroed(sizeof(struct mevent_srv_common));
mevent_srv_init_common(s_mevent_srv_common_ptr, gUnknown_8468BCC, 0, 1);
}
-u32 mevent_srv_init_do_exec(u16 * a0)
+u32 mevent_srv_common_do_exec(u16 * a0)
{
u32 result;
if (s_mevent_srv_common_ptr == NULL)
@@ -526,12 +526,12 @@ static u32 common_mainseq_4(struct mevent_srv_common * svr)
break;
case 26:
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/mevent_server.c", 506);
- memcpy(svr->mevent_32e0, sav1_get_mevent_buffer_1(), 332);
+ memcpy(svr->mevent_32e0, GetSavedWonderCard(), 332);
sub_814410C(svr->mevent_32e0);
break;
case 27:
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/mevent_server.c", 512);
- memcpy(svr->mevent_3120, sub_8143D58(), 444);
+ memcpy(svr->mevent_3120, GetSavedWonderNews(), 444);
break;
case 28:
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, "C:/WORK/POKeFRLG/src/pm_lgfr_ose/source/mevent_server.c", 517);
diff --git a/src/mystery_gift_menu.c b/src/mystery_gift_menu.c
new file mode 100644
index 000000000..0cbfb4be5
--- /dev/null
+++ b/src/mystery_gift_menu.c
@@ -0,0 +1,1756 @@
+#include "global.h"
+#include "palette.h"
+#include "dma3.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "task.h"
+#include "scanline_effect.h"
+#include "malloc.h"
+#include "text.h"
+#include "window.h"
+#include "text_window.h"
+#include "menu.h"
+#include "new_menu_helpers.h"
+#include "sound.h"
+#include "mystery_gift_menu.h"
+#include "title_screen.h"
+#include "list_menu.h"
+#include "link_rfu.h"
+#include "string_util.h"
+#include "mevent.h"
+#include "save.h"
+#include "link.h"
+#include "event_data.h"
+#include "mevent_server.h"
+#include "menews_jisan.h"
+#include "help_system.h"
+#include "constants/songs.h"
+
+EWRAM_DATA u8 sDownArrowCounterAndYCoordIdx[8] = {};
+EWRAM_DATA bool8 gGiftIsFromEReader = FALSE;
+
+void task_add_00_mystery_gift(void);
+void task00_mystery_gift(u8 taskId);
+void task_add_00_ereader(void);
+
+extern const u8 gText_PickOKExit[];
+extern const u8 gText_PickOKCancel[];
+extern const u8 gText_MysteryGift[];
+extern const u8 gJPText_MysteryGift[];
+extern const u8 gJPText_DecideStop[];
+extern const u8 gText_WhatToDoWithCards[];
+extern const u8 gText_WhatToDoWithNews[];
+extern const u8 gText_OkayToDiscardNews[];
+extern const u8 gText_IfThrowAwayCardEventWontHappen[];
+extern const u8 gText_WonderCardThrownAway[];
+extern const u8 gText_WonderNewsThrownAway[];
+extern const u8 gText_DataWillBeSaved[];
+extern const u8 gText_SaveCompletedPressA[];
+extern const u8 gText_WonderCards[];
+extern const u8 gText_WonderNews[];
+extern const u8 gText_Exit3[];
+extern const u8 gText_WirelessCommunication[];
+extern const u8 gText_Friend2[];
+extern const u8 gFameCheckerText_Cancel[];
+extern const u8 gText_Receive[];
+extern const u8 gText_Send[];
+extern const u8 gText_Toss[];
+extern const u8 gText_VarietyOfEventsImportedWireless[];
+extern const u8 gText_WonderCardsInPossession[];
+extern const u8 gText_ReadNewsThatArrived[];
+extern const u8 gText_ReturnToTitle[];
+extern const u8 gText_NothingSentOver[];
+extern const u8 gText_RecordUploadedViaWireless[];
+extern const u8 gText_WonderCardReceived[];
+extern const u8 gText_WonderCardReceivedFrom[];
+extern const u8 gText_WonderNewsReceived[];
+extern const u8 gText_WonderNewsReceivedFrom[];
+extern const u8 gText_NewStampReceived[];
+extern const u8 gText_AlreadyHadCard[];
+extern const u8 gText_AlreadyHadStamp[];
+extern const u8 gText_AlreadyHadNews[];
+extern const u8 gText_NoMoreRoomForStamps[];
+extern const u8 gText_CommunicationCanceled[];
+extern const u8 gText_CantAcceptCardFromTrainer[];
+extern const u8 gText_CantAcceptNewsFromTrainer[];
+extern const u8 gText_CommunicationError[];
+extern const u8 gText_NewTrainerReceived[];
+extern const u8 gText_WonderCardSentTo[];
+extern const u8 gText_WonderNewsSentTo[];
+extern const u8 gText_StampSentTo[];
+extern const u8 gText_OtherTrainerHasCard[];
+extern const u8 gText_OtherTrainerHasStamp[];
+extern const u8 gText_OtherTrainerHasNews[];
+extern const u8 gText_OtherTrainerCanceled[];
+extern const u8 gText_GiftSentTo[];
+extern const u8 gText_CantSendGiftToTrainer[];
+extern const u8 gText_DontHaveCardNewOneInput[];
+extern const u8 gText_DontHaveNewsNewOneInput[];
+extern const u8 gText_WhereShouldCardBeAccessed[];
+extern const u8 gText_WhereShouldNewsBeAccessed[];
+extern const u8 gText_Communicating[];
+extern const u8 gText_ThrowAwayWonderCard[];
+extern const u8 gText_HaventReceivedCardsGift[];
+extern const u8 gText_CommunicationCompleted[];
+extern const u8 gText_HaventReceivedGiftOkayToDiscard[];
+extern const u8 gText_SendingWonderCard[];
+extern const u8 gText_SendingWonderNews[];
+
+const u16 gUnkTextboxBorderPal[] = INCBIN_U16("graphics/interface/unk_textbox_border.gbapal");
+const u32 gUnkTextboxBorderGfx[] = INCBIN_U32("graphics/interface/unk_textbox_border.4bpp.lz");
+
+struct MysteryGiftTaskData
+{
+ u16 curPromptWindowId;
+ u16 unk2;
+ u16 unk4;
+ u16 unk6;
+ u8 state;
+ u8 textState;
+ u8 unkA;
+ u8 unkB;
+ u8 IsCardOrNews;
+ u8 source;
+ u8 prevPromptWindowId;
+ u8 * buffer;
+};
+
+const struct BgTemplate sBGTemplates[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 15,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 14,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0x000
+ }, {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 13,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x000
+ }, {
+ .bg = 3,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 12,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x000
+ }
+};
+
+const struct WindowTemplate sMainWindows[] = {
+ {
+ .priority = 0x00,
+ .tilemapLeft = 0x00,
+ .tilemapTop = 0x00,
+ .width = 0x1e,
+ .height = 0x02,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0013
+ }, {
+ .priority = 0x00,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x0f,
+ .width = 0x1c,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x004f
+ }, {
+ .priority = 0x00,
+ .tilemapLeft = 0x00,
+ .tilemapTop = 0x0f,
+ .width = 0x1e,
+ .height = 0x05,
+ .paletteNum = 0x0d,
+ .baseBlock = 0x004f
+ }, {
+ 0xFF
+ }
+};
+
+const struct WindowTemplate sWindowTemplate_PromptYesOrNo_Width28 = {
+ .priority = 0x00,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x0f,
+ .width = 0x1c,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x00e5
+};
+
+const struct WindowTemplate sWindowTemplate_PromptYesOrNo_Width20 = {
+ .priority = 0x00,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x0f,
+ .width = 0x14,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x00e5
+};
+
+const struct WindowTemplate sMysteryGiftMenuWindowTemplate = {
+ .priority = 0x00,
+ .tilemapLeft = 0x01,
+ .tilemapTop = 0x0f,
+ .width = 0x13,
+ .height = 0x04,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x00e5
+};
+
+const struct WindowTemplate sWindowTemplate_ThreeOptions = {
+ .priority = 0x00,
+ .tilemapLeft = 0x08,
+ .tilemapTop = 0x05,
+ .width = 0x0e,
+ .height = 0x05,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct WindowTemplate sWindowTemplate_YesNoBox = {
+ .priority = 0x00,
+ .tilemapLeft = 0x17,
+ .tilemapTop = 0x0f,
+ .width = 0x06,
+ .height = 0x04,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct WindowTemplate sWindowTemplate_7by8 = {
+ .priority = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0c,
+ .width = 0x07,
+ .height = 0x07,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct WindowTemplate sWindowTemplate_7by6 = {
+ .priority = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0e,
+ .width = 0x07,
+ .height = 0x05,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct WindowTemplate sWindowTemplate_7by4 = {
+ .priority = 0x00,
+ .tilemapLeft = 0x16,
+ .tilemapTop = 0x0f,
+ .width = 0x07,
+ .height = 0x04,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x0155
+};
+
+const struct ListMenuItem sListMenuItems_CardsOrNews[] = {
+ { gText_WonderCards, 0 },
+ { gText_WonderNews, 1 },
+ { gText_Exit3, -2 }
+};
+
+const struct ListMenuItem sListMenuItems_WirelessOrFriend[] = {
+ { gText_WirelessCommunication, 0 },
+ { gText_Friend2, 1 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuTemplate sListMenuTemplate_ThreeOptions = {
+ .items = NULL,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const struct ListMenuItem sListMenuItems_ReceiveSendToss[] = {
+ { gText_Receive, 0 },
+ { gText_Send, 1 },
+ { gText_Toss, 2 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuItem sListMenuItems_ReceiveToss[] = {
+ { gText_Receive, 0 },
+ { gText_Toss, 2 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuItem sListMenuItems_ReceiveSend[] = {
+ { gText_Receive, 0 },
+ { gText_Send, 1 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuItem sListMenuItems_Receive[] = {
+ { gText_Receive, 0 },
+ { gFameCheckerText_Cancel, -2 }
+};
+
+const struct ListMenuTemplate sListMenu_ReceiveSendToss = {
+ .items = sListMenuItems_ReceiveSendToss,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 4,
+ .maxShowed = 4,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 2,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const struct ListMenuTemplate sListMenu_ReceiveToss = {
+ .items = sListMenuItems_ReceiveToss,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const struct ListMenuTemplate sListMenu_ReceiveSend = {
+ .items = sListMenuItems_ReceiveSend,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const struct ListMenuTemplate sListMenu_Receive = {
+ .items = sListMenuItems_Receive,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 2,
+ .maxShowed = 2,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 2,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0
+};
+
+const u8 *const Unref_08366ED8[] = {
+ gText_VarietyOfEventsImportedWireless,
+ gText_WonderCardsInPossession,
+ gText_ReadNewsThatArrived,
+ gText_ReturnToTitle
+};
+
+ALIGNED(4) const struct TextColor sMG_Ereader_TextColor_1 = { 0, 1, 2 };
+ALIGNED(4) const struct TextColor sMG_Ereader_TextColor_1_Copy = { 0, 1, 2 };
+ALIGNED(4) const struct TextColor sMG_Ereader_TextColor_2 = { 1, 2, 3 };
+
+const u8 gUnknown_8466EF3[] = _("テスト");
+const u8 gUnknown_8466EF7[] = _("むげんのチケット");
+
+void vblankcb_mystery_gift_e_reader_run(void)
+{
+ ProcessSpriteCopyRequests();
+ LoadOam();
+ TransferPlttBuffer();
+}
+
+void c2_mystery_gift_e_reader_run(void)
+{
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+}
+
+bool32 HandleMysteryGiftOrEReaderSetup(s32 mg_or_ereader)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL);
+ ResetPaletteFade();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetTasks();
+ ScanlineEffect_Stop();
+ ResetBgsAndClearDma3BusyFlags(1);
+
+ InitBgsFromTemplates(0, sBGTemplates, ARRAY_COUNT(sBGTemplates));
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ ChangeBgX(3, 0, 0);
+ ChangeBgY(3, 0, 0);
+
+ SetBgTilemapBuffer(3, Alloc(0x800));
+ SetBgTilemapBuffer(2, Alloc(0x800));
+ SetBgTilemapBuffer(1, Alloc(0x800));
+ SetBgTilemapBuffer(0, Alloc(0x800));
+
+ sub_814FE40(0, 10, 0xE0);
+ sub_814FDA0(0, 1, 0xF0);
+ sub_80F696C(3, gUnkTextboxBorderGfx, 0x100, 0, 0);
+ InitWindows(sMainWindows);
+ DeactivateAllTextPrinters();
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ gMain.state++;
+ break;
+ case 1:
+ LoadPalette(gUnkTextboxBorderPal, 0, 0x20);
+ LoadPalette(stdpal_get(2), 0xd0, 0x20);
+ FillBgTilemapBufferRect(0, 0x000, 0, 0, 32, 32, 0x11);
+ FillBgTilemapBufferRect(1, 0x000, 0, 0, 32, 32, 0x11);
+ FillBgTilemapBufferRect(2, 0x000, 0, 0, 32, 32, 0x11);
+ MG_DrawCheckerboardPattern();
+ PrintMysteryGiftOrEReaderTopMenu(mg_or_ereader, 0);
+ gMain.state++;
+ break;
+ case 2:
+ CopyBgTilemapBufferToVram(3);
+ CopyBgTilemapBufferToVram(2);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(0);
+ gMain.state++;
+ break;
+ case 3:
+ ShowBg(0);
+ ShowBg(3);
+ PlayBGM(BGM_FRLG_MYSTERY_GIFT);
+ SetVBlankCallback(vblankcb_mystery_gift_e_reader_run);
+ EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void c2_mystery_gift(void)
+{
+ if (HandleMysteryGiftOrEReaderSetup(0))
+ {
+ SetMainCallback2(c2_mystery_gift_e_reader_run);
+ gGiftIsFromEReader = FALSE;
+ task_add_00_mystery_gift();
+ }
+}
+
+void c2_ereader(void)
+{
+ if (HandleMysteryGiftOrEReaderSetup(1))
+ {
+ SetMainCallback2(c2_mystery_gift_e_reader_run);
+ gGiftIsFromEReader = TRUE;
+ task_add_00_ereader();
+ }
+}
+
+void MainCB_FreeAllBuffersAndReturnToInitTitleScreen(void)
+{
+ gGiftIsFromEReader = FALSE;
+ FreeAllWindowBuffers();
+ Free(GetBgTilemapBuffer(0));
+ Free(GetBgTilemapBuffer(1));
+ Free(GetBgTilemapBuffer(2));
+ Free(GetBgTilemapBuffer(3));
+ SetMainCallback2(CB2_InitTitleScreen);
+}
+
+void PrintMysteryGiftOrEReaderTopMenu(bool8 mg_or_ereader, bool32 usePickOkCancel)
+{
+ const u8 * src;
+ s32 width;
+ FillWindowPixelBuffer(0, 0x00);
+ if (!mg_or_ereader)
+ {
+ src = usePickOkCancel == TRUE ? gText_PickOKExit : gText_PickOKCancel;
+ AddTextPrinterParametrized2(0, 2, 2, 2, 0, 0, &sMG_Ereader_TextColor_1, 0, gText_MysteryGift);
+ width = 222 - GetStringWidth(0, src, 0);
+ AddTextPrinterParametrized2(0, 0, width, 2, 0, 0, &sMG_Ereader_TextColor_1, 0, src);
+ }
+ else
+ {
+ AddTextPrinterParametrized2(0, 2, 2, 2, 0, 0, &sMG_Ereader_TextColor_1, 0, gJPText_MysteryGift);
+ AddTextPrinterParametrized2(0, 0, 0x78, 2, 0, 0, &sMG_Ereader_TextColor_1, 0, gJPText_DecideStop);
+ }
+ CopyWindowToVram(0, 2);
+ PutWindowTilemap(0);
+}
+
+void MG_DrawTextBorder(u8 windowId)
+{
+ DrawTextBorderOuter(windowId, 0x01, 0xF);
+}
+
+void MG_DrawCheckerboardPattern(void)
+{
+ s32 i = 0, j;
+
+ FillBgTilemapBufferRect(3, 0x003, 0, 0, 32, 2, 0x11);
+
+ for (i = 0; i < 18; i++)
+ {
+ for (j = 0; j < 32; j++)
+ {
+ if ((i & 1) != (j & 1))
+ {
+ FillBgTilemapBufferRect(3, 1, j, i + 2, 1, 1, 0x11);
+ }
+ else
+ {
+ FillBgTilemapBufferRect(3, 2, j, i + 2, 1, 1, 0x11);
+ }
+ }
+ }
+}
+
+void ClearScreenInBg0(bool32 ignoreTopTwoRows)
+{
+ switch (ignoreTopTwoRows)
+ {
+ case 0:
+ FillBgTilemapBufferRect(0, 0, 0, 0, 32, 32, 0x11);
+ break;
+ case 1:
+ FillBgTilemapBufferRect(0, 0, 0, 2, 32, 30, 0x11);
+ break;
+ }
+ CopyBgTilemapBufferToVram(0);
+}
+
+void AddTextPrinterToWindow1(const u8 *str)
+{
+ StringExpandPlaceholders(gStringVar4, str);
+ FillWindowPixelBuffer(1, 0x11);
+ AddTextPrinterParametrized2(1, 2, 0, 2, 0, 2, &sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(1, 0x001, 0xF);
+ PutWindowTilemap(1);
+ CopyWindowToVram(1, 3);
+}
+
+void ClearTextWindow(void)
+{
+ rbox_fill_rectangle(1);
+ ClearWindowTilemap(1);
+ CopyWindowToVram(1, 1);
+}
+
+bool32 MG_PrintTextOnWindow1AndWaitButton(u8 *textState, const u8 *str)
+{
+ switch (*textState)
+ {
+ case 0:
+ AddTextPrinterToWindow1(str);
+ goto inc;
+ case 1:
+ DrawDownArrow(1, 0xD0, 0x14, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ inc:
+ (*textState)++;
+ }
+ break;
+ case 2:
+ DrawDownArrow(1, 0xD0, 0x14, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ *textState = 0;
+ ClearTextWindow();
+ return TRUE;
+ case 0xFF:
+ *textState = 2;
+ break;
+ }
+ return FALSE;
+}
+
+void HideDownArrow(void)
+{
+ DrawDownArrow(1, 0xD0, 0x14, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+}
+
+void ShowDownArrow(void)
+{
+ DrawDownArrow(1, 0xD0, 0x14, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+}
+
+bool32 unref_HideDownArrowAndWaitButton(u8 * textState)
+{
+ switch (*textState)
+ {
+ case 0:
+ HideDownArrow();
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ (*textState)++;
+ }
+ break;
+ case 1:
+ ShowDownArrow();
+ *textState = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool32 PrintStringAndWait2Seconds(u8 * counter, const u8 * str)
+{
+ if (*counter == 0)
+ {
+ AddTextPrinterToWindow1(str);
+ }
+ if (++(*counter) > 120)
+ {
+ *counter = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+u32 MysteryGift_HandleThreeOptionMenu(u8 * unused0, u16 * unused1, u8 whichMenu)
+{
+ struct ListMenuTemplate listMenuTemplate = sListMenuTemplate_ThreeOptions;
+ struct WindowTemplate windowTemplate = sWindowTemplate_ThreeOptions;
+ u32 width;
+ s32 finalWidth;
+ s32 response;
+ u32 i;
+
+ if (whichMenu == 0)
+ {
+ listMenuTemplate.items = sListMenuItems_CardsOrNews;
+ }
+ else
+ {
+ listMenuTemplate.items = sListMenuItems_WirelessOrFriend;
+ }
+ width = 0;
+ for (i = 0; i < listMenuTemplate.totalItems; i++)
+ {
+ u32 curWidth = GetStringWidth(2, listMenuTemplate.items[i].unk_00, listMenuTemplate.lettersSpacing);
+ if (curWidth > width)
+ width = curWidth;
+ }
+ finalWidth = (((width + 9) / 8) + 2) & ~1;
+ windowTemplate.width = finalWidth;
+ windowTemplate.tilemapLeft = (30 - finalWidth) / 2;
+ response = DoMysteryGiftListMenu(&windowTemplate, &listMenuTemplate, 1, 0x00A, 0xE0);
+ if (response != -1)
+ {
+ ClearWindowTilemap(2);
+ CopyWindowToVram(2, 1);
+ }
+ return response;
+}
+
+s8 mevent_message_print_and_prompt_yes_no(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str)
+{
+ struct WindowTemplate windowTemplate;
+ s8 input;
+
+ switch (*textState)
+ {
+ case 0:
+ StringExpandPlaceholders(gStringVar4, str);
+ if (yesNoBoxPlacement == 0)
+ {
+ *windowId = AddWindow(&sWindowTemplate_PromptYesOrNo_Width28);
+ }
+ else
+ {
+ *windowId = AddWindow(&sWindowTemplate_PromptYesOrNo_Width20);
+ }
+ FillWindowPixelBuffer(*windowId, 0x11);
+ AddTextPrinterParametrized2(*windowId, 2, 0, 2, 0, 2, &sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(*windowId, 0x001, 0x0F);
+ CopyWindowToVram(*windowId, 2);
+ PutWindowTilemap(*windowId);
+ (*textState)++;
+ break;
+ case 1:
+ windowTemplate = sWindowTemplate_YesNoBox;
+ if (yesNoBoxPlacement == 0)
+ {
+ windowTemplate.tilemapTop = 9;
+ }
+ else
+ {
+ windowTemplate.tilemapTop = 15;
+ }
+ sub_810FF60(&windowTemplate, 2, 0, 2, 10, 14, 0);
+ (*textState)++;
+ break;
+ case 2:
+ input = ProcessMenuInputNoWrap_();
+ if (input == -1 || input == 0 || input == 1)
+ {
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return input;
+ }
+ break;
+ case 0xFF:
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return -1;
+ }
+
+ return -2;
+}
+
+s32 HandleMysteryGiftListMenu(u8 * textState, u16 * windowId, bool32 cannotToss, bool32 cannotSend)
+{
+ struct WindowTemplate windowTemplate;
+ s32 input;
+
+ switch (*textState)
+ {
+ case 0:
+ if (cannotToss == 0)
+ {
+ StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithCards);
+ }
+ else
+ {
+ StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithNews);
+ }
+ *windowId = AddWindow(&sMysteryGiftMenuWindowTemplate);
+ FillWindowPixelBuffer(*windowId, 0x11);
+ AddTextPrinterParametrized2(*windowId, 2, 0, 2, 0, 2, &sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(*windowId, 0x001, 0x0F);
+ CopyWindowToVram(*windowId, 2);
+ PutWindowTilemap(*windowId);
+ (*textState)++;
+ break;
+ case 1:
+ windowTemplate = sWindowTemplate_YesNoBox;
+ if (cannotSend)
+ {
+ if (cannotToss == 0)
+ {
+ input = DoMysteryGiftListMenu(&sWindowTemplate_7by6, &sListMenu_ReceiveToss, 1, 0x00A, 0xE0);
+ }
+ else
+ {
+ input = DoMysteryGiftListMenu(&sWindowTemplate_7by4, &sListMenu_Receive, 1, 0x00A, 0xE0);
+ }
+ }
+ else
+ {
+ if (cannotToss == 0)
+ {
+ input = DoMysteryGiftListMenu(&sWindowTemplate_7by8, &sListMenu_ReceiveSendToss, 1, 0x00A, 0xE0);
+ }
+ else
+ {
+ input = DoMysteryGiftListMenu(&sWindowTemplate_7by6, &sListMenu_ReceiveSend, 1, 0x00A, 0xE0);
+ }
+ }
+ if (input != -1)
+ {
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return input;
+ }
+ break;
+ case 0xFF:
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return -2;
+ }
+
+ return -1;
+}
+
+bool32 ValidateCardOrNews(bool32 cardOrNews)
+{
+ if (cardOrNews == 0)
+ {
+ return ValidateReceivedWonderCard();
+ }
+ else
+ {
+ return ValidateReceivedWonderNews();
+ }
+}
+
+bool32 HandleLoadWonderCardOrNews(u8 * state, bool32 cardOrNews)
+{
+ s32 v0;
+
+ switch (*state)
+ {
+ case 0:
+ if (cardOrNews == 0)
+ {
+ InitWonderCardResources(GetSavedWonderCard(), sav1_get_mevent_buffer_2());
+ }
+ else
+ {
+ InitWonderNewsResources(GetSavedWonderNews());
+ }
+ (*state)++;
+ break;
+ case 1:
+ if (cardOrNews == 0)
+ {
+ v0 = FadeToWonderCardMenu();
+ check:
+ if (v0 != 0)
+ {
+ goto done;
+ }
+ break;
+ }
+ else
+ {
+ v0 = FadeToWonderNewsMenu();
+ goto check;
+ }
+ done:
+ *state = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+bool32 DestroyNewsOrCard(bool32 cardOrNews)
+{
+ if (cardOrNews == 0)
+ {
+ DestroyWonderCard();
+ }
+ else
+ {
+ DestroyWonderNews();
+ }
+ return TRUE;
+}
+
+bool32 TearDownCardOrNews_ReturnToTopMenu(bool32 cardOrNews, bool32 arg1)
+{
+ if (cardOrNews == 0)
+ {
+ if (FadeOutFromWonderCard(arg1) != 0)
+ {
+ DestroyWonderCardResources();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (FadeOutFromWonderNews(arg1) != 0)
+ {
+ DestroyWonderNewsResources();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+}
+
+s32 mevent_message_prompt_discard(u8 * textState, u16 * windowId, bool32 cardOrNews)
+{
+ if (cardOrNews == 0)
+ {
+ return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_IfThrowAwayCardEventWontHappen);
+ }
+ else
+ {
+ return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_OkayToDiscardNews);
+ }
+}
+
+bool32 mevent_message_was_thrown_away(u8 * textState, bool32 cardOrNews)
+{
+ if (cardOrNews == 0)
+ {
+ return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderCardThrownAway);
+ }
+ else
+ {
+ return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderNewsThrownAway);
+ }
+}
+
+bool32 mevent_save_game(u8 * state)
+{
+ switch (*state)
+ {
+ case 0:
+ AddTextPrinterToWindow1(gText_DataWillBeSaved);
+ (*state)++;
+ break;
+ case 1:
+ TrySavingData(0);
+ (*state)++;
+ break;
+ case 2:
+ AddTextPrinterToWindow1(gText_SaveCompletedPressA);
+ (*state)++;
+ break;
+ case 3:
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ {
+ (*state)++;
+ }
+ break;
+ case 4:
+ *state = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+const u8 * mevent_message(u32 * flag_p, u8 cardOrNews, u8 cardOrNewsSource, u32 msgId)
+{
+ const u8 * msg = NULL;
+ *flag_p = 0;
+
+ switch (msgId)
+ {
+ case 0:
+ *flag_p = 0;
+ msg = gText_NothingSentOver;
+ break;
+ case 1:
+ *flag_p = 0;
+ msg = gText_RecordUploadedViaWireless;
+ break;
+ case 2:
+ *flag_p = 1;
+ msg = cardOrNewsSource == 0 ? gText_WonderCardReceived : gText_WonderCardReceivedFrom;
+ break;
+ case 3:
+ *flag_p = 1;
+ msg = cardOrNewsSource == 0 ? gText_WonderNewsReceived : gText_WonderNewsReceivedFrom;
+ break;
+ case 4:
+ *flag_p = 1;
+ msg = gText_NewStampReceived;
+ break;
+ case 5:
+ *flag_p = 0;
+ msg = gText_AlreadyHadCard;
+ break;
+ case 6:
+ *flag_p = 0;
+ msg = gText_AlreadyHadStamp;
+ break;
+ case 7:
+ *flag_p = 0;
+ msg = gText_AlreadyHadNews;
+ break;
+ case 8:
+ *flag_p = 0;
+ msg = gText_NoMoreRoomForStamps;
+ break;
+ case 9:
+ *flag_p = 0;
+ msg = gText_CommunicationCanceled;
+ break;
+ case 10:
+ *flag_p = 0;
+ msg = cardOrNews == 0 ? gText_CantAcceptCardFromTrainer : gText_CantAcceptNewsFromTrainer;
+ break;
+ case 11:
+ *flag_p = 0;
+ msg = gText_CommunicationError;
+ break;
+ case 12:
+ *flag_p = 1;
+ msg = gText_NewTrainerReceived;
+ break;
+ case 13:
+ *flag_p = 1;
+ break;
+ case 14:
+ *flag_p = 0;
+ break;
+ }
+
+ return msg;
+}
+
+bool32 PrintMGSuccessMessage(u8 * state, const u8 * arg1, u16 * arg2)
+{
+ switch (*state)
+ {
+ case 0:
+ if (arg1 != NULL)
+ {
+ AddTextPrinterToWindow1(arg1);
+ }
+ PlayFanfare(MUS_FANFA4);
+ *arg2 = 0;
+ (*state)++;
+ break;
+ case 1:
+ if (++(*arg2) > 0xF0)
+ {
+ (*state)++;
+ }
+ break;
+ case 2:
+ if (IsFanfareTaskInactive())
+ {
+ *state = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+const u8 * mevent_message_stamp_card_etc_send_status(u32 * a0, u8 unused, u32 msgId)
+{
+ const u8 * result = gText_CommunicationError;
+ *a0 = 0;
+ switch (msgId)
+ {
+ case 0:
+ result = gText_NothingSentOver;
+ break;
+ case 1:
+ result = gText_RecordUploadedViaWireless;
+ break;
+ case 2:
+ result = gText_WonderCardSentTo;
+ *a0 = 1;
+ break;
+ case 3:
+ result = gText_WonderNewsSentTo;
+ *a0 = 1;
+ break;
+ case 4:
+ result = gText_StampSentTo;
+ break;
+ case 5:
+ result = gText_OtherTrainerHasCard;
+ break;
+ case 6:
+ result = gText_OtherTrainerHasStamp;
+ break;
+ case 7:
+ result = gText_OtherTrainerHasNews;
+ break;
+ case 8:
+ result = gText_NoMoreRoomForStamps;
+ break;
+ case 9:
+ result = gText_OtherTrainerCanceled;
+ break;
+ case 10:
+ result = gText_CantSendGiftToTrainer;
+ break;
+ case 11:
+ result = gText_CommunicationError;
+ break;
+ case 12:
+ result = gText_GiftSentTo;
+ break;
+ case 13:
+ result = gText_GiftSentTo;
+ break;
+ case 14:
+ result = gText_CantSendGiftToTrainer;
+ break;
+ }
+ return result;
+}
+
+bool32 PrintMGSendStatus(u8 * state, u16 * arg1, u8 arg2, u32 msgId)
+{
+ u32 flag;
+ const u8 * str = mevent_message_stamp_card_etc_send_status(&flag, arg2, msgId);
+ if (flag)
+ {
+ return PrintMGSuccessMessage(state, str, arg1);
+ }
+ else
+ {
+ return MG_PrintTextOnWindow1AndWaitButton(state, str);
+ }
+}
+
+void task_add_00_mystery_gift(void)
+{
+ u8 taskId = CreateTask(task00_mystery_gift, 0);
+ struct MysteryGiftTaskData * data = (void *)gTasks[taskId].data;
+ data->state = 0;
+ data->textState = 0;
+ data->unkA = 0;
+ data->unkB = 0;
+ data->IsCardOrNews = 0;
+ data->source = 0;
+ data->curPromptWindowId = 0;
+ data->unk2 = 0;
+ data->unk4 = 0;
+ data->unk6 = 0;
+ data->prevPromptWindowId = 0;
+ data->buffer = AllocZeroed(0x40);
+}
+
+void task00_mystery_gift(u8 taskId)
+{
+ struct MysteryGiftTaskData * data = (void *)gTasks[taskId].data;
+ u32 sp0;
+ const u8 * r1;
+
+ switch (data->state)
+ {
+ case 0:
+ data->state = 1;
+ break;
+ case 1:
+ switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->curPromptWindowId, FALSE))
+ {
+ case 0:
+ data->IsCardOrNews = 0;
+ if (ValidateReceivedWonderCard() == TRUE)
+ {
+ data->state = 18;
+ }
+ else
+ {
+ data->state = 2;
+ }
+ break;
+ case 1:
+ data->IsCardOrNews = 1;
+ if (ValidateReceivedWonderNews() == TRUE)
+ {
+ data->state = 18;
+ }
+ else
+ {
+ data->state = 2;
+ }
+ break;
+ case -2u:
+ data->state = 37;
+ break;
+ }
+ break;
+ case 2:
+ {
+ if (data->IsCardOrNews == 0)
+ {
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveCardNewOneInput))
+ {
+ data->state = 3;
+ PrintMysteryGiftOrEReaderTopMenu(0, 1);
+ }
+ }
+ else
+ {
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveNewsNewOneInput))
+ {
+ data->state = 3;
+ PrintMysteryGiftOrEReaderTopMenu(0, 1);
+ }
+ }
+ break;
+ }
+ case 3:
+ if (data->IsCardOrNews == 0)
+ {
+ AddTextPrinterToWindow1(gText_WhereShouldCardBeAccessed);
+ }
+ else
+ {
+ AddTextPrinterToWindow1(gText_WhereShouldNewsBeAccessed);
+ }
+ data->state = 4;
+ break;
+ case 4:
+ switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->curPromptWindowId, TRUE))
+ {
+ case 0:
+ ClearTextWindow();
+ data->state = 5;
+ data->source = 0;
+ break;
+ case 1:
+ ClearTextWindow();
+ data->state = 5;
+ data->source = 1;
+ break;
+ case -2u:
+ ClearTextWindow();
+ if (ValidateCardOrNews(data->IsCardOrNews))
+ {
+ data->state = 18;
+ }
+ else
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ }
+ break;
+ case 5:
+ {
+ register u8 eos asm("r1");
+ gStringVar1[0] = (eos = EOS);
+ gStringVar2[0] = eos;
+ gStringVar3[0] = eos;
+ }
+ switch (data->IsCardOrNews)
+ {
+ case 0:
+ if (data->source == 1)
+ {
+ MEvent_CreateTask_CardOrNewsWithFriend(0x15);
+ }
+ else if (data->source == 0)
+ {
+ MEvent_CreateTask_CardOrNewsOverWireless(0x15);
+ }
+ break;
+ case 1:
+ if (data->source == 1)
+ {
+ MEvent_CreateTask_CardOrNewsWithFriend(0x16);
+ }
+ else if (data->source == 0)
+ {
+ MEvent_CreateTask_CardOrNewsOverWireless(0x16);
+ }
+ break;
+ }
+ data->state = 6;
+ break;
+ case 6:
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = 7;
+ mevent_client_do_init();
+ }
+ else if (gSpecialVar_Result == 5)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = 3;
+ }
+ break;
+ case 7:
+ AddTextPrinterToWindow1(gText_Communicating);
+ data->state = 8;
+ break;
+ case 8:
+ switch (mevent_client_do_exec(&data->curPromptWindowId))
+ {
+ case 6:
+ task_add_05_task_del_08FA224_when_no_RfuFunc();
+ data->prevPromptWindowId = data->curPromptWindowId;
+ data->state = 13;
+ break;
+ case 5:
+ memcpy(data->buffer, mevent_client_get_buffer(), 0x40);
+ mevent_client_inc_flag();
+ break;
+ case 3:
+ data->state = 10;
+ break;
+ case 2:
+ data->state = 9;
+ break;
+ case 4:
+ data->state = 11;
+ StringCopy(gStringVar1, gLinkPlayers[0].name);
+ break;
+ }
+ break;
+ case 9:
+ switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, mevent_client_get_buffer()))
+ {
+ case 0:
+ mevent_client_set_param(0);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case 1:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case -1u:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ }
+ break;
+ case 10:
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, mevent_client_get_buffer()))
+ {
+ mevent_client_inc_flag();
+ data->state = 7;
+ }
+ break;
+ case 11:
+ switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_ThrowAwayWonderCard))
+ {
+ case 0:
+ if (CheckReceivedGiftFromWonderCard() == TRUE)
+ {
+ data->state = 12;
+ }
+ else
+ {
+ mevent_client_set_param(0);
+ mevent_client_inc_flag();
+ data->state = 7;
+ }
+ break;
+ case 1:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case -1u:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ }
+ break;
+ case 12:
+ switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_HaventReceivedCardsGift))
+ {
+ case 0:
+ mevent_client_set_param(0);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case 1:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ case -1u:
+ mevent_client_set_param(1);
+ mevent_client_inc_flag();
+ data->state = 7;
+ break;
+ }
+ break;
+ case 13:
+ if (IsNoOneConnected())
+ {
+ DestroyWirelessStatusIndicatorSprite();
+ data->state = 14;
+ }
+ break;
+ case 14:
+ if (PrintStringAndWait2Seconds(&data->textState, gText_CommunicationCompleted))
+ {
+ if (data->source == 1)
+ {
+ StringCopy(gStringVar1, gLinkPlayers[0].name);
+ }
+ data->state = 15;
+ }
+ break;
+ case 15:
+ {
+ register bool32 flag asm("r1");
+ r1 = mevent_message(&sp0, data->IsCardOrNews, data->source, data->prevPromptWindowId);
+ if (r1 == NULL)
+ {
+ r1 = data->buffer;
+ }
+ if (sp0)
+ {
+ flag = PrintMGSuccessMessage(&data->textState, r1, &data->curPromptWindowId);
+ }
+ else
+ {
+ flag = MG_PrintTextOnWindow1AndWaitButton(&data->textState, r1);
+ }
+ if (flag)
+ {
+ if (data->prevPromptWindowId == 3)
+ {
+ if (data->source == 1)
+ {
+ GenerateRandomNews(1);
+ }
+ else
+ {
+ GenerateRandomNews(2);
+ }
+ }
+ if (sp0 == 0)
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ else
+ {
+ data->state = 17;
+ }
+ }
+ break;
+ }
+ case 16:
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError))
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ case 17:
+ if (mevent_save_game(&data->textState))
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ case 18:
+ if (HandleLoadWonderCardOrNews(&data->textState, data->IsCardOrNews))
+ {
+ data->state = 20;
+ }
+ break;
+ case 20:
+ if (data->IsCardOrNews == 0)
+ {
+ if (JOY_NEW(A_BUTTON))
+ {
+ data->state = 21;
+ }
+ if (JOY_NEW(B_BUTTON))
+ {
+ data->state = 27;
+ }
+ }
+ else
+ {
+ switch (MENews_GetInput(gMain.newKeys))
+ {
+ case 0:
+ MENews_RemoveScrollIndicatorArrowPair();
+ data->state = 21;
+ break;
+ case 1:
+ data->state = 27;
+ break;
+ }
+ }
+ break;
+ case 21:
+ {
+ u32 result;
+ if (data->IsCardOrNews == 0)
+ {
+ if (WonderCard_Test_Unk_08_6())
+ {
+ result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, FALSE);
+ }
+ else
+ {
+ result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, TRUE);
+ }
+ }
+ else
+ {
+ if (WonderNews_Test_Unk_02())
+ {
+ result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, FALSE);
+ }
+ else
+ {
+ result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, TRUE);
+ }
+ }
+ switch (result)
+ {
+ case 0:
+ data->state = 28;
+ break;
+ case 1:
+ data->state = 29;
+ break;
+ case 2:
+ data->state = 22;
+ break;
+ case -2u:
+ if (data->IsCardOrNews == 1)
+ {
+ MENews_AddScrollIndicatorArrowPair();
+ }
+ data->state = 20;
+ break;
+ }
+ break;
+ }
+ case 22:
+ switch (mevent_message_prompt_discard(&data->textState, &data->curPromptWindowId, data->IsCardOrNews))
+ {
+ case 0:
+ if (data->IsCardOrNews == 0 && CheckReceivedGiftFromWonderCard() == TRUE)
+ {
+ data->state = 23;
+ }
+ else
+ {
+ data->state = 24;
+ }
+ break;
+ case 1:
+ data->state = 21;
+ break;
+ case -1:
+ data->state = 21;
+ break;
+ }
+ break;
+ case 23:
+ switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, TRUE, gText_HaventReceivedGiftOkayToDiscard))
+ {
+ case 0:
+ data->state = 24;
+ break;
+ case 1:
+ data->state = 21;
+ break;
+ case -1u:
+ data->state = 21;
+ break;
+ }
+ break;
+ case 24:
+ if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1))
+ {
+ DestroyNewsOrCard(data->IsCardOrNews);
+ data->state = 25;
+ }
+ break;
+ case 25:
+ if (mevent_save_game(&data->textState))
+ {
+ data->state = 26;
+ }
+ break;
+ case 26:
+ if (mevent_message_was_thrown_away(&data->textState, data->IsCardOrNews))
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ case 27:
+ if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 0))
+ {
+ data->state = 0;
+ }
+ break;
+ case 28:
+ if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1))
+ {
+ data->state = 3;
+ }
+ break;
+ case 29:
+ if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1))
+ {
+ switch (data->IsCardOrNews)
+ {
+ case 0:
+ MEvent_CreateTask_Leader(21);
+ break;
+ case 1:
+ MEvent_CreateTask_Leader(22);
+ break;
+ }
+ data->source = 1;
+ data->state = 30;
+ }
+ break;
+ case 30:
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ ClearScreenInBg0(1);
+ data->state = 31;
+ }
+ else if (gSpecialVar_Result == 5)
+ {
+ ClearScreenInBg0(1);
+ data->state = 18;
+ }
+ break;
+ case 31:
+ {
+ register u8 eos asm("r1");
+ gStringVar1[0] = (eos = EOS);
+ gStringVar2[0] = eos;
+ gStringVar3[0] = eos;
+ }
+ if (data->IsCardOrNews == 0)
+ {
+ AddTextPrinterToWindow1(gText_SendingWonderCard);
+ mevent_srv_new_wcard();
+ }
+ else
+ {
+ AddTextPrinterToWindow1(gText_SendingWonderNews);
+ mevent_srv_init_wnews();
+ }
+ data->state = 32;
+ break;
+ case 32:
+ if (mevent_srv_common_do_exec(&data->curPromptWindowId) == 3)
+ {
+ data->prevPromptWindowId = data->curPromptWindowId;
+ data->state = 33;
+ }
+ break;
+ case 33:
+ task_add_05_task_del_08FA224_when_no_RfuFunc();
+ StringCopy(gStringVar1, gLinkPlayers[1].name);
+ data->state = 34;
+ break;
+ case 34:
+ if (IsNoOneConnected())
+ {
+ DestroyWirelessStatusIndicatorSprite();
+ data->state = 35;
+ }
+ break;
+ case 35:
+ if (PrintMGSendStatus(&data->textState, &data->curPromptWindowId, data->source, data->prevPromptWindowId))
+ {
+ if (data->source == 1 && data->prevPromptWindowId == 3)
+ {
+ GenerateRandomNews(3);
+ data->state = 17;
+ }
+ else
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ }
+ break;
+ case 36:
+ if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError))
+ {
+ data->state = 0;
+ PrintMysteryGiftOrEReaderTopMenu(0, 0);
+ }
+ break;
+ case 37:
+ CloseLink();
+ sub_812B484();
+ Free(data->buffer);
+ DestroyTask(taskId);
+ SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
+ break;
+ }
+}
+
+u16 GetMysteryGiftBaseBlock(void)
+{
+ return 0x19B;
+}
diff --git a/src/script.c b/src/script.c
index d7246752c..608dc6ba0 100644
--- a/src/script.c
+++ b/src/script.c
@@ -9,7 +9,7 @@ extern u8 gUnknown_203ADFA;
extern void sub_80CBDE8(void); // field_specials
extern u16 CalcCRC16WithTable(u8 *data, int length); // util
-extern bool32 sub_8143FC8(void); // mevent
+extern bool32 ValidateReceivedWonderCard(void); // mevent
enum
{
@@ -525,7 +525,7 @@ bool32 sub_8069DFC(void)
u8 *sub_8069E48(void)
{
struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data;
- if (!sub_8143FC8())
+ if (!ValidateReceivedWonderCard())
return NULL;
if (scriptData->magic != RAM_SCRIPT_MAGIC)
return NULL;
diff --git a/src/seagallop.c b/src/seagallop.c
new file mode 100644
index 000000000..585838607
--- /dev/null
+++ b/src/seagallop.c
@@ -0,0 +1,460 @@
+#include "global.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "palette.h"
+#include "malloc.h"
+#include "scanline_effect.h"
+#include "battle_dome_cards.h"
+#include "window.h"
+#include "text_window.h"
+#include "sound.h"
+#include "task.h"
+#include "help_system.h"
+#include "overworld.h"
+#include "event_data.h"
+#include "field_fadetransition.h"
+#include "field_weather.h"
+#include "constants/songs.h"
+#include "constants/maps.h"
+#include "seagallop.h"
+
+#define TILESTAG_FERRY 3000
+#define TILESTAG_WAKE 4000
+
+#define PALTAG_FERRY_WAKE 3000
+
+static EWRAM_DATA void * sBg3TilemapBuffer = NULL;
+
+static void CB2_SetUpSeaGallopScene(void);
+static void VBlankCB_SeaGallop(void);
+static void MainCB2_SeaGallop(void);
+static void Task_SeaGallop_0(u8 taskId);
+static void Task_SeaGallop_1(u8 taskId);
+static void Task_SeaGallop_2(u8 taskId);
+static void Task_SeaGallop_3(void);
+static void ResetGPU(void);
+static void ResetAllAssets(void);
+static void SetDispcnt(void);
+static void ResetBGPos(void);
+static void LoadFerrySpriteResources(void);
+static void FreeFerrySpriteResources(void);
+static void CreateFerrySprite(void);
+static void SpriteCB_Ferry(struct Sprite * sprite);
+static void CreateWakeSprite(s16 x);
+static void SpriteCB_Wake(struct Sprite * sprite);
+static bool8 GetDirectionOfTravel(void);
+
+static const u16 sWaterTiles[] = INCBIN_U16("data/seagallop/water.4bpp");
+static const u16 sWaterPal[] = INCBIN_U16("data/seagallop/water.gbapal");
+static const u16 sWaterTilemap_WB[] = INCBIN_U16("data/seagallop/wb_tilemap.bin");
+static const u16 sWaterTilemap_EB[] = INCBIN_U16("data/seagallop/eb_tilemap.bin");
+static const u16 sFerrySpriteTiles[] = INCBIN_U16("data/seagallop/ferry_sprite.4bpp");
+static const u16 sFerryAndWakePal[] = INCBIN_U16("data/seagallop/ferry_and_wake.gbapal");
+static const u16 sWakeSpriteTiles[] = INCBIN_U16("data/seagallop/wake.4bpp");
+
+static const struct BgTemplate sBGTemplates[] = {
+ {
+ .bg = 3,
+ .charBaseIndex = 3,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x000
+ }
+};
+
+static const s8 sSeaGallopSpawnTable[][4] = {
+ // Map X Y
+ [SEAGALLOP_VERMILION_CITY] = {MAP(VERMILIONCITY), 0x17, 0x20},
+ [SEAGALLOP_ONE_ISLAND] = {MAP(ONEISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_TWO_ISLAND] = {MAP(TWOISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_THREE_ISLAND] = {MAP(THREEISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_FOUR_ISLAND] = {MAP(FOURISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_FIVE_ISLAND] = {MAP(FIVEISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_SIX_ISLAND] = {MAP(SIXISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_SEVEN_ISLAND] = {MAP(SEVENISLAND_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_CINNABAR_ISLAND] = {MAP(CINNABARISLAND), 0x15, 0x07},
+ [SEAGALLOP_NAVEL_ROCK] = {MAP(NAVELROCK_HARBOR), 0x08, 0x05},
+ [SEAGALLOP_BIRTH_ISLAND] = {MAP(BIRTHISLAND_HARBOR), 0x08, 0x05}
+};
+
+// Bitpacked array. In the commented section, right-most bit is the
+// flag for traveling from (row port) to Vermilion City, and so on.
+// Flags follow these enums:
+
+enum TravelDirections
+{
+ DIRN_WESTBOUND = 0,
+ DIRN_EASTBOUND = 1
+};
+
+static const u16 sTravelDirectionMatrix[] = {
+ [SEAGALLOP_VERMILION_CITY] = 0x6fe, // 11011111110
+ [SEAGALLOP_ONE_ISLAND] = 0x6fc, // 11011111100
+ [SEAGALLOP_TWO_ISLAND] = 0x6f8, // 11011111000
+ [SEAGALLOP_THREE_ISLAND] = 0x6f0, // 11011110000
+ [SEAGALLOP_FOUR_ISLAND] = 0x6e0, // 11011100000
+ [SEAGALLOP_FIVE_ISLAND] = 0x4c0, // 10011000000
+ [SEAGALLOP_SIX_ISLAND] = 0x400, // 10000000000
+ [SEAGALLOP_SEVEN_ISLAND] = 0x440, // 10001000000
+ [SEAGALLOP_CINNABAR_ISLAND] = 0x7ff, // 11111111111
+ [SEAGALLOP_NAVEL_ROCK] = 0x6e0, // 11011100000
+ [SEAGALLOP_BIRTH_ISLAND] = 0x000 // 00000000000
+};
+
+static const union AnimCmd sSpriteAnims_Ferry_WB[] = {
+ ANIMCMD_FRAME(0, 10),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnims_Ferry_EB[] = {
+ ANIMCMD_FRAME(0, 10, .hFlip = TRUE),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_Ferry[] = {
+ sSpriteAnims_Ferry_WB,
+ sSpriteAnims_Ferry_EB
+};
+
+static const struct OamData sOamData_Ferry = {
+ .size = 3
+};
+
+static const struct SpriteTemplate sFerrySpriteTemplate = {
+ TILESTAG_FERRY,
+ PALTAG_FERRY_WAKE,
+ &sOamData_Ferry,
+ sSpriteAnimTable_Ferry,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCB_Ferry
+};
+
+static const struct SpriteSheet sFerryAndWakeSpriteSheets[] = {
+ {(const void *)sWakeSpriteTiles, sizeof(sWakeSpriteTiles), TILESTAG_WAKE},
+ {(const void *)sFerrySpriteTiles, sizeof(sFerrySpriteTiles), TILESTAG_FERRY},
+ {}
+};
+
+static const struct SpritePalette sFerryAndWakeSpritePalettes[] = {
+ {sFerryAndWakePal, PALTAG_FERRY_WAKE},
+ {}
+};
+
+static const union AnimCmd sSpriteAnims_Wake_WB[] = {
+ ANIMCMD_FRAME(0x00, 0x14),
+ ANIMCMD_FRAME(0x10, 0x14),
+ ANIMCMD_FRAME(0x20, 0x0f),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd sSpriteAnims_Wake_EB[] = {
+ ANIMCMD_FRAME(0x00, 0x14, .hFlip = TRUE),
+ ANIMCMD_FRAME(0x10, 0x14, .hFlip = TRUE),
+ ANIMCMD_FRAME(0x20, 0x0f, .hFlip = TRUE),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sSpriteAnimTable_Wake[] = {
+ sSpriteAnims_Wake_WB,
+ sSpriteAnims_Wake_EB
+};
+
+static const struct OamData sOamData_Wake = {
+ .size = 2
+};
+
+static const struct SpriteTemplate sWakeSpriteTemplate = {
+ TILESTAG_WAKE,
+ PALTAG_FERRY_WAKE,
+ &sOamData_Wake,
+ sSpriteAnimTable_Wake,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCB_Wake
+};
+
+void ScrSpecial_SeaGallopFerry(void)
+{
+ SetVBlankCallback(NULL);
+ sub_812B478();
+ SetMainCallback2(CB2_SetUpSeaGallopScene);
+}
+
+static void CB2_SetUpSeaGallopScene(void)
+{
+ void ** ptr;
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL); // redundant since the setup routine already did this
+ ResetGPU();
+ gMain.state++;
+ break;
+ case 1:
+ ResetAllAssets();
+ gMain.state++;
+ break;
+ case 2:
+ ptr = &sBg3TilemapBuffer;
+ *ptr = AllocZeroed(0x800);
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, sBGTemplates, NELEMS(sBGTemplates));
+ SetBgTilemapBuffer(3, *ptr);
+ ResetBGPos();
+ gMain.state++;
+ break;
+ case 3:
+ LoadBgTiles(3, sWaterTiles, sizeof(sWaterTiles), 0);
+ if (GetDirectionOfTravel() == DIRN_EASTBOUND)
+ {
+ CopyToBgTilemapBufferRect(3, sWaterTilemap_EB, 0, 0, 32, 32);
+ }
+ else
+ {
+ CopyToBgTilemapBufferRect(3, sWaterTilemap_WB, 0, 0, 32, 32);
+ }
+ LoadPalette(sWaterPal, 0x40, 0x20);
+ LoadPalette(stdpal_get(2), 0xF0, 0x20);
+ gMain.state++;
+ break;
+ case 4:
+ if (IsDma3ManagerBusyWithBgCopy() != DIRN_EASTBOUND)
+ {
+ ShowBg(0);
+ ShowBg(3);
+ CopyBgTilemapBufferToVram(3);
+ gMain.state++;
+ }
+ break;
+ case 5:
+ LoadFerrySpriteResources();
+ BlendPalettes(0xFFFFFFFF, 16, RGB_BLACK);
+ gMain.state++;
+ break;
+ case 6:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ gMain.state++;
+ break;
+ case 7:
+ SetDispcnt();
+ SetVBlankCallback(VBlankCB_SeaGallop);
+ PlaySE(SE_NAMINORI);
+ CreateFerrySprite();
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ SetGpuReg(REG_OFFSET_WININ, 0x3F);
+ SetGpuReg(REG_OFFSET_WINOUT, 0x00);
+ SetGpuReg(REG_OFFSET_WIN0H, 0x00F0);
+ SetGpuReg(REG_OFFSET_WIN0V, 0x1888);
+ CreateTask(Task_SeaGallop_0, 8);
+ SetMainCallback2(MainCB2_SeaGallop);
+ gMain.state = 0;
+ break;
+ }
+}
+
+static void VBlankCB_SeaGallop(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void MainCB2_SeaGallop(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void Task_SeaGallop_0(u8 taskId)
+{
+ gTasks[taskId].func = Task_SeaGallop_1;
+}
+
+static void ScrollBG(void)
+{
+ if (GetDirectionOfTravel() == DIRN_EASTBOUND)
+ {
+ ChangeBgX(3, 0x600, 1);
+ }
+ else
+ {
+ ChangeBgX(3, 0x600, 2);
+ }
+}
+
+static void Task_SeaGallop_1(u8 taskId)
+{
+ struct Task * task = &gTasks[taskId];
+
+ ScrollBG();
+ if (++task->data[1] == 140)
+ {
+ Overworld_FadeOutMapMusic();
+ sub_807DC18();
+ task->func = Task_SeaGallop_2;
+ }
+}
+
+static void Task_SeaGallop_2(u8 taskId)
+{
+ ScrollBG();
+ if (sub_8055FC4() && !gPaletteFade.active)
+ {
+ Task_SeaGallop_3();
+ sub_812B484();
+ DestroyTask(taskId);
+ }
+}
+
+static void Task_SeaGallop_3(void)
+{
+ const s8 * warpInfo;
+
+ if (gSpecialVar_0x8006 >= NELEMS(sSeaGallopSpawnTable))
+ gSpecialVar_0x8006 = 0;
+
+ warpInfo = sSeaGallopSpawnTable[gSpecialVar_0x8006];
+ Overworld_SetWarpDestination(warpInfo[0], warpInfo[1], -1, warpInfo[2], warpInfo[3]);
+ play_some_sound();
+ PlaySE(SE_KAIDAN);
+ gUnknown_3005020 = sub_807DF64;
+ warp_in();
+ SetMainCallback2(sub_805671C);
+ ResetInitialPlayerAvatarState();
+ FreeFerrySpriteResources();
+ Free(sBg3TilemapBuffer);
+ FreeAllWindowBuffers();
+}
+
+static void ResetGPU(void)
+{
+ void * dest = (void *) VRAM;
+ DmaClearLarge16(3, dest, VRAM_SIZE, 0x1000);
+
+ DmaClear32(3, (void *)OAM, OAM_SIZE);
+ DmaClear16(3, (void *)PLTT, PLTT_SIZE);
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ SetGpuReg(REG_OFFSET_BG0CNT, 0);
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1CNT, 0);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2CNT, 0);
+ SetGpuReg(REG_OFFSET_BG2HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3CNT, 0);
+ SetGpuReg(REG_OFFSET_BG3HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3VOFS, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, 0);
+ SetGpuReg(REG_OFFSET_WIN0V, 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);
+}
+
+static void ResetAllAssets(void)
+{
+ ScanlineEffect_Stop();
+ ResetTasks();
+ ResetSpriteData();
+ dp13_810BB8C();
+ ResetPaletteFade();
+ FreeAllSpritePalettes();
+}
+
+static void SetDispcnt(void)
+{
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON);
+}
+
+static void ResetBGPos(void)
+{
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ ChangeBgX(3, 0, 0);
+ ChangeBgY(3, 0, 0);
+}
+
+static void LoadFerrySpriteResources(void)
+{
+ LoadSpriteSheets(sFerryAndWakeSpriteSheets);
+ LoadSpritePalettes(sFerryAndWakeSpritePalettes);
+}
+
+static void FreeFerrySpriteResources(void)
+{
+ FreeSpriteTilesByTag(TILESTAG_FERRY);
+ FreeSpriteTilesByTag(TILESTAG_WAKE);
+ FreeSpritePaletteByTag(PALTAG_FERRY_WAKE);
+}
+
+static void CreateFerrySprite(void)
+{
+ u8 spriteId = CreateSprite(&sFerrySpriteTemplate, 0, 92, 0);
+ gSprites[spriteId].data[0] = 48;
+ if (GetDirectionOfTravel() == DIRN_EASTBOUND)
+ {
+ StartSpriteAnim(&gSprites[spriteId], 1);
+ }
+ else
+ {
+ gSprites[spriteId].pos1.x = 240;
+ gSprites[spriteId].data[0] *= -1;
+ }
+}
+
+static void SpriteCB_Ferry(struct Sprite * sprite)
+{
+ sprite->data[1] += sprite->data[0];
+ sprite->pos2.x = sprite->data[1] >> 4;
+ if (sprite->data[2] % 5 == 0)
+ {
+ CreateWakeSprite(sprite->pos1.x + sprite->pos2.x);
+ }
+ sprite->data[2]++;
+ if ((u16)(300 + sprite->pos2.x) > 600)
+ {
+ DestroySprite(sprite);
+ }
+}
+
+static void CreateWakeSprite(s16 x)
+{
+ u8 spriteId = CreateSprite(&sWakeSpriteTemplate, x, 92, 8);
+ if (spriteId != MAX_SPRITES)
+ {
+ if (GetDirectionOfTravel() == DIRN_EASTBOUND)
+ {
+ StartSpriteAnim(&gSprites[spriteId], 1);
+ }
+ }
+}
+
+static void SpriteCB_Wake(struct Sprite * sprite)
+{
+ if (sprite->animEnded)
+ {
+ DestroySprite(sprite);
+ }
+}
+
+static bool8 GetDirectionOfTravel(void)
+{
+ if (gSpecialVar_0x8004 >= NELEMS(sTravelDirectionMatrix))
+ {
+ return DIRN_EASTBOUND;
+ }
+ return (sTravelDirectionMatrix[gSpecialVar_0x8004] >> gSpecialVar_0x8006) & 1;
+}
diff --git a/src/text.c b/src/text.c
index d74d77e2f..34ceb92d4 100644
--- a/src/text.c
+++ b/src/text.c
@@ -5,13 +5,13 @@
#include "window.h"
#include "text.h"
#include "sprite.h"
+#include "blit.h"
extern u8 gGlyphInfo[0x90];
extern u8 gUnknown_203ADFA;
extern u16 gTMCaseMainWindowPalette[];
extern const struct OamData gOamData_83AC9D0;
-extern void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
extern void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16 height);
extern void BlitBitmapRectToWindow(u8 windowId, const u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight);
extern u8 GetKeypadIconWidth(u8 keypadIconId);
diff --git a/src/window.c b/src/window.c
index 71cfa6898..c4ea49956 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2,17 +2,13 @@
#include "window.h"
#include "malloc.h"
#include "bg.h"
+#include "blit.h"
u8 gWindowClearTile;
void *gWindowBgTilemapBuffers[4];
EWRAM_DATA struct Window gWindows[WINDOWS_MAX] = {0};
-extern void BlitBitmapRect4Bit(struct Bitmap *src, struct Bitmap *dest, u16 srcX, u16 srcY, u16 destX, u16 destY, u16 width, u16 height, u8 colorKey);
-extern void BlitBitmapRect4BitTo8Bit(struct Bitmap *src, struct Bitmap *dest, u16 srcX, u16 srcY, u16 destX, u16 destY, u16 width, u16 height, u8 colorKey, u8 paletteNum);
-extern void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
-extern void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
-
static u8 GetNumActiveWindowsOnBg(u8 bgId);
static const struct WindowTemplate sDummyWindowTemplate = {0xFF, 0, 0, 0, 0, 0, 0};
diff --git a/src/window_8bpp.c b/src/window_8bpp.c
index 5eac3c558..8e5d19565 100644
--- a/src/window_8bpp.c
+++ b/src/window_8bpp.c
@@ -2,13 +2,11 @@
#include "window.h"
#include "malloc.h"
#include "bg.h"
+#include "blit.h"
EWRAM_DATA static struct Window* sWindowPtr = NULL;
EWRAM_DATA static u16 sWindowSize = 0;
-extern void BlitBitmapRect4BitTo8Bit(struct Bitmap *src, struct Bitmap *dest, u16 srcX, u16 srcY, u16 destX, u16 destY, u16 width, u16 height, u8 colorKey, u8 paletteNum);
-extern void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
-
static u8 GetNumActiveWindowsOnBg8Bit(u8 bgId);
static void nullsub_9(void)