Wiiリモコンの値をJavaScriptで取得する方法(Wiiインターネットチャンネル)

任天堂のQ&Aサイトで、Wiiリモコンの値を取得する方法が公開されていることを知人から教えてもらいました。


インターネットチャンネル向けのウェブページを作りたいのですが…。 : Q&A – Wii

インターネットチャンネルの拡張機能について知りたい
Wiiインターネットチャンネルでは特別な JavaScript を用いる事でWiiリモコンのひねりや
テレビとの距離、複数のコントローラの状態を取得する事ができます。

手元にWii本体の実機がないので(Wiiリモコンはある^^)まだ試していませんが、こんな感じでJavaScriptからWiiリモコンの値が取れるっぽいですね。

if (window.opera && window.opera.wiiremote) {
  var num = 0; // wiiremote number 0,1,2,3
  var pad = window.opera.wiiremote.update(num);
  if (pad.isEnabled && pad.isDataValid) {
    //
    var x = null;
    var y = null;
    if (pad.dpdValidity > 0) {
       x = pad.dpdX;
       y = pad.dpdY;
    }
    //
    // if (!pad.isBrowsing) { var hold = pad.hold; }
    var button_left  = (pad.hold & 1);
    var button_right = (pad.hold & 2);
    var button_up    = (pad.hold & 4);
    var button_down  = (pad.hold & 8);
    var button_plus  = (pad.hold & 16);
    var button_2     = (pad.hold & 256);
    var button_1     = (pad.hold & 512);
    var button_B     = (pad.hold & 1024);
    var button_A     = (pad.hold & 2048);
    var button_minus = (pad.hold & 4096);
    //
    var distance = pad.dpdDistance;
    var roll_angle = Math.atan2(pad.dpdRollY, pad.dpdRollX) * 180.0 / Math.PI;
    //
    // hogehoge
  }
}

numの値を変えれば、2本目以降のリモコンの値も取れるみたいです。

画面からの距離(dpdDistance)やリモコンの傾き(dpdRollY, dpdRollX)の情報が取れるのは面白いですね。
Wiiリモコンを用いたインタフェースの研究開発とかを個人の家庭用ゲーム機で実現できるので、hackしがいがあるかも。

拡張機能アツすぎます。

実際に動いたー!っていう人がいればぜひ教えてください。

SWF Binary Golf on FlashLite

先週の土曜日の勉強会で発表した資料を公開します。

FizzBuzz SWF Binary Golf on FlashLite 1.1

FizzBuzz SWF Binary Golf on FlashLite 1.1
http://namazu.org/~takesako/swf/FizzBuzz-SWF-Golf.ppt

申し訳ないことにActionScriptの話は一つもでてきません。
SWFファイルの構造解析とASバイトコードの話です。
そんなシチュエーションがあるかどうかわかりませんが、
SWFファイルのバイナリを直接いじりたいときに役に立つのではないかと。

勉強会ではどの発表も面白かったのですが、個人的にはBeInteractive!のyossyさんとASバイトコードの話ができて嬉しかったです。

[お約束] SWF で FizzBuzz ってみた

とりあえず

(1) 正解のFizzBuzz文字列をそのまま出力した場合 -> 478 byte (FlashLite1.1)
http://namazu.org/~takesako/swf/fizz478.txt

(2) FizzBuzzを計算しながら出力した場合 -> 251 byte (FlashLite1.1)
http://namazu.org/~takesako/swf/fizz251.txt

(3) FizzBuzzを計算しながら出力した場合 -> 159 byte (FlashLite2.0)
http://namazu.org/~takesako/swf/fizz159.txt

ここまで圧縮できました。

ASバイトコード最適化

ASバイトコードの最適化の過程はこんな感じで

http://namazu.org/~takesako/swf/

--- fizz287.flm	
+++ fizz161.flm
@@ -1,71 +1,48 @@
-movie 'fizz287.swf' // flash 4, total frames: 1, frame rate: 12 fps, 104x104 px
+movie 'fizz161.swf' compressed // flash 6, total frames: 1, frame rate: 12 fps, 104x104 px

   frame 0
-    push 'i', '0'
-    setVariable
    label1:
-    push 'i', 'i'
+    push '100', 'i', 'i', 'i'
     getVariable
     increment
     setVariable
-    push '100', 'i'
     getVariable
     oldLessThan
-    not
-    not
     branchIfTrue label6
-    push 'x', 'x', 'x'
-    getVariable
-    push 'i'
+    push 'x', 'x'
     getVariable
     push 'i'
     getVariable
     push '15'
-    divide
-    int
-    push '15'
-    multiply
-    subtract
+    modulo
     branchIfTrue label2
     push 'FizzBuzz'
     branch label5
    label2:
     push 'i'
     getVariable
-    push 'i'
-    getVariable
     push '5'
-    divide
-    int
-    push '5'
-    multiply
-    subtract
+    modulo
     branchIfTrue label3
     push 'Buzz'
     branch label5
    label3:
     push 'i'
     getVariable
-    push 'i'
-    getVariable
     push '3'
-    divide
-    int
-    push '3'
-    multiply
-    subtract
+    modulo
     branchIfTrue label4
     push 'Fizz'
     branch label5
    label4:
     push 'i'
     getVariable
    label5:
     concat
     push ' '
     concat
     setVariable
     branch label1
    label6:
   end // of frame 0
end

yossyさんから教えてもらったFlasmのコードでASバイトコードを読みやすい形に変換しています。

最後のFizzBuzz159byteへの圧縮は、ちょっとトリッキーなことをしています。

僕はActionScriptの経験は素人以下ですが、SWFバイナリの話ならできますので、
またどこかでAS関係のイベントがあれば声を掛けてくださると嬉しいです。(><)

この度は貴重な勉強会に参加できてよかったです。ありがとうございました。

連載企画 FizzBuzz ではじめる Code Golf (x86 32bit) 入門

Code Golf とは? Matzにっき(2006-10-05) より

ゴルフとは如何に少ないストロークでホールインするかを競う競技である。
コードゴルフとは、如何に少ないキーストローク(バイト数)で、プログラムを実装できるかを競う競技である。

先日FizzBuzz.com (MS-DOS 16bit版) を作ってみたら、32bit版のプログラムにも挑戦したくなりましたので、x86 32bitで命令長を減らすテクニックについて紹介したいと思います。

※まずはコード長の比較のみで実行クロック数は競わないことにします。

■ x86 32bit コード最適化

【問題】EBXレジスタに1を、EAXレジスタに4を代入したい

できるだけ短いバイト数でコードを実現するためには、いろいろなx86命令をフル活用することを考えます。

自分の思いついた解答をNASMの記法で書いてみます。

続きを読む

FizzBuzz x86 for バイナリアン

昨日の続き。今日は息抜きに FizzBuzz.com (MS-DOS 16bit版) を作ってみました。

0000000 b4 02 bb 31 30 30 ed e8 2c 00 e8 29 00 e8 39 00 
0000020 e8 23 00 e8 3e 00 e8 30 00 e8 1a 00 e8 17 00 e8
0000040 27 00 e8 2f 00 e8 0e 00 e8 1e 00 e8 08 00 e8 05
0000060 00 e8 13 00 eb d1 80 ff 30 74 04 88 fa cd 21 88
0000100 da cd 21 e8 28 00 c3 fe c5 b2 46 cd 21 b2 69 cd
0000120 21 e9 08 00 b2 42 cd 21 b2 75 cd 21 b2 7a cd 21
0000140 cd 21 84 ed 75 04 e8 05 00 c3 30 ed eb e6 b2 0d
0000160 cd 21 b2 0a cd 21 fe c3 80 fb 3a 75 09 b3 30 fe
0000200 c7 80 ff 3a 74 01 c3 b8 00 4c cd 21
0000214

これで140byte

続きを読む

FizzBuzz – Golf Challenge

FizzBuzzプログラムを書くのが流行っているみたいなので私も参加してみることに。

Perl部門

1. 目指せ最短 (perl -eも含めて56byte)

perl -e’die+map{(Fizz)[$_%3].(Buzz)[$_%5]||$_,$/}1..1e2′

※ perl -lオプションを使わずに最短を目指す。標準エラー出力がNGの場合はprintを使って57byteに

perl -e’print+(Fizz)[$_%3].(Buzz)[$_%5]||$_,$/for 1..1e2′

anarchy golf – FizzBuzz で換算すると48byteでPerl最短 (perl -eを含めない)

print+(Fizz)[$_%3].(Buzz)[$_%5]||$_,$/for 1..1e2

これだと perl FizzBuzz.pl と実行できて Code Golf に参加できます。

お約束の展開

2. ppencodeバージョンで

perl -e "print q q print q and print chr oct oct ord uc q map m and print chr oct oct oct ord uc q else and print chr ord uc qw q for q and print chr ord q tie gt and print chr length q x rename sethostent srand pack pipe setpwent syscall else eq split sleep endservent qw require symlink ne keys ord require x and print chr length q q splice srand getservbyname setnetent ne reset endprotoent foreach scalar rewinddir cos setnetent not else getprotobyname q and print chr oct oct oct ord uc q rmdir and print chr oct hex ord uc q dump and and print chr oct oct oct ord uc qw q binmode q and print chr oct hex ord uc q my m and print chr oct oct oct ord uc q oct no and print chr oct oct ord uc q rmdir and print chr oct hex ord uc qw q wait q and print chr oct oct ord uc qw q fcntl q and print chr oct hex ord q q eq and print chr ord uc qw q bind q and print chr ord q dump and and print chr length q q splice srand getservbyname setnetent ne reset endprotoent foreach scalar rewinddir cos setnetent not else getprotobyname q and print chr length q q splice srand getservbyname setnetent ne reset endprotoent foreach scalar rewinddir cos setnetent not else getprotobyname q and print chr oct oct oct ord uc q rmdir and print chr oct hex ord uc q dump and and print chr oct oct oct ord uc qw q bless q and print chr oct hex ord uc q my m and print chr oct oct oct ord uc q lc eval and print chr oct ord uc q each ne and print chr oct hex ord uc qw q wait q and print chr oct oct hex ord qw q die q and print chr oct oct hex ord qw q die q and print chr oct oct oct ord uc qw q binmode q and print chr oct hex ord uc q my m and print chr oct oct ord uc qw q bind q and print chr oct oct oct ord uc qw q binmode q and print chr oct oct ord uc qw q gt q and print chr ord qw q for q and print chr ord q xor x and print chr ord q or no and print chr ord q q q and print chr oct oct oct ord q eq ne and print chr oct oct ord uc qw q fcntl q and print chr oct oct ord uc qw q for q and print chr oct oct oct ord q eq le and print chr ord q ne sin and print chr hex ord q m alarm" | perl

※ perlの予約語だけでプログラミングした場合

他の Perl Monger の解答

3. 404 Blog Not Found:ブクマゴルフってどうよ? (66byte)

perl -le ‘print $_%15?$_%5?$_%3?$_:Fizz:Buzz:FizzBuzz for(1..100)’

※オーソドックスな実装

4. ひおにっき(2007-05-09) [Program] FizzBuzz (56byte)

perl -le’print+(Fizz)[$_%3].(Buzz)[$_%5]||$_ for 1..100′

※インスパイヤの元ネタ。おそらくこれが最短でスマートな実装かも。hioさんの実装よりも短くしようと頑張ったけど、結局抜けませんでした。

5. Golf Challenge: FizzBuzz (この中から面白い実装をピックアップ)

perl -le ‘print+($_,Fizz,Buzz,FizzBuzz)[3&19142723>>2*$_%30]for 1..100′

※ あとでググって見つけたページ。自分の解答もかぶっててちょっと悔しかったです。(><)

6. YappoLogs: FizzBuzzのPerlさいたんきろくたっせい(34ばいと) (Yappoさんのwarn実装)

perl -le’warn((Fizz)[$_%3].(Buzz)[$_%5]||$_)for 1..100′

※ FizzBuzz at -e line 1. みたいな表示になるけど、hioさんの実装より1byte短くなる

7. Acme::FizzBuzz を使えば、これ最強

SET PERL5OPT=-MAcme::FizzBuzz                 # MS-DOSの場合
setenv PERL5OPT="-MAcme::FizzBuzz"            # tcsh系の場合
PERL5OPT="-MAcme::FizzBuzz"; export PERL5OPT  # bash系の場合

※ 環境変数PERL5OPTを使う方法はmiyagawaさんに教えてもらいました。

perl -e1

やっぱりPerl最強です。Ruby や Python でもこの最短記録を抜けるのかな?

anarchy golf – FizzBuzz #Language Ranking ではPerlを抜いてBashが1位で43byte、すげー。どんなコードなんだろうか。興味津々です。

Multi-USB::MissileLauncher for Win32

YAPC::Asia 2007 Tokyo で大人気だった USB::MissileLauncher をマルチに制御するパッチを作りましたので公開します。

Multi-USB::MissileLauncher for Win32 binary package
http://namazu.org/~takesako/pub/usblauncher-20070501.zip

Triple USB Missile Launcher

■ ctlmissileコマンド使用法

Usage: ctlmissile [ up | down | left | right | fire | stop ] [ 3000]

オリジナルからの変更点

http://www.earth.li/~noodles/files/usblauncher-0.0.3.tar.gz からの変更点

* ctlmissile.c.patch

  1. コンパイルオプション -DLINUX -DWIN32 の追加
    (Linux以外のWindows、Mac OS X の環境でも動作するように)
  2. msec秒でコマンドを発行するコマンドライン引数 [ 3000 ] を追加
  3. 複数のUSBミサイルランチャーの接続に対応
    同時制御と逐次制御が可能

■ インストール方法

Windows の場合

事前にLibUsb-Win32からダウンロードできるlibusb-win32-filter-bin-0.1.12.1.exeをインストール

$ gcc -DWIN32 ctlmissile.c -o ctlmissile -lusb

Linux の場合

ディストリビューション付属のlibusbパッケージをインストール

$ gcc -DLINUX ctlmissile.c -o ctlmissile -lusb

Mac OS X の場合

libusbをインストール

$ gcc ctlmissile.c -o ctlmissile -lusb

■ 応用

POE::Component::Server::TCPを使って、USBミサイルランチャーを制御するTCPデーモンを1時間で書く。

missile_server.pl

#!/usr/bin/perl
use POE qw(Component::Server::TCP);
use strict;

sub main {
  my $bind_port = $ARGV[0] || 6969;

  my $kernel = POE::Component::Server::TCP->new(
    Port     => $bind_port,
    Error    => \&error_handler,
    Concurrency => -1,

    ClientInput        => \&handle_client_input,
    ClientConnected    => \&handle_client_connect,
    ClientDisconnected => \&handle_client_disconnect,
    ClientError        => \&handle_client_error,
    ClientFlushed      => \&handle_client_flush,
    ClientShutdownOnError => 0,
  );

  POE::Kernel->run();
}

sub accept_handler {
  my ($socket, $remote_address, $remote_port) = @_[ARG0, ARG1, ARG2];
}

sub error_handler {
  my ($syscall_name, $error_number, $error_string) = @_[ARG0, ARG1, ARG2];
}

sub exe {
  my ($cmd) = @_;
  $cmd =~ s/[^\s\d\w]//g;
  system split(/\s+/, $cmd);
}

sub handle_client_input {
  my $heap = $_[HEAP];
  my $kernel = $_[KERNEL];
  my $input_record = $_[ARG0];
  my $msg = "yes sir, $input_record";
  if ($input_record =~ m/(shutdown|quit)/i) {
    $kernel->yield("shutdown");
    $msg = "connection closed...";
  } elsif ($input_record =~ m/help/i) {
    $msg = "Ugage: [ up | down | left | right | fire | stop ] [ 3000 ]";
  } elsif ($input_record =~ m/^\s*$/ims) {
    $msg = "help";
  } else {
    exe("ctlmissile $input_record");
  }
  $heap->{client}->put($msg);
}

sub handle_client_error {
  my ($syscall_name, $error_number, $error_string) = @_[ARG0, ARG1, ARG2];
}

sub handle_client_connect {
  my $heap = $_[HEAP];
  $heap->{client}->put("connected on USB-Missile-Launcher 200 OK");
}

sub handle_client_disconnect {}

sub handle_client_flush {}

main();

1;

POEのプログラミングは初めてでしたが、perldoc POE::Component::Server::TCP 見ながら簡単に書けました。

■参考URL

YappoLogs: ミサイルは国境を越える 
http://blog.yappo.jp/yappo/archives/000504.html

Google Maps: ミサイルが本当に国境を越えてる???
http://maps.google.com/maps?q=38.22657,-112.299&z=18&t=k

Tilting Google Maps and MissileLauncher - SlideShare (miyagawa-san at osdc.tw)
http://www.slideshare.net/miyagawa/tilting-google-maps-and-missilelauncher/

throw new CybozuLabsException() - libusbを使うPHP Extensionを作りました
http://labs.cybozu.co.jp/blog/tsuruoka/anubis/blog_show/43

TokuLog 改め Perl を極めて結婚するブログ - missile on ruby.
http://d.hatena.ne.jp/tokuhirom/20070407/1175935832

西尾泰和のブログ @ Cybozu Labs: PythonワンライナーでUSBミサイルランチャーを制御
http://labs.cybozu.co.jp/blog/nishio/2007/04/pythonusb.html

*BSDでのUSBデバイスドライバーの実装
http://www.ofug.net/~yamajun/presentation/2003/usb.html

ToDo

ctlmissile.cで複数のミサイルランチャーを制御する拡張コマンドを追加したので
(ひ)メモ – Assurer::Plugin::Notify::Missileの概要設計の実装が待たれるところです。

カテゴリー: Perl