他人の空似自作物置場

touhouSE_old.zip/touhouSE_src/th075.c

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

struct th075_list{
	char fn[100];
	int size;
	int addr;
};

void load_pal(char *data){
	int i;

	if(data == NULL){
		return;
	} else {
		i = 0;
		while(i < 256){
			pal[i].b = (data[i*2]&0x1F) << 3;
			pal[i].g = ((data[i*2]&0xE0) >> 2) + ((data[i*2+1]&0x03) << 6);
			pal[i].r = (data[i*2+1]&0x7C) << 1;
			pal[i].alpha = ((data[i*2+1]&0x80)>>7)*0xFF;
			i++;
		}
	}
}

char *load_col(unsigned char *data,char cn,int w,int h,char **p){
	unsigned char *s,*str;
	COLOR *col;
	int i,size,t;

	size = w*h;
	if(cn == 32 || cn == 24){
		col = malloc(sizeof(COLOR)*size);
		s = data;
		i = 0;
		while(i < size){
			t = *(unsigned int *)&s[0];
			while(t > 0){
				col[i].b = s[4];
				col[i].g = s[5];
				col[i].r = s[6];
				if(cn==32)col[i].alpha = s[7];
				else if(cn==24)col[i].alpha = 0xff;
				i++;
				t--;
			}
			s += 8;
		}
		*p = s;
		s = (char *)col;
	} else if(cn == 16){
		col = malloc(sizeof(COLOR)*size);
		s = data;
		i = 0;
		while(i < size){
			t = *(unsigned short *)&s[0];
			while(t > 0){
				col[i].b = (s[2]&0x1F) << 3;
				col[i].g = ((s[2]&0xE0) >> 2) + ((s[3]&0x03) << 6);
				col[i].r = (s[3]&0x7C) << 1;
				col[i].alpha = ((s[3]&0x80)>>7)*0xFF;
				i++;
				t--;
			}
			s += 4;
		}
		*p = s;
		s = (char *)col;
	} else if(cn == 8){
		str = malloc(size);
		s = data;
		i = 0;
		while(i < size){
			t = *s;
			while(t > 0){
				str[i] = s[1];
				i++;
				t--;
			}
			s += 2;
		}
		*p = s;
		s = str;
	} else {
		printf("未対応の色数です(%d)\n",cn);
		s = NULL;
	}
	return s;
}

void th075img_convert(char *data,int size,char *filename){
	int w,h,i,loop,len;
	char str[512],*s,cn,fn[256];
	COLOR *col;

	strcpy(fn,filename);
/*
	i = 0;
	while(i < *data){
		load_pal(i,&data[1+i*512]);
		i++;
	}
*/
	if(*data > 0)load_pal(&data[1]);

	s = &data[1+(*data)*512];
	i = 0;
	while(s-data < size){
		w = *(int *)s;
		h = *(int *)&s[4];
		cn = s[12];
		s += 17;

		col = (COLOR *)load_col(s,cn,w,h,&s);
		if(col != NULL){
			sprintf(&fn[strlen(filename)-4],"/%02d.png",i);
			pngout(w,h,w,(char *)col,fn,cn);
			free(col);
		}
		i++;
	}
}


void th075_convert(unsigned char *data,int size,char *filename,unsigned char a,unsigned char b,unsigned char c){
	int i;
	char fn[256];
	FILE *fp;

	i = 0;
	while(i < size){
		data[i] ^= a;
		a += b;
		b += c;
		i++;
	}

	if(filename == NULL)return;
	strcpy(fn,filename);
	if(strcmp(&fn[strlen(fn)-4],".sce") == 0){
		i = strlen(fn)-1;
		while(i > 0 && fn[i] != '\\' && fn[i] != '/')i--;
		i++;
		strcpy(&fn[i],"scenario.txt");
	} else {
		strcpy(&fn[strlen(fn)-4],".txt");
	}
	fp = fopen2(fn,"wb");
	fwrite(data,1,size,fp);
	fclose(fp);
}
#define cl_convert(x,y,z)	th075_convert(x,y,z,0x60,0x61,0x41)
#define sce_convert(x,y,z)	th075_convert(x,y,z,0x63,0x62,0x42)
#define mr_convert(x,y,z)	th075_convert(x,y,z,0x5C,0x5A,0x3D)
#define index_convert(x,y)	th075_convert(x,y,NULL,0x64,0x64,0x4d)

void wave_convert(char *data,int data_size,char *filename){
	int i,size;
	char *s,head[44],fn[256],str[7];
	FILE *fp;

	strcpy(fn,filename);
	i = 0;
	s = data+4;
	while(i < *(int *)data && s-data < data_size){
		s++;
		if(*(s-1) != 0){
			size = *(int *)s;
			s += 4;
			memcpy(head,"RIFF",4);
			*(int *)&head[4] = size+36;
			memcpy(&head[8],"WAVEfmt ",8);
			*(int *)&head[16] = 0x00000010;
			memcpy(&head[20],s,16);
			s += 18;
			memcpy(&head[36],"data",4);
			*(int *)&head[40] = size;

			sprintf(str,"/%02d.wav",i);
			strcpy(&fn[strlen(filename)-4],str);
			fp = fopen2(fn,"wb");
			fwrite(head,1,44,fp);
			fwrite(s,1,size,fp);
			fclose(fp);
			s += size;
		}
		i++;
	}
}


int th075_getlist(char *filename){
	int flist,size,last;
	char *str,*s;
	int i,k,t,ret;
	unsigned char len;
	struct th075_list *tlist;

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

	list = malloc(fcount*sizeof(LIST));
	i = 0;
	while(i < fcount){
		if(strlen(list[i].fn)>99){
			free(tlist);
			ret = 8;
			goto end;
		}
		strcpy(list[i].fn,tlist[i].fn);
		list[i].size = tlist[i].size;
		list[i].addr = tlist[i].addr;
		i++;
	}
	free(tlist);

	i = 0;
	last = 0;
	dat_size = 0;
	while(i < fcount){
		if(list[i].addr+list[i].size > last){
			last = list[i].addr+list[i].size;
		}
		dat_size += list[i].size;
		i++;
	}
	if(last > size){
		//printf("指定アドレスがファイル終端を越えています\n");
		ret = 7;
		goto end;
	}
/*
	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);

end:
	return ret;
}

void th075_putfile(char *data,int size,char *fn){
	FILE *fp;

	if(strcmp(&fn[strlen(fn)-12],"cardlist.dat") == 0)cl_convert(data,size,fn);
	else if(strcmp(&fn[strlen(fn)-4],".sce") == 0)sce_convert(data,size,fn);
	else if(strcmp(&fn[strlen(fn)-13],"musicroom.dat") == 0)mr_convert(data,size,fn);
	else if(strcmp(&fn[strlen(fn)-4],".dat") == 0){
		if(strncmp(fn,"wave\\",5) == 0)wave_convert(data,size,fn);
		else th075img_convert(data,size,fn);
	} else {
		fp = fopen2(fn,"wb");
		fwrite(data,1,size,fp);
		fclose(fp);
	}
}

char *th075_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);
	return str;
}
/*
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をth075dat形式だと解釈し展開します。\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;

				th075_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;
}
*/