他人の空似自作物置場

touhouSE_old.zip/touhouSE_src/th105.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include "lib.h"
#include "png.h"
#include "main.h"

//本来はやってはいけない
#include "mt.c"

char pal_name[256] = "";
int cv2_flag = 1;


void th105_loadpal(char *fn,int n);
char *pal_extract(char *filename,char *pal);


/*
datのヘッダ解析および展開前準備関数
終了処理の関係上gotoを使っているが、アルゴリズム見直しのおかげでendの必要性が無くなっている。
*/
int th105_getlist(char *filename){
	int flist,size,last;
	char *str,*s;
	int i,k,t,ret;
	unsigned char len;

	list_free();
	ret = 0;
	fp = fopen(filename,"rb");
	if(fp == NULL){
		//printf("指定されたファイルが存在しません\n");
		ret = 1;
		goto end;
	}
	fseek(fp,0,SEEK_END);
	size = ftell(fp);
	if(size < 6){
		//printf("格納数を読み取れません\nファイルサイズが小さすぎます\n");
		ret = 2;
		goto end;
	}
	fseek(fp,0,SEEK_SET);
	fread(&fcount,2,1,fp);
	fread(&flist,4,1,fp);
	if(size < flist+6){
		//printf("ヘッダサイズ指定が異常です\n");
		ret = 3;
		goto end;
	}
	str = malloc(flist);
	if(str == NULL){
		//printf("メモリー確保に失敗しました\n格納されたファイル数が多すぎます\n");
		ret = 4;
		goto end;
	}
	fread(str,1,flist,fp);

	init_genrand(6+flist);
	i = 0;
	while(i < flist){
		str[i] ^= genrand_int32() & 0xff;
		i++;
	}
	i = 0;
	k = 0xC5;
	t = 0x83;
	while(i < flist){
		str[i] ^= k;
		k += t;
		t += 0x53;
		i++;
	}

	list = malloc(sizeof(struct data_list)*fcount);
	if(list == NULL){
		//printf("メモリー確保に失敗しました\n格納されたファイル数が多すぎます\n");
		ret = 5;
		goto free;
	}
	s = str;
	i = 0;
	last = 0;
	dat_size = 0;
	while(i < fcount){
		list[i].addr = *(int *)s;
		s += 4;
		list[i].size = *(int *)s;
		s += 4;
		if(list[i].addr+list[i].size > last){
			last = list[i].addr+list[i].size;
		}
		len = *s;
		s++;
		//list[i].fn = malloc(len+1);
		memcpy(list[i].fn,s,len);
		s += len;
		list[i].fn[len] = '\0';
		if(strlen(list[i].fn) != len){
			//printf("ヘッダ情報が不正です\n");
			ret = 6;
			goto free;
		}
		dat_size += list[i].size;
		i++;
	}
	if(last > size){
		//printf("指定アドレスがファイル終端を越えています\n");
		ret = 7;
		goto free;
	}
/*
	i = 0;
	while(i < fcount){
		printf("0x%08x %8d %s\n",list[i].addr,list[i].size,list[i].fn);
		i++;
	}
*/
	printf("%d個のファイルを検出しました。\n",fcount);
	strcpy(dat_name,filename);

free:
	free(str);
end:
	return ret;
}

char *th105_extract(int num){
	char *str;
	int i,k;

	fseek(fp,list[num].addr,SEEK_SET);
	str = malloc(list[num].size);
	if(str == NULL){
		printf("メモリー確保に失敗しました\n展開対象のファイルサイズが大きすぎる恐れがあります\n");
		return NULL;
	}
	fread(str,1,list[num].size,fp);
	i = 0;
	k = (list[num].addr>>1) | 0x23;
	while(i < list[num].size){
		str[i] ^= k;
		i++;
	}
	return str;
}

void th105_loadpal(char *fn,int n){
	char str[256],s[15],*data;
	int i;
	FILE *fp;

	if(n > 999 || n < 0)return;

	sprintf(s,"palette%03d.pal",n);
	strcpy(str,fn);
	i = strlen(str)-1;
	while(i >= 0 && str[i] != '\\' && str[i] != '/')i--;
	strcpy(&str[i+1],s);
	if(!strcmp(str,pal_name)){
		return;
	}
	strcpy(pal_name,str);

	i = 0;
	while(i < fcount){
		if(!strcmp(str,list[i].fn)){
			break;
		}
		i++;
	}
	if(i == fcount){
		fp = fopen(str,"rb");
		if(fp == NULL){
			data = pal_extract(dat_name,str);
		} else {
			data = malloc(768);
			fread(data,1,768,fp);
			fclose(fp);
		}
	} else {
		data = extract(i);
	}
	if(data == NULL){
		return;
	} else if(*data != 0x10){
		printf("\n不正なpalファイルです\n");
	} else {
		i = 0;
		while(i < 256){
			pal[i].b = (data[i*2+1]&0x1F) << 3;
			pal[i].g = ((data[i*2+1]&0xE0) >> 2) + ((data[i*2+2]&0x03) << 6);
			pal[i].r = (data[i*2+2]&0x7C) << 1;
			pal[i].alpha = ((data[i*2+2]&0x80)>>7)*0xFF;
			i++;
		}
	}
	free(data);
}

void ex_cv01(unsigned char *data,int len,char *fn){
	FILE *fp;
	unsigned char a,b,c;
	char str[256];
	int i;

	fp = fopen2(fn,"wb");
	if(fp == NULL){
		printf("ファイルオープンに失敗しました(ex_cv01)\n%sは出力されません\n",fn);
		return;
	}
	a = 0x8B;
	b = 0x71;
	i = 0;
	while(i < len){
		c = data[i];
		c ^= a;
		fwrite(&c,1,1,fp);
		a += b;
		b -= 0x6B;
		i++;
	}
	fclose(fp);
}

void ex_cv3(unsigned char *data,int len,char *fn){
	FILE *fp;
	unsigned int size;
	char str[256];
	int i;

	fp = fopen2(fn,"wb");
	if(fp == NULL){
		printf("ファイルオープンに失敗しました(ex_cv3)\n%sは出力されません\n",fn);
		return;
	}
	if(!strncmp(data,"RIFF",4)){				//wav to cv3
		fwrite(&data[0x14],1,0x10,fp);
		fwrite(&data[0x28],1,len-0x28,fp);
	} else {						//cv3 to wav
		size = *(unsigned int *)&data[18];		//波形データサイズを読み込む

		strncpy(str,"RIFF",4);				//WAVEファイルヘッダを生成
		*(int *)&str[4] = size + 0x24;
		strncpy(&str[8],"WAVEfmt ",8);
		*(int *)&str[16] = 0x00000010;
		fwrite(str,1,20,fp);

		memcpy(str,data,16);				//フォーマットIDから先はCV3から取り出す
		strncpy(&str[0x10],"data",4);			//拡張フォーマット部分を置き換える
		fwrite(str,1,0x14,fp);

		fwrite(&data[18],1,len-18,fp);			//EOFまで波形データ扱いで書き込み(wav終端〜EOFまで不明文字列が含まれているため)
	}
	fclose(fp);
}

void ex_cv2(unsigned char *data,int len,char *fn){
	int w,h,w2,i,l;
	COLOR *col;
	char str[256],*c;
	FILE *fp;

	str[0] = data[0];
	w2 = *(unsigned int *)&data[1];
	h = *(unsigned int *)&data[5];
	w = *(unsigned int *)&data[9];
	if(*str == 24 || *str == 32){
		if(cv2_flag){
			i = 0;
			l = 0;
			col = malloc(sizeof(COLOR)*h*w2);
			while(i < h*w2){
				col[i].b = data[17+l*4];
				col[i].g = data[17+l*4+1];
				col[i].r = data[17+l*4+2];
				col[i].alpha = data[17+l*4+3];
				i++;
				l++;
				if(i%w2==0){l+=w-w2;}
			}
			pngout(w2,h,w2,(char *)col,fn,*str);
		} else {
			i = 0;
			col = malloc(sizeof(COLOR)*h*w);
			while(i < h*w){
				col[i].b = data[17+i*4];
				col[i].g = data[17+i*4+1];
				col[i].r = data[17+i*4+2];
				col[i].alpha = data[17+i*4+3];
				i++;
			}
			pngout(w2,h,w,(char *)col,fn,*str);
		}
		free(col);
	} else if(*str == 8){
		th105_loadpal(fn,0);
		if(cv2_flag){
			i = 0;
			l = 0;
			c = malloc(h*w2);
			while(i < h*w2){
				c[i] = data[17+l];
				i++;
				l++;
				if(i%w2==0){l+=w-w2;}
			}
			pngout(w2,h,w2,c,fn,*str);
			free(c);
		} else {
			c = &data[17];
			pngout(w2,h,w,c,fn,*str);
		}
	} else {
		strcpy(str,fn);
		strcpy(&str[strlen(str)-4],".cv2");
		fp = fopen2(str,"wb");
		fwrite(data,1,len,fp);
		fclose(fp);
	}
}

char *pal_extract(char *filename,char *pal){
	char str[256],fn[256],*data;
	FILE *fp;
	int i,a;
	HANDLE hSearch;
	WIN32_FIND_DATA fd;

	strcpy(fn,filename);
	i = strlen(fn)-1;
	while(i > 0 && fn[i] != '\\' && fn[i] != '/')i--;
	fn[i] = '\0';
	sprintf(str,"%s/*.dat",fn);

	data = malloc(768);
	data[0] = 0;
	hSearch = FindFirstFile(str, &fd );
	if( hSearch == INVALID_HANDLE_VALUE )return data;
	while(1){
		sprintf(str,"pal_extract --noprint %s %s/%s",pal,fn,fd.cFileName);
		fp = _popen(str,"rb");
		a = fread(data,1,768,fp);
		_pclose(fp);
		if(a == 768){
			break;
		}
		if(!FindNextFile( hSearch, &fd )){
			if( GetLastError() == ERROR_NO_MORE_FILES ){
				break;
			}
		}
	}
	FindClose( hSearch );
	return data;
}

void th105_putfile(char *data,int size,char *fn){
	char s[256];
	FILE *fp;

	if(!strcmp(&fn[strlen(fn)-4],".cv0")){
		strcpy(s,fn);
		strcpy(&s[strlen(s)-4],".txt");
		ex_cv01(data,size,s);
	} else if(!strcmp(&fn[strlen(fn)-4],".cv1")){
		strcpy(s,fn);
		strcpy(&s[strlen(s)-4],".csv");
		ex_cv01(data,size,s);
	} else if(!strcmp(&fn[strlen(fn)-4],".cv2")){
		strcpy(s,fn);
		strcpy(&s[strlen(s)-4],".png");
		ex_cv2(data,size,s);
	} else if(!strcmp(&fn[strlen(fn)-4],".cv3")){
		strcpy(s,fn);
		strcpy(&s[strlen(s)-4],".wav");
		ex_cv3(data,size,s);
	} else {
		fp = fopen2(fn,"wb");
		fwrite(data,1,size,fp);
		fclose(fp);
	}
}
/*
int main(int argc,char *argv[]){
	int i,count,temp,size;
	char *str,*fn,s[256];
	FILE *fp;
	time_t t,a,b;

	if(argc < 2)return 0;
	SetAppDir();

	i = 1;
	while(i < argc){
		printf("%sをth105dat形式だと解釈し展開します。\n",argv[i]);
		if(0 != (temp = getlist(argv[i]))){
			printf("datの読み込みに失敗しました(エラー%d)\n",temp);
		} else {
			if(fcount)printf("ファイル展開を始めます。\n展開数");
			time(&t);
			size = 0;
			count = 0;
			while(count < fcount){
				str = extract(count);
				fn = list[count].fn;
				size += list[count].size;

				th105_putfile(str,list[count].size,fn);

				free(str);
				count++;
				time(&a);
				a = a-t;
				b = (dat_size-size)*a/size;
				printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%5d/%5d %02d:%02d(残り%02d:%02d)",count,fcount,(int)a/60,(int)a%60,(int)b/60,(int)b%60);
			}
		}
		list_free();
		printf("\n展開終了しました\n");
		i++;
	}
	printf("全ての処理が終了しました\n終了する場合はENTERを押してください\n");
	getchar();
	return 0;
}
*/