scninfo_c

「scninfo_c」の編集履歴(バックアップ)一覧はこちら

scninfo_c」(2007/12/30 (日) 22:47:33) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

*read_uint8(FILE *f)関数  ファイルf から8ビット読み込み、返す。 *read_uint16(FILE *f)関数  ファイルf から8ビットずつ2回読み込み、順番を逆にして返す。 *read_uint24(FILE *f)関数  ファイルf から8ビットずつ3回読み込み、順番を逆にして返す。 *read_uint32(FILE *f)関数  ファイルf から8ビットずつ4回読み込み、順番を逆にして返す。 *ソースコードsource: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <inttypes.h> #ifdef USE_ICONV # include <iconv.h> #endif static int verbose = 0; static int dw_version = 1; static uint8_t read_uint8(FILE *f) { uint8_t val; fread(&val, 1, 1, f); return val; } static uint16_t read_uint16(FILE *f) { uint16_t val; uint8_t b2[2]; fread(b2, 1, 2, f); val = b2[0] + (b2[1] << 8); return val; } static uint32_t read_uint32(FILE *f) { uint32_t val; uint8_t b4[4]; fread(b4, 1, 4, f); val = b4[0] + (b4[1] << 8) + (b4[2] << 16) + (b4[3] << 24); return val; } static uint8_t *get_bitmap(uint16_t *blist, uint8_t *blocks, uint32_t nblocks, uint32_t width) { uint32_t bi, xo, yo, xi, yi, x, y, height, blocks_x; uint16_t b; uint8_t index, *bitmap; assert(blist != NULL); assert(blocks != NULL); height = (nblocks * 16 / width); blocks_x = width / 4; if(width % 4) blocks ++; printf("%dx%d\n", width, height); bitmap = calloc(width * height, sizeof(uint8_t)); for(yo = 0; yo < height; yo += 4) { for(xo = 0; xo < width; xo += 4) { for(yi = 0; yi < 4; yi ++) { if((yo + yi) >= height) break; for(xi = 0; xi < 4; xi ++) { if((xo + xi) >= width) break; x = xo + xi; y = yo + yi; bi = ((yo / 4) * blocks_x + (xo / 4)); b = blist[bi] & 0x7FFF; assert(b < nblocks); index = blocks[b * 16 + yi * 4 + xi]; bitmap[y * width + x] = index; } } } } return bitmap; } static void hexdump(FILE *f, uint32_t len, uint8_t b32) { uint32_t q, i, pos; pos = ftell(f); for(i = 0; i < len; i += 4) { if((i % 16) == 0) { if(i) printf("\n"); printf("%08x:", pos + i); } if(b32) { q = read_uint32(f); printf(" 0x%08x", q); } else { q = read_uint8(f); printf(" %02x", q); q = read_uint8(f); printf(" %02x", q); q = read_uint8(f); printf(" %02x", q); q = read_uint8(f); printf(" %02x", q); } } printf("\n"); } static uint16_t decode_16bit(uint16_t op) { return (op & 0x003F) + ((op & 0x3FC0) << 2); } static void parse_0x000A(FILE *f, uint32_t len) { uint32_t i, off; uint8_t code; uint8_t op8; uint16_t op16; uint32_t op32; uint8_t stats[256]; for(i = 0; i < 256; i++) stats[i] = 0; i = 0; off = ftell(f); while(i < len) { code = read_uint8(f); i += 1; switch(code) { /* no operand */ case 0x00: /* padding, end... */ case 0x02: case 0x03: case 0x04: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: /* DW2 */ case 0x23: case 0x24: case 0x26: case 0x27: case 0x28: case 0x29: printf("OP: [0x%08x] %02X (%dx)\n", (off + i - 1), code, ++ stats[code]); break; /* 8 bit operand */ case 0x41: case 0x4a: case 0x4c: case 0x4e: case 0x50: op8 = read_uint8(f); i += 1; printf("OP: [0x%08x] %02X 0x%02x (%dx)\n", (off + i - 2), code, op8, ++ stats[code]); break; case 0x81: case 0x8a: case 0x8c: case 0x8e: /* DW2 */ case 0x91: case 0x92: op16 = read_uint16(f); i += 2; printf("OP: [0x%08x] %02X 0x%04x (decoded: 0x%04X) (%dx)\n", (off + i - 3), code, op16, decode_16bit(op16), ++ stats[code]); break; /* 32 bit operand */ case 0x01: case 0x06: case 0x07: case 0x08: case 0x2B: /* DW2, ?? */ op32 = read_uint32(f); i += 4; printf("OP: [0x%08x] %02X 0x%08x (%dx)\n", (off + i - 5), code, op32, ++ stats[code]); break; default: printf("OP: [0x%08x] %02X (unknown opcode)\n", (int)ftell(f) - 1, code); return; break; } } } int main(int argc, char *argv[]) { FILE *f; uint16_t type; uint32_t magic; uint32_t next_offset = 0L, this_offset = 0L, flen, blen, bread; uint8_t tlen, buf[8192+1]; uint8_t palette[256][3]; uint16_t *block_list = NULL; uint32_t block_list_len; uint8_t *blocks; uint32_t blocks_num; uint16_t dump_width = 320, dump_height = 200; #ifdef USE_ICONV iconv_t icv; char *ic_outbuf, *ic_inbuf, *ic_outp, *ic_inp; size_t ic_inlen, ic_outlen = 2048; #endif memset(palette, 0, 256 * 3); if(argc < 2) { fprintf(stderr, "usage: %s <scnfile>\n", argv[0]); return EXIT_FAILURE; } if(argc > 2) { verbose = (int)strtoul(argv[2], NULL, 10); } f = fopen(argv[1], "rb"); if(f == NULL) { fprintf(stderr, "%s: error reading file '%s'\n", argv[0], argv[1]); return EXIT_FAILURE; } #ifdef USE_ICONV icv = iconv_open("utf-8", "cp1252"); #endif fseek(f, 0, SEEK_END); flen = ftell(f); /* printf("length of file: %u\n", flen); */ do { this_offset = next_offset; fseek(f, next_offset, SEEK_SET); type = read_uint16(f); magic = read_uint16(f); next_offset = read_uint32(f); if(magic != 0x3334) { fprintf(stderr, "%s: magic != 34 33 (0x3334)\n", argv[0]); break; } blen = (next_offset != 0) ? (next_offset - this_offset) : (flen - this_offset); printf("0x%8.8X: type 0x%4.4X (next: 0x%8.8X), %u (%u) bytes\n", this_offset, type, next_offset, blen, blen - 8); switch(type) { case 0x0001: /* text */ if(verbose) { uint32_t off; uint32_t local_index = 0; static uint32_t index = 0; static uint32_t chunk_index = 0; printf("DIALOGUE (0x%04X):\n", chunk_index ++); bread = 0; do { off = (uint32_t)ftell(f); tlen = read_uint8(f); bread += 1; if(tlen == 0x83) { tlen = read_uint8(f); bread += 1; } if(tlen == 0x82) { tlen = read_uint8(f); bread += 1; } if(tlen == 0x80) { tlen = read_uint8(f); bread += 1; } fread(buf, 1, tlen, f); bread += tlen; buf[tlen] = '\0'; #ifdef USE_ICONV if(tlen > 0) { ic_inlen = tlen; ic_inp = ic_inbuf = calloc(ic_inlen + 1, sizeof(char)); strcpy(ic_inbuf, (char *)buf); ic_outlen = 2048; ic_outp = ic_outbuf = calloc(ic_outlen, sizeof(char)); iconv(icv, &ic_inp, &ic_inlen, &ic_outp, &ic_outlen); strcpy((char *)buf, ic_outbuf); } #endif printf(" 0x%08x >> [%02X, 0x%04X] %s\n", off - 1, local_index ++, index, buf); #ifdef USE_ICONV if(tlen > 0) { free(ic_outbuf); free(ic_inbuf); } #endif index ++; } while(bread < (blen - 8)); } break; case 0x0003: /* block list */ { uint32_t i; block_list_len = ((blen - 8) - 8) / 2; read_uint32(f); /* blocks base */ read_uint32(f); /* unknown */ block_list = calloc(block_list_len, sizeof(uint16_t)); for(i = 0; i < block_list_len; i ++) { block_list[i] = read_uint16(f); #if 0 if(i < 10) printf("#%u: 0x%04x (0x%8.8X)\n", i, block_list[i], (unsigned int)ftell(f) - 2); #endif } printf("BLOCK LIST\n"); } break; case 0x0004: /* graphics? */ printf("GRAPHICS BLOCKS\n"); if(verbose) { FILE *pf; uint32_t i, j; uint8_t index; uint16_t width, height, bx, by; uint8_t *bitmap; pf = fopen("dump.ppm", "w"); if(pf == NULL) { fprintf(stderr, "%s: failed to write dump.ppm\n", argv[0]); break; } blocks_num = (blen - 8) / 16; blocks = calloc(blocks_num * 16, sizeof(uint8_t)); for(i = 0; i < blocks_num; i ++) { for(j = 0; j < 16; j ++) { blocks[i * 16 + j] = read_uint8(f); } } width = dump_width; height = dump_height; bx = width / 4; if(width % 4) bx ++; by = height / 4; if(height % 4) by ++; printf("bx=%u, by=%u\n", bx, by); bitmap = get_bitmap(block_list, blocks, bx * by, width); fprintf(pf, "P3\n" "# CREATOR: scninfo\n" "%u %u\n" "255\n", width, height); for(i = 0; i < (width * height); i ++) { index = bitmap[i]; fprintf(pf, "%u\n%u\n%u\n", palette[index][0], palette[index][1], palette[index][2]); } fclose(pf); } break; case 0x0005: /* palette */ printf("PALETTE\n"); if(verbose) { FILE *pf; int i; uint8_t r,g,b; char fname[2048]; sprintf(fname, "%s/.gimp-2.2/palettes/dw-%s.gpl", getenv("HOME"), "001"); pf = fopen(fname, "w"); if(pf == NULL) { fprintf(stderr, "%s: failed to write palette\n", argv[0]); break; } fprintf(pf, "GIMP Palette\n" "Name: Discworld\n" "Columns: 4\n" "#\n"); for(i = 0; i < 256; i ++) { r = read_uint8(f); g = read_uint8(f); b = read_uint8(f); read_uint8(f); /* ignored */ palette[i][0] = r; palette[i][1] = g; palette[i][2] = b; fprintf(pf, "%3u %3u %3u color%d\n", r, g, b, i); } fclose(pf); } break; case 0x0006: /* graphics descriptions */ { uint16_t i, num, width, height; uint32_t bexp; long pos; printf("GRAPHICS:\n num offset size flags?\n"); num = (blen - 8) / 16; bexp = 0; for(i = 0; i < num; i ++) { uint32_t offset; uint32_t a1, off_pal; int16_t off_x, off_y; pos = ftell(f); width = read_uint16(f); height = read_uint16(f); bexp += width * height; off_x = read_uint16(f); off_y = read_uint16(f); a1 = read_uint32(f); off_pal = read_uint32(f); if(verbose) printf("GFX: #%04d: 0x%08x, %03ux%03u " "O:%4d,%4d A:0x%08x P:0x%08x\n", i, (unsigned)pos, width, height, off_x, off_y, a1, off_pal); offset = a1 & 0x007FFFFF; if(offset == 0x18) { dump_width = width; dump_height = height; } } } break; case 0x0007: /* IMAGE LIST */ { uint16_t i, tmp1, tmp2; uint32_t off; printf("OFFSETS?:\n"); for(i = 0; i < ((blen - 8) / 8); i ++) { #if 0 off1 = read_uint16(f); off2 = read_uint16(f); #else off = read_uint32(f) & 0x7FFFFF; #endif tmp1 = read_uint16(f); tmp2 = read_uint16(f); if(verbose) printf( " #%04u: 0x%08x (0x%4.4X, 0x%4.4X)\n", i, off, tmp1, tmp2); } } break; case 0x0008: hexdump(f, (blen - 8), 1); break; case 0x000A: parse_0x000A(f, (blen - 8)); break; case 0x000B: /* some flags? */ hexdump(f, (blen - 8), 1); break; case 0x000C: /* positions? */ hexdump(f, (blen - 8), 1); break; case 0x000D: printf("SCRIPT LIST\n"); { uint32_t i, flags, id, offset; for(i = 0; i < ((blen - 8) / 12); i ++) { flags = read_uint32(f); id = read_uint32(f); offset = read_uint32(f); printf("O: %04d: 0x%08x, 0x%08x, 0x%08x\n", i, flags, id, offset); } } break; case 0x000E: /* DIRECTORY? */ hexdump(f, (blen - 8), 1); break; case 0x0011: if(dw_version == 1) { /* DW 1 */ printf("NUMBER OF OBJECTS: %d\n", read_uint32(f)); } break; case 0x0012: if(dw_version == 1) { uint32_t id, a1, a2, flags, i; printf("OBJECTS\n"); /* DW 1 */ for(i = 0; i < (blen - 8) / 16; i ++) { id = read_uint32(f); a1 = read_uint32(f); a2 = read_uint32(f); flags = read_uint32(f); if(verbose) { printf("OBJ: %03d: 0x%04x (0x%04x) " "0x%08x 0x%08x [0x%08x]\n", i, id, decode_16bit((uint16_t)(id & 0xFFFF)), a1, a2, flags); } } } break; case 0x0019: /* DW2 BITMAP */ printf("DW2 BITMAP\n"); break; default: hexdump(f, (blen - 8), 0); /* unknown */ break; } } while(next_offset != 0); fclose(f); #ifdef USE_ICONV iconv_close(icv); #endif return EXIT_SUCCESS; }
*read_uint8(FILE *f)関数  ファイルf から8ビット読み込み、返す。 *read_uint16(FILE *f)関数  ファイルf から8ビットずつ2回読み込み、順番を逆にして返す。 *read_uint24(FILE *f)関数  ファイルf から8ビットずつ3回読み込み、順番を逆にして返す。 *read_uint32(FILE *f)関数  ファイルf から8ビットずつ4回読み込み、順番を逆にして返す。 *ソースコードsource:

表示オプション

横に並べて表示:
変化行の前後のみ表示: