/title/00000001/00000002/data/play_rec.dat

From WiiBrew
< /title‎ | 00000001‎ | 00000002‎ | data
Jump to navigation Jump to search


This file is generated by the System Menu before it launches a title.

typedef union {
        struct {
                u32 checksum;
                u16 name[0x28];
                u32 _pad1;
                u64 ticks_boot;
                u64 ticks_last;
                u32 title_id;
                u32 _pad2[5];
        };
        struct {
                u32 _checksum;
                u32 data[0x1f];
        };
} __attribute__((packed)) playtime_t;

SDK-based titles update this periodically with the current timestamp and on clean shutdown. The next time the System Menu starts, it checks for this file, and if it finds a valid play_rec.dat file it adds this entry to the "playtime log" in /title/00000001/00000002/data/cdb.vff and deletes this file.

In order to prevent strange effects that arise from not updating the timestamps correctly, the Homebrew Channel writes a corrupted entry to this file. This causes the System Menu to discard it upon the next boot.

The "ticks per second" for the timestamps in this file is 60750000. Multiplying this by a regular timestamp and subtracting the "seconds to 2000" (946684800) will convert it.

static char _playtime_path[] __attribute__((aligned(32))) =
        "/title/00000001/00000002/data/play_rec.dat";

void playtime_destroy(void) {
        s32 res;
        s32 pt_fd = -1;
        static u8 pt_buf[4] __attribute__((aligned(32)));

        gprintf("destroying playtime\n");

        res = ISFS_Initialize();
        if (res) {
                ISFS_Deinitialize();
                gprintf("error initializing isfs (%d)\n", res);
                return;
        }

        pt_fd = IOS_Open(_playtime_path, IPC_OPEN_RW);
        if(pt_fd < 0) {
                ISFS_Deinitialize();
                gprintf("playtime open failed: %d\n", pt_fd);
                return;
        }

        memset(pt_buf, 0, sizeof(pt_buf));

        res = IOS_Write(pt_fd, &pt_buf, sizeof(pt_buf));
        if (res != sizeof(pt_buf)) {
                IOS_Close(pt_fd);
                ISFS_Deinitialize();
                gprintf("error destroying playtime (%d)\n", res);
                return;
        }

        IOS_Close(pt_fd);
        ISFS_Deinitialize();

        return;
}