/*
 *	acpxpk - ACPXPK01展開ユーティリティ
 *
 *	"ACPXPK01"形式のアーカイブを展開するためのツールです。
 *	『流聖天使プリマヴェールＶ』のBGMを取り出すために作りました。
 *
 *	僕はNSN氏の音楽作品のファンで、(さとみアタックとかマリエルンとか特にいいですねー)
 *	プリマヴェールＶもNSNの氏の音楽だと思って買ってみたらNSN氏じゃなかった〜
 *	一瞬がっかり(スミマセン!)したのですが、聴いてみるとチームサボ天氏の音楽もいいですね。
 *	淡々とした曲調がなかなか。音楽単体でも楽しめます。というわけで・・・
 *
 *	エスクードさんのゲームはBGM CDDAのものが多いのですが、このゲームはOggVorbisでした。
 *	とても簡単なアーカイブ形式なので、手作業で取り出してもさほど手間はかからないですけど、
 *	一応、取り出し用ツールを作ってみました。
 *
 *	Copyright (C) 2004 Naoyuki Sawa
 *
 *	* Sat Jan 03 19:31:00 JST 2004 Naoyuki Sawa
 *	- 作成開始。
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define VERSION		"20040103"

const char* APPNAME;
const char* ARCHIVE;

typedef struct _HEADER {
	char fname[32];		/* ファイル名 */
	int offset;		/* ファイル開始位置(アーカイブ内絶対位置) */
	int size;		/* ファイルサイズ */
} HEADER;

void
usage()
{
	printf("acpxpk - ACPXPK01展開ユーティリティ (%s)\n", VERSION);
	printf("USAGE:\n");
	printf("\t%s <アーカイブファイル名>\n", APPNAME);
	printf("EXAMPLE:\n");
	printf("\t%s \"C:\\Program Files\\エスクード\\流聖天使プリマヴェールＶ\\BGM.bin\"\n", APPNAME);
	exit(-1);
}

int
main(int argc, char* argv[])
{
	int retval;
	FILE *fp_in, *fp_out;
	char signature[8];
	int count, i;
	HEADER header;
	fpos_t pos;
	void* buf;

	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(signature, 1, sizeof signature, fp_in);
	if(retval != sizeof signature || memcmp(signature, "ACPXPK01", sizeof signature) != 0) {
		printf("### signature エラー\n");
		exit(-1);
	}

	retval = fread(&count, 1, sizeof count, fp_in);
	if(retval != sizeof count || count <= 0) {
		printf("### count エラー\n");
		exit(-1);
	}

	for(i = 0; i < count; i++) {
		retval = fread(&header, 1, sizeof header, fp_in);
		if(retval != sizeof header) {
			printf("### header エラー\n");
			exit(-1);
		}
		printf("#%d: %s offset=%d size=%d\n", i, header.fname, header.offset, header.size);

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

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

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

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

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

		retval = fwrite(buf, 1, header.size, fp_out);
		if(retval != header.size) {
			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");
	getchar();

	return 0;
}
