| 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 | |
|---|
| 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"); |
|---|
| 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 | |
|---|
| 79 | void 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 | |
|---|
| 101 | void 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 | |
|---|
| 126 | void 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 | |
|---|
| 141 | char* 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 |
|---|
| 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); |
|---|
| 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 | |
|---|
| 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++) { |
|---|
| 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 | } |
|---|