/* * --- public domain, no warranty. */ #include #include #include #include /* FONTX2 header */ #define CODETYPE_ASCII 0 #define CODETYPE_KANJI 1 /* common */ typedef struct { uint8_t identifier[6]; uint8_t fontname[8]; uint8_t xsize; uint8_t ysize; uint8_t codetype; } __attribute__((packed)) FONTX2_HEADER; /* sjis */ typedef struct { uint16_t start; uint16_t end; } __attribute__((packed)) FONTX2_CODETABLE; 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}, }; /* font data buffer */ #define BUFFERSIZE (65536*4) static uint8_t Buf[BUFFERSIZE]; /* 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; } /* 24bit(12x2) -> 32bit(16x2) */ static void decode_kanji(uint8_t *outbuf, uint8_t *inbuf) { int i, n; for (i = 0; i < 6; i++) { n = (inbuf[0] << 16) | (inbuf[1] << 8) | inbuf[2]; outbuf[0] = (n >> 16) & 0xff; outbuf[1] = (n >> 8) & 0xf0; outbuf[2] = (n >> 4) & 0xff; outbuf[3] = (n << 4) & 0xf0; inbuf += 3; outbuf += 4; } return; } /* 24bit(6x4) -> 32bit(8x4) */ static void decode_ank(uint8_t *outbuf, uint8_t *inbuf) { int i; uint32_t n; for (i = 0; i < 3; i++) { n = (inbuf[0] << 16) | (inbuf[1] << 8) | inbuf[2]; outbuf[0] = (n >> 16) & 0xfc; outbuf[1] = (n >> 10) & 0xfc; outbuf[2] = (n >> 4) & 0xfc; outbuf[3] = (n << 2) & 0xfc; inbuf += 3; outbuf += 4; } return; } static void convert_kanji(uint8_t *buf) { #define KuTen2Ix(ku, ten) ((ku - 1) * 94 + (ten - 1)) int i, j, jis, ku, ten, ix; uint8_t n, d[24]; FILE *fp; FONTX2_HEADER h; fp = fopen("neko12x12.fnt", "wb"); if (fp == NULL) goto fin0; /* header */ strncpy(h.identifier, "FONTX2", sizeof(h.identifier)); strncpy(h.fontname, "NEKOIRAZ", sizeof(h.fontname)); h.xsize = 12; h.ysize = 12; h.codetype = CODETYPE_KANJI; fwrite(&h, sizeof(h), 1, fp); n = sizeof(CodeTable_SJIS1) / sizeof(FONTX2_CODETABLE); fputc(n, fp); fwrite(CodeTable_SJIS1, sizeof(CodeTable_SJIS1), 1, fp); for (i = 0; i < n; i++) { for (j = CodeTable_SJIS1[i].start; j <= CodeTable_SJIS1[i].end; j++) { jis = _mbcjmstojis(j); ku = ((jis >> 8) & 0xff) - 0x20; ten = (jis & 0xff) - 0x20; ix = KuTen2Ix(ku, ten); /* offsetとなる16進数は単純デコードの結果から求める */ if (KuTen2Ix(16, 1) <= ix) { /* 亜〜腕 */ ix -= KuTen2Ix(16, 1) - 0x3438 / 24; } else if (KuTen2Ix( 7, 49) <= ix) { /* а〜я */ ix -= KuTen2Ix( 7, 49) - 0x3030 / 24; } else if (KuTen2Ix( 7, 1) <= ix) { /* А〜Я */ ix -= KuTen2Ix( 7, 1) - 0x2d18 / 24; } else if (KuTen2Ix( 6, 33) <= ix) { /* α〜ω */ ix -= KuTen2Ix( 6, 33) - 0x2ac0 / 24; } else if (KuTen2Ix( 6, 1) <= ix) { /* Α〜Ω */ ix -= KuTen2Ix( 6, 1) - 0x2868 / 24; } else if (KuTen2Ix( 5, 1) <= ix) { /* ァ〜ヶ */ ix -= KuTen2Ix( 5, 1) - 0x2058 / 24; } else if (KuTen2Ix( 4, 1) <= ix) { /* ぁ〜ん */ ix -= KuTen2Ix( 4, 1) - 0x1818 / 24; } else if (KuTen2Ix( 3, 65) <= ix) { /* a〜z */ ix -= KuTen2Ix( 3, 65) - 0x15a8 / 24; } else if (KuTen2Ix( 3, 33) <= ix) { /* A〜Z */ ix -= KuTen2Ix( 3, 33) - 0x1338 / 24; } else if (KuTen2Ix( 3, 16) <= ix) { /* 0〜9 */ ix -= KuTen2Ix( 3, 16) - 0x1248 / 24; } decode_kanji(d, &buf[ix * 18 + 0x07e0]); fwrite(d, sizeof(d), 1, fp); } } fclose(fp); fin0: return; } static void convert_ank(uint8_t *buf) { int i; uint8_t d[12]; FILE *fp; FONTX2_HEADER h; fp = fopen("neko6x12.fnt", "wb"); if (fp == NULL) goto fin0; /* header */ strncpy(h.identifier, "FONTX2", sizeof(h.identifier)); strncpy(h.fontname, "NEKOIRAZ", sizeof(h.fontname)); h.xsize = 6; h.ysize = 12; h.codetype = CODETYPE_ASCII; fwrite(&h, sizeof(h), 1, fp); /* 0x00-0x1f: blank */ memset(d, 0, sizeof(d)); for (i = 0x00; i < 0x20; i++) fwrite(d, sizeof(d), 1, fp); /* 0x20-0xff */ for (i = 0x20; i < 0x100; i++) { decode_ank(d, &buf[(i - 0x20) * 9]); fwrite(d, sizeof(d), 1, fp); } fclose(fp); fin0: return; } static int bload(char *filename, uint8_t *buf, int size) { int result; FILE *fp; fp = fopen(filename, "rb"); if (fp == NULL) { result = -1; goto fin0; } fread(buf, 1, 7, fp); /* discard BSAVE header */ fread(buf, 1, size, fp); fclose(fp); result = 0; fin0: return result; } int main(int argc, char *argv[]) { if (bload("kanji3.grp", Buf, 65419) < 0) { printf("kanji3.grp not found\n"); goto fin0; } convert_ank(Buf); convert_kanji(Buf); fin0: return 0; }