mirror of
https://github.com/pret/pokefirered.git
synced 2026-10-02 05:50:47 -05:00
4
Makefile
4
Makefile
@@ -92,7 +92,7 @@ MID_BUILDDIR = $(OBJ_DIR)/$(MID_SUBDIR)
|
||||
|
||||
ASFLAGS := -mcpu=arm7tdmi --defsym $(GAME_VERSION)=1 --defsym REVISION=$(GAME_REVISION) --defsym $(GAME_LANGUAGE)=1 --defsym MODERN=$(MODERN)
|
||||
|
||||
LDFLAGS = -Map ../../$(MAP)
|
||||
LDFLAGS = --print-memory-usage -Map ../../$(MAP)
|
||||
|
||||
LIB := $(LIBPATH) -lc -lgcc
|
||||
ifneq ($(MODERN),0)
|
||||
@@ -238,6 +238,8 @@ sound/songs/%.s: sound/songs/%.mid
|
||||
$(MID) $< $@
|
||||
|
||||
ifeq ($(MODERN),0)
|
||||
$(C_BUILDDIR)/siirtc.o: CFLAGS := -mthumb-interwork
|
||||
|
||||
$(C_BUILDDIR)/agb_flash.o: CFLAGS := -O -mthumb-interwork
|
||||
$(C_BUILDDIR)/agb_flash_1m.o: CFLAGS := -O -mthumb-interwork
|
||||
$(C_BUILDDIR)/agb_flash_mx.o: CFLAGS := -O -mthumb-interwork
|
||||
|
||||
1
common_syms/rtc.txt
Normal file
1
common_syms/rtc.txt
Normal file
@@ -0,0 +1 @@
|
||||
gLocalTime
|
||||
@@ -98,6 +98,7 @@ ViridianCity_Mart_Items::
|
||||
.2byte ITEM_STICKY_BARB
|
||||
.2byte ITEM_ORAN_BERRY
|
||||
.2byte ITEM_BEAST_BALL
|
||||
.2byte ITEM_POMEG_BERRY
|
||||
.2byte ITEM_NONE
|
||||
release
|
||||
end
|
||||
|
||||
@@ -162,8 +162,8 @@ gSpecials::
|
||||
def_special NullFieldSpecial @ Cable Car specials
|
||||
def_special NullFieldSpecial
|
||||
def_special Overworld_PlaySpecialMapMusic
|
||||
def_special NullFieldSpecial @ Wall Clock specials
|
||||
def_special NullFieldSpecial
|
||||
def_special StartWallClock
|
||||
def_special Special_ViewWallClock
|
||||
def_special NullFieldSpecial
|
||||
def_special StartOldManTutorialBattle
|
||||
def_special ChangePokemonNickname
|
||||
@@ -215,7 +215,7 @@ gSpecials::
|
||||
def_special NullFieldSpecial
|
||||
def_special EnterSafariMode
|
||||
def_special ExitSafariMode
|
||||
def_special NullFieldSpecial @ Misc Hoenn specials
|
||||
def_special GetWeekCount
|
||||
def_special NullFieldSpecial
|
||||
def_special NullFieldSpecial
|
||||
def_special NullFieldSpecial
|
||||
|
||||
@@ -13,7 +13,7 @@ gText_PlayerSavedTheGame::
|
||||
.string "{PLAYER} saved the game.$"
|
||||
|
||||
gText_SaveFailed2::
|
||||
.string "セーブに しっぱい しました‥$"
|
||||
.string "Save failed…$"
|
||||
|
||||
gText_DifferentGameFile::
|
||||
.string "WARNING!\p"
|
||||
|
||||
7
graphics/misc/reset_rtc_screen_arrow.pal
Normal file
7
graphics/misc/reset_rtc_screen_arrow.pal
Normal file
@@ -0,0 +1,7 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
4
|
||||
0 0 0
|
||||
255 0 0
|
||||
74 74 74
|
||||
0 0 0
|
||||
BIN
graphics/misc/reset_rtc_screen_downarrow.png
Normal file
BIN
graphics/misc/reset_rtc_screen_downarrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 113 B |
BIN
graphics/misc/reset_rtc_screen_rightarrow.png
Normal file
BIN
graphics/misc/reset_rtc_screen_rightarrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 110 B |
BIN
graphics/wallclock/clock.png
Normal file
BIN
graphics/wallclock/clock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
graphics/wallclock/clock_start.bin
Normal file
BIN
graphics/wallclock/clock_start.bin
Normal file
Binary file not shown.
BIN
graphics/wallclock/clock_view.bin
Normal file
BIN
graphics/wallclock/clock_view.bin
Normal file
Binary file not shown.
19
graphics/wallclock/female.pal
Normal file
19
graphics/wallclock/female.pal
Normal file
@@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
65 65 90
|
||||
222 230 238
|
||||
213 213 222
|
||||
205 205 213
|
||||
197 197 205
|
||||
255 197 255
|
||||
255 156 255
|
||||
255 115 255
|
||||
255 82 255
|
||||
74 180 189
|
||||
255 230 49
|
||||
90 90 123
|
||||
123 123 172
|
||||
65 65 90
|
||||
255 255 255
|
||||
0 0 0
|
||||
BIN
graphics/wallclock/hand.png
Normal file
BIN
graphics/wallclock/hand.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 204 B |
19
graphics/wallclock/male.pal
Normal file
19
graphics/wallclock/male.pal
Normal file
@@ -0,0 +1,19 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
16
|
||||
65 65 90
|
||||
222 230 238
|
||||
213 213 222
|
||||
205 205 213
|
||||
197 197 205
|
||||
164 180 255
|
||||
115 139 255
|
||||
74 98 255
|
||||
32 65 255
|
||||
74 180 189
|
||||
255 230 49
|
||||
90 90 123
|
||||
123 123 172
|
||||
65 65 90
|
||||
255 255 255
|
||||
0 0 0
|
||||
7
graphics/wallclock/text_prompt.pal
Normal file
7
graphics/wallclock/text_prompt.pal
Normal file
@@ -0,0 +1,7 @@
|
||||
JASC-PAL
|
||||
0100
|
||||
4
|
||||
0 0 0
|
||||
74 180 189
|
||||
255 255 255
|
||||
0 0 0
|
||||
8
include/clock.h
Normal file
8
include/clock.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef GUARD_CLOCK_H
|
||||
#define GUARD_CLOCK_H
|
||||
|
||||
// TODO: time of day and seconds in a day defines
|
||||
|
||||
void DoTimeBasedEvents(void);
|
||||
|
||||
#endif // GUARD_CLOCK_H
|
||||
@@ -886,7 +886,7 @@
|
||||
#define FLAG_0x359 0x359
|
||||
#define FLAG_0x35A 0x35A
|
||||
#define FLAG_0x35B 0x35B
|
||||
#define FLAG_0x35C 0x35C
|
||||
#define FLAG_SET_WALL_CLOCK 0x35C
|
||||
#define FLAG_0x35D 0x35D
|
||||
#define FLAG_0x35E 0x35E
|
||||
#define FLAG_0x35F 0x35F
|
||||
@@ -938,6 +938,9 @@
|
||||
#define FLAG_0x38D 0x38D
|
||||
#define FLAG_0x38E 0x38E
|
||||
#define FLAG_0x38F 0x38F
|
||||
|
||||
#define DAILY_FLAGS_START (FLAG_0x38F + (8 - FLAG_0x38F % 8))
|
||||
|
||||
#define FLAG_0x390 0x390
|
||||
#define FLAG_0x391 0x391
|
||||
#define FLAG_0x392 0x392
|
||||
@@ -1002,6 +1005,9 @@
|
||||
#define FLAG_0x3CD 0x3CD
|
||||
#define FLAG_0x3CE 0x3CE
|
||||
#define FLAG_0x3CF 0x3CF
|
||||
|
||||
#define DAILY_FLAGS_END (FLAG_0x3CF + (7 - FLAG_0x3CF % 8))
|
||||
|
||||
#define FLAG_0x3D0 0x3D0
|
||||
#define FLAG_0x3D1 0x3D1
|
||||
#define FLAG_0x3D2 0x3D2
|
||||
@@ -1394,7 +1400,7 @@
|
||||
#define FLAG_SYS_SAW_HELP_SYSTEM_INTRO (SYS_FLAGS + 0x3C)
|
||||
#define FLAG_0x83D (SYS_FLAGS + 0x3D)
|
||||
#define FLAG_OPENED_START_MENU (SYS_FLAGS + 0x3E)
|
||||
#define FLAG_0x83F (SYS_FLAGS + 0x3F)
|
||||
#define FLAG_SYS_CLOCK_SET (SYS_FLAGS + 0x3F) // FLAG_0x83F
|
||||
#define FLAG_SYS_NATIONAL_DEX (SYS_FLAGS + 0x40)
|
||||
#define FLAG_SYS_PC_STORAGE_DISABLED (SYS_FLAGS + 0x41)
|
||||
#define FLAG_SYS_INFORMED_OF_LOCAL_WIRELESS_PLAYER (SYS_FLAGS + 0x42)
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
#define VAR_0x4029 0x4029
|
||||
#define VAR_0x402A 0x402A
|
||||
#define VAR_0x402B 0x402B
|
||||
#define VAR_0x402C 0x402C
|
||||
#define VAR_DAYS 0x402C // was VAR_RESET_RTC_ENABLE
|
||||
#define VAR_0x402D 0x402D
|
||||
#define VAR_0x402E 0x402E
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ extern u16 gSpecialVar_PrevTextColor;
|
||||
|
||||
void InitEventData(void);
|
||||
void ClearTempFieldEventData(void);
|
||||
void ClearDailyFlags(void);
|
||||
void ClearUpperFlags(void);
|
||||
void DisableNationalPokedex(void);
|
||||
void EnableNationalPokedex(void);
|
||||
|
||||
@@ -2781,6 +2781,13 @@ extern const u8 gTeachyTvScreen_Tilemap[];
|
||||
extern const u8 gTeachyTvTitle_Tilemap[];
|
||||
extern const u32 gTeachyTv_Pal[];
|
||||
|
||||
// wall clock
|
||||
extern const u32 gWallClock_Gfx[];
|
||||
extern const u16 gWallClockMale_Pal[];
|
||||
extern const u16 gWallClockFemale_Pal[];
|
||||
extern const u32 gWallClockStart_Tilemap[];
|
||||
extern const u32 gWallClockView_Tilemap[];
|
||||
|
||||
// berry_fix_program
|
||||
extern const u8 gBerryFixGameboy_Gfx[];
|
||||
extern const u8 gBerryFixGameboy_Tilemap[];
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "sprite.h"
|
||||
#include "constants/items.h"
|
||||
#include "constants/region_map_sections.h"
|
||||
#include "constants/map_groups.h"
|
||||
#include "constants/pokemon.h"
|
||||
|
||||
#define GET_BASE_SPECIES_ID(speciesId) (GetFormSpeciesId(speciesId, 0))
|
||||
@@ -767,6 +768,7 @@ u16 GetMonEVCount(struct Pokemon *mon);
|
||||
void RandomlyGivePartyPokerus(struct Pokemon *party);
|
||||
u8 CheckPartyPokerus(struct Pokemon *party, u8 party_bm);
|
||||
u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection);
|
||||
void UpdatePartyPokerusTime(u16 days);
|
||||
void PartySpreadPokerus(struct Pokemon *party);
|
||||
bool8 TryIncrementMonLevel(struct Pokemon *mon);
|
||||
u32 CanMonLearnTMHM(struct Pokemon *mon, u8 tm);
|
||||
|
||||
6
include/reset_rtc_screen.h
Normal file
6
include/reset_rtc_screen.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef GUARD_RESET_RTC_SCREEN_H
|
||||
#define GUARD_RESET_RTC_SCREEN_H
|
||||
|
||||
void CB2_InitResetRtcScreen(void);
|
||||
|
||||
#endif // GUARD_RESET_RTC_SCREEN_H
|
||||
122
include/rtc.h
Normal file
122
include/rtc.h
Normal file
@@ -0,0 +1,122 @@
|
||||
#ifndef GUARD_RTC_UTIL_H
|
||||
#define GUARD_RTC_UTIL_H
|
||||
|
||||
#include "siirtc.h"
|
||||
|
||||
#define RTC_INIT_ERROR 0x0001
|
||||
#define RTC_INIT_WARNING 0x0002
|
||||
|
||||
#define RTC_ERR_12HOUR_CLOCK 0x0010
|
||||
#define RTC_ERR_POWER_FAILURE 0x0020
|
||||
#define RTC_ERR_INVALID_YEAR 0x0040
|
||||
#define RTC_ERR_INVALID_MONTH 0x0080
|
||||
#define RTC_ERR_INVALID_DAY 0x0100
|
||||
#define RTC_ERR_INVALID_HOUR 0x0200
|
||||
#define RTC_ERR_INVALID_MINUTE 0x0400
|
||||
#define RTC_ERR_INVALID_SECOND 0x0800
|
||||
|
||||
#define RTC_ERR_FLAG_MASK 0x0FF0
|
||||
|
||||
//Morning and evening don't exist in Gen 3
|
||||
#if OW_TIMES_OF_DAY == GEN_3
|
||||
#define MORNING_HOUR_BEGIN 0
|
||||
#define MORNING_HOUR_END 0
|
||||
|
||||
#define DAY_HOUR_BEGIN 12
|
||||
#define DAY_HOUR_END HOURS_PER_DAY
|
||||
|
||||
#define EVENING_HOUR_BEGIN 0
|
||||
#define EVENING_HOUR_END 0
|
||||
|
||||
#define NIGHT_HOUR_BEGIN 0
|
||||
#define NIGHT_HOUR_END 12
|
||||
//Evening doesn't exist in Gen 4
|
||||
#elif OW_TIMES_OF_DAY == GEN_4
|
||||
#define MORNING_HOUR_BEGIN 4
|
||||
#define MORNING_HOUR_END 10
|
||||
|
||||
#define DAY_HOUR_BEGIN 10
|
||||
#define DAY_HOUR_END 20
|
||||
|
||||
#define EVENING_HOUR_BEGIN 0
|
||||
#define EVENING_HOUR_END 0
|
||||
|
||||
#define NIGHT_HOUR_BEGIN 20
|
||||
#define NIGHT_HOUR_END 4
|
||||
//Gen 5 currently not included as the seasons change the times of day
|
||||
#elif OW_TIMES_OF_DAY <= GEN_6
|
||||
#define MORNING_HOUR_BEGIN 4
|
||||
#define MORNING_HOUR_END 11
|
||||
|
||||
#define DAY_HOUR_BEGIN 11
|
||||
#define DAY_HOUR_END 18
|
||||
|
||||
#define EVENING_HOUR_BEGIN 18
|
||||
#define EVENING_HOUR_END 21
|
||||
|
||||
#define NIGHT_HOUR_BEGIN 21
|
||||
#define NIGHT_HOUR_END 4
|
||||
//These are the Sun/Ultra Sun times
|
||||
#elif OW_TIMES_OF_DAY == GEN_7
|
||||
#define MORNING_HOUR_BEGIN 6
|
||||
#define MORNING_HOUR_END 10
|
||||
|
||||
#define DAY_HOUR_BEGIN 10
|
||||
#define DAY_HOUR_END 17
|
||||
|
||||
#define EVENING_HOUR_BEGIN 17
|
||||
#define EVENING_HOUR_END 18
|
||||
|
||||
#define NIGHT_HOUR_BEGIN 18
|
||||
#define NIGHT_HOUR_END 6
|
||||
#elif OW_TIMES_OF_DAY >= GEN_8
|
||||
#define MORNING_HOUR_BEGIN 6
|
||||
#define MORNING_HOUR_END 10
|
||||
|
||||
#define DAY_HOUR_BEGIN 10
|
||||
#define DAY_HOUR_END 19
|
||||
|
||||
#define EVENING_HOUR_BEGIN 19
|
||||
#define EVENING_HOUR_END 20
|
||||
|
||||
#define NIGHT_HOUR_BEGIN 20
|
||||
#define NIGHT_HOUR_END 6
|
||||
#endif
|
||||
|
||||
#define TIME_MORNING 0
|
||||
#define TIME_DAY 1
|
||||
#define TIME_EVENING 2
|
||||
#define TIME_NIGHT 3
|
||||
|
||||
extern struct Time gLocalTime;
|
||||
|
||||
void RtcDisableInterrupts(void);
|
||||
void RtcRestoreInterrupts(void);
|
||||
u32 ConvertBcdToBinary(u8 bcd);
|
||||
bool8 IsLeapYear(u32 year);
|
||||
u16 ConvertDateToDayCount(u8 year, u8 month, u8 day);
|
||||
u16 RtcGetDayCount(struct SiiRtcInfo *rtc);
|
||||
void RtcInit(void);
|
||||
u16 RtcGetErrorStatus(void);
|
||||
void RtcGetInfo(struct SiiRtcInfo *rtc);
|
||||
void RtcGetDateTime(struct SiiRtcInfo *rtc);
|
||||
void RtcGetStatus(struct SiiRtcInfo *rtc);
|
||||
void RtcGetRawInfo(struct SiiRtcInfo *rtc);
|
||||
u16 RtcCheckInfo(struct SiiRtcInfo *rtc);
|
||||
void RtcReset(void);
|
||||
void FormatDecimalTime(u8 *dest, s32 hour, s32 minute, s32 second);
|
||||
void FormatHexTime(u8 *dest, s32 hour, s32 minute, s32 second);
|
||||
void FormatHexRtcTime(u8 *dest);
|
||||
void FormatDecimalDate(u8 *dest, s32 year, s32 month, s32 day);
|
||||
void FormatHexDate(u8 *dest, s32 year, s32 month, s32 day);
|
||||
void RtcCalcTimeDifference(struct SiiRtcInfo *rtc, struct Time *result, struct Time *t);
|
||||
void RtcCalcLocalTime(void);
|
||||
bool8 IsBetweenHours(s32 hours, s32 begin, s32 end);
|
||||
u8 GetTimeOfDay(void);
|
||||
void RtcInitLocalTimeOffset(s32 hour, s32 minute);
|
||||
void RtcCalcLocalTimeOffset(s32 days, s32 hours, s32 minutes, s32 seconds);
|
||||
void CalcTimeDifference(struct Time *result, struct Time *t1, struct Time *t2);
|
||||
u32 RtcGetMinuteCount(void);
|
||||
u32 RtcGetLocalDayCount(void);
|
||||
|
||||
#endif // GUARD_RTC_UTIL_H
|
||||
54
include/siirtc.h
Normal file
54
include/siirtc.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef GUARD_RTC_H
|
||||
#define GUARD_RTC_H
|
||||
|
||||
#include "gba/gba.h"
|
||||
|
||||
#define SIIRTCINFO_INTFE 0x01 // frequency interrupt enable
|
||||
#define SIIRTCINFO_INTME 0x02 // per-minute interrupt enable
|
||||
#define SIIRTCINFO_INTAE 0x04 // alarm interrupt enable
|
||||
#define SIIRTCINFO_24HOUR 0x40 // 0: 12-hour mode, 1: 24-hour mode
|
||||
#define SIIRTCINFO_POWER 0x80 // power on or power failure occurred
|
||||
|
||||
enum
|
||||
{
|
||||
MONTH_JAN = 1,
|
||||
MONTH_FEB,
|
||||
MONTH_MAR,
|
||||
MONTH_APR,
|
||||
MONTH_MAY,
|
||||
MONTH_JUN,
|
||||
MONTH_JUL,
|
||||
MONTH_AUG,
|
||||
MONTH_SEP,
|
||||
MONTH_OCT,
|
||||
MONTH_NOV,
|
||||
MONTH_DEC
|
||||
};
|
||||
|
||||
struct SiiRtcInfo
|
||||
{
|
||||
u8 year;
|
||||
u8 month;
|
||||
u8 day;
|
||||
u8 dayOfWeek;
|
||||
u8 hour;
|
||||
u8 minute;
|
||||
u8 second;
|
||||
u8 status;
|
||||
u8 alarmHour;
|
||||
u8 alarmMinute;
|
||||
};
|
||||
|
||||
void SiiRtcUnprotect(void);
|
||||
void SiiRtcProtect(void);
|
||||
u8 SiiRtcProbe(void);
|
||||
bool8 SiiRtcReset(void);
|
||||
bool8 SiiRtcGetStatus(struct SiiRtcInfo *rtc);
|
||||
bool8 SiiRtcSetStatus(struct SiiRtcInfo *rtc);
|
||||
bool8 SiiRtcGetDateTime(struct SiiRtcInfo *rtc);
|
||||
bool8 SiiRtcSetDateTime(struct SiiRtcInfo *rtc);
|
||||
bool8 SiiRtcGetTime(struct SiiRtcInfo *rtc);
|
||||
bool8 SiiRtcSetTime(struct SiiRtcInfo *rtc);
|
||||
bool8 SiiRtcSetAlarm(struct SiiRtcInfo *rtc);
|
||||
|
||||
#endif // GUARD_RTC_H
|
||||
@@ -506,6 +506,7 @@ extern const u8 gText_ABtnRegistrationCounter[];
|
||||
extern const u8 gText_SaveFileCorrupted[];
|
||||
extern const u8 gText_SaveFileHasBeenDeleted[];
|
||||
extern const u8 gText_1MSubCircuitBoardNotInstalled[];
|
||||
extern const u8 gText_BatteryRunDry[];
|
||||
extern const u8 gText_NewGame[];
|
||||
extern const u8 gText_Continue[];
|
||||
extern const u8 gText_MysteryGift[];
|
||||
@@ -520,6 +521,11 @@ extern const u8 gText_Badges[];
|
||||
extern const u8 gTextJPDummy_Ko[];
|
||||
extern const u8 gText_Register[];
|
||||
|
||||
// wallclock
|
||||
extern const u8 gText_Confirm3[];
|
||||
extern const u8 gText_Cancel4[];
|
||||
extern const u8 gText_IsThisTheCorrectTime[];
|
||||
|
||||
// mystery_gift_menu
|
||||
extern const u8 gText_PickOKExit[];
|
||||
extern const u8 gText_PickOKCancel[];
|
||||
@@ -625,6 +631,19 @@ extern const u8 gText_MessageWillBeLost[];
|
||||
extern const u8 gText_BagIsFull[];
|
||||
extern const u8 gText_MailReturnedToBagMessageErased[];
|
||||
|
||||
// reset rtc screen texts
|
||||
extern const u8 gText_Day[];
|
||||
extern const u8 gText_Colon3[];
|
||||
extern const u8 gText_Confirm2[];
|
||||
extern const u8 gText_PresentTime[];
|
||||
extern const u8 gText_PreviousTime[];
|
||||
extern const u8 gText_ResetRTCConfirmCancel[];
|
||||
extern const u8 gText_NoSaveFileCantSetTime[];
|
||||
extern const u8 gText_PleaseResetTime[];
|
||||
extern const u8 gText_ClockHasBeenReset[];
|
||||
extern const u8 gText_SaveCompleted[];
|
||||
extern const u8 gText_SaveFailed[];
|
||||
|
||||
// start_menu
|
||||
extern const u8 gText_MenuPokedex[];
|
||||
extern const u8 gText_MenuBag[];
|
||||
|
||||
6
include/time_events.h
Normal file
6
include/time_events.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef GUARD_TIME_EVENTS_H
|
||||
#define GUARD_TIME_EVENTS_H
|
||||
|
||||
|
||||
|
||||
#endif // GUARD_TIME_EVENTS_H
|
||||
7
include/wallclock.h
Normal file
7
include/wallclock.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef GUARD_WALLCLOCK_H
|
||||
#define GUARD_WALLCLOCK_H
|
||||
|
||||
void CB2_StartWallClock(void);
|
||||
void CB2_ViewWallClock(void);
|
||||
|
||||
#endif //GUARD_WALLCLOCK_H
|
||||
11
ld_script.ld
11
ld_script.ld
@@ -71,6 +71,7 @@ SECTIONS {
|
||||
src/string_util.o(.text);
|
||||
src/link.o(.text);
|
||||
src/multiboot.o(.text);
|
||||
src/rtc.o(.text);
|
||||
src/main_menu.o(.text);
|
||||
src/battle_controllers.o(.text);
|
||||
src/decompress.o(.text);
|
||||
@@ -114,6 +115,8 @@ SECTIONS {
|
||||
src/event_data.o(.text);
|
||||
src/coord_event_weather.o(.text);
|
||||
src/field_tasks.o(.text);
|
||||
src/clock.o(.text);
|
||||
src/reset_rtc_screen.o(.text);
|
||||
src/start_menu.o(.text);
|
||||
src/tileset_anims.o(.text);
|
||||
src/palette.o(.text);
|
||||
@@ -197,10 +200,12 @@ SECTIONS {
|
||||
src/region_map.o(.text);
|
||||
src/image_processing_effects.o(.text);
|
||||
src/battle_ai_script_commands.o(.text);
|
||||
src/wallclock.o(.text);
|
||||
src/fldeff_rocksmash.o(.text);
|
||||
src/fldeff_dig.o(.text);
|
||||
src/fldeff_flash.o(.text);
|
||||
src/post_battle_event_funcs.o(.text);
|
||||
src/time_events.o(.text);
|
||||
src/prof_pc.o(.text);
|
||||
src/hof_pc.o(.text);
|
||||
src/field_specials.o(.text);
|
||||
@@ -338,6 +343,7 @@ SECTIONS {
|
||||
src/agb_flash_1m.o(.text);
|
||||
src/agb_flash_mx.o(.text);
|
||||
src/agb_flash_le.o(.text);
|
||||
src/siirtc.o(.text);
|
||||
src/librfu_stwi.o(.text);
|
||||
src/librfu_intr.o(.text);
|
||||
src/librfu_rfu.o(.text);
|
||||
@@ -411,6 +417,8 @@ SECTIONS {
|
||||
src/bg_regs.o(.rodata);
|
||||
src/string_util.o(.rodata);
|
||||
src/link.o(.rodata);
|
||||
src/rtc.o(.rodata);
|
||||
src/reset_rtc_screen.o(.rodata);
|
||||
src/main_menu.o(.rodata);
|
||||
src/data.o(.rodata);
|
||||
src/battle_bg.o(.rodata);
|
||||
@@ -506,7 +514,9 @@ SECTIONS {
|
||||
src/region_map.o(.rodata);
|
||||
src/image_processing_effects.o(.rodata);
|
||||
src/battle_ai_script_commands.o(.rodata);
|
||||
src/wallclock.o(.rodata);
|
||||
src/fldeff_flash.o(.rodata);
|
||||
src/time_events.o(.rodata);
|
||||
src/field_specials.o(.rodata);
|
||||
src/battle_records.o(.rodata);
|
||||
src/evolution_scene.o(.rodata);
|
||||
@@ -975,6 +985,7 @@ SECTIONS {
|
||||
src/agb_flash_1m.o(.rodata);
|
||||
src/agb_flash_mx.o(.rodata);
|
||||
src/agb_flash_le.o(.rodata);
|
||||
src/siirtc.o(.rodata);
|
||||
src/librfu_rfu.o(.rodata);
|
||||
src/librfu_sio32id.o(.rodata);
|
||||
src/isagbprn.o(.rodata);
|
||||
|
||||
87
src/clock.c
Normal file
87
src/clock.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "global.h"
|
||||
#include "event_data.h"
|
||||
#include "rtc.h"
|
||||
#include "time_events.h"
|
||||
#include "field_specials.h"
|
||||
// #include "lottery_corner.h"
|
||||
// #include "dewford_trend.h"
|
||||
// #include "tv.h"
|
||||
#include "field_weather.h"
|
||||
// #include "berry.h"
|
||||
#include "main.h"
|
||||
#include "overworld.h"
|
||||
#include "wallclock.h"
|
||||
|
||||
static void UpdatePerDay(struct Time *localTime);
|
||||
static void UpdatePerMinute(struct Time *localTime);
|
||||
|
||||
static void InitTimeBasedEvents(void)
|
||||
{
|
||||
FlagSet(FLAG_SYS_CLOCK_SET);
|
||||
RtcCalcLocalTime();
|
||||
gSaveBlock2Ptr->lastBerryTreeUpdate = gLocalTime;
|
||||
VarSet(VAR_DAYS, gLocalTime.days);
|
||||
}
|
||||
|
||||
void DoTimeBasedEvents(void)
|
||||
{
|
||||
// TODO: relevant?
|
||||
if (FlagGet(FLAG_SYS_CLOCK_SET)) // && !InPokemonCenter()
|
||||
{
|
||||
RtcCalcLocalTime();
|
||||
UpdatePerDay(&gLocalTime);
|
||||
UpdatePerMinute(&gLocalTime);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdatePerDay(struct Time *localTime)
|
||||
{
|
||||
u16 *days = GetVarPointer(VAR_DAYS);
|
||||
u16 daysSince;
|
||||
|
||||
if (*days != localTime->days && *days <= localTime->days)
|
||||
{
|
||||
daysSince = localTime->days - *days;
|
||||
ClearDailyFlags();
|
||||
// UpdateDewfordTrendPerDay(daysSince);
|
||||
// UpdateTVShowsPerDay(daysSince);
|
||||
// UpdateWeatherPerDay(daysSince);
|
||||
UpdatePartyPokerusTime(daysSince);
|
||||
// UpdateMirageRnd(daysSince);
|
||||
// UpdateBirchState(daysSince);
|
||||
// UpdateFrontierManiac(daysSince);
|
||||
// UpdateFrontierGambler(daysSince);
|
||||
// SetShoalItemFlag(daysSince);
|
||||
// SetRandomLotteryNumber(daysSince);
|
||||
*days = localTime->days;
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdatePerMinute(struct Time *localTime)
|
||||
{
|
||||
struct Time difference;
|
||||
int minutes;
|
||||
|
||||
CalcTimeDifference(&difference, &gSaveBlock2Ptr->lastBerryTreeUpdate, localTime);
|
||||
minutes = 24 * 60 * difference.days + 60 * difference.hours + difference.minutes;
|
||||
if (minutes != 0)
|
||||
{
|
||||
if (minutes >= 0)
|
||||
{
|
||||
// BerryTreeTimeUpdate(minutes);
|
||||
gSaveBlock2Ptr->lastBerryTreeUpdate = *localTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ReturnFromStartWallClock(void)
|
||||
{
|
||||
InitTimeBasedEvents();
|
||||
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
|
||||
}
|
||||
|
||||
void StartWallClock(void)
|
||||
{
|
||||
SetMainCallback2(CB2_StartWallClock);
|
||||
gMain.savedCallback = ReturnFromStartWallClock;
|
||||
}
|
||||
@@ -13632,9 +13632,9 @@ const struct SpeciesInfo gSpeciesInfoGen1[] =
|
||||
{EVO_ITEM, ITEM_FIRE_STONE, SPECIES_FLAREON},
|
||||
{EVO_FRIENDSHIP_DAY, 0, SPECIES_ESPEON},
|
||||
{EVO_FRIENDSHIP_NIGHT, 0, SPECIES_UMBREON},
|
||||
{EVO_SPECIFIC_MAP, MAPSEC_VIRIDIAN_FOREST, SPECIES_LEAFEON},
|
||||
{EVO_SPECIFIC_MAP, MAP_VIRIDIAN_FOREST, SPECIES_LEAFEON},
|
||||
{EVO_ITEM, ITEM_LEAF_STONE, SPECIES_LEAFEON},
|
||||
{EVO_SPECIFIC_MAP, MAPSEC_SEAFOAM_ISLANDS, SPECIES_GLACEON},
|
||||
{EVO_SPECIFIC_MAP, MAP_SEAFOAM_ISLANDS_B4F, SPECIES_GLACEON},
|
||||
{EVO_ITEM, ITEM_ICE_STONE, SPECIES_GLACEON},
|
||||
{EVO_FRIENDSHIP_MOVE_TYPE, TYPE_FAIRY, SPECIES_SYLVEON}),
|
||||
},
|
||||
|
||||
@@ -1126,7 +1126,7 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
|
||||
FOOTPRINT(Crabrawler)
|
||||
.levelUpLearnset = sCrabrawlerLevelUpLearnset,
|
||||
.teachableLearnset = sCrabrawlerTeachableLearnset,
|
||||
.evolutions = EVOLUTION({EVO_SPECIFIC_MAP, MAPSEC_SEAFOAM_ISLANDS, SPECIES_CRABOMINABLE},
|
||||
.evolutions = EVOLUTION({EVO_SPECIFIC_MAP, MAP_SEAFOAM_ISLANDS_B4F, SPECIES_CRABOMINABLE},
|
||||
{EVO_ITEM, ITEM_ICE_STONE, SPECIES_CRABOMINABLE}),
|
||||
},
|
||||
|
||||
|
||||
@@ -8263,42 +8263,42 @@
|
||||
{
|
||||
"min_level": 3,
|
||||
"max_level": 3,
|
||||
"species": "SPECIES_DEOXYS"
|
||||
"species": "SPECIES_EEVEE"
|
||||
},
|
||||
{
|
||||
"min_level": 3,
|
||||
"max_level": 3,
|
||||
"species": "SPECIES_DEOXYS"
|
||||
"species": "SPECIES_EEVEE"
|
||||
},
|
||||
{
|
||||
"min_level": 3,
|
||||
"max_level": 3,
|
||||
"species": "SPECIES_DEOXYS_ATTACK"
|
||||
"species": "SPECIES_EEVEE"
|
||||
},
|
||||
{
|
||||
"min_level": 3,
|
||||
"max_level": 3,
|
||||
"species": "SPECIES_DEOXYS_ATTACK"
|
||||
"species": "SPECIES_EEVEE"
|
||||
},
|
||||
{
|
||||
"min_level": 2,
|
||||
"max_level": 2,
|
||||
"species": "SPECIES_DEOXYS_DEFENSE"
|
||||
"species": "SPECIES_EEVEE"
|
||||
},
|
||||
{
|
||||
"min_level": 2,
|
||||
"max_level": 2,
|
||||
"species": "SPECIES_DEOXYS_DEFENSE"
|
||||
"species": "SPECIES_EEVEE"
|
||||
},
|
||||
{
|
||||
"min_level": 3,
|
||||
"max_level": 3,
|
||||
"species": "SPECIES_DEOXYS_DEFENSE"
|
||||
"species": "SPECIES_EEVEE"
|
||||
},
|
||||
{
|
||||
"min_level": 3,
|
||||
"max_level": 3,
|
||||
"species": "SPECIES_MIMIKYU"
|
||||
"species": "SPECIES_EEVEE"
|
||||
},
|
||||
{
|
||||
"min_level": 4,
|
||||
|
||||
@@ -35,6 +35,9 @@ EWRAM_DATA u16 gSpecialVar_PrevTextColor = 0;
|
||||
EWRAM_DATA u16 gSpecialVar_0x8014 = 0;
|
||||
EWRAM_DATA u8 sSpecialFlags[SPECIAL_FLAGS_SIZE] = {};
|
||||
|
||||
#define NUM_DAILY_FLAGS (DAILY_FLAGS_END - DAILY_FLAGS_START + 1)
|
||||
#define DAILY_FLAGS_SIZE (NUM_DAILY_FLAGS / 8)
|
||||
|
||||
u16 gLastQuestLogStoredFlagOrVarIdx;
|
||||
|
||||
extern u16 *const gSpecialVars[];
|
||||
@@ -57,6 +60,12 @@ void ClearTempFieldEventData(void)
|
||||
FlagClear(FLAG_SYS_INFORMED_OF_LOCAL_WIRELESS_PLAYER);
|
||||
}
|
||||
|
||||
|
||||
void ClearDailyFlags(void)
|
||||
{
|
||||
memset(gSaveBlock1Ptr->flags + (DAILY_FLAGS_START / 8), 0, DAILY_FLAGS_SIZE);
|
||||
}
|
||||
|
||||
// Unused
|
||||
static void DisableNationalPokedex_RSE(void)
|
||||
{
|
||||
@@ -176,11 +185,12 @@ void EnableResetRTC(void)
|
||||
|
||||
bool32 CanResetRTC(void)
|
||||
{
|
||||
if (!FlagGet(FLAG_SYS_RESET_RTC_ENABLE))
|
||||
return FALSE;
|
||||
if (VarGet(VAR_RESET_RTC_ENABLE) != 0x0920)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
// if (!FlagGet(FLAG_SYS_RESET_RTC_ENABLE))
|
||||
// return FALSE;
|
||||
// if (VarGet(VAR_RESET_RTC_ENABLE) != 0x0920)
|
||||
// return FALSE;
|
||||
// return TRUE;
|
||||
}
|
||||
|
||||
u16 *GetVarPointer(u16 idx)
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "mystery_gift.h"
|
||||
#include "naming_screen.h"
|
||||
#include "party_menu.h"
|
||||
#include "rtc.h"
|
||||
#include "wallclock.h"
|
||||
#include "dynamic_placeholder_text_util.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "constants/songs.h"
|
||||
@@ -94,6 +96,13 @@ void ShowDiploma(void)
|
||||
LockPlayerFieldControls();
|
||||
}
|
||||
|
||||
void Special_ViewWallClock(void)
|
||||
{
|
||||
gMain.savedCallback = CB2_ReturnToField;
|
||||
SetMainCallback2(CB2_ViewWallClock);
|
||||
LockPlayerFieldControls();
|
||||
}
|
||||
|
||||
void ForcePlayerOntoBike(void)
|
||||
{
|
||||
if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ON_FOOT)
|
||||
@@ -160,6 +169,16 @@ void SetHiddenItemFlag(void)
|
||||
FlagSet(gSpecialVar_0x8004);
|
||||
}
|
||||
|
||||
u16 GetWeekCount(void)
|
||||
{
|
||||
u16 weekCount = gLocalTime.days / 7;
|
||||
if (weekCount > 9999)
|
||||
{
|
||||
weekCount = 9999;
|
||||
}
|
||||
return weekCount;
|
||||
}
|
||||
|
||||
u8 GetLeadMonFriendship(void)
|
||||
{
|
||||
struct Pokemon * pokemon = &gPlayerParty[GetLeadMonIndex()];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "bike.h"
|
||||
#include "clock.h"
|
||||
#include "event_data.h"
|
||||
#include "field_camera.h"
|
||||
#include "field_effect_helpers.h"
|
||||
@@ -69,18 +70,45 @@ static void Task_RunPerStepCallback(u8 taskId)
|
||||
sPerStepCallbacks[idx](taskId);
|
||||
}
|
||||
|
||||
|
||||
// RTC functionality from RS was removed here.
|
||||
#define tState data[0]
|
||||
#define tAmbientCryState data[1]
|
||||
#define tAmbientCryDelay data[2]
|
||||
|
||||
// RTC functionality from RS was removed here.
|
||||
static void RunTimeBasedEvents(s16 *data)
|
||||
{
|
||||
switch (tState)
|
||||
{
|
||||
case 0:
|
||||
if (*gMain.vblankCounter1 & 0x1000)
|
||||
{
|
||||
DoTimeBasedEvents();
|
||||
tState++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (!(*gMain.vblankCounter1 & 0x1000))
|
||||
{
|
||||
tState--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Task_RunTimeBasedEvents(u8 taskId)
|
||||
{
|
||||
s16 *data = gTasks[taskId].data;
|
||||
|
||||
if (!ArePlayerFieldControlsLocked() && !QL_IS_PLAYBACK_STATE)
|
||||
{
|
||||
RunTimeBasedEvents(data);
|
||||
UpdateAmbientCry(&tAmbientCryState, &tAmbientCryDelay);
|
||||
}
|
||||
}
|
||||
|
||||
#undef tState
|
||||
|
||||
void SetUpFieldTasks(void)
|
||||
{
|
||||
if (!FuncIsActiveTask(Task_RunPerStepCallback))
|
||||
|
||||
@@ -1258,6 +1258,12 @@ const u16 gTilesetPalettes_General[][16] =
|
||||
|
||||
const u32 gTilesetTiles_General[] = INCBIN_U32("data/tilesets/primary/general/tiles.4bpp.lz");
|
||||
|
||||
const u16 gWallClockMale_Pal[] = INCBIN_U16("graphics/wallclock/male.gbapal");
|
||||
const u16 gWallClockFemale_Pal[] = INCBIN_U16("graphics/wallclock/female.gbapal");
|
||||
const u32 gWallClock_Gfx[] = INCBIN_U32("graphics/wallclock/clock.4bpp.lz");
|
||||
const u32 gWallClockStart_Tilemap[] = INCBIN_U32("graphics/wallclock/clock_start.bin.lz");
|
||||
const u32 gWallClockView_Tilemap[] = INCBIN_U32("graphics/wallclock/clock_view.bin.lz");
|
||||
|
||||
const u8 gBerryFixGameboy_Pal[] = INCBIN_U8("graphics/berry_fix/gba_small.gbapal");
|
||||
const u8 gBerryFixGameboy_Gfx[] = INCBIN_U8("graphics/berry_fix/gba_small.4bpp.lz");
|
||||
const u8 gBerryFixGameboy_Tilemap[] = INCBIN_U8("graphics/berry_fix/gba_small.bin.lz");
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "decompress.h"
|
||||
#include "util.h"
|
||||
#include "trig.h"
|
||||
#include "load_save.h"
|
||||
#include "constants/songs.h"
|
||||
#include "constants/sound.h"
|
||||
|
||||
@@ -992,12 +993,15 @@ void CB2_InitCopyrightScreenAfterBootup(void)
|
||||
{
|
||||
if (!SetUpCopyrightScreen())
|
||||
{
|
||||
SeedRngAndSetTrainerId();
|
||||
SetSaveBlocksPointers();
|
||||
ResetMenuAndMonGlobals();
|
||||
Save_ResetSaveCounters();
|
||||
LoadGameSave(SAVE_NORMAL);
|
||||
if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_INVALID)
|
||||
Sav2_ClearSetDefault();
|
||||
SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound);
|
||||
InitHeap(gHeap, HEAP_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "link_rfu.h"
|
||||
#include "load_save.h"
|
||||
#include "m4a.h"
|
||||
#include "rtc.h"
|
||||
#include "random.h"
|
||||
#include "gba/flash_internal.h"
|
||||
#include "help_system.h"
|
||||
@@ -130,6 +131,7 @@ void AgbMain()
|
||||
m4aSoundInit();
|
||||
EnableVCountIntrAtLine150();
|
||||
InitRFU();
|
||||
RtcInit();
|
||||
CheckForFlashMemory();
|
||||
InitMainCallbacks();
|
||||
InitMapMusic();
|
||||
@@ -463,6 +465,7 @@ void DoSoftReset(void)
|
||||
DmaStop(1);
|
||||
DmaStop(2);
|
||||
DmaStop(3);
|
||||
SiiRtcProtect();
|
||||
SoftReset(RESET_ALL & ~RESET_SIO_REGS);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "save.h"
|
||||
#include "event_data.h"
|
||||
#include "menu.h"
|
||||
#include "rtc.h"
|
||||
#include "link.h"
|
||||
#include "oak_speech.h"
|
||||
#include "overworld.h"
|
||||
@@ -44,6 +45,8 @@ enum MainMenuWindow
|
||||
|
||||
static bool32 MainMenuGpuInit(u8 a0);
|
||||
static void Task_SetWin0BldRegsAndCheckSaveFile(u8 taskId);
|
||||
static void Task_MainMenuCheckBattery(u8);
|
||||
static void Task_WaitForBatteryDryErrorWindow(u8);
|
||||
static void PrintSaveErrorStatus(u8 taskId, const u8 *str);
|
||||
static void Task_SaveErrorStatus_RunPrinterThenWaitButton(u8 taskId);
|
||||
static void Task_SetWin0BldRegsNoSaveFileCheck(u8 taskId);
|
||||
@@ -241,7 +244,8 @@ static void Task_SetWin0BldRegsAndCheckSaveFile(u8 taskId)
|
||||
{
|
||||
gTasks[taskId].tMenuType = MAIN_MENU_CONTINUE;
|
||||
}
|
||||
gTasks[taskId].func = Task_SetWin0BldRegsNoSaveFileCheck;
|
||||
// gTasks[taskId].func = Task_SetWin0BldRegsNoSaveFileCheck;
|
||||
gTasks[taskId].func = Task_MainMenuCheckBattery;
|
||||
break;
|
||||
case SAVE_STATUS_INVALID:
|
||||
SetStdFrame0OnBg(0);
|
||||
@@ -276,6 +280,67 @@ static void Task_SetWin0BldRegsAndCheckSaveFile(u8 taskId)
|
||||
}
|
||||
}
|
||||
|
||||
static void Task_MainMenuCheckBattery(u8 taskId)
|
||||
{
|
||||
if (!gPaletteFade.active)
|
||||
{
|
||||
SetGpuReg(REG_OFFSET_WIN0H, 0);
|
||||
SetGpuReg(REG_OFFSET_WIN0V, 0);
|
||||
SetGpuReg(REG_OFFSET_WININ, 0x0001);
|
||||
SetGpuReg(REG_OFFSET_WINOUT, 0x0021);
|
||||
SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_DARKEN);
|
||||
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0));
|
||||
SetGpuReg(REG_OFFSET_BLDY, 7);
|
||||
|
||||
if (!(RtcGetErrorStatus() & RTC_ERR_FLAG_MASK))
|
||||
{
|
||||
if(gTasks[taskId].tMenuType == MAIN_MENU_NEWGAME) {
|
||||
LoadUserFrameToBg(0);
|
||||
gTasks[taskId].tMenuType = MAIN_MENU_NEWGAME;
|
||||
gTasks[taskId].func = Task_SetWin0BldRegsNoSaveFileCheck;
|
||||
}
|
||||
else {
|
||||
gTasks[taskId].func = Task_SetWin0BldRegsNoSaveFileCheck;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetStdFrame0OnBg(0);
|
||||
PrintSaveErrorStatus(taskId, gText_BatteryRunDry);
|
||||
gTasks[taskId].func = Task_WaitForBatteryDryErrorWindow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Task_WaitForBatteryDryErrorWindow(u8 taskId)
|
||||
{
|
||||
if (!gPaletteFade.active)
|
||||
{
|
||||
RunTextPrinters();
|
||||
if(gTasks[taskId].tUnused8 == 3)
|
||||
{
|
||||
if(!IsTextPrinterActive(MAIN_MENU_WINDOW_ERROR))
|
||||
{
|
||||
gTasks[taskId].func = Task_SetWin0BldRegsNoSaveFileCheck;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsTextPrinterActive(MAIN_MENU_WINDOW_ERROR) && JOY_NEW(A_BUTTON))
|
||||
{
|
||||
ClearWindowTilemap(MAIN_MENU_WINDOW_ERROR);
|
||||
MainMenu_EraseWindow(&sWindowTemplate[MAIN_MENU_WINDOW_ERROR]);
|
||||
LoadUserFrameToBg(0);
|
||||
|
||||
if (gTasks[taskId].tMenuType == MAIN_MENU_NEWGAME)
|
||||
gTasks[taskId].func = Task_SetWin0BldRegsNoSaveFileCheck;
|
||||
else
|
||||
gTasks[taskId].func = Task_PrintMainMenuText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintSaveErrorStatus(u8 taskId, const u8 *str)
|
||||
{
|
||||
PrintMessageOnWindow4(str);
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#include "berry_powder.h"
|
||||
#include "pokemon_jump.h"
|
||||
#include "event_scripts.h"
|
||||
#include "save.h"
|
||||
#include "rtc.h"
|
||||
|
||||
// this file's functions
|
||||
static void ResetMiniGamesResults(void);
|
||||
@@ -107,6 +109,9 @@ void ResetMenuAndMonGlobals(void)
|
||||
void NewGameInitData(void)
|
||||
{
|
||||
u8 rivalName[PLAYER_NAME_LENGTH + 1];
|
||||
|
||||
if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_INVALID)
|
||||
RtcReset();
|
||||
|
||||
StringCopy(rivalName, gSaveBlock1Ptr->rivalName);
|
||||
gDifferentSaveFile = TRUE;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "gflib.h"
|
||||
#include "bg_regs.h"
|
||||
#include "cable_club.h"
|
||||
#include "clock.h"
|
||||
#include "credits.h"
|
||||
#include "event_data.h"
|
||||
#include "event_object_movement.h"
|
||||
@@ -758,6 +759,7 @@ void LoadMapFromCameraTransition(u8 mapGroup, u8 mapNum)
|
||||
ResetCyclingRoadChallengeData();
|
||||
RestartWildEncounterImmunitySteps();
|
||||
MapResetTrainerRematches(mapGroup, mapNum);
|
||||
DoTimeBasedEvents();
|
||||
SetSavedWeatherFromCurrMapHeader();
|
||||
ChooseAmbientCrySpecies();
|
||||
SetDefaultFlashLevel();
|
||||
@@ -793,6 +795,7 @@ static void LoadMapFromWarp(bool32 unused)
|
||||
ResetCyclingRoadChallengeData();
|
||||
RestartWildEncounterImmunitySteps();
|
||||
MapResetTrainerRematches(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum);
|
||||
DoTimeBasedEvents();
|
||||
SetSavedWeatherFromCurrMapHeader();
|
||||
ChooseAmbientCrySpecies();
|
||||
if (isOutdoors)
|
||||
@@ -815,6 +818,7 @@ static void QL_LoadMapNormal(void)
|
||||
LoadObjEventTemplatesFromHeader();
|
||||
isOutdoors = IsMapTypeOutdoors(gMapHeader.mapType);
|
||||
TrySetMapSaveWarpStatus();
|
||||
DoTimeBasedEvents();
|
||||
SetSavedWeatherFromCurrMapHeader();
|
||||
ChooseAmbientCrySpecies();
|
||||
SetDefaultFlashLevel();
|
||||
@@ -1684,6 +1688,7 @@ void CB2_ContinueSavedGame(void)
|
||||
LoadSaveblockMapHeader();
|
||||
LoadSaveblockObjEventScripts();
|
||||
UnfreezeObjectEvents();
|
||||
DoTimeBasedEvents();
|
||||
Overworld_ResetStateOnContinue();
|
||||
InitMapFromSavedGame();
|
||||
PlayTimeCounter_Start();
|
||||
|
||||
149
src/pokemon.c
149
src/pokemon.c
@@ -3,6 +3,7 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "random.h"
|
||||
#include "rtc.h"
|
||||
#include "text.h"
|
||||
#include "data.h"
|
||||
#include "battle.h"
|
||||
@@ -4103,37 +4104,37 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
break;
|
||||
case EVO_FRIENDSHIP_DAY:
|
||||
if (/*GetTimeOfDay() != TIME_NIGHT &&*/ friendship >= FRIENDSHIP_EVO_THRESHOLD)
|
||||
if (GetTimeOfDay() != TIME_NIGHT && friendship >= FRIENDSHIP_EVO_THRESHOLD)
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
break;
|
||||
case EVO_LEVEL_DAY:
|
||||
if (/* GetTimeOfDay() != TIME_NIGHT && */ evolutions[i].param <= level)
|
||||
if (GetTimeOfDay() != TIME_NIGHT && evolutions[i].param <= level)
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
break;
|
||||
case EVO_FRIENDSHIP_NIGHT:
|
||||
if (/* GetTimeOfDay() == TIME_NIGHT && */ friendship >= FRIENDSHIP_EVO_THRESHOLD)
|
||||
if (GetTimeOfDay() == TIME_NIGHT && friendship >= FRIENDSHIP_EVO_THRESHOLD)
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
break;
|
||||
case EVO_LEVEL_NIGHT:
|
||||
if (/* GetTimeOfDay() == TIME_NIGHT && */ evolutions[i].param <= level)
|
||||
if (GetTimeOfDay() == TIME_NIGHT && evolutions[i].param <= level)
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
break;
|
||||
case EVO_ITEM_HOLD_NIGHT:
|
||||
if (/* GetTimeOfDay() == TIME_NIGHT && */ heldItem == evolutions[i].param)
|
||||
if (GetTimeOfDay() == TIME_NIGHT && heldItem == evolutions[i].param)
|
||||
{
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
consumeItem = TRUE;
|
||||
}
|
||||
break;
|
||||
case EVO_ITEM_HOLD_DAY:
|
||||
if (/* GetTimeOfDay() != TIME_NIGHT && */ heldItem == evolutions[i].param)
|
||||
if (GetTimeOfDay() != TIME_NIGHT && heldItem == evolutions[i].param)
|
||||
{
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
consumeItem = TRUE;
|
||||
}
|
||||
break;
|
||||
case EVO_LEVEL_DUSK:
|
||||
if (/* GetTimeOfDay() == TIME_EVENING && */ evolutions[i].param <= level)
|
||||
if (GetTimeOfDay() == TIME_EVENING && evolutions[i].param <= level)
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
break;
|
||||
case EVO_LEVEL:
|
||||
@@ -4374,11 +4375,11 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
break;
|
||||
case EVO_ITEM_NIGHT:
|
||||
if (/* GetTimeOfDay() == TIME_NIGHT && */ evolutions[i].param == evolutionItem)
|
||||
if (GetTimeOfDay() == TIME_NIGHT && evolutions[i].param == evolutionItem)
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
break;
|
||||
case EVO_ITEM_DAY:
|
||||
if (/* GetTimeOfDay() != TIME_NIGHT && */ evolutions[i].param == evolutionItem)
|
||||
if (GetTimeOfDay() != TIME_NIGHT && evolutions[i].param == evolutionItem)
|
||||
targetSpecies = evolutions[i].targetSpecies;
|
||||
break;
|
||||
}
|
||||
@@ -4949,14 +4950,44 @@ u16 GetMonEVCount(struct Pokemon *mon)
|
||||
return count;
|
||||
}
|
||||
|
||||
// This function was stubbed from RS, but it is stubbed badly.
|
||||
// This variable is likely the u8 passed to SetMonData in RSE.
|
||||
// The pointer reference causes agbcc to reserve it on the stack before even checking
|
||||
// whether it's used.
|
||||
void RandomlyGivePartyPokerus(struct Pokemon *party)
|
||||
{
|
||||
u8 foo;
|
||||
&foo;
|
||||
u16 rnd = Random();
|
||||
if (rnd == 0x4000 || rnd == 0x8000 || rnd == 0xC000)
|
||||
{
|
||||
struct Pokemon *mon;
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
rnd = Random() % PARTY_SIZE;
|
||||
mon = &party[rnd];
|
||||
}
|
||||
while (!GetMonData(mon, MON_DATA_SPECIES, 0));
|
||||
}
|
||||
while (GetMonData(mon, MON_DATA_IS_EGG, 0));
|
||||
|
||||
if (!(CheckPartyHasHadPokerus(party, gBitTable[rnd])))
|
||||
{
|
||||
u8 rnd2;
|
||||
|
||||
do
|
||||
{
|
||||
rnd2 = Random();
|
||||
}
|
||||
while ((rnd2 & 0x7) == 0);
|
||||
|
||||
if (rnd2 & 0xF0)
|
||||
rnd2 &= 0x7;
|
||||
|
||||
rnd2 |= (rnd2 << 4);
|
||||
rnd2 &= 0xF3;
|
||||
rnd2++;
|
||||
|
||||
SetMonData(&party[rnd], MON_DATA_POKERUS, &rnd2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 CheckPartyPokerus(struct Pokemon *party, u8 selection)
|
||||
@@ -5017,16 +5048,58 @@ u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection)
|
||||
|
||||
// These two functions are stubbed from RS, but they're stubbed badly.
|
||||
// See note on RandomlyGivePartyPokerus above.
|
||||
static void UpdatePartyPokerusTime(void)
|
||||
void UpdatePartyPokerusTime(u16 days)
|
||||
{
|
||||
u8 foo;
|
||||
&foo;
|
||||
int i;
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, 0))
|
||||
{
|
||||
u8 pokerus = GetMonData(&gPlayerParty[i], MON_DATA_POKERUS, 0);
|
||||
if (pokerus & 0xF)
|
||||
{
|
||||
if ((pokerus & 0xF) < days || days > 4)
|
||||
pokerus &= 0xF0;
|
||||
else
|
||||
pokerus -= days;
|
||||
|
||||
if (pokerus == 0)
|
||||
pokerus = 0x10;
|
||||
|
||||
SetMonData(&gPlayerParty[i], MON_DATA_POKERUS, &pokerus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PartySpreadPokerus(struct Pokemon *party)
|
||||
{
|
||||
u8 foo;
|
||||
&foo;
|
||||
if ((Random() % 3) == 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_SPECIES, 0))
|
||||
{
|
||||
u8 pokerus = GetMonData(&party[i], MON_DATA_POKERUS, 0);
|
||||
u8 curPokerus = pokerus;
|
||||
if (pokerus)
|
||||
{
|
||||
if (pokerus & 0xF)
|
||||
{
|
||||
// Spread to adjacent party members.
|
||||
if (i != 0 && !(GetMonData(&party[i - 1], MON_DATA_POKERUS, 0) & 0xF0))
|
||||
SetMonData(&party[i - 1], MON_DATA_POKERUS, &curPokerus);
|
||||
if (i != (PARTY_SIZE - 1) && !(GetMonData(&party[i + 1], MON_DATA_POKERUS, 0) & 0xF0))
|
||||
{
|
||||
SetMonData(&party[i + 1], MON_DATA_POKERUS, &curPokerus);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SetMonExpWithMaxLevelCheck(struct Pokemon *mon, int species, u8 unused, u32 data)
|
||||
@@ -5926,18 +5999,15 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32
|
||||
case FORM_CHANGE_ITEM_USE:
|
||||
if (arg == formChanges[i].param1)
|
||||
{
|
||||
// TODO: time
|
||||
switch (formChanges[i].param2)
|
||||
{
|
||||
case DAY:
|
||||
// if (GetTimeOfDay() != TIME_NIGHT)
|
||||
// targetSpecies = formChanges[i].targetSpecies;
|
||||
targetSpecies = SPECIES_NONE;
|
||||
if (GetTimeOfDay() != TIME_NIGHT)
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
break;
|
||||
case NIGHT:
|
||||
// if (GetTimeOfDay() == TIME_NIGHT)
|
||||
// targetSpecies = formChanges[i].targetSpecies;
|
||||
targetSpecies = SPECIES_NONE;
|
||||
if (GetTimeOfDay() == TIME_NIGHT)
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
break;
|
||||
default:
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
@@ -5971,20 +6041,17 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
break;
|
||||
case FORM_CHANGE_TIME_OF_DAY:
|
||||
// TODO: time
|
||||
// switch (formChanges[i].param1)
|
||||
// {
|
||||
// case DAY:
|
||||
// if (GetTimeOfDay() != TIME_NIGHT)
|
||||
// targetSpecies = formChanges[i].targetSpecies;
|
||||
// break;
|
||||
// case NIGHT:
|
||||
// if (GetTimeOfDay() == TIME_NIGHT)
|
||||
// targetSpecies = formChanges[i].targetSpecies;
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
targetSpecies = SPECIES_NONE;
|
||||
switch (formChanges[i].param1)
|
||||
{
|
||||
case DAY:
|
||||
if (GetTimeOfDay() != TIME_NIGHT)
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
break;
|
||||
case NIGHT:
|
||||
if (GetTimeOfDay() == TIME_NIGHT)
|
||||
targetSpecies = formChanges[i].targetSpecies;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
766
src/reset_rtc_screen.c
Normal file
766
src/reset_rtc_screen.c
Normal file
@@ -0,0 +1,766 @@
|
||||
#include "global.h"
|
||||
#include "reset_rtc_screen.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "event_data.h"
|
||||
#include "main.h"
|
||||
#include "menu.h"
|
||||
#include "palette.h"
|
||||
#include "rtc.h"
|
||||
#include "save.h"
|
||||
#include "sprite.h"
|
||||
#include "constants/songs.h"
|
||||
#include "sound.h"
|
||||
#include "string_util.h"
|
||||
#include "strings.h"
|
||||
#include "task.h"
|
||||
#include "text.h"
|
||||
#include "text_window.h"
|
||||
#include "scanline_effect.h"
|
||||
#include "bg.h"
|
||||
#include "window.h"
|
||||
#include "gpu_regs.h"
|
||||
#include "constants/rgb.h"
|
||||
|
||||
#define PALTAG_ARROW 0x1000
|
||||
|
||||
// Task data for the Task_ResetRtc_* series of tasks, when setting the time on the clock
|
||||
// Data from these tasks is also used by the cursors and the main task (Task_ResetRtcScreen)
|
||||
enum {
|
||||
DATAIDX_DAYS = 3,
|
||||
DATAIDX_HOURS,
|
||||
DATAIDX_MINS,
|
||||
DATAIDX_SECS,
|
||||
DATAIDX_CONFIRM,
|
||||
};
|
||||
#define tFinished data[0]
|
||||
#define tSetTime data[1]
|
||||
#define tSelection data[2]
|
||||
#define tDays data[DATAIDX_DAYS]
|
||||
#define tHours data[DATAIDX_HOURS]
|
||||
#define tMinutes data[DATAIDX_MINS]
|
||||
#define tSeconds data[DATAIDX_SECS]
|
||||
#define tConfirm data[DATAIDX_CONFIRM]
|
||||
#define tWindowId data[8]
|
||||
|
||||
enum {
|
||||
SELECTION_DAYS = 1,
|
||||
SELECTION_HOURS,
|
||||
SELECTION_MINS,
|
||||
SELECTION_SECS,
|
||||
SELECTION_CONFIRM,
|
||||
SELECTION_NONE
|
||||
};
|
||||
|
||||
enum {
|
||||
WIN_TIME,
|
||||
WIN_MSG,
|
||||
};
|
||||
|
||||
struct ResetRtcInputMap
|
||||
{
|
||||
/*0x0*/ u8 dataIndex;
|
||||
/*0x2*/ u16 minVal;
|
||||
/*0x4*/ u16 maxVal;
|
||||
/*0x6*/ u8 left;
|
||||
/*0x7*/ u8 right;
|
||||
/*0x8*/ u8 unk; // never read
|
||||
};
|
||||
|
||||
static void CB2_ResetRtcScreen(void);
|
||||
static void VBlankCB(void);
|
||||
static void Task_ResetRtcScreen(u8 taskId);
|
||||
static void InitResetRtcScreenBgAndWindows(void);
|
||||
|
||||
static const struct BgTemplate sBgTemplates[] =
|
||||
{
|
||||
{
|
||||
.bg = 0,
|
||||
.charBaseIndex = 0,
|
||||
.mapBaseIndex = 31,
|
||||
.screenSize = 0,
|
||||
.paletteMode = 0,
|
||||
.priority = 0,
|
||||
.baseTile = 0
|
||||
}
|
||||
};
|
||||
|
||||
static const struct WindowTemplate sWindowTemplates[] =
|
||||
{
|
||||
[WIN_TIME] = {
|
||||
.bg = 0,
|
||||
.tilemapLeft = 1,
|
||||
.tilemapTop = 1,
|
||||
.width = 19,
|
||||
.height = 9,
|
||||
.paletteNum = 15,
|
||||
.baseBlock = 0x155
|
||||
},
|
||||
[WIN_MSG] = {
|
||||
.bg = 0,
|
||||
.tilemapLeft = 2,
|
||||
.tilemapTop = 15,
|
||||
.width = 27,
|
||||
.height = 4,
|
||||
.paletteNum = 15,
|
||||
.baseBlock = 0xE9
|
||||
},
|
||||
DUMMY_WIN_TEMPLATE
|
||||
};
|
||||
|
||||
static const struct WindowTemplate sInputTimeWindow = {
|
||||
.bg = 0,
|
||||
.tilemapLeft = 4,
|
||||
.tilemapTop = 9,
|
||||
.width = 21,
|
||||
.height = 2,
|
||||
.paletteNum = 15,
|
||||
.baseBlock = 0xBF
|
||||
};
|
||||
|
||||
static const struct ResetRtcInputMap sInputMap[] =
|
||||
{
|
||||
[SELECTION_DAYS - 1] = {
|
||||
.dataIndex = DATAIDX_DAYS,
|
||||
.minVal = 1,
|
||||
.maxVal = 9999,
|
||||
.left = 0,
|
||||
.right = 2,
|
||||
.unk = 0,
|
||||
},
|
||||
[SELECTION_HOURS - 1] = {
|
||||
.dataIndex = DATAIDX_HOURS,
|
||||
.minVal = 0,
|
||||
.maxVal = 23,
|
||||
.left = 1,
|
||||
.right = 3,
|
||||
.unk = 0,
|
||||
},
|
||||
[SELECTION_MINS - 1] = {
|
||||
.dataIndex = DATAIDX_MINS,
|
||||
.minVal = 0,
|
||||
.maxVal = 59,
|
||||
.left = 2,
|
||||
.right = 4,
|
||||
.unk = 0,
|
||||
},
|
||||
[SELECTION_SECS - 1] = {
|
||||
.dataIndex = DATAIDX_SECS,
|
||||
.minVal = 0,
|
||||
.maxVal = 59,
|
||||
.left = 3,
|
||||
.right = 5,
|
||||
.unk = 0,
|
||||
},
|
||||
[SELECTION_CONFIRM - 1] = {
|
||||
.dataIndex = DATAIDX_CONFIRM,
|
||||
.minVal = 0,
|
||||
.maxVal = 0,
|
||||
.left = 4,
|
||||
.right = 0,
|
||||
.unk = 6,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct OamData sOamData_Arrow =
|
||||
{
|
||||
.y = 0,
|
||||
.affineMode = ST_OAM_AFFINE_OFF,
|
||||
.objMode = ST_OAM_OBJ_NORMAL,
|
||||
.mosaic = FALSE,
|
||||
.bpp = ST_OAM_4BPP,
|
||||
.shape = SPRITE_SHAPE(8x8),
|
||||
.x = 0,
|
||||
.matrixNum = 0,
|
||||
.size = SPRITE_SIZE(8x8),
|
||||
.tileNum = 0,
|
||||
.priority = 0,
|
||||
.paletteNum = 0,
|
||||
.affineParam = 0,
|
||||
};
|
||||
static const u8 sResetRtcScreen_DownArrowGfx[] = INCBIN_U8("graphics/misc/reset_rtc_screen_downarrow.4bpp");
|
||||
static const u8 sResetRtcScreen_RightArrowGfx[] = INCBIN_U8("graphics/misc/reset_rtc_screen_rightarrow.4bpp");
|
||||
static const u16 sResetRtcScreen_ArrowPal[] = INCBIN_U16("graphics/misc/reset_rtc_screen_arrow.gbapal");
|
||||
|
||||
// static const u8 sArrowDown_Gfx[] = INCBIN_U8("graphics/reset_rtc_screen/arrow_down.4bpp");
|
||||
// static const u8 sArrowRight_Gfx[] = INCBIN_U8("graphics/reset_rtc_screen/arrow_right.4bpp");
|
||||
// static const u16 sArrow_Pal[] = INCBIN_U16("graphics/reset_rtc_screen/arrow.gbapal");
|
||||
|
||||
static const struct SpriteFrameImage sPicTable_Arrow[] =
|
||||
{
|
||||
obj_frame_tiles(sResetRtcScreen_DownArrowGfx),
|
||||
obj_frame_tiles(sResetRtcScreen_RightArrowGfx)
|
||||
};
|
||||
|
||||
const struct SpritePalette gSpritePalette_Arrow =
|
||||
{
|
||||
sResetRtcScreen_ArrowPal, PALTAG_ARROW
|
||||
};
|
||||
|
||||
static const union AnimCmd sAnim_Arrow_Down[] =
|
||||
{
|
||||
ANIMCMD_FRAME(0, 30),
|
||||
ANIMCMD_JUMP(0),
|
||||
};
|
||||
|
||||
static const union AnimCmd sAnim_Arrow_Up[] =
|
||||
{
|
||||
ANIMCMD_FRAME(0, 30, .vFlip = TRUE),
|
||||
ANIMCMD_JUMP(0),
|
||||
};
|
||||
|
||||
static const union AnimCmd sAnim_Arrow_Right[] =
|
||||
{
|
||||
ANIMCMD_FRAME(1, 30),
|
||||
ANIMCMD_JUMP(0),
|
||||
};
|
||||
|
||||
enum {
|
||||
ARROW_DOWN,
|
||||
ARROW_UP,
|
||||
ARROW_RIGHT,
|
||||
};
|
||||
|
||||
static const union AnimCmd *const sAnims_Arrow[] =
|
||||
{
|
||||
[ARROW_DOWN] = sAnim_Arrow_Down,
|
||||
[ARROW_UP] = sAnim_Arrow_Up,
|
||||
[ARROW_RIGHT] = sAnim_Arrow_Right,
|
||||
};
|
||||
|
||||
const struct SpriteTemplate gSpriteTemplate_Arrow =
|
||||
{
|
||||
.tileTag = TAG_NONE,
|
||||
.paletteTag = PALTAG_ARROW,
|
||||
.oam = &sOamData_Arrow,
|
||||
.anims = sAnims_Arrow,
|
||||
.images = sPicTable_Arrow,
|
||||
.affineAnims = gDummySpriteAffineAnimTable,
|
||||
.callback = SpriteCallbackDummy,
|
||||
};
|
||||
|
||||
#define sTaskId data[0]
|
||||
#define sState data[1]
|
||||
|
||||
static void SpriteCB_Cursor_UpOrRight(struct Sprite *sprite)
|
||||
{
|
||||
int state = gTasks[sprite->sTaskId].tSelection;
|
||||
if (state != sprite->sState)
|
||||
{
|
||||
sprite->sState = state;
|
||||
switch (state)
|
||||
{
|
||||
case SELECTION_DAYS:
|
||||
sprite->invisible = FALSE;
|
||||
sprite->animNum = ARROW_UP;
|
||||
sprite->animDelayCounter = 0;
|
||||
sprite->x = 53;
|
||||
sprite->y = 68;
|
||||
break;
|
||||
case SELECTION_HOURS:
|
||||
sprite->invisible = FALSE;
|
||||
sprite->animNum = ARROW_UP;
|
||||
sprite->animDelayCounter = 0;
|
||||
sprite->x = 86;
|
||||
sprite->y = 68;
|
||||
break;
|
||||
case SELECTION_MINS:
|
||||
sprite->invisible = FALSE;
|
||||
sprite->animNum = ARROW_UP;
|
||||
sprite->animDelayCounter = 0;
|
||||
sprite->x = 101;
|
||||
sprite->y = 68;
|
||||
break;
|
||||
case SELECTION_SECS:
|
||||
sprite->invisible = FALSE;
|
||||
sprite->animNum = ARROW_UP;
|
||||
sprite->animDelayCounter = 0;
|
||||
sprite->x = 116;
|
||||
sprite->y = 68;
|
||||
break;
|
||||
case SELECTION_CONFIRM:
|
||||
sprite->invisible = FALSE;
|
||||
sprite->animNum = ARROW_RIGHT;
|
||||
sprite->animDelayCounter = 0;
|
||||
sprite->x = 153;
|
||||
sprite->y = 80;
|
||||
break;
|
||||
case SELECTION_NONE:
|
||||
DestroySprite(sprite);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SpriteCB_Cursor_Down(struct Sprite *sprite)
|
||||
{
|
||||
int state = gTasks[sprite->sTaskId].tSelection;
|
||||
if (state != sprite->sState)
|
||||
{
|
||||
sprite->sState = state;
|
||||
switch (state)
|
||||
{
|
||||
case SELECTION_DAYS:
|
||||
sprite->invisible = FALSE;
|
||||
sprite->animNum = ARROW_DOWN;
|
||||
sprite->animDelayCounter = 0;
|
||||
sprite->x = 53;
|
||||
sprite->y = 92;
|
||||
break;
|
||||
case SELECTION_HOURS:
|
||||
sprite->invisible = FALSE;
|
||||
sprite->animNum = ARROW_DOWN;
|
||||
sprite->animDelayCounter = 0;
|
||||
sprite->x = 86;
|
||||
sprite->y = 92;
|
||||
break;
|
||||
case SELECTION_MINS:
|
||||
sprite->invisible = FALSE;
|
||||
sprite->animNum = ARROW_DOWN;
|
||||
sprite->animDelayCounter = 0;
|
||||
sprite->x = 101;
|
||||
sprite->y = 92;
|
||||
break;
|
||||
case SELECTION_SECS:
|
||||
sprite->invisible = FALSE;
|
||||
sprite->animNum = ARROW_DOWN;
|
||||
sprite->animDelayCounter = 0;
|
||||
sprite->x = 116;
|
||||
sprite->y = 92;
|
||||
break;
|
||||
case SELECTION_CONFIRM:
|
||||
// The up arrow is used as a right arrow when Confirm is selected
|
||||
// Hide the down arrow
|
||||
sprite->invisible = TRUE;
|
||||
break;
|
||||
case SELECTION_NONE:
|
||||
DestroySprite(sprite);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CreateCursor(u8 taskId)
|
||||
{
|
||||
u32 spriteId;
|
||||
|
||||
LoadSpritePalette(&gSpritePalette_Arrow);
|
||||
|
||||
spriteId = CreateSpriteAtEnd(&gSpriteTemplate_Arrow, 53, 68, 0);
|
||||
gSprites[spriteId].callback = SpriteCB_Cursor_UpOrRight;
|
||||
gSprites[spriteId].sTaskId = taskId;
|
||||
gSprites[spriteId].sState = -1;
|
||||
|
||||
spriteId = CreateSpriteAtEnd(&gSpriteTemplate_Arrow, 53, 68, 0);
|
||||
gSprites[spriteId].callback = SpriteCB_Cursor_Down;
|
||||
gSprites[spriteId].sTaskId = taskId;
|
||||
gSprites[spriteId].sState = -1;
|
||||
}
|
||||
|
||||
static void FreeCursorPalette(void)
|
||||
{
|
||||
FreeSpritePaletteByTag(gSpritePalette_Arrow.tag);
|
||||
}
|
||||
|
||||
static void HideChooseTimeWindow(u8 windowId)
|
||||
{
|
||||
ClearStdWindowAndFrameToTransparent(windowId, FALSE);
|
||||
RemoveWindow(windowId);
|
||||
ScheduleBgCopyTilemapToVram(0);
|
||||
}
|
||||
|
||||
static void PrintTime(u8 windowId, u8 x, u8 y, u16 days, u8 hours, u8 minutes, u8 seconds)
|
||||
{
|
||||
u8 *dest = gStringVar4;
|
||||
|
||||
// Print days
|
||||
ConvertIntToDecimalStringN(gStringVar1, days, STR_CONV_MODE_RIGHT_ALIGN, 4);
|
||||
dest = StringCopy(dest, gStringVar1);
|
||||
dest = StringCopy(dest, gText_Day);
|
||||
|
||||
// Print hours
|
||||
ConvertIntToDecimalStringN(gStringVar1, hours, STR_CONV_MODE_RIGHT_ALIGN, 3);
|
||||
dest = StringCopy(dest, gStringVar1);
|
||||
dest = StringCopy(dest, gText_Colon3);
|
||||
|
||||
// Print minutes
|
||||
ConvertIntToDecimalStringN(gStringVar1, minutes, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
dest = StringCopy(dest, gStringVar1);
|
||||
dest = StringCopy(dest, gText_Colon3);
|
||||
|
||||
// Print seconds
|
||||
ConvertIntToDecimalStringN(gStringVar1, seconds, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
dest = StringCopy(dest, gStringVar1);
|
||||
|
||||
AddTextPrinterParameterized(windowId, FONT_NORMAL, gStringVar4, x, y, TEXT_SKIP_DRAW, NULL);
|
||||
}
|
||||
|
||||
static void ShowChooseTimeWindow(u8 windowId, u16 days, u8 hours, u8 minutes, u8 seconds)
|
||||
{
|
||||
DrawStdFrameWithCustomTileAndPalette(windowId, FALSE, 0x214, 0xE);
|
||||
PrintTime(windowId, 0, 1, days, hours, minutes, seconds);
|
||||
AddTextPrinterParameterized(windowId, FONT_NORMAL, gText_Confirm2, 126, 1, 0, NULL);
|
||||
ScheduleBgCopyTilemapToVram(0);
|
||||
}
|
||||
|
||||
static bool32 MoveTimeUpDown(s16 *val, int minVal, int maxVal, u16 keys)
|
||||
{
|
||||
if (keys & DPAD_DOWN)
|
||||
{
|
||||
*val -= 1;
|
||||
if (*val < minVal)
|
||||
*val = maxVal;
|
||||
}
|
||||
else if (keys & DPAD_UP)
|
||||
{
|
||||
*val += 1;
|
||||
if (*val > maxVal)
|
||||
*val = minVal;
|
||||
}
|
||||
else if (keys & DPAD_LEFT)
|
||||
{
|
||||
*val -= 10;
|
||||
if (*val < minVal)
|
||||
*val = maxVal;
|
||||
}
|
||||
else if (keys & DPAD_RIGHT)
|
||||
{
|
||||
*val += 10;
|
||||
if (*val > maxVal)
|
||||
*val = minVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void Task_ResetRtc_SetFinished(u8 taskId)
|
||||
{
|
||||
gTasks[taskId].tFinished = TRUE;
|
||||
}
|
||||
|
||||
static void Task_ResetRtc_Exit(u8 taskId)
|
||||
{
|
||||
s16 *data = gTasks[taskId].data;
|
||||
|
||||
HideChooseTimeWindow(tWindowId);
|
||||
FreeCursorPalette();
|
||||
gTasks[taskId].func = Task_ResetRtc_SetFinished;
|
||||
}
|
||||
|
||||
static void Task_ResetRtc_HandleInput(u8 taskId)
|
||||
{
|
||||
s16 *data = gTasks[taskId].data;
|
||||
u8 selection = tSelection;
|
||||
const struct ResetRtcInputMap *selectionInfo = &sInputMap[selection - 1];
|
||||
|
||||
if (JOY_NEW(B_BUTTON))
|
||||
{
|
||||
gTasks[taskId].func = Task_ResetRtc_Exit;
|
||||
tSetTime = FALSE;
|
||||
tSelection = SELECTION_NONE;
|
||||
PlaySE(SE_SELECT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (JOY_NEW(DPAD_RIGHT))
|
||||
{
|
||||
if (selectionInfo->right)
|
||||
{
|
||||
tSelection = selectionInfo->right;
|
||||
PlaySE(SE_SELECT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (JOY_NEW(DPAD_LEFT))
|
||||
{
|
||||
if (selectionInfo->left)
|
||||
{
|
||||
tSelection = selectionInfo->left;
|
||||
PlaySE(SE_SELECT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (selection == SELECTION_CONFIRM)
|
||||
{
|
||||
if (JOY_NEW(A_BUTTON))
|
||||
{
|
||||
gLocalTime.days = tDays;
|
||||
gLocalTime.hours = tHours;
|
||||
gLocalTime.minutes = tMinutes;
|
||||
gLocalTime.seconds = tSeconds;
|
||||
PlaySE(SE_SELECT);
|
||||
gTasks[taskId].func = Task_ResetRtc_Exit;
|
||||
tSetTime = TRUE;
|
||||
tSelection = SELECTION_NONE;
|
||||
}
|
||||
}
|
||||
else if (MoveTimeUpDown(&data[selectionInfo->dataIndex], selectionInfo->minVal, selectionInfo->maxVal, JOY_REPT(DPAD_UP | DPAD_DOWN)))
|
||||
{
|
||||
PlaySE(SE_SELECT);
|
||||
PrintTime(tWindowId, 0, 1, tDays, tHours, tMinutes, tSeconds);
|
||||
CopyWindowToVram(tWindowId, COPYWIN_GFX);
|
||||
}
|
||||
}
|
||||
|
||||
static void Task_ResetRtc_Init(u8 taskId)
|
||||
{
|
||||
s16 *data = gTasks[taskId].data;
|
||||
tFinished = FALSE;
|
||||
tDays = gLocalTime.days;
|
||||
tHours = gLocalTime.hours;
|
||||
tMinutes = gLocalTime.minutes;
|
||||
tSeconds = gLocalTime.seconds;
|
||||
tWindowId = AddWindow(&sInputTimeWindow);
|
||||
ShowChooseTimeWindow(tWindowId, tDays, tHours, tMinutes, tSeconds);
|
||||
CreateCursor(taskId);
|
||||
tSelection = SELECTION_HOURS;
|
||||
gTasks[taskId].func = Task_ResetRtc_HandleInput;
|
||||
}
|
||||
|
||||
void CB2_InitResetRtcScreen(void)
|
||||
{
|
||||
#ifdef FIRERED
|
||||
FillPalette(RGB(30, 18, 11), 0, PLTT_SIZE);
|
||||
#endif
|
||||
#ifdef LEAFGREEN
|
||||
FillPalette(RGB(23, 28, 11), 0, PLTT_SIZE);
|
||||
#endif
|
||||
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
|
||||
|
||||
SetGpuReg(REG_OFFSET_DISPCNT, 0);
|
||||
SetGpuReg(REG_OFFSET_BLDY, 0);
|
||||
ResetBgsAndClearDma3BusyFlags(FALSE);
|
||||
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);
|
||||
DeactivateAllTextPrinters();
|
||||
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
|
||||
ShowBg(0);
|
||||
|
||||
DmaClear16(3, PLTT, PLTT_SIZE);
|
||||
DmaFillLarge16(3, 0, (u8 *)VRAM, VRAM_SIZE, 0x1000);
|
||||
ResetOamRange(0, 128);
|
||||
LoadOam();
|
||||
ScanlineEffect_Stop();
|
||||
ScanlineEffect_Clear();
|
||||
ResetSpriteData();
|
||||
ResetTasks();
|
||||
ResetPaletteFade();
|
||||
InitResetRtcScreenBgAndWindows();
|
||||
SetVBlankCallback(VBlankCB);
|
||||
SetMainCallback2(CB2_ResetRtcScreen);
|
||||
CreateTask(Task_ResetRtcScreen, 80);
|
||||
}
|
||||
|
||||
static void InitResetRtcScreenBgAndWindows(void)
|
||||
{
|
||||
ClearScheduledBgCopiesToVram();
|
||||
ResetBgsAndClearDma3BusyFlags(0);
|
||||
InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates));
|
||||
ScheduleBgCopyTilemapToVram(0);
|
||||
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
|
||||
ShowBg(0);
|
||||
InitWindows(sWindowTemplates);
|
||||
DeactivateAllTextPrinters();
|
||||
LoadStdWindowFrameGfx();
|
||||
}
|
||||
|
||||
static void CB2_ResetRtcScreen(void)
|
||||
{
|
||||
RunTasks();
|
||||
AnimateSprites();
|
||||
BuildOamBuffer();
|
||||
DoScheduledBgTilemapCopiesToVram();
|
||||
UpdatePaletteFade();
|
||||
}
|
||||
|
||||
static void VBlankCB(void)
|
||||
{
|
||||
ProcessSpriteCopyRequests();
|
||||
LoadOam();
|
||||
TransferPlttBuffer();
|
||||
}
|
||||
|
||||
static void ShowMessage(const u8 *str)
|
||||
{
|
||||
DrawDialogFrameWithCustomTileAndPalette(WIN_MSG, FALSE, 0x200, 0xF);
|
||||
AddTextPrinterParameterized(WIN_MSG, FONT_NORMAL, str, 0, 1, 0, NULL);
|
||||
ScheduleBgCopyTilemapToVram(0);
|
||||
}
|
||||
|
||||
#define tState data[0]
|
||||
|
||||
static void Task_ShowResetRtcPrompt(u8 taskId)
|
||||
{
|
||||
s16 *data = gTasks[taskId].data;
|
||||
|
||||
switch (tState)
|
||||
{
|
||||
case 0:
|
||||
DrawStdFrameWithCustomTileAndPalette(WIN_TIME, FALSE, 0x214, 0xE);
|
||||
|
||||
AddTextPrinterParameterized(WIN_TIME, FONT_NORMAL, gText_PresentTime, 0, 1, TEXT_SKIP_DRAW, 0);
|
||||
PrintTime(
|
||||
WIN_TIME,
|
||||
0,
|
||||
17,
|
||||
gLocalTime.days,
|
||||
gLocalTime.hours,
|
||||
gLocalTime.minutes,
|
||||
gLocalTime.seconds);
|
||||
|
||||
AddTextPrinterParameterized(WIN_TIME, FONT_NORMAL, gText_PreviousTime, 0, 33, TEXT_SKIP_DRAW, 0);
|
||||
PrintTime(
|
||||
WIN_TIME,
|
||||
0,
|
||||
49,
|
||||
gSaveBlock2Ptr->lastBerryTreeUpdate.days,
|
||||
gSaveBlock2Ptr->lastBerryTreeUpdate.hours,
|
||||
gSaveBlock2Ptr->lastBerryTreeUpdate.minutes,
|
||||
gSaveBlock2Ptr->lastBerryTreeUpdate.seconds);
|
||||
|
||||
ShowMessage(gText_ResetRTCConfirmCancel);
|
||||
CopyWindowToVram(WIN_TIME, COPYWIN_GFX);
|
||||
ScheduleBgCopyTilemapToVram(0);
|
||||
tState++;
|
||||
case 1:
|
||||
if (JOY_NEW(B_BUTTON))
|
||||
{
|
||||
// Cancel, exit without resetting RTC
|
||||
DestroyTask(taskId);
|
||||
DoSoftReset();
|
||||
}
|
||||
else if (JOY_NEW(A_BUTTON))
|
||||
{
|
||||
// Confirm
|
||||
PlaySE(SE_SELECT);
|
||||
DestroyTask(taskId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#undef tState
|
||||
|
||||
// Task states for Task_ResetRtcScreen
|
||||
enum {
|
||||
MAINSTATE_FADE_IN,
|
||||
MAINSTATE_CHECK_SAVE,
|
||||
MAINSTATE_START_SET_TIME,
|
||||
MAINSTATE_WAIT_SET_TIME,
|
||||
MAINSTATE_SAVE,
|
||||
MAINSTATE_WAIT_EXIT,
|
||||
MAINSTATE_EXIT,
|
||||
};
|
||||
|
||||
#define tState data[0]
|
||||
#define tSubTaskId data[1]
|
||||
|
||||
static void Task_ResetRtcScreen(u8 taskId)
|
||||
{
|
||||
s16 *data = gTasks[taskId].data;
|
||||
|
||||
switch (tState)
|
||||
{
|
||||
case MAINSTATE_FADE_IN:
|
||||
BeginNormalPaletteFade(PALETTES_ALL, 1, 0x10, 0, RGB_WHITEALPHA);
|
||||
tState = MAINSTATE_CHECK_SAVE;
|
||||
break;
|
||||
case MAINSTATE_CHECK_SAVE:
|
||||
if (!gPaletteFade.active)
|
||||
{
|
||||
if (gSaveFileStatus == SAVE_STATUS_EMPTY
|
||||
|| gSaveFileStatus == SAVE_STATUS_INVALID)
|
||||
{
|
||||
ShowMessage(gText_NoSaveFileCantSetTime);
|
||||
tState = MAINSTATE_WAIT_EXIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtcCalcLocalTime();
|
||||
tSubTaskId = CreateTask(Task_ShowResetRtcPrompt, 80);
|
||||
tState = MAINSTATE_START_SET_TIME;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MAINSTATE_START_SET_TIME:
|
||||
// Wait for A or B press on prompt first
|
||||
if (gTasks[tSubTaskId].isActive != TRUE)
|
||||
{
|
||||
ClearStdWindowAndFrameToTransparent(WIN_TIME, FALSE);
|
||||
ShowMessage(gText_PleaseResetTime);
|
||||
gLocalTime = gSaveBlock2Ptr->lastBerryTreeUpdate;
|
||||
tSubTaskId = CreateTask(Task_ResetRtc_Init, 80);
|
||||
tState = MAINSTATE_WAIT_SET_TIME;
|
||||
}
|
||||
break;
|
||||
case MAINSTATE_WAIT_SET_TIME:
|
||||
if (gTasks[tSubTaskId].tFinished)
|
||||
{
|
||||
if (!gTasks[tSubTaskId].tSetTime)
|
||||
{
|
||||
// Exited without setting time, return to "Please reset time"
|
||||
DestroyTask(tSubTaskId);
|
||||
tState = MAINSTATE_START_SET_TIME;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Time has been chosen, reset rtc and save
|
||||
DestroyTask(tSubTaskId);
|
||||
RtcReset();
|
||||
RtcCalcLocalTimeOffset(
|
||||
gLocalTime.days,
|
||||
gLocalTime.hours,
|
||||
gLocalTime.minutes,
|
||||
gLocalTime.seconds);
|
||||
gSaveBlock2Ptr->lastBerryTreeUpdate = gLocalTime;
|
||||
VarSet(VAR_DAYS, gLocalTime.days);
|
||||
DisableResetRTC();
|
||||
ShowMessage(gText_ClockHasBeenReset);
|
||||
tState = MAINSTATE_SAVE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MAINSTATE_SAVE:
|
||||
if (TrySavingData(SAVE_NORMAL) == SAVE_STATUS_OK)
|
||||
{
|
||||
ShowMessage(gText_SaveCompleted);
|
||||
PlaySE(SE_DING_DONG);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMessage(gText_SaveFailed);
|
||||
PlaySE(SE_BOO);
|
||||
}
|
||||
tState = MAINSTATE_WAIT_EXIT;
|
||||
// fallthrough
|
||||
case MAINSTATE_WAIT_EXIT:
|
||||
if (JOY_NEW(A_BUTTON))
|
||||
{
|
||||
BeginNormalPaletteFade(PALETTES_ALL, 1, 0, 0x10, RGB_WHITEALPHA);
|
||||
tState = MAINSTATE_EXIT;
|
||||
// fallthrough
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MAINSTATE_EXIT:
|
||||
if (!gPaletteFade.active)
|
||||
{
|
||||
DestroyTask(taskId);
|
||||
FreeAllWindowBuffers();
|
||||
DoSoftReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
366
src/rtc.c
Normal file
366
src/rtc.c
Normal file
@@ -0,0 +1,366 @@
|
||||
#include "global.h"
|
||||
#include "rtc.h"
|
||||
#include "string_util.h"
|
||||
#include "text.h"
|
||||
|
||||
// iwram bss
|
||||
static u16 sErrorStatus;
|
||||
static struct SiiRtcInfo sRtc;
|
||||
static u8 sProbeResult;
|
||||
static u16 sSavedIme;
|
||||
|
||||
// iwram common
|
||||
struct Time gLocalTime;
|
||||
|
||||
// const rom
|
||||
|
||||
static const struct SiiRtcInfo sRtcDummy = {0, MONTH_JAN, 1}; // 2000 Jan 1
|
||||
|
||||
static const s32 sNumDaysInMonths[12] =
|
||||
{
|
||||
31,
|
||||
28,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
};
|
||||
|
||||
void RtcDisableInterrupts(void)
|
||||
{
|
||||
sSavedIme = REG_IME;
|
||||
REG_IME = 0;
|
||||
}
|
||||
|
||||
void RtcRestoreInterrupts(void)
|
||||
{
|
||||
REG_IME = sSavedIme;
|
||||
}
|
||||
|
||||
u32 ConvertBcdToBinary(u8 bcd)
|
||||
{
|
||||
if (bcd > 0x9F)
|
||||
return 0xFF;
|
||||
|
||||
if ((bcd & 0xF) <= 9)
|
||||
return (10 * ((bcd >> 4) & 0xF)) + (bcd & 0xF);
|
||||
else
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
bool8 IsLeapYear(u32 year)
|
||||
{
|
||||
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
u16 ConvertDateToDayCount(u8 year, u8 month, u8 day)
|
||||
{
|
||||
s32 i;
|
||||
u16 dayCount = 0;
|
||||
|
||||
for (i = year - 1; i >= 0; i--)
|
||||
{
|
||||
dayCount += 365;
|
||||
|
||||
if (IsLeapYear(i) == TRUE)
|
||||
dayCount++;
|
||||
}
|
||||
|
||||
for (i = 0; i < month - 1; i++)
|
||||
dayCount += sNumDaysInMonths[i];
|
||||
|
||||
if (month > MONTH_FEB && IsLeapYear(year) == TRUE)
|
||||
dayCount++;
|
||||
|
||||
dayCount += day;
|
||||
|
||||
return dayCount;
|
||||
}
|
||||
|
||||
u16 RtcGetDayCount(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
u8 year = ConvertBcdToBinary(rtc->year);
|
||||
u8 month = ConvertBcdToBinary(rtc->month);
|
||||
u8 day = ConvertBcdToBinary(rtc->day);
|
||||
return ConvertDateToDayCount(year, month, day);
|
||||
}
|
||||
|
||||
void RtcInit(void)
|
||||
{
|
||||
sErrorStatus = 0;
|
||||
|
||||
RtcDisableInterrupts();
|
||||
SiiRtcUnprotect();
|
||||
sProbeResult = SiiRtcProbe();
|
||||
RtcRestoreInterrupts();
|
||||
|
||||
if ((sProbeResult & 0xF) != 1)
|
||||
{
|
||||
sErrorStatus = RTC_INIT_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sProbeResult & 0xF0)
|
||||
sErrorStatus = RTC_INIT_WARNING;
|
||||
else
|
||||
sErrorStatus = 0;
|
||||
|
||||
RtcGetRawInfo(&sRtc);
|
||||
sErrorStatus = RtcCheckInfo(&sRtc);
|
||||
}
|
||||
|
||||
u16 RtcGetErrorStatus(void)
|
||||
{
|
||||
return sErrorStatus;
|
||||
}
|
||||
|
||||
void RtcGetInfo(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
if (sErrorStatus & RTC_ERR_FLAG_MASK)
|
||||
*rtc = sRtcDummy;
|
||||
else
|
||||
RtcGetRawInfo(rtc);
|
||||
}
|
||||
|
||||
void RtcGetDateTime(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
RtcDisableInterrupts();
|
||||
SiiRtcGetDateTime(rtc);
|
||||
RtcRestoreInterrupts();
|
||||
}
|
||||
|
||||
void RtcGetStatus(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
RtcDisableInterrupts();
|
||||
SiiRtcGetStatus(rtc);
|
||||
RtcRestoreInterrupts();
|
||||
}
|
||||
|
||||
void RtcGetRawInfo(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
RtcGetStatus(rtc);
|
||||
RtcGetDateTime(rtc);
|
||||
}
|
||||
|
||||
u16 RtcCheckInfo(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
u16 errorFlags = 0;
|
||||
s32 year;
|
||||
s32 month;
|
||||
s32 value;
|
||||
|
||||
if (rtc->status & SIIRTCINFO_POWER)
|
||||
errorFlags |= RTC_ERR_POWER_FAILURE;
|
||||
|
||||
if (!(rtc->status & SIIRTCINFO_24HOUR))
|
||||
errorFlags |= RTC_ERR_12HOUR_CLOCK;
|
||||
|
||||
year = ConvertBcdToBinary(rtc->year);
|
||||
|
||||
if (year == 0xFF)
|
||||
errorFlags |= RTC_ERR_INVALID_YEAR;
|
||||
|
||||
month = ConvertBcdToBinary(rtc->month);
|
||||
|
||||
if (month == 0xFF || month == 0 || month > 12)
|
||||
errorFlags |= RTC_ERR_INVALID_MONTH;
|
||||
|
||||
value = ConvertBcdToBinary(rtc->day);
|
||||
|
||||
if (value == 0xFF)
|
||||
errorFlags |= RTC_ERR_INVALID_DAY;
|
||||
|
||||
if (month == MONTH_FEB)
|
||||
{
|
||||
if (value > IsLeapYear(year) + sNumDaysInMonths[month - 1])
|
||||
errorFlags |= RTC_ERR_INVALID_DAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value > sNumDaysInMonths[month - 1])
|
||||
errorFlags |= RTC_ERR_INVALID_DAY;
|
||||
}
|
||||
|
||||
value = ConvertBcdToBinary(rtc->hour);
|
||||
|
||||
if (value > 24)
|
||||
errorFlags |= RTC_ERR_INVALID_HOUR;
|
||||
|
||||
value = ConvertBcdToBinary(rtc->minute);
|
||||
|
||||
if (value > 60)
|
||||
errorFlags |= RTC_ERR_INVALID_MINUTE;
|
||||
|
||||
value = ConvertBcdToBinary(rtc->second);
|
||||
|
||||
if (value > 60)
|
||||
errorFlags |= RTC_ERR_INVALID_SECOND;
|
||||
|
||||
return errorFlags;
|
||||
}
|
||||
|
||||
void RtcReset(void)
|
||||
{
|
||||
RtcDisableInterrupts();
|
||||
SiiRtcReset();
|
||||
RtcRestoreInterrupts();
|
||||
}
|
||||
|
||||
void FormatDecimalTime(u8 *dest, s32 hour, s32 minute, s32 second)
|
||||
{
|
||||
dest = ConvertIntToDecimalStringN(dest, hour, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest++ = CHAR_COLON;
|
||||
dest = ConvertIntToDecimalStringN(dest, minute, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest++ = CHAR_COLON;
|
||||
dest = ConvertIntToDecimalStringN(dest, second, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest = EOS;
|
||||
}
|
||||
|
||||
void FormatHexTime(u8 *dest, s32 hour, s32 minute, s32 second)
|
||||
{
|
||||
dest = ConvertIntToHexStringN(dest, hour, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest++ = CHAR_COLON;
|
||||
dest = ConvertIntToHexStringN(dest, minute, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest++ = CHAR_COLON;
|
||||
dest = ConvertIntToHexStringN(dest, second, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest = EOS;
|
||||
}
|
||||
|
||||
void FormatHexRtcTime(u8 *dest)
|
||||
{
|
||||
FormatHexTime(dest, sRtc.hour, sRtc.minute, sRtc.second);
|
||||
}
|
||||
|
||||
void FormatDecimalDate(u8 *dest, s32 year, s32 month, s32 day)
|
||||
{
|
||||
dest = ConvertIntToDecimalStringN(dest, year, STR_CONV_MODE_LEADING_ZEROS, 4);
|
||||
*dest++ = CHAR_HYPHEN;
|
||||
dest = ConvertIntToDecimalStringN(dest, month, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest++ = CHAR_HYPHEN;
|
||||
dest = ConvertIntToDecimalStringN(dest, day, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest = EOS;
|
||||
}
|
||||
|
||||
void FormatHexDate(u8 *dest, s32 year, s32 month, s32 day)
|
||||
{
|
||||
dest = ConvertIntToHexStringN(dest, year, STR_CONV_MODE_LEADING_ZEROS, 4);
|
||||
*dest++ = CHAR_HYPHEN;
|
||||
dest = ConvertIntToHexStringN(dest, month, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest++ = CHAR_HYPHEN;
|
||||
dest = ConvertIntToHexStringN(dest, day, STR_CONV_MODE_LEADING_ZEROS, 2);
|
||||
*dest = EOS;
|
||||
}
|
||||
|
||||
void RtcCalcTimeDifference(struct SiiRtcInfo *rtc, struct Time *result, struct Time *t)
|
||||
{
|
||||
u16 days = RtcGetDayCount(rtc);
|
||||
result->seconds = ConvertBcdToBinary(rtc->second) - t->seconds;
|
||||
result->minutes = ConvertBcdToBinary(rtc->minute) - t->minutes;
|
||||
result->hours = ConvertBcdToBinary(rtc->hour) - t->hours;
|
||||
result->days = days - t->days;
|
||||
|
||||
if (result->seconds < 0)
|
||||
{
|
||||
result->seconds += 60;
|
||||
--result->minutes;
|
||||
}
|
||||
|
||||
if (result->minutes < 0)
|
||||
{
|
||||
result->minutes += 60;
|
||||
--result->hours;
|
||||
}
|
||||
|
||||
if (result->hours < 0)
|
||||
{
|
||||
result->hours += 24;
|
||||
--result->days;
|
||||
}
|
||||
}
|
||||
|
||||
bool8 IsBetweenHours(s32 hours, s32 begin, s32 end)
|
||||
{
|
||||
if (end < begin)
|
||||
return hours >= begin || hours < end;
|
||||
else
|
||||
return hours >= begin && hours < end;
|
||||
}
|
||||
|
||||
u8 GetTimeOfDay(void)
|
||||
{
|
||||
RtcCalcLocalTime();
|
||||
if (IsBetweenHours(gLocalTime.hours, MORNING_HOUR_BEGIN, MORNING_HOUR_END))
|
||||
return TIME_MORNING;
|
||||
else if (IsBetweenHours(gLocalTime.hours, EVENING_HOUR_BEGIN, EVENING_HOUR_END))
|
||||
return TIME_EVENING;
|
||||
else if (IsBetweenHours(gLocalTime.hours, NIGHT_HOUR_BEGIN, NIGHT_HOUR_END))
|
||||
return TIME_NIGHT;
|
||||
return TIME_DAY;
|
||||
}
|
||||
|
||||
void RtcCalcLocalTime(void)
|
||||
{
|
||||
RtcGetInfo(&sRtc);
|
||||
RtcCalcTimeDifference(&sRtc, &gLocalTime, &gSaveBlock2Ptr->localTimeOffset);
|
||||
}
|
||||
|
||||
void RtcInitLocalTimeOffset(s32 hour, s32 minute)
|
||||
{
|
||||
RtcCalcLocalTimeOffset(0, hour, minute, 0);
|
||||
}
|
||||
|
||||
void RtcCalcLocalTimeOffset(s32 days, s32 hours, s32 minutes, s32 seconds)
|
||||
{
|
||||
gLocalTime.days = days;
|
||||
gLocalTime.hours = hours;
|
||||
gLocalTime.minutes = minutes;
|
||||
gLocalTime.seconds = seconds;
|
||||
RtcGetInfo(&sRtc);
|
||||
RtcCalcTimeDifference(&sRtc, &gSaveBlock2Ptr->localTimeOffset, &gLocalTime);
|
||||
}
|
||||
|
||||
void CalcTimeDifference(struct Time *result, struct Time *t1, struct Time *t2)
|
||||
{
|
||||
result->seconds = t2->seconds - t1->seconds;
|
||||
result->minutes = t2->minutes - t1->minutes;
|
||||
result->hours = t2->hours - t1->hours;
|
||||
result->days = t2->days - t1->days;
|
||||
|
||||
if (result->seconds < 0)
|
||||
{
|
||||
result->seconds += 60;
|
||||
--result->minutes;
|
||||
}
|
||||
|
||||
if (result->minutes < 0)
|
||||
{
|
||||
result->minutes += 60;
|
||||
--result->hours;
|
||||
}
|
||||
|
||||
if (result->hours < 0)
|
||||
{
|
||||
result->hours += 24;
|
||||
--result->days;
|
||||
}
|
||||
}
|
||||
|
||||
u32 RtcGetMinuteCount(void)
|
||||
{
|
||||
RtcGetInfo(&sRtc);
|
||||
return (24 * 60) * RtcGetDayCount(&sRtc) + 60 * sRtc.hour + sRtc.minute;
|
||||
}
|
||||
|
||||
u32 RtcGetLocalDayCount(void)
|
||||
{
|
||||
return RtcGetDayCount(&sRtc);
|
||||
}
|
||||
23
src/scrcmd.c
23
src/scrcmd.c
@@ -1,5 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "clock.h"
|
||||
#include "rtc.h"
|
||||
#include "script.h"
|
||||
#include "mystery_event_script.h"
|
||||
#include "event_data.h"
|
||||
@@ -656,28 +658,25 @@ bool8 ScrCmd_delay(struct ScriptContext * ctx)
|
||||
|
||||
bool8 ScrCmd_initclock(struct ScriptContext * ctx)
|
||||
{
|
||||
// u8 hour = VarGet(ScriptReadHalfword(ctx));
|
||||
// u8 minute = VarGet(ScriptReadHalfword(ctx));
|
||||
//
|
||||
// RtcInitLocalTimeOffset(hour, minute);
|
||||
u8 hour = VarGet(ScriptReadHalfword(ctx));
|
||||
u8 minute = VarGet(ScriptReadHalfword(ctx));
|
||||
|
||||
RtcInitLocalTimeOffset(hour, minute);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool8 ScrCmd_dotimebasedevents(struct ScriptContext * ctx)
|
||||
{
|
||||
// DoTimeBasedEvents();
|
||||
DoTimeBasedEvents();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool8 ScrCmd_gettime(struct ScriptContext * ctx)
|
||||
{
|
||||
// RtcCalcLocalTime();
|
||||
// gSpecialVar_0x8000 = gLocalTime.hours;
|
||||
// gSpecialVar_0x8001 = gLocalTime.minutes;
|
||||
// gSpecialVar_0x8002 = gLocalTime.seconds;
|
||||
gSpecialVar_0x8000 = 0;
|
||||
gSpecialVar_0x8001 = 0;
|
||||
gSpecialVar_0x8002 = 0;
|
||||
RtcCalcLocalTime();
|
||||
gSpecialVar_0x8000 = gLocalTime.hours;
|
||||
gSpecialVar_0x8001 = gLocalTime.minutes;
|
||||
gSpecialVar_0x8002 = gLocalTime.seconds;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
445
src/siirtc.c
Normal file
445
src/siirtc.c
Normal file
@@ -0,0 +1,445 @@
|
||||
// Ruby/Sapphire/Emerald cartridges contain a Seiko Instruments Inc. (SII)
|
||||
// S-3511A real-time clock (RTC). This library ("SIIRTC_V001") is for
|
||||
// communicating with the RTC.
|
||||
|
||||
#include "gba/gba.h"
|
||||
#include "siirtc.h"
|
||||
|
||||
#define STATUS_INTFE 0x02 // frequency interrupt enable
|
||||
#define STATUS_INTME 0x08 // per-minute interrupt enable
|
||||
#define STATUS_INTAE 0x20 // alarm interrupt enable
|
||||
#define STATUS_24HOUR 0x40 // 0: 12-hour mode, 1: 24-hour mode
|
||||
#define STATUS_POWER 0x80 // power on or power failure occurred
|
||||
|
||||
#define TEST_MODE 0x80 // flag in the "second" byte
|
||||
|
||||
#define ALARM_AM 0x00
|
||||
#define ALARM_PM 0x80
|
||||
|
||||
#define OFFSET_YEAR offsetof(struct SiiRtcInfo, year)
|
||||
#define OFFSET_MONTH offsetof(struct SiiRtcInfo, month)
|
||||
#define OFFSET_DAY offsetof(struct SiiRtcInfo, day)
|
||||
#define OFFSET_DAY_OF_WEEK offsetof(struct SiiRtcInfo, dayOfWeek)
|
||||
#define OFFSET_HOUR offsetof(struct SiiRtcInfo, hour)
|
||||
#define OFFSET_MINUTE offsetof(struct SiiRtcInfo, minute)
|
||||
#define OFFSET_SECOND offsetof(struct SiiRtcInfo, second)
|
||||
#define OFFSET_STATUS offsetof(struct SiiRtcInfo, status)
|
||||
#define OFFSET_ALARM_HOUR offsetof(struct SiiRtcInfo, alarmHour)
|
||||
#define OFFSET_ALARM_MINUTE offsetof(struct SiiRtcInfo, alarmMinute)
|
||||
|
||||
#define INFO_BUF(info, index) (*((u8 *)(info) + (index)))
|
||||
|
||||
#define DATETIME_BUF(info, index) INFO_BUF(info, OFFSET_YEAR + index)
|
||||
#define DATETIME_BUF_LEN (OFFSET_SECOND - OFFSET_YEAR + 1)
|
||||
|
||||
#define TIME_BUF(info, index) INFO_BUF(info, OFFSET_HOUR + index)
|
||||
#define TIME_BUF_LEN (OFFSET_SECOND - OFFSET_HOUR + 1)
|
||||
|
||||
#define WR 0 // command for writing data
|
||||
#define RD 1 // command for reading data
|
||||
|
||||
#define CMD(n) (0x60 | (n << 1))
|
||||
|
||||
#define CMD_RESET CMD(0)
|
||||
#define CMD_STATUS CMD(1)
|
||||
#define CMD_DATETIME CMD(2)
|
||||
#define CMD_TIME CMD(3)
|
||||
#define CMD_ALARM CMD(4)
|
||||
|
||||
#define SCK_HI 1
|
||||
#define SIO_HI 2
|
||||
#define CS_HI 4
|
||||
|
||||
#define DIR_0_IN 0
|
||||
#define DIR_0_OUT 1
|
||||
#define DIR_1_IN 0
|
||||
#define DIR_1_OUT 2
|
||||
#define DIR_2_IN 0
|
||||
#define DIR_2_OUT 4
|
||||
#define DIR_ALL_IN (DIR_0_IN | DIR_1_IN | DIR_2_IN)
|
||||
#define DIR_ALL_OUT (DIR_0_OUT | DIR_1_OUT | DIR_2_OUT)
|
||||
|
||||
#define GPIO_PORT_DATA (*(vu16 *)0x80000C4)
|
||||
#define GPIO_PORT_DIRECTION (*(vu16 *)0x80000C6)
|
||||
#define GPIO_PORT_READ_ENABLE (*(vu16 *)0x80000C8)
|
||||
|
||||
extern vu16 GPIOPortDirection;
|
||||
|
||||
static u16 sDummy; // unused variable
|
||||
static bool8 sLocked;
|
||||
|
||||
static int WriteCommand(u8 value);
|
||||
static int WriteData(u8 value);
|
||||
static u8 ReadData();
|
||||
static void EnableGpioPortRead();
|
||||
static void DisableGpioPortRead();
|
||||
|
||||
static const char AgbLibRtcVersion[] = "SIIRTC_V001";
|
||||
|
||||
void SiiRtcUnprotect(void)
|
||||
{
|
||||
EnableGpioPortRead();
|
||||
sLocked = FALSE;
|
||||
}
|
||||
|
||||
void SiiRtcProtect(void)
|
||||
{
|
||||
DisableGpioPortRead();
|
||||
sLocked = TRUE;
|
||||
}
|
||||
|
||||
u8 SiiRtcProbe(void)
|
||||
{
|
||||
u8 errorCode;
|
||||
struct SiiRtcInfo rtc;
|
||||
|
||||
if (!SiiRtcGetStatus(&rtc))
|
||||
return 0;
|
||||
|
||||
errorCode = 0;
|
||||
|
||||
if ((rtc.status & (SIIRTCINFO_POWER | SIIRTCINFO_24HOUR)) == SIIRTCINFO_POWER
|
||||
|| (rtc.status & (SIIRTCINFO_POWER | SIIRTCINFO_24HOUR)) == 0)
|
||||
{
|
||||
// The RTC is in 12-hour mode. Reset it and switch to 24-hour mode.
|
||||
|
||||
// Note that the conditions are redundant and equivalent to simply
|
||||
// "(rtc.status & SIIRTCINFO_24HOUR) == 0". It's possible that this
|
||||
// was also intended to handle resetting the clock after power failure
|
||||
// but a mistake was made.
|
||||
|
||||
if (!SiiRtcReset())
|
||||
return 0;
|
||||
|
||||
errorCode++;
|
||||
}
|
||||
|
||||
SiiRtcGetTime(&rtc);
|
||||
|
||||
if (rtc.second & TEST_MODE)
|
||||
{
|
||||
// The RTC is in test mode. Reset it to leave test mode.
|
||||
|
||||
if (!SiiRtcReset())
|
||||
return (errorCode << 4) & 0xF0;
|
||||
|
||||
errorCode++;
|
||||
}
|
||||
|
||||
return (errorCode << 4) | 1;
|
||||
}
|
||||
|
||||
bool8 SiiRtcReset(void)
|
||||
{
|
||||
u8 result;
|
||||
struct SiiRtcInfo rtc;
|
||||
|
||||
if (sLocked == TRUE)
|
||||
return FALSE;
|
||||
|
||||
sLocked = TRUE;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI | CS_HI;
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_ALL_OUT;
|
||||
|
||||
WriteCommand(CMD_RESET | WR);
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
|
||||
sLocked = FALSE;
|
||||
|
||||
rtc.status = SIIRTCINFO_24HOUR;
|
||||
|
||||
result = SiiRtcSetStatus(&rtc);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool8 SiiRtcGetStatus(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
u8 statusData;
|
||||
|
||||
if (sLocked == TRUE)
|
||||
return FALSE;
|
||||
|
||||
sLocked = TRUE;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI | CS_HI;
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_ALL_OUT;
|
||||
|
||||
WriteCommand(CMD_STATUS | RD);
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_0_OUT | DIR_1_IN | DIR_2_OUT;
|
||||
|
||||
statusData = ReadData();
|
||||
|
||||
rtc->status = (statusData & (STATUS_POWER | STATUS_24HOUR))
|
||||
| ((statusData & STATUS_INTAE) >> 3)
|
||||
| ((statusData & STATUS_INTME) >> 2)
|
||||
| ((statusData & STATUS_INTFE) >> 1);
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
|
||||
sLocked = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 SiiRtcSetStatus(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
u8 statusData;
|
||||
|
||||
if (sLocked == TRUE)
|
||||
return FALSE;
|
||||
|
||||
sLocked = TRUE;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI | CS_HI;
|
||||
|
||||
statusData = STATUS_24HOUR
|
||||
| ((rtc->status & SIIRTCINFO_INTAE) << 3)
|
||||
| ((rtc->status & SIIRTCINFO_INTME) << 2)
|
||||
| ((rtc->status & SIIRTCINFO_INTFE) << 1);
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_ALL_OUT;
|
||||
|
||||
WriteCommand(CMD_STATUS | WR);
|
||||
|
||||
WriteData(statusData);
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
|
||||
sLocked = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 SiiRtcGetDateTime(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (sLocked == TRUE)
|
||||
return FALSE;
|
||||
|
||||
sLocked = TRUE;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI | CS_HI;
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_ALL_OUT;
|
||||
|
||||
WriteCommand(CMD_DATETIME | RD);
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_0_OUT | DIR_1_IN | DIR_2_OUT;
|
||||
|
||||
for (i = 0; i < DATETIME_BUF_LEN; i++)
|
||||
DATETIME_BUF(rtc, i) = ReadData();
|
||||
|
||||
INFO_BUF(rtc, OFFSET_HOUR) &= 0x7F;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
|
||||
sLocked = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 SiiRtcSetDateTime(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (sLocked == TRUE)
|
||||
return FALSE;
|
||||
|
||||
sLocked = TRUE;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI | CS_HI;
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_ALL_OUT;
|
||||
|
||||
WriteCommand(CMD_DATETIME | WR);
|
||||
|
||||
for (i = 0; i < DATETIME_BUF_LEN; i++)
|
||||
WriteData(DATETIME_BUF(rtc, i));
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
|
||||
sLocked = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 SiiRtcGetTime(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (sLocked == TRUE)
|
||||
return FALSE;
|
||||
|
||||
sLocked = TRUE;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI | CS_HI;
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_ALL_OUT;
|
||||
|
||||
WriteCommand(CMD_TIME | RD);
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_0_OUT | DIR_1_IN | DIR_2_OUT;
|
||||
|
||||
for (i = 0; i < TIME_BUF_LEN; i++)
|
||||
TIME_BUF(rtc, i) = ReadData();
|
||||
|
||||
INFO_BUF(rtc, OFFSET_HOUR) &= 0x7F;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
|
||||
sLocked = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 SiiRtcSetTime(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (sLocked == TRUE)
|
||||
return FALSE;
|
||||
|
||||
sLocked = TRUE;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI | CS_HI;
|
||||
|
||||
GPIO_PORT_DIRECTION = DIR_ALL_OUT;
|
||||
|
||||
WriteCommand(CMD_TIME | WR);
|
||||
|
||||
for (i = 0; i < TIME_BUF_LEN; i++)
|
||||
WriteData(TIME_BUF(rtc, i));
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
|
||||
sLocked = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool8 SiiRtcSetAlarm(struct SiiRtcInfo *rtc)
|
||||
{
|
||||
u8 i;
|
||||
u8 alarmData[2];
|
||||
|
||||
if (sLocked == TRUE)
|
||||
return FALSE;
|
||||
|
||||
sLocked = TRUE;
|
||||
|
||||
// Decode BCD.
|
||||
alarmData[0] = (rtc->alarmHour & 0xF) + 10 * ((rtc->alarmHour >> 4) & 0xF);
|
||||
|
||||
// The AM/PM flag must be set correctly even in 24-hour mode.
|
||||
|
||||
if (alarmData[0] < 12)
|
||||
alarmData[0] = rtc->alarmHour | ALARM_AM;
|
||||
else
|
||||
alarmData[0] = rtc->alarmHour | ALARM_PM;
|
||||
|
||||
alarmData[1] = rtc->alarmMinute;
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI | CS_HI;
|
||||
|
||||
GPIOPortDirection = DIR_ALL_OUT; // Why is this the only instance that uses a symbol?
|
||||
|
||||
WriteCommand(CMD_ALARM | WR);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
WriteData(alarmData[i]);
|
||||
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
GPIO_PORT_DATA = SCK_HI;
|
||||
|
||||
sLocked = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int WriteCommand(u8 value)
|
||||
{
|
||||
u8 i;
|
||||
u8 temp;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
temp = ((value >> (7 - i)) & 1);
|
||||
GPIO_PORT_DATA = (temp << 1) | CS_HI;
|
||||
GPIO_PORT_DATA = (temp << 1) | CS_HI;
|
||||
GPIO_PORT_DATA = (temp << 1) | CS_HI;
|
||||
GPIO_PORT_DATA = (temp << 1) | SCK_HI | CS_HI;
|
||||
}
|
||||
|
||||
// control reaches end of non-void function
|
||||
}
|
||||
|
||||
static int WriteData(u8 value)
|
||||
{
|
||||
u8 i;
|
||||
u8 temp;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
temp = ((value >> i) & 1);
|
||||
GPIO_PORT_DATA = (temp << 1) | CS_HI;
|
||||
GPIO_PORT_DATA = (temp << 1) | CS_HI;
|
||||
GPIO_PORT_DATA = (temp << 1) | CS_HI;
|
||||
GPIO_PORT_DATA = (temp << 1) | SCK_HI | CS_HI;
|
||||
}
|
||||
|
||||
// control reaches end of non-void function
|
||||
}
|
||||
|
||||
static u8 ReadData()
|
||||
{
|
||||
u8 i;
|
||||
u8 temp;
|
||||
u8 value;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
GPIO_PORT_DATA = CS_HI;
|
||||
GPIO_PORT_DATA = CS_HI;
|
||||
GPIO_PORT_DATA = CS_HI;
|
||||
GPIO_PORT_DATA = CS_HI;
|
||||
GPIO_PORT_DATA = CS_HI;
|
||||
GPIO_PORT_DATA = SCK_HI | CS_HI;
|
||||
|
||||
temp = ((GPIO_PORT_DATA & SIO_HI) >> 1);
|
||||
value = (value >> 1) | (temp << 7); // UB: accessing uninitialized var
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void EnableGpioPortRead()
|
||||
{
|
||||
GPIO_PORT_READ_ENABLE = 1;
|
||||
}
|
||||
|
||||
static void DisableGpioPortRead()
|
||||
{
|
||||
GPIO_PORT_READ_ENABLE = 0;
|
||||
}
|
||||
@@ -30,9 +30,9 @@ const u8 gText_FailedUpdateSwapBackup[] = _("レポ-トの こうしんは\nし
|
||||
const u8 gText_SaveFileCorrupted[] = _("The save file is corrupted.\pThe previous save file will be\nloaded.");
|
||||
const u8 gText_SaveFileHasBeenDeleted[] = _("The save file has been\ndeleted...");
|
||||
const u8 gText_1MSubCircuitBoardNotInstalled[] = _("The 1M sub-circuit board is\nnot installed.");
|
||||
const u8 gTextJP_InternalBatteryHasRunDry[] = _("でんちぎれの ために\nとけいが うごかなくなりました\pとけいに かんけいする できごとは おきませんが\nゲ-ムを つづけて あそぶことは できます");
|
||||
const u8 gText_PlayerUnused[] = _("しゅじんこう");
|
||||
const u8 gText_PokedexUnused[] = _("ポケモンずかん");
|
||||
const u8 gText_BatteryRunDry[] = _("The internal battery has run dry.\nThe game can be played.\pHowever, clock-based events will\nno longer occur.");
|
||||
const u8 gUnknown_8415CD9[] = _("しゅじんこう");
|
||||
const u8 gUnknown_8415CE0[] = _("ポケモンずかん");
|
||||
const u8 gText_MainMenuTime[] = _("TIME");
|
||||
const u8 gText_BadgesUnused[] = _("もっているバッジ");
|
||||
const u8 gText_AButton[] = _("Aボタン");
|
||||
@@ -156,6 +156,16 @@ const u8 gText_SelectorArrow2[] = _("▶");
|
||||
const u8 gText_YesNo[] = _("YES\nNO");
|
||||
const u8 gText_GoBackToThePreviousMenu[] = _("Go back to the\nprevious menu.");
|
||||
const u8 gText_WhatWouldYouLikeToDo[] = _("What would you like to do?");
|
||||
|
||||
const u8 gText_ResetRTCConfirmCancel[] = _("Reset RTC?\nA: Confirm, B: Cancel");
|
||||
const u8 gText_PresentTime[] = _("Present time in game");
|
||||
const u8 gText_PreviousTime[] = _("Previous time in game");
|
||||
const u8 gText_PleaseResetTime[] = _("Please reset the time.");
|
||||
const u8 gText_ClockHasBeenReset[] = _("The clock has been reset.\nData will be saved. Please wait.");
|
||||
const u8 gText_SaveCompleted[] = _("Save completed.");
|
||||
const u8 gText_NoSaveFileCantSetTime[] = _("There is no save file, so the time\ncan't be set.");
|
||||
const u8 gText_InGameClockUsable[] = _("The in-game clock adjustment system\nis now useable.");
|
||||
|
||||
const u8 gText_MenuPokedex[] = _("POKéDEX");
|
||||
const u8 gText_MenuBag[] = _("BAG");
|
||||
const u8 gText_MenuPokenav[] = _("ポケナビ");
|
||||
@@ -886,15 +896,7 @@ const u8 gText_ButtonTypeLEqualsA[] = _("L=A");
|
||||
const u8 gText_ButtonTypeLR[] = _("LR");
|
||||
const u8 gText_FrameType[] = _("TYPE");
|
||||
const u8 gText_PickSwitchCancel[] = _("{DPAD_UPDOWN}PICK {DPAD_LEFTRIGHT}SWITCH {A_BUTTON}{B_BUTTON}CANCEL");
|
||||
const u8 gText_ResetRTCConfirmCancel[] = _("RTCを リセットします\nAで けってい Bで キャンセル");
|
||||
const u8 gText_PresentTime[] = _("げんざいの ゲ-ムない じかん");
|
||||
const u8 gText_PreviousTime[] = _("ぜんかいの ゲ-ムない じかん");
|
||||
const u8 gText_PleaseResetTime[] = _("じかんを さいせってい してください");
|
||||
const u8 gText_ClockHasBeenReset[] = _("じかんを さいせってい しました!\nレポ-トを かいています おまちください");
|
||||
const u8 gText_SaveCompleted[] = _("レポ-トを かきこみました!");
|
||||
const u8 gText_SaveFailed[] = _("レポ-トの かきこみに\nしっぱい しました‥");
|
||||
const u8 gText_NoSaveFileCantSetTime[] = _("レポ-トが ないので\nじかんの せっていは できません!");
|
||||
const u8 gText_InGameClockUsable[] = _("ゲ-ムない じかんの しゅうせい システムが\nつかえる ように なりました!");
|
||||
const u8 gText_SavingDontTurnOffThePower2[] = _("SAVING…\nDON'T TURN OFF THE POWER.");
|
||||
|
||||
// Start menu option descriptions
|
||||
@@ -969,6 +971,9 @@ const u8 gText_Diploma_National[] = _("NATIONAL");
|
||||
const u8 gText_Diploma_Kanto[] = _("KANTO");
|
||||
const u8 gText_ClearAllSaveData[] = _("Clear all save data areas?");
|
||||
const u8 gText_ClearingData[] = _("Clearing data‥\nPlease wait.");
|
||||
const u8 gText_IsThisTheCorrectTime[] = _("Is this the correct time?");
|
||||
const u8 gText_Confirm3[] = _("CONFIRM");
|
||||
const u8 gText_Cancel4[] = _("CANCEL");
|
||||
const u8 gText_Player[] = _("PLAYER");
|
||||
const u8 gText_Time[] = _("TIME");
|
||||
const u8 gText_Colon[] = _(":");
|
||||
@@ -1175,6 +1180,9 @@ const u8 gText_BronzeCard[] = _("BRONZE");
|
||||
const u8 gText_CopperCard[] = _("COPPER");
|
||||
const u8 gText_SilverCard[] = _("SILVER");
|
||||
const u8 gText_GoldCard[] = _("GOLD");
|
||||
const u8 gText_Day[] = _("DAY");
|
||||
const u8 gText_Colon3[] = _(":");
|
||||
const u8 gText_Confirm2[] = _("CONFIRM");
|
||||
const u8 gText_HelpSystemControls_A_Next[] = _("{A_BUTTON}NEXT");
|
||||
const u8 gText_HelpSystemControls_PickOkEnd[] = _("{DPAD_UPDOWN}PICK {A_BUTTON}OK {B_BUTTON}END");
|
||||
const u8 gText_HelpSystemControls_AorBtoCancel[] = _("{A_BUTTON}{B_BUTTON}CANCEL");
|
||||
|
||||
11
src/time_events.c
Normal file
11
src/time_events.c
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "global.h"
|
||||
#include "time_events.h"
|
||||
#include "event_data.h"
|
||||
#include "field_weather.h"
|
||||
#include "pokemon.h"
|
||||
#include "random.h"
|
||||
#include "overworld.h"
|
||||
#include "rtc.h"
|
||||
#include "script.h"
|
||||
#include "task.h"
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
#include "new_game.h"
|
||||
#include "random.h"
|
||||
#include "save.h"
|
||||
#include "event_data.h"
|
||||
#include "main_menu.h"
|
||||
#include "clear_save_data_screen.h"
|
||||
#include "reset_rtc_screen.h"
|
||||
#include "berry_fix_program.h"
|
||||
#include "decompress.h"
|
||||
#include "constants/songs.h"
|
||||
@@ -55,6 +57,8 @@ static void UpdateScanlineEffectRegBuffer(s16 y);
|
||||
static void ScheduleStopScanlineEffect(void);
|
||||
static void LoadMainTitleScreenPalsAndResetBgs(void);
|
||||
static void CB2_FadeOutTransitionToSaveClearScreen(void);
|
||||
static void CB2_GoToResetRtcScreen(void);
|
||||
static void CB2_FadeOutTransitionToResetRtcScreen(void);
|
||||
static void CB2_FadeOutTransitionToBerryFix(void);
|
||||
static void LoadSpriteGfxAndPals(void);
|
||||
#if defined(FIRERED)
|
||||
@@ -608,6 +612,7 @@ static void SetTitleScreenScene_FadeIn(s16 *data)
|
||||
}
|
||||
|
||||
#define KEYSTROKE_DELSAVE (B_BUTTON | SELECT_BUTTON | DPAD_UP)
|
||||
#define KEYSTROKE_RESET_RTC (B_BUTTON | SELECT_BUTTON | DPAD_LEFT)
|
||||
#define KEYSTROKE_BERRY_FIX (B_BUTTON | SELECT_BUTTON)
|
||||
|
||||
static void SetTitleScreenScene_Run(s16 *data)
|
||||
@@ -634,6 +639,12 @@ static void SetTitleScreenScene_Run(s16 *data)
|
||||
DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
|
||||
SetMainCallback2(CB2_FadeOutTransitionToSaveClearScreen);
|
||||
}
|
||||
else if (JOY_HELD(KEYSTROKE_RESET_RTC) == KEYSTROKE_RESET_RTC && CanResetRTC() == TRUE)
|
||||
{
|
||||
DeactivateSlashSprite(tSlashSpriteId);
|
||||
DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
|
||||
SetMainCallback2(CB2_FadeOutTransitionToResetRtcScreen);
|
||||
}
|
||||
else if (JOY_HELD(KEYSTROKE_BERRY_FIX) == KEYSTROKE_BERRY_FIX)
|
||||
{
|
||||
DeactivateSlashSprite(tSlashSpriteId);
|
||||
@@ -652,6 +663,15 @@ static void SetTitleScreenScene_Run(s16 *data)
|
||||
}
|
||||
}
|
||||
|
||||
static void CB2_FadeOutTransitionToResetRtcScreen(void)
|
||||
{
|
||||
if (!UpdatePaletteFade())
|
||||
{
|
||||
m4aMPlayAllStop();
|
||||
SetMainCallback2(CB2_InitResetRtcScreen);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetGpuRegsForTitleScreenRun(void)
|
||||
{
|
||||
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON);
|
||||
@@ -728,15 +748,20 @@ static void SetTitleScreenScene_Cry(s16 *data)
|
||||
case 2:
|
||||
if (!gPaletteFade.active)
|
||||
{
|
||||
SeedRngAndSetTrainerId();
|
||||
SetSaveBlocksPointers();
|
||||
ResetMenuAndMonGlobals();
|
||||
Save_ResetSaveCounters();
|
||||
LoadGameSave(SAVE_NORMAL);
|
||||
if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_INVALID)
|
||||
Sav2_ClearSetDefault();
|
||||
SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound);
|
||||
InitHeap(gHeap, HEAP_SIZE);
|
||||
// These are commented out as they’ve been relocated to intro.c.
|
||||
// This also allows RTC reset to work without file corruption.
|
||||
// It also has the side effect of allowing you to run flags
|
||||
// and functions as early as the intro.
|
||||
|
||||
// SeedRngAndSetTrainerId();
|
||||
// SetSaveBlocksPointers();
|
||||
// ResetMenuAndMonGlobals();
|
||||
// Save_ResetSaveCounters();
|
||||
// Save_LoadGameData(SAVE_NORMAL);
|
||||
// if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_INVALID)
|
||||
// Sav2_ClearSetDefault();
|
||||
// SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound);
|
||||
// InitHeap(gHeap, HEAP_SIZE);
|
||||
SetMainCallback2(CB2_InitMainMenu);
|
||||
DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
|
||||
}
|
||||
|
||||
1126
src/wallclock.c
Normal file
1126
src/wallclock.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,9 @@
|
||||
.include "src/m4a_1.o"
|
||||
.include "data/sound_data.o"
|
||||
.include "src/agb_flash.o"
|
||||
.include "src/siirtc.o"
|
||||
.include "src/rtc.o"
|
||||
.include "src/reset_rtc_screen.o"
|
||||
.include "*libgcc.a:dp-bit.o"
|
||||
.include "*libgcc.a:fp-bit.o"
|
||||
.include "*libc.a:syscalls.o"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
.include "main.o"
|
||||
.include "rtc.o"
|
||||
.include "bg.o"
|
||||
.include "text_printer.o"
|
||||
.align 4
|
||||
|
||||
Reference in New Issue
Block a user