/* view2fontx.c code: SASANO Takayoshi ---- freeware, no warranty. [charset=EUC-JP] ●目的 MSX-View用漢字ROMのROMイメージから12×8および 12×12ドットフォントを切り出して、FONTX2形式のフォントに変換する。 ●動作条件 gccが動く環境であれば基本的に問題は無いはずですが、 intが32bitでなかったりbig-endianな環境ではどうなるか分かりません。 開発環境はFreeBSD-4.7R-i386で動くgcc-3.4.2を使っていますので、 これと似たようなものであれば動作する確率が高いと思われます。 ●コンパイル方法 gcc view2fontx.c で十分です。得られたa.outを使用して作業を行います。 ●変換対象 以下に示す、MSX-View用漢字ROMのROMイメージが変換対象となります。 MSX-View付属の漢字ROM (256Kbyte) FS-A1GT内蔵のMSX-View用漢字ROM (2048Kbyte) これら以外のものには対応していません。 ●使用方法 引数を指定せずに実行した場合は、簡単な使用方法を表示します。 実行例) uaa@rouge:~$ ./a.out usage: ./a.out [filename] uaa@rouge:~$ filenameには、ターゲットとなるROMイメージのファイル名を指定します。 ファイルが見つからなかった場合を除き、メッセージは特に表示されません。 shellなりなんなりのプロンプトに戻って、4つのファイルが生成されていれば 作業は終了です。 実行例) uaa@rouge:~$ ls a.out* gt2mb.rom uaa@rouge:~$ uaa@rouge:~$ ./a.out gt2mb.rom uaa@rouge:~$ uaa@rouge:~$ ls a.out* vgh12x12.fnt vgz12x12.fnt gt2mb.rom vgh12x8.fnt vgz12x8.fnt uaa@rouge:~$ ●生成ファイル FONTX2形式に変換されたフォントのファイル名は、 使用したROMイメージによって変わります。 ・MSX-View付属の漢字ROMを使用した場合 半角 全角 12×8 vkh12x8.fnt vkz12x8.fnt 12×12 vkh12x12.fnt vkz12x12.fnt ・FS-A1GT内蔵のMSX-View用漢字ROM を使用した場合 半角 全角 12×8 vgh12x8.fnt vgz12x8.fnt 12×12 vgh12x12.fnt vgz12x12.fnt ●制限事項 変換対象となるASCIIコード領域は、0x20〜0x7eおよび0xa0〜0xdfです。 これら以外のものに関しては対応するデータが MSX-View用漢字ROM内に存在しないため、空白としています。 よって変換結果をDOS/V等でお使いになる場合は、 必要に応じて不足する記号や罫線の類を各自で追加して下さい。 変換対象となるSJISコード領域は、このプログラム中の CodeTable_SJIS1[]およびCodeTable_SJIS2[]に記述してあります。 基本的なものに関しては変換するようになっていますが、 いわゆる機種依存文字がありそうな領域や一部の領域 (罫線や♪等の記号がある辺り)は、文字の並びが異なっていたり 空白だったりするために変換対象から外しています。 これらは必要に応じ、各自で変換対象領域の再設定や 文字コード変換テーブル等を作成して対処して下さい。 基本的には以下に示した違いを除き、 MSX-View用漢字ROMに格納されているフォントデータは同一のようです。 ・MSX-View付属の漢字ROM 12×8全角のJIS第二水準フォントはありません。 12×12半角のASCII 0x7e(~)は空白となります。 12×12全角のJIS第二水準フォントには並びのおかしな部分が 一部見られます(この部分は補正して変換を行うため、 変換結果に影響はないものと思われます)。 ・FS-A1GT内蔵のMSX-View用漢字ROM 12×8全角のJIS第二水準フォントはありません。 12×12全角のJIS第二水準フォントもありません。 ●参考文献 Let's use "MSX-View付属ROM" 第六版 (http://www.yo.rim.or.jp/~anaka/AtoC/labo/labo32.htm) FONTXテクニカルリファレンス (http://www.cfc.co.jp/lepton/fontx.html#application) 漢字コードに関する資料・SJISからJISへ (http://www.net.is.uec.ac.jp/~ueno/material/kanji/sjis2jis.html) …他、SONYの漢字コード一覧表とかMSX-Datapack Volume1とか。 ●このプログラムの取り扱いに関して このプログラム自体の使用や配布に関する条件はありません。 その代わり、不具合とか起こった場合も自分で何とかして下さい。 ていうか、どなたかもっとマトモなコンバータ作って下さいお願いします。 フォントデータだのROMイメージだのに関してうだうだ書くのは 趣味じゃないんですが、著作権が存在する以上はそれに従って下さい。 */ #include #include #include /* FONTX2 header */ #define CODETYPE_ASCII 0 #define CODETYPE_KANJI 1 /* common */ typedef struct { unsigned char identifier[6]; unsigned char fontname[8]; unsigned char xsize; unsigned char ysize; unsigned char codetype; } __attribute__((packed)) FONTX2_HEADER; /* ascii */ typedef struct { FONTX2_HEADER h; unsigned char d[1]; } __attribute__((packed)) FONTX2_ASCII; /* sjis */ typedef struct { FONTX2_HEADER h; unsigned char tnum; unsigned char d[1]; } __attribute__((packed)) FONTX2_KANJI; typedef struct { unsigned short start; unsigned short end; } __attribute__((packed)) FONTX2_CODETABLE; /* MSX-View font offsets */ #define MSXViewKROM_Offset 0x0010 typedef struct _fontoffset { int ascii_20_12x8; int ascii_a0_12x8; int jis_1_12x8; int jis_2_12x8; int ascii_20_12x12; int ascii_a0_12x12; int jis_1_12x12; int jis_2_12x12; char *fontname; char *name_ascii_12x8; char *name_jis_12x8; char *name_ascii_12x12; char *name_jis_12x12; } FontOffset; static FontOffset Offset[] = { /* MSX-View */ { 0x00024000, 0x00026880, 0x00024000, -1, 0x00002000, 0x00005cc0, 0x00002000, 0x00014000, "ViewKROM", "vkh12x8.fnt", "vkz12x8.fnt", "vkh12x12.fnt", "vkz12x12.fnt", }, /* FS-A1GT */ { 0x001c0000, 0x001c2880, 0x001c0000, -1, 0x00140000, 0x00143cc0, 0x00140000, -1, "ViewGT", "vgh12x8.fnt", "vgz12x8.fnt", "vgh12x12.fnt", "vgz12x12.fnt", }, }; static FONTX2_CODETABLE CodeTable_SJIS1[] = { {0x8140, 0x817e}, {0x8180, 0x81ac}, /* symbol */ {0x824f, 0x8258}, /* number */ {0x8260, 0x8279}, /* alphabet (large) */ {0x8281, 0x829a}, /* alphabet (small) */ {0x829f, 0x82f1}, /* hiragana */ {0x8340, 0x837e}, {0x8380, 0x8396}, /* katakana */ {0x839f, 0x83b6}, /* greek (large) */ {0x83bf, 0x83d6}, /* greek (small) */ {0x8440, 0x8460}, /* russian (large) */ {0x8470, 0x847e}, {0x8480, 0x8491}, /* russian (small) */ {0x889f, 0x88fc}, /* kanji (JIS1) */ {0x8940, 0x897e}, {0x8980, 0x89fc}, {0x8a40, 0x8a7e}, {0x8a80, 0x8afc}, {0x8b40, 0x8b7e}, {0x8b80, 0x8bfc}, {0x8c40, 0x8c7e}, {0x8c80, 0x8cfc}, {0x8d40, 0x8d7e}, {0x8d80, 0x8dfc}, {0x8e40, 0x8e7e}, {0x8e80, 0x8efc}, {0x8f40, 0x8f7e}, {0x8f80, 0x8ffc}, {0x9040, 0x907e}, {0x9080, 0x90fc}, {0x9140, 0x917e}, {0x9180, 0x91fc}, {0x9240, 0x927e}, {0x9280, 0x92fc}, {0x9340, 0x937e}, {0x9380, 0x93fc}, {0x9440, 0x947e}, {0x9480, 0x94fc}, {0x9540, 0x957e}, {0x9580, 0x95fc}, {0x9640, 0x967e}, {0x9680, 0x96fc}, {0x9740, 0x977e}, {0x9780, 0x97fc}, {0x9840, 0x9872}, }; static FONTX2_CODETABLE CodeTable_SJIS2[] = { {0x989f, 0x98fc}, /* kanji (JIS2) */ {0x9940, 0x997e}, {0x9980, 0x99fc}, {0x9a40, 0x9a7e}, {0x9a80, 0x9afc}, {0x9b40, 0x9b7e}, {0x9b80, 0x9bfc}, {0x9c40, 0x9c7e}, {0x9c80, 0x9cfc}, {0x9d40, 0x9d7e}, {0x9d80, 0x9dfc}, {0x9e40, 0x9e7e}, {0x9e80, 0x9efc}, {0x9f40, 0x9f7e}, {0x9f80, 0x9ffc}, {0xe040, 0xe07e}, {0xe080, 0xe0fc}, {0xe140, 0xe17e}, {0xe180, 0xe1fc}, {0xe240, 0xe27e}, {0xe280, 0xe2fc}, {0xe340, 0xe37e}, {0xe380, 0xe3fc}, {0xe440, 0xe47e}, {0xe480, 0xe4fc}, {0xe540, 0xe57e}, {0xe580, 0xe5fc}, {0xe640, 0xe67e}, {0xe680, 0xe6fc}, {0xe740, 0xe77e}, {0xe780, 0xe7fc}, {0xe840, 0xe87e}, {0xe880, 0xe8fc}, {0xe940, 0xe97e}, {0xe980, 0xe9fc}, {0xea40, 0xea7e}, {0xea80, 0xeaa2}, }; /* ROM data buffer, font data bufer */ #define BUFFERSIZE (2048 * 1024) static char RomData[BUFFERSIZE]; static char FontData[BUFFERSIZE]; /* misc */ #define is8dot(x) ((x) == 8) /* 2line/24bit(12bit-12bit) -> 2line/32bit(12bit-4bit-12bit-4bit) */ static void zen12_align(char *in, char *out, int line) { int i, ix_i, ix_o; for (i = ix_i = ix_o = 0; i < line / 2; i++, ix_i += 3, ix_o += 4) { out[ix_o + 0] = in[ix_i + 0]; out[ix_o + 1] = in[ix_i + 1] & 0xf0; out[ix_o + 2] = ((in[ix_i + 1] << 4) | ((in[ix_i + 2] >> 4) & 0x0f)); out[ix_o + 3] = in[ix_i + 2] << 4; } return; } /* 2line/24bit(6bit-6bit-6bit-6bit) -> 2line/16bit(6bit-2bit-6bit-2bit) */ static void han12_align(char *in, char *out, int line) { int i, ix_i, ix_o; for (i = ix_i = ix_o = 0; i < line / 2; i++, ix_i += 3, ix_o += 2) { out[ix_o + 0] = in[ix_i + 0] & 0xfc; out[ix_o + 1] = ((in[ix_i + 1] << 4) | ((in[ix_i + 2] >> 4) & 0x0f)); } return; } /* Check MSX-View ROM */ static int isViewKROM(void) { static char sign[] = "MSXViewKROM"; return !memcmp(RomData + MSXViewKROM_Offset, sign, sizeof(sign) - 1); } #if 0 /* display 16dot/line * n */ static void disp16(unsigned char *data, int line) { int i; unsigned short mask, d; for (i = 0; i < line; i++, data += 2) { d = (data[0] << 8) | data[1]; for (mask = 0x8000; mask > 0; mask >>= 1) { printf("%s", (mask & d) ? "##" : " "); } printf("\n"); } return; } /* display 8dot/line * n */ static void disp8(unsigned char *data, int line) { int i; unsigned char mask; for (i = 0; i < line; i++, data++) { for (mask = 0x80; mask > 0; mask >>= 1) { printf("%s", (mask & *data) ? "##" : " "); } printf("\n"); } return; } #endif /* SJIS -> JIS */ static int _mbcjmstojis(int jms) { int low, high; high = (jms >> 8) & 0xff; low = jms & 0xff; if (low < 0x9f) { if (high < 0xa0) { high -= 0x81; high *= 2; high += 0x21; } else { high -= 0xe0; high *= 2; high += 0x5f; } if (low > 0x7f) low--; low -= 0x1f; } else { if (high < 0xa0) { high -= 0x81; high *= 2; high += 0x22; } else { high -= 0xe0; high *= 2; high += 0x60; } low -= 0x7e; } return (high << 8) | low; } /* get kanji font pointer */ static unsigned char *get_kanji_pointer(int type, int ysize, int sjis) { int kuten, ku, ten, idx, step, offset; kuten = _mbcjmstojis(sjis) - 0x2020; ku = (kuten >> 8) & 0xff; ten = kuten & 0xff; step = is8dot(ysize) ? 12 : 18; if (ku < 48) { idx = ku * 96 + ten - (ku >= 16) * 512; offset = is8dot(ysize) ? Offset[type].jis_1_12x8 : Offset[type].jis_1_12x12; } else { idx = (ku - 48) * 96 + ten; /* bug fix for ViewKROM */ switch(ku) { case 64: if (ten < 7) idx -= 2; break; case 66: if (ten < 2) idx -= 2; break; case 84: if (ten < 5) idx -= 2; break; default: break; } offset = is8dot(ysize) ? Offset[type].jis_2_12x8 : Offset[type].jis_2_12x12; } return (offset < 0) ? NULL : (RomData + offset + step * idx); } /* copy CodeTable */ static char *copy_table(char *dst, FONTX2_CODETABLE *src, int entry) { int i; /* table must be little-endian */ for (i = 0; i < entry; i++) { *dst++ = src[i].start & 0xff; *dst++ = (src[i].start >> 8) & 0xff; *dst++ = src[i].end & 0xff; *dst++ = (src[i].end >> 8) & 0xff; } return dst; } /* convert (kanji) */ static void convert_kanji(int type, int ysize) { int i, tnum1, tnum2, sjis, chr; unsigned char *d, *ptr; FILE *fp; FONTX2_KANJI *f; if (ysize != 8 && ysize != 12) goto fin0; memset(FontData, 0, sizeof(FontData)); f = (FONTX2_KANJI *)FontData; /* JIS1 available? */ tnum1 = (get_kanji_pointer(type, ysize, 0x8140) != NULL) ? (sizeof(CodeTable_SJIS1) / sizeof(FONTX2_CODETABLE)) : 0; /* JIS2 available? */ tnum2 = (get_kanji_pointer(type, ysize, 0x989f) != NULL) ? (sizeof(CodeTable_SJIS2) / sizeof(FONTX2_CODETABLE)) : 0; /* create header */ strncpy(f->h.identifier, "FONTX2", sizeof(f->h.identifier)); strncpy(f->h.fontname, Offset[type].fontname, sizeof(f->h.fontname)); for (i = 0; i < sizeof(f->h.fontname); i++) { if (f->h.fontname[i] < 0x20) f->h.fontname[i] = 0x20; } f->h.xsize = 12; f->h.ysize = ysize; f->h.codetype = CODETYPE_KANJI; f->tnum = tnum1 + tnum2; /* make CodeTable */ d = f->d; d = copy_table(d, CodeTable_SJIS1, tnum1); d = copy_table(d, CodeTable_SJIS2, tnum2); chr = 0; /* convert font (JIS1) */ for (i = 0; i < tnum1; i++) { for (sjis = CodeTable_SJIS1[i].start; sjis <= CodeTable_SJIS1[i].end; sjis++, chr++) { ptr = get_kanji_pointer(type, ysize, sjis); if (ptr == NULL) { printf("font not found: SJIS #%x\n", sjis); } else { zen12_align(ptr, d, ysize); } d += ysize * 2; } } /* convert font (JIS2) */ for (i = 0; i < tnum2; i++) { for (sjis = CodeTable_SJIS2[i].start; sjis <= CodeTable_SJIS2[i].end; sjis++, chr++) { ptr = get_kanji_pointer(type, ysize, sjis); if (ptr == NULL) { printf("font not found: SJIS #%x\n", sjis); } else { zen12_align(ptr, d, ysize); } d += ysize * 2; } } /* save result */ fp = fopen(is8dot(ysize) ? Offset[type].name_jis_12x8 : Offset[type].name_jis_12x12, "wb"); if (fp != NULL) { fwrite(FontData, 1, (sizeof(FONTX2_HEADER) + (tnum1 + tnum2) * sizeof(FONTX2_CODETABLE) + ysize * 2 * chr + 1), fp); } fclose(fp); fin0: return; } /* convert (ASCII) */ static void convert_ascii(int type, int ysize) { int i, offset, step; FILE *fp; FONTX2_ASCII *f; if (ysize != 8 && ysize != 12) goto fin0; memset(FontData, 0, sizeof(FontData)); f = (FONTX2_ASCII *)FontData; /* create header */ strncpy(f->h.identifier, "FONTX2", sizeof(f->h.identifier)); strncpy(f->h.fontname, Offset[type].fontname, sizeof(f->h.fontname)); for (i = 0; i < sizeof(f->h.fontname); i++) { if (f->h.fontname[i] < 0x20) f->h.fontname[i] = 0x20; } f->h.xsize = 12 / 2; f->h.ysize = ysize; f->h.codetype = CODETYPE_ASCII; /* convert font (ASCII, 0x20-0x7e) */ if (is8dot(ysize)) { offset = Offset[type].ascii_20_12x8; step = 12; } else { offset = Offset[type].ascii_20_12x12; step = 18; } for (i = 0x20; offset >= 0 && i < 0x80; i++) { han12_align(RomData + offset + step * (i - 0x20), &f->d[ysize * i], ysize); } /* convert font (ASCII, 0xa0-0xdf) */ if (is8dot(ysize)) { offset = Offset[type].ascii_a0_12x8; } else { offset = Offset[type].ascii_a0_12x12; } for (i = 0xa0; offset >= 0 && i < 0xe0; i++) { han12_align(RomData + offset + step * (i - 0xa0), &f->d[ysize * i], ysize); } /* save result */ fp = fopen(is8dot(ysize) ? Offset[type].name_ascii_12x8 : Offset[type].name_ascii_12x12, "wb"); if (fp != NULL) { fwrite(FontData, 1, sizeof(FONTX2_HEADER) + 256 * ysize, fp); } fclose(fp); fin0: return; } /* convert all characters */ static void convert_font(void) { int type; type = isViewKROM() ? 0 : 1; /* convert 12x8, ASCII */ convert_ascii(type, 8); /* convert 12x12, ASCII */ convert_ascii(type, 12); /* convert 12x8, Kanji */ convert_kanji(type, 8); /* convert 12x12, Kanji */ convert_kanji(type, 12); return; } /* entry */ int main(int argc, char *argv[]) { int result; FILE *fp; if (argc < 2) { printf("usage: %s [filename]\n", argv[0]); result = EXIT_FAILURE; goto fin0; } fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("file open error\n"); result = EXIT_FAILURE; goto fin0; } memset(RomData, ~0, sizeof(RomData)); fread(RomData, 1, sizeof(RomData), fp); convert_font(); // fin1: fclose(fp); fin0: return result; }