2022-04-11 20:27:15 +02:00
|
|
|
{% extends "konami.html" %}
|
2021-12-29 02:41:21 +01:00
|
|
|
{% block title %}Application protocol{% endblock %}
|
2021-12-28 21:54:12 +01:00
|
|
|
{% block body %}
|
|
|
|
<h1>Application Protocol</h1>
|
|
|
|
<p>As the previous pages have eluded to (you <i>did</i> read them, didn't you?), eAmuse uses HTTP as its main way of
|
|
|
|
getting data around. This means we need an HTTP server running but, as we'll see, we don't need to think too
|
|
|
|
hard about that.</p>
|
|
|
|
<p>Every request made is a <code>POST</code> request, to <code>//<model>/<module>/<method></code>,
|
2021-12-29 05:39:45 +01:00
|
|
|
with its body being encoded data as described in the previous sections. This behaviour can be altered using the
|
|
|
|
<code>url_slash</code> flag in <code>ea3-config.xml</code>. Disabling this switches to using
|
|
|
|
<code>/?model=...&module=...&method=...</code> for requests instead. Make sure to implement both of these if
|
|
|
|
implementing a server!
|
2021-12-28 21:54:12 +01:00
|
|
|
</p>
|
|
|
|
<p>Every request is followed immediately by a response. Any response code other than <code>200</code> is considered
|
|
|
|
a failure.</p>
|
|
|
|
|
|
|
|
<details>
|
|
|
|
<summary>Source code details</summary>
|
|
|
|
<figure>
|
|
|
|
<img src="images/200_only.png">
|
|
|
|
<figcaption><code>libavs-win32-ea3.dll:0x1000f8e7</code></figcaption>
|
|
|
|
</figure>
|
|
|
|
</details>
|
|
|
|
|
|
|
|
<p>All requests follow a basic format:</p>
|
2021-12-28 23:29:33 +01:00
|
|
|
<pre>{% highlight "cxml" %}<call model="??model" srcid="??srcid" tag="??tag">
|
|
|
|
<??module method="??method" ...attributes>
|
|
|
|
...children
|
|
|
|
</??module>
|
|
|
|
</call>{% endhighlight %}</pre>
|
2021-12-28 21:54:12 +01:00
|
|
|
<p>The responses follow a similar format:</p>
|
2021-12-28 23:29:33 +01:00
|
|
|
<pre>{% highlight "cxml" %}<response>
|
|
|
|
<??module status="??status" ...attributes>
|
|
|
|
...children
|
|
|
|
</??module>
|
|
|
|
</response>{% endhighlight %}</pre>
|
2021-12-28 21:54:12 +01:00
|
|
|
<p>With <code>"0"</code> being a successful status. Convention is to identify a specific method as
|
|
|
|
<code><i>module</i>.<i>method</i></code>, and we'll be following this convention in this document too. There are
|
|
|
|
a <i>lot</i> of possible methods, so the majority of this document is a big reference for them all. There are a
|
|
|
|
number of generic methods, and a number of game specific ones. If you haven't clocked yet, I've been working on
|
|
|
|
an SDVX 4 build for most of these pages, and each game also comes with its own set of game-specific methods.
|
2022-01-12 22:57:26 +01:00
|
|
|
These methods are sometimes namespaced tidily, and in other cases are strewn all over the place. Namespaces I'm
|
|
|
|
currently aware of are listed below. Note that <code>game.*</code> is used by many games, and has identically named
|
|
|
|
methods within the <code>game</code> module. Expect to need to filter based on model code for this one.
|
2021-12-28 21:54:12 +01:00
|
|
|
</p>
|
2022-01-12 22:57:26 +01:00
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<td><code>game.*</code></td>
|
|
|
|
<td>Sound Voltex I</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>game.sv4_*</code></td>
|
|
|
|
<td>Sound Voltex IV</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>game.sv5_*</code></td>
|
|
|
|
<td>Sound Voltex V</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>game.sv6_*</code></td>
|
|
|
|
<td>Sound Voltex VI</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>exchain_*</code></td>
|
|
|
|
<td>GITADORA EXCHAIN</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>matixx_*</code></td>
|
|
|
|
<td>GITADORA Matixx</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>nextage_*</code></td>
|
|
|
|
<td>GITADORA NEXTAGE</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>op2_*</code></td>
|
|
|
|
<td>Nostalgia Op.2</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>game.*</code>, <code>playerdata.*</code></td>
|
|
|
|
<td>Pop'n Music</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>game.*</code></td>
|
|
|
|
<td>HELLO! POP'N MUSIC</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>info22.*</code>, <code>player22.*</code></td>
|
|
|
|
<td>Pop'n Music 22 (Lapistoria)</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>info23.*</code>, <code>player23.*</code></td>
|
|
|
|
<td>Pop'n Music 23 (éclale)</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>info24.*</code>, <code>player24.*</code></td>
|
|
|
|
<td>Pop'n Music 24 (Usagi to Neko to Shounen no Yume)</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>game_3.*</code></td>
|
|
|
|
<td>Museca</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>info2.*</code>, <code>player2.*</code></td>
|
|
|
|
<td>BeatStream</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
2021-12-28 21:54:12 +01:00
|
|
|
<p>Paths in the XML bodies are formatted using an XPath-like syntax. That is, <code>status@/response</code> gets the
|
|
|
|
<code>status</code> attribute from <code>response</code>, and <code>response/eacoin/sequence</code> would return
|
|
|
|
that node's value.
|
|
|
|
</p>
|
|
|
|
<p><b>NOTE:</b> I am using the non-standard notation of <code><node* ...</code> and
|
|
|
|
<code><node attr*="" ...</code> to indicate that an attribute or node is not always present! Additionally, I
|
|
|
|
am going to use the notation of <code><node[]></code> to indicate that a node repeats.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<td>Status</td>
|
|
|
|
<td>Meaning</td>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tr>
|
|
|
|
<td><code>0</code></td>
|
|
|
|
<td>Success</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>109</code></td>
|
|
|
|
<td>No profile</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>110</code></td>
|
|
|
|
<td>Not allowed</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>112</code></td>
|
|
|
|
<td>Card not found (<code>cardmng.inquire</code>)</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>116</code></td>
|
|
|
|
<td>Card pin invalid (<code>cardmng.authpass</code>)</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
<details>
|
|
|
|
<summary>How to reverse engineer these calls</summary>
|
|
|
|
<p>Turns out bemani have been quite sensible in how they implemented their code for creating structures, so it's
|
|
|
|
rather readable. That said, if you've been using Ghidra (like me!), this is the time to switch to IDA. I'll
|
|
|
|
let the below screenshots below speak for themselves:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<details>
|
|
|
|
<summary>Ghidra</summary>
|
|
|
|
<img src="images/eventlog_ghidra.png">
|
|
|
|
<img src="images/matching_request_ghidra.png">
|
|
|
|
</details>
|
|
|
|
<details>
|
|
|
|
<summary>IDA Pro</summary>
|
|
|
|
<img src="images/eventlog_ida.png">
|
|
|
|
<img src="images/matching_request_ida.png">
|
|
|
|
</details>
|
|
|
|
|
|
|
|
<p>I know which of these I'd rather use for reverse engineering (sorry, Ghidra)!</p>
|
|
|
|
</details>
|
|
|
|
|
2022-02-12 09:59:54 +01:00
|
|
|
<h2>Service URLs</h2>
|
|
|
|
<p>By design, different modules call to different service endpoints. This is totally optional (all endpoints can be set
|
|
|
|
to the same value) however it can also be leveraged to simplify deployment. The first request any game makes when
|
|
|
|
starting is <code>services.get</code>, which is made to the service URL configured in the ea3 configuration. The
|
|
|
|
response to this request returns a list of endpoints and their corresponding URLs.</p>
|
|
|
|
<p>Notably, the <code>services.get</code> request contains everything required to identify a game, so it may be
|
|
|
|
beneficial to route different games to different URLs (where appropriate).</p>
|
|
|
|
<p>The endpoint names <b>are not</b> the same as module names. Many are, but similarly, many aren't.</p>
|
|
|
|
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<td>Endpoint</td>
|
|
|
|
<td>Modules serviced</td>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tr>
|
|
|
|
<td><code>lobby</code></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>lobby2</code></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>local</code></td>
|
|
|
|
<td><code>eventlog</code>, <code>game_3</code></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>local2</code></td>
|
|
|
|
<td><code>eventlog</code>, <code>playerdata</code>, <code>matching</code>, <code>system</code>,
|
|
|
|
<code>esoc</code>, <code>game</code>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>globby</code></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>pkglist</code></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>posevent</code></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td><code>netlog</code></td>
|
|
|
|
<td></td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
<p>Modules not listed can be assumed to be served by the endpoint of the same name. <b>This table is very
|
|
|
|
incomplete.</b></p>
|
|
|
|
|
2021-12-28 21:54:12 +01:00
|
|
|
<h2>Possible XRPC requests</h2>
|
|
|
|
|
2021-12-28 23:29:33 +01:00
|
|
|
{{ generate_xrpc_list()|safe }}
|
2021-12-28 21:54:12 +01:00
|
|
|
{% endblock %}
|