他人の空似自作物置場

touhouSE_old.zip/touhouSE_src/tnb.c

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

#define DIC_SIZE 2048

struct tnb_dictionary {
	char map[DIC_SIZE];
	int cur;
};
#define ASSERT(a) if(!(a)){printf("ASSERT ERROR:%d\n%s\n",__LINE__,#a);getchar();}

void tnb_dic_add(struct tnb_dictionary *dic, char *str, int len) {
	ASSERT(dic->cur < DIC_SIZE);
	ASSERT(dic->cur >= 0);
	ASSERT(len <= DIC_SIZE);

	if(dic->cur + len <= DIC_SIZE) {
		memcpy(&dic->map[dic->cur], str, len);
		dic->cur = (dic->cur + len) % DIC_SIZE;
	} else {
		memcpy(&dic->map[dic->cur], str, DIC_SIZE - dic->cur);
		memcpy(dic->map, &str[DIC_SIZE-dic->cur], len - (DIC_SIZE - dic->cur));
		dic->cur = len - (DIC_SIZE - dic->cur);
	}

	ASSERT(dic->cur < DIC_SIZE);
	ASSERT(dic->cur >= 0);
}
void tnb_dic_cpy_c(struct tnb_dictionary *dic, char *str, int pos) {
	ASSERT(pos >= 0);
	ASSERT(pos < DIC_SIZE);
	ASSERT(dic->cur < DIC_SIZE);
	ASSERT(dic->cur >= 0);

	*str = dic->map[pos];
	dic->map[dic->cur] = *str;
	dic->cur = (dic->cur+1)%DIC_SIZE;

	ASSERT(dic->cur < DIC_SIZE);
	ASSERT(dic->cur >= 0);
}
void tnb_dic_cpy(struct tnb_dictionary *dic, char *str, int pos, int len) {
	pos = dic->cur - pos;
	while(pos < 0){
		pos += DIC_SIZE;
	}
	while(len){
		tnb_dic_cpy_c(dic, str, pos);
		str++;
		pos = (pos+1)%DIC_SIZE;
		len--;
	}
}

#undef DIC_SIZE

void tnb_convert(unsigned char *in,int in_size,unsigned char *out, int out_size){
	struct tnb_dictionary dictionary, *dic;

	if(in_size == out_size){
		memcpy(out, in, in_size);
		return;
	}

#define IN_INC(n)	{in+=n;in_size-=n;}
#define OUT_INC(n)	{out+=n;out_size-=n;}

	dic = &dictionary;
	dic->cur = 0;
	while(in_size > 0 && out_size > 0){
		int head = *in;
		ASSERT(in_size > 1);
		IN_INC(1);
		if(head < 0x80){
			int len = head + 1;
			ASSERT(in_size >= len);
			ASSERT(out_size >= len);
			memcpy(out, in, len);
			tnb_dic_add(dic, out, len);
			IN_INC(len);
			OUT_INC(len);
		} else {
			int len = (head & 0x0F) + 3;
			int pos = *in + 1 + (256 * ((head >> 4) & 0x07));
			IN_INC(1);
			ASSERT(out_size >= len);
			tnb_dic_cpy(dic, out, pos, len);
			OUT_INC(len);
		}
	}
}

char *tnb_extract(int num){
	char *data,*out;

	data = malloc(list[num].comp_size);
	fseek(fp, list[num].addr, SEEK_SET);
	fread(data, 1, list[num].comp_size, fp);
	out = malloc(list[num].size);
	tnb_convert(data, list[num].comp_size, out, list[num].size);
	free(data);
	data = out;

	return data;
}

void tnb_ex_tga(unsigned char *data,int size,char *fn){
	int h,w;
	char filename[256];
	unsigned char *p = &data[18];

	strcpy(filename,fn);
	strcpy(&filename[strlen(filename)-4], ".png");
	w = *(unsigned short*)&data[12];
	h = *(unsigned short*)&data[14];

	if(data[1] == 0x01 && data[16] == 0x08){
		unsigned char *map;
		ASSERT(*(unsigned short*)&data[5] > 0);
		if(data[7] == 0x20){
			memcpy(pal,p,sizeof(COLOR) * *(unsigned short*)&data[5]);
			p += sizeof(COLOR) * *(unsigned short*)&data[5];
		} else if(data[7] == 0x18){
			int i = 0;
			while(i < *(unsigned short*)&data[5]){
				memcpy(&pal[i],p,3);
				p += 3;
				pal[i].alpha = 0xFF;
				i++;
			}
		} else {
			ASSERT(0);
		}
		{
			int i = 0;
			while(i < 256){
				int t = pal[i].r;
				pal[i].r = pal[i].b;
				pal[i].b = t;
				i++;
			}
		}
		map = (unsigned char*)malloc(w*h);
		if(data[2] == 0x01){
			memcpy(map,p,w*h);
		} else if(data[2] == 0x09){
			unsigned char *c = map;
			while(c < map+w*h){
				ASSERT(p < data+size);
				if(*p >= 0x80){
					unsigned char *end = c + ((*p)&0x7f) + 1;
					ASSERT(end <= map+w*h);
					p++;
					ASSERT(p < data+size);
					while(c < end){
						*c = *p;
						c++;
					}
					p++;
				} else {
					ASSERT(p <= data+size-(*p + 2));
					ASSERT(c <= map+w*h-(*p + 1));
					memcpy(c,p+1,*p + 1);
					c += *p + 1;
					p += *p + 2;
				}
			}
		} else {
			ASSERT(0);
		}
		if(!(data[17]&0x20)){
			int i = 0;
			char *temp = malloc(w);
			while(i < h/2){
				memcpy(temp,&map[w*i],w);
				memcpy(&map[w*i], &map[w*(h-i-1)],w);
				memcpy(&map[w*(h-i-1)],temp,w);
				i++;
			}
			free(temp);
		}
		if(data[17]&0x10){
			ASSERT(0);
		}
		pngout(w,h,w,map,filename,8);
		free(map);
	} else if(data[1] == 0x00){
		COLOR *map;
		map = (COLOR*)malloc(w*h*sizeof(COLOR));
		if(data[16] == 0x20){
			if(data[2] == 0x02){
				memcpy(map,p,w*h*sizeof(COLOR));
			} else if(data[2] == 0x0A){
				COLOR *c;
				c = map;
				while(c < map+w*h){
					ASSERT(p < data+size);
					if(*p >= 0x80){
						COLOR *end = c + ((*p)&0x7f) + 1;
						ASSERT(end <= map+w*h);
						p++;
						ASSERT(p < data+size);
						while(c < end){
							c->b = p[0];
							c->g = p[1];
							c->r = p[2];
							c->alpha = p[3];
							c++;
						}
						p+=4;
					} else {
						COLOR *end = c + *p + 1;
						ASSERT(p <= data+size-(*p + 2));
						ASSERT(c <= map+w*h-(*p + 1));
						p++;
						while(c < end){
							c->b = p[0];
							c->g = p[1];
							c->r = p[2];
							c->alpha = p[3];
							c++;
							p+=4;
						}
					}
				}
			} else {
				ASSERT(0);
			}
		} else if(data[16] == 0x18){
			if(data[2] == 0x02){
				int i = 0;
				while(i < w*h){
					map[i].b = p[0];
					map[i].g = p[1];
					map[i].r = p[2];
					map[i].alpha = 0xFF;
					i++;
				}
			} else if(data[2] == 0x0A){
				COLOR *c;
				c = map;
				while(c < map+w*h){
					ASSERT(p < data+size);
					if(*p >= 0x80){
						COLOR *end = c + ((*p)&0x7f) + 1;
						ASSERT(end <= map+w*h);
						p++;
						ASSERT(p < data+size);
						while(c < end){
							c->b = p[0];
							c->g = p[1];
							c->r = p[2];
							c->alpha = 0xFF;
							c++;
						}
						p+=3;
					} else {
						COLOR *end = c + *p + 1;
						ASSERT(p <= data+size-(*p + 2));
						ASSERT(c <= map+w*h-(*p + 1));
						p++;
						while(c < end){
							c->b = p[0];
							c->g = p[1];
							c->r = p[2];
							c->alpha = 0xFF;
							c++;
							p+=3;
						}
					}
				}
			} else {
				ASSERT(0);
			}
		}
		if(!(data[17]&0x20)){
			int i = 0;
			char *temp = malloc(w*sizeof(COLOR));
			while(i < h/2){
				memcpy(temp,&map[w*i],w*sizeof(COLOR));
				memcpy(&map[w*i], &map[w*(h-i-1)],w*sizeof(COLOR));
				memcpy(&map[w*(h-i-1)],temp,w*sizeof(COLOR));
				i++;
			}
			free(temp);
		}
		if(data[17]&0x10){
			ASSERT(0);
		}
		pngout(w,h,w,(char*)map,filename,32);
		free(map);
	} else {
		ASSERT(0);
	}
}

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

	if(0 == strcmp(&fn[strlen(fn)-4], ".tga")){
		tnb_ex_tga(data,size,fn);
		return;
	}

	fp = fopen2(fn,"wb");
	fwrite(data,1,size,fp);
	fclose(fp);
}


int tnb_getlist(char *filename){
	char tail[8];
	int ret;
	int addr;
	int i;

	list_free();
	ret = 0;
	fp = fopen(filename, "rb");
	if(fp == NULL){
		//printf("指定されたファイルが存在しません\n");
		ret = 1;
		goto end;
	}
	fseek(fp, 0, SEEK_END);
	dat_size = ftell(fp);
	if(dat_size < 12){
		//printf("dat構成情報を読み取れません\nファイルサイズが小さすぎます\n");
		ret = 2;
		goto end;
	}
	fseek(fp, -8, SEEK_END);
	fread(tail, 1, 8, fp);
	addr = *(int*)&tail[4] * 4;
	if(*(int *)tail != 0x00000004 || addr >= dat_size-8){//識別子じゃないけど識別子扱い
		//printf("dat形式がテンドーブレード形式ではありません\n");
		ret = 3;
		goto end;
	}
	fseek(fp, addr, SEEK_SET);
	fread(&fcount,4,1,fp);
	if(addr + 4 + fcount * 21 + 8 > dat_size){
		//printf("dat形式がテンドーブレード形式ではありません\n");
		ret = 4;
		goto end;
	}

	list = malloc(sizeof(LIST)*fcount);
	if(list == NULL){
		//printf("メモリー確保に失敗しました\n格納されたファイル数が多すぎます\n");
		ret = 5;
		goto end;
	}
	i = 0;
	while(i < fcount){
		int len;
		fread(&list[i].addr,4,1,fp);
		list[i].addr *= 4;
		fread(&list[i].comp_size,4,1,fp);
		fread(&list[i].size,4,1,fp);
		fseek(fp,4,SEEK_CUR);
		fread(&len,4,1,fp);
		fread(list[i].fn,1,len,fp);
		if(len > 99){
			free(list);
			//printf("ファイルリストが異常です(%d)\n",t);
			return 6;
		}
		list[i].fn[len] = '\0';
		i++;
	}
/*
	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;
}