日記

4月 10日 (日)

1. DARIUS PREMIUM BOX-REBIRTH

メモ。明日から予約開始。買うかどうか微妙なところ。

2. 年間維持費3億円の原子力発電の広報用ウェブページ

原子力発電の年間維持費が三億円…ではなくて、広報用ウェブページの年間維持費が三億円だそうです。ぶっちゃけありえない♪。何をどう見積もればこんな金額になるのか、教えて!!知○留先生。

3. 武刃街

7-4の例の難所がクリアできません。壁面走行、滑空、三角跳びを繰り返すということはわかっているのですが、壁に掴まってくれなくてずるずる落ちていってしまいます。ちゃんと掴まれよ、ga○kt。

4月 12日 (火)

1. T・J・S!! T・J・S!!

TJSエンジン引っこ抜きメモ。VCL依存だけは避けたいところですが、どうなることやら。

  • using bcc32 v5.6.4
  • Regex++ ver.3
  • Regex++ を build & install
  • 吉里吉里の core/tjs2/ 以下を丸ごと適当なディレクトリにコピー。
  • サンプルコートを書く。TJS2リファレンスに載ってるやつ。
  • 適当にMakefileをでっち上げる(PPマクロ TJS_SUPPORT_VCL は定義しない)。
  • make (使用されるのは $(REGEX_LIBPATH)/boost_regex_bcb6_mss.lib)。
  • 1MBくらいの実行ファイルができあがる。結構でかい。
  • 実行してみる。
  • ウマー

サンプルコードではwindows.hとSTL stringをインクルードすること。そのままだとコンパイルエラーになった。

#include <windows.h>
#include <stdio.h>
#include <string>
#include "tjs.h"
#include "tjsError.h"

4月 13日 (水)

1. TJS

TJSのエンジン部をDLLにしました。コマンドライン版TJSを作るだけなら、わざわざDLLにする必要はないのですが、ほかの計画で流用する予定なのでこうしておきます。

DLLからエクスポートされた関数の呼び出し方は、通常はGetProcAddress()関数を使って、DLLインスタンスハンドルと関数名から関数ポインタを取得し、それを実行します。しかし、利用者側が毎回こんなことをするのは面倒なので、DLLを作成する時点でラッパー関数を定義するコードも作成します。もちろん自動生成です。このコードを、DLL利用者がコンパイルすることで、エクスポートされた関数を簡単に利用できるようにします。

inline tTJS * TJSEGetScriptEngine()
{
  if (!TJSEImportFuncPtr_TJSEGetScriptEngine) {
    static char funcname[] = "TJSEGetScriptEngine";
    TJSEImportFuncPtr_TJSEGetScriptEngine = GetProcAddress(TJSEDLLInstanceHandle, funcname);
  }
  typedef tTJS * (WINAPI * __functype)();
  return ((__functype)(TJSEImportFuncPtr_TJSEGetScriptEngine))();
}

static変数のせいでinline展開できないのはご愛敬ということで。そのうち対処方法を考えます。ちなみに、このコードはtp_stub.hのコードを恥も外聞もなく真似たものです。

4月 14日 (木)

1. TJS

ネイティブ関数を追加するための機構とマクロを追加しました。これを使って、 global.print(String) 関数を作成しました。TJSから標準出力にナロー文字列を出力する関数です。とりあえず、こんなコードが動きました。

if (TJSELoadLibrary() == NULL) {
  printf("ロードエラー\n");
  return -1;
}
TJSEExecScript(
  L"function test(x, y) { return x*y; } \n"
  L"var res = '結果 = ' + test(4, 5); \n"
  L"print(res + '\\n'); \n",
  NULL, NULL,
  TJS_W("test code"));

DLLロード直後にスクリプトを実行できるあたりが、ちょっぴり素敵です。

ほか、早いうちに実装しておきたいのがファイル入出力関連です。TJSエンジンには、標準ではファイル入出力機能が実装されていないっぽい(インターフェースだけが提供されている)ので、Array.load()等が使えません。吉里吉里ではたしかVCLを使って実装していたような気がしますが、今回はVCL非依存を前提にしているので、いつものように(?)パクって済ませるわけにはいかなそうです。

4月 15日 (金)

1. TJS

I/O関連の実装を始めました。吉里吉里ではVCLを使っていたと思ったのですが、TVP2.24RC3 *1 のソースを追いかけてみたら、VCLは使われていませんでした。気のせいだったのか、記憶違いか…確か以前TStreamクラスとか使っていたような…まあいいか。

で、追っかけですが、吉里吉里のストレージ周りは複雑怪奇でよくわかりませんでした。下手すると、レイヤ周りよりも複雑かも。とりあえずファイルストリームとファイルストレージの部分だけを取り出して、うまい具合につなぎ合わせて、モジュール化。吉里吉里に深く依存した部分を所々コメントアウトしているため、動作はちょっと怪しいかもしれません。特にエラー処理。まあ追々直していくとしましょう。

ていうか、結局パクりかよ。

TJSCreateTextStreamForReadに関数の実体(へのポインタ)をコピーするところまで漕ぎ着け、Array.load()が動作するのを確認して終了。書き込み周りは、そのうち気が向いたらパクる実装するとしましょう。

  • *1: すでに2.24 stableがリリースされてますね。

4月 16日 (土)

1. TJS

簡易版スタブモジュールを作成しました。通常版スタブをリンクすれば、TJS関係の機能(tTJSStringとかeTJSとかいろいろ)を使えますが、バイナリのサイズはかなり大きくなってしまいます。簡易版では、TJS関連を一切使えませんが、TJSライブラリをリンクしないので、バイナリのサイズは小さくなります。この簡易版を使ってコマンドライン版を作成したところ、実行ファイルが64KB、DLL(TJSエンジン)が1MBとなりました。

ところで、当初の計画にはあった、プラットフォーム非依存の実行環境ですが、Windows APIに依存している部分が多々あったり、MakefileがBorland Makeに特化してたり、その他アレ(何)だったりで、現状では無理そうです。bash on Linux上でtjs HelloWorld.tjsとか叩けると楽しそうなんですけどね。

あと、コメントをちゃんと書いて、Doxygenで出力させてみました。

4月 17日 (日)

1. 武刃街

例の登れなかった場所ですが、ふとやり方が閃いたので、登ることができました。要するに、

  1. 滑空
  2. カメラ補正
  3. 壁面走行
  4. 三角跳び
  5. …以下繰り返し

ということですね。

そのまま勢いで、エンディングまでいきました。

2. TJS

メッセージ周りのインターフェースを作りました。TJS本体で定義されているメッセージを利用できる形にしました。

4月 18日 (月)

1. sqlite3 for 吉里吉里

おや、かぶってしまいましたか。

わたなべごうさんのは、吉里吉里プラグインにsqlite3本体を組み込んだ形になっています。また、2.25系の(俺的には)目玉機能である「プラグインでネイティブクラス」を利用しています。

私のは吉里吉里プラグインとsqlite3本体が別になっています。sqlite3本体は吉里吉里とは無関係なDLLですので、吉里吉里以外からも利用できますが、使う人いるんかいな。また、2.24系なので「プラグインで無理矢理クラス」です。インチキくさい。

4月 19日 (火)

1. TJS

ああ、なるほど、iTJSConsoleOutputを使えばいいのですね。

class TJSEStandardOutput : public iTJSConsoleOutput
{
  void ExceptionPrint(const tjs_char *msg) { printf("%ls\n", msg); }
  void Print(const tjs_char *msg) { printf("%ls\n", msg); }
};

このクラスのインスタンスを、tTJS::SetConsoleOutput()でエンジンに食わせてやると、エラー発生時に標準出力にこんなものを吐いてくれます。

==== An exception occured at A simple script invoked from TJSEExecSimpleScriptSTDC()(6)[(top level script) global], VM ip = 54 ====
-- Disassembled VM code --
…(略)
-- Register dump --
…(略)
-----------------------------------------------------------------------------------------------------------------------------------
メンバ "foo" が見つかりません at A simple script invoked from TJSEExecSimpleScriptSTDC()(6)[(top level script) global]

つまり、コールバックインスタンスとして機能させるわけです。違う実装を食わせてやれば、違う出力が得られる、と。いい作りしてますね。素晴らしい。これならエラー処理しなくていいじゃないか、なんていう錯覚に陥りそうになりました。いや、実際にはやることはいろいろありますよ。