Table of Contents
やりたいこと
統合エミュであるBizHawkから、Luaスクリプトを介してSocketを発信する。
これができると、例えばゲーム内のメモリデータをダンプし、Luaを介して別アプリにSocket送信ができるので、Luaでは出来ないOSの機能をいくらでも使えるようになる。
BizHawk側でやること
BizHawkは自前のSocket通信APIが積んであるんだが、何故かGUIのくせにコマンドからIP等の設定をしないと通信機能が使えないという謎仕様である。
具体的にはLuaスクリプトで
comm.socketServerSend("fuck the police")
とかやっても、
Socket server was not initialized, please initialize it via the command line
-1
と怒られる。
初期化されてないなら初期化すればええやんと思うんだが、初期化する関数ねーんだこれが。
で、ソース見たら「コマンドラインでipとportを設定した場合のみ初期化する」という仕様だった。なんでや。
というわけで、BizHawk起動はコマンドラインを介して行う。
BizHawk.exeと同じディレクトリにrun.batあたりの名前でバッチファイルを作成するのが手っ取り早い。内容は以下。
@echo off
EmuHawk --socket_ip=127.0.0.1 --socket_port=22222
exit
ただし起動時に即サーバーへ接続を試みた挙げ句、失敗するとそれっきりなので、まずサーバーを立てておく必要がある。
サーバーをたてる
今回はC#のコンソールアプリケーションで例を示す。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SocketServer
{
class Program
{
static void Main(string[] args)
{
TcpListener tcp;
const int PORT = 22222;
IPAddress IP = IPAddress.Parse("127.0.0.1");
//127.0.0.1に22222のソケットサーバを建てる
tcp = new TcpListener(IP, PORT);
//受付開始
Console.Write("Waiting for a connection... ");
tcp.Start();
var cli = tcp.AcceptTcpClient();
Console.WriteLine("Connected!");
//読み込みループ
var nstr = cli.GetStream();
try
{
while (cli.Connected)
{
byte[] buf = new byte[1024];
var cnt = nstr.Read(buf, 0, 1024);
var str = Encoding.UTF8.GetString(buf, 0, cnt);
Console.WriteLine(str);
}
}
catch (Exception ex)
{
//エミュを終了させると例外になったりするので見なかったことにする
}
}
}
}
これを実行した状態で改めてcomm.socketServerSend(str)すれば送った文字列がそのままコンソールに出てくるぞ。
コネクションを保った状態でストリームに垂れ流す感じなので、あとはだらだらストリームをループから読めばいい。