Mercurial > otakunoraifu
annotate system/visarc.cc @ 66:d112357a0ec1
Fix a bug with savegames introduced with changeset c7bcc0ec2267.
Warning: savegames created since c7bcc0ec2267 are probably corrupted,
you may have to start the game over.
If you chose not to do so, you should replace all occurrences of 'TextWindow' by 'TextImplWindow',
and 'Text Window' by 'TextImpl Window' in your save files.
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Sat, 11 Dec 2010 18:36:20 +0100 |
parents | 4416cfac86ae |
children |
rev | line source |
---|---|
0 | 1 #define CMDNAME "visarc" |
2 #define VERSION "1.00" | |
3 | |
4 /***************************************** | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
5 ** Visual Arts の圧縮書庫ファイルを |
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
6 ** 展開する |
0 | 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 * | |
27 | 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. | |
0 | 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 | |
52 void 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 | |
64 void List(char* path) { | |
65 ARCFILE* file; | |
66 FILE* f = fopen(path, "rb"); | |
52 | 67 if (f == NULL) return; |
0 | 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 | |
79 void ExtractOne(ARCFILE* arc, char* file) { | |
80 ARCINFO* info = arc->Find(file,""); | |
52 | 81 if (info == NULL) { |
0 | 82 fprintf(stderr, "Cannot find file %s in archive\n",file); |
83 return; | |
84 } | |
85 FILE* out = fopen(file, "w"); | |
52 | 86 if (out == NULL) { |
0 | 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 | |
101 void Extract(char* path, char** files, int fnum) { | |
102 ARCFILE* file; | |
103 FILE* f = fopen(path, "rb"); | |
52 | 104 if (f == NULL) return; |
0 | 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(); | |
52 | 112 if (files != NULL && fnum != 0) { |
0 | 113 int i; for (i=0; i<fnum; i++) { |
114 ExtractOne(file, files[i]); | |
115 } | |
116 } else { | |
117 file->InitList(); | |
52 | 118 char* path; |
119 while( (path=file->ListItem()) != 0) { | |
0 | 120 ExtractOne(file, path); |
121 } | |
122 } | |
123 delete file; | |
124 } | |
125 | |
126 void ChangeExt(char* path, char* new_ext, char* buf) { | |
127 char* name = strrchr(path, DIR_SPLIT); | |
52 | 128 if (name == NULL) name = path; |
0 | 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 | |
141 char* ReadFile(char* fname, int* len) { | |
142 FILE* in = fopen(fname, "rb"); | |
52 | 143 if (in == NULL) return 0; |
144 fseek(in, 0, SEEK_END); | |
145 size_t s = ftell(in); | |
146 fseek(in, 0, SEEK_SET); | |
0 | 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 | |
156 void 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 | |
220 void ExtractPngRgbaGraphic(char* path,char* outpath = 0) { | |
221 char buf[1024]; char* fname = buf; | |
222 int len; | |
223 char* dat = ReadFile(path, &len); | |
52 | 224 if (dat == NULL) { |
0 | 225 fprintf(stderr, "Cannot open PDT file : %s\n",path); |
226 return; | |
227 } | |
228 GRPCONV* conv = GRPCONV::AssignConverter(dat, len, path); | |
52 | 229 if (conv == NULL) { |
0 | 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++) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
242 data[4*i+3] = 0xff; // 不透明度を最大にする |
0 | 243 } |
244 } | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
245 if (outpath == NULL) ChangeExt(path,".png", buf); // path をつくる |
0 | 246 else fname = outpath; |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
247 FILE* out = fopen(fname, "wb"); // ファイルを開く |
52 | 248 if (out == NULL) { |
0 | 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 | |
260 int 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++) { | |
65
4416cfac86ae
Convert EUC-JP files to UTF8
Thibaut Girka <thib@sitedethib.com>
parents:
52
diff
changeset
|
270 /* option を削る */ |
0 | 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 } |