root/system/visarc.cc

Revision 65:4416cfac86ae, 7.5 KB (checked in by Thibaut Girka <thib@…>, 18 months ago)
Convert EUC-JP files to UTF8
Line 
1#define CMDNAME "visarc"
2#define VERSION "1.00"
3
4/*****************************************
5**      Visual Arts の圧瞮曞庫ファむルを
6**      展開する
7**
8**      usage : visarc x <arcfile> <file> [<file> ...]
9**              visarc l <arcfile>
10**              visarc g <arcfile> <graphic file>
11**              visarc m <arcfile> <mask file>
12**
13******************************************
14*/
15/*
16 *
17 *  Copyright (C) 2000-   Kazunori Ueno(JAGARL) <jagarl@creator.club.ne.jp>
18 *
19 *  This program is free software; you can redistribute it and/or modify
20 *  it under the terms of the GNU General Public License as published by
21 *  the Free Software Foundation; either version 2 of the License, or
22 *  (at your option) any later version.
23 *
24 *  This program is distributed in the hope that it will be useful,
25 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27 *  GNU General Public License for more details.
28 *
29 *  You should have received a copy of the GNU General Public License along
30 *  with this program; if not, write to the Free Software Foundation, Inc.,
31 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 *
33*/
34
35#ifdef HAVE_CONFIG_H
36#  include "config.h"
37#endif
38
39#include <stdio.h>
40#include <unistd.h>
41#include <string.h>
42
43// use only file subsystem
44#include "file.h"
45#include "file_impl.h"
46// #include "file.cc"
47
48#ifdef HAVE_LIBPNG
49#include <png.h>
50#endif
51
52void usage(void) {
53        fprintf(stderr, "usage : visarc <cmd> <arcfile> [<file1> [<file2> [...] ]]\n");
54        fprintf(stderr, "           cmd :   x : extract\n");
55        fprintf(stderr, "                   l : list all files\n");
56        fprintf(stderr, "\n");
57#ifdef HAVE_LIBPNG
58        fprintf(stderr, "usage2: visarc <cmd> <pdt-file> [<output-file>]\n");
59        fprintf(stderr, "           cmd     p : unpack pdt file and save as png file\n");
60#endif /* HAVE_LIBPNG */ 
61        fprintf(stderr, "\n");
62}
63
64void List(char* path) {
65        ARCFILE* file;
66        FILE* f = fopen(path, "rb");
67        if (f == NULL) return;
68        char header[32];
69        fread(header, 32, 1, f);
70        fclose(f);
71        char magic_raf[8] = {'C','A','P','F',1,0,0,0};
72        if (strncmp(header, "PACL", 4) == 0) file = new ARCFILE(path);
73        else file = new SCN2kFILE(path);
74        file->Init();
75        file->ListFiles(stdout);
76        delete file;
77}
78
79void ExtractOne(ARCFILE* arc, char* file) {
80        ARCINFO* info = arc->Find(file,"");
81        if (info == NULL) {
82                fprintf(stderr, "Cannot find file %s in archive\n",file);
83                return;
84        }
85        FILE* out = fopen(file, "w");
86        if (out == NULL) {
87                delete info;
88                fprintf(stderr, "Cannot open output file %s\n",file);
89                return;
90        }
91       
92        fprintf(stdout, "Extracting %s ... ",file);
93        int size = info->Size();
94        const char* data = info->Read();
95        fwrite(data, size, 1, out);
96        fclose(out);
97        fprintf(stdout, "done\n");
98        delete info;
99}
100
101void Extract(char* path, char** files, int fnum) {
102        ARCFILE* file;
103        FILE* f = fopen(path, "rb");
104        if (f == NULL) return;
105        char header[32];
106        fread(header, 32, 1, f);
107        fclose(f);
108        char magic_raf[8] = {'C','A','P','F',1,0,0,0};
109        if (strncmp(header, "PACL", 4) == 0) file = new ARCFILE(path);
110        else file = new SCN2kFILE(path);
111        file->Init();
112        if (files != NULL && fnum != 0) {
113                int i; for (i=0; i<fnum; i++) {
114                        ExtractOne(file, files[i]);
115                }
116        } else {
117                file->InitList();
118                char* path;
119                while( (path=file->ListItem()) != 0) {
120                        ExtractOne(file, path);
121                }
122        }
123        delete file;
124}
125
126void ChangeExt(char* path, char* new_ext, char* buf) {
127        char* name = strrchr(path, DIR_SPLIT);
128        if (name == NULL) name = path;
129        else name++;
130        int path_len = name - path;
131
132        char* ext = strrchr(name, '.');
133        int ext_len;
134        if (ext) ext_len = ext - name;
135        else ext_len = strlen(name);
136
137        strncpy(buf, path, path_len+ext_len);
138        strcpy(buf+path_len+ext_len, new_ext);
139}
140
141char* ReadFile(char* fname, int* len) {
142        FILE* in = fopen(fname, "rb");
143        if (in == NULL) return 0;
144        fseek(in, 0, SEEK_END);
145        size_t s = ftell(in);
146        fseek(in, 0, SEEK_SET);
147        char* buf = new char[s];
148        fread(buf,s,1,in);
149        fclose(in);
150        if (len) *len = s;
151        return buf;
152}
153
154
155#ifdef HAVE_LIBPNG
156void create_png(FILE* stream, char* path, char* desc, int width, int height, char* data) {
157        png_structp png_ptr;
158        png_infop info_ptr;
159
160        /* create struct */
161        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
162        if (png_ptr == NULL) return;
163
164        /* initialize information */
165        info_ptr = png_create_info_struct(png_ptr);
166        if (info_ptr == NULL) {
167                png_destroy_write_struct(&png_ptr, (png_infop*)NULL);
168                return;
169        }
170
171        if (setjmp(png_jmpbuf(png_ptr))) {
172                /* error occured !! */
173                png_destroy_write_struct(&png_ptr,&info_ptr);
174                fprintf(stderr, "Get error while processing PNG from file %s\n",path);
175                return;
176        }
177
178        /* initialize I/O (for stream) */
179        png_init_io(png_ptr, stream);
180
181        /* initialize headers */
182        png_set_IHDR(png_ptr, info_ptr,
183                width, height, 8 /* bit_dept */,
184                PNG_COLOR_TYPE_RGB_ALPHA,
185                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
186        /* create text information */
187        png_text info_text[3];
188        info_text[0].key = "Title";
189        info_text[0].text= path;
190        info_text[0].compression = PNG_TEXT_COMPRESSION_NONE;
191        info_text[1].key = "Author";
192        info_text[1].text= CMDNAME " version " VERSION;
193        info_text[1].compression = PNG_TEXT_COMPRESSION_NONE;
194        info_text[2].key = "Description";
195        info_text[2].text= desc;
196        info_text[2].compression = PNG_TEXT_COMPRESSION_NONE;
197        png_set_text(png_ptr, info_ptr, info_text, 3);
198
199        /* write information */
200        png_write_info(png_ptr, info_ptr);
201
202        /* write body */
203        /* rgba image ; input/output is 32bpp.*/
204        char* row = new char[width*4];
205        int i; for (i=0; i<height; i++) {
206                char* row_ptr = row;
207                int j; for (j=0; j<width; j++) {
208                        row_ptr[0] = data[2];
209                        row_ptr[1] = data[1];
210                        row_ptr[2] = data[0];
211                        row_ptr[3] = data[3];
212                        row_ptr += 4; data += 4;
213                }
214                png_write_rows(png_ptr, (png_byte**)&row, 1);
215        }
216        png_write_end(png_ptr, info_ptr);
217        png_destroy_write_struct(&png_ptr, &info_ptr);
218}
219
220void ExtractPngRgbaGraphic(char* path,char* outpath = 0) {
221        char buf[1024]; char* fname = buf;
222        int len;
223        char* dat = ReadFile(path, &len);
224        if (dat == NULL) {
225                fprintf(stderr, "Cannot open PDT file : %s\n",path);
226                return;
227        }
228        GRPCONV* conv = GRPCONV::AssignConverter(dat, len, path);
229        if (conv == NULL) {
230                fprintf(stderr, "Invalid format\n");
231                return;
232        }
233        bool masked = conv->IsMask();
234        char* data = new char[conv->Width() * conv->Height() * 4 + 1024];
235        if (! conv->Read(data)) {
236                fprintf(stderr, "Insufficient memory\n");
237                delete conv;
238                return;
239        }
240        if (! masked) {
241                for (int i = 0; i < conv->Width() * conv->Height(); i++) {
242                        data[4*i+3] = 0xff;     // 䞍透明床を最倧にする
243                }
244        }
245        if (outpath == NULL) ChangeExt(path,".png", buf); // path を぀くる
246        else fname = outpath;
247        FILE* out = fopen(fname, "wb"); // ファむルを開く
248        if (out == NULL) {
249                fprintf(stderr, "Cannot open raw file : %s\n",buf);
250                delete conv;
251                return;
252        }
253        create_png(out, path, "", conv->Width(), conv->Height(), data);
254        fclose(out);
255       
256        delete conv;
257}
258#endif /* HAVE_LIBPNG */
259
260int main(int argc, char* argv[]) {
261        int i; 
262        fprintf(stderr, "%s version %s\n", CMDNAME, VERSION);
263        if (argc < 3) { 
264                usage(); return -1;
265        }
266        if (strlen(argv[1]) != 1) {
267                usage(); return -1;
268        }
269        for (i=2; i<argc; i++) {
270                /* option を削る */
271                argc--;
272                int j; for (j=i; j<argc; j++) argv[j] = argv[j+1];
273        }
274        switch(argv[1][0]) {
275                case 'x': case 'X':
276                        if (argc < 4) Extract(argv[2], 0, -1);
277                        else Extract(argv[2], argv+3, argc-3);
278                        break;
279                case 'l': case 'L':
280                        List(argv[2]);
281                        break;
282#ifdef HAVE_LIBPNG
283                case 'p': case 'P':
284                case 'a': case 'A':
285                        if (argc < 4)
286                                ExtractPngRgbaGraphic(argv[2]);
287                        else
288                                ExtractPngRgbaGraphic(argv[2],argv[3]);
289                        break;
290#endif /* HAVE_LIBPNG */
291                default:
292                        usage(); return -1;
293        }
294        return 0;
295}
Note: See TracBrowser for help on using the browser.