Merge remote-tracking branch 'remotes/origin/pr/1080'
# Conflicts: # BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj merges PR #1080 closes PR #1080 (let's see if either of these can do it)
This commit is contained in:
commit
b179a30d99
|
@ -0,0 +1,149 @@
|
||||||
|
function round(num, numDecimalPlaces)
|
||||||
|
local mult = 10^(numDecimalPlaces or 0)
|
||||||
|
return math.floor(num * mult + 0.5) / mult
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_baseline()
|
||||||
|
i = 100
|
||||||
|
client.reboot_core()
|
||||||
|
t = os.clock()
|
||||||
|
|
||||||
|
while i > 0 do
|
||||||
|
emu.frameadvance()
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
baseline = os.clock() - t
|
||||||
|
print('Baseline: ' .. round(baseline, 3) .. " secs")
|
||||||
|
return baseline
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_mmf()
|
||||||
|
i = 100
|
||||||
|
client.reboot_core()
|
||||||
|
t = os.clock()
|
||||||
|
while i > 0 do
|
||||||
|
emu.frameadvance()
|
||||||
|
comm.mmfScreenshot()
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
print('Memory mapped files: ' .. round((os.clock() - t - baseline), 3) .. " secs")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_http()
|
||||||
|
print("Testing HTTP server")
|
||||||
|
client.reboot_core()
|
||||||
|
i = 100
|
||||||
|
t = os.clock()
|
||||||
|
|
||||||
|
while i > 0 do
|
||||||
|
emu.frameadvance()
|
||||||
|
comm.httpTestGet()
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
print('HTTP get: ' .. round((os.clock() - t - baseline), 3) .. " secs")
|
||||||
|
|
||||||
|
client.reboot_core()
|
||||||
|
i = 100
|
||||||
|
t = os.clock()
|
||||||
|
|
||||||
|
while i > 0 do
|
||||||
|
emu.frameadvance()
|
||||||
|
comm.httpPostScreenshot()
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
print('HTTP post: ' .. round((os.clock() - t - baseline), 3) .. " secs")
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_socket()
|
||||||
|
|
||||||
|
i = 100
|
||||||
|
client.reboot_core()
|
||||||
|
t = os.clock()
|
||||||
|
while i > 0 do
|
||||||
|
emu.frameadvance()
|
||||||
|
comm.socketServerScreenShot()
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
print('Socket server: ' .. round((os.clock() - t - baseline), 3) .. " secs")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_socketresponse()
|
||||||
|
best_time = -100
|
||||||
|
timeouts = {1, 2, 3, 4, 5, 10, 20, 25, 50, 100, 250, 500, 1000}
|
||||||
|
comm.socketServerSetTimeout(1000)
|
||||||
|
resp = comm.socketServerScreenShotResponse()
|
||||||
|
for t, timeout in ipairs(timeouts) do
|
||||||
|
comm.socketServerSetTimeout(timeout)
|
||||||
|
client.reboot_core()
|
||||||
|
print("Trying to find minimal timeout for Socket server")
|
||||||
|
i = 100
|
||||||
|
t = os.clock()
|
||||||
|
while i > 0 do
|
||||||
|
emu.frameadvance()
|
||||||
|
resp = comm.socketServerScreenShotResponse()
|
||||||
|
if resp ~= 'ack' then
|
||||||
|
i = -100
|
||||||
|
print(resp)
|
||||||
|
print("Failed to a get a proper response")
|
||||||
|
end
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
if i > -100 then
|
||||||
|
print("Best timeout: " .. timeout .. " msecs")
|
||||||
|
print("Best time: " .. round((os.clock() - t - baseline), 3) .. " secs")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_http_response()
|
||||||
|
err = false
|
||||||
|
print("Testing HTTP server response")
|
||||||
|
client.reboot_core()
|
||||||
|
i = 100
|
||||||
|
|
||||||
|
while i > 0 do
|
||||||
|
emu.frameadvance()
|
||||||
|
resp = comm.httpTestGet()
|
||||||
|
if resp ~= "<html><body><h1>hi!</h1></body></html>" then
|
||||||
|
print("Failed to get correct HTTP get response")
|
||||||
|
print(resp)
|
||||||
|
i = 0
|
||||||
|
err = true
|
||||||
|
end
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
if not err then
|
||||||
|
print("HTTP GET looks fine: No errors occurred")
|
||||||
|
end
|
||||||
|
|
||||||
|
client.reboot_core()
|
||||||
|
i = 100
|
||||||
|
err = false
|
||||||
|
while i > 0 do
|
||||||
|
emu.frameadvance()
|
||||||
|
resp = comm.httpPostScreenshot()
|
||||||
|
if resp ~= "<html><body>OK</body></html>" then
|
||||||
|
print("Failed to get correct HTTP post response")
|
||||||
|
print(resp)
|
||||||
|
i = 0
|
||||||
|
err = true
|
||||||
|
end
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
if not err then
|
||||||
|
print("HTTP POST looks fine: No errors occurred")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
baseline = get_baseline()
|
||||||
|
test_socket()
|
||||||
|
test_mmf()
|
||||||
|
test_http()
|
||||||
|
print("#####################")
|
||||||
|
test_http_response()
|
||||||
|
test_socketresponse()
|
||||||
|
print()
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
print("##########################################################")
|
||||||
|
getUrl = comm.httpGetGetUrl()
|
||||||
|
print("GET URL: " .. getUrl)
|
||||||
|
|
||||||
|
postUrl = comm.httpGetPostUrl()
|
||||||
|
print("POST URL: " .. postUrl)
|
||||||
|
|
||||||
|
print("\nChecking GET URL change")
|
||||||
|
error = false
|
||||||
|
comm.httpSetGetUrl('a')
|
||||||
|
if (getUrl ~= comm.httpGetGetUrl()) then
|
||||||
|
comm.httpSetGetUrl(getUrl)
|
||||||
|
error = (getUrl ~= comm.httpGetGetUrl())
|
||||||
|
else
|
||||||
|
error = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if error == false then
|
||||||
|
print("Get URL was successfully changed")
|
||||||
|
else
|
||||||
|
print("Error while changing Get URL")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
print("\nChecking POST URL change")
|
||||||
|
error = false
|
||||||
|
comm.httpSetPostUrl('a')
|
||||||
|
if (postUrl ~= comm.httpGetPostUrl()) then
|
||||||
|
comm.httpSetPostUrl(postUrl)
|
||||||
|
error = (postUrl ~= comm.httpGetPostUrl())
|
||||||
|
else
|
||||||
|
error = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if error == false then
|
||||||
|
print("Post URL was successfully changed")
|
||||||
|
else
|
||||||
|
print("Error while changing Post URL")
|
||||||
|
end
|
||||||
|
|
||||||
|
print("\nChecking GET request")
|
||||||
|
getResponse = comm.httpGet("http://tasvideos.org/BizHawk.html")
|
||||||
|
if string.find(getResponse, "Bizhawk") then
|
||||||
|
print("GET seems to work")
|
||||||
|
else
|
||||||
|
print("Either the Bizhawk site is down or the GET does not work")
|
||||||
|
end
|
||||||
|
|
||||||
|
print("\nChecking memory mapped filed")
|
||||||
|
|
||||||
|
size = comm.mmfScreenshot()
|
||||||
|
if size > 0 then
|
||||||
|
print("Memory mapped file was successfully written")
|
||||||
|
else
|
||||||
|
print("Failed to write memory mapped file")
|
||||||
|
end
|
||||||
|
|
||||||
|
mmf_filename = comm.mmfGetFilename()
|
||||||
|
print("MMF filename: " .. mmf_filename)
|
||||||
|
comm.mmfSetFilename("deleteme.tmp")
|
||||||
|
error = false
|
||||||
|
if (mmf_filename ~= comm.mmfGetFilename()) then
|
||||||
|
comm.mmfSetFilename(mmf_filename)
|
||||||
|
error = (mmf_filename ~= comm.mmfGetFilename())
|
||||||
|
else
|
||||||
|
error = true
|
||||||
|
end
|
||||||
|
if error == false then
|
||||||
|
print("MMF filename successfully changed")
|
||||||
|
else
|
||||||
|
print("MMF filename change failed")
|
||||||
|
end
|
||||||
|
|
||||||
|
print("Writing to MMF")
|
||||||
|
|
||||||
|
message = "ABC"
|
||||||
|
resp_n = tonumber(comm.mmfWrite(mmf_filename, message))
|
||||||
|
if (resp_n ~= string.len(message)) then
|
||||||
|
print("Failed to write to MMF")
|
||||||
|
else
|
||||||
|
resp = comm.mmfRead(mmf_filename, string.len(message))
|
||||||
|
if (resp ~= message) then
|
||||||
|
print("Failed to read from MMF")
|
||||||
|
else
|
||||||
|
print("MMF read and read OK")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
print("\nTests finished")
|
||||||
|
print("Please run TestCommunication_All.lua with the supplied Python server for a more comprehensive test")
|
|
@ -27,11 +27,14 @@ namespace BizHawk.Client.EmuHawk
|
||||||
public bool luaConsole = false;
|
public bool luaConsole = false;
|
||||||
public int socket_port = 9999;
|
public int socket_port = 9999;
|
||||||
public string socket_ip = null;
|
public string socket_ip = null;
|
||||||
|
public string mmf_filename = null;
|
||||||
|
public string URL_get = null;
|
||||||
|
public string URL_post = null;
|
||||||
|
|
||||||
|
public void ParseArguments(string[] args)
|
||||||
|
|
||||||
public void parseArguments(string[] args)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i<args.Length; i++)
|
for (int i = 0; i < args.Length; i++)
|
||||||
{
|
{
|
||||||
// For some reason sometimes visual studio will pass this to us on the commandline. it makes no sense.
|
// For some reason sometimes visual studio will pass this to us on the commandline. it makes no sense.
|
||||||
if (args[i] == ">")
|
if (args[i] == ">")
|
||||||
|
@ -62,8 +65,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
}
|
}
|
||||||
else if (arg.StartsWith("--dump-frames="))
|
else if (arg.StartsWith("--dump-frames="))
|
||||||
{
|
{
|
||||||
var list = arg.Substring(arg.IndexOf('=') + 1);
|
string list = arg.Substring(arg.IndexOf('=') + 1);
|
||||||
var items = list.Split(',');
|
string[] items = list.Split(',');
|
||||||
_currAviWriterFrameList = new HashSet<int>();
|
_currAviWriterFrameList = new HashSet<int>();
|
||||||
foreach (string item in items)
|
foreach (string item in items)
|
||||||
{
|
{
|
||||||
|
@ -110,11 +113,55 @@ namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
socket_ip = arg.Substring(arg.IndexOf('=') + 1);
|
socket_ip = arg.Substring(arg.IndexOf('=') + 1);
|
||||||
}
|
}
|
||||||
|
else if (arg.StartsWith("--mmf="))
|
||||||
|
{
|
||||||
|
mmf_filename = args[i].Substring(args[i].IndexOf('=') + 1);
|
||||||
|
}
|
||||||
|
else if (arg.StartsWith("--url_get="))
|
||||||
|
{
|
||||||
|
URL_get = args[i].Substring(args[i].IndexOf('=') + 1);
|
||||||
|
}
|
||||||
|
else if (arg.StartsWith("--url_post="))
|
||||||
|
{
|
||||||
|
URL_post = args[i].Substring(args[i].IndexOf('=') + 1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cmdRom = args[i];
|
cmdRom = args[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
////initialize HTTP communication
|
||||||
|
if (URL_get != null || URL_post != null)
|
||||||
|
{
|
||||||
|
if (URL_get != null)
|
||||||
|
{
|
||||||
|
GlobalWin.httpCommunication.initialized = true;
|
||||||
|
GlobalWin.httpCommunication.SetGetUrl(URL_get);
|
||||||
|
}
|
||||||
|
if (URL_post != null)
|
||||||
|
{
|
||||||
|
GlobalWin.httpCommunication.initialized = true;
|
||||||
|
GlobalWin.httpCommunication.SetPostUrl(URL_post);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//inititalize socket server
|
||||||
|
if (socket_ip != null && socket_port > -1)
|
||||||
|
{
|
||||||
|
GlobalWin.socketServer.initialized = true;
|
||||||
|
GlobalWin.socketServer.SetIp(socket_ip, socket_port);
|
||||||
|
}
|
||||||
|
else if (socket_ip != null)
|
||||||
|
{
|
||||||
|
GlobalWin.socketServer.initialized = true;
|
||||||
|
GlobalWin.socketServer.SetIp(socket_ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
//initialize mapped memory files
|
||||||
|
if (mmf_filename != null)
|
||||||
|
{
|
||||||
|
GlobalWin.memoryMappedFiles.initialized = true;
|
||||||
|
GlobalWin.memoryMappedFiles.SetFilename(mmf_filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.DirectoryServices" />
|
<Reference Include="System.DirectoryServices" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Numerics" />
|
<Reference Include="System.Numerics" />
|
||||||
<Reference Include="System.Xaml" />
|
<Reference Include="System.Xaml" />
|
||||||
<Reference Include="System.Xml.Linq">
|
<Reference Include="System.Xml.Linq">
|
||||||
|
@ -197,6 +198,7 @@
|
||||||
<Compile Include="BizBoxInfoControl.Designer.cs">
|
<Compile Include="BizBoxInfoControl.Designer.cs">
|
||||||
<DependentUpon>BizBoxInfoControl.cs</DependentUpon>
|
<DependentUpon>BizBoxInfoControl.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Communication.cs" />
|
||||||
<Compile Include="config\AnalogRangeConfig.cs">
|
<Compile Include="config\AnalogRangeConfig.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -877,6 +879,7 @@
|
||||||
<DependentUpon>NewHexEditor.cs</DependentUpon>
|
<DependentUpon>NewHexEditor.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Client.cs" />
|
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Client.cs" />
|
||||||
|
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Communication.cs" />
|
||||||
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Console.cs" />
|
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Console.cs" />
|
||||||
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.cs" />
|
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.cs" />
|
||||||
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Forms.cs" />
|
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Forms.cs" />
|
||||||
|
@ -2179,4 +2182,4 @@
|
||||||
<PreBuildEvent />
|
<PreBuildEvent />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(SolutionDir)Build\Common.targets" />
|
<Import Project="$(SolutionDir)Build\Common.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -0,0 +1,445 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.IO.MemoryMappedFiles;
|
||||||
|
using BizHawk.Bizware.BizwareGL;
|
||||||
|
using System.Drawing;
|
||||||
|
using BizHawk.Emulation.Common;
|
||||||
|
using BizHawk.Client.Common;
|
||||||
|
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace BizHawk.Client.EmuHawk
|
||||||
|
{
|
||||||
|
|
||||||
|
public class Communication
|
||||||
|
{
|
||||||
|
|
||||||
|
public class HttpCommunication
|
||||||
|
{
|
||||||
|
private static HttpClient client = new HttpClient();
|
||||||
|
private string PostUrl = "http://localhost:9876/post/";
|
||||||
|
private string GetUrl = "http://localhost:9876/index";
|
||||||
|
public bool initialized = false;
|
||||||
|
private ScreenShot screenShot = new ScreenShot();
|
||||||
|
public int timeout = 0;
|
||||||
|
public int default_timeout = 500;
|
||||||
|
|
||||||
|
public void SetTimeout(int _timeout)
|
||||||
|
{
|
||||||
|
//timeout = _timeout.TotalMilliseconds;
|
||||||
|
if (timeout == 0 && _timeout == 0)
|
||||||
|
{
|
||||||
|
timeout = default_timeout;
|
||||||
|
}
|
||||||
|
if (_timeout != 0)
|
||||||
|
{
|
||||||
|
client.Timeout = new TimeSpan(0, 0, 0, _timeout / 1000, _timeout % 1000);
|
||||||
|
timeout = _timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public void SetPostUrl(string url)
|
||||||
|
{
|
||||||
|
PostUrl = url;
|
||||||
|
}
|
||||||
|
public void SetGetUrl(string url)
|
||||||
|
{
|
||||||
|
GetUrl = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetGetUrl()
|
||||||
|
{
|
||||||
|
return GetUrl;
|
||||||
|
}
|
||||||
|
public string GetPostUrl()
|
||||||
|
{
|
||||||
|
return PostUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> Get(string url)
|
||||||
|
{
|
||||||
|
client.DefaultRequestHeaders.ConnectionClose = false;
|
||||||
|
HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false);
|
||||||
|
if (response.IsSuccessStatusCode) {
|
||||||
|
return await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> Post(string url, FormUrlEncodedContent content)
|
||||||
|
{
|
||||||
|
client.DefaultRequestHeaders.ConnectionClose = true;
|
||||||
|
HttpResponseMessage response = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = await client.PostAsync(url, content).ConfigureAwait(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MessageBox.Show(e.ToString());
|
||||||
|
return e.ToString();
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TestGet()
|
||||||
|
{
|
||||||
|
Task<String> getResponse = Get(GetUrl);
|
||||||
|
return getResponse.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SendScreenshot(string url, string parameter)
|
||||||
|
{
|
||||||
|
int trials = 5;
|
||||||
|
var values = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{parameter, screenShot.GetScreenShotAsString()},
|
||||||
|
};
|
||||||
|
FormUrlEncodedContent content = new FormUrlEncodedContent(values);
|
||||||
|
|
||||||
|
Task<string> postResponse = null;
|
||||||
|
while (postResponse == null && trials > 0)
|
||||||
|
{
|
||||||
|
postResponse = Post(PostUrl, content);
|
||||||
|
trials -= 1;
|
||||||
|
}
|
||||||
|
return postResponse.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SendScreenshot()
|
||||||
|
{
|
||||||
|
return SendScreenshot(PostUrl, "screenshot");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SendScreenshot(string url)
|
||||||
|
{
|
||||||
|
return SendScreenshot(url, "screenshot");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ExecGet(string url)
|
||||||
|
{
|
||||||
|
return Get(url).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ExecGet()
|
||||||
|
{
|
||||||
|
return Get(GetUrl).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ExecPost(string url, string payload)
|
||||||
|
{
|
||||||
|
var values = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{"payload", payload},
|
||||||
|
};
|
||||||
|
FormUrlEncodedContent content = new FormUrlEncodedContent(values);
|
||||||
|
return Post(url, content).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ExecPost(string payload)
|
||||||
|
{
|
||||||
|
var values = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{"payload", payload},
|
||||||
|
};
|
||||||
|
FormUrlEncodedContent content = new FormUrlEncodedContent(values);
|
||||||
|
return Post(PostUrl, content).Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class SocketServer
|
||||||
|
{
|
||||||
|
|
||||||
|
public string ip = "192.168.178.21";
|
||||||
|
public int port = 9999;
|
||||||
|
public Decoder decoder = Encoding.UTF8.GetDecoder();
|
||||||
|
public Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
public IPAddress ipAdd;
|
||||||
|
public IPEndPoint remoteEP;
|
||||||
|
public IVideoProvider currentVideoProvider = null;
|
||||||
|
public bool connected = false;
|
||||||
|
public bool initialized = false;
|
||||||
|
public int retries = 10;
|
||||||
|
public bool success = false; //indicates whether the last command was executed succesfully
|
||||||
|
|
||||||
|
public void Initialize(IVideoProvider _currentVideoProvider)
|
||||||
|
{
|
||||||
|
currentVideoProvider = _currentVideoProvider;
|
||||||
|
SetIp(ip, port);
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
public void Connect()
|
||||||
|
{
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
Initialize(currentVideoProvider);
|
||||||
|
}
|
||||||
|
remoteEP = new IPEndPoint(ipAdd, port);
|
||||||
|
soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
soc.Connect(remoteEP);
|
||||||
|
connected = true;
|
||||||
|
soc.ReceiveTimeout = 5;
|
||||||
|
|
||||||
|
}
|
||||||
|
public void SetIp(string ip_)
|
||||||
|
{
|
||||||
|
ip = ip_;
|
||||||
|
ipAdd = System.Net.IPAddress.Parse(ip);
|
||||||
|
remoteEP = new IPEndPoint(ipAdd, port);
|
||||||
|
}
|
||||||
|
public void SetIp(string ip_, int port_)
|
||||||
|
{
|
||||||
|
ip = ip_;
|
||||||
|
port = port_;
|
||||||
|
ipAdd = System.Net.IPAddress.Parse(ip);
|
||||||
|
remoteEP = new IPEndPoint(ipAdd, port);
|
||||||
|
|
||||||
|
}
|
||||||
|
public void SetTimeout(int timeout)
|
||||||
|
{
|
||||||
|
soc.ReceiveTimeout = timeout;
|
||||||
|
}
|
||||||
|
public void SocketConnected()
|
||||||
|
{
|
||||||
|
bool part1 = soc.Poll(1000, SelectMode.SelectRead);
|
||||||
|
bool part2 = (soc.Available == 0);
|
||||||
|
if (part1 && part2)
|
||||||
|
connected = false;
|
||||||
|
else
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
public int SendString(string SendString)
|
||||||
|
{
|
||||||
|
|
||||||
|
int sentBytes = SendBytes(Encoding.ASCII.GetBytes(SendString));
|
||||||
|
success = sentBytes > 0;
|
||||||
|
return sentBytes;
|
||||||
|
}
|
||||||
|
public int SendBytes(byte[] SendBytes)
|
||||||
|
{
|
||||||
|
int sentBytes = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sentBytes = soc.Send(SendBytes);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
sentBytes = -1;
|
||||||
|
}
|
||||||
|
return sentBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SendScreenshot()
|
||||||
|
{
|
||||||
|
return SendScreenshot(0);
|
||||||
|
}
|
||||||
|
public string SendScreenshot(int waitingTime)
|
||||||
|
{
|
||||||
|
if (!connected)
|
||||||
|
{
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
ScreenShot screenShot = new ScreenShot();
|
||||||
|
using (BitmapBuffer bb = screenShot.MakeScreenShotImage())
|
||||||
|
{
|
||||||
|
using (var img = bb.ToSysdrawingBitmap())
|
||||||
|
{
|
||||||
|
byte[] bmpBytes = screenShot.ImageToByte(img);
|
||||||
|
int sentBytes = 0;
|
||||||
|
int tries = 0;
|
||||||
|
while (sentBytes <= 0 && tries < retries)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tries++;
|
||||||
|
sentBytes = SendBytes(bmpBytes);
|
||||||
|
}
|
||||||
|
catch (SocketException)
|
||||||
|
{
|
||||||
|
Connect();
|
||||||
|
sentBytes = 0;
|
||||||
|
}
|
||||||
|
if (sentBytes == -1)
|
||||||
|
{
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success = (tries < retries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String resp = "";
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
resp = "Screenshot could not be sent";
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
resp = "Screenshot was sent";
|
||||||
|
}
|
||||||
|
if (waitingTime == 0)
|
||||||
|
{
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
resp = "";
|
||||||
|
resp = ReceiveMessage();
|
||||||
|
if (resp == "")
|
||||||
|
{
|
||||||
|
resp = "Failed to get a response";
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
public string ReceiveMessage()
|
||||||
|
{
|
||||||
|
if (!connected)
|
||||||
|
{
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
string resp = "";
|
||||||
|
byte[] receivedBytes = new byte[256];
|
||||||
|
int receivedLength = 1;
|
||||||
|
|
||||||
|
while (receivedLength > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
receivedLength = soc.Receive(receivedBytes, receivedBytes.Length, 0);
|
||||||
|
resp += Encoding.ASCII.GetString(receivedBytes);
|
||||||
|
} catch
|
||||||
|
{
|
||||||
|
receivedLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
public bool Successful()
|
||||||
|
{
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MemoryMappedFiles
|
||||||
|
{
|
||||||
|
public string filename_main = "BizhawkTemp_main";
|
||||||
|
public Dictionary<string, MemoryMappedFile> mmf_files = new Dictionary<string, MemoryMappedFile>();
|
||||||
|
public int index = 0;
|
||||||
|
public bool initialized = false;
|
||||||
|
public int main_size = 10 ^ 5;
|
||||||
|
ScreenShot screenShot = new ScreenShot();
|
||||||
|
|
||||||
|
public void SetFilename(string filename)
|
||||||
|
{
|
||||||
|
filename_main = filename;
|
||||||
|
}
|
||||||
|
public string GetFilename()
|
||||||
|
{
|
||||||
|
return filename_main;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ScreenShotToFile()
|
||||||
|
{
|
||||||
|
ScreenShot screenShot = new ScreenShot();
|
||||||
|
var bb = screenShot.MakeScreenShotImage();
|
||||||
|
var img = bb.ToSysdrawingBitmap();
|
||||||
|
byte[] bmpBytes = screenShot.ImageToByte(img);
|
||||||
|
return WriteToFile(@filename_main, bmpBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int WriteToFile(string filename, byte[] outputBytes)
|
||||||
|
{
|
||||||
|
MemoryMappedFile mmf_file;
|
||||||
|
int bytesWritten = -1;
|
||||||
|
if (mmf_files.TryGetValue(filename, out mmf_file) == false)
|
||||||
|
{
|
||||||
|
mmf_file = MemoryMappedFile.CreateOrOpen(filename, outputBytes.Length);
|
||||||
|
mmf_files[filename] = mmf_file;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (MemoryMappedViewAccessor accessor = mmf_file.CreateViewAccessor(0, outputBytes.Length, MemoryMappedFileAccess.Write))
|
||||||
|
{
|
||||||
|
accessor.WriteArray<byte>(0, outputBytes, 0, outputBytes.Length);
|
||||||
|
bytesWritten = outputBytes.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mmf_file.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mmf_file = MemoryMappedFile.CreateOrOpen(filename, outputBytes.Length);
|
||||||
|
mmf_files[filename] = mmf_file;
|
||||||
|
using (MemoryMappedViewAccessor accessor = mmf_file.CreateViewAccessor(0, outputBytes.Length, MemoryMappedFileAccess.Write))
|
||||||
|
{
|
||||||
|
accessor.WriteArray<byte>(0, outputBytes, 0, outputBytes.Length);
|
||||||
|
bytesWritten = outputBytes.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadFromFile(string filename, int expectedSize)
|
||||||
|
{
|
||||||
|
MemoryMappedFile mmf_file = mmf_file = MemoryMappedFile.OpenExisting(@filename);
|
||||||
|
using (MemoryMappedViewAccessor viewAccessor = mmf_file.CreateViewAccessor())
|
||||||
|
{
|
||||||
|
byte[] bytes = new byte[expectedSize];
|
||||||
|
viewAccessor.ReadArray(0, bytes, 0, bytes.Length);
|
||||||
|
string text = Encoding.UTF8.GetString(bytes);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScreenShot
|
||||||
|
//makes all functionalities for providing screenshots available
|
||||||
|
{
|
||||||
|
private IVideoProvider currentVideoProvider = null;
|
||||||
|
private ImageConverter converter = new ImageConverter();
|
||||||
|
public BitmapBuffer MakeScreenShotImage()
|
||||||
|
{
|
||||||
|
if (currentVideoProvider == null)
|
||||||
|
{
|
||||||
|
currentVideoProvider = Global.Emulator.AsVideoProviderOrDefault();
|
||||||
|
}
|
||||||
|
return GlobalWin.DisplayManager.RenderVideoProvider(currentVideoProvider);
|
||||||
|
}
|
||||||
|
public byte[] ImageToByte(Image img)
|
||||||
|
{
|
||||||
|
return (byte[])converter.ConvertTo(img, typeof(byte[]));
|
||||||
|
}
|
||||||
|
public string ImageToString(Image img)
|
||||||
|
{
|
||||||
|
return Convert.ToBase64String(ImageToByte(img));
|
||||||
|
}
|
||||||
|
public string GetScreenShotAsString()
|
||||||
|
{
|
||||||
|
BitmapBuffer bb = MakeScreenShotImage();
|
||||||
|
byte[] imgBytes = ImageToByte(bb.ToSysdrawingBitmap());
|
||||||
|
return Convert.ToBase64String(imgBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,5 +24,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
public static GLManager GLManager;
|
public static GLManager GLManager;
|
||||||
|
|
||||||
public static int ExitCode;
|
public static int ExitCode;
|
||||||
|
public static Communication.HttpCommunication httpCommunication = new Communication.HttpCommunication();
|
||||||
|
public static Communication.SocketServer socketServer = new Communication.SocketServer();
|
||||||
|
public static Communication.MemoryMappedFiles memoryMappedFiles = new Communication.MemoryMappedFiles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
argParse.parseArguments(args);
|
argParse.ParseArguments(args);
|
||||||
|
|
||||||
Database.LoadDatabase(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "gamedb.txt"));
|
Database.LoadDatabase(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "gamedb.txt"));
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using NLua;
|
||||||
|
using BizHawk.Emulation.Common;
|
||||||
|
using BizHawk.Client.Common;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BizHawk.Client.EmuHawk
|
||||||
|
{
|
||||||
|
[Description("A library for communicating with other programs")]
|
||||||
|
public sealed class CommunicationLuaLibrary : LuaLibraryBase
|
||||||
|
{
|
||||||
|
[RequiredService]
|
||||||
|
private IEmulator Emulator { get; set; }
|
||||||
|
|
||||||
|
[RequiredService]
|
||||||
|
private IVideoProvider VideoProvider { get; set; }
|
||||||
|
|
||||||
|
public CommunicationLuaLibrary(Lua lua)
|
||||||
|
: base(lua) { }
|
||||||
|
|
||||||
|
public CommunicationLuaLibrary(Lua lua, Action<string> logOutputCallback)
|
||||||
|
: base(lua, logOutputCallback) { }
|
||||||
|
|
||||||
|
public override string Name => "comm";
|
||||||
|
|
||||||
|
//TO DO: not fully working yet!
|
||||||
|
[LuaMethod("getluafunctionslist", "returns a list of implemented functions")]
|
||||||
|
public static string GetLuaFunctionsList()
|
||||||
|
{
|
||||||
|
var list = new StringBuilder();
|
||||||
|
foreach (var function in typeof(CommunicationLuaLibrary).GetMethods())
|
||||||
|
{
|
||||||
|
list.AppendLine(function.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
[LuaMethod("socketServerScreenShot", "sends a screenshot to the Socket server")]
|
||||||
|
public string SocketServerScreenShot()
|
||||||
|
{
|
||||||
|
return GlobalWin.socketServer.SendScreenshot();
|
||||||
|
}
|
||||||
|
[LuaMethod("socketServerScreenShotResponse", "sends a screenshot to the Socket server and retrieves the response")]
|
||||||
|
public string SocketServerScreenShotResponse()
|
||||||
|
{
|
||||||
|
return GlobalWin.socketServer.SendScreenshot(1000).ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
[LuaMethod("socketServerSend", "sends a string to the Socket server")]
|
||||||
|
public string SocketServerSend(string SendString)
|
||||||
|
{
|
||||||
|
return "Sent : " + GlobalWin.socketServer.SendString(SendString).ToString() + " bytes";
|
||||||
|
}
|
||||||
|
[LuaMethod("socketServerResponse", "receives a message from the Socket server")]
|
||||||
|
public string SocketServerResponse()
|
||||||
|
{
|
||||||
|
return GlobalWin.socketServer.ReceiveMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
[LuaMethod("socketServerSuccessful", "returns the status of the last Socket server action")]
|
||||||
|
public bool SocketServerSuccessful()
|
||||||
|
{
|
||||||
|
return GlobalWin.socketServer.Successful();
|
||||||
|
}
|
||||||
|
[LuaMethod("socketServerSetTimeout", "sets the timeout in milliseconds for receiving messages")]
|
||||||
|
public void SocketServerSetTimeout(int timeout)
|
||||||
|
{
|
||||||
|
GlobalWin.socketServer.SetTimeout(timeout);
|
||||||
|
}
|
||||||
|
// All MemoryMappedFile related methods
|
||||||
|
[LuaMethod("mmfSetFilename", "Sets the filename for the screenshots")]
|
||||||
|
public void MmfSetFilename(string filename)
|
||||||
|
{
|
||||||
|
GlobalWin.memoryMappedFiles.SetFilename(filename);
|
||||||
|
}
|
||||||
|
[LuaMethod("mmfGetFilename", "Gets the filename for the screenshots")]
|
||||||
|
public string MmfSetFilename()
|
||||||
|
{
|
||||||
|
return GlobalWin.memoryMappedFiles.GetFilename();
|
||||||
|
}
|
||||||
|
|
||||||
|
[LuaMethod("mmfScreenshot", "Saves screenshot to memory mapped file")]
|
||||||
|
public int MmfScreenshot()
|
||||||
|
{
|
||||||
|
return GlobalWin.memoryMappedFiles.ScreenShotToFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
[LuaMethod("mmfWrite", "Writes a string to a memory mapped file")]
|
||||||
|
public int MmfWrite(string mmf_filename, string outputString)
|
||||||
|
{
|
||||||
|
return GlobalWin.memoryMappedFiles.WriteToFile(mmf_filename, Encoding.ASCII.GetBytes(outputString));
|
||||||
|
}
|
||||||
|
[LuaMethod("mmfRead", "Reads a string from a memory mapped file")]
|
||||||
|
public string MmfRead(string mmf_filename, int expectedSize)
|
||||||
|
{
|
||||||
|
return GlobalWin.memoryMappedFiles.ReadFromFile(mmf_filename, expectedSize).ToString();
|
||||||
|
}
|
||||||
|
// All HTTP related methods
|
||||||
|
[LuaMethod("httpTest", "tests HTTP connections")]
|
||||||
|
public string HttpTest()
|
||||||
|
{
|
||||||
|
var list = new StringBuilder();
|
||||||
|
list.AppendLine(GlobalWin.httpCommunication.TestGet());
|
||||||
|
list.AppendLine(GlobalWin.httpCommunication.SendScreenshot());
|
||||||
|
list.AppendLine("done testing");
|
||||||
|
return list.ToString();
|
||||||
|
}
|
||||||
|
[LuaMethod("httpTestGet", "tests the HTTP GET connection")]
|
||||||
|
public string HttpTestGet()
|
||||||
|
{
|
||||||
|
return GlobalWin.httpCommunication.TestGet();
|
||||||
|
}
|
||||||
|
[LuaMethod("httpGet", "makes a HTTP GET request")]
|
||||||
|
public string HttpGet(string url)
|
||||||
|
{
|
||||||
|
return GlobalWin.httpCommunication.ExecGet(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
[LuaMethod("httpPost", "makes a HTTP POST request")]
|
||||||
|
public string HttpPost(string url, string payload)
|
||||||
|
{
|
||||||
|
return GlobalWin.httpCommunication.ExecPost(url, payload);
|
||||||
|
}
|
||||||
|
[LuaMethod("httpPostScreenshot", "HTTP POST screenshot")]
|
||||||
|
public string HttpPostScreenshot()
|
||||||
|
{
|
||||||
|
return GlobalWin.httpCommunication.SendScreenshot();
|
||||||
|
}
|
||||||
|
[LuaMethod("httpSetTimeout", "Sets HTTP timeout in milliseconds")]
|
||||||
|
public void HttpSetTimeout(int timeout)
|
||||||
|
{
|
||||||
|
GlobalWin.httpCommunication.SetTimeout(timeout);
|
||||||
|
}
|
||||||
|
[LuaMethod("httpSetPostUrl", "Sets HTTP POST URL")]
|
||||||
|
public void HttpSetPostUrl(string url)
|
||||||
|
{
|
||||||
|
GlobalWin.httpCommunication.SetPostUrl(url);
|
||||||
|
}
|
||||||
|
[LuaMethod("httpSetGetUrl", "Sets HTTP GET URL")]
|
||||||
|
public void HttpSetGetUrl(string url)
|
||||||
|
{
|
||||||
|
GlobalWin.httpCommunication.SetGetUrl(url);
|
||||||
|
}
|
||||||
|
[LuaMethod("httpGetPostUrl", "Gets HTTP POST URL")]
|
||||||
|
public string HttpGetPostUrl()
|
||||||
|
{
|
||||||
|
return GlobalWin.httpCommunication.GetPostUrl();
|
||||||
|
}
|
||||||
|
[LuaMethod("httpGetGetUrl", "Gets HTTP GET URL")]
|
||||||
|
public string HttpGetGetUrl()
|
||||||
|
{
|
||||||
|
return GlobalWin.httpCommunication.GetGetUrl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue