Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions include/revolution/NWC24/NWC24MBoxCtrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,61 @@ extern "C" {

NWC24Err NWC24iOpenMBox(void);

typedef struct MountInfoStruct {
u32 count; // 0x00
s32 type; // 0x04
} MountInfoStruct;

typedef struct MBoxControlHeader {
u32 magic; // 0x00
u32 version; // 0x04
u32 msgCount; // 0x08
u32 capacity; // 0x0C
u32 totalMsgSize; // 0x10
u32 mailDataOffset; // 0x14
u32 nextMsgId; // 0x18
u32 nextFreeEntry; // 0x1C
u32 oldestMsgId; // 0x20
u32 freeSpace; // 0x24
char padding[0x58]; // to 0x80
} MBoxControlHeader;

typedef struct MBoxControlEntry {
u32 id; // 0x00
u32 flags; // 0x04
u32 length; // 0x08
u32 appId; // 0x0C
u32 UNK_0x10; // 0x10
u32 tag; // 0x14
u32 ledPattern; // 0x18
u32 nextFreeOrCreationMs; // 0x1C
u64 fromId; // 0x20
u32 createTime; // 0x28
u32 UNK_0x2C; // 0x2C
u8 numTo; // 0x30
u8 numAttached; // 0x31
u16 groupId; // 0x32
u32 packedSubjectText; // 0x34
u32 packedTextSubjectSize; // 0x38
u32 packedSubjectTextSize; // 0x3C
u32 packedTextSizeContentType; // 0x40
u32 packedContentTypeTransferEnc; // 0x44
u32 textPtr; // 0x48
u32 textSize; // 0x4C
u32 attached0Ptr; // 0x50
u32 attached0Size; // 0x54
u32 attached1Ptr; // 0x58
u32 attached1Size; // 0x5C
u32 attached0OrigSize; // 0x60
u32 attached1OrigSize; // 0x64
u32 attached0_type; // 0x68
u32 attached1_type; // 0x6C
u32 textOrigSize; // 0x70
u32 UNK_0x74; // 0x74
u32 UNK_0x78; // 0x78
u32 UNK_0x7C; // 0x7C
} MBoxControlEntry;

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion include/revolution/NWC24/NWC24Manage.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ typedef struct NWC24Work {
char WORK_0x1180[128];
char WORK_0x1200[128];
char WORK_0x1280[128];
u8 base64Work[256]; // at 0x1300
s8 base64Work[256]; // at 0x1300
char WORK_0x1400[0x2400 - 0x1400];
u8 flHeader[WORK_SIZE(NWC24FLHeader)]; // at 0x2800
u8 secretFlHeader[WORK_SIZE(NWC24SecretFLHeader)]; // at 0x2800
Expand Down
2 changes: 1 addition & 1 deletion include/revolution/NWC24/NWC24Mime.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
extern "C" {
#endif

void NWC24InitBase64Table(u8* table);
void NWC24InitBase64Table(s8* table);

#ifdef __cplusplus
}
Expand Down
8 changes: 8 additions & 0 deletions include/revolution/NWC24/NWC24MsgCommit.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,23 @@
#include <types.h>

#include <revolution/NWC24/NWC24Types.h>
#include <revolution/NWC24/NWC24Utils.h>
#ifdef __cplusplus
extern "C" {
#endif

#define NWC24_WORK_BUFFER_SIZE 1024

// Forward declarations
typedef struct NWC24MsgObj NWC24MsgObj;

NWC24Err NWC24CommitMsg(NWC24MsgObj*);

typedef union {
u64 id;
NWC24Data data;
} NWC24AddrId;

#ifdef __cplusplus
}
#endif
Expand Down
11 changes: 6 additions & 5 deletions include/revolution/NWC24/NWC24MsgObj.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ typedef struct NWC24MsgObj {
u32 flags; // at 0x4
u32 length; // at 0x8
u32 appId; // at 0xC
char UNK_0x10[0x4];
s32 UNK_0x10;
u32 tag; // at 0x14
u32 ledPattern; // at 0x18
u64 fromId; // at 0x20
u32 WORD_0x28;
u32 createTime; // at 0x28
u32 WORD_0x2C;
NWC24Data DATA_0x30;
NWC24Data DATA_0x38;
NWC24Data subject; // at 0x40
NWC24Data text; // at 0x48
NWC24Data DATA_0x50;
NWC24Data DATA_0x58;
NWC24Data contentType; // at 0x50
NWC24Data transferEncoding; // at 0x58
NWC24Charset charset; // at 0x60
NWC24Encoding encoding; // at 0x64
NWC24Data attached[NWC24_MSG_ATTACHMENT_MAX]; // at 0x68
Expand All @@ -70,7 +70,8 @@ typedef struct NWC24MsgObj {
NWC24Data DATA_0xD0;
NWC24Data face; // at 0xD8
NWC24Data alt; // at 0xE0
char UNK_0xE8[0x100 - 0xE8];
NWC24Data altMeta;
char UNK_0xF0[0x100 - 0xF0];
} NWC24MsgObj;

NWC24Err NWC24InitMsgObj(NWC24MsgObj* msg, NWC24MsgType type);
Expand Down
12 changes: 12 additions & 0 deletions include/revolution/NWC24/NWC24Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ typedef struct NWC24Date {
u8 BYTE_0x7;
} NWC24Date;

typedef struct NWC24Calendar {
/* 0x00 */ u32 sec;
/* 0x04 */ u32 min;
/* 0x08 */ u32 hour;
/* 0x0C */ u32 day;
/* 0x10 */ u32 month;
/* 0x14 */ u32 year;
/* 0x18 */ u32 UNK_0x18;
/* 0x1C */ u32 UNK_0x1C;
/* 0x20 */ u32 UNK_0x20;
} NWC24Calendar;

void NWC24Data_Init(NWC24Data* data);
void NWC24Data_SetDataP(NWC24Data* data, const void* ptr, u32 size);
void NWC24Date_Init(NWC24Date* date);
Expand Down
193 changes: 193 additions & 0 deletions src/revolution/NWC24/NWC24DateParser.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#include <revolution/NWC24.h>

const u8 DAYS_OF_MONTH[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0, 0, 0, 0};
const u16 DAYS_OF_YEAR[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};

NWC24Err NWC24iDateToMinutes(s32 *outMinutes, const NWC24Date *date);
NWC24Err NWC24iEpochSecondsToDate(NWC24Date *date, s64 timestamp);
NWC24Err NWC24iDateToOSCalendarTime(OSCalendarTime *time, const NWC24Date *date);
NWC24Err NWC24iIsValidDate(u16 year, u8 month, u8 day);
static BOOL IsLeapYear(u16 year);
s32 ConvertDateToDays(u16 year, u16 month, u16 day);
void ConvertDaysToDate(u16 *year, u8 *month, u8 *day, s32 days);
static s32 ConvertTimeToMinutes(u8 hour, u8 sec);
static s32 ConvertDaysToMinutes(s32 days);
static s32 ConvertMinutesToDays(s32 minutes);

NWC24Err NWC24iDateToMinutes(s32 *outMinutes, const NWC24Date *date) {
s32 days;
s32 minutes;

days = ConvertDateToDays(date->year, date->month, date->day);

if (days == -1) {
return NWC24_ERR_FAILED;
}

minutes = ConvertTimeToMinutes(date->hour, date->min);
if (minutes == -1 || date->sec > 60) {
return NWC24_ERR_FAILED;
}

*outMinutes = ConvertDaysToMinutes(days) + minutes;
return NWC24_OK;
}

NWC24Err NWC24iEpochSecondsToDate(NWC24Date *date, s64 timestamp) {
s64 adjusted = -0x7c558180U;
s32 minutes;
u32 days;

if (0 > (timestamp + adjusted)) {
timestamp = -adjusted;
}

timestamp += adjusted;
date->sec = (u8)(timestamp % 60);
minutes = timestamp / 60;
if (minutes < 0) {
minutes = 0;
}

days = ConvertMinutesToDays(minutes);
minutes %= (24 * 60);

date->hour = (u8)(minutes / 60);
date->min = (u8)(minutes % 60);
ConvertDaysToDate(&date->year, &date->month, &date->day, days);
return NWC24_OK;
}

NWC24Err NWC24iDateToOSCalendarTime(OSCalendarTime *time, const NWC24Date *date) {
s32 daysSinceEpoch;

time->year = date->year;
time->month = date->month - 1;
time->mday = date->day;
time->hour = date->hour;
time->min = date->min;
time->sec = date->sec;
time->msec = 0;
time->usec = 0;
time->yday = (DAYS_OF_YEAR[time->month] + date->day) - 1;

if (IsLeapYear(date->year) && date->month > 2) {
time->yday++;
}

daysSinceEpoch = ConvertDateToDays(date->year, date->month, date->day);
// Possibly NWC24iGetDayOfWeek(daysSinceEpoch)?
time->wday = (daysSinceEpoch + 1) % 7;
return NWC24_OK;
}

NWC24Err NWC24iIsValidDate(u16 year, u8 month, u8 day) {
s32 days = ConvertDateToDays(year, month, day);
s32 result = NWC24_OK;

if (days == -1) {
result = NWC24_ERR_INVALID_VALUE;
}

return result;
}

static BOOL IsLeapYear(u16 year) {
return (((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) != 0);
}

s32 ConvertDateToDays(u16 year, u16 month, u16 day) {
s32 dayOfYear;
s32 yearsSince1900;
s32 days;
s32 leapDays;
s32 gregorianCorrection;

if (year < 1900 || month < 1 || month > 12) {
return -1;
}

if (month == 2 && IsLeapYear(year)) {
if (day < 1 || day > 29) {
return -1;
}
} else {
if (day < 1 || (u16)DAYS_OF_MONTH[month - 1] < day) {
return -1;
}
}

dayOfYear = day - 1;
dayOfYear += DAYS_OF_YEAR[month - 1];

if (month >= 3 && IsLeapYear(year)) {
dayOfYear++;
}

yearsSince1900 = year - 1900;

leapDays = (yearsSince1900 - 1) / 4 - (yearsSince1900 - 1) / 100;
gregorianCorrection = (yearsSince1900 + 299) / 400;

days = yearsSince1900 * 365 + dayOfYear;
days += leapDays + gregorianCorrection;

return days;
}

void ConvertDaysToDate(u16 *year, u8 *month, u8 *day, s32 days) {
s32 remaining;

*year = 1900;
*month = 1;
*day = 1;

if (days < 0) {
return;
}

while (1) {
remaining = days;
days -= IsLeapYear(*year) ? 366 : 365;

if (days < 0) {
days = remaining;
break;
}

(*year)++;
}

while (1) {
remaining = days;

if (*month == 2 && IsLeapYear(*year)) {
days -= 29;
} else {
days -= DAYS_OF_MONTH[*month - 1];
}

if (days < 0) {
break;
}

(*month)++;
}

*day += remaining;
}

static s32 ConvertTimeToMinutes(u8 hour, u8 sec) {
if (hour > 23 || sec > 59) {
return -1;
}
return (sec + (hour * 60));
}

static s32 ConvertDaysToMinutes(s32 days) {
return days * (24 * 60);
}

static s32 ConvertMinutesToDays(s32 minutes) {
return minutes / (24 * 60);
}
Loading
Loading