-
o
-
-
C`bg
-
ANZX
プリンターのログファイル(MSX用16ドットプリンタ)をPNGファイルに変換するツールのソース
本題
Common Source Code ProjectやopenMSXなどで出力できる、プリンタ(MSX用)のログファイルをPNGファイルに変換するツールです。
ただし、実行ファイルは配布しません。C#のソースだけ置いておきます。
未実装機能や不備も多いですが改善予定は未定なので、(JUNK)としておきます。
サンプル1(MSX.ROM不使用、アンチエイリアスなし)
サンプル2(MSX.ROM不使用、アンチエイリアスあり)
サンプル3(MSX.ROM使用)
実行ファイル生成について
C#のソースは、.NET Frameworkのプログラムが動作するWindows環境であればコマンドプロンプトから
C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe lptlog2png.cs
みたいなので実行ファイルを生成できるような気がしますが、”v3.5”の部分を変更する必要があったりするかもしれません。
v2.0系でもOKですが、v1.1系ではダメです。
Linux(Mono)等は未確認です。
コマンドライン
パラメータ無しで実行すれば大体わかるんじゃないかと思いますが、
lptlog2png.exe prn_2015-10-16_22-35-16.txt prn_2015-10-16_22-38-52.txt
な感じで。パラメータは全てログファイル名として解釈されます。
複数パラメータを入力した場合、パラメータをソートしてから、その順番に入力されます。ソートが不要であれば、ソースの System.Array.Sort(args); をコメントアウトして下さい。
基本
HX-P560という、MSX用の16ドットプリンタ(日本向け、漢字非対応、カラー非対応)をモデルにしています。B4用紙相当の画像ファイルに出力します。ただし、余白などは実装していません。
画像ファイルのファイル名は、printer0001.png, printer0002.png, ...という感じです。カレントフォルダに、無条件で上書き出力します。
プリンタのフォントROMは内蔵していないので、文字の部分は適当に生成します。なので、実行環境によって出力画像は変わる可能性があります。
カレントフォルダに”MSX.ROM”(MSXのメインROM)や”KANJI.ROM”(MSXの漢字ROM)が存在する場合、それぞれANKや漢字のプリンタフォントROMとして使用します。それらが存在しない場合、文字の部分は適当に生成します。その場合、実行環境によって出力画像は変わる可能性があります。
未実装機能も色々とあります。MSX用プリンタとして最低限必要な制御コードは実装しているはずです。
ソースを少し変更すれば、出力ファイル名の変更、(内部でフォントを生成する場合の)フォントのアンチエイリアスの有無切り替えや、出力画像のdpi変更などもある程度は可能です。
追加実装機能
・漢字手抜き出力(ESC K のみ。詳細な仕様は知らないので適当。漢字コードの違い、フォント幅/ピッチなどは考慮していません。)
・24ドットビットイメージ手抜き出力(ドットを間引いて縦16ドットに変換します。また、改行幅制御等との兼ね合いで行間が開いたり重なったりする可能性もありますし、横幅が足りなくて途中で改行する可能性もあるかもしれません。縦横比も考慮しません。)
・プロポーショナルモード(ESC P、とりあえずフォント幅が不定なだけ。他のモードとの統一感なし。)
未実装機能
・水平タブ
・垂直タブとかVFUとか、そのへん
・余白/マージン
・ドットアドレッシング
・拡大文字
・逆方向改行
・アンダーライン
など。
不備
・(内部でフォントを生成する場合)フォントが美しくなかったり、濁点や半濁点の上のほうが欠けたり、別の文字は下のほうが欠けたり、縦線が消えたり、一部分のフォントが違っていたりするかもしれない しかし、フォントROMを使用すれば美しいというわけでもない
・ビットイメージの縦横比とか、文字のサイズとの兼ね合いは考慮していない
・(私が気付いていない不具合も色々とあるでしょう……)
・(ソースの中身に関しても、まあ色々と……)
など。
駄文1
201PL(PC-PR201とか、その辺)の制御コードも基本は同じような感じのはずなので、流用もしくは共通化もできるかもしれないけど、たぶん私はやりません。
2015-10-31の時点でCommon Source Code ProjectのMSXはプリンタ出力に対応していないのですが、対応は難しくないみたいなので、私を含めた誰かがそのうちやるかもしれません。やらないかもしれません。
駄文2
不具合修正・機能追加・仕様変更・醜いソースの改善・英文のつもりかもしれない箇所の表記修正などを行う人が現れるかどうかはわかりませんが、もしそういうのを配布する場合は、ハンドルネームと日付とかバージョン番号なんかが実行ファイルにも含まれるようにして、改変されていることを容易に判別できるようにすればいいんじゃないかなと思います。
C# lptlog2png.cs (use Unicode)
using System; using System.IO; using System.Text; using System.Drawing; using System.Drawing.Text; using System.Drawing.Imaging; class ProgramMain { static void Main(string[] args) { Lptlog2PNG plog2png = new Lptlog2PNG(); try { if (args.Length<1) { string av0; av0 = System.Windows.Forms.Application.ExecutablePath; av0 = System.IO.Path.GetFileName(av0); Console.WriteLine(plog2png.comment(0)); Console.WriteLine(plog2png.comment(1)); Console.WriteLine(" usage: {0} logfile1 [logfile2 [...]]", av0); Console.WriteLine(" example: {0} prn_2015-10-16_22-35-16.txt prn_2015-10-16_22-36-52.txt", av0); return; } System.Array.Sort(args); plog2png.set_format_png_filename("printer{0:0000}.png"); foreach(string str in args) { Console.WriteLine("input: {0}", str); using (FileStream fs_lptlog = File.OpenRead(str)) { while(true) { byte[] lptlogbuf = new byte[4]; int sz; sz = fs_lptlog.Read(lptlogbuf, 0, lptlogbuf.Length); if (0 == sz) break; int i; for(i=0; i
0) {write_multi(d); return;} else if ((0x00 < d) && (0x20 > d)) write_ctrl1(d); else if (!flag_kanji) {if (0x00 < d) write_char1(d);} else if (0 > byte_kanji_1st) byte_kanji_1st = (int)d; else {write_char2((byte)byte_kanji_1st, d); byte_kanji_1st = -1;} } void write_ctrl1(byte d) { switch(d) { case 0x0A: write_lf(); break; case 0x0D: write_cr(); break; case 0x0C: write_ff(); break; case 0x18: write_can(); break; default: if ((d == 0x01) || (d == 0x1B) || (d == 0x1C) || (d == 0x1A)) { add1_buf_command(d); } break; } } void write_multi(byte d) { switch(buf_command[0]) { case 0x01: if ((d >= 0x40) && (d < 0x60)) write_char1((byte)(d - 0x40)); clear_buf_command(); break; case 0x1B: write_multi_0x1B(d); break; default: clear_buf_command(); break; } } void write_multi_0x1B(byte d) { add1_buf_command(d); int len = get_len_buf_command(); switch(buf_command[1]) { case (byte)'N': width_dot_font = dpi_paper/10.0F; flag_kanji = false; clear_buf_command(); break; case (byte)'H': width_dot_font = dpi_paper/10.0F; flag_kanji = false; clear_buf_command(); break; case (byte)'E': width_dot_font = dpi_paper/12.0F; flag_kanji = false; clear_buf_command(); break; case (byte)'Q': width_dot_font = dpi_paper/17.0F; flag_kanji = false; clear_buf_command(); break; case (byte)'P': width_dot_font = -1; flag_kanji = false; clear_buf_command(); break; case (byte)'K': flag_kanji = true; byte_kanji_1st = -1; clear_buf_command(); break; case (byte)'A': lf_dot = dpi_paper/6; clear_buf_command(); break; case (byte)'B': lf_dot = dpi_paper/8; clear_buf_command(); break; case (byte)'T': if (len == 4) { lf_dot = dpi_paper * get_num_buf_command(2, 2)/120.0F; clear_buf_command(); } break; case (byte)'R': if (len == 6) { int i = get_num_buf_command(2, 3); for(; i>0; i--) write_char1(buf_command[5]); clear_buf_command(); } break; case (byte)'S': if (len == 7) { write_graphic_command(1); del_buf_command(1); count_graphics--; if (0 == count_graphics) clear_buf_command(); } else if (len == 6) { count_graphics = get_num_buf_command(2, 4); } break; case (byte)'I': if (len == 8) { write_graphic_command(2); del_buf_command(2); count_graphics--; if (0 == count_graphics) clear_buf_command(); } else if (len == 6) { count_graphics = get_num_buf_command(2, 4); } break; case (byte)'J': if (len == 9) { write_graphic_command(3); del_buf_command(3); count_graphics--; if (0 == count_graphics) clear_buf_command(); } else if (len == 6) { count_graphics = get_num_buf_command(2, 4); } break; case (byte)'V': if (len == 7) { int i = get_num_buf_command(2, 4); for(; i>0; i--) write_graphic_command(1); clear_buf_command(); } break; case (byte)'W': if (len == 8) { int i = get_num_buf_command(2, 4); for(; i>0; i--) write_graphic_command(2); clear_buf_command(); } break; case (byte)'U': if (len == 9) { int i = get_num_buf_command(2, 4); for(; i>0; i--) write_graphic_command(3); clear_buf_command(); } break; case (byte)'F': if (len == 6) { header_dot_x = get_num_buf_command(2, 4)*dpi_paper/dpi_printer; clear_buf_command(); } break; default: clear_buf_command(); break; } } void write_cr() { flush_line_to_page(); header_dot_x = 0; } void write_lf() { flush_line_to_page(); header_dot_y += lf_dot; if (/*bmp_page.Height < header_dot_y + bmp_line.Height*/(Math.Ceiling(height_mm_paper*dpi_paper/25.4F)) < header_dot_y + (dot_printer*dpi_paper/dpi_printer)) { if (null == bmp_page) { create_bmp_page(false); } save_page(); header_dot_y = 0; } } void write_ff() { flush_line_to_page(); if (null == bmp_page) { create_bmp_page(false); } save_page(); header_dot_y = 0; } void write_can() { rel_bmp_line(); header_dot_x = 0; } void write_char1(byte d) { if (null == buf_font_msx_ank) { string str_char = new String(chr1byte[d], 1); write_char(str_char, width_dot_font); } else { write_char1_fontrom(d, width_dot_font); } } void write_char2(byte d1, byte d2) { if (0 == d1) { if (null == buf_font_msx_ank) { string str_char = new String(chr1byte[d2], 1); write_char(str_char, dpi_paper/10.0F); } else { write_char1_fontrom(d2, dpi_paper/10.0F); } } else { if (null == buf_font_msx_kanji) { Encoding jisEnc = Encoding.GetEncoding("iso-2022-jp"); byte[] bytes = new byte[] {0x1B, 0x24, 0x42, 0, 0}; //byte[] bytes = new byte[] {0x1B, 0x24, 0x40, 0, 0}; bytes[3] = d1; bytes[4] = d2; string str_char = jisEnc.GetString(bytes); write_char(str_char, dpi_paper*3/20.0F); } else { write_char2_fontrom(d1, d2, dpi_paper*3/20.0F); } } } void write_char(string str_char, float width_dot) { // I don't have printer font ROM!!! if (null == bmp_line) { create_bmp_line(false); } SizeF szf; if (width_dot < 0) { szf = grp_line.MeasureString(str_char, draw_font_p, new PointF(0.0F, 0.0F), sf); if (bmp_line.Width < header_dot_x + Math.Ceiling(szf.Width)) {write_cr(); write_lf(); create_bmp_line(true);} grp_line.DrawString(str_char, draw_font_p, draw_brush, (int)header_dot_x, 0, sf); header_dot_x += (float)Math.Ceiling(szf.Width); } else { szf = grp_line.MeasureString(str_char, draw_font, new PointF(0.0F, 0.0F), sf); if (bmp_line.Width < header_dot_x + width_dot) {write_cr(); write_lf(); create_bmp_line(true);} Bitmap bmp_font = null; Graphics grp_font = null; create_bmp(ref bmp_font, ref grp_font, (int)Math.Ceiling(szf.Width), (int)Math.Ceiling(szf.Height)); grp_font.DrawString(str_char, draw_font, draw_brush, 0, 0, sf); if (!flag_anti_alias) bmp_font.MakeTransparent(Color.White); grp_line.DrawImage(bmp_font, (int)header_dot_x, 0, (int)width_dot, (int)Math.Ceiling(szf.Height)); header_dot_x += width_dot; grp_font.Dispose(); bmp_font.Dispose(); } } void write_char1_fontrom(byte d, float width_dot) { byte[] pattern = new byte[32]; int i, j, k; Array.Clear(pattern, 0, 32); for(i=0; i<2; i++) for(j=0; j<4; j++) for(k=0; k<8; k++) { if (0 != (buf_font_msx_ank[d*8+i*4+j] & (1<
d1) { a = (d1-32)*96+d2-32; } else if (0x50 <= d1) { a = (d1-80)*96+d2-32 + (128*1024/32); } else { a = (d1-32)*96+d2-544; } a *= 32; if ((a < 0) || (a >= buf_font_msx_kanji.Length)) a=0; for(i=0; i<2; i++) for(j=0; j<2; j++) for(k=0; k<8; k++) for(l=0; l<8; l++) { if (0 != (buf_font_msx_kanji[a+i*16+j*8+k] & (1<
もう、ついでに書いておくけど、msx.cppで
io->set_iomap_range_rw(0x90, 0x91, printer);
printer.cppを新規追加して
void PRINTER::write_io8(uint32 addr, uint32 data) { switch(addr & 0xff) { case 0x90: emu->printer_strobe((data & 0x01) == 0); break; case 0x91: emu->printer_out(data & 0xff); break; } } uint32 PRINTER::read_io8(uint32 addr) { switch(addr & 0xff) { case 0x90: return busy ? 0xff : 0xfd; } return 0xff; }
みたいな感じで、Common Source Code ProjectのMSXもプリンタログ出力できるようです。でも今は、バイナリ公開しません。面倒なので。
2015-10-31版へのリンク
戻る
ANZX
SEO
/
SEO
FC2
:
Text
AD
:
JEFFC2
z[y[W
T[rXLO
VbsOJ[g
BBS
Cu`bg
JE^[
[
hCo^798~`
^T[o[
AvP[VJ
Io