2010-12-27 10:44:27 +01:00
|
|
|
|
/*
|
|
|
|
|
PLAYLOG.C
|
|
|
|
|
This code allows to modify play_rec.dat in order to store the
|
|
|
|
|
game time in Wii's log correctly.
|
|
|
|
|
|
|
|
|
|
by Marc
|
|
|
|
|
Thanks to tueidj for giving me some hints on how to do it :)
|
|
|
|
|
Most of the code was taken from here:
|
|
|
|
|
http://forum.wiibrew.org/read.php?27,22130
|
|
|
|
|
|
|
|
|
|
Modified by Dimok
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <ogcsys.h>
|
|
|
|
|
#include <malloc.h>
|
|
|
|
|
#include "gecko.h"
|
|
|
|
|
#include "utils/tools.h"
|
|
|
|
|
|
|
|
|
|
#define SECONDS_TO_2000 946684800LL
|
|
|
|
|
#define TICKS_PER_SECOND 60750000LL
|
|
|
|
|
|
|
|
|
|
//! Should be 32 byte aligned
|
|
|
|
|
static const char PLAYRECPATH[] ATTRIBUTE_ALIGN(32) = "/title/00000001/00000002/data/play_rec.dat";
|
|
|
|
|
|
|
|
|
|
typedef struct _PlayRec
|
|
|
|
|
{
|
|
|
|
|
u32 checksum;
|
|
|
|
|
union
|
|
|
|
|
{
|
|
|
|
|
u32 data[31];
|
|
|
|
|
struct
|
|
|
|
|
{
|
|
|
|
|
u16 name[42];
|
|
|
|
|
u64 ticks_boot;
|
|
|
|
|
u64 ticks_last;
|
|
|
|
|
char title_id[6];
|
|
|
|
|
char unknown[18];
|
|
|
|
|
} ATTRIBUTE_PACKED;
|
|
|
|
|
};
|
|
|
|
|
} PlayRec;
|
|
|
|
|
|
|
|
|
|
// Thanks to Dr. Clipper
|
|
|
|
|
static u64 getWiiTime(void)
|
|
|
|
|
{
|
|
|
|
|
time_t uTime = time(NULL);
|
|
|
|
|
return TICKS_PER_SECOND * (uTime - SECONDS_TO_2000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Playlog_Create(void)
|
|
|
|
|
{
|
|
|
|
|
s32 fd = IOS_Open(PLAYRECPATH, IPC_OPEN_RW);
|
|
|
|
|
if(fd >= 0)
|
|
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
|
//exists
|
|
|
|
|
IOS_Close(fd);
|
|
|
|
|
return 0;
|
2010-12-27 10:44:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
ISFS_Initialize();
|
2010-12-27 10:44:27 +01:00
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
//In case the play_rec.dat wasn´t found create one and try again
|
|
|
|
|
int ret = ISFS_CreateFile(PLAYRECPATH, 0, 3, 3, 3);
|
|
|
|
|
if(ret >= 0)
|
|
|
|
|
ISFS_SetAttr(PLAYRECPATH, 0x1000, 1, 0, 3, 3, 3);
|
2010-12-27 10:44:27 +01:00
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
ISFS_Deinitialize();
|
2010-12-27 10:44:27 +01:00
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
return ret;
|
2010-12-27 10:44:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Playlog_Update(const char * ID, const u16 * title)
|
|
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
|
if(!ID || !title)
|
|
|
|
|
return -1;
|
2010-12-27 10:44:27 +01:00
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
s32 fd = -1, res = -1;
|
2010-12-27 10:44:27 +01:00
|
|
|
|
u32 sum = 0;
|
|
|
|
|
u8 i;
|
|
|
|
|
|
|
|
|
|
//Open play_rec.dat
|
|
|
|
|
fd = IOS_Open(PLAYRECPATH, IPC_OPEN_RW);
|
|
|
|
|
if(fd == -106)
|
|
|
|
|
{
|
|
|
|
|
//In case the play_rec.dat wasn´t found create one and try again
|
|
|
|
|
int ret = Playlog_Create();
|
|
|
|
|
if(ret < 0)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
fd = IOS_Open(PLAYRECPATH, IPC_OPEN_RW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(fd < 0)
|
2011-07-26 00:28:22 +02:00
|
|
|
|
return res;
|
2010-12-27 10:44:27 +01:00
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
PlayRec * playrec_buf = memalign(32, ALIGN32(sizeof(PlayRec))); //! Should be 32 byte aligned
|
|
|
|
|
if(!playrec_buf)
|
|
|
|
|
{
|
|
|
|
|
IOS_Close(fd);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2010-12-27 10:44:27 +01:00
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
memset(playrec_buf, 0, sizeof(PlayRec));
|
2010-12-27 10:44:27 +01:00
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
u64 stime = getWiiTime();
|
2010-12-27 10:44:27 +01:00
|
|
|
|
playrec_buf->ticks_boot = stime;
|
|
|
|
|
playrec_buf->ticks_last = stime;
|
|
|
|
|
|
|
|
|
|
//Update channel name and ID
|
|
|
|
|
memcpy(playrec_buf->name, title, 84);
|
|
|
|
|
memcpy(playrec_buf->title_id, ID, 6);
|
|
|
|
|
|
|
|
|
|
//Calculate and update checksum
|
|
|
|
|
for(i = 0; i < 31; i++)
|
|
|
|
|
sum += playrec_buf->data[i];
|
|
|
|
|
|
|
|
|
|
playrec_buf->checksum = sum;
|
|
|
|
|
|
|
|
|
|
//Write play_rec.dat
|
|
|
|
|
if(IOS_Write(fd, playrec_buf, sizeof(PlayRec)) == sizeof(PlayRec))
|
|
|
|
|
res = 0;
|
|
|
|
|
|
|
|
|
|
IOS_Close(fd);
|
|
|
|
|
|
|
|
|
|
free(playrec_buf);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Playlog_Delete(void)
|
|
|
|
|
{
|
2011-07-26 00:28:22 +02:00
|
|
|
|
s32 res = -1;
|
2010-12-27 10:44:27 +01:00
|
|
|
|
|
|
|
|
|
//Open play_rec.dat
|
|
|
|
|
s32 fd = IOS_Open(PLAYRECPATH, IPC_OPEN_RW);
|
|
|
|
|
if(fd < 0)
|
|
|
|
|
return fd;
|
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
PlayRec * playrec_buf = memalign(32, ALIGN32(sizeof(PlayRec)));
|
|
|
|
|
if(!playrec_buf)
|
2010-12-27 10:44:27 +01:00
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
//Read play_rec.dat
|
|
|
|
|
if(IOS_Read(fd, playrec_buf, sizeof(PlayRec)) != sizeof(PlayRec))
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
if(IOS_Seek(fd, 0, 0) < 0)
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
// invalidate checksum
|
|
|
|
|
playrec_buf->checksum = 0;
|
|
|
|
|
|
|
|
|
|
if(IOS_Write(fd, playrec_buf, sizeof(PlayRec)) != sizeof(PlayRec))
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
2011-07-26 00:28:22 +02:00
|
|
|
|
res = 0;
|
2010-12-27 10:44:27 +01:00
|
|
|
|
|
|
|
|
|
cleanup:
|
2011-07-26 00:28:22 +02:00
|
|
|
|
free(playrec_buf);
|
|
|
|
|
IOS_Close(fd);
|
|
|
|
|
return res;
|
2010-12-27 10:44:27 +01:00
|
|
|
|
}
|