mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-01-09 21:25:03 +01:00
1f4c88c952
* Copy Berry Fix MB dism from FR
290 lines
7.6 KiB
C
290 lines
7.6 KiB
C
#include "gba/gba.h"
|
|
#include "global.h"
|
|
#include "main.h"
|
|
#include "rtc.h"
|
|
#include "flash.h"
|
|
|
|
static s32 gInitialWaitTimer;
|
|
IntrFunc gIntrTable[16];
|
|
u16 gHeldKeys;
|
|
u16 gNewKeys;
|
|
u8 gIntrVector[0x100];
|
|
u32 gUpdateSuccessful;
|
|
u32 gUnknown_3001194;
|
|
u32 gUnknown_30011A0[0x19];
|
|
u32 gMainCallbackState;
|
|
u32 gGameVersion;
|
|
|
|
EWRAM_DATA u8 gSharedMem[0x8000] = {};
|
|
|
|
void IntrMain(void);
|
|
void ReadKeys(void);
|
|
void dummy_intr_0(void);
|
|
void dummy_intr_1(void);
|
|
void main_callback(u32 *, void *, void *);
|
|
|
|
|
|
const char gBerryFixGameCode[] = "AGBJ";
|
|
const IntrFunc gIntrFuncPointers[] = {
|
|
dummy_intr_0,
|
|
dummy_intr_1,
|
|
dummy_intr_0,
|
|
dummy_intr_0,
|
|
dummy_intr_0,
|
|
dummy_intr_0,
|
|
dummy_intr_0,
|
|
dummy_intr_0,
|
|
dummy_intr_0,
|
|
dummy_intr_0,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
const char gVersionData[][2] = {
|
|
{'J', 1},
|
|
{'E', 2},
|
|
{'D', 1},
|
|
{'F', 1},
|
|
{'I', 1},
|
|
{'S', 1}
|
|
};
|
|
const char gRubyTitleAndCode[] = "POKEMON RUBYAXV";
|
|
const char gSapphireTitleAndCode[] = "POKEMON SAPPAXP";
|
|
const u16 sDebugPals[20] = {
|
|
RGB(00, 00, 00),
|
|
RGB(31, 00, 00),
|
|
RGB(00, 31, 00),
|
|
RGB(00, 00, 31)
|
|
};
|
|
const u16 sDebugDigitsGfx[] = INCBIN_U16("graphics/debug_digits.4bpp");
|
|
|
|
void AgbMain(void)
|
|
{
|
|
RegisterRamReset(0x1E);
|
|
DmaCopy32(3, gIntrFuncPointers, gIntrTable, sizeof gIntrFuncPointers);
|
|
DmaCopy32(3, IntrMain, gIntrVector, sizeof(gIntrVector));
|
|
INTR_VECTOR = gIntrVector;
|
|
REG_IE = INTR_FLAG_VBLANK;
|
|
if (*RomHeaderMagic == 0x96 && *(u32 *)RomHeaderGameCode == *(u32 *)gBerryFixGameCode)
|
|
REG_IE |= INTR_FLAG_GAMEPAK;
|
|
REG_DISPSTAT = DISPSTAT_VBLANK_INTR;
|
|
REG_IME = INTR_FLAG_VBLANK;
|
|
msg_load_gfx();
|
|
gMainCallbackState = MAINCB_INIT;
|
|
gUnknown_3001194 = 0;
|
|
for (;;)
|
|
{
|
|
VBlankIntrWait();
|
|
ReadKeys();
|
|
main_callback(&gMainCallbackState, gUnknown_30011A0, gSharedMem);
|
|
}
|
|
}
|
|
|
|
void dummy_intr_1(void)
|
|
{}
|
|
|
|
void dummy_intr_0(void)
|
|
{}
|
|
|
|
void ReadKeys(void)
|
|
{
|
|
u16 keyInput = REG_KEYINPUT ^ KEYS_MASK;
|
|
gNewKeys = keyInput & ~gHeldKeys;
|
|
gHeldKeys = keyInput;
|
|
}
|
|
|
|
void fill_palette(const u8 * src, u16 * dest, u8 value)
|
|
{
|
|
s32 i;
|
|
for (i = 0; src[i] != 0; i++)
|
|
dest[i] = src[i] | value << 12;
|
|
}
|
|
|
|
bool32 berry_fix_memcmp(const char * src1, const char * src2, size_t size)
|
|
{
|
|
s32 i;
|
|
for (i = 0; i < size; i++)
|
|
{
|
|
if (src1[i] != src2[i])
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
s32 validate_rom_header_internal(void)
|
|
{
|
|
char languageCode = *(RomHeaderGameCode + 3);
|
|
s32 softwareVersion = *RomHeaderSoftwareVersion;
|
|
s32 shouldUpdate = -1;
|
|
s32 i;
|
|
for (i = 0; i < ARRAY_COUNT(gVersionData); i++)
|
|
{
|
|
if (languageCode == gVersionData[i][0])
|
|
{
|
|
if (softwareVersion >= gVersionData[i][1])
|
|
{
|
|
shouldUpdate = 0;
|
|
}
|
|
else
|
|
{
|
|
shouldUpdate = 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (shouldUpdate != -1)
|
|
{
|
|
if (berry_fix_memcmp(RomHeaderGameTitle, gRubyTitleAndCode, 15) == TRUE)
|
|
{
|
|
if (shouldUpdate == 0)
|
|
return RUBY_NONEED;
|
|
else
|
|
{
|
|
gGameVersion = VERSION_RUBY;
|
|
return RUBY_UPDATABLE;
|
|
}
|
|
}
|
|
else if (berry_fix_memcmp(RomHeaderGameTitle, gSapphireTitleAndCode, 15) == TRUE)
|
|
{
|
|
if (shouldUpdate == 0)
|
|
return SAPPHIRE_NONEED;
|
|
else
|
|
{
|
|
gGameVersion = VERSION_SAPPHIRE;
|
|
return SAPPHIRE_UPDATABLE;
|
|
}
|
|
}
|
|
}
|
|
return INVALID;
|
|
}
|
|
|
|
s32 validate_rom_header(void)
|
|
{
|
|
if (*RomHeaderMakerCode == '0' && *(RomHeaderMakerCode + 1) == '1' && *RomHeaderMagic == 0x96)
|
|
return validate_rom_header_internal();
|
|
else
|
|
return INVALID;
|
|
}
|
|
|
|
void main_callback(u32 * state, void * unused1, void * unused2)
|
|
{
|
|
u8 year;
|
|
switch (*state)
|
|
{
|
|
case MAINCB_INIT:
|
|
msg_display(MSGBOX_WILL_NOW_UPDATE);
|
|
if (++gInitialWaitTimer >= 180)
|
|
{
|
|
gInitialWaitTimer = 0;
|
|
gUpdateSuccessful = 0;
|
|
switch (validate_rom_header())
|
|
{
|
|
case SAPPHIRE_UPDATABLE:
|
|
case RUBY_UPDATABLE: // Should Update Ruby
|
|
++(*state); // MAINCB_CHECK_RTC
|
|
break;
|
|
case INVALID: // Invalid header
|
|
*state = MAINCB_ERROR;
|
|
break;
|
|
case SAPPHIRE_NONEED: // Should not update Sapphire
|
|
case RUBY_NONEED: // Should not update Ruby
|
|
*state = MAINCB_NO_NEED_TO_FIX;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case MAINCB_CHECK_RTC:
|
|
if (!rtc_maincb_is_rtc_working())
|
|
*state = MAINCB_ERROR;
|
|
else
|
|
++(*state); // MAINCB_CHECK_FLASH
|
|
break;
|
|
case MAINCB_CHECK_FLASH:
|
|
if (flash_maincb_ident_is_valid() == TRUE)
|
|
++(*state); // MAINCB_READ_SAVE
|
|
else
|
|
*state = MAINCB_ERROR;
|
|
break;
|
|
case MAINCB_READ_SAVE:
|
|
if (flash_maincb_read_save(0) == SAVE_STATUS_OK)
|
|
++(*state); // MAINCB_CHECK_TIME
|
|
else
|
|
*state = MAINCB_ERROR;
|
|
break;
|
|
case MAINCB_CHECK_TIME:
|
|
if (rtc_maincb_is_time_since_last_berry_update_positive(&year) == TRUE)
|
|
{
|
|
if (year == 0)
|
|
++(*state); // MAINCB_FIX_DATE
|
|
else
|
|
*state = MAINCB_CHECK_PACIFIDLOG_TM;
|
|
}
|
|
else
|
|
{
|
|
if (year != 1)
|
|
*state = MAINCB_YEAR_MAKES_NO_SENSE;
|
|
else
|
|
++(*state); // MAINCB_FIX_DATE
|
|
}
|
|
break;
|
|
case MAINCB_FIX_DATE:
|
|
rtc_maincb_fix_date();
|
|
gUpdateSuccessful |= 1;
|
|
*state = MAINCB_CHECK_PACIFIDLOG_TM;
|
|
break;
|
|
case MAINCB_CHECK_PACIFIDLOG_TM:
|
|
if (flash_maincb_check_need_reset_pacifidlog_tm() == TRUE)
|
|
*state = MAINCB_FINISHED;
|
|
else
|
|
*state = MAINCB_FIX_PACIFIDLOG_TM;
|
|
break;
|
|
case MAINCB_FIX_PACIFIDLOG_TM:
|
|
msg_display(MSGBOX_UPDATING);
|
|
if (flash_maincb_reset_pacifidlog_tm() == TRUE)
|
|
{
|
|
gUpdateSuccessful |= 1;
|
|
*state = MAINCB_FINISHED;
|
|
}
|
|
else
|
|
*state = MAINCB_ERROR;
|
|
break;
|
|
case MAINCB_FINISHED:
|
|
if (gUpdateSuccessful == 0)
|
|
*state = MAINCB_NO_NEED_TO_FIX;
|
|
else
|
|
msg_display(MSGBOX_HAS_BEEN_UPDATED);
|
|
break;
|
|
case MAINCB_NO_NEED_TO_FIX:
|
|
msg_display(MSGBOX_NO_NEED_TO_UPDATE);
|
|
break;
|
|
case MAINCB_YEAR_MAKES_NO_SENSE:
|
|
msg_display(MSGBOX_UNABLE_TO_UPDATE);
|
|
break;
|
|
case MAINCB_ERROR:
|
|
msg_display(MSGBOX_UNABLE_TO_UPDATE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DBG_LoadDigitsPal(void)
|
|
{
|
|
const u16 * src;
|
|
s32 i;
|
|
register vu16 * dest asm("r3") = (vu16 *)BG_PLTT + 1;
|
|
DmaFill16(3, RGB(31, 31, 31), (vu16 *)BG_PLTT, BG_PLTT_SIZE);
|
|
src = sDebugPals;
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
*dest = *src;
|
|
dest += 16;
|
|
src++;
|
|
}
|
|
}
|
|
|
|
void DBG_LoadDigits(void)
|
|
{
|
|
DmaFill16(3, 0x1111, (void *)VRAM + 0x8420, 0x1800);
|
|
DmaCopy32(3, sDebugDigitsGfx, (void *)VRAM + 0x8600, 0x200);
|
|
DBG_LoadDigitsPal();
|
|
}
|