?? leafpak.c
字號:
/* * leafpak.c * decode leaf archive file. * 10/06/1997 by TF <tf@imou.to> *//* * Changes: * 10/31/2000 TAKAHASHI Kaoru <kaoru@kaisei.org> * Fixed a probrem when fopen(,"w") failed. * 10/17/1997 FUJIWARA Teruyoshi <tf@imou.to> * Add auto key calculation. * Support maxxdata.pak in 'Saorin to Issho!!'*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "leafpak.h"static void check_magic(FILE *);static int get_file_num(FILE *);static void set_type(LEAFPACK *);static void init_leafpack(LEAFPACK *);static void extract_table(LEAFPACK *);static void regularize_name(char *);static void guess_key(LEAFPACK *);#ifdef DEBUGstatic void verify_key(LEAFPACK *);#endif/* * Open archive file and extact file table. */LEAFPACK *leafpack_open(const char *filename){ LEAFPACK *lp = NULL; lp = (LEAFPACK *)malloc(sizeof(LEAFPACK)); if (lp == NULL) { fprintf(stderr, "leafpack_open: Memory allocation error.\n"); return NULL; } lp->fp = fopen(filename, "r"); if (lp->fp == NULL) { fprintf(stderr, "leafpack_open: Can't open %s\n", filename); return NULL; } check_magic(lp->fp); lp->file_num = get_file_num(lp->fp); set_type(lp); if (lp->type == UNKNOWN) { guess_key(lp); } init_leafpack(lp); extract_table(lp); return lp;}/* * Free allocated memories and close file. */void leafpack_close(LEAFPACK *lp){ int i; if (lp->fp != NULL) { fclose(lp->fp); } lp->fp = NULL; for (i = 0; i < lp->file_num; i++) { free(lp->name[i]); } free(lp->name); free(lp->pos); free(lp->len); free(lp->nextpos); free(lp);}/* * Extract all archive into current directory. Archive file * shuold already be opend. */void extract_all(LEAFPACK *lp){ int i, k; int val, pos; FILE *fp; for (i = 0; i < lp->file_num; i++) { fp = fopen(lp->name[i], "w"); if (fp == NULL) { printf("Can't write %s. skip\n", lp->name[i]); } else { printf("extracting %s...", lp->name[i]); fflush(stdout); pos = lp->pos[i]; fseek(lp->fp, (long)pos, SEEK_SET); k = 0; while (pos != lp->nextpos[i]) { val = (fgetc(lp->fp) - lp->key[k]) & 0xff; k = (++k) % KEY_LEN; fputc(val, fp); pos++; } fclose(fp); printf("done.\n"); } } printf("\nAll files are extracted.\n");}/* * Extract a file specified by name from archive. Archive file * shuold already be opened. */int leafpack_extract_file(LEAFPACK *lp, const char *file){ int i = 0, k = 0; int val, pos; FILE *fp; /* lookup table */ while (i < lp->file_num) { if (!strcasecmp(file, lp->name[i])) { break; } i++; } if (i == lp->file_num) { printf("%s isn't included in this archive.\n", file); return 1; } printf("extracting %s...", file); fflush(stdout); fp = fopen(file, "w"); if ( fp == NULL ) { printf("Can't write %s.\n", file); return -1; } pos = lp->pos[i]; fseek(lp->fp, (long)pos, SEEK_SET); while (pos != lp->nextpos[i]) { val = (fgetc(lp->fp) - lp->key[k]) & 0xff; k = (++k) % KEY_LEN; fputc(val, fp); pos++; } fclose(fp); printf("done.\n"); return 0;}/* * a char array 'buf' should have size more than 9.*/void leafpack_read_magic(LEAFPACK *lp, const char *file, char *buf){ int i = 0; int pos; /* lookup table */ while (i < lp->file_num) { if (!strcasecmp(file, lp->name[i])) { break; } i++; } if (i == lp->file_num) { printf("%s isn't included in archive.\n", file); buf[0] = '\0'; return; } pos = lp->pos[i]; fseek(lp->fp, (long)pos, SEEK_SET); for (i = 0; i < 8; i++) { buf[i] = (fgetc(lp->fp) - lp->key[i]) & 0xff; } buf[8] = '\0'; return;}int *leafpack_extract_file_to_data(LEAFPACK *lp, const char *file, int *size){ int i = 0, j = 0, k = 0; int pos; int *res; /* lookup table */ while (i < lp->file_num) { if (!strcasecmp(file, lp->name[i])) { break; } i++; } if (i == lp->file_num) { printf("%s isn't included in archive.\n", file); return NULL; } *size = lp->len[i]; printf("extracting %s...", file); fflush(stdout); res = (int *)calloc(lp->len[i], sizeof(int)); pos = lp->pos[i]; fseek(lp->fp, (long)pos, SEEK_SET); while (pos != lp->nextpos[i]) { res[j] = (fgetc(lp->fp) - lp->key[k]) & 0xff; k = (++k) % KEY_LEN; pos++; j++; } printf("done.\n"); return res;}/* * PRIVATE FUNCTIONS*/static void check_magic(FILE *fp){ int i; char buf[9]; for (i = 0; i < 8; i++) { buf[i] = fgetc(fp); } buf[8] = '\0'; if (strcmp(buf, "LEAFPACK")) { fprintf(stderr, "This file isn't a Leaf archive file.\n"); exit(1); }}static int get_file_num(FILE *fp){ int u, l; l = fgetc(fp); u = fgetc(fp); return u << 8 | l;}/* * Type is set by the number of files included in an archive file. * (And this type is used to select an encryption key!) * Then we can't extract an unkown archive. *//* * 10/16/1997: Add auto key calculation feature(experimental). */static void set_type(LEAFPACK *lp){ guess_key(lp); if (lp->file_num == 0x0248 || lp->file_num == 0x03e1) { lp->type = TOHEART; return; } else if (lp->file_num == 0x01fb) { lp->type = KIZUWIN; return; } else if (lp->file_num == 0x0193) { lp->type = SIZUWIN; return; } else if (lp->file_num == 0x0072) { lp->type = SAORIN; } else { lp->type = UNKNOWN; } #ifdef DEBUG verify_key(lp);#endif}#ifdef DEBUGstatic void verify_key(LEAFPACK *lp){ int i; int result = TRUE; if (lp->type == UNKNOWN || lp->type == SAORIN) { return; } for (i = 0; i < KEY_LEN; i++) { if (key_const[lp->type][i] != lp->key[i]) { fprintf(stderr, "Warning: An auto-calculated key is bad.\n"); result = FALSE; break; } } if (result == FALSE) { for (i = 0; i < KEY_LEN; i++) { lp->key[i] = key_const[lp->type][i]; } }}#endifstatic void init_leafpack(LEAFPACK *lp){ int i; /* initialize a filename table */ lp->name = (char **)calloc(lp->file_num, sizeof(char *)); for (i = 0; i < lp->file_num; i++) { lp->name[i] = (char *)calloc(13, sizeof(char)); } /* initialize table entories */ lp->pos = (int *)calloc(lp->file_num, sizeof(int)); lp->len = (int *)calloc(lp->file_num, sizeof(int)); lp->nextpos = (int *)calloc(lp->file_num, sizeof(int));}static void extract_table(LEAFPACK *lp){ int i, j; int k = 0; int b[4]; /* set a position to the head of the header part */ fseek(lp->fp, (long)(-24 * lp->file_num), SEEK_END); for (i = 0; i < lp->file_num; i++) { /* get filename */ for (j = 0; j < 12; j++) { lp->name[i][j] = (fgetc(lp->fp) - lp->key[k]) & 0xff; k = (++k) % KEY_LEN; } regularize_name(lp->name[i]); /* a position in the archive file */ for (j = 0; j < 4; j++) { b[j] = (fgetc(lp->fp) - lp->key[k]) & 0xff; k = (++k) % KEY_LEN; } lp->pos[i] = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]; /* file length */ for (j = 0; j < 4; j++) { b[j] = (fgetc(lp->fp) - lp->key[k]) & 0xff; k = (++k) % KEY_LEN; } lp->len[i] = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]; /* the head of the next file */ for (j = 0; j < 4; j++) { b[j] = (fgetc(lp->fp) - lp->key[k]) & 0xff; k = (++k) % KEY_LEN; } lp->nextpos[i] = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]; }}static void regularize_name(char *name){ char buf[12]; int i = 0; strcpy(buf, name); while (i < 8 && buf[i] != 0x20) { name[i] = buf[i]; i++; } name[i++] = '.'; /* file extention */ name[i++] = buf[8]; name[i++] = buf[9]; name[i++] = buf[10]; name[i] = '\0';}void print_type(LEAFPACK *lp){ printf("Archive file: "); switch (lp->type) { case SIZUWIN: printf("SHIZUKU for Windows95\n\n"); break; case KIZUWIN: printf("KIZUATO for Windows95\n\n"); break; case TOHEART: printf("To Heart\n\n"); break; case SAORIN: printf("Saorin to Issho!! (maxxdata.pak)\n\n"); break; default: printf("Unknown\n\n"); }}void print_table(LEAFPACK *lp, int verbose){ int i; if (verbose == TRUE) { printf("Key: "); for (i = 0; i < KEY_LEN; i++) { printf("%02x ", lp->key[i]); } printf("\n\n"); } if (verbose == TRUE) { printf("Filename Position Length Next\n"); printf("------------ -------- ------- --------\n"); } else { printf("Filename Length\n"); printf("------------ -------\n"); } for (i = 0; i < lp->file_num; i++) { printf("%12s ", lp->name[i]); if (verbose == TRUE) { printf("%08x ", lp->pos[i]); } printf("%8d ", lp->len[i]); if (verbose == TRUE) { printf("%08x", lp->nextpos[i]); } printf("\n"); } printf("%d files.\n", lp->file_num);}/* * Calculate key using length of archive data. * To use this function, the archive must include at least 3 files. */static void guess_key(LEAFPACK *lp){ int buf[72]; int i; /* find the top of table */ fseek(lp->fp, (long)(-24 * lp->file_num), SEEK_END); /* read 3 table entries, needed to calculate keys. */ for (i = 0; i < 72; i++) { buf[i] = fgetc(lp->fp); } /* zero */ lp->key[0] = buf[11]; /* 1st position, (maybe :-)) constant */ lp->key[1] = (buf[12] - 0x0a) & 0xff; lp->key[2] = buf[13]; lp->key[3] = buf[14]; lp->key[4] = buf[15]; /* 2nd position, from 1st next position */ lp->key[5] = (buf[38] - buf[22] + lp->key[0]) & 0xff; lp->key[6] = (buf[39] - buf[23] + lp->key[1]) & 0xff; /* 3rd position, from 2nd next position */ lp->key[7] = (buf[62] - buf[46] + lp->key[2]) & 0xff; lp->key[8] = (buf[63] - buf[47] + lp->key[3]) & 0xff; /* 1st next position, from 2nd position */ lp->key[9] = (buf[20] - buf[36] + lp->key[3]) & 0xff; lp->key[10] = (buf[21] - buf[37] + lp->key[4]) & 0xff;}/* end of file */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -