2014年12月28日

やってしまった

zlib を使ったコードを Visual C++ で書いて Xcode でテストしていたのですが、謎のエラーに悩まされました。Visual C++ で実行しているときは何もないのですが、Xcode で実行すると落ちるんです。やっとのことで原因をみつけだしてみると...


uint32_t destsize = ...
...
int zerr = ::uncompress(destbuf, (uLongf *)&destsize, sourcebuf, sourcesize);

とかやっていたのが原因でした。問題は (uLongf *)&size の部分です。uLongf は zlib で typedef されている型で、実体は unsigned long です。

Visual C++ だと uint32_t も long も同じ 32 ビットだったのですが、Xcode だと long は 64 ビットなんですよね…

たしかに int とか long は環境によってサイズが異なる、というのはCの常識としてあったわけだけですが、いつの間にかそういう常識も忘れてしまうという話でした。ああ、うん、安易にキャストするものじゃないですよね。ハイ。

(なんか昔 wchar_t のサイズが 2 バイトだと思い込んでいたせいで困ったことになった記憶があるのですが、その教訓は生かされなかったようです)
posted by JUNOSOFT at 03:26| Comment(0) | プログラミング

2014年12月17日

フルスクリーンでのデバッグ中にフリーズした場合の復帰

パソコン1台、モニタ1台の環境で問題になるのが、フルスクリーンゲームのデバッグです。
フルスクリーンでゲーム実行中にブレークポイントに差し掛かったり、フリーズしたりすると、わりとどうしようもないことになります。
デバッガの画面を見たいけとフルスクリーン状態でフリーズしたウィンドウが邪魔で見れない、
デバッグをあきらめ、強制終了しようとしてタスクマネージャを起動しても、タスクマネージャの画面すら隠れてしまうと。
そんなときはもうWindowsを再起動するか、サインアウトするしかなかったのですが、最近少しだけましな方法を発見しました。
Windows8.1限定かもしれませんが、フルスクリーンでフリーズした状態で Ctrl+Alt+Del でメニューを出し、「ユーザー切り替え」を選択し、現在利用中のユーザーを改めて選ぶとデスクトップ画面に復帰することができます。

たとえばフルスクリーン時に 640x480 の解像度にしていた場合、デスクトップ左上の 640x480 の部分は引き続きゲームによって占領されていますが、それ以外の領域は普通に使うことができます。
そのため、エラーダイアログをチェックするなり、デバッガから強制終了するなり、どうにか操作することができます(ただし、フルスクリーン時の解像度がデスクトップ解像度に近い場合、やはり画面の大部分が操作不能のまま残ることになりそうですが…)。
ただ、この方法も100%うまくいくわけではなく、フリーズ内容によっては引き続き画面全体が操作不可能な状態になります

まあ、それでもだいぶ助かりますけどね。
posted by JUNOSOFT at 15:30| Comment(0) | プログラミング

2014年12月08日

バイナリ―オプション

どうやら数年前から話題にはなっていたようなのですが、某所でバイナリ―オプション取引というものがネタになっていて、初めてその存在を知りました。通過が10分後に値上がりするか値下がりするかの二者択一で予想するだけ、というヤツです。

そこで話題になっていた取引サイトは bo-box.com というところだったのですが、なんと倍率は 1.75 倍です。例えば 1000 円払って「値上がり」を購入したとして、その 10 分後、通貨が値上がりしていれば 1750 円戻ってきます。驚くことに倍率は固定で、たとえ購入した全員の予想が当たったとしても、戻ってくる金額に変化はありません。話がうますぎてなんとも不安になるじゃありませんか。

いったいどんなものなのか気になり、bo-box.com にフリーのメアドで登録だけしてみたのですが、なるほど単純でわかりやすく、ほとんどゲーム感覚で取引することができるみたいですね。
これって普通に現金を使ったギャンブルゲームに見えるのですが…確かにハマる人はハマりそうです。

で、自分はそんなものに手を出す余裕も勇気もないので、代わりに過去のチャートから次の値動きを予想するプログラムを組んでみました。「自分だったらここでこれを買うなあ」というのをそのままアルゴリズムにした感じです。

さっそく「過去2日間にわたり、5分毎にひたすら取引を繰り返した」という設定で実行してみたところ、勝率が 50.8% という極めて微妙な値になりました…。うん。サイコロ振って決めるのと変わらないですね。
というかこんなプログラムひとつで稼げるならだれも苦労はしないわけで。

なんとも当り前な結論になりました。
posted by JUNOSOFT at 18:51| Comment(0) | 雑談

2014年11月26日

yamlをluaのテーブルに変換したい

自分が作っているアプリでは、設定ファイルなどにはだいたい xml を使っていたのですが、いいかげん xml のタイプ量の多さが嫌になり、yaml を使うようになりました。

そこで libyaml を使って yaml が読み込めるようにしたのですが、なんだか xml のときと同じ作業をしているような気がしてなりません。
xml のパーサには TinyXml を使っていますが、その時もどぶじぇくとツリーに気軽にアクセスができるよう、自前のヘルパー関数を作っていました。
libyaml でも全く同じ作業をしています。libyaml はシーケンスを返すだけなので、どのノードがどのノードの子になっているとか親になっているとか、そういうのは自分で解析しないといけません。

そんなわけで、ある時期からは設定ファイル自体を lua 形式で書くようにしました。これが非常に使い勝手が良くて、ただ値をつらつらと並べるほかにも、規則性のあるデータが続くときは for 文で機械的にデータを作り出すこともできます。

こうなると、xml は lua でパースして lua テーブルに置き換え、yaml も lua でパースして lua テーブルに置き換えたくなります。
そうすれば xml だろうが yaml だろうが C からは lua テーブルとしてアクセスすればいいだけです。
そんなわけで適当にググって発見した luaXml と luaYaml の使い勝手を試してみようかなと考えているところです。
posted by JUNOSOFT at 11:18| Comment(0) | プログラミング

2014年10月22日

C#ツールバーのDockをTopにしてもClientで隠される

C# でフォームデザインしているときに地味に困ったのが以下の現象です。

・フォーム上にツールバーを配置する
・ツールバーの Dock を Top に設定してフォームの上に貼りつくようにする
・ツールバーの下側に適当なパネルを配置する
・パネルの Dock を Client に設定する

すると... !!
なんと ツールバーの存在がガン無視されて、パネルがツールバーの裏側にまで回り込んでしまうのです!当然パネルの上端はツールバーによって隠されます。
すごい地味な嫌がらせですよこれは。
仕方がないので Dock で設定せずに Ancher だけでそれっぽいことをやっていたのですが、やっぱり気持ち悪いです。
というわけで調べてみたところ、パネルとツールバーの優先順位を入れ替えればよいという、ただそれだけのことでした。

Docking with ToolStrip and Panel
http://stackoverflow.com/questions/17069256/docking-with-toolstrip-and-panel

[表示]→[その他のウィンドウ]→[ドキュメントアウトライン] と辿っていくと、GUIコントロールのツリー構造を編集できるウィンドウが表示されます。
ここを見ると、ツールバーのほうがパネルよりも上に位置していると思うので、これをドラッグしてツールバーのほうが下側に来るようにします。
この状態で Dock を設定すると、みごとに問題解決します。
posted by JUNOSOFT at 00:43| Comment(0) | プログラミング

2014年10月20日

RGBとアルファ値で別々の合成式を使う

漠然と不思議に思っていたんです。Diretxでアルファ合成したときに、合成後のアルファ値はどうなっているのだろうかと。
普通に考えれば不透明のターゲットに対して半透明の画像をアルファ合成したとき、合成後のアルファ値は不透明なままになるのが自然なのですが、アルファ合成の式を

device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);

と設定しているのにアルファ値だけ計算方法が異なるというのもおかしな話です。となると、アルファ値も上記の式に従っているはずなのですが…。
しかし合成後のアルファ値というのは使う機会がなく、別にどんな値でも最終的に描画される画像にも影響しないために特に追求することなく放置していました。

ところが合成語のアルファ値を使う機会が出てきてしまったのです。そう、レンダーターゲットへの描画です。
不透明画像があるレンダーターゲットに対して半透明画像をアルファ合成してから、そのレンダーターゲットを描画すると、半透明画像の部分だけアルファ値がおかしくなります。

アルファ部分だけ別の合成式にする設定さえあれば…と考えたところでふと思い出したのですが、そういえば以前 OpenGL のマニュアルで Separate blend ナントカって関数を見たなと。
それをみた当時はさっぱり意味が分からず、glBlendFunc 以外にも合成関数があったのかぐらいに思っていたのですが、考えてみたら名前がすごくそれっぽいです。
そこで OpenGL オンラインマニュアルの glBlendFunc を開き、関連項目を見てみると、glBlendFuncSeparate というのがありました。まさに今、欲している機能です。

http://www.opengl.org/sdk/docs/man2/xhtml/glBlendFuncSeparate.xml

というわけで、この glBlendFuncSeparate 相当の機能を Direct3D9 で探してみようと google 先生に聞いてみたところ、D3DRS_SEPARATEALPHABLENDENABLE という単語が引っかかりました。
で、最終的に以下のページに行きつき、目的の関数と設定を得ることができました

http://msdn.microsoft.com/ja-jp/library/bb147328(v=vs.85).aspx
http://marupeke296.com/cgi-bin/cbbs/cbbs.cgi?mode=al2&namber=1423&rev=&no=0&P=R&KLOG=2

これでRGBとAで異なる合成関数を適用してみたところ、見事にアルファがらみの問題がなくなりました。
めでたし、めでたしです。

しかしまさか OpenGL のマニュアルに助けられるとは。あれを思い出さなかったら、調べるのにもっと時間がかかったかもしれません。

posted by JUNOSOFT at 08:59| Comment(0) | プログラミング

2014年09月29日

FLTK2.0

コントロールのドッキングができる FLTK Dock (http://fltkdock.sourceforge.net/) を使ってみたくて入手したのですが、どうやら FLTK 2.0 専用のようで、FLTK 1.3 ではコンパイルできません。
そこで FLTK 2.0 を持ってきてビルドしようとしたのですが、ライブラリをビルドする時に苦労したのでメモです。

まず FLTK 2 はサブバージョンのリポジトリから直接もってくる必要があるので、svn をインストールします。自分は Tortoise SVN を使いました。説明文によれば、ユーザー名とパスワードは両方とも "ENTER" と入れればよいそうです。
FLTK のリポジトリをチェックアウトしたら ide/visualc/ にある Visual C++ のファイルを開きます。
いくつかプロジェクトが含まれていますが、そのうちの "fltk" が fltk2 のスタティックライブラリのビルド用で、"fltk_gl" が OpenGL と組み合わせる時に使うライブラリです。これをビルドし、できあがったライブラリをリンクすれば良いのですが、そう素直には行きません。

ここで作ったライブラリを自分のプロジェクトからリンクして使おうとすると、elete_associations_for の実体がないというリンカエラーが発生します。
この実体、実は src/win32/WidgetAssociation.cxx にあるのですが、このソースファイルは元のfltk プロジェクトファイルには含まれておらず、#include “win32/WidgetAssociation.cxx”という感じで run.cxx から直接インクルードされています。
ソースファイルを連結しているだけなので問題ないように見えるのですが、なぜかダメみたいです。
というわけで、win32/WidgetAssociation.cxx を fltk プロジェクトに追加し、再びビルドします。

これでリンカエラーが出ずに、FLTK2 が使えるようになりました。

そして当初の目的であった FLTK Dock を使おうとしたら、なんと古いバージョンの FLTK2 用らしく、いろいろなところでコンパイルエラーが。
一気にモチベーションがさがり、それっきり FLTK を触っていません…。
posted by JUNOSOFT at 05:03| Comment(0) | プログラミング

2014年09月04日

FLTK

必要最低限の機能を押さえていて、インストール&ビルドが楽、ということで最近 FLTK 1.3 をテストしています。
ボタンやツリービュー、メニュー、タブなど一通りのコントロールがそろっていて、なによりも無改造で日本語に対応している点がよいですね!
フォントを変更する必要すらありません。FLTK は文字列を utf-8 で扱っているので(wchar_t ではなく、マルチバイト文字列であることに注意)、それさえ気を付ければ簡単に日本語を表示する事ができます。

まず普通にアルファベットを表示したりするときは

Fl_Window *wnd = new Fl_Window(0, 0, 320, 240, “HELLO”);

のようにします。日本語で表示させたい時はまず UTF8 に変換する必要がありますから、

std::string utf8(const std::string &s);

とかいう適当な変換関数を用意して、

Fl_Window *wnd = new Fl_Window(0, 0, 320, 240, utf8(“ウィンドウ”).c_str());

のようにすればいいです…といいたいところですが、これはうまく行きません。
Fl_Window をはじめとして FLTK のコントロールはコンストラクタで渡された文字列ポインタをそのまま保持しているみたいです。
そのため文字列の実体がずっと存在することが前提となっているんですね。
ところが上記のような指定方法だと、文字列の実体は初期化式を抜けた時に破棄されてしまい、ウィンドウのタイトルとして不正な文字列が使われてしまいます。

これを回避するには、単純に static な文字列を指定するか、あるいは文字列引数を省略して(コンストラクタでの文字列指定はオプション引数になっている)
とりあえず生成してしまい、あとから copy_label でタイトルを指定する必要があります。

Fl_Window *wnd = new Fl_Window(0, 0, 320, 240);
wnd->copy_label(utf8(“ウィンドウ”).c_str());


コンストラクタ以外でタイトルを指定するには label() と copy_label() があるのですが、
label() だとコンストラクタで指定するのと同じで文字列のポインタがそのまま保持されるだけになってしまい、ダメです。
copy_label() ならその名の通り文字列のコピーを保持するようになるため、安心して扱う事が出来ます

ちなみに 文字コード変換の関数はこんな感じで作れます

static std::wstring ToWide(int codepage, const std::string &s) {
if (s.empty()) return std::wstring();
int len = MultiByteToWideChar(codepage, 0, &s[0], -1, NULL, 0);
len--; // 終端の\0は不要
if (len <= 0) return std::wstring();
std::wstring ws(len, L'\0');
MultiByteToWideChar(codepage, 0, &s[0], -1, &ws[0], ws.length());
return ws;
}

static std::string ToMBSC(int codepage, const std::wstring &ws) {
if (ws.empty()) return std::string();
int len = WideCharToMultiByte(codepage, 0, &ws[0], -1, NULL, 0, NULL, NULL);
len--; // 終端の\0は不要
if (len <= 0) return std::string();
std::string s(len, '\0');
WideCharToMultiByte(codepage, 0, &ws[0], -1, &s[0], s.length(), NULL, NULL);
return s;
}

std::string utf8(const std::string &s) {
const int SJIS = 932;
std::wstring ws = ToWide(SJIS, s)
return ToMBSC(CP_UTF8, ws);
}

FLTK 2.0 もためしてみようかな


posted by JUNOSOFT at 06:38| Comment(0) | プログラミング

2014年08月15日

エディットコンテニュが効かない時

VC++ 2012 (Express) で、特定のプロジェクトだけエディットコンテニュが効かない現象に悩まされました。
一時停止中に適当に編集してから続行しても、再コンパイルする気配を全く見せず、なにかメッセージが出るわけでもなく、何事もなかったかのように再開します。
当然編集内容は反映されていません。

以前から使っているプロジェクトや、新規作成した状態プロジェクトではちゃんとできるので、なにか設定が悪いはず。
いろいろ考え、もしかしたら、と思って静的リンクしているライブラリを外してみたところ、見事にエディットコンテニュできるようになりました。

どうやらリンクしているライブラリに、リリースモードでビルドされていたものが混ざっていたようです。
というわけでライブラリのソースを持ってきてデバッグモードで自前ビルドし、そのライブラリにリンクするようにしたところ、うまくいきました。
無駄な時間を過ごしてしまった…
posted by JUNOSOFT at 23:49| Comment(0) | プログラミング

2014年08月12日

minmax

WinDef.h に min マクロと max マクロがあって、ちょくちょく使っていたのですがこれって std::min std::max と思い切り衝突するんですよね...
どうせなテンプレート版の min/max を使いたいのですが、そうすると Visual C++ のコンパイラに怒られるのであきらめていました。
ところが、よくよく見たら

#ifndef NOMINMAX

なんてスイッチがあるではないですか。WinDef.h をインクルードする (Windows.h から間接インクルードしている場合がほとんどだと思う)
前にこれを define しておけば無効化されるようです。


しかし min max が定義済みってのは少しやりにくいですね。あと、rad1 が定義済みなのも地味に痛いんですよ。
ラジアン値を入れるのに一時変数名で rad = GetAngle(A) みたいに使ったりするので。角度値を複数入れようとし rad0 = GetAngle(A); rad1 = GetAngle(B) とかやろうとするとアウトです。


posted by JUNOSOFT at 05:42| Comment(0) | プログラミング