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;
}