User:Ludo6431/pit-read.c

From DSiBrew
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
/*
 *  pitread.c -- pit.bin file reader by Ludo6431 <ludolacost_gm@il_com>
 */

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#ifndef BIT
#   define BIT(b) (1<<(b))
#endif

void mexit(int ret, char *format, ...) {
    if(format) {
        va_list ap;
        va_start(ap, format);
        vfprintf(stderr, format, ap);
        fprintf(stderr, "\n");
        va_end(ap);
    }
    exit(ret);
}

typedef struct PIT_HDR sPIT_HDR;
struct PIT_HDR {
    u32 magic;
    u32 dunno1;         // "00_1"
    u16 slotsnum;       // 3000 slots in the file
    u16 msbfolderctr;
    u16 lsbfolderctr;   // next folder's number will be ++folderctr
    u16 photoctr;       // next photo's number will be ++photoctr
    u16 dunno2;         // 0x0000
    u16 framectr;       // next frame's number will be ++framectr
    u16 checksum;       // crc16 of whole file
    u16 hdrsize;        // 0x18
};

#define F_DIRNUM(f)     (((f)&0x1)*100 + ((f)>>1)&0x7f) // 8bits (100-129)
#define F_ENTNUM(f)     ((((f)>>11)&0x7f)+1)            // 7bits (0-99)
#define F_STICKER(f)    (((f)>>18)&0x3)
#define F_TYPE(f)       (((f)>>20)&0x1)
typedef struct PIT_ENTRY sPIT_ENTRY;
struct PIT_ENTRY {
    u32 date;
    u8 dunno[8];
    u32 flags; // (bit0: hundreds' digit of folder num; bit1-7: tens' digits of folder num; bit8-10: UNKNOWN (0); bit11-17: photo's number minus 1; bit18-19: sticker 0: None, 1: Star, 2: Clover, 3: Heart; bit20: type 0:photo, 1:frame; bit21-31: UNKNOWN (0))
};

int main(int argc, char *argv[]) {
    if(argc!=2) mexit(1, "Usage:\n\t%s <pit.bin>", argv[0]);

    char *fname = argv[1];
    FILE *fd = fopen(fname, "rb+");
    if(!fd) mexit(1, "Can't open file \"%s\"!", fname);

    fseek(fd, 0, SEEK_END);
    unsigned fsize = ftell(fd);
    rewind(fd);

    sPIT_HDR hdr;

    if(fread((void *)&hdr, 1, sizeof(sPIT_HDR), fd)!=sizeof(sPIT_HDR)) {
        fclose(fd);
        mexit(1, "Can't read file \"%s\"!", fname);
    }

    printf("magic       : \"%c%c%c%c\"\n", hdr.magic>>24, (hdr.magic>>16)&0xFF, (hdr.magic>>8)&0xFF, hdr.magic&0xFF);
    printf("dunno1      : \"%c%c%c%c\"\n", hdr.dunno1&0xFF, (hdr.dunno1>>8)&0xFF, (hdr.dunno1>>16)&0xFF, hdr.dunno1>>24);
    printf("slotsnum    : %d\n", hdr.slotsnum);
    printf("folderctr   : %d%02d\n", hdr.msbfolderctr, hdr.lsbfolderctr);
    printf("photoctr    : %d\n", hdr.photoctr);
    printf("framectr    : %d\n", hdr.framectr);
    printf("checksum    : 0x%02x\n", hdr.checksum);
    printf("headersize  : %d\n", hdr.hdrsize);

    // jump after the header
    fseek(fd, hdr.hdrsize, SEEK_SET);

    u32 i, photocnt=0, framecnt=0, offset;
    sPIT_ENTRY entry;
    for(i=0; i<hdr.slotsnum; i++) {
        offset = ftell(fd);
        if(fread((void *)&entry, 1, sizeof(sPIT_ENTRY), fd)!=sizeof(sPIT_ENTRY)) {
            fclose(fd);
            mexit(1, "Can't read file \"%s\" (after %d+%d valid entries)!", fname, photocnt, framecnt);
        }

        if(!entry.date) continue;

        switch(F_TYPE(entry.flags)) {
        case 0: // photo
            photocnt++;
            printf("-- photo%04d -- (slot%d in file)\n", photocnt, (offset-hdr.hdrsize)>>4);
            break;
        case 1: // frame
            framecnt++;
            printf("-- frame%04d -- (slot%d in file)\n", framecnt, (offset-hdr.hdrsize)>>4);
            break;
        default:
            break;
        }

        struct tm ttm;
        time_t stm;
        bzero(&ttm, sizeof(ttm));
        ttm.tm_year = 2000 - 1900;   // 2000
        ttm.tm_mon = 0;  // january
        ttm.tm_mday = 1; // 1st
        stm = mktime(&ttm);
        stm += entry.date;

        printf("  date(UTC) : %s", asctime(gmtime(&stm)));
        printf("  folder    : %d\n", F_DIRNUM(entry.flags));
        printf("  number    : %d\n", F_ENTNUM(entry.flags));

        char fname[128];
        switch(F_TYPE(entry.flags)) {
        case 0:
            printf("  sticker   : %d\n", F_STICKER(entry.flags));
            sprintf(fname, "/DCIM/%03dNIN02/HNI_%04d.JPG", F_DIRNUM(entry.flags), F_ENTNUM(entry.flags));
            break;
        case 1:
            sprintf(fname, "/private/ds/app/484E494A/DCIM/%03dNIN02/HNI_%04d.JPG", F_DIRNUM(entry.flags), F_ENTNUM(entry.flags));
            break;
        default:
            break;
        }

        printf("  filename  : %s\n", fname);
    }
    printf("The file contains %d photos and %d frames.\n", photocnt, framecnt);

    fclose(fd);
}