/*
 *	『あののの。〜君と過ごしたあの日あの時あの未来〜』体験版 展開ユーティリティ
 *
 *	『あののの。〜君と過ごしたあの日あの時あの未来〜』体験版のアーカイブを展開するためのツールです。
 *	『あののの。〜君と過ごしたあの日あの時あの未来〜』体験版のBGMを取り出すために作りました。
 *
 *	まだ体験版を途中まで遊んだところです。絵の評判が良いみたいですけれど、BGMもなかなか良いですね。
 *	生徒会長(名前はまだ覚えてません(^^;)の個人BGMがとくに気に入りました。買おうかなあ。
 *
 *	Copyright (C) 2005 Naoyuki Sawa
 *
 *	* Fri Feb 25 20:00:00 JST 2005 Naoyuki Sawa
 *	- 作成開始。
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define VERSION		"20050225"

const char* APPNAME;
const char* ARCHIVE;

#pragma pack(1)

/* アーカイブヘッダ */
typedef struct _ARCHDR {
	int  unknown;		/* ファイルタイプ識別子？ */
	char ext[4];		/* 拡張子 ("OGG\0","ANM\0"など) */
	int  file_num;		/* アーカイブ内のファイル数 */
	int  list_pos;		/* リストの先頭 (アーカイブ先頭からのオフセット) */
	/* アーカイブによっては、この後に用途不明のデータが続くものもあります */
} ARCHDR;

/* リストヘッダ */
typedef struct _LISTHDR {
	char fname[9];		/* ファイル名 (nul終端) */
	int file_len;		/* ファイルサイズ */
	int file_pos;		/* ファイルの位置 (アーカイブ先頭からのオフセット) */
} LISTHDR;

#pragma pack()

void
usage()
{
	printf("anonono - あののの。体験版展開ユーティリティ (%s)\n", VERSION);
	printf("USAGE:\n");
	printf("\t%s <アーカイブファイル名>\n", APPNAME);
	printf("EXAMPLE:\n");
	printf("\t%s \"C:\\Program Files\\Will\\あののの。体験版Ver101\\Bgm.arc\"\n", APPNAME);
	exit(-1);
}

int
main(int argc, char* argv[])
{
	int retval;
	int i;
	FILE* fp_in;
	FILE* fp_out;
	ARCHDR archdr;
	LISTHDR listhdr;
	fpos_t pos;
	void* buf;
	char fname[_MAX_FNAME];

	APPNAME = argv[0];
	if(argc != 1 + 1) usage();
	ARCHIVE = argv[1];

	fp_in = fopen(ARCHIVE, "rb");
	if(!fp_in) {
		printf("### %s が開けません。\n", ARCHIVE);
		exit(-1);
	}

	retval = fread(&archdr, sizeof archdr, 1, fp_in);
	if(retval != 1) {
		printf("### アーカイブヘッダ読み込みエラー\n");
		exit(-1);
	}

	for(i = 0; i < archdr.file_num; i++) {
		retval = fread(&listhdr, sizeof listhdr, 1, fp_in);
		if(retval != 1) {
			printf("### リストヘッダ読み込みエラー\n");
			exit(-1);
		}
		_makepath(fname, NULL, NULL, listhdr.fname, archdr.ext);
		printf("#%d: %s offset=%d size=%d\n", i, fname, listhdr.file_pos, listhdr.file_len);

/*{{1*/		retval = fgetpos(fp_in, &pos);
		if(retval != 0) {
			printf("### fgetpos エラー\n");
			exit(-1);
		}

		retval = fseek(fp_in, listhdr.file_pos, SEEK_SET);
		if(retval != 0) {
			printf("### fseek エラー\n");
			exit(-1);
		}

/*{{2*/		buf = malloc(listhdr.file_len);
		if(!buf) {
			printf("### malloc エラー\n");
			exit(-1);
		}

		retval = fread(buf, 1, listhdr.file_len, fp_in);
		if(retval != listhdr.file_len) {
			printf("### fread エラー\n");
			exit(-1);
		}

/*{{3*/		fp_out = fopen(fname, "wb");
		if(!fp_out) {
			printf("### %s が作成できません。\n", fname);
			exit(-1);
		}

		retval = fwrite(buf, 1, listhdr.file_len, fp_out);
		if(retval != listhdr.file_len) {
			printf("### fwrite エラー\n");
			exit(-1);
		}

/*}}3*/		fclose(fp_out);

/*}}2*/		free(buf);

/*}}1*/		retval = fsetpos(fp_in, &pos);
		if(retval != 0) {
			printf("### fsetpos エラー\n");
			exit(-1);
		}
	}

	printf("OK\n");

	return 0;
}
