先日出荷したNT Service関係のモジュールが返って来た。
ユーザーの本来の要望と、営業が聞いて来た要望が食い違っていたらしい。ユーザーはNT Serviceとして自動起動した上で、更に対話的インターフェイス(Desk topのと対話
ってやつ)を要求していたのだが、こちらではServiceとして起動するとだけ聞いていたので、そうしたインターフェイスは提供しないものとして作成した。とゆ〜か、Desk topのと対話
を許可すると、Service起動されるプログラム本体がプリンタを認識してくれないものだから逃げたわけである。
Desk topのと対話
を許可するにはLocal System権限でNT Serviceを起動する必要がある。プリンタの検索にはGetProfileString()というWin16互換APIを使っているのだが、これがLocal System accountではマトモに動いてくれない。と思ったのだが、よく調べてみるとGetProfileString()が検索するregistry(プリンタ情報が入っているはず)に、Local System account(及び他の不明なaccount)の場合は何も入っていない。結局、これが原因でプリンタが認識できないと見える。
これを解決するにはWin32 APIのEnumPrinters()を使うように変更すればいいのだが、多くのモジュールで改修を行わなければならないため、私一人ではできない。たぶん、GetProfileString()と同じインターフェイスを持つようなEnumPrinters()のwrapper関数を作れば解決なのだが。
ビデオで小松左京劇場
を見る。
小松左京の短編・ショートショートを原作にしたGAINAX製作の短編アニメ集だが、可もなく不可もなくといったところ。夏の行事
や初夢
はかなりアレンジを加えられているが、それで面白くなったとは言えないところが辛い。それでも昔の義理
や辺境の寝床
辺りはなかなか楽しませてくれる。
という事を書いても、分かる人はまずいないような気がする今日この頃。
ふじさんに借りたSEGA SATURN版ゆみみみっくす
をやる。
本編を始める前におまけが気になってやってみたら、上海だった。本編の前に、これで2時間近く遊んでしまったのはアホかも知れない。
んで本編。3時間弱でエンディングにたどり着いたのだが、これが中々におもしろい。いかにも竹本泉
な変な話で、読み切りマンガを遊んでいるような感覚である。見た目はどこにでもあるデジコミなのだが、どの選択肢を選んでもおもしろい。これって凄い事だと思う。
トンベイXSMに参加。
ゆっくり話の出来る、いいイベントだったと思う(前に来たときは、ステージの音量が大きすぎて人と話すのが大変だった)。
収穫は、なるとさんのCD。なるとさんなら(いい意味で)安心して聞けると思って買ったのだが、音がMIDI丸出しなのが少し気に入らない。曲は好みなんだけど。
他にもEXPANSION SLOT
(限定15台の紫版)とか、STRATFORD
の教育ソフト(テープ版・未開封)とか、はっちゃけあやよさん
(定価より高く売れたという伝説あり)といった辺りが美味しい買い物だった。MSX-SEEDの最終号も買ったけど、あまりの薄さ(物理的な)に思わず涙が。後継誌ぽぴぷっ
はもう少し厚くなるといいなぁ。
東の方からやってきた人々と京都で合流。
道に迷ってだいぶ遅れたが、なんとか合流できた。しかし、箕面から京都へはちと遠い。ちなみに、かちゅ〜しゃさん、よしまつTUQさんに、フロントラインのNASUさん、TAKOさん、浦田さん(字が違うかも)である。
このメンツで緑のぷよを食べたり、湯葉を食べたり、お好み焼を食べたりしていたわけだが、ひさごの親子丼はやはり絶品である。更に、ここ(ひさご)のトイレは想像を絶する代物(汚いとかじゃない)で、これを見て何も感じない人は人間として終わっているかも。あの衝撃を体験する為に京都へ行っても、損はしないと思う。
で、夜は宿泊費を浮かすべく大阪の健康ランドへ(かちゅ〜しゃさんは更に浮かすべく、黒田氏の家に向かったそうな)。Moveにはとても全員は乗り切れないので、関西在住のよしまつさんと私は電車で健康ランドへ向かった。
渋滞に巻き込まれた車組を待つ間、健康ランドの隣にあるゲーセン(だけじゃなかったが)で暇潰し。テクノドライブという運転技能をテストするゲームが面白かった。最初にやったときは3つの項目全てが最低ランク(E)で、走る凶器とか言われてしまったが。
合流して健康ランドに入ってからは、ラーメン食べて、風呂入って、ゲームして、とやってる間にベッドが埋まり、床でくたばる事に。まぁ、そんなもんでしょ。
Think Blueでまたバグ発見。
入力ファイルの最後の行にCR/LFもEOFもないと、ASCIIに戻さないで終了してしまう。ファイルの最後でASCIIに戻っていなければ、ESC ( Bを追加する処理を入れるだけなのだが、ちょっと問題が。
まず、ファイルの終了判定をどうやっていたのか思い出せない。なにか少々トリッキーな事をやった記憶があるのだが、それだけに正確な事が分からないんである。
更にもう一つ。現在の状態を返すルーチンを変換毎に追加しなければならないが、変換のアルゴリズムが思い出せないので、解析して内部状態を抽出するコードを書かなければならない。が、コメントが皆無なので面倒臭い。
そうこうしている内に、UU Decode/SEV Decodeのバグを見つけたので、そっちを優先。uud *.* h:とすると妙な場所にファイルを作ろうとするバグだが、結局ドライブ番号の求め方に問題があった。ドライブ名は大文字(A,B,C,...)の場合と、小文字の場合(a,b,c,...)があるのだが、FILE.MACの_JGDIRというルーチンが小文字の可能性を考慮していなかったという、つまらないミスが原因。
凡ミスを無くすのは、なかなか難しい。
gooでUNICODEのendianについて調べてみた。
どうやらbig endianでもlittle endianでもいいらしい。かといって区別出来ないと困るので、EF FFという制御コード(?)が用意されている。little endianでは先頭に(?)FF EFの2bytesが来て、以降のendianを示すようだ。規格でどちらかに固定しておけばいいと思うんだけどなぁ。
UNICODEについて調べるとこれ以外にも妙な部分が多く(合成文字とか)、テキスト処理が楽になるとは思えない。そもそも、処理を簡単にする為に各国の文化に犠牲を強いるという考え方が気に入らないんだけど。
なんとなくUNICODE → ShiftJISの変換器が作りたくなった。
まずはUNICODEとShiftJISの対応表を作らなければならないのだが、数千字の文字を手で調べるのは無茶というもんである。ここはWindowsのUNICODE <-> ShiftJIS変換APIを利用することにした。
ちなみにMSXしか持っていない人間なので、会社のマシンを使っている。ばれたらちょっとまずいかも知れないが、どうせ余剰戦力の暇人だし、一応勉強だし(言い訳)。
てなわけで、仕事中にこっそり書いたのが次のコード。わざわざここに引用するのは、この日記もどきの量を水増しする為だったりする(なんだかなぁ)。
#include <stdlib.h> #include <wchar.h> #include <afxwin.h> int main(void) { CFile fileTbl; fileTbl.Open("UcTbl.bin", CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyWrite); CFile fileList; fileList.Open("UcList.Txt", CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyWrite); wchar_t strUC[] = {0x00, 0x00, 0x00, 0x00}; unsigned char strSJIS[] = {0x00, 0x00, 0x00, 0x00}; const unsigned char strDefault[] = {0x81, 0x40, 0x00}; BOOL bUseDefault = TRUE; int iH, iL; for(iH = 1; iH < 0x100; iH++) { for(iL = 0; iL < 0x100; iL++) { strUC[0] = iH << 8 | iL; WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, strUC, 1, (char*) strSJIS, sizeof strSJIS, (char*) strDefault, &bUseDefault); fileTbl.Write((char*) strSJIS, strlen((char*) strSJIS)); if(strcmp((char*) strSJIS, (char*) strDefault) != 0 && strSJIS[0] < 0xf0) { CString strTemp; strTemp.Format("%04X: %02X%02X (%s)¥r¥n", iH << 8 | iL, strSJIS[0], strSJIS[1] , strSJIS); fileList.Write(strTemp, strTemp.GetLength()); } } } fileTbl.Close(); fileList.Close(); return EXIT_SUCCESS; }
これで全ての対応関係表と、ShiftJISとの関係に絞った表の二つが得られる。で、気付いたのだが、UNICODEがlittle endianで格納されている。確かにVC++のwchar_tはshort intにtypedefされているので、Wintel環境では不思議でも何でもないのだが、プラットホームを離れて考えると変である。
最初は128KBの対応表をVRAMに置いて使おうと思ったのだが、特定の範囲にShiftJIS相当の文字が集中している(って当たり前か)。これなら上位byteで下位byteテーブルへのアドレスを引いて変換する方法でもいけそうである。
ちなみにこんな感じ(でまた水増し)。
LD D,HIGH HI_TBL ;high byte table LD E,(HL) ;low byte tableのaddressを表引きする INC HL LD A,(DE) ;A ← low byte table addressのhigh byte LD D,A LD E,(HL) INC HL LD A,(DE) LD (BC),A ;BCとHLの初期値を同じにしておく INC BC INC D ;low byte tableは水平型にしておく LD A,(DE) ;UNICODE → ShiftJISの変換は膨張しない LD (BC),A ;従ってUNICODE dataを読み込んだ領域に INC BC ;ShiftJIS dataを上書きしても問題なし
ShiftJISなら7000文字以下しかないからテーブルが14KB以下で済む → Main RAMに納まるという、それだけの事でやんす。
寮にCATVが入った。
で、CSも見られるようになったのだが、画質が異様に悪い。画面の変化が少ないシーンでは確かに高画質なのだが、動きが激しくなると急にノイズが増え、10年前のVHSデッキで3倍モード録画したみたいになる。
どうも伝送レート一定を前提に圧縮しているような感じで、変化の大きい部分ではコマ当たりの情報量が少なくなっているらしいのだが、これをデジタル高画質
などと言って宣伝するのは問題あるよ〜な。
確かCSはMPEG2を使っていたはずだが、額面通りの画質が出せるようになるには、まだ時間が掛かりそうな雰囲気である。いかにもデジタルなブロックノイズも多いし。
この期に及んでFS-A1GTを入手。
某伝言板で売りに出されていたもので、SOFMAPやSTAND BYで買うより遥かに安い。で、早速困ったのがどこから音を出すのかという問題。音声出力がなく、アンプに繋げられない。RGBで繋げば、一応モニタから音は出るのだが、哀しい音質なので嫌なんである。GTからモニタに入力して、モニタの出力をアンプに入れる手も考えたのだが、ハウリングを起こしそうでちと怖い。
結局、音無しで使っているのだが、なんとかしたいもんである。
RFC1468を読んで、Think Blue
で大間違いをやらかした事に気付いた。
JISでは制御文字(Controll code/00H〜20H,7FH)と図形文字(21H〜7EH)は独立しており、2bytes文字の文脈で制御文字を使う場合でも文脈を切り替える事なく両者を混在出来る。Think Blue
でもこの仕様に則って変換を行う。しかし、ISO-2022-JPの仕様を定めたRFC1468を見ると、
segment =single-byte-segment / double-byte-segment single-byte-segment=single-byte-seq 1*single-byte-char double-byte-segment=double-byte-seq 1*( one-of-94 one-of-94 ) ; ( Octal, Decimal.) one-of-94 =<any one of 94 values> ; (41-176, 33.-126.) 7BIT =<any 7-bit value> ; ( 0-177, 0.-127.) single-byte-char =<any 7BIT, including bare CR & bare LF, but NOT including CRLF, and not including ESC, SI, SO>
となっている(必要なところだけ抜粋)。
私にとって重要なのは、double byte segmentがone of 94(21H〜7EH)のみで構成されている点である。更にsingle byte segmnetがCRLF/ESC/SI/SO以外の制御文字を含んでいる事からして、2bytes文字の文脈で制御文字を使うにはASCIIかJIS X0201ローマ字に切り替える必要があると判断出来る。
これは、ver1.01までのJISへの変換は蟲付きで、ver1.02のDOCに書いた文章は大嘘であったという事を意味する。
とゆ〜わけで、Netscape社さん、Microsoft社さん、ごめんなさい。
やはり一次資料を当たらなければ正確な事は掴めないというのが、身に染みて分かりましたですよ。はい。
でも....なんでこんな仕様になったんだろ。double byte segment中でなら固定長で扱えるけど、それ以外のメリットってないよなぁ?
RFC1149を読む。
いやもう、これが中々に面白い。鳥類によるIP伝送
を扱っているのだが、要するに伝書鳩でIP datagramを運ぼうという冗談提案。Bandwidth(帯域)は足の長さによって制限される(足に巻き物を付ける)とか、典型的なMTUは256mg(milligrams)であるとか、しょ〜もない駄洒落が妙に笑える。
ちなみに、4月1日付けのRFCの一つらしいです。
大学の時の友人に、簡単なフィルタプログラムを頼まれる。
仕様としては、
といったところ。最初にPerlで書いてみたのがこれ。
#!/usr/bin/perl if(!open(TXT, $ARGV[0])) { print("File Not Found"); } $next = ""; while(<TXT>) { chomp; if($_ ne "") { if($next ne "") { print("$next$ARGV[1]¥n"); } $next = $_; for($i = 0; $i < $count; $i++) { print("¥n") } $count = 0; } else { $count++; } } print($next."¥n"); for($i = 0; $i < $count; $i++) { print("¥n") } exit(0);
Perlの練習を兼ねているので、あまりPerlらしくないかも。
だがしかし。これを送ったら、使っているサーバにPerlが無いとのこと。そ〜ゆ〜事は先に言え。
仕方がないので、Cで書き直してみる。面倒だわ、長いわ、汚いわで、もう最悪である。せめてC++が使えればなぁ。
#include <stdio.h> #include <stdlib.h> #define BUFFER_SIZE 1024 int main(int argc, char* argv[]) { char line[BUFFER_SIZE]; char* p; int flag; int count; FILE* fp; if(argc < 3) { fputs("Few arguments.¥n", stderr); return EXIT_FAILURE; } fp = fopen(argv[1], "r"); if(fp == NULL) { fputs("File cannot open.¥n", stderr); return EXIT_FAILURE; } flag = -1; count = 0; while(fgets(line, BUFFER_SIZE, fp) != NULL) { if(*line == '¥n' && flag != 1) count++; else { if(flag == 0) puts(argv[2]); for(;count > 0; count--) putchar('¥n'); flag = 1; p = line; while(*p != '¥0') { if(*p == '¥n') flag = 0; else putchar(*p); p++; } } } if(flag == 0) count++; for(;count > 0; count--) putchar('¥n'); fclose(fp); return EXIT_SUCCESS; }
これをcomplieしてみようとRIM-NETに転送してcc test.c
としたのだが、なにやらエラーが返ってくる。エラーの原因は、EXIT_SUCCESSとEXIT_FAILUREが定義されていない事と、main()の引数が間違っている事らしい。EXIT_〜は、事実上0と1で代用出来るから特に問題はない。厳密にANSI Cとして書きたかっただけである。
しかし、main()の引数はどう見ても正しい形のはずであり、エラーが出るのは解せない。そう思い込んでしばらく詰まっていたのだが、unixにはANSI C対応のC compilerはあまり出回っていないという噂を思い出す。試しにK&R型式に書き換えたら、正常にcompileできた。
RIM-NET大阪ドメインのサーバには、この古いccしか入っていないようで、この手のテストをするときは本当に不便である。やはりディスク容量を増やして、gccを入れるしかないのだろ〜か。
Web site開設に向けて、CGIをいくつか書いてみた。
初めてのPerl 2nd edition
を見ながらAPeD & Viperでごりごり書いて、EsTermでRIM-NETのサーバに転送して実行するという手順。最初はCGIとは無関係に、お約束のHello, world.
。しかし、動かし方が分からない。
転送した後、
chmod 755 hello.cgi
hello.cgi
としたのだが、そんなコマンドは知らないと言われてしまう。駄目元でPathの通っているディレクトリに移してみたが、結果は同じ。色々試した挙句、
./hello.cgi
としたら動いた。こういうとき、自分がunix素人である事を実感する。
で、実行の仕方が分かったので訪問者カウンターを書いてみる。ところが、なぜかcomplierにはねられてしまう。my($retry)=@_;
が原因だと分かったのだが、local変数を定義しているだけで、本を見た感じでは正しそうに見える。しばらく考えて、初めてのPerl 2nd edition
はPerl5の本であり、RIM-NETのPerlは少々古いのではないかと気付く。
perl -version
とすると案の定、RIM-NETのPerlはver4だった。WebでPerl4/Perl5の資料を捜すと、my
はPerl5で追加された語である事が判明し、結局local
を使って書き直した。
この期に及んでSEGA SATURN(SHIRO!)を買ってきた。
それもこれも機動戦艦ナデシコ The blank of 3 years
を遊ぶ為なのだが、正直期待外れ。なんせプレイヤーの選択肢が少なすぎて、ゲームをしている感じが全くない。かといって、アニメを見ている感覚には程遠い。つまらないのを我慢し、ストーリーを知りたい一心で進めたらあっけない終わり方するし。
まだ他のシナリオもあるみたいだが、また我慢の数時間を過ごすのかと思うとやる気にならない。