root/system/file.cc

Revision 65:4416cfac86ae, 54.5 KB (checked in by Thibaut Girka <thib@…>, 18 months ago)
Convert EUC-JP files to UTF8
Line 
1bool init_end=false;
2/*  file.cc  : KANON の圧瞮ファむル・PDT ファむル画像ファむルの展開の
3 *            ためのメ゜ッド
4 *     class ARCFILE : 曞庫ファむル党䜓を扱うクラス
5 *     class ARCINFO : 曞庫ファむルの䞭の぀のファむルを扱うクラス
6 *     class PDTCONV : PDT ファむルの展開を行う。
7 *
8 */
9
10/*
11 *
12 *  Copyright (C) 2000-   Kazunori Ueno(JAGARL) <jagarl@creator.club.ne.jp>
13 *
14 *  This program is free software; you can redistribute it and/or modify
15 *  it under the terms of the GNU General Public License as published by
16 *  the Free Software Foundation; either version 2 of the License, or
17 *  (at your option) any later version.
18 *
19 *  This program is distributed in the hope that it will be useful,
20 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 *  GNU General Public License for more details.
23 *
24 *  You should have received a copy of the GNU General Public License along
25 *  with this program; if not, write to the Free Software Foundation, Inc.,
26 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *
28*/
29
30#ifdef HAVE_CONFIG_H
31#  include "config.h"
32#endif
33
34#ifdef HAVE_MMAP
35#  ifdef MACOSX
36#    undef HAVE_MMAP
37#  endif /* MACOSX */
38#endif /* HAVE_MMAP */
39
40#include <ctype.h>
41#include <fcntl.h>
42#include <unistd.h>
43#include <stdlib.h>
44#include <stdio.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <vector>
48#include <algorithm>
49#if HAVE_MMAP
50#include <sys/mman.h>
51#endif /* HAVE_MMAP */
52#if HAVE_DIRENT_H
53# include <dirent.h>
54# define NAMLEN(dirent) strlen((dirent)->d_name)
55#else
56# define dirent direct
57# define NAMLEN(dirent) (dirent)->d_namlen
58# if HAVE_SYS_NDIR_H
59#  include <sys/ndir.h>
60# endif
61# if HAVE_SYS_DIR_H
62#  include <sys/dir.h>
63# endif
64# if HAVE_NDIR_H
65#  include <ndir.h>
66# endif
67#endif
68
69#if HAVE_LIBZ
70#include <zlib.h>
71#endif
72#if HAVE_LIBPNG
73#include <png.h>
74#endif
75#if HAVE_LIBJPEG
76extern "C" {
77#include <jpeglib.h>
78}
79#endif
80
81#include "file.h"
82#include "file_impl.h"
83
84using namespace std;
85
86// #define delete fprintf(stderr,"file.cc: %d.",__LINE__), delete
87
88/* FileSearcher class の default の振る舞い */
89FileSearcher *FileSearcher::_singleton = NULL;
90FileSearcher::ARCTYPE FileSearcher::default_is_archived[TYPEMAX] = {
91        ATYPE_DIR, ATYPE_DIR, ATYPE_DIR, ATYPE_DIR,
92        ATYPE_ARC, ATYPE_ARC, ATYPE_ARC, ATYPE_ARC,
93        ATYPE_DIR, ATYPE_DIR, ATYPE_DIR, ATYPE_DIR,
94        ATYPE_DIR, ATYPE_DIR
95};
96const char* FileSearcher::default_dirnames[TYPEMAX] = {
97        0, 0, "", "pdt", 
98        "seen.txt", "allanm.anl", "allard.ard", "allcur.cur", 
99        0, 0, "koe", "bgm", "mov", "gan"};
100
101/*********************************************
102**  ARCFILE / DIRFILE:
103**      曞庫ファむル、あるいはディレクトリの
104**      党䜓を管理するクラス
105**
106**      曞庫ファむルからファむルの抜き出しはFind()
107**      Find したものをReadするず内容が埗られる。
108*/
109
110ARCFILE::ARCFILE(const char* aname) {
111        struct stat sb;
112        /* 倉数初期化 */
113        arcname = NULL;
114        list_point = 0;
115        filenames_orig = NULL;
116        next = NULL;
117        if (aname[0] == '\0') {
118                arcname = new char[1];
119                arcname[0]='\0';
120                return;
121        } // NULFILE
122        /* ディレクトリか吊かのチェック */
123        if (stat(aname,&sb) == -1) { /* error */
124                perror("stat");
125        }
126        if ( (sb.st_mode&S_IFMT) == S_IFDIR) {
127                int l = strlen(aname);
128                arcname = new char[l+2]; strcpy(arcname, aname);
129                if (arcname[l-1] != DIR_SPLIT) {
130                        arcname[l] = DIR_SPLIT;
131                        arcname[l+1] = 0;
132                }
133        } else if ( (sb.st_mode&S_IFMT) == S_IFREG) {
134                arcname = new char[strlen(aname)+1];
135                strcpy(arcname,aname);
136                if (arcname[strlen(arcname)-1] == DIR_SPLIT)
137                        arcname[strlen(arcname)-1] = '\0';
138        }
139}
140
141void ARCFILE::Init(void) {
142        if (! arc_atom.empty()) return;
143        if (arcname == NULL) return;
144        /* ファむル数を埗る */
145        int slen = CheckFileDeal();
146        /* ファむル名のセット */
147        ListupFiles(slen);
148        if ( (!arc_atom.empty()) && arc_atom[0].filename) filenames_orig = arc_atom[0].filename;
149        sort(arc_atom.begin(), arc_atom.end());
150}
151ARCFILE::~ARCFILE() {
152        if (filenames_orig) delete[] filenames_orig;
153        delete[] arcname;
154        delete next;
155}
156
157ARCFILE::iterator ARCFILE::SearchName(const char* f, const char* ext) {
158        char buf[1024]; char buf_ext[1024];
159        iterator it;
160        Init();
161        if (f == NULL) return arc_atom.end();
162        if (arc_atom.empty()) return arc_atom.end();
163        /* ゚ラヌチェック */
164        if (strlen(f)>500) return arc_atom.end();
165        if (ext && strlen(ext)>500) return arc_atom.end();
166
167        /* 怜玢 */
168        strncpy(buf, f, 1000);
169        buf[1000]=0;
170        it = lower_bound(arc_atom.begin(), arc_atom.end(), (char*)buf);
171        if (it != arc_atom.end() && strcmp(it->filename_lower, buf) == 0) return it;
172        // 拡匵子を぀けお怜玢
173        if (ext) {
174                strcpy(buf_ext, buf);
175                char* ext_pt = strrchr(buf_ext, '.');
176                if (ext_pt == NULL || ext_pt == buf_ext) ext_pt = buf_ext + strlen(buf_ext);
177                *ext_pt++ = '.';
178                while(*ext=='.') ext++;
179                strcat(buf_ext, ext);
180                it = lower_bound(arc_atom.begin(), arc_atom.end(), (char*)buf_ext);
181                if (it != arc_atom.end() && strcmp(it->filename_lower, buf_ext) == 0) return it;
182        }
183
184        /* 小文字にしお 怜玢 */
185        int i; int l = strlen(f);
186        if (l > 500) l = 500;
187        for (i=0; i<l; i++)
188                buf[i] = tolower(f[i]);
189        buf[i++] = 0;
190        it = lower_bound(arc_atom.begin(), arc_atom.end(), (char*)buf);
191        if (it != arc_atom.end() && strcmp(it->filename_lower, buf) == 0) return it;
192
193        // 拡匵子を぀けお怜玢
194        if (ext == NULL) return arc_atom.end();
195        strcpy(buf_ext, buf);
196        char* ext_pt = strrchr(buf_ext, '.');
197        if (ext_pt == NULL || ext_pt == buf_ext) ext_pt = buf_ext + strlen(buf_ext);
198        *ext_pt++ = '.';
199        /* 拡匵子の長さを埗る */
200        l = strlen(ext);
201        for (i=0; i<l; i++)
202                ext_pt[i] = tolower(*ext++);
203        ext_pt[i] = 0;
204        it = lower_bound(arc_atom.begin(), arc_atom.end(), (char*)buf_ext);
205        if (it != arc_atom.end() && strcmp(it->filename_lower, buf_ext) == 0) return it;
206        return arc_atom.end();
207}
208
209ARCINFO* ARCFILE::Find(const char* fname, const char* ext) {
210        Init();
211        iterator atom = SearchName(fname,ext);
212        if (atom == arc_atom.end()) {
213                if (next) return next->Find(fname, ext);
214                else return NULL;
215        }
216        return MakeARCINFO(*atom);
217}
218ARCINFO* ARCFILE::MakeARCINFO(ARCFILE_ATOM& atom) {
219        if (atom.arcsize == atom.filesize)
220                return new ARCINFO(arcname, atom);
221        else // 圧瞮付
222                return new ARCINFO_AVG32(arcname, atom);
223}
224ARCINFO* NULFILE::MakeARCINFO(ARCFILE_ATOM& atom) {
225        fprintf(stderr,"NULFILE::MakeARCINFO is invalid call!\n");
226        return 0;
227}
228ARCINFO* SCN2kFILE::MakeARCINFO(ARCFILE_ATOM& atom) {
229        return new ARCINFO2k(arcname, atom);
230}
231ARCINFO* DIRFILE::MakeARCINFO(ARCFILE_ATOM& atom) {
232        char* name = atom.filename;
233        char* new_path = new char[strlen(arcname)+strlen(name)+1];
234        strcpy(new_path,arcname); strcat(new_path, name);
235        ARCINFO* ret = new ARCINFO(new_path, atom);
236        delete[] new_path;
237        return ret;
238}
239
240FILE* DIRFILE::Open(const char* fname) {
241        iterator atom = SearchName(fname);
242        if (atom == arc_atom.end()) return 0;
243        char* name = atom->filename;
244        // make FILE*
245        char* new_path = new char[strlen(arcname)+strlen(name)+1];
246        strcpy(new_path,arcname); strcat(new_path, name);
247        FILE* ret = fopen(new_path, "rb+");
248        fseek(ret, 0, SEEK_SET);
249        delete[] new_path;
250        return ret;
251}
252
253char* DIRFILE::SearchFile(const char* fname) {
254        iterator atom = SearchName(fname);
255        if (atom == arc_atom.end()) return 0;
256        char* name = atom->filename;
257        char* new_path = new char[strlen(arcname)+strlen(name)+1];
258        strcpy(new_path,arcname); strcat(new_path, name);
259        struct stat sb;
260        if (stat(new_path, &sb) == 0 &&
261                ( (sb.st_mode&S_IFMT) == S_IFREG ||
262                  (sb.st_mode&S_IFMT) == S_IFDIR)) {
263                return new_path;
264        }
265        delete[] new_path;
266        return 0;
267}
268
269void ARCFILE::ListFiles(FILE* out) {
270        Init();
271        if (arc_atom.empty()) return;
272        // list file name...
273        fprintf(out,"%16s %10s %10s %10s\n", "Filename", 
274                "pointer","arcsize", "filesize");
275        vector<ARCFILE_ATOM>::iterator it;
276        for (it=arc_atom.begin(); it!=arc_atom.end(); it++) {
277                fprintf(out,"%16s %10d %10d %10d\n",
278                        it->filename,it->offset,it->arcsize,it->filesize);
279        }
280        return;
281}
282
283void ARCFILE::InitList(void) {
284        Init();
285        list_point = 0;
286}
287char* ARCFILE::ListItem(void) {
288        if (list_point < 0) return NULL;
289        if (list_point >= arc_atom.size()) return NULL;
290        char* fname = arc_atom[list_point].filename;
291        if (fname == NULL) return NULL;
292        char* ret = new char[strlen(fname)+1];
293        strcpy(ret, fname);
294        list_point++;
295        return ret;
296}
297
298int ARCFILE::CheckFileDeal(void) {
299        char buf[0x20];
300        /* ヘッダのチェック */
301        FILE* stream = fopen(arcname, "rb");
302        if (stream == NULL) {
303                fprintf(stderr, "Cannot open archive file : %s\n",arcname);
304                return 0;
305        }
306        fseek(stream, 0, SEEK_END);
307        size_t arc_size = ftell(stream);
308        fseek(stream, 0, SEEK_SET);
309        if (arc_size < 0x20) {
310                fclose(stream);
311                return 0;
312        }
313        fread(buf, 0x20, 1, stream);
314        if (strncmp(buf, "PACL", 4) != 0) {
315                fclose(stream);
316                return 0;
317        }
318        int len = read_little_endian_int(buf+0x10);
319        if (arc_size < size_t(0x20 + len*0x20)) {
320                fclose(stream);
321                return 0;
322        }
323        int i; int slen = 0;
324        for (i=0; i<len; i++) {
325                fread(buf, 0x20, 1, stream);
326                slen += strlen(buf)+1;
327        }
328        fclose(stream);
329        return slen;
330}
331void ARCFILE::ListupFiles(int fname_len) {
332        int i; char fbuf[0x20];
333        fname_len *= 2;
334        char* buf = new char[fname_len];
335        FILE* stream = fopen(arcname, "rb");
336        if (stream == NULL) {
337                fprintf(stderr, "Cannot open archive file : %s\n",arcname);
338                return;
339        }
340        fread(fbuf,0x20,1,stream);
341        int len = read_little_endian_int(fbuf+0x10);
342        ARCFILE_ATOM atom;
343        for (i=0; i<len; i++) {
344                fread(fbuf, 0x20, 1, stream);
345                int l = strlen(fbuf);
346                if (l*2+2 > fname_len) {
347                        break;
348                }
349                atom.offset = read_little_endian_int(fbuf+0x10);
350                atom.arcsize = read_little_endian_int(fbuf+0x14);
351                atom.filesize = read_little_endian_int(fbuf+0x18);
352                int j; for (j=0; j<l; j++) {
353                        buf[j] = fbuf[j];
354                        buf[j+l+1] = tolower(fbuf[j]);
355                }
356                buf[j] = buf[j+l+1] = 0;
357                atom.filename = buf;
358                atom.filename_lower = buf+l+1;
359                arc_atom.push_back(atom);
360                buf += l*2+2; fname_len -= l*2+2;
361        }
362        fclose(stream);
363        return;
364}
365int DIRFILE::CheckFileDeal(void) {
366        DIR* dir; struct dirent* ent;
367        int flen = 0;
368        dir = opendir(arcname);
369        if (dir == NULL) {
370                fprintf(stderr, "Cannot open dir file : %s\n",arcname);
371                return 0;
372        }
373        int count = 0;
374        while( (ent = readdir(dir)) != NULL) {
375                count++;
376                flen += strlen(ent->d_name)+1;
377        }
378        closedir(dir);
379        return flen;
380}
381void DIRFILE::ListupFiles(int fname_len) {
382        DIR* dir;
383        fname_len *= 2;
384        dir = opendir(arcname);
385        if (dir == NULL) { 
386                fprintf(stderr, "Cannot open dir file : %s\n",arcname);
387                return;
388        }
389        /* 䞀時的に arcname のディレクトリに移動する */
390        int old_dir_fd = open(".",O_RDONLY);
391        if (old_dir_fd < 0) {
392                closedir(dir);
393                return;
394        }
395        if (chdir(arcname) != 0) {
396                fprintf(stderr, "Cannot open dir file : %s\n",arcname);
397                closedir(dir);
398                close(old_dir_fd);
399                return;
400        }
401
402        char* buf = new char[fname_len];
403        ARCFILE_ATOM atom;
404        struct stat sb;
405        struct dirent* ent;
406        while( (ent = readdir(dir)) != NULL) {
407                if (stat(ent->d_name, &sb) == -1) continue;
408                if ( (sb.st_mode & S_IFMT) == S_IFREG) {
409                        atom.offset = 0;
410                        atom.arcsize = sb.st_size;
411                        atom.filesize = sb.st_size;
412                } else if ( (sb.st_mode & S_IFMT) == S_IFDIR) {
413                        atom.offset = 0;
414                        atom.arcsize = atom.filesize = 0;
415                } else {
416                        continue;
417                }
418                int l = strlen(ent->d_name);
419                if (l*2+2 > fname_len) {
420                        break;
421                }
422                int j; for (j=0; j<l+1; j++) {
423                        buf[j] = ent->d_name[j];
424                        buf[j+l+1] = tolower(ent->d_name[j]);
425                }
426                atom.filename = buf; atom.filename_lower = buf+l+1;
427                arc_atom.push_back(atom);
428                buf += l*2+2; fname_len -= l*2+2;
429        }
430        /* chdir() したのを元に戻る */
431        closedir(dir);
432        fchdir(old_dir_fd); close(old_dir_fd);
433}
434
435int NULFILE::CheckFileDeal(void) {
436        return 20;
437}
438
439void NULFILE::ListupFiles(int fname_len) {
440        char* s = new char[40];
441        ARCFILE_ATOM atom;
442        atom.offset = 0; atom.arcsize = 0; atom.filesize = 0;
443        strcpy(s, "** null dummy **");
444        atom.filename = s;
445        atom.filename_lower = s;
446        arc_atom.push_back(atom);
447}
448
449int SCN2kFILE::CheckFileDeal(void) {
450        /* ヘッダのチェック */
451        FILE* stream = fopen(arcname, "rb");
452        if (stream == NULL) {
453                fprintf(stderr, "Cannot open archive file : %s\n",arcname);
454                return 0;
455        }
456        fseek(stream, 0, SEEK_END);
457        size_t arc_size = ftell(stream);
458        fseek(stream, 0, SEEK_SET);
459        if (arc_size < 10000*8) {
460                fclose(stream);
461                return 0;
462        }
463        char* buf = new char[10000*8];
464        fread(buf, 10000, 8, stream);
465        /* size == 0 のデヌタは存圚しない */
466        int count = 0;
467        int i; for (i=0; i<10000; i++) {
468                int tmp_offset = read_little_endian_int(buf+i*8);
469                int tmp_size = read_little_endian_int(buf+i*8+4);
470                if (tmp_size <= 0 || tmp_offset < 0 || tmp_offset+tmp_size > int(arc_size) ) continue;
471                count++;
472        }
473        fclose(stream);
474        delete[] buf;
475        return count*13; /* ファむル名は seenXXXX.txt だから、䞀぀12文字+null */
476}
477
478void SCN2kFILE::ListupFiles(int fname_len) {
479        FILE* stream = fopen(arcname, "rb");
480        if (stream == NULL) {
481                fprintf(stderr, "Cannot open archive file : %s\n",arcname);
482                return;
483        }
484        char* sbuf = new char[fname_len];
485        char* buf = new char[10000*8];
486        fread(buf, 10000, 8, stream);
487        fseek(stream, 0, SEEK_END);
488        size_t arc_size = ftell(stream);
489        ARCFILE_ATOM atom;
490        int i; for (i=0; i<10000; i++) {
491                char header[0x200];
492                int tmp_offset = read_little_endian_int(buf+i*8);
493                int tmp_size = read_little_endian_int(buf+i*8+4);
494                if (tmp_size <= 0 || tmp_offset < 0 || tmp_offset+tmp_size > int(arc_size) ) continue;
495                /* header を埗お圧瞮圢匏などを調べる */
496                fseek(stream, tmp_offset, SEEK_SET);
497                fread(header, 0x200, 1, stream);
498                int header_top = read_little_endian_int(header+0);
499                int file_version = read_little_endian_int(header+4);
500
501                if (file_version == 0x1adb2) ; // Little Busters!
502                else if (file_version != 0x2712) continue; /* system version が違う */
503
504                if (header_top == 0x1cc) { /* 叀い圢匏 : avg2000 */
505                        int header_size = read_little_endian_int(header+0)+read_little_endian_int(header+0x20)*4;
506                        int data_size = read_little_endian_int(header+0x24);
507                        atom.arcsize = data_size + header_size;
508                        atom.filesize = data_size + header_size;
509                        atom.private_data = header_size;
510
511                } else if (header_top == 0x1b8) { /* 初倜献䞊 */
512                        int header_size = read_little_endian_int(header+0)+read_little_endian_int(header+0x08)*4;
513                        int data_size = read_little_endian_int(header+0x0c);
514                        int compdata_size = read_little_endian_int(header+0x10);
515                        atom.arcsize = compdata_size + header_size;
516                        atom.filesize = data_size + header_size;
517                        atom.private_data = header_size;
518                       
519                } else if (header_top == 0x1d0) { /* 新しい圢匏 reallive */
520                        int header_size = read_little_endian_int(header+0x20);
521                        int data_size = read_little_endian_int(header+0x24);
522                        int compdata_size = read_little_endian_int(header+0x28);
523                        atom.arcsize = compdata_size + header_size;
524                        atom.filesize = data_size + header_size;
525                        atom.private_data = header_size;
526                } else {
527                        fprintf(stderr,"invalid header top; %x : not supported\n",header_top);
528                        continue; /* サポヌトしない圢匏 */
529                }
530
531                atom.offset = tmp_offset;
532                atom.filename = sbuf;
533                atom.filename_lower = sbuf;
534                arc_atom.push_back(atom);
535                sprintf(sbuf, "seen%04d.txt",i); sbuf += 13;
536        }
537        delete[] buf;
538        fclose(stream);
539}
540
541/********************************************************
542** KeyHolder
543*/
544
545KeyHolder* KeyHolder::_singleton = NULL;
546
547KeyHolder* KeyHolder::GetInstance(void)
548{
549        if (_singleton == NULL) _singleton = new KeyHolder;
550        return _singleton;
551}
552
553void KeyHolder::Quit(void)
554{
555        if (_singleton != NULL) {
556                delete _singleton;
557                _singleton = NULL;
558        }
559}
560
561void KeyHolder::SetKey(char new_key[16])
562{
563        unsigned short int i;
564        for (i=0; i < 16; i++)
565                key[i] = new_key[i];
566}
567
568void KeyHolder::SetKey2(char new_key[33])
569{
570        unsigned short int i;
571        char tmp[3];
572        tmp[2] = '\0';
573        for (i=0; i < 16; i++) {
574                tmp[0] = new_key[i*2];
575                tmp[1] = new_key[i*2+1];
576                key[i] = strtoul(tmp, NULL, 16);
577        }
578}
579
580void KeyHolder::GuessKey(char *regname)
581{
582        char key1[16] = {
583                0xa8, 0x28, 0xfd, 0x66,
584                0xa0, 0x23, 0x77, 0x69,
585                0xf9, 0x45, 0xf8, 0x2c,
586                0x7c, 0x00, 0xad, 0xf4
587        };
588
589        char key2[16] = {
590                0xAF, 0x2F, 0xFB, 0x6B,
591                0xAF, 0x30, 0x77, 0x17,
592                0x87, 0x48, 0xFE, 0x2C,
593                0x68, 0x1A, 0xB9, 0xF0
594        };
595
596
597        if (strcmp(regname, "KEY\\CLANNAD_FV") == 0) {
598                SetKey(key2);
599        }
600        else {
601                SetKey(key1);
602        }
603}
604
605const char * KeyHolder::GetKey(void)
606{
607        return key;
608}
609
610/********************************************************
611** FileSearcher クラスの実装
612*/
613
614FileSearcher* FileSearcher::GetInstance(void) {
615        if (_singleton == NULL) _singleton = new FileSearcher;
616        return _singleton;
617}
618
619void FileSearcher::Quit(void) {
620        if (_singleton != NULL) {
621                delete _singleton;
622                _singleton = NULL;
623        }
624}
625
626FileSearcher::FileSearcher(void) {
627        int i;
628        root_dir = NULL;
629        dat_dir = NULL;
630        for (i=0; i<TYPEMAX; i++) {
631                searcher[i] = NULL;
632                filenames[i] = default_dirnames[i];
633                is_archived[i] = default_is_archived[i];
634        }
635}
636
637FileSearcher::~FileSearcher(void) {
638        int i;
639        for (i=0; i<TYPEMAX; i++) {
640                if (filenames[i] != NULL && filenames[i] != default_dirnames[i]) delete[] filenames[i];
641                if (searcher[i] && searcher[i] != dat_dir && searcher[i] != root_dir) {
642                        delete searcher[i];
643                }
644        }
645        if (dat_dir && dat_dir != root_dir) delete dat_dir;
646        if (root_dir) delete root_dir;
647}
648
649int FileSearcher::InitRoot(char* root) {
650        /* 必芁に応じお ~/ を展開 */
651        if (root[0] == '~' && root[1] == '/') {
652                char* home = getenv("HOME");
653                if (home != NULL) {
654                        char* new_root = new char[strlen(home)+strlen(root)];
655                        strcpy(new_root, home);
656                        strcat(new_root, root+1);
657                        root = new_root;
658                }
659        }
660        /* 叀いデヌタを消す */
661        int i;
662        for (i=0; i<TYPEMAX; i++) {
663                if (searcher[i] != NULL &&
664                        searcher[i] != root_dir &&
665                        searcher[i] != dat_dir) {
666                                delete searcher[i];
667                }
668                searcher[i] = NULL;
669        }
670        if (dat_dir && root_dir != dat_dir) delete dat_dir;
671        if (root_dir) delete root_dir;
672        dat_dir = NULL;
673
674        /* 新しいディレクトリのもずで初期化 */
675        root_dir = new DIRFILE(root);
676        root_dir->Init();
677        /* dat/ を怜玢 */
678        char* dat_path = root_dir->SearchFile("dat");
679        if (dat_path == NULL) {
680                /* 芋぀からなかったら root を dat の代わりに぀かう */
681                dat_dir = root_dir;
682        } else {
683                dat_dir = new DIRFILE(dat_path);
684                delete[] dat_path;
685                dat_dir->Init();
686        }
687        searcher[ALL] = dat_dir;
688        searcher[ROOT] = root_dir;
689        return 0;
690}
691
692void FileSearcher::SetFileInformation(FILETYPE tp, ARCTYPE is_arc, char* filename) {
693        int type = tp;
694        if (type < 0 || type >= TYPEMAX) return;
695        ARCFILE* next_arc = NULL;
696        /* すでに searcher が存圚すれば解攟 */
697        if (searcher[type] != NULL &&
698          searcher[type] != root_dir &&
699          searcher[type] != dat_dir) {
700                next_arc = searcher[type]->Next();
701                delete searcher[type];
702        }
703        searcher[type] = NULL;
704        /* 適圓に初期化 */
705        if (filenames[type] != NULL &&
706                filenames[type] != default_dirnames[type]) delete[] filenames[type];
707        filenames[type] = filename;
708        is_archived[type] = is_arc;
709        searcher[type] = MakeARCFILE(is_arc, filename);
710        if (searcher[type] != NULL && next_arc)
711                searcher[type]->SetNext(next_arc);
712}
713
714void FileSearcher::AppendFileInformation(FILETYPE tp, ARCTYPE is_arc, char* filename) {
715        int type = tp;
716        if (type < 0 || type >= TYPEMAX) return;
717        /* searcher がただ割り圓おられおない堎合 */
718        if (searcher[type] == NULL ||
719          searcher[type] == root_dir ||
720          searcher[type] == dat_dir) {
721                searcher[type] = MakeARCFILE(is_archived[type], filenames[type]);
722                if (searcher[type] == NULL) { /* 䜜成できなかった堎合 */
723                        /* この型情報を FileInformation ずする */
724                        SetFileInformation(tp, is_arc, filename);
725                        return;
726                }
727        }
728        /* 初期化 */
729        ARCFILE* arc = MakeARCFILE(is_arc, filename);
730        /* append */
731        ARCFILE* cur;
732        for (cur=searcher[type]; cur->Next() != NULL; cur = cur->Next()) ;
733        cur->SetNext(arc);
734}
735
736ARCFILE* FileSearcher::MakeARCFILE(ARCTYPE tp, const char* filename) {
737        ARCFILE* arc = NULL;
738        char* file;
739        if (filename == NULL) goto err;
740        if (tp == ATYPE_DIR) {
741                file = root_dir->SearchFile(filename);
742        } else {
743                file = dat_dir->SearchFile(filename);
744                if (file == NULL)
745                        file = root_dir->SearchFile(filename);
746        }
747        if (file == NULL) goto err;
748        switch(tp) {
749                case ATYPE_DIR: arc = new DIRFILE(file); break;
750                case ATYPE_SCN2k:
751                case ATYPE_ARC: {
752                        FILE* f = fopen(file, "rb");
753                        if (f == NULL) goto err;
754                        char header[32];
755                        memset(header, 0, 32);
756                        fread(header, 32, 1, f);
757                        fclose(f);
758                        char magic_raf[8] = {'C','A','P','F',1,0,0,0};
759                        if (strncmp(header, "PACL", 4) == 0) arc = new ARCFILE(file);
760                        else arc = new SCN2kFILE(file);
761                        }
762                        break;
763                default: fprintf(stderr,"FileSearcher::MAKEARCFILE : invalid archive type; type %d name %s\n",tp,filename);
764                        delete[] file;
765                        goto err;
766        }
767        delete[] file;
768        return arc;
769err:
770        arc = new NULFILE;
771        return arc;
772}
773
774ARCINFO* FileSearcher::Find(FILETYPE type, const char* fname, const char* ext) {
775        if (searcher[type] == NULL) {
776                /* searcher 䜜成 */
777                if (filenames[type] == NULL) {
778                        searcher[type] = dat_dir;
779                } else {
780                        searcher[type] = MakeARCFILE(is_archived[type], filenames[type]);
781                        if (searcher[type] == NULL) {
782                                fprintf(stderr,"FileSearcher::Find : invalid archive type; type %d name %s\n",type,fname);
783                                return NULL;
784                        }
785                }
786        }
787        return searcher[type]->Find(fname,ext);
788}
789
790char** FileSearcher::ListAll(FILETYPE type) {
791        /* ずりあえず searcher を初期化 */
792        Find(type, "THIS FILENAME MAY NOT EXIST IN THE FILE SYSTEM !!!");
793        if (searcher[type] == NULL) return NULL;
794        /* 党ファむルのリストアップ */
795        int deal = 0;
796        ARCFILE* file;
797        for (file = searcher[type]; file != NULL; file = file->Next())
798                deal += file->Deal();
799        if (deal <= 0) return NULL;
800        char** ret_list = new char*[deal+1];
801        int count = 0;
802        for (file = searcher[type]; file != NULL; file = file->Next()) {
803                file->InitList();
804                char* f;
805                while( (f = file->ListItem() ) != 0) {
806                        ret_list[count] = new char[strlen(f)+1];
807                        strcpy(ret_list[count], f);
808                        count++;
809                }
810        }
811        ret_list[count] = NULL;
812        return ret_list;
813}
814
815ARCINFO::ARCINFO(const char* __arcname, ARCFILE_ATOM& atom) : info(atom) {
816        arcfile = new char[strlen(__arcname)+1];
817        strcpy(arcfile, __arcname);
818        use_mmap = false;
819        mmapped_memory = NULL;
820        data = NULL;
821        fd = -1;
822}
823
824ARCINFO::~ARCINFO() {
825#ifdef HAVE_MMAP
826        if (mmapped_memory) munmap(mmapped_memory, info.arcsize);
827#endif /* HAVE_MMAP */
828        if (fd != -1) close(fd);
829        if (data != mmapped_memory) delete[] data;
830        delete[] arcfile;
831}
832
833int ARCINFO::Size(void) const {
834        return info.filesize;
835}
836
837/* コピヌを返す */
838char* ARCINFO::CopyRead(void) {
839        const char* d = Read();
840        if (d == NULL) return NULL;
841        int s = Size();
842        if (s <= 0) return NULL;
843        char* ret = new char[s]; memcpy(ret, d, s);
844        return ret;
845}
846
847const char* ARCINFO::Path(void) const {
848        if (info.offset != 0) return NULL; /* archive file なのでパスを垰せない */
849        char* ret = new char[strlen(arcfile)+1];
850        strcpy(ret, arcfile);
851        return ret;
852}
853
854/* 互換性専甚 */
855FILE* ARCINFO::OpenFile(int* length) const {
856        FILE* f = fopen(arcfile, "rb");
857        if (info.offset) lseek(fileno(f), info.offset, SEEK_SET);
858        if (length) *length = info.arcsize;
859        return f;
860}
861
862// 展開凊理はなし
863bool ARCINFO::ExecExtract(void) {
864        return true;
865}
866
867/* 読み蟌みを開始する */
868const char* ARCINFO::Read(void) {
869        // すでにデヌタを読み蟌み枈みなら䜕もしない
870        if (data != NULL) return data;
871
872        if (info.offset < 0 || info.arcsize <= 0) {
873                return NULL;
874        }
875        /* ファむルを開く */
876        fd = open(arcfile, O_RDONLY);
877        if (fd < 0) {
878                return NULL;
879        }
880        if (lseek(fd, info.offset, SEEK_SET) != info.offset) {
881                close(fd);
882                fd = -1;
883                return NULL;
884        }
885        /* mmap を詊みる */
886#ifdef HAVE_MMAP
887        mmapped_memory = (char*)mmap(NULL, info.arcsize, PROT_READ, MAP_SHARED, fd, info.offset);
888        if (mmapped_memory != MAP_FAILED) {
889                use_mmap = true;
890                data = (const char*)mmapped_memory;
891        } else
892#endif /* HAVE_MMAP */
893        {
894                /* 倱敗普通にファむルを読み蟌み */
895                char* d = new char[info.arcsize];
896                read(fd, d, info.arcsize);
897                close(fd);
898                fd = -1;
899                use_mmap = false;
900                data = d;
901        }
902        /* 展開する */
903        if (! ExecExtract()) {
904                // 倱敗
905#ifdef HAVE_MMAP
906                if (use_mmap) {
907                        munmap(mmapped_memory, info.arcsize);
908                        if (data == (const char*)mmapped_memory) data = NULL;
909                }
910#endif /* HAVE_MMAP */
911                delete[] (char*)data;
912                close(fd);
913                fd = -1; data = NULL;
914                return NULL;
915        }
916#ifdef HAVE_MMAP
917        if (use_mmap && data != (const char*)mmapped_memory) {
918                // すでに mmap は必芁ない
919                munmap(mmapped_memory, info.arcsize);
920                close(fd);
921                fd = -1;
922                use_mmap = false;
923        }
924#endif /* HAVE_MMAP */
925        return data;
926}
927
928/**********************************************
929**
930**      画像展開系クラスの定矩、実装
931**
932***********************************************
933*/
934GRPCONV::GRPCONV(void) {
935        filename = NULL;
936        data = NULL;
937}
938
939GRPCONV::~GRPCONV() {
940        if (filename) delete[] filename;
941}
942
943void GRPCONV::Init(const char* f, const char* d, int dlen, int w, int h, bool is_m) {
944        if (filename) delete[] filename;
945        if (f == NULL) {
946                char* fn = new char[1];
947                fn[0] = 0;
948                filename = fn;
949        } else {
950                char* fn = new char[strlen(f)+1];
951                strcpy(fn,f);
952                filename = fn;
953        }
954
955        data = d;
956        datalen = dlen;
957        width = w;
958        height = h;
959        is_mask = is_m;
960}
961
962class PDTCONV : public GRPCONV {
963        private:
964                bool Read_PDT10(char* image);
965                bool Read_PDT11(char* image);
966        public:
967                PDTCONV(const char* _inbuf, int inlen, const char* fname);
968                ~PDTCONV() {}
969                bool Read(char* image);
970};
971
972class G00CONV : public GRPCONV {
973        private:
974                struct REGION {
975                        int x1, y1, x2, y2;
976                        int Width() { return x2-x1+1;}
977                        int Height() { return y2-y1+1;}
978                        void FixVar(int& v, int& w) {
979                                if (v < 0) v = 0;
980                                if (v >= w) v = w-1;
981                        }
982                        void Fix(int w, int h) {
983                                FixVar(x1,w);
984                                FixVar(x2,w);
985                                FixVar(y1,h);
986                                FixVar(y2,h);
987                                if (x1 > x2) x2 = x1;
988                                if (y1 > y2) y2 = y1;
989                        }
990                };
991
992                void Copy_16bpp(char* image, int x, int y, const char* src, int bpl, int h);
993                void Copy_32bpp(char* image, int x, int y, const char* src, int bpl, int h);
994                bool Read_Type0(char* image);
995                bool Read_Type1(char* image);
996                bool Read_Type2(char* image);
997        public:
998                G00CONV(const char* _inbuf, int _inlen, const char* fname);
999                ~G00CONV() { }
1000                bool Read(char* image);
1001};
1002
1003class BMPCONV : public GRPCONV {
1004        public:
1005                BMPCONV(const char* _inbuf, int _inlen, const char* fname);
1006                ~BMPCONV() {};
1007                bool Read(char* image);
1008};
1009
1010#if HAVE_LIBPNG
1011class PNGCONV : public GRPCONV {
1012        private:
1013                const char* png_data;
1014                static void png_read(png_structp, png_bytep, png_size_t);
1015
1016        public:
1017                PNGCONV(const char* _inbuf, int _inlen, const char* fname);
1018                ~PNGCONV() {};
1019                bool Read(char* image);
1020};
1021#endif
1022
1023#if HAVE_LIBJPEG
1024class JPEGCONV : public GRPCONV {
1025        public:
1026                JPEGCONV(const char* _inbuf, int _inlen, const char* fname);
1027                ~JPEGCONV() {};
1028                bool Read(char* image);
1029                void SetupSrc(struct jpeg_decompress_struct* cinfo, const char* data, int size);
1030                static void init_source(j_decompress_ptr cinfo);
1031                static boolean fill_input_buffer(j_decompress_ptr cinfo);
1032                static void skip_input_data(j_decompress_ptr cinfo, long num_bytes);
1033                static boolean resync_to_restart(j_decompress_ptr cinfo, int desired);
1034                static void term_source(j_decompress_ptr cinf);
1035};
1036#endif
1037
1038GRPCONV* GRPCONV::AssignConverter(const char* inbuf, int inlen, const char* fname) {
1039        /* ファむルの内容に応じたコンバヌタヌを割り圓おる */
1040        GRPCONV* conv = NULL;
1041        if (inlen < 10) return NULL; /* invalid file */
1042        if (strncmp(inbuf, "PDT10", 5) == 0 || strncmp(inbuf, "PDT11", 5) == 0) { /* PDT10 or PDT11 */
1043                conv = new PDTCONV(inbuf, inlen, fname);
1044                if (conv->data == NULL) {
1045                        delete conv;
1046                        conv = NULL;
1047                }
1048        }
1049#if HAVE_LIBPNG
1050        unsigned char png_magic[4] = {0x89, 'P', 'N', 'G'};
1051        if (conv == NULL && memcmp(inbuf, png_magic,4) == 0) {
1052                conv = new PNGCONV(inbuf, inlen, fname);
1053                if (conv->data == NULL) {
1054                        delete conv;
1055                        conv = NULL;
1056                }
1057        }
1058#endif
1059#if HAVE_LIBJPEG
1060        if ( conv == NULL && *(unsigned char*)inbuf == 0xff && *(unsigned char*)(inbuf+1) == 0xd8 &&
1061                (strncmp(inbuf+6, "JFIF",4) == 0 || strncmp(inbuf+6,"Exif",4) == 0)) {
1062                conv = new JPEGCONV(inbuf, inlen, fname);
1063                if (conv->data == NULL) {
1064                        delete conv;
1065                        conv = NULL;
1066                }
1067        }
1068#endif
1069        if (conv == NULL && inbuf[0]=='B' && inbuf[1]=='M' && read_little_endian_int(inbuf+10)==0x36 && read_little_endian_int(inbuf+14) == 0x28) { // Windows BMP
1070                conv = new BMPCONV(inbuf, inlen, fname);
1071                if (conv->data == NULL) {
1072                        delete conv;
1073                        conv = NULL;
1074                }
1075        }
1076        if (conv == NULL && (inbuf[0] == 0 || inbuf[0] == 1 || inbuf[0] == 2)) { /* G00 */
1077                conv = new G00CONV(inbuf, inlen, fname);
1078                if (conv->data == NULL) {
1079                        delete conv;
1080                        conv = NULL;
1081                }
1082        }
1083        return conv;
1084}
1085
1086PDTCONV::PDTCONV(const char* _inbuf, int _inlen,const char* filename) {
1087//      PDT FILE のヘッダ
1088//      +00 'PDT10'     (PDT11 は未察応)
1089//      +08 ファむルサむズ (無芖)
1090//      +0C width (ほがすべお、640)
1091//      +10 height(ほがすべお、480)
1092//      +14 (mask の) x 座暙 (実際は無芖・・・党ファむルで 0 )
1093//      +1c (mask の) y座暙 (実際は無芖 ・・・党ファむルで 0 )
1094//      +20 mask が存圚すれば、mask ぞのポむンタ
1095
1096        /* ヘッダチェック */
1097        if (_inlen < 0x20) {
1098                fprintf(stderr, "Invalid PDT file %s : size is too small\n",filename);
1099                return;
1100        }
1101        if (strncmp(_inbuf, "PDT10", 5) != 0 && strncmp(_inbuf, "PDT11", 5) != 0) {
1102                fprintf(stderr, "Invalid PDT file %s : not 'PDT10 / PDT11' file.\n", filename);
1103                return;
1104        }
1105        if (size_t(_inlen) != size_t(read_little_endian_int(_inbuf+0x08))) {
1106                fprintf(stderr, "Invalid archive file %s : invalid header.(size)\n",
1107                        filename);
1108                return;
1109        }
1110
1111        int w = read_little_endian_int(_inbuf+0x0c);
1112        int h = read_little_endian_int(_inbuf+0x10);
1113        int mask_pt = read_little_endian_int(_inbuf + 0x1c);
1114        Init(filename, _inbuf, _inlen, w, h, mask_pt ? true : false);
1115}
1116
1117
1118G00CONV::G00CONV(const char* _inbuf, int _inlen, const char* filename) {
1119//      G00 FILE のヘッダ
1120//      +00 type (1, 2)
1121//      +01: width(word)
1122//      +03: height(word)
1123//      type 1: (color table 付き LZ 圧瞮 ; PDT11 に察応)
1124//              +05: 圧瞮サむズ(dword) ; +5 するずデヌタ党䜓のサむズ
1125//              +09: 展開埌サむズ(dword)
1126//      type 2: (マスク可、画像を矩圢領域に分割しおそれぞれ圧瞮)
1127//              +05: index size
1128//              +09: index table(each size is 0x18)
1129//                      +00
1130//                     
1131//              +09+0x18*size+00: data size
1132//              +09+0x18*size+04: out size
1133//              +09+0x18*size+08: (data top)
1134//
1135
1136        /* デヌタから情報読み蟌み */
1137        int type = *_inbuf;
1138
1139        int w = read_little_endian_short(_inbuf+1);
1140        int h = read_little_endian_short(_inbuf+3);
1141        if (w < 0 || h < 0) return;
1142
1143        if (type == 0 || type == 1) { // color table 付き圧瞮
1144                if (_inlen < 13) {
1145                        fprintf(stderr, "Invalid G00 file %s : size is too small\n",filename);
1146                        return;
1147                }
1148                int data_sz = read_little_endian_int(_inbuf+5);
1149
1150                if (_inlen != data_sz+5) {
1151                        fprintf(stderr, "Invalid archive file %s : invalid header.(size)\n",
1152                                filename);
1153                        return;
1154                }
1155                Init(filename, _inbuf, _inlen, w, h, false);
1156        } else if (type == 2) { // color table なし、マスク付き可の圧瞮
1157
1158                int head_size = read_little_endian_short(_inbuf+5);
1159                if (head_size < 0 || head_size*24 > _inlen) return;
1160
1161                const char* data_top = _inbuf + 9 + head_size*24;
1162                int data_sz = read_little_endian_int(data_top);
1163                if (_inbuf + _inlen != data_top + data_sz) {
1164                        fprintf(stderr, "Invalid archive file %s : invalid header.(size)\n",
1165                                filename);
1166                        return;
1167                }
1168                Init(filename, _inbuf, _inlen, w, h, true);
1169        }
1170        return;
1171}
1172
1173bool G00CONV::Read(char* image) {
1174        if (data == NULL) return false;
1175        /* header 識別 */
1176        int type = *data;
1177        if (type == 0) return Read_Type0(image);
1178        else if (type == 1) return Read_Type1(image);
1179        else if (type == 2) return Read_Type2(image);
1180}
1181
1182/* 䞀般的な LZ 圧瞮の展開ルヌチン */
1183/* datasize はデヌタの倧きさ、char / short / int を想定 */
1184/* datatype は Copy1Pixel (1デヌタのコピヌ)及び ExtractData(LZ 圧瞮の情報を埗る
1185** ずいうメ゜ッドを実装したクラス */
1186static int bitrev_table[256] = {
1187        0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1188        0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1189        0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1190        0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1191        0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1192        0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1193        0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1194        0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1195        0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1196        0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1197        0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1198        0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1199        0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1200        0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1201        0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1202        0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff};
1203
1204template<class DataType, class DataSize> inline int lzExtract(DataType& datatype,const char*& src, char*& dest, const char* srcend, char* destend) {
1205        int count = 0;
1206        const char* lsrcend = srcend; char* ldestend = destend;
1207        const char* lsrc = src; char* ldest = dest;
1208
1209        if (lsrc+50 < lsrcend && ldest+1024 < ldestend) {
1210                /* たず、範囲チェックを緩くしお高速なルヌチンを䜿う */
1211                lsrcend -= 50;
1212                ldestend += 1024;
1213                while (ldest < ldestend && lsrc < lsrcend) {
1214                        count += 8;
1215                        int flag = int(*(unsigned char*)lsrc++);
1216                        if (datatype.IsRev()) flag = bitrev_table[flag];
1217                        int i; for (i=0; i<8; i++) {
1218                                if (flag & 0x80) {
1219                                        datatype.Copy1Pixel(lsrc, ldest);
1220                                } else {
1221                                        int data, size;
1222                                        datatype.ExtractData(lsrc, data, size);
1223                                        DataSize* p_dest = ((DataSize*)ldest) - data;
1224                                        int k; for (k=0; k<size; k++) {
1225                                                p_dest[data] = *p_dest;
1226                                                p_dest++;
1227                                        }
1228                                        ldest += size*sizeof(DataSize);
1229                                }
1230                                flag <<= 1;
1231                        }
1232                }
1233                lsrcend += 50;
1234                ldestend += 1024;
1235        }
1236        /* 残りを倉換 */
1237        while (ldest < ldestend && lsrc < lsrcend) {
1238                count += 8;
1239                int flag = int(*(unsigned char*)lsrc++);
1240                if (datatype.IsRev()) flag = bitrev_table[flag];
1241                int i; for (i=0; i<8 && ldest < ldestend && lsrc < lsrcend; i++) {
1242                        if (flag & 0x80) {
1243                                datatype.Copy1Pixel(lsrc, ldest);
1244                        } else {
1245                                int data, size;
1246                                datatype.ExtractData(lsrc, data, size);
1247                                DataSize* p_dest = ((DataSize*)ldest) - data;
1248                                int k; for (k=0; k<size; k++) {
1249                                        p_dest[data] = *p_dest;
1250                                        p_dest++;
1251                                }
1252                                ldest += size*sizeof(DataSize);
1253                        }
1254                        flag <<= 1;
1255                }
1256        }
1257        dest=ldest; src=lsrc;
1258        return 0;
1259}
1260
1261/* 匕数を枛らすためのwrapper */
1262template<class DataType, class DataSize> inline int lzExtract(DataType datatype, DataSize datasize ,const char*& src, char*& dest, const char* srcend, char* destend) {
1263        return lzExtract<DataType, DataSize>(datatype,src,dest,srcend,destend);
1264}
1265
1266/* 普通の PDT */
1267class Extract_DataType {
1268        public:
1269                static void ExtractData(const char*& lsrc, int& data, int& size) {
1270                        data = read_little_endian_short(lsrc) & 0xffff;
1271                        size = (data & 0x0f) + 1;
1272                        data = (data>>4)+1;
1273                        lsrc += 2;
1274                }
1275                static void Copy1Pixel(const char*& lsrc, char*& ldest) {
1276#ifdef WORDS_BIGENDIAN
1277                        ldest[3] = lsrc[0];
1278                        ldest[2] = lsrc[1];
1279                        ldest[1] = lsrc[2];
1280                        ldest[0] = 0;
1281#else
1282                        *(int*)ldest = read_little_endian_int(lsrc); ldest[3]=0;
1283#endif
1284                        lsrc += 3; ldest += 4;
1285                }
1286                static int IsRev(void) { return 0; }
1287};
1288
1289/* PDT11 の第䞀段階倉換 */
1290class Extract_DataType_PDT11 {
1291        private:
1292                int* index_table;
1293        public:
1294                Extract_DataType_PDT11(int* it) { index_table = it; }
1295                void ExtractData(const char*& lsrc, int& data, int& size) {
1296                        data = int(*(const unsigned char*)lsrc);
1297                        size = (data>>4) + 2;
1298                        data = index_table[data&0x0f];
1299                        lsrc++;
1300                }
1301                static void Copy1Pixel(const char*& lsrc, char*& ldest) {
1302                        *ldest = *lsrc;
1303                        ldest++; lsrc++;
1304                }
1305                static int IsRev(void) { return 0; }
1306};
1307
1308/* マスク甚 */
1309class Extract_DataType_Mask {
1310        public:
1311                void ExtractData(const char*& lsrc, int& data, int& size) {
1312                        int d = read_little_endian_short(lsrc) & 0xffff;
1313                        size = (d & 0xff) + 2;
1314                        data = (d>>8)+1;
1315                        lsrc += 2;
1316                }
1317                static void Copy1Pixel(const char*& lsrc, char*& ldest) {
1318                        *ldest = *lsrc;
1319                        ldest++; lsrc++;
1320                }
1321                static int IsRev(void) { return 0; }
1322};
1323
1324/* 曞庫甚 */
1325class Extract_DataType_ARC {
1326        public:
1327                void ExtractData(const char*& lsrc, int& data, int& size) {
1328                        data = read_little_endian_short(lsrc) & 0xffff;
1329                        size = (data&0x0f) + 2;
1330                        data = (data>>4) + 1;
1331                        lsrc+= 2;
1332                }
1333                static void Copy1Pixel(const char*& lsrc, char*& ldest) {
1334                        *ldest = *lsrc;
1335                        ldest++; lsrc++;
1336                }
1337                static int IsRev(void) { return 0; }
1338};
1339
1340/* avg2000 のシナリオ甚 */
1341class Extract_DataType_SCN2k {
1342        public:
1343                void ExtractData(const char*& lsrc, int& data, int& size) {
1344                        data = read_little_endian_short(lsrc) & 0xffff;
1345                        size = (data&0x0f) + 2;
1346                        data = (data>>4);
1347                        lsrc+= 2;
1348                }
1349                static void Copy1Pixel(const char*& lsrc, char*& ldest) {
1350                        *ldest = *lsrc;
1351                        ldest++; lsrc++;
1352                }
1353                static int IsRev(void) { return 1; }
1354};
1355
1356/* ReadLive の type0 */
1357class Extract_DataType_G00Type0 {
1358        public:
1359                static void ExtractData(const char*& lsrc, int& data, int& size) {
1360                        data = read_little_endian_short(lsrc) & 0xffff;
1361                        size = ((data & 0x0f)+ 1) * 3;
1362                        data = (data>>4) * 3;
1363                        lsrc += 2;
1364                }
1365                static void Copy1Pixel(const char*& lsrc, char*& ldest) {
1366#ifdef WORDS_BIGENDIAN
1367                        ldest[0] = lsrc[0];
1368                        ldest[1] = lsrc[1];
1369                        ldest[2] = lsrc[2];
1370#else /* LITTLE ENDIAN / intel architecture */
1371                        *(int*)ldest = *(int*)lsrc;
1372#endif
1373                        lsrc += 3; ldest += 3;
1374                }
1375                static int IsRev(void) { return 1; }
1376};
1377
1378
1379bool PDTCONV::Read(char* image) {
1380        if (data == NULL) return false;
1381
1382        if (strncmp(data, "PDT10", 5) == 0) {
1383                if (! Read_PDT10(image)) return false;
1384        } else if (strncmp(data, "PDT11", 5) == 0) {
1385                if (! Read_PDT11(image)) return false;
1386        }
1387        if (! is_mask) return true;
1388        // マスク読み蟌み
1389        int mask_pt = read_little_endian_int(data + 0x1c);
1390        char* buf = new char[width*height+1024];
1391        const char* src = data + mask_pt;
1392        const char* srcend = data + datalen;
1393        char* dest = buf;
1394        char* destend = buf + width*height;
1395        while(lzExtract(Extract_DataType_Mask(), char(), src, dest, srcend, destend)) ;
1396        int i; int len = width*height;
1397        src = buf; dest = image;
1398        for (i=0; i<len; i++) {
1399                *(int*)dest |= int(*(unsigned char*)src) << 24;
1400                src++;
1401                dest += 4;
1402        }
1403        delete[] buf;
1404        return true;
1405}
1406
1407
1408bool PDTCONV::Read_PDT10(char* image) {
1409        int mask_pt = read_little_endian_int(data + 0x1c);
1410
1411        const char* src = data + 0x20;
1412        const char* srcend;
1413        if (mask_pt == 0) srcend = data + datalen;
1414        else srcend = data + mask_pt;
1415
1416        char* dest = image;
1417        char* destend;
1418
1419        destend = image + width*height*4;
1420        while(lzExtract(Extract_DataType(), int(), src, dest, srcend, destend)) ;
1421        return true;
1422}
1423
1424bool PDTCONV::Read_PDT11(char* image) {
1425        int index_table[16];
1426        int color_table[256];
1427        int i;
1428        for (i=0; i<16; i++)
1429                index_table[i] = read_little_endian_int(data + 0x420 + i*4);
1430
1431        int mask_pt = read_little_endian_int(data + 0x1c);
1432
1433        const char* src = data + 0x460;
1434        const char* srcend;
1435        if (mask_pt == 0) srcend = data + datalen;
1436        else srcend = data + mask_pt;
1437
1438        char* dest = image;
1439        char* destend = image + width*height;
1440
1441        while(lzExtract(Extract_DataType_PDT11(index_table), char(), src, dest, srcend, destend)) ;
1442
1443        const char* cur = data + 0x20;
1444        for (i=0; i<256; i++) {
1445                color_table[i] =  read_little_endian_int(cur);
1446                cur += 4;
1447        }
1448        src = image + width*height;
1449        int* desti = (int*)(image + width*height*4);
1450        while(desti != (int*)image)
1451                *--desti = color_table[*(unsigned char*)--src];
1452        return true;
1453}
1454
1455/* dest は dest_end よりも 256 byte 以䞊先たで
1456** 曞き蟌み可胜であるこず。
1457*/
1458void ARCINFO::Extract(char*& dest_start, char*& src_start, char* dest_end, char* src_end) {
1459        const char* src = src_start;
1460        while (lzExtract(Extract_DataType_ARC(), char(), src, dest_start, src_end, dest_end)) ;
1461        src_start = (char*)src;
1462}
1463
1464void ARCINFO::Extract2k(char*& dest_start, char*& src_start, char* dest_end, char* src_end) {
1465        const char* src = src_start;
1466        while (lzExtract(Extract_DataType_SCN2k(), char(), src, dest_start, src_end, dest_end)) ;
1467        src_start = (char*)src;
1468}
1469
1470bool ARCINFO_AVG32::ExecExtract(void) {
1471        // ヘッダのチェック
1472        if (strncmp(data, "PACK", 4) != 0) return false;
1473        if (read_little_endian_int(data+8) != info.filesize) return false;
1474        if (read_little_endian_int(data+12) != info.arcsize) return false;
1475
1476        // ファむルを展開する
1477        char* ret_data = new char[info.filesize+1024];
1478
1479        const char* s = data + 0x10;
1480        const char* send = data + info.arcsize;
1481        char* d = ret_data;
1482        char* dend = ret_data + info.filesize;
1483        while(lzExtract(Extract_DataType_ARC(), char(), s, d, send, dend)) ;
1484        if (! use_mmap) delete[] data;
1485        data = ret_data;
1486        return true;
1487}
1488
1489char ARCINFO2k::decode_seed[256] ={
1490 0x8b ,0xe5 ,0x5d ,0xc3 ,0xa1 ,0xe0 ,0x30 ,0x44 ,0x00 ,0x85 ,0xc0 ,0x74 ,0x09 ,0x5f ,0x5e ,0x33
1491,0xc0 ,0x5b ,0x8b ,0xe5 ,0x5d ,0xc3 ,0x8b ,0x45 ,0x0c ,0x85 ,0xc0 ,0x75 ,0x14 ,0x8b ,0x55 ,0xec
1492,0x83 ,0xc2 ,0x20 ,0x52 ,0x6a ,0x00 ,0xe8 ,0xf5 ,0x28 ,0x01 ,0x00 ,0x83 ,0xc4 ,0x08 ,0x89 ,0x45
1493,0x0c ,0x8b ,0x45 ,0xe4 ,0x6a ,0x00 ,0x6a ,0x00 ,0x50 ,0x53 ,0xff ,0x15 ,0x34 ,0xb1 ,0x43 ,0x00
1494,0x8b ,0x45 ,0x10 ,0x85 ,0xc0 ,0x74 ,0x05 ,0x8b ,0x4d ,0xec ,0x89 ,0x08 ,0x8a ,0x45 ,0xf0 ,0x84
1495,0xc0 ,0x75 ,0x78 ,0xa1 ,0xe0 ,0x30 ,0x44 ,0x00 ,0x8b ,0x7d ,0xe8 ,0x8b ,0x75 ,0x0c ,0x85 ,0xc0
1496,0x75 ,0x44 ,0x8b ,0x1d ,0xd0 ,0xb0 ,0x43 ,0x00 ,0x85 ,0xff ,0x76 ,0x37 ,0x81 ,0xff ,0x00 ,0x00
1497,0x04 ,0x00 ,0x6a ,0x00 ,0x76 ,0x43 ,0x8b ,0x45 ,0xf8 ,0x8d ,0x55 ,0xfc ,0x52 ,0x68 ,0x00 ,0x00
1498,0x04 ,0x00 ,0x56 ,0x50 ,0xff ,0x15 ,0x2c ,0xb1 ,0x43 ,0x00 ,0x6a ,0x05 ,0xff ,0xd3 ,0xa1 ,0xe0
1499,0x30 ,0x44 ,0x00 ,0x81 ,0xef ,0x00 ,0x00 ,0x04 ,0x00 ,0x81 ,0xc6 ,0x00 ,0x00 ,0x04 ,0x00 ,0x85
1500,0xc0 ,0x74 ,0xc5 ,0x8b ,0x5d ,0xf8 ,0x53 ,0xe8 ,0xf4 ,0xfb ,0xff ,0xff ,0x8b ,0x45 ,0x0c ,0x83
1501,0xc4 ,0x04 ,0x5f ,0x5e ,0x5b ,0x8b ,0xe5 ,0x5d ,0xc3 ,0x8b ,0x55 ,0xf8 ,0x8d ,0x4d ,0xfc ,0x51
1502,0x57 ,0x56 ,0x52 ,0xff ,0x15 ,0x2c ,0xb1 ,0x43 ,0x00 ,0xeb ,0xd8 ,0x8b ,0x45 ,0xe8 ,0x83 ,0xc0
1503,0x20 ,0x50 ,0x6a ,0x00 ,0xe8 ,0x47 ,0x28 ,0x01 ,0x00 ,0x8b ,0x7d ,0xe8 ,0x89 ,0x45 ,0xf4 ,0x8b
1504,0xf0 ,0xa1 ,0xe0 ,0x30 ,0x44 ,0x00 ,0x83 ,0xc4 ,0x08 ,0x85 ,0xc0 ,0x75 ,0x56 ,0x8b ,0x1d ,0xd0
1505,0xb0 ,0x43 ,0x00 ,0x85 ,0xff ,0x76 ,0x49 ,0x81 ,0xff ,0x00 ,0x00 ,0x04 ,0x00 ,0x6a ,0x00 ,0x76};
1506
1507
1508bool ARCINFO2k::ExecExtract(void) {
1509        int i;
1510        char* ret_data = new char[info.filesize + 1024];
1511        char* decoded_data = new char[info.arcsize + 1024];
1512       
1513        /* header のコピヌ */
1514        memcpy(ret_data, data, info.private_data);
1515
1516        /* たず、xor の暗号化を解く */
1517        const char* s; const char* send;
1518        char* d; char* dend;
1519
1520        s = data + info.private_data;
1521        send = data + info.arcsize;
1522        d = decoded_data + info.private_data;
1523        dend = decoded_data + info.arcsize;
1524        i = 0;
1525        while(s != send)
1526                *d++ = *s++ ^ decode_seed[(i++)&0xff];
1527
1528        if (info.filesize == info.arcsize) {
1529                memcpy(ret_data+info.private_data, decoded_data + info.private_data + 8, info.arcsize - info.private_data - 8);
1530        } else {
1531                /* 圧瞮されおいるなら、それを展開 */
1532                s = (const char*)(decoded_data + info.private_data + 8);
1533                send = (const char*)(decoded_data + info.arcsize);
1534                d = ret_data + info.private_data;
1535                dend = ret_data + info.filesize;
1536                while(lzExtract(Extract_DataType_SCN2k(), char(), s, d, send, dend)) ;
1537        }
1538        if (read_little_endian_int(data+4) == 0x1adb2) { // Little Busters!
1539                const char *decode_key = KeyHolder::GetInstance()->GetKey();
1540                int header_size = info.private_data;
1541                for (i=0x100; i<=0x200 && header_size+i < info.filesize; i++) {
1542                        ret_data[header_size+i] ^= decode_key[i&0x0f];
1543                }
1544        }
1545        delete[] decoded_data;
1546        if (! use_mmap) delete[] data;
1547        data = ret_data;
1548        return true;
1549}
1550
1551bool G00CONV::Read_Type0(char* image) {
1552        int uncompress_size = read_little_endian_int(data+9);
1553        char* uncompress_data = new char[uncompress_size+1024];
1554
1555        // たず展開
1556        const char* src = data + 13;
1557        const char* srcend = data + datalen;
1558        char* dest = uncompress_data;
1559        char* dstend = uncompress_data + uncompress_size;
1560        while(lzExtract(Extract_DataType_G00Type0(), char(), src, dest, srcend, dstend)){};
1561        // image にコピヌ
1562        CopyRGB(image, uncompress_data);
1563        delete[] uncompress_data;
1564        return true;
1565}
1566
1567bool G00CONV::Read_Type1(char* image) {
1568        int i;
1569        int uncompress_size = read_little_endian_int(data+9) + 1;
1570        char* uncompress_data = new char[uncompress_size + 1024];
1571
1572        // たず、展開
1573        const char* src = data + 13;
1574        const char* srcend = data + datalen;
1575        char* dest = uncompress_data;
1576        char* destend = uncompress_data + uncompress_size;
1577
1578        while(lzExtract(Extract_DataType_SCN2k(), char(), src, dest, srcend, destend)){};
1579
1580        int colortable[256];
1581        memset(colortable, 0, sizeof(int)*256);
1582        int colortable_len = read_little_endian_short(uncompress_data);
1583        if (colortable_len > 256) colortable_len = 256;
1584        if (colortable_len < 0) colortable_len = 0;
1585        for (i=0; i<colortable_len; i++) {
1586                colortable[i] = read_little_endian_int(uncompress_data+2+i*4);
1587        }
1588        src = uncompress_data + 2 + read_little_endian_short(uncompress_data)*4;
1589        srcend = uncompress_data + uncompress_size;
1590        dest = image; destend = image + width*height*4;
1591        while(dest < destend && src < srcend) {
1592                *(int*)dest = colortable[*(unsigned char*)src];
1593                dest += 4; src ++;
1594        }
1595        delete[] uncompress_data;
1596        return true;
1597}
1598
1599bool G00CONV::Read_Type2(char* image) {
1600        memset(image, 0, width*height*4);
1601        /* 分割領域を埗る */
1602        int region_deal = read_little_endian_int(data+5);
1603        REGION* region_table = new REGION[region_deal];
1604
1605        const char* head = data + 9;
1606        int i; for (i=0; i<region_deal; i++) {
1607                region_table[i].x1 = read_little_endian_int(head+0);
1608                region_table[i].y1 = read_little_endian_int(head+4);
1609                region_table[i].x2 = read_little_endian_int(head+8);
1610                region_table[i].y2 = read_little_endian_int(head+12);
1611                region_table[i].Fix(width, height);
1612                head += 24;
1613        }
1614
1615        // 展開
1616        int uncompress_size = read_little_endian_int(head+4);
1617        char* uncompress_data = new char[uncompress_size + 1024];
1618
1619        const char* src = head + 8;
1620        const char* srcend = data + datalen;
1621        char* dest = uncompress_data;
1622        char* destend = uncompress_data + uncompress_size;
1623        while(lzExtract(Extract_DataType_SCN2k(), char(), src, dest, srcend, destend)){};
1624
1625        /* region_deal2 == region_deal のはず  */
1626        int region_deal2 = read_little_endian_int(uncompress_data);
1627        if (region_deal > region_deal2) region_deal = region_deal2;
1628
1629        for (i=0; i < region_deal; i++) {
1630                int offset = read_little_endian_int(uncompress_data + i*8 + 4);
1631                int length = read_little_endian_int(uncompress_data + i*8 + 8);
1632                src = (const char*)(uncompress_data + offset + 0x74);
1633                srcend = (const char*)(uncompress_data + offset + length);
1634                while(src < srcend) {
1635                        int x, y, w, h;
1636                        /* コピヌする領域を埗る */
1637                        x = read_little_endian_short(src);
1638                        y = read_little_endian_short(src+2);
1639                        w = read_little_endian_short(src+6);
1640                        h = read_little_endian_short(src+8);
1641                        src += 0x5c;
1642
1643                        x += region_table[i].x1;
1644                        y += region_table[i].y1;
1645
1646                        Copy_32bpp(image, x, y, src, w*4, h);
1647
1648                        src += w*h*4;
1649                }
1650        }
1651        delete[] uncompress_data;
1652        delete[] region_table;
1653        return true;
1654}
1655
1656void G00CONV::Copy_32bpp(char* image, int x, int y, const char* src, int bpl, int h) {
1657        int i;
1658        int* dest = (int*)(image + x*4 + y*4*width);
1659        int w = bpl / 4;
1660        for (i=0; i<h; i++) {
1661                const char* s = src;
1662                int* d = dest;
1663                int j; for (j=0; j<w; j++) {
1664                        *d++ = read_little_endian_int(s);
1665                        s += 4;
1666                }
1667                src += bpl; dest += width;
1668        }
1669}
1670
1671void GRPCONV::CopyRGBA_rev(char* image, const char* buf) {
1672        int mask = is_mask ? 0 : 0xff000000;
1673        /* 色倉換を行う */
1674        int len = width * height;
1675        int i;
1676        unsigned char* s = (unsigned char*)buf;
1677        int* d = (int*)image;
1678        for(i=0; i<len; i++) {
1679                *d = (int(s[2])) | (int(s[1])<<8) | (int(s[0])<<16) | (int(s[3])<<24) | mask;
1680                d++; s += 4;
1681        }
1682}
1683
1684void GRPCONV::CopyRGBA(char* image, const char* buf) {
1685        if (!is_mask) {
1686                CopyRGB(image, buf);
1687                return;
1688        }
1689        /* 色倉換を行う */
1690        int len = width * height;
1691        int i;
1692        int* outbuf = (int*)image;
1693        for(i=0; i<len; i++) {
1694                *outbuf++ =  read_little_endian_int(buf);
1695                buf += 4;
1696        }
1697}
1698
1699void GRPCONV::CopyRGB(char* image, const char* buf) {
1700        /* 色倉換を行う */
1701        int len = width * height;
1702        int i;
1703        unsigned char* s = (unsigned char*)buf;
1704        int* d = (int*)image;
1705        for(i=0; i<len; i++) {
1706                *d = (int(s[0])) | (int(s[1])<<8) | (int(s[2])<<16) | 0xff000000;
1707                d++; s+=3;
1708        }
1709}
1710
1711#if HAVE_LIBPNG
1712PNGCONV::PNGCONV(const char* _inbuf, int _inlen, const char* _filename) {
1713        int w,h,type;
1714        png_structp png_ptr = NULL;
1715        png_infop info_ptr = NULL;
1716        png_infop end_info = NULL;
1717
1718        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
1719        if (!png_ptr) return;
1720
1721        info_ptr = png_create_info_struct(png_ptr);
1722        if (!info_ptr) goto err;
1723
1724        end_info = png_create_info_struct(png_ptr);
1725        if (!end_info) goto err;
1726
1727        if (setjmp(png_jmpbuf(png_ptr))) {
1728                /* error occured !! */
1729                goto err;
1730        }
1731
1732        /* initialize I/O */
1733        png_data = _inbuf;
1734        png_set_read_fn(png_ptr, (png_voidp)this, &png_read);
1735
1736        png_read_info(png_ptr, info_ptr);
1737
1738        w = png_get_image_width(png_ptr, info_ptr);
1739        h = png_get_image_height(png_ptr, info_ptr);
1740        type = png_get_color_type(png_ptr, info_ptr);
1741
1742        if (type == PNG_COLOR_TYPE_GRAY || type == PNG_COLOR_TYPE_GRAY_ALPHA) goto err; // not supported
1743
1744        Init(filename, _inbuf, _inlen, w, h, type == PNG_COLOR_TYPE_RGB_ALPHA ? true : false);
1745
1746err:
1747        if (png_ptr) {
1748                if (end_info)
1749                        png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);
1750                else if (info_ptr)
1751                        png_destroy_read_struct(&png_ptr, &info_ptr,(png_infopp)0);
1752                else
1753                        png_destroy_read_struct(&png_ptr, (png_infopp) 0,(png_infopp)0);
1754        }
1755}
1756
1757bool PNGCONV::Read(char* image) {
1758        if (data == NULL) return false;
1759        bool retcode = false;
1760        int bpp = is_mask ? 4 : 3;
1761        int i;
1762        char* buf;
1763        png_bytepp row_pointers = NULL;
1764
1765        png_structp png_ptr = NULL;
1766        png_infop info_ptr = NULL;
1767        png_infop end_info = NULL;
1768
1769        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
1770        if (!png_ptr) goto err;
1771        info_ptr = png_create_info_struct(png_ptr);
1772        if (!info_ptr) goto err;
1773        end_info = png_create_info_struct(png_ptr);
1774        if (!end_info) goto err;
1775
1776        if (setjmp(png_jmpbuf(png_ptr))) {
1777                /* error occured !! */
1778                goto err;
1779        }
1780
1781        buf= new char[width*height*4];
1782        /* initialize I/O */
1783        png_data = data;
1784        png_set_read_fn(png_ptr, (png_voidp)this, &png_read);
1785       
1786        row_pointers = (png_bytepp)png_malloc(png_ptr, height*sizeof(png_bytep));
1787        for (i=0; i<height; i++) row_pointers[i] = (png_bytep)(buf + width*bpp*i);
1788        png_set_rows(png_ptr, info_ptr, row_pointers);
1789
1790        png_read_png(png_ptr, info_ptr,
1791           PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_BGR,0);
1792
1793        if (buf != image) {
1794                CopyRGBA(image, buf);
1795                delete[] buf;
1796        }
1797        png_free(png_ptr, (png_voidp)row_pointers);
1798
1799        retcode = true;
1800err:
1801        if (png_ptr) {
1802                if (end_info)
1803                        png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);
1804                else if (info_ptr)
1805                        png_destroy_read_struct(&png_ptr, &info_ptr,(png_infopp)0);
1806                else
1807                        png_destroy_read_struct(&png_ptr, (png_infopp) 0,(png_infopp)0);
1808        }
1809        return retcode;
1810}
1811
1812void PNGCONV::png_read(png_structp png_ptr, png_bytep d, png_size_t sz) {
1813        PNGCONV* orig = (PNGCONV*)png_get_io_ptr(png_ptr);
1814        memcpy(d, orig->png_data, sz);
1815        orig->png_data += sz;
1816}
1817#endif /* HAVE_LIBPNG */
1818
1819#if HAVE_LIBJPEG
1820JPEGCONV::JPEGCONV(const char* _inbuf, int _inlen, const char* _filename) {
1821        struct jpeg_decompress_struct cinfo;
1822        struct jpeg_error_mgr jerr;
1823        cinfo.err = jpeg_std_error(&jerr);
1824        jpeg_create_decompress(&cinfo);
1825        cinfo.src = new jpeg_source_mgr;
1826        SetupSrc(&cinfo, _inbuf, _inlen);
1827
1828        if (jpeg_read_header(&cinfo, TRUE) == JPEG_HEADER_OK)  {
1829                Init(filename, _inbuf, _inlen, cinfo.image_width, cinfo.image_height, false);
1830        }
1831        delete cinfo.src;
1832        cinfo.src = NULL;
1833        jpeg_destroy_decompress(&cinfo);
1834}
1835               
1836bool JPEGCONV::Read(char* image) {
1837        if (data == NULL) return false;
1838        bool retcode = false;
1839        JSAMPARRAY rows, rows_orig;
1840        int i;
1841        char* buf = NULL;
1842
1843        struct jpeg_decompress_struct cinfo;
1844        struct jpeg_error_mgr jerr;
1845        cinfo.err = jpeg_std_error(&jerr);
1846        jpeg_create_decompress(&cinfo);
1847        cinfo.src = new jpeg_source_mgr;
1848        SetupSrc(&cinfo, data, datalen);
1849
1850        if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) goto err;
1851
1852        cinfo.out_color_space = JCS_RGB;
1853       
1854        jpeg_start_decompress(&cinfo);
1855
1856        rows = new JSAMPROW[height];
1857        rows_orig = rows;
1858        buf = new char[width*height*3];
1859        for (i=0; i<height; i++) rows[i] = (JSAMPROW)(buf+width*3*i);
1860
1861        for (i=0; i<height; ) {
1862                int cnt = jpeg_read_scanlines(&cinfo, rows, height-i);
1863                rows += cnt;
1864                i += cnt;
1865        }
1866        delete[] rows_orig;
1867        CopyRGBA_rev(image, buf);
1868        delete[] buf;
1869       
1870        jpeg_finish_decompress(&cinfo);
1871        retcode = true;
1872err:
1873        delete cinfo.src;
1874        cinfo.src = NULL;
1875        jpeg_destroy_decompress(&cinfo);
1876        return retcode;
1877}
1878
1879void JPEGCONV::init_source(j_decompress_ptr cinfo) {
1880}
1881
1882boolean JPEGCONV::fill_input_buffer(j_decompress_ptr cinfo) {
1883        static char dummy[1024];
1884        memset(dummy, 0, 1024);
1885        cinfo->src->next_input_byte = (const JOCTET*)dummy;
1886        cinfo->src->bytes_in_buffer = 1024;
1887        fprintf(stderr,"JPEGCONV::fill_input_buffer: warning corrupted jpeg stream\n");
1888        return TRUE;
1889}
1890
1891void JPEGCONV::skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
1892        if (cinfo->src->bytes_in_buffer > num_bytes) {
1893                cinfo->src->next_input_byte += num_bytes;
1894                cinfo->src->bytes_in_buffer -= num_bytes;
1895        }
1896}
1897
1898boolean JPEGCONV::resync_to_restart(j_decompress_ptr cinfo, int desired) {
1899        return jpeg_resync_to_restart(cinfo, desired);
1900}
1901
1902void JPEGCONV::term_source(j_decompress_ptr cinf) {
1903}
1904
1905void JPEGCONV::SetupSrc(struct jpeg_decompress_struct* cinfo, const char* data, int size) {
1906        cinfo->src->next_input_byte = (const JOCTET*) data;
1907        cinfo->src->bytes_in_buffer = size;
1908        cinfo->src->init_source = init_source;
1909        cinfo->src->fill_input_buffer = fill_input_buffer;
1910        cinfo->src->skip_input_data = skip_input_data;
1911        cinfo->src->resync_to_restart = resync_to_restart;
1912        cinfo->src->term_source = term_source;
1913}
1914
1915#endif /* HAVE_LIBJPEG */
1916BMPCONV::BMPCONV(const char* _inbuf, int _inlen, const char* _filename) {
1917        /* デヌタから情報読み蟌み */
1918        int w = read_little_endian_int(_inbuf + 0x12);
1919        int h = read_little_endian_int(_inbuf + 0x16);
1920        if (h < 0) h = -h;
1921        int bpp = read_little_endian_short(_inbuf + 0x1c);
1922        int comp = read_little_endian_int(_inbuf + 0x1e);
1923        Init(filename, _inbuf, _inlen, w, h, bpp==32 ? true : false);
1924}
1925
1926bool BMPCONV::Read(char* image) {
1927        if (data == NULL) return false;
1928
1929        /* マスクのチェック */
1930        int bpp = read_little_endian_short(data+0x1c);
1931        int h = read_little_endian_int(data + 0x16);
1932        int dsz = read_little_endian_int(data + 0x22);
1933        bpp /= 8;
1934
1935        int bpl = dsz / height;
1936        if (bpl == 0) bpl = bpp*width;
1937        bpl = bpp * width;
1938        bpl = (bpl+3) & (~3);
1939       
1940
1941        int i;
1942        char* buf = new char[width*height*bpp+1024];
1943        const char* src = data + 0x36;
1944        char* dest = buf;
1945        if (h < 0) {
1946                for (i=0; i<height; i++) {
1947                        memcpy(dest+i*width*bpp, src+i*bpl, width*bpp);
1948                }
1949        } else {
1950                for (i=0; i<height; i++) {
1951                        memcpy(dest+i*width*bpp, src+(height-i-1)*bpl, width*bpp);
1952                }
1953        }
1954        if (bpp == 3) CopyRGB(image, buf);
1955        else /* bpp == 4 */ CopyRGBA(image, buf);
1956        delete[] buf;
1957        return true;
1958}
1959
Note: See TracBrowser for help on using the browser.