mirror of
https://gitea.tendokyu.moe/eamuse/docs.git
synced 2024-11-23 22:40:57 +01:00
Flask
This commit is contained in:
parent
20affcfa63
commit
2da6e2b056
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.pyc
|
||||
__pycache__/
|
||||
build/
|
@ -21,4 +21,4 @@
|
||||
</table>
|
||||
|
||||
|
||||
</body>
|
||||
{% endblock %}
|
79
docs.py
Normal file
79
docs.py
Normal file
@ -0,0 +1,79 @@
|
||||
from flask import Flask, send_from_directory, render_template
|
||||
from livereload import Server
|
||||
import os
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/styles.css")
|
||||
def styles():
|
||||
return send_from_directory(".", "styles.css")
|
||||
|
||||
|
||||
for base, folders, files in os.walk("images"):
|
||||
for name in files:
|
||||
def handler(base, name):
|
||||
def handler():
|
||||
return send_from_directory(base, name)
|
||||
return handler
|
||||
local_base = base.replace("\\", "/").strip(".").strip("/")
|
||||
route = local_base + "/" + name
|
||||
if not route.startswith("/"):
|
||||
route = "/" + route
|
||||
|
||||
handler = handler(base, name)
|
||||
handler.__name__ == route
|
||||
app.add_url_rule(route, route, handler)
|
||||
|
||||
TEMPLATES = "templates"
|
||||
PAGES_BASE = "pages"
|
||||
for base, folders, files in os.walk(TEMPLATES + "/" + PAGES_BASE):
|
||||
if ".git" in base:
|
||||
continue
|
||||
if base.startswith(TEMPLATES):
|
||||
base = base[len(TEMPLATES):]
|
||||
|
||||
for name in files:
|
||||
if name.endswith(".html"):
|
||||
def handler(base, name):
|
||||
def handler():
|
||||
return render_template(os.path.join(base, name).strip("/").replace("\\", "/"))
|
||||
return handler
|
||||
|
||||
local_base = base.replace("\\", "/").strip(".").strip("/")
|
||||
if local_base.startswith(PAGES_BASE):
|
||||
local_base = local_base[len(PAGES_BASE):]
|
||||
|
||||
route = local_base + "/" + name
|
||||
if route.endswith("/index.html"):
|
||||
route = route[:-10]
|
||||
if not route.startswith("/"):
|
||||
route = "/" + route
|
||||
|
||||
handler = handler(base, name)
|
||||
handler.__name__ == route
|
||||
app.add_url_rule(route, route, handler)
|
||||
|
||||
|
||||
from flask import url_for
|
||||
def has_no_empty_params(rule):
|
||||
defaults = rule.defaults if rule.defaults is not None else ()
|
||||
arguments = rule.arguments if rule.arguments is not None else ()
|
||||
return len(defaults) >= len(arguments)
|
||||
@app.route("/site-map")
|
||||
def site_map():
|
||||
links = []
|
||||
for rule in app.url_map.iter_rules():
|
||||
# Filter out rules we can't navigate to in a browser
|
||||
# and rules that require parameters
|
||||
if "GET" in rule.methods and has_no_empty_params(rule):
|
||||
url = url_for(rule.endpoint, **(rule.defaults or {}))
|
||||
links.append((url, rule.endpoint))
|
||||
return str(links)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.config['TEMPLATES_AUTO_RELOAD'] = True
|
||||
app.config['DEBUG'] = True
|
||||
|
||||
server = Server(app.wsgi_app)
|
||||
server.watch("templates")
|
||||
server.serve(port=3000)
|
7
freeze.py
Normal file
7
freeze.py
Normal file
@ -0,0 +1,7 @@
|
||||
from flask_frozen import Freezer
|
||||
from docs import app
|
||||
|
||||
freezer = Freezer(app)
|
||||
|
||||
if __name__ == '__main__':
|
||||
freezer.freeze()
|
106
index.html
106
index.html
@ -1,106 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href=".">Contents</a></td>
|
||||
<td><a href="./transport.html">Transport layer</a></td>
|
||||
<td><a href="./packet.html">Packet format</a></td>
|
||||
<td><a href="./protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>Benami/Konami e-Amusement API</h1>
|
||||
<p>Why?</p>
|
||||
<p>I was curious how these APIs work, yet could find little to nothing on Google. There are a number of
|
||||
closed-source projects, with presumably similarly closed-source internal documentation, and a scattering of
|
||||
implementations of things, yet I couldn't find a site that actually just documents how the API works. If I'm
|
||||
going to have to reverse engineer an open source project (or a closed source one, for that matter), I might as
|
||||
well just go reverse engineer an actual game (or it's stdlib, as most of my time has been spent currently).</p>
|
||||
<p>For the sake of being lazy, I'll probably end up calling it eAmuse more than anything else throughout these
|
||||
pages. Other names you may come across include <code>httac</code> and <code>xrpc</code>. The latter are the
|
||||
suite of HTTP functions used in the Bemani stdlib, and the name of their communication protocol they implement
|
||||
at the application layer, but whenever someone refers to any of them in the context of a rhythm game, they will
|
||||
be referring to the things documented here.</p>
|
||||
<p>These pages are very much a work in progress, and are being written <i>as</i> I reverse engineer parts of the
|
||||
protocol. I've been asserting all my assumptions by writing my own implementation as I go, however it currently
|
||||
isn't sharable quality code and, more importantly, the purpose of these pages is to make implementation of one's
|
||||
own code hopefully trivial (teach a man to fish, and all that).</p>
|
||||
<p>Sharing annotated sources for all of the games' stdlibs would be both impractical and unwise. Where relevant
|
||||
however I try to include snippets to illustrate concepts, and have included their locations in the source for if
|
||||
you feel like taking a dive too.</p>
|
||||
<p>If you're here because you work on one of those aforementioned closed source projects, hello! Feel free to share
|
||||
knowledge with the rest of the world, or point out corrections. Or don't; you do you.</p>
|
||||
|
||||
<h3>Code snippets</h3>
|
||||
<p>Across these pages there are a number of code snippets. They roughly break down into three categories:</p>
|
||||
<ul>
|
||||
<li>Assembly: Directly disassembled code from game binaries</li>
|
||||
<li>C: Either raw decompilation, or slightly cleaned up decompilation</li>
|
||||
<li>Python: Snippets from my local testing implementations</li>
|
||||
<li>Pseudocode: Used to illustrate some points. Note that it probably started life as Python before being
|
||||
pseudo'd</li>
|
||||
</ul>
|
||||
<p>If you yoink chunks of Python code, attribution is always appreciated, but consider it under CC0 (just don't be
|
||||
that person who tries to take credit for it, yeah?).</p>
|
||||
|
||||
<h2>Contents</h2>
|
||||
<ol>
|
||||
<li><a href="./transport.html">Transport layer</a></li>
|
||||
<ol>
|
||||
<li><a href="./transport.html#packet">Packet structure</a></li>
|
||||
<li><a href="./transport.html#type">Types</a></li>
|
||||
</ol>
|
||||
<li><a href="./packet.html">The inner packet structure</a></li>
|
||||
<ol>
|
||||
<li><a href="./packet.html#xml">XML packets</a></li>
|
||||
<li><a href="./packet.html#binary">Binary packed packets</a></li>
|
||||
<li><a href="./packet.html#schema">Binary schemas</a></li>
|
||||
<li><a href="./packet.html#data">Binary data</a></li>
|
||||
</ol>
|
||||
<li><a href="./protocol.html">Communication protocol details</a></li>
|
||||
<ul>
|
||||
<li>There are a crazy number of sub pages here, so just go check the contents there.</li>
|
||||
</ul>
|
||||
<li>Misc pages</li>
|
||||
<ol>
|
||||
<li><a href="./cardid.html">Parsing and converting card IDs</a></li>
|
||||
</ol>
|
||||
</ol>
|
||||
|
||||
<h2>Getting started</h2>
|
||||
<p>My aim with these pages is to cover as much as possible, so you don't need to try and figure them out yourself.
|
||||
That said, being able to follow along yourself will almost certainly help get more out of this. For following
|
||||
along with source code, you're really going to want to grab yourself a dumped copy of a game (it's going to be a
|
||||
lot easier, and cheeper, than dumping one yourself). I trust you can figure out where to find that.</p>
|
||||
<p>For network related things, your options are a little broader. The ideal would be physical ownership of a
|
||||
cabinet, and a subscription to genuine e-amusement. Odds are you don't have both of those :P. A connection to an
|
||||
alternative network works just as well. In the more likely case that you don't have a physical cabinet, it's
|
||||
time to crack out that dumped copy of a game and just run it on your own PC (or a VM, if you're not on Windows)
|
||||
(odds are whatever you downloaded came with the program you'll need to start it pre-packaged. If not, it rhymes
|
||||
with rice.).</p>
|
||||
<p>You will also need a local e-amusement-emulating server. By the time I'm done with these pages, there will
|
||||
hopefully be everything you need to be able to write your own. Unfortunately I'm not finished writing them;
|
||||
depending on where you acquired your game, it may have shipped with one of said servers. If it didn't, Asphyxia
|
||||
CORE will do the trick (yes, it's closed source).</p>
|
||||
<p>If this all sounds like way too much work, and/or you're just here because of curiosity, I plan to prepare some
|
||||
pcaps of network traffic to play around with without needing a running copy of a game or a network tap on a cab.
|
||||
</p>
|
||||
|
||||
<a href="./transport.html">Next page</a>
|
||||
|
||||
<p><small>This site intentionally looks not-great. I don't feel like changing that, and honestly quite like the
|
||||
aesthetic.</small></p>
|
||||
</body>
|
||||
|
||||
</html>
|
896
packet.html
896
packet.html
@ -1,896 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Packet format | eAmuse API</title>
|
||||
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href=".">Contents</a></td>
|
||||
<td><a href="./transport.html">Transport layer</a></td>
|
||||
<td><a href="./packet.html">Packet format</a></td>
|
||||
<td><a href="./protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>Packet format</h1>
|
||||
|
||||
<p>eAmuse uses XML for its application layer payloads*. This XML is either verbatim, or in a custom packed binary
|
||||
format.<br /><small>*Newer games use JSON, but this page is about XML.</small></p>
|
||||
|
||||
|
||||
<h2 id="xml">The XML format</h2>
|
||||
|
||||
<p>Each tag that contains a value has a <code>__type</code> attribute that identifies what type it is. Array types
|
||||
have a <code>__count</code> attribute indicating how many items are in the array. Binary blobs additionally have
|
||||
a <code>__size</code> attribute indicating their length (this is notably not present on strings, however).</p>
|
||||
<p>It is perhaps simpler to illustrate with an example, so:</p>
|
||||
<pre><code><?xml version='1.0' encoding='UTF-8'?>
|
||||
<call model="KFC:J:A:A:2019020600" srcid="1000" tag="b0312077">
|
||||
<eventlog method="write">
|
||||
<retrycnt __type="u32" />
|
||||
<data>
|
||||
<eventid __type="str">G_CARDED</eventid>
|
||||
<eventorder __type="s32">5</eventorder>
|
||||
<pcbtime __type="u64">1639669516779</pcbtime>
|
||||
<gamesession __type="s64">1</gamesession>
|
||||
<strdata1 __type="str" />
|
||||
<strdata2 __type="str" />
|
||||
<numdata1 __type="s64">1</numdata1>
|
||||
<numdata2 __type="s64" />
|
||||
<locationid __type="str">ea</locationid>
|
||||
</data>
|
||||
</eventlog>
|
||||
</call></code></pre>
|
||||
<p>Arrays are encoded by concatenating every value together, with spaces between them. Data types that have multiple
|
||||
values, are serialized similarly.</p>
|
||||
<p>Therefore, an element storing an array of <code>3u8</code> (<code>[(1, 2, 3), (4, 5, 6)]</code>) would look like
|
||||
this</p>
|
||||
<pre><code><demo __type="3u8" __count="2">1 2 3 4 5 6</demo></code></pre>
|
||||
<p>Besides this, this is otherwise a rather standard XML.</p>
|
||||
|
||||
<h2 id="binary">Packed binary overview</h2>
|
||||
|
||||
<p>Many packets, rather than using a string-based XML format, use a custom binary packed format instead. While it
|
||||
can be a little confusing, remembering that this is encoding an XML tree can make it easier to parse.</p>
|
||||
<p>To start with, let's take a look at the overall structure of the packets.</p>
|
||||
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
<td>12</td>
|
||||
<td>13</td>
|
||||
<td>14</td>
|
||||
<td>15</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td><i>A0</i></td>
|
||||
<td>C</td>
|
||||
<td>E</td>
|
||||
<td>~E</td>
|
||||
<td colspan="4">Head length</td>
|
||||
<td style="border-bottom: none" colspan="8"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none; border-bottom: none;" colspan="16">Schema definition</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none;" colspan="12"></td>
|
||||
<td colspan="1"><i>FF</i></td>
|
||||
<td colspan="3">Align</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">Data length</td>
|
||||
<td style="border-bottom: none" colspan="12"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none; border-bottom: none;" colspan="16">Payload</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none;" colspan="13"></td>
|
||||
<td colspan="3">Align</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Every packet starts with the magic byte <code>0xA0</code>. Following this is the content byte, the encoding byte,
|
||||
and then the 2's compliment of the encoding byte.</p>
|
||||
<p>Currently known possible values for the content byte are:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>C</td>
|
||||
<td>Content</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td><code>0x42</code></td>
|
||||
<td>Compressed data</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x43</code></td>
|
||||
<td>Compressed, no data</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x45</code></td>
|
||||
<td>Decompressed data</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x46</code></td>
|
||||
<td>Decompressed, no data</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Decompressed packets contain an XML string. Compressed packets are what we're interested in here.</p>
|
||||
<p>The encoding flag indicates the encoding for all string types in the packet (more on those later). Possible
|
||||
values are:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td><code>E</code></td>
|
||||
<td><code>~E</code></td>
|
||||
<td colspan="3">Encoding name</td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tr>
|
||||
<td><code>0x20</code></td>
|
||||
<td><code>0xDF</code></td>
|
||||
<td><code>ASCII</code></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x40</code></td>
|
||||
<td><code>0xBF</code></td>
|
||||
<td><code>ISO-8859-1</code></td>
|
||||
<td><code>ISO_8859-1</code></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x60</code></td>
|
||||
<td><code>0x9F</code></td>
|
||||
<td><code>EUC-JP</code></td>
|
||||
<td><code>EUCJP</code></td>
|
||||
<td><code>EUC_JP</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x80</code></td>
|
||||
<td><code>0x7F</code></td>
|
||||
<td><code>SHIFT-JIS</code></td>
|
||||
<td><code>SHIFT_JIS</code></td>
|
||||
<td><code>SJIS</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0xA0</code></td>
|
||||
<td><code>0x5F</code></td>
|
||||
<td><code>UTF-8</code></td>
|
||||
<td><code>UTF8</code></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<details>
|
||||
<summary>Source code details</summary>
|
||||
<p>The full table for these values can be found in libavs.</p>
|
||||
<figure>
|
||||
<img src="./images/encoding_table.png">
|
||||
<figcaption><code>libavs-win32.dll:0x1006b960</code></figcaption>
|
||||
</figure>
|
||||
<p>A second table exists just before this on in the source, responsible for the
|
||||
<code><?xml version='1.0' encoding='??'?></code> line in XML files.
|
||||
</p>
|
||||
<figure>
|
||||
<img src="./images/xml_encoding_table.png">
|
||||
<figcaption><code>libavs-win32.dll:0x1006b940</code></figcaption>
|
||||
</figure>
|
||||
<p>This is indexed using the following function, which maps the above encoding IDs to 1, 2, 3, 4 and 5
|
||||
respectively.</p>
|
||||
<pre><code>char* xml_get_encoding_name(uint encoding_id) {
|
||||
return ENCODING_NAME_TABLE[((encoding_id & 0xe0) >> 5) * 4];
|
||||
}</code></pre>
|
||||
</details>
|
||||
<p>While validating <code>~E</code> isn't technically required, it acts as a useful assertion that the packet being
|
||||
parsed is valid.</p>
|
||||
|
||||
<h2 id="schema">The packet schema header</h2>
|
||||
<p>Following the 4 byte header, is a 4 byte integer containing the length of the next part of the header (this is
|
||||
technically made redundant as this structure is also terminated).</p>
|
||||
<p>This part of the header defines the schema that the main payload uses.</p>
|
||||
|
||||
<p>A tag definition looks like:</p>
|
||||
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
<td>12</td>
|
||||
<td>13</td>
|
||||
<td>14</td>
|
||||
<td>15</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<td>nlen</td>
|
||||
<td colspan="7">Tag name</td>
|
||||
<td style="border-bottom: none" colspan="8"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none;" colspan="15">Attributes and children</td>
|
||||
<td colspan="1"><i>FE</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Structure names are encoded as densely packed 6 bit values, length prefixed (<code>nlen</code>). The acceptable
|
||||
alphabet is <code>0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz</code>, and the packed values
|
||||
are indecies within this alphabet.</p>
|
||||
|
||||
<p>The children can be a combination of either attribute names, or child tags. Attribute names are represented by
|
||||
the byte <code>0x2E</code> followed by a length prefixed name as defined above. Child tags follow the above
|
||||
format. Type <code>0x2E</code> must therefore be considered reserved as a possible structure type.</p>
|
||||
|
||||
<p>Attributes (type <code>0x2E</code>) represent a string attribute. Any other attribute must be defined as a child
|
||||
tag. Is it notable that 0 children is allowable, which is how the majority of values are encoded.</p>
|
||||
<p>All valid IDs, and their respective type, are listed in the following table. The bucket column here will be
|
||||
used later when unpacking the main data, so we need not worry about it for now, but be warned it exists and is
|
||||
possibly the least fun part of this format.</p>
|
||||
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>Bytes</td>
|
||||
<td>C type</td>
|
||||
<td>Bucket</td>
|
||||
<td colspan="2">XML names</td>
|
||||
<td></td>
|
||||
<td>ID</td>
|
||||
<td>Bytes</td>
|
||||
<td>C type</td>
|
||||
<td>Bucket</td>
|
||||
<td colspan="2">XML names</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>0x01</td>
|
||||
<td>0</td>
|
||||
<td>void</td>
|
||||
<td>-</td>
|
||||
<td>void</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x21</td>
|
||||
<td>24</td>
|
||||
<td>uint64[3]</td>
|
||||
<td>int</td>
|
||||
<td>3u64</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x02</td>
|
||||
<td>1</td>
|
||||
<td>int8</td>
|
||||
<td>byte</td>
|
||||
<td>s8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x22</td>
|
||||
<td>12</td>
|
||||
<td>float[3]</td>
|
||||
<td>int</td>
|
||||
<td>3f</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x03</td>
|
||||
<td>1</td>
|
||||
<td>uint8</td>
|
||||
<td>byte</td>
|
||||
<td>u8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x23</td>
|
||||
<td>24</td>
|
||||
<td>double[3]</td>
|
||||
<td>int</td>
|
||||
<td>3d</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x04</td>
|
||||
<td>2</td>
|
||||
<td>int16</td>
|
||||
<td>short</td>
|
||||
<td>s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x24</td>
|
||||
<td>4</td>
|
||||
<td>int8[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s8</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x05</td>
|
||||
<td>2</td>
|
||||
<td>uint16</td>
|
||||
<td>short</td>
|
||||
<td>s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x25</td>
|
||||
<td>4</td>
|
||||
<td>uint8[4]</td>
|
||||
<td>int</td>
|
||||
<td>4u8</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x06</td>
|
||||
<td>4</td>
|
||||
<td>int32</td>
|
||||
<td>int</td>
|
||||
<td>s32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x26</td>
|
||||
<td>8</td>
|
||||
<td>int16[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s16</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x07</td>
|
||||
<td>4</td>
|
||||
<td>uint32</td>
|
||||
<td>int</td>
|
||||
<td>u32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x27</td>
|
||||
<td>8</td>
|
||||
<td>uint8[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s16</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x08</td>
|
||||
<td>8</td>
|
||||
<td>int64</td>
|
||||
<td>int</td>
|
||||
<td>s64</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x28</td>
|
||||
<td>16</td>
|
||||
<td>int32[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s32</td>
|
||||
<td>vs32</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x09</td>
|
||||
<td>8</td>
|
||||
<td>uint64</td>
|
||||
<td>int</td>
|
||||
<td>u64</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x29</td>
|
||||
<td>16</td>
|
||||
<td>uint32[4]</td>
|
||||
<td>int</td>
|
||||
<td>4u32</td>
|
||||
<td>vs32</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0a</td>
|
||||
<td><i>prefix</i></td>
|
||||
<td>char[]</td>
|
||||
<td>int</td>
|
||||
<td>bin</td>
|
||||
<td>binary</td>
|
||||
<td></td>
|
||||
<td>0x2a</td>
|
||||
<td>32</td>
|
||||
<td>int64[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s64</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0b</td>
|
||||
<td><i>prefix</i></td>
|
||||
<td>char[]</td>
|
||||
<td>int</td>
|
||||
<td>str</td>
|
||||
<td>string</td>
|
||||
<td></td>
|
||||
<td>0x2b</td>
|
||||
<td>32</td>
|
||||
<td>uint64[4]</td>
|
||||
<td>int</td>
|
||||
<td>4u64</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0c</td>
|
||||
<td>4</td>
|
||||
<td>uint8[4]</td>
|
||||
<td>int</td>
|
||||
<td>ip4</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x2c</td>
|
||||
<td>16</td>
|
||||
<td>float[4]</td>
|
||||
<td>int</td>
|
||||
<td>4f</td>
|
||||
<td>vf</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0d</td>
|
||||
<td>4</td>
|
||||
<td>uint32</td>
|
||||
<td>int</td>
|
||||
<td>time</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x2d</td>
|
||||
<td>32</td>
|
||||
<td>double[4]</td>
|
||||
<td>int</td>
|
||||
<td>4d</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0e</td>
|
||||
<td>4</td>
|
||||
<td>float</td>
|
||||
<td>int</td>
|
||||
<td>float</td>
|
||||
<td>f</td>
|
||||
<td></td>
|
||||
<td>0x2e</td>
|
||||
<td><i>prefix</i></td>
|
||||
<td>char[]</td>
|
||||
<td>int</td>
|
||||
<td>attr</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0f</td>
|
||||
<td>8</td>
|
||||
<td>double</td>
|
||||
<td>int</td>
|
||||
<td>double</td>
|
||||
<td>d</td>
|
||||
<td></td>
|
||||
<td>0x2f</td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td>-</td>
|
||||
<td>array</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x10</td>
|
||||
<td>2</td>
|
||||
<td>int8[2]</td>
|
||||
<td>short</td>
|
||||
<td>2s8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x30</td>
|
||||
<td>16</td>
|
||||
<td>int8[16]</td>
|
||||
<td>int</td>
|
||||
<td>vs8</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x11</td>
|
||||
<td>2</td>
|
||||
<td>uint8[2]</td>
|
||||
<td>short</td>
|
||||
<td>2u8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x31</td>
|
||||
<td>16</td>
|
||||
<td>uint8[16]</td>
|
||||
<td>int</td>
|
||||
<td>vu8</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x12</td>
|
||||
<td>4</td>
|
||||
<td>int16[2]</td>
|
||||
<td>int</td>
|
||||
<td>2s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x32</td>
|
||||
<td>16</td>
|
||||
<td>int8[8]</td>
|
||||
<td>int</td>
|
||||
<td>vs16</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x13</td>
|
||||
<td>4</td>
|
||||
<td>uint16[2]</td>
|
||||
<td>int</td>
|
||||
<td>2s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x33</td>
|
||||
<td>16</td>
|
||||
<td>uint8[8]</td>
|
||||
<td>int</td>
|
||||
<td>vu16</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x14</td>
|
||||
<td>8</td>
|
||||
<td>int32[2]</td>
|
||||
<td>int</td>
|
||||
<td>2s32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x34</td>
|
||||
<td>1</td>
|
||||
<td>bool</td>
|
||||
<td>byte</td>
|
||||
<td>bool</td>
|
||||
<td>b</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x15</td>
|
||||
<td>8</td>
|
||||
<td>uint32[2]</td>
|
||||
<td>int</td>
|
||||
<td>2u32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x35</td>
|
||||
<td>2</td>
|
||||
<td>bool[2]</td>
|
||||
<td>short</td>
|
||||
<td>2b</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x16</td>
|
||||
<td>16</td>
|
||||
<td>int16[2]</td>
|
||||
<td>int</td>
|
||||
<td>2s64</td>
|
||||
<td>vs64</td>
|
||||
<td></td>
|
||||
<td>0x36</td>
|
||||
<td>3</td>
|
||||
<td>bool[3]</td>
|
||||
<td>int</td>
|
||||
<td>3b</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x17</td>
|
||||
<td>16</td>
|
||||
<td>uint16[2]</td>
|
||||
<td>int</td>
|
||||
<td>2u64</td>
|
||||
<td>vu64</td>
|
||||
<td></td>
|
||||
<td>0x37</td>
|
||||
<td>4</td>
|
||||
<td>bool[4]</td>
|
||||
<td>int</td>
|
||||
<td>4b</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x18</td>
|
||||
<td>8</td>
|
||||
<td>float[2]</td>
|
||||
<td>int</td>
|
||||
<td>2f</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x38</td>
|
||||
<td>16</td>
|
||||
<td>bool[16]</td>
|
||||
<td>int</td>
|
||||
<td>vb</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x19</td>
|
||||
<td>16</td>
|
||||
<td>double[2]</td>
|
||||
<td>int</td>
|
||||
<td>2d</td>
|
||||
<td>vd</td>
|
||||
<td></td>
|
||||
<td>0x38</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1a</td>
|
||||
<td>3</td>
|
||||
<td>int8[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x39</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1b</td>
|
||||
<td>3</td>
|
||||
<td>uint8[3]</td>
|
||||
<td>int</td>
|
||||
<td>3u8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3a</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1c</td>
|
||||
<td>6</td>
|
||||
<td>int16[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3b</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1d</td>
|
||||
<td>6</td>
|
||||
<td>uint16[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3c</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1e</td>
|
||||
<td>12</td>
|
||||
<td>int32[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3d</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1f</td>
|
||||
<td>12</td>
|
||||
<td>uint32[3]</td>
|
||||
<td>int</td>
|
||||
<td>3u32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3e</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x20</td>
|
||||
<td>24</td>
|
||||
<td>int64[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s64</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3f</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Strings should be encoded and decoded according to the encoding specified in the packet header. Null termination is optional, however should be stripped during decoding.</p>
|
||||
<p>All of these IDs are <code>& 0x3F</code>. Any value can be turned into an array by setting the 7<sup>th</sup> bit
|
||||
high (<code>| 0x40</code>). Arrays of this form, in the data section, will be an aligned <code>size: u32</code>
|
||||
immediately followed by <code>size</code> bytes' worth of (unaligned!) values of the unmasked type.</p>
|
||||
|
||||
<details>
|
||||
<summary>Source code details</summary>
|
||||
<p>The full table for these values can be found in libavs. This table contains the names of every tag, along
|
||||
with additional information such as how many bytes that data type requires, and which parsing function
|
||||
should be used.</p>
|
||||
<figure>
|
||||
<img src="./images/types_table.png">
|
||||
<figcaption><code>libavs-win32.dll:0x100782a8</code></figcaption>
|
||||
</figure>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Note about the <code>array</code> type:</summary>
|
||||
<p>While I'm not totally sure, I have a suspicion this type is used internally as a pseudo-type. Trying to
|
||||
identify its function as a parsable type has some obvious blockers:</p>
|
||||
|
||||
<p>All of the types have convenient <code>printf</code>-using helper functions that are used to emit them when
|
||||
serializing XML. All except one.</p>
|
||||
<img src="./images/no_array.png">
|
||||
<p>If we have a look inside the function that populates node sizes (<code>libavs-win32.dll:0x1000cf00</code>),
|
||||
it has an explicit case, however is the same fallback as the default case.</p>
|
||||
<img src="./images/no_array_2.png">
|
||||
|
||||
<p>In the same function, however, we can find a second (technically first) check for the array type.</p>
|
||||
<img src="./images/yes_array.png">
|
||||
<p>This seems to suggest that internally arrays are represented as a normal node, with the <code>array</code>
|
||||
type, however when serializing it's converted into the array types we're used to (well, will be after the
|
||||
next sections) by masking 0x40 onto the contained type.</p>
|
||||
<p>Also of interest from this snippet is the fact that <code>void</code>, <code>bin</code>, <code>str</code>,
|
||||
and <code>attr</code> cannot be arrays. <code>void</code> and <code>attr</code> make sense, however
|
||||
<code>str</code> and <code>bin</code> are more interesting. I suspect this is because konami want to be able
|
||||
to preallocate the memory, which wouldn't be possible with these variable length structures.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<h2 id="data">The data section</h2>
|
||||
|
||||
<p>This is where all the actual packet data is. For the most part, parsing this is the easy part. We traverse our
|
||||
schema, and read values out of the packet according to the value indicated in the schema. Unfortunately, konami
|
||||
decided all data should be aligned very specifically, and that gaps left during alignment should be backfilled
|
||||
later. This makes both reading and writing somewhat more complicated, however the system can be fairly easily
|
||||
understood.</p>
|
||||
<p>Firstly, we divide the payload up into 4 byte chunks. Each chunk can be allocated to either store individual
|
||||
bytes, shorts, or ints (these are the buckets in the table above). When reading or writing a value, we first
|
||||
check if a chunk allocated to the desired type's bucket is available and has free/as-yet-unread space within it.
|
||||
If so, we will store/read our data to/from there. If there is no such chunk, we claim the next unclaimed chunk
|
||||
for our bucket.</p>
|
||||
<p>For example, imagine we write the sequence <code>byte, int, byte, short, byte, int, short</code>. The final output should look like:</p>
|
||||
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
<td>12</td>
|
||||
<td>13</td>
|
||||
<td>14</td>
|
||||
<td>15</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>byte</td>
|
||||
<td>byte</td>
|
||||
<td>byte</td>
|
||||
<td></td>
|
||||
<td colspan="4">int</td>
|
||||
<td colspan="2">short</td>
|
||||
<td colspan="2">short</td>
|
||||
<td colspan="4">int</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>While this might seem a silly system compared to just not aligning values, it is at least possible to intuit that it helps reduce wasted space. It should be noted that any variable-length structure, such as a string or an array, claims all chunks it encroaches on for the <code>int</code> bucket, disallowing the storage of bytes or shorts within them.</p>
|
||||
|
||||
<details>
|
||||
<summary>Implementing a packer</summary>
|
||||
<p>While the intuitive way to understand the packing algorithm is via chunks and buckets, a far more efficient implementation can be made that uses three pointers. Rather than try to explain in words, hopefully this python implementation should suffice as explanation:<pre><code>class Packer:
|
||||
def __init__(self, offset=0):
|
||||
self._word_cursor = offset
|
||||
self._short_cursor = offset
|
||||
self._byte_cursor = offset
|
||||
self._boundary = offset % 4
|
||||
|
||||
def _next_block(self):
|
||||
self._word_cursor += 4
|
||||
return self._word_cursor - 4
|
||||
|
||||
def request_allocation(self, size):
|
||||
if size == 0:
|
||||
return self._word_cursor
|
||||
elif size == 1:
|
||||
if self._byte_cursor % 4 == self._boundary:
|
||||
self._byte_cursor = self._next_block() + 1
|
||||
else:
|
||||
self._byte_cursor += 1
|
||||
return self._byte_cursor - 1
|
||||
elif size == 2:
|
||||
if self._short_cursor % 4 == self._boundary:
|
||||
self._short_cursor = self._next_block() + 2
|
||||
else:
|
||||
self._short_cursor += 2
|
||||
return self._short_cursor - 2
|
||||
else:
|
||||
old_cursor = self._word_cursor
|
||||
for _ in range(math.ceil(size / 4)):
|
||||
self._word_cursor += 4
|
||||
return old_cursor
|
||||
|
||||
def notify_skipped(self, no_bytes):
|
||||
for _ in range(math.ceil(no_bytes / 4)):
|
||||
self.request_allocation(4)</code></pre></p>
|
||||
</details>
|
||||
|
||||
<a href="./transport.html">Prev page</a> | <a href="./protocol.html">Next page</a>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,33 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>apsmanager</code></h1>
|
||||
<h2 id="getstat"><code>apsmanager.getstat</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<apsmanager method="getstat" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<apsmanager status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,232 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>cardmng</code></h1>
|
||||
<p>As the name might imply, this service is responsible for handling interactions with physical e-Amusement cards.
|
||||
e-Amusement currently has two different types of cards in circulation. There are classic e-Amusement cards
|
||||
making use of a magnetic stripe, and the newer RFID cards using FeliCa (these are probably what you have). They
|
||||
are identified in requests using the <code>cardtype</code> attribute as in the below table.
|
||||
</p>
|
||||
<p>e-Amusement cards have a "card number" and a "card id". Confusingly, neither is a number. The card number is the
|
||||
one printed on your card. The card ID is your KONAMI ID. You can (and should) read about the algorithm used for
|
||||
these IDs on <a href="../cardid.html">the Card IDs page</a>.</p>
|
||||
<p>In the interest of not wasting space, <code>cardid</code> and <code>cardtype</code> will be omitted from
|
||||
individual breakdowns where their meaning is obvious.</p>
|
||||
|
||||
<h4>Card types:</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td><code>cardtype</code></td>
|
||||
<td>Meaning</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td><code>1</code></td>
|
||||
<td>Old style magnetic stripe card</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>2</code></td>
|
||||
<td>FeliCa RFID card</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<ul>
|
||||
<li><code><a href="#inquire">cardmng.inquire</a></code></li>
|
||||
<li><code><a href="#getrefid">cardmng.getrefid</a></code></li>
|
||||
<li><code><a href="#bindmodel">cardmng.bindmodel</a></code></li>
|
||||
<li><code><a href="#bindcard">cardmng.bindcard</a></code></li>
|
||||
<li><code><a href="#authpass">cardmng.authpass</a></code></li>
|
||||
<li><code><a href="#getkeepspan">cardmng.getkeepspan</a></code></li>
|
||||
<li><code><a href="#getkeepremain">cardmng.getkeepremain</a></code></li>
|
||||
<li><code><a href="#getdatalist">cardmng.getdatalist</a></code></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2 id="inquire"><code>cardmng.inquire</code></h2>
|
||||
<p>Request information about a card that has been inserted or touched against a reader.</p>
|
||||
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="inquire" cardid="" cardtype="" update="" model*="" />
|
||||
</call></code></pre>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>update</code></td>
|
||||
<td>Should the tracked last play time be updated by this inquiry? (Just a guess)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" refid="" dataid="" pcode="" newflag="" binded="" expired=" ecflag="" useridflag="" extidflag="" lastupdate="" />
|
||||
</response></code></pre>
|
||||
<p>To handle this request, we first must lookup if this <code>cardid</code> has ever been seen by our servers
|
||||
before. If not, we abort with a <code>112</code> status. Otherwise, we proceeed to check if this card has been
|
||||
seen for this specific game. If we have never seen this card used on this game, it is possible this card was
|
||||
used with an older version of this game, and migration is supported, in which case we report as if we had found
|
||||
a profile for this game.</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>refid</code></td>
|
||||
<td>A reference to this card to be used in other requests</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dataid</code></td>
|
||||
<td>Appears to be set the same as <code>refid</code>; presumably to allow different keys for game state vs
|
||||
login details.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>newflag</code></td>
|
||||
<td>Inverse of <code>binded</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>binded</code></td>
|
||||
<td>Has a profile ever been created for this game (or an older version, requiring a migration)
|
||||
(<code>1</code> or <code>0</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>expired</code></td>
|
||||
<td>? Just set to <code>0</code>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2 id="getrefid"><code>cardmng.getrefid</code></h2>
|
||||
<p>Register a new card to this server.</p>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="getrefid" cardtype="" cardid=" newflag="" passwd="" model*="" />
|
||||
</call></code></pre>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>newflag</code></td>
|
||||
<td>?</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>passwd</code></td>
|
||||
<td>The pin for this new user. <i>Should</i> always be a four digit number (and that's worth validating),
|
||||
but it's passed as a string so could feasibly be anything desired.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" refid="" dataid="" pcode="" />
|
||||
</response></code></pre>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>refid</code></td>
|
||||
<td>A reference to this card to be used in other requests</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dataid</code></td>
|
||||
<td>Appears to be set the same as <code>refid</code>; presumably to allow different keys for game state vs
|
||||
login details.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>pcode</code></td>
|
||||
<td>? Not present in captured data.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2 id="bindmodel"><code>cardmng.bindmodel</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="bindmodel" refid="" newflag="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" dataid="" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="bindcard"><code>cardmng.bindcard</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="bindcard" cardtype="" newid="" refid="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="authpass"><code>cardmng.authpass</code></h2>
|
||||
<p>Test a pin for a card. This request notably uses the <code>refid</code>, so required a
|
||||
<code>cardmng.inquire</code> call to be made first.
|
||||
</p>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="authpass" refid="" pass="" model*="" />
|
||||
</call></code></pre>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>refid</code></td>
|
||||
<td>The reference we received either during <code>cardmng.inquire</code> or <code>cardmng.getrefid</code>
|
||||
(the latter for new cards)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>pass</code></td>
|
||||
<td>The pin to test. See <code>cardmng.getrefid</code>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
<p>If the pin is valid, status should be <code>0</code>. Otherwise, <code>116</code>.</p>
|
||||
|
||||
<h2 id="getkeepspan"><code>cardmng.getkeepspan</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="getkeepspan" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" keepspan="" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="getkeepremain"><code>cardmng.getkeepremain</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="getkeepremain" refid="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" keepremain="" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="getdatalist"><code>cardmng.getdatalist</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="getdatalist" refid="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>">
|
||||
<item[]>
|
||||
<mcode __type="str" />
|
||||
<dataid __type="str" />
|
||||
<regtime __type="str" />
|
||||
<lasttime __type="str" />
|
||||
<exptime __type="str" />
|
||||
<expflag __type="u8" />
|
||||
</item[]>
|
||||
</cardmng>
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,54 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>dlstatus</code></h1>
|
||||
<h2 id="done"><code>dlstatus.done</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<dlstatus method="done">
|
||||
<url>
|
||||
<param __type="str" />
|
||||
</url>
|
||||
<name __type="str" />
|
||||
<size __type="s32" />
|
||||
</dlstatus>
|
||||
</call></code></pre>
|
||||
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<dlstatus status="<i>status</i>">
|
||||
<progress __type="s32" />
|
||||
</dlstatus>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="progress"><code>dlstatus.progress</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<dlstatus method="progress" />
|
||||
<progress __type="s32" />
|
||||
</dlstatus>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<dlstatus status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,37 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>esign</code></h1>
|
||||
<h2 id="request"><code>esign.request</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<esign method="request">
|
||||
<i>placeholder</i>
|
||||
</esign>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<esign status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</esign>
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,50 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>esoc</code></h1>
|
||||
<h2 id="read"><code>esoc.read</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<esoc method="read">
|
||||
<senddata />
|
||||
</esoc>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<esoc status="<i>status</i>">
|
||||
<recvdata />
|
||||
</esoc>
|
||||
</response></code></pre>
|
||||
<p>Go figure.</p>
|
||||
|
||||
<h2 id="write"><code>esoc.write</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<esoc method="write">
|
||||
<senddata />
|
||||
</esoc>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<esoc status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,58 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>eventlog</code></h1>
|
||||
<h2 id="write"><code>eventlog.write</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eventlog method="write">
|
||||
<retrycnt __type="u32" />
|
||||
<data>
|
||||
<eventid __type="str" />
|
||||
<eventorder __type="s32" />
|
||||
<pcbtime __type="u64" />
|
||||
<gamesession __type="s64" />
|
||||
<strdata1 __type="str" />
|
||||
<strdata2 __type="str" />
|
||||
<numdata1 __type="s64" />
|
||||
<numdata2 __type="s64" />
|
||||
<locationid __type="str" />
|
||||
</data>
|
||||
</eventlog>
|
||||
</call></code></pre>
|
||||
<p>Event ID list:</p>
|
||||
<ul>
|
||||
<li><code>G_GAMED</code></li>
|
||||
<li><code>S_ERROR</code></li>
|
||||
<li><code>S_PWRON</code> <b>TODO: find more!</b></li>
|
||||
<li><code>T_OTDEMO</code></li>
|
||||
</ul>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eventlog status="<i>status</i>">
|
||||
<gamesession __type="s64" />
|
||||
<logsendflg __type="s32" />
|
||||
<logerrlevel __type="s32" />
|
||||
<evtidnosendflg __type="s32" />
|
||||
</eventlog>
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,35 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>message</code></h1>
|
||||
<h2 id="get"><code>message.get</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<message method="get" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<message expire="" status="<i>status</i>">
|
||||
<item[] name="" start="" end="" data="" />
|
||||
</message>
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,47 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>package</code></h1>
|
||||
<h2 id="list"><code>package.list</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<package method="list" pkgtype="<i>pkgtype</i>" model*="" />
|
||||
</call></code></pre>
|
||||
<p><code>all</code> is the only currently observed value for <code>pkgtype</code></p>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<package status="<i>status</i>">
|
||||
<item[] url="" />
|
||||
</package>
|
||||
</response></code></pre>
|
||||
<p>A list of all packages available for download.</p>
|
||||
|
||||
<h2 id="intend"><code>package.intend</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<package method="intend" url="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<package status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,41 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>pcbevent</code></h1>
|
||||
<h2 id="put"><code>pcbevent.put</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<pcbevent method="put">
|
||||
<time __type="time" />
|
||||
<seq __type="u32" />
|
||||
<item[]>
|
||||
<name __type="str" />
|
||||
<value __type="s32" />
|
||||
<time __type="time" />
|
||||
</item[]>
|
||||
</pcbevent>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<pcbevent status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,39 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>pcbtracker</code></h1>
|
||||
<h2 id="alive"><code>pcbtracker.alive</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<pcbtracker method="alive" model*="" hardid="" softid="" accountid="" agree="" ecflag="" />
|
||||
</call></code></pre>
|
||||
<p><code>ecflag</code> here is determining if the arcade operator allows the use of paseli on this machine.</p>
|
||||
<p><code>agree@</code> and <code>ecflag@</code> appear to either be totally non present, or present with a value of
|
||||
<code>"1"</code>, but then again I may be reading the code wrong, so take that with a pinch of salt.
|
||||
</p>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<pcbtracker status="" time="" limit="" ecenable="" eclimit="" >
|
||||
</response></code></pre>
|
||||
<p>As you might guess, <code>ecenable@</code> is therefore the flag to determine if paseli is enabled (i.e. the
|
||||
arcade operator and the server both allow its use).</p>
|
||||
</body>
|
@ -1,70 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>services</code></h1>
|
||||
<h2 id="get"><code>services.get</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<services method="get" model*="" >
|
||||
<info>
|
||||
<AVS2 __type="str"><i>AVS2 version</i></AVS2>
|
||||
</info>
|
||||
</services>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<services expire="" method="get" mode="" status="<i>status</i>">
|
||||
<item[] name="<i>service</i>" url="<i>url</i>" />
|
||||
</services>
|
||||
</response></code></pre>
|
||||
<p>Known services are:</p>
|
||||
<ul>
|
||||
<li><code>ntp</code></li>
|
||||
<li><code>keepalive</code></li>
|
||||
<li><code>cardmng</code></li>
|
||||
<li><code>facility</code></li>
|
||||
<li><code>message</code></li>
|
||||
<li><code>numbering</code></li>
|
||||
<li><code>package</code></li>
|
||||
<li><code>pcbevent</code></li>
|
||||
<li><code>pcbtracker</code></li>
|
||||
<li><code>pkglist</code></li>
|
||||
<li><code>posevent</code></li>
|
||||
<li><code>userdata</code></li>
|
||||
<li><code>userid</code></li>
|
||||
<li><code>eacoin</code></li>
|
||||
<li><code>local</code></li>
|
||||
<li><code>local2</code></li>
|
||||
<li><code>lobby</code></li>
|
||||
<li><code>lobby2</code></li>
|
||||
<li><code>dlstatus</code></li>
|
||||
<li><code>netlog</code></li>
|
||||
<li><code>sidmgr</code></li>
|
||||
<li><code>globby</code></li>
|
||||
</ul>
|
||||
<p>Most of these will usually just return the URL to the eAmuse server (or your fake one ;D). <code>ntp</code> is a
|
||||
notable exception, unless you're planning on reimplementing NTP. <code>keepalive</code> will likely alsop be a
|
||||
custom URL with query parameters pre-baked.</p>
|
||||
<p><code>mode</code> is one of <code>operation</code>, <code>debug</code>, <code>test</code>, or
|
||||
<code>factory</code>.
|
||||
</p>
|
||||
</body>
|
@ -1,94 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>sidmgr</code></h1>
|
||||
<h2 id="create"><code>sidmgr.create</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="create">
|
||||
<cardtype __type="str" />
|
||||
<cardid __type="str" />
|
||||
<cardgid __type="str" />
|
||||
<steal __type="u8" />
|
||||
</sidmgr>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>">
|
||||
<state __type="u32" />
|
||||
<e_count __type="u8" />
|
||||
<last __type="time" />
|
||||
<locked __type="time" />
|
||||
<sid __type="str" />
|
||||
<cardid_status __type="u8" />
|
||||
<refid __type="str" />
|
||||
</sidmgr>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="open"><code>sidmgr.open</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="open" sid="" >
|
||||
<pass __type="str" />
|
||||
</sidmgr>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>">
|
||||
<state __type="u32" />
|
||||
<refid __type="str" />
|
||||
<locked __type="time" />
|
||||
</sidmgr>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="touch"><code>sidmgr.touch</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="touch" sid="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="branch"><code>sidmgr.branch</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="branch" sid="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="close"><code>sidmgr.close</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="close" sid="" />
|
||||
<cause __type="u32" />
|
||||
</sidmgr>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,40 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>traceroute</code></h1>
|
||||
<h2 id="send"><code>traceroute.send</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<traceroute proto="" method="send">
|
||||
<hop[]>
|
||||
<valid __type="bool">
|
||||
<addr __type="ip4">
|
||||
<usec __type="u64">
|
||||
</hop[]>
|
||||
</traceroute>
|
||||
</call></code></pre>
|
||||
<p><code>hop</code> repeats for every hop (unsurprisingly)</p>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<traceroute status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
</body>
|
@ -1,48 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>userdata</code></h1>
|
||||
<h2 id="read"><code>userdata.read</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<userdata method="read" card*="" model*="" label="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<userdata status="<i>status</i>" time="">
|
||||
<b[] __type="" />
|
||||
</userdata>
|
||||
</response></code></pre>
|
||||
<p><code>__type</code> here can be either <code>bin</code> or <code>str</code></p>
|
||||
|
||||
<h2 id="write"><code>userdata.write</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<userdata method="write" card="" time="" model*="" label*="" >
|
||||
<b[] __type="str" />
|
||||
</userdata>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<userdata status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
</body>
|
284
protocol.html
284
protocol.html
@ -1,284 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Packet format | eAmuse API</title>
|
||||
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href=".">Contents</a></td>
|
||||
<td><a href="./transport.html">Transport layer</a></td>
|
||||
<td><a href="./packet.html">Packet format</a></td>
|
||||
<td><a href="./protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<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>,
|
||||
with its body being encoded data as described in the previous sections. In addition to the
|
||||
<code>X-Compress:</code> and <code>X-Eamuse-Info:</code> headers previously detailed, there is also a
|
||||
<code>X-PCB-ID:</code> header. that can be set. Your machine's PCB ID uniquely defines the physical board. This
|
||||
header is added in out-bound requests, and allows the server to identify you. Importantly, it's also the value
|
||||
that the server uses to identify which machines are authorized to be on the network, and which are not.
|
||||
</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>
|
||||
<pre><code><call model="<i>model</i>" srcid="<i>srcid</i>" tag="<i>tag</i>">
|
||||
<<i>module</i> method="<i>method</i>" <i>...attributes</i>>
|
||||
<i>children</i>
|
||||
</<i>module</i>>
|
||||
</call></code></pre>
|
||||
<p>The responses follow a similar format:</p>
|
||||
<pre><code><response>
|
||||
<<i>module</i> status="<i>status</i>" <i>...attributes</i>>
|
||||
<i>children</i>
|
||||
</<i>module</i>>
|
||||
</response></code></pre>
|
||||
<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.
|
||||
These are namespaces under the <code>game.%s</code> module and, in the case of SDVX 4, are all
|
||||
<code>game.sv4_<i>method</i></code>. I may or may not document the SDVX 4 specific methods, but I've listed them
|
||||
here anyway for completeness.
|
||||
</p>
|
||||
<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>
|
||||
|
||||
<h2>Possible XRPC requests</h2>
|
||||
|
||||
<ul>
|
||||
<li><code><a href="proto/eventlog.html">eventlog.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/eventlog.html#eventlog.write">eventlog.write</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/playerdata.html">playerdata.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_send">playerdata.usergamedata_send</a></code></li>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_recv">playerdata.usergamedata_recv</a></code></li>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_inheritance">playerdata.usergamedata_inheritance</a></code>
|
||||
</li>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_condrecv">playerdata.usergamedata_condrecv</a></code>
|
||||
</li>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_scorerank">playerdata.usergamedata_scorerank</a></code>
|
||||
</li>
|
||||
</ul>
|
||||
<li><code><a href="proto/matching.html">matching.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/matching.html#request">matching.request</a></code></li>
|
||||
<li><code><a href="proto/matching.html#wait">matching.wait</a></code></li>
|
||||
<li><code><a href="proto/matching.html#finish">matching.finish</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/system.html">system.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/system.html#getmaster">system.getmaster</a></code></li>
|
||||
<li><code><a href="proto/system.html#getlocationiplist">system.getlocationiplist</a></code></li>
|
||||
<li><code><a href="proto/system.html#xrpcproxy">system.xrpcproxy</a></code></li>
|
||||
<li><code><a href="proto/system.html#convcardnumber">system.convcardnumber</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/esoc.html">esoc.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/esoc.html#read">esoc.read</a></code></li>
|
||||
<li><code><a href="proto/esoc.html#write">esoc.write</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/cardmng.html">cardmng.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/cardmng.html#inquire">cardmng.inquire</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#getrefid">cardmng.getrefid</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#bindmodel">cardmng.bindmodel</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#bindcard">cardmng.bindcard</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#authpass">cardmng.authpass</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#getkeepspan">cardmng.getkeepspan</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#getkeepremain">cardmng.getkeepremain</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#getdatalist">cardmng.getdatalist</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/esign.html">esign.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/esign.html#request">esign.request</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/package.html">package.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/package.html#list">package.list</a></code></li>
|
||||
<li><code><a href="proto/package.html#intend">package.intend</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/userdata.html">userdata.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/userdata.html#read">userdata.read</a></code></li>
|
||||
<li><code><a href="proto/userdata.html#write">userdata.write</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/services.html">services.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/services.html#get">services.get</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/pcbtracker.html">pcbtracker.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/pcbtracker.html#alive">pcbtracker.alive</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/pcbevent.html">pcbevent.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/pcbevent.html#put">pcbevent.put</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/message.html">message.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/message.html#get">message.get</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/facility.html">facility.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/facility.html#get">facility.get</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/apsmanager.html">apsmanager.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/apsmanager.html#getstat">apsmanager.getstat</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/sidmgr.html">sidmgr.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/sidmgr.html#create">sidmgr.create</a></code></li>
|
||||
<li><code><a href="proto/sidmgr.html#open">sidmgr.open</a></code></li>
|
||||
<li><code><a href="proto/sidmgr.html#touch">sidmgr.touch</a></code></li>
|
||||
<li><code><a href="proto/sidmgr.html#branch">sidmgr.branch</a></code></li>
|
||||
<li><code><a href="proto/sidmgr.html#close">sidmgr.close</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/dlstatus.html">dlstatus.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/dlstatus.html#done">dlstatus.done</a></code></li>
|
||||
<li><code><a href="proto/dlstatus.html#progress">dlstatus.progress</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/eacoin.html">eacoin.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/eacoin.html#checkin">eacoin.checkin</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#checkout">eacoin.checkout</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#consume">eacoin.consume</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#getbalance">eacoin.getbalance</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#getecstatus">eacoin.getecstatus</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#touch">eacoin.touch</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#opchpass">eacoin.opchpass</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#opcheckin">eacoin.opcheckin</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#opcheckout">eacoin.opcheckout</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#getlog">eacoin.getlog</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/traceroute.html">traceroute.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/traceroute.html#send">traceroute.send</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/game/sv4.html">game.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/game/sv4.html#sample">game.sv4_sample</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#new">game.sv4_new</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#load">game.sv4_load</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#load_m">game.sv4_load_m</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save">game.sv4_save</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_m">game.sv4_save_m</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#common">game.sv4_common</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#shop">game.sv4_shop</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#hiscore">game.sv4_hiscore</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#buy">game.sv4_buy</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#exception">game.sv4_exception</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#entry_s">game.sv4_entry_s</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#entry_e">game.sv4_entry_e</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#frozen">game.sv4_frozen</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#lounce">game.sv4_lounce</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_e">game.sv4_save_e</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_pb">game.sv4_save_pb</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_c">game.sv4_save_c</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#play_s">game.sv4_play_s</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#play_e">game.sv4_play_e</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#serial">game.sv4_serial</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_fi">game.sv4_save_fi</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#print">game.sv4_print</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#print_h">game.sv4_print_h</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#load_r">game.sv4_load_r</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_campaign">game.sv4_save_campaign</a></code></li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<b>Totally undocumented services (based on <code>services.get</code>):</b>
|
||||
<ul>
|
||||
<li><code>numbering</code></li>
|
||||
<li><code>pkglist</code></li>
|
||||
<li><code>userid</code></li>
|
||||
<li><code>local</code></li>
|
||||
<li><code>local2</code></li>
|
||||
<li><code>lobby</code></li>
|
||||
<li><code>lobby2</code></li>
|
||||
<li><code>netlog</code></li>
|
||||
<li><code>globby</code></li>
|
||||
</ul>
|
||||
<p>I'll try and figure these out in due course, promise!</p>
|
||||
</body>
|
25
templates/base.html
Normal file
25
templates/base.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}{% endblock %}{% if self.title() %} | {% endif %}e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="{{ROOT}}/styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="{{ROOT}}/">Contents</a></td>
|
||||
<td><a href="{{ROOT}}/transport.html">Transport layer</a></td>
|
||||
<td><a href="{{ROOT}}/packet.html">Packet format</a></td>
|
||||
<td><a href="{{ROOT}}/protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
{% block body %}{% endblock %}
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,34 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href=".">Contents</a></td>
|
||||
<td><a href="transport.html">Transport layer</a></td>
|
||||
<td><a href="packet.html">Packet format</a></td>
|
||||
<td><a href="protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>Card ID generation</h1>
|
||||
<details>
|
||||
<summary>I'm just here for code.</summary>
|
||||
<p>Fair. My intent with these pages is to describe things in enough detail that they should be simple to
|
||||
implement yourself, but this is one of those things that's quite easy to just drop in some pre-made code
|
||||
for. My local implementation is in python, so that's all you're getting :). As a free bonus, have some test
|
||||
cases too. It's not great code by any stretch, and it liberally uses assertions rather than proper
|
||||
exceptions, but it should be a good enough starting point for your own version.</p>
|
||||
<pre><code>import binascii
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1>Card ID generation</h1>
|
||||
<details>
|
||||
<summary>I'm just here for code.</summary>
|
||||
<p>Fair. My intent with these pages is to describe things in enough detail that they should be simple to
|
||||
implement yourself, but this is one of those things that's quite easy to just drop in some pre-made code
|
||||
for. My local implementation is in python, so that's all you're getting :). As a free bonus, have some test
|
||||
cases too. It's not great code by any stretch, and it liberally uses assertions rather than proper
|
||||
exceptions, but it should be a good enough starting point for your own version.</p>
|
||||
<pre><code>import binascii
|
||||
from Crypto.Cipher import DES3
|
||||
|
||||
|
||||
@ -39,183 +19,183 @@ ALPHABET = "0123456789ABCDEFGHJKLMNPRSTUWXYZ"
|
||||
|
||||
|
||||
def enc_des(uid):
|
||||
cipher = DES3.new(_KEY, DES3.MODE_CBC, iv=b'\0' * 8)
|
||||
return cipher.encrypt(uid)
|
||||
cipher = DES3.new(_KEY, DES3.MODE_CBC, iv=b'\0' * 8)
|
||||
return cipher.encrypt(uid)
|
||||
|
||||
|
||||
def dec_des(uid):
|
||||
cipher = DES3.new(_KEY, DES3.MODE_CBC, iv=b'\0' * 8)
|
||||
return cipher.decrypt(uid)
|
||||
cipher = DES3.new(_KEY, DES3.MODE_CBC, iv=b'\0' * 8)
|
||||
return cipher.decrypt(uid)
|
||||
|
||||
|
||||
def checksum(data):
|
||||
chk = sum(data[i] * (i % 3 + 1) for i in range(15))
|
||||
chk = sum(data[i] * (i % 3 + 1) for i in range(15))
|
||||
|
||||
while chk > 31:
|
||||
chk = (chk >> 5) + (chk & 31)
|
||||
while chk > 31:
|
||||
chk = (chk >> 5) + (chk & 31)
|
||||
|
||||
return chk
|
||||
return chk
|
||||
|
||||
|
||||
def pack_5(data):
|
||||
data = "".join(f"{i:05b}" for i in data)
|
||||
if len(data) % 8 != 0:
|
||||
data += "0" * (8 - (len(data) % 8))
|
||||
return bytes(int(data[i:i+8], 2) for i in range(0, len(data), 8))
|
||||
data = "".join(f"{i:05b}" for i in data)
|
||||
if len(data) % 8 != 0:
|
||||
data += "0" * (8 - (len(data) % 8))
|
||||
return bytes(int(data[i:i+8], 2) for i in range(0, len(data), 8))
|
||||
|
||||
|
||||
def unpack_5(data):
|
||||
data = "".join(f"{i:08b}" for i in data)
|
||||
if len(data) % 5 != 0:
|
||||
data += "0" * (5 - (len(data) % 5))
|
||||
return bytes(int(data[i:i+5], 2) for i in range(0, len(data), 5))
|
||||
data = "".join(f"{i:08b}" for i in data)
|
||||
if len(data) % 5 != 0:
|
||||
data += "0" * (5 - (len(data) % 5))
|
||||
return bytes(int(data[i:i+5], 2) for i in range(0, len(data), 5))
|
||||
|
||||
|
||||
def to_konami_id(uid):
|
||||
assert len(uid) == 16, "UID must be 16 bytes"
|
||||
assert len(uid) == 16, "UID must be 16 bytes"
|
||||
|
||||
if uid.upper().startswith("E004"):
|
||||
card_type = 1
|
||||
elif uid.upper().startswith("0"):
|
||||
card_type = 2
|
||||
else:
|
||||
raise ValueError("Invalid UID prefix")
|
||||
if uid.upper().startswith("E004"):
|
||||
card_type = 1
|
||||
elif uid.upper().startswith("0"):
|
||||
card_type = 2
|
||||
else:
|
||||
raise ValueError("Invalid UID prefix")
|
||||
|
||||
kid = binascii.unhexlify(uid)
|
||||
assert len(kid) == 8, "ID must be 8 bytes"
|
||||
kid = binascii.unhexlify(uid)
|
||||
assert len(kid) == 8, "ID must be 8 bytes"
|
||||
|
||||
out = bytearray(unpack_5(enc_des(kid[::-1]))[:13]) + b'\0\0\0'
|
||||
out = bytearray(unpack_5(enc_des(kid[::-1]))[:13]) + b'\0\0\0'
|
||||
|
||||
out[0] ^= card_type
|
||||
out[13] = 1
|
||||
for i in range(1, 14):
|
||||
out[i] ^= out[i - 1]
|
||||
out[14] = card_type
|
||||
out[15] = checksum(out)
|
||||
out[0] ^= card_type
|
||||
out[13] = 1
|
||||
for i in range(1, 14):
|
||||
out[i] ^= out[i - 1]
|
||||
out[14] = card_type
|
||||
out[15] = checksum(out)
|
||||
|
||||
return "".join(ALPHABET[i] for i in out)
|
||||
return "".join(ALPHABET[i] for i in out)
|
||||
|
||||
|
||||
def to_uid(konami_id):
|
||||
if konami_id[14] == "1":
|
||||
card_type = 1
|
||||
elif konami_id[14] == "2":
|
||||
card_type = 2
|
||||
else:
|
||||
raise ValueError("Invalid ID")
|
||||
if konami_id[14] == "1":
|
||||
card_type = 1
|
||||
elif konami_id[14] == "2":
|
||||
card_type = 2
|
||||
else:
|
||||
raise ValueError("Invalid ID")
|
||||
|
||||
assert len(konami_id) == 16, f"ID must be 16 characters"
|
||||
assert all(i in ALPHABET for i in konami_id), "ID contains invalid characters"
|
||||
card = [ALPHABET.index(i) for i in konami_id]
|
||||
assert card[11] % 2 == card[12] % 2, "Parity check failed"
|
||||
assert card[13] == card[12] ^ 1, "Card invalid"
|
||||
assert card[15] == checksum(card), "Checksum failed"
|
||||
assert len(konami_id) == 16, f"ID must be 16 characters"
|
||||
assert all(i in ALPHABET for i in konami_id), "ID contains invalid characters"
|
||||
card = [ALPHABET.index(i) for i in konami_id]
|
||||
assert card[11] % 2 == card[12] % 2, "Parity check failed"
|
||||
assert card[13] == card[12] ^ 1, "Card invalid"
|
||||
assert card[15] == checksum(card), "Checksum failed"
|
||||
|
||||
for i in range(13, 0, -1):
|
||||
card[i] ^= card[i - 1]
|
||||
for i in range(13, 0, -1):
|
||||
card[i] ^= card[i - 1]
|
||||
|
||||
card[0] ^= card_type
|
||||
card[0] ^= card_type
|
||||
|
||||
card_id = dec_des(pack_5(card[:13])[:8])[::-1]
|
||||
card_id = binascii.hexlify(card_id).decode().upper()
|
||||
card_id = dec_des(pack_5(card[:13])[:8])[::-1]
|
||||
card_id = binascii.hexlify(card_id).decode().upper()
|
||||
|
||||
if card_type == 1:
|
||||
assert card_id[:4] == "E004", "Invalid card type"
|
||||
elif card_type == 2:
|
||||
assert card_id[0] == "0", "Invalid card type"
|
||||
return card_id
|
||||
if card_type == 1:
|
||||
assert card_id[:4] == "E004", "Invalid card type"
|
||||
elif card_type == 2:
|
||||
assert card_id[0] == "0", "Invalid card type"
|
||||
return card_id
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
assert to_konami_id("0000000000000000") == "007TUT8XJNSSPN2P", "To KID failed"
|
||||
assert to_uid("007TUT8XJNSSPN2P") == "0000000000000000", "From KID failed"
|
||||
assert to_uid(to_konami_id("000000100200F000")) == "000000100200F000", "Roundtrip failed"
|
||||
assert to_konami_id("0000000000000000") == "007TUT8XJNSSPN2P", "To KID failed"
|
||||
assert to_uid("007TUT8XJNSSPN2P") == "0000000000000000", "From KID failed"
|
||||
assert to_uid(to_konami_id("000000100200F000")) == "000000100200F000", "Roundtrip failed"
|
||||
</code></pre>
|
||||
</details>
|
||||
<p>e-Amusement cards use 16 digit IDs. KONAMI IDs are also 16 digits. Are they related? Yes! In fact, KONAMI IDs are
|
||||
derived from the ID stored on the e-Amusement card.</p>
|
||||
<p>KONAMI IDs have an alphabet of <code>0123456789ABCDEFGHJKLMNPRSTUWXYZ</code> (note that <code>IOQV</code> are
|
||||
absent), whereas e-A IDs (yeah I'm not typing that out every time) have an alphabet of
|
||||
<code>0123456789ABCDEF</code> (hex). It stands to reason then that there's additional information present in
|
||||
KONAMI IDs, as they are the same length, but can hold a greater density of information. That intuition would be
|
||||
correct.
|
||||
</p>
|
||||
<h2 id="konami">Converting KONAMI IDs to e-Amusement IDs</h2>
|
||||
<p>Let's take a look at the format of KONAMI IDs. The first step before we can do anything is to convert it from a
|
||||
string to a series of integers. Each byte is replaced with its index in the alphabet, giving us 16 values
|
||||
ranging from 0 through 31. These bytes has the following meanings:</p>
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
<td>12</td>
|
||||
<td>13</td>
|
||||
<td>14</td>
|
||||
<td>15</td>
|
||||
</tr>
|
||||
</thead>
|
||||
</details>
|
||||
<p>e-Amusement cards use 16 digit IDs. KONAMI IDs are also 16 digits. Are they related? Yes! In fact, KONAMI IDs are
|
||||
derived from the ID stored on the e-Amusement card.</p>
|
||||
<p>KONAMI IDs have an alphabet of <code>0123456789ABCDEFGHJKLMNPRSTUWXYZ</code> (note that <code>IOQV</code> are
|
||||
absent), whereas e-A IDs (yeah I'm not typing that out every time) have an alphabet of
|
||||
<code>0123456789ABCDEF</code> (hex). It stands to reason then that there's additional information present in
|
||||
KONAMI IDs, as they are the same length, but can hold a greater density of information. That intuition would be
|
||||
correct.
|
||||
</p>
|
||||
<h2 id="konami">Converting KONAMI IDs to e-Amusement IDs</h2>
|
||||
<p>Let's take a look at the format of KONAMI IDs. The first step before we can do anything is to convert it from a
|
||||
string to a series of integers. Each byte is replaced with its index in the alphabet, giving us 16 values
|
||||
ranging from 0 through 31. These bytes has the following meanings:</p>
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td colspan="13">e-Amusement ID</td>
|
||||
<td>Check byte</td>
|
||||
<td>Card type</td>
|
||||
<td>Checksum</td>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
<td>12</td>
|
||||
<td>13</td>
|
||||
<td>14</td>
|
||||
<td>15</td>
|
||||
</tr>
|
||||
</table>
|
||||
</thead>
|
||||
<tr>
|
||||
<td colspan="13">e-Amusement ID</td>
|
||||
<td>Check byte</td>
|
||||
<td>Card type</td>
|
||||
<td>Checksum</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Due to how IDs are constructed, there are a number of checks we can perform to validate an ID:</p>
|
||||
<ul>
|
||||
<li>Parity check: <code>[11] % 2 == [12] % 2</code></li>
|
||||
<li>Encoding check: <code>[13] == [12] ^ 1</code></li>
|
||||
<li>Checksum: <code>[15] == <a href="#checksum">checksum([0..14])</a></code></li>
|
||||
<li>Post-decoding, FeliCa cards start with <code>0</code> and magnetic strip cards start with <code>E004</code>.
|
||||
</li>
|
||||
<li>Card type: <code>[14] == 1</code> (magnetic stripe) or <code>[14] == 2</code> (FeliCa)</li>
|
||||
</ul>
|
||||
<p>Due to how IDs are constructed, there are a number of checks we can perform to validate an ID:</p>
|
||||
<ul>
|
||||
<li>Parity check: <code>[11] % 2 == [12] % 2</code></li>
|
||||
<li>Encoding check: <code>[13] == [12] ^ 1</code></li>
|
||||
<li>Checksum: <code>[15] == <a href="#checksum">checksum([0..14])</a></code></li>
|
||||
<li>Post-decoding, FeliCa cards start with <code>0</code> and magnetic strip cards start with <code>E004</code>.
|
||||
</li>
|
||||
<li>Card type: <code>[14] == 1</code> (magnetic stripe) or <code>[14] == 2</code> (FeliCa)</li>
|
||||
</ul>
|
||||
|
||||
<p>To decrypt a KONAMI ID, at a high level we must:</p>
|
||||
<ul>
|
||||
<li>Remove the XOR encoding</li>
|
||||
<li>5-pack the ID</li>
|
||||
<li>Decrypt the packed ID</li>
|
||||
<li>Reverse the bytes</li>
|
||||
<li>Convert to upper-case hex</li>
|
||||
</ul>
|
||||
<p>As we'll see in the next section, card IDs have an XOR pass performed. This is what allows for the above encoding
|
||||
check, but we must remove it before we can begin decoding. A line of code speaks a thousand words, so have
|
||||
three:</p>
|
||||
<pre><code>for i from 13 to 1 inclusive:
|
||||
<p>To decrypt a KONAMI ID, at a high level we must:</p>
|
||||
<ul>
|
||||
<li>Remove the XOR encoding</li>
|
||||
<li>5-pack the ID</li>
|
||||
<li>Decrypt the packed ID</li>
|
||||
<li>Reverse the bytes</li>
|
||||
<li>Convert to upper-case hex</li>
|
||||
</ul>
|
||||
<p>As we'll see in the next section, card IDs have an XOR pass performed. This is what allows for the above encoding
|
||||
check, but we must remove it before we can begin decoding. A line of code speaks a thousand words, so have
|
||||
three:</p>
|
||||
<pre><code>for i from 13 to 1 inclusive:
|
||||
card[i] ^= card[i - 1]
|
||||
card[0] ^= card_type</code></pre>
|
||||
<p id="packing">The values in the <code>e-Amusement ID</code> field above will all maximally be 31
|
||||
(<code>0b11111</code>) therefore before we perform the decryption step we first densly pack these 5-bit
|
||||
integers. That is, <code>0b11111 0b00000 0b11111</code> would be packed to <code>0b11111000 0b00111110</code>.
|
||||
This value will be 8 bytes long. We can now <a href="#des">decrypt it</a>, reverse it, and convert to hex.
|
||||
<p id="packing">The values in the <code>e-Amusement ID</code> field above will all maximally be 31
|
||||
(<code>0b11111</code>) therefore before we perform the decryption step we first densly pack these 5-bit
|
||||
integers. That is, <code>0b11111 0b00000 0b11111</code> would be packed to <code>0b11111000 0b00111110</code>.
|
||||
This value will be 8 bytes long. We can now <a href="#des">decrypt it</a>, reverse it, and convert to hex.
|
||||
</p>
|
||||
<details>
|
||||
<summary>Implementing 5-bit packing</summary>
|
||||
<p>In most languages, implementing a packer can be done one of two ways. The approach chosen by Bemani is to
|
||||
first create a table of every individual bit (each stored in a whole byte!), then iterate through the bits
|
||||
ORing them together. This is a simple but wasteful implementation. The other approach is to use a buffer
|
||||
byte and slowly shift values in, tracking how many bits are stored in the buffer byte, and performing
|
||||
different actions depending on how many bits this is. For both packing and unpacking this requires three
|
||||
cases. It's somewhat more complex, but less wasteful in terms of memory usage. Pick your poison I suppose.
|
||||
</p>
|
||||
<details>
|
||||
<summary>Implementing 5-bit packing</summary>
|
||||
<p>In most languages, implementing a packer can be done one of two ways. The approach chosen by Bemani is to
|
||||
first create a table of every individual bit (each stored in a whole byte!), then iterate through the bits
|
||||
ORing them together. This is a simple but wasteful implementation. The other approach is to use a buffer
|
||||
byte and slowly shift values in, tracking how many bits are stored in the buffer byte, and performing
|
||||
different actions depending on how many bits this is. For both packing and unpacking this requires three
|
||||
cases. It's somewhat more complex, but less wasteful in terms of memory usage. Pick your poison I suppose.
|
||||
</p>
|
||||
<details>
|
||||
<summary>In <i>most</i> languages?</summary>
|
||||
<p>Haha well you see we can actually cheat and use string manipulation. Wasteful? Incredibly. Efficient? Not
|
||||
at all. Quick and easy? Yup!</p>
|
||||
<pre><code>def pack_5(data):
|
||||
<summary>In <i>most</i> languages?</summary>
|
||||
<p>Haha well you see we can actually cheat and use string manipulation. Wasteful? Incredibly. Efficient? Not
|
||||
at all. Quick and easy? Yup!</p>
|
||||
<pre><code>def pack_5(data):
|
||||
data = "".join(f"{i:05b}" for i in data)
|
||||
if len(data) % 8 != 0:
|
||||
data += "0" * (8 - (len(data) % 8))
|
||||
@ -226,39 +206,39 @@ def unpack_5(data):
|
||||
if len(data) % 5 != 0:
|
||||
data += "0" * (5 - (len(data) % 5))
|
||||
return bytes(int(data[i:i+5], 2) for i in range(0, len(data), 5))</code></pre>
|
||||
<p>If your language of choice allows this, and you don't care for efficiency, this can be a great time-saver
|
||||
towards get something working. Truth be told my local implementation originally used the Bemani method
|
||||
(it was a line-for-line port, after all), switched to the second method, then I opted for this hacky
|
||||
string method in the name of code clarity.</p>
|
||||
</details>
|
||||
<p>If your language of choice allows this, and you don't care for efficiency, this can be a great time-saver
|
||||
towards get something working. Truth be told my local implementation originally used the Bemani method
|
||||
(it was a line-for-line port, after all), switched to the second method, then I opted for this hacky
|
||||
string method in the name of code clarity.</p>
|
||||
</details>
|
||||
</details>
|
||||
|
||||
<h2 id="eaid">Converting e-Amusement IDs to KONAMI IDs</h2>
|
||||
<p>This is mostly the above process, in reverse, but we need to make sure to populate some of the extra check bytes.
|
||||
</p>
|
||||
<p>Before we start, we need to make sure we have a valid card! FeliCa cards (type <code>2</code>) will begin with a
|
||||
single null nibble, and magnetic stripe cards (type <code>1</code>) with the word <code>E004</code>. We then
|
||||
parse the entire ID as a hex string, giving us an 8-byte value.</p>
|
||||
<p>This value is reversed, and <a href="#des">encrypted</a>. After encryption, we need to unpack it from it's
|
||||
5-packed format. This is the same process as <a href="#packing">unpacking</a>, but reversed. The unpacked data
|
||||
can be ambiguous in length. It's 13 bytes. If your unpacker produces a 14th byte, it'll be null and can be
|
||||
discarded.</p>
|
||||
<p>We pad the 13 bytes with 3 extra null bytes, then apply our checks to the ID:</p>
|
||||
<pre><code>card[0] ^= card_type
|
||||
<h2 id="eaid">Converting e-Amusement IDs to KONAMI IDs</h2>
|
||||
<p>This is mostly the above process, in reverse, but we need to make sure to populate some of the extra check bytes.
|
||||
</p>
|
||||
<p>Before we start, we need to make sure we have a valid card! FeliCa cards (type <code>2</code>) will begin with a
|
||||
single null nibble, and magnetic stripe cards (type <code>1</code>) with the word <code>E004</code>. We then
|
||||
parse the entire ID as a hex string, giving us an 8-byte value.</p>
|
||||
<p>This value is reversed, and <a href="#des">encrypted</a>. After encryption, we need to unpack it from it's
|
||||
5-packed format. This is the same process as <a href="#packing">unpacking</a>, but reversed. The unpacked data
|
||||
can be ambiguous in length. It's 13 bytes. If your unpacker produces a 14th byte, it'll be null and can be
|
||||
discarded.</p>
|
||||
<p>We pad the 13 bytes with 3 extra null bytes, then apply our checks to the ID:</p>
|
||||
<pre><code>card[0] ^= card_type
|
||||
card[13] = 1
|
||||
for i from 0 to 13 inclusive:
|
||||
card[i + 1] ^= card[i]
|
||||
card[14] = card_type
|
||||
card[15] = <a href="#checksum">checksum(card)</a></code></pre>
|
||||
|
||||
<p>This leaves us with 16 values ranging from 0 to 31, which we apply as indecies to our alphabet to produce the
|
||||
final ID.</p>
|
||||
<p>This leaves us with 16 values ranging from 0 to 31, which we apply as indecies to our alphabet to produce the
|
||||
final ID.</p>
|
||||
|
||||
<h2 id="checksum">Checksums</h2>
|
||||
<p>As if the encryption and XOR wasn't enough, card IDs also contain a checksum to make <i>absolutely</i> sure the
|
||||
card is valid. I could explain in words how the checksum works, but that's probably not very useful. Have a
|
||||
pseudocode snippet instead:</p>
|
||||
<pre><code>checksum(bytes):
|
||||
<h2 id="checksum">Checksums</h2>
|
||||
<p>As if the encryption and XOR wasn't enough, card IDs also contain a checksum to make <i>absolutely</i> sure the
|
||||
card is valid. I could explain in words how the checksum works, but that's probably not very useful. Have a
|
||||
pseudocode snippet instead:</p>
|
||||
<pre><code>checksum(bytes):
|
||||
chk = 0
|
||||
for i from 0 to 14 inclusive:
|
||||
chk += bytes[i] * (i % 3 + 1)
|
||||
@ -268,31 +248,31 @@ card[15] = <a href="#checksum">checksum(card)</a></code></pre>
|
||||
|
||||
return chk</code></pre>
|
||||
|
||||
<h2 id="des">The DES scheme used</h2>
|
||||
<p>For whatever reason, Bemani decided that IDs should be encrypted. Thankfully however they used triple DES, which
|
||||
almost certainly has an existing implementation in your language of choice. It is triple DES, in CBC mode, with
|
||||
a totally null <code>IV</code>. The key is quite easy to find if you hit the right binaries with
|
||||
<code>strings</code>. <span style="color: white">Alternatively, check the source of this page.</span> The key
|
||||
contains characters that are all within the ASCII range. Before we can use it with DES, the value of every byte
|
||||
needs doubled. This was presumably done to give the values more range, but I sincerely doubt it adds any
|
||||
additional security.
|
||||
</p>
|
||||
<!-- Oh hello there. "?I'llB2c.YouXXXeMeHaYpy!" (without the quotes). Don't forget to double every byte before using
|
||||
<h2 id="des">The DES scheme used</h2>
|
||||
<p>For whatever reason, Bemani decided that IDs should be encrypted. Thankfully however they used triple DES, which
|
||||
almost certainly has an existing implementation in your language of choice. It is triple DES, in CBC mode, with
|
||||
a totally null <code>IV</code>. The key is quite easy to find if you hit the right binaries with
|
||||
<code>strings</code>. <span style="color: white">Alternatively, check the source of this page.</span> The key
|
||||
contains characters that are all within the ASCII range. Before we can use it with DES, the value of every byte
|
||||
needs doubled. This was presumably done to give the values more range, but I sincerely doubt it adds any
|
||||
additional security.
|
||||
</p>
|
||||
<!-- Oh hello there. "?I'llB2c.YouXXXeMeHaYpy!" (without the quotes). Don't forget to double every byte before using
|
||||
the key, giving us an actual key of 7e924ed8d88464c65cb2deeab0b0b0ca9aca90c2b2e0f242. -->
|
||||
<details>
|
||||
<summary>I'm curious how Bemani implemented this in their own code!</summary>
|
||||
<p>Curiosity is a great thing. Unfortunately, this is code that is implement within the game specific DLL files.
|
||||
If you happen to have SDXV 4 in front of you too, head over over to <code>soundvoltex.dll:0x1027316f</code>
|
||||
and you should see everything you need.
|
||||
</p>
|
||||
<p>As part of breaking down how this all works, I produced a more or less line-for-line Python port of the game
|
||||
code, for testing, validation, etc.. It's not especially pretty, but should give you an idea of how it works
|
||||
under the hood. One interesting observation is that it looks like the initial and final permutation steps
|
||||
were inlined. It's also possible that they did the whole thing with macros rather than inline functions.
|
||||
Either way, my python port didn't do any cleaning up, because we can just use a DES library.</p>
|
||||
<details>
|
||||
<summary>I'm curious how Bemani implemented this in their own code!</summary>
|
||||
<p>Curiosity is a great thing. Unfortunately, this is code that is implement within the game specific DLL files.
|
||||
If you happen to have SDXV 4 in front of you too, head over over to <code>soundvoltex.dll:0x1027316f</code>
|
||||
and you should see everything you need.
|
||||
</p>
|
||||
<p>As part of breaking down how this all works, I produced a more or less line-for-line Python port of the game
|
||||
code, for testing, validation, etc.. It's not especially pretty, but should give you an idea of how it works
|
||||
under the hood. One interesting observation is that it looks like the initial and final permutation steps
|
||||
were inlined. It's also possible that they did the whole thing with macros rather than inline functions.
|
||||
Either way, my python port didn't do any cleaning up, because we can just use a DES library.</p>
|
||||
<details>
|
||||
<summary>Show me that!</summary>
|
||||
<pre><code>DES_KEYMAP = [
|
||||
<summary>Show me that!</summary>
|
||||
<pre><code>DES_KEYMAP = [
|
||||
[0x02080008, 0x02082000, 0x00002008, 0x00000000, 0x02002000, 0x00080008, 0x02080000, 0x02082008, 0x00000008, 0x02000000, 0x00082000, 0x00002008, 0x00082008, 0x02002008, 0x02000008, 0x02080000, 0x00002000, 0x00082008, 0x00080008, 0x02002000, 0x02082008, 0x02000008, 0x00000000, 0x00082000, 0x02000000, 0x00080000, 0x02002008, 0x02080008, 0x00080000, 0x00002000, 0x02082000, 0x00000008, 0x00080000, 0x00002000, 0x02000008, 0x02082008, 0x00002008, 0x02000000, 0x00000000, 0x00082000, 0x02080008, 0x02002008, 0x02002000, 0x00080008, 0x02082000, 0x00000008, 0x00080008, 0x02002000, 0x02082008, 0x00080000, 0x02080000, 0x02000008, 0x00082000, 0x00002008, 0x02002008, 0x02080000, 0x00000008, 0x02082000, 0x00082008, 0x00000000, 0x02000000, 0x02080008, 0x00002000, 0x00082008],
|
||||
[0x08000004, 0x00020004, 0x00000000, 0x08020200, 0x00020004, 0x00000200, 0x08000204, 0x00020000, 0x00000204, 0x08020204, 0x00020200, 0x08000000, 0x08000200, 0x08000004, 0x08020000, 0x00020204, 0x00020000, 0x08000204, 0x08020004, 0x00000000, 0x00000200, 0x00000004, 0x08020200, 0x08020004, 0x08020204, 0x08020000, 0x08000000, 0x00000204, 0x00000004, 0x00020200, 0x00020204, 0x08000200, 0x00000204, 0x08000000, 0x08000200, 0x00020204, 0x08020200, 0x00020004, 0x00000000, 0x08000200, 0x08000000, 0x00000200, 0x08020004, 0x00020000, 0x00020004, 0x08020204, 0x00020200, 0x00000004, 0x08020204, 0x00020200, 0x00020000, 0x08000204, 0x08000004, 0x08020000, 0x00020204, 0x00000000, 0x00000200, 0x08000004, 0x08000204, 0x08020200, 0x08020000, 0x00000204, 0x00000004, 0x08020004],
|
||||
[0x80040100, 0x01000100, 0x80000000, 0x81040100, 0x00000000, 0x01040000, 0x81000100, 0x80040000, 0x01040100, 0x81000000, 0x01000000, 0x80000100, 0x81000000, 0x80040100, 0x00040000, 0x01000000, 0x81040000, 0x00040100, 0x00000100, 0x80000000, 0x00040100, 0x81000100, 0x01040000, 0x00000100, 0x80000100, 0x00000000, 0x80040000, 0x01040100, 0x01000100, 0x81040000, 0x81040100, 0x00040000, 0x81040000, 0x80000100, 0x00040000, 0x81000000, 0x00040100, 0x01000100, 0x80000000, 0x01040000, 0x81000100, 0x00000000, 0x00000100, 0x80040000, 0x00000000, 0x81040000, 0x01040100, 0x00000100, 0x01000000, 0x81040100, 0x80040100, 0x00040000, 0x81040100, 0x80000000, 0x01000100, 0x80040100, 0x80040000, 0x00040100, 0x01040000, 0x81000100, 0x80000100, 0x01000000, 0x81000000, 0x01040100],
|
||||
@ -482,7 +462,6 @@ def load_key(key):
|
||||
for i in range(24):
|
||||
key_data[i] = 2 * key[i % len(key)]
|
||||
des3_setkey(KEY_DATA, key_data)</code></pre>
|
||||
</details>
|
||||
</details>
|
||||
|
||||
</body>
|
||||
</details>
|
||||
{% endblock %}
|
84
templates/pages/index.html
Normal file
84
templates/pages/index.html
Normal file
@ -0,0 +1,84 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1>Benami/Konami e-Amusement API</h1>
|
||||
<p>Why?</p>
|
||||
<p>I was curious how these APIs work, yet could find little to nothing on Google. There are a number of
|
||||
closed-source projects, with presumably similarly closed-source internal documentation, and a scattering of
|
||||
implementations of things, yet I couldn't find a site that actually just documents how the API works. If I'm
|
||||
going to have to reverse engineer an open source project (or a closed source one, for that matter), I might as
|
||||
well just go reverse engineer an actual game (or it's stdlib, as most of my time has been spent currently).</p>
|
||||
<p>For the sake of being lazy, I'll probably end up calling it eAmuse more than anything else throughout these
|
||||
pages. Other names you may come across include <code>httac</code> and <code>xrpc</code>. The latter are the
|
||||
suite of HTTP functions used in the Bemani stdlib, and the name of their communication protocol they implement
|
||||
at the application layer, but whenever someone refers to any of them in the context of a rhythm game, they will
|
||||
be referring to the things documented here.</p>
|
||||
<p>These pages are very much a work in progress, and are being written <i>as</i> I reverse engineer parts of the
|
||||
protocol. I've been asserting all my assumptions by writing my own implementation as I go, however it currently
|
||||
isn't sharable quality code and, more importantly, the purpose of these pages is to make implementation of one's
|
||||
own code hopefully trivial (teach a man to fish, and all that).</p>
|
||||
<p>Sharing annotated sources for all of the games' stdlibs would be both impractical and unwise. Where relevant
|
||||
however I try to include snippets to illustrate concepts, and have included their locations in the source for if
|
||||
you feel like taking a dive too.</p>
|
||||
<p>If you're here because you work on one of those aforementioned closed source projects, hello! Feel free to share
|
||||
knowledge with the rest of the world, or point out corrections. Or don't; you do you.</p>
|
||||
|
||||
<h3>Code snippets</h3>
|
||||
<p>Across these pages there are a number of code snippets. They roughly break down into three categories:</p>
|
||||
<ul>
|
||||
<li>Assembly: Directly disassembled code from game binaries</li>
|
||||
<li>C: Either raw decompilation, or slightly cleaned up decompilation</li>
|
||||
<li>Python: Snippets from my local testing implementations</li>
|
||||
<li>Pseudocode: Used to illustrate some points. Note that it probably started life as Python before being
|
||||
pseudo'd</li>
|
||||
</ul>
|
||||
<p>If you yoink chunks of Python code, attribution is always appreciated, but consider it under CC0 (just don't be
|
||||
that person who tries to take credit for it, yeah?).</p>
|
||||
|
||||
<h2>Contents</h2>
|
||||
<ol>
|
||||
<li><a href="./transport.html">Transport layer</a></li>
|
||||
<ol>
|
||||
<li><a href="./transport.html#packet">Packet structure</a></li>
|
||||
<li><a href="./transport.html#type">Types</a></li>
|
||||
</ol>
|
||||
<li><a href="./packet.html">The inner packet structure</a></li>
|
||||
<ol>
|
||||
<li><a href="./packet.html#xml">XML packets</a></li>
|
||||
<li><a href="./packet.html#binary">Binary packed packets</a></li>
|
||||
<li><a href="./packet.html#schema">Binary schemas</a></li>
|
||||
<li><a href="./packet.html#data">Binary data</a></li>
|
||||
</ol>
|
||||
<li><a href="./protocol.html">Communication protocol details</a></li>
|
||||
<ul>
|
||||
<li>There are a crazy number of sub pages here, so just go check the contents there.</li>
|
||||
</ul>
|
||||
<li>Misc pages</li>
|
||||
<ol>
|
||||
<li><a href="./cardid.html">Parsing and converting card IDs</a></li>
|
||||
</ol>
|
||||
</ol>
|
||||
|
||||
<h2>Getting started</h2>
|
||||
<p>My aim with these pages is to cover as much as possible, so you don't need to try and figure them out yourself.
|
||||
That said, being able to follow along yourself will almost certainly help get more out of this. For following
|
||||
along with source code, you're really going to want to grab yourself a dumped copy of a game (it's going to be a
|
||||
lot easier, and cheeper, than dumping one yourself). I trust you can figure out where to find that.</p>
|
||||
<p>For network related things, your options are a little broader. The ideal would be physical ownership of a
|
||||
cabinet, and a subscription to genuine e-amusement. Odds are you don't have both of those :P. A connection to an
|
||||
alternative network works just as well. In the more likely case that you don't have a physical cabinet, it's
|
||||
time to crack out that dumped copy of a game and just run it on your own PC (or a VM, if you're not on Windows)
|
||||
(odds are whatever you downloaded came with the program you'll need to start it pre-packaged. If not, it rhymes
|
||||
with rice.).</p>
|
||||
<p>You will also need a local e-amusement-emulating server. By the time I'm done with these pages, there will
|
||||
hopefully be everything you need to be able to write your own. Unfortunately I'm not finished writing them;
|
||||
depending on where you acquired your game, it may have shipped with one of said servers. If it didn't, Asphyxia
|
||||
CORE will do the trick (yes, it's closed source).</p>
|
||||
<p>If this all sounds like way too much work, and/or you're just here because of curiosity, I plan to prepare some
|
||||
pcaps of network traffic to play around with without needing a running copy of a game or a network tap on a cab.
|
||||
</p>
|
||||
|
||||
<a href="./transport.html">Next page</a>
|
||||
|
||||
<p><small>This site intentionally looks not-great. I don't feel like changing that, and honestly quite like the
|
||||
aesthetic.</small></p>
|
||||
{% endblock %}
|
881
templates/pages/packet.html
Normal file
881
templates/pages/packet.html
Normal file
@ -0,0 +1,881 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1>Packet format</h1>
|
||||
|
||||
<p>eAmuse uses XML for its application layer payloads*. This XML is either verbatim, or in a custom packed binary
|
||||
format.<br /><small>*Newer games use JSON, but this page is about XML.</small></p>
|
||||
|
||||
|
||||
<h2 id="xml">The XML format</h2>
|
||||
|
||||
<p>Each tag that contains a value has a <code>__type</code> attribute that identifies what type it is. Array types
|
||||
have a <code>__count</code> attribute indicating how many items are in the array. Binary blobs additionally have
|
||||
a <code>__size</code> attribute indicating their length (this is notably not present on strings, however).</p>
|
||||
<p>It is perhaps simpler to illustrate with an example, so:</p>
|
||||
<pre><code><?xml version='1.0' encoding='UTF-8'?>
|
||||
<call model="KFC:J:A:A:2019020600" srcid="1000" tag="b0312077">
|
||||
<eventlog method="write">
|
||||
<retrycnt __type="u32" />
|
||||
<data>
|
||||
<eventid __type="str">G_CARDED</eventid>
|
||||
<eventorder __type="s32">5</eventorder>
|
||||
<pcbtime __type="u64">1639669516779</pcbtime>
|
||||
<gamesession __type="s64">1</gamesession>
|
||||
<strdata1 __type="str" />
|
||||
<strdata2 __type="str" />
|
||||
<numdata1 __type="s64">1</numdata1>
|
||||
<numdata2 __type="s64" />
|
||||
<locationid __type="str">ea</locationid>
|
||||
</data>
|
||||
</eventlog>
|
||||
</call></code></pre>
|
||||
<p>Arrays are encoded by concatenating every value together, with spaces between them. Data types that have multiple
|
||||
values, are serialized similarly.</p>
|
||||
<p>Therefore, an element storing an array of <code>3u8</code> (<code>[(1, 2, 3), (4, 5, 6)]</code>) would look like
|
||||
this</p>
|
||||
<pre><code><demo __type="3u8" __count="2">1 2 3 4 5 6</demo></code></pre>
|
||||
<p>Besides this, this is otherwise a rather standard XML.</p>
|
||||
|
||||
<h2 id="binary">Packed binary overview</h2>
|
||||
|
||||
<p>Many packets, rather than using a string-based XML format, use a custom binary packed format instead. While it
|
||||
can be a little confusing, remembering that this is encoding an XML tree can make it easier to parse.</p>
|
||||
<p>To start with, let's take a look at the overall structure of the packets.</p>
|
||||
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
<td>12</td>
|
||||
<td>13</td>
|
||||
<td>14</td>
|
||||
<td>15</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td><i>A0</i></td>
|
||||
<td>C</td>
|
||||
<td>E</td>
|
||||
<td>~E</td>
|
||||
<td colspan="4">Head length</td>
|
||||
<td style="border-bottom: none" colspan="8"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none; border-bottom: none;" colspan="16">Schema definition</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none;" colspan="12"></td>
|
||||
<td colspan="1"><i>FF</i></td>
|
||||
<td colspan="3">Align</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">Data length</td>
|
||||
<td style="border-bottom: none" colspan="12"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none; border-bottom: none;" colspan="16">Payload</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none;" colspan="13"></td>
|
||||
<td colspan="3">Align</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Every packet starts with the magic byte <code>0xA0</code>. Following this is the content byte, the encoding byte,
|
||||
and then the 2's compliment of the encoding byte.</p>
|
||||
<p>Currently known possible values for the content byte are:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>C</td>
|
||||
<td>Content</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td><code>0x42</code></td>
|
||||
<td>Compressed data</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x43</code></td>
|
||||
<td>Compressed, no data</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x45</code></td>
|
||||
<td>Decompressed data</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x46</code></td>
|
||||
<td>Decompressed, no data</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Decompressed packets contain an XML string. Compressed packets are what we're interested in here.</p>
|
||||
<p>The encoding flag indicates the encoding for all string types in the packet (more on those later). Possible
|
||||
values are:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td><code>E</code></td>
|
||||
<td><code>~E</code></td>
|
||||
<td colspan="3">Encoding name</td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tr>
|
||||
<td><code>0x20</code></td>
|
||||
<td><code>0xDF</code></td>
|
||||
<td><code>ASCII</code></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x40</code></td>
|
||||
<td><code>0xBF</code></td>
|
||||
<td><code>ISO-8859-1</code></td>
|
||||
<td><code>ISO_8859-1</code></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x60</code></td>
|
||||
<td><code>0x9F</code></td>
|
||||
<td><code>EUC-JP</code></td>
|
||||
<td><code>EUCJP</code></td>
|
||||
<td><code>EUC_JP</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x80</code></td>
|
||||
<td><code>0x7F</code></td>
|
||||
<td><code>SHIFT-JIS</code></td>
|
||||
<td><code>SHIFT_JIS</code></td>
|
||||
<td><code>SJIS</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0xA0</code></td>
|
||||
<td><code>0x5F</code></td>
|
||||
<td><code>UTF-8</code></td>
|
||||
<td><code>UTF8</code></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<details>
|
||||
<summary>Source code details</summary>
|
||||
<p>The full table for these values can be found in libavs.</p>
|
||||
<figure>
|
||||
<img src="./images/encoding_table.png">
|
||||
<figcaption><code>libavs-win32.dll:0x1006b960</code></figcaption>
|
||||
</figure>
|
||||
<p>A second table exists just before this on in the source, responsible for the
|
||||
<code><?xml version='1.0' encoding='??'?></code> line in XML files.
|
||||
</p>
|
||||
<figure>
|
||||
<img src="./images/xml_encoding_table.png">
|
||||
<figcaption><code>libavs-win32.dll:0x1006b940</code></figcaption>
|
||||
</figure>
|
||||
<p>This is indexed using the following function, which maps the above encoding IDs to 1, 2, 3, 4 and 5
|
||||
respectively.</p>
|
||||
<pre><code>char* xml_get_encoding_name(uint encoding_id) {
|
||||
return ENCODING_NAME_TABLE[((encoding_id & 0xe0) >> 5) * 4];
|
||||
}</code></pre>
|
||||
</details>
|
||||
<p>While validating <code>~E</code> isn't technically required, it acts as a useful assertion that the packet being
|
||||
parsed is valid.</p>
|
||||
|
||||
<h2 id="schema">The packet schema header</h2>
|
||||
<p>Following the 4 byte header, is a 4 byte integer containing the length of the next part of the header (this is
|
||||
technically made redundant as this structure is also terminated).</p>
|
||||
<p>This part of the header defines the schema that the main payload uses.</p>
|
||||
|
||||
<p>A tag definition looks like:</p>
|
||||
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
<td>12</td>
|
||||
<td>13</td>
|
||||
<td>14</td>
|
||||
<td>15</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<td>nlen</td>
|
||||
<td colspan="7">Tag name</td>
|
||||
<td style="border-bottom: none" colspan="8"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border-top: none;" colspan="15">Attributes and children</td>
|
||||
<td colspan="1"><i>FE</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Structure names are encoded as densely packed 6 bit values, length prefixed (<code>nlen</code>). The acceptable
|
||||
alphabet is <code>0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz</code>, and the packed values
|
||||
are indecies within this alphabet.</p>
|
||||
|
||||
<p>The children can be a combination of either attribute names, or child tags. Attribute names are represented by
|
||||
the byte <code>0x2E</code> followed by a length prefixed name as defined above. Child tags follow the above
|
||||
format. Type <code>0x2E</code> must therefore be considered reserved as a possible structure type.</p>
|
||||
|
||||
<p>Attributes (type <code>0x2E</code>) represent a string attribute. Any other attribute must be defined as a child
|
||||
tag. Is it notable that 0 children is allowable, which is how the majority of values are encoded.</p>
|
||||
<p>All valid IDs, and their respective type, are listed in the following table. The bucket column here will be
|
||||
used later when unpacking the main data, so we need not worry about it for now, but be warned it exists and is
|
||||
possibly the least fun part of this format.</p>
|
||||
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>Bytes</td>
|
||||
<td>C type</td>
|
||||
<td>Bucket</td>
|
||||
<td colspan="2">XML names</td>
|
||||
<td></td>
|
||||
<td>ID</td>
|
||||
<td>Bytes</td>
|
||||
<td>C type</td>
|
||||
<td>Bucket</td>
|
||||
<td colspan="2">XML names</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>0x01</td>
|
||||
<td>0</td>
|
||||
<td>void</td>
|
||||
<td>-</td>
|
||||
<td>void</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x21</td>
|
||||
<td>24</td>
|
||||
<td>uint64[3]</td>
|
||||
<td>int</td>
|
||||
<td>3u64</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x02</td>
|
||||
<td>1</td>
|
||||
<td>int8</td>
|
||||
<td>byte</td>
|
||||
<td>s8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x22</td>
|
||||
<td>12</td>
|
||||
<td>float[3]</td>
|
||||
<td>int</td>
|
||||
<td>3f</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x03</td>
|
||||
<td>1</td>
|
||||
<td>uint8</td>
|
||||
<td>byte</td>
|
||||
<td>u8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x23</td>
|
||||
<td>24</td>
|
||||
<td>double[3]</td>
|
||||
<td>int</td>
|
||||
<td>3d</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x04</td>
|
||||
<td>2</td>
|
||||
<td>int16</td>
|
||||
<td>short</td>
|
||||
<td>s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x24</td>
|
||||
<td>4</td>
|
||||
<td>int8[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s8</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x05</td>
|
||||
<td>2</td>
|
||||
<td>uint16</td>
|
||||
<td>short</td>
|
||||
<td>s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x25</td>
|
||||
<td>4</td>
|
||||
<td>uint8[4]</td>
|
||||
<td>int</td>
|
||||
<td>4u8</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x06</td>
|
||||
<td>4</td>
|
||||
<td>int32</td>
|
||||
<td>int</td>
|
||||
<td>s32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x26</td>
|
||||
<td>8</td>
|
||||
<td>int16[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s16</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x07</td>
|
||||
<td>4</td>
|
||||
<td>uint32</td>
|
||||
<td>int</td>
|
||||
<td>u32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x27</td>
|
||||
<td>8</td>
|
||||
<td>uint8[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s16</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x08</td>
|
||||
<td>8</td>
|
||||
<td>int64</td>
|
||||
<td>int</td>
|
||||
<td>s64</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x28</td>
|
||||
<td>16</td>
|
||||
<td>int32[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s32</td>
|
||||
<td>vs32</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x09</td>
|
||||
<td>8</td>
|
||||
<td>uint64</td>
|
||||
<td>int</td>
|
||||
<td>u64</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x29</td>
|
||||
<td>16</td>
|
||||
<td>uint32[4]</td>
|
||||
<td>int</td>
|
||||
<td>4u32</td>
|
||||
<td>vs32</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0a</td>
|
||||
<td><i>prefix</i></td>
|
||||
<td>char[]</td>
|
||||
<td>int</td>
|
||||
<td>bin</td>
|
||||
<td>binary</td>
|
||||
<td></td>
|
||||
<td>0x2a</td>
|
||||
<td>32</td>
|
||||
<td>int64[4]</td>
|
||||
<td>int</td>
|
||||
<td>4s64</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0b</td>
|
||||
<td><i>prefix</i></td>
|
||||
<td>char[]</td>
|
||||
<td>int</td>
|
||||
<td>str</td>
|
||||
<td>string</td>
|
||||
<td></td>
|
||||
<td>0x2b</td>
|
||||
<td>32</td>
|
||||
<td>uint64[4]</td>
|
||||
<td>int</td>
|
||||
<td>4u64</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0c</td>
|
||||
<td>4</td>
|
||||
<td>uint8[4]</td>
|
||||
<td>int</td>
|
||||
<td>ip4</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x2c</td>
|
||||
<td>16</td>
|
||||
<td>float[4]</td>
|
||||
<td>int</td>
|
||||
<td>4f</td>
|
||||
<td>vf</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0d</td>
|
||||
<td>4</td>
|
||||
<td>uint32</td>
|
||||
<td>int</td>
|
||||
<td>time</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x2d</td>
|
||||
<td>32</td>
|
||||
<td>double[4]</td>
|
||||
<td>int</td>
|
||||
<td>4d</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0e</td>
|
||||
<td>4</td>
|
||||
<td>float</td>
|
||||
<td>int</td>
|
||||
<td>float</td>
|
||||
<td>f</td>
|
||||
<td></td>
|
||||
<td>0x2e</td>
|
||||
<td><i>prefix</i></td>
|
||||
<td>char[]</td>
|
||||
<td>int</td>
|
||||
<td>attr</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x0f</td>
|
||||
<td>8</td>
|
||||
<td>double</td>
|
||||
<td>int</td>
|
||||
<td>double</td>
|
||||
<td>d</td>
|
||||
<td></td>
|
||||
<td>0x2f</td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
<td>-</td>
|
||||
<td>array</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x10</td>
|
||||
<td>2</td>
|
||||
<td>int8[2]</td>
|
||||
<td>short</td>
|
||||
<td>2s8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x30</td>
|
||||
<td>16</td>
|
||||
<td>int8[16]</td>
|
||||
<td>int</td>
|
||||
<td>vs8</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x11</td>
|
||||
<td>2</td>
|
||||
<td>uint8[2]</td>
|
||||
<td>short</td>
|
||||
<td>2u8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x31</td>
|
||||
<td>16</td>
|
||||
<td>uint8[16]</td>
|
||||
<td>int</td>
|
||||
<td>vu8</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x12</td>
|
||||
<td>4</td>
|
||||
<td>int16[2]</td>
|
||||
<td>int</td>
|
||||
<td>2s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x32</td>
|
||||
<td>16</td>
|
||||
<td>int8[8]</td>
|
||||
<td>int</td>
|
||||
<td>vs16</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x13</td>
|
||||
<td>4</td>
|
||||
<td>uint16[2]</td>
|
||||
<td>int</td>
|
||||
<td>2s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x33</td>
|
||||
<td>16</td>
|
||||
<td>uint8[8]</td>
|
||||
<td>int</td>
|
||||
<td>vu16</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x14</td>
|
||||
<td>8</td>
|
||||
<td>int32[2]</td>
|
||||
<td>int</td>
|
||||
<td>2s32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x34</td>
|
||||
<td>1</td>
|
||||
<td>bool</td>
|
||||
<td>byte</td>
|
||||
<td>bool</td>
|
||||
<td>b</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x15</td>
|
||||
<td>8</td>
|
||||
<td>uint32[2]</td>
|
||||
<td>int</td>
|
||||
<td>2u32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x35</td>
|
||||
<td>2</td>
|
||||
<td>bool[2]</td>
|
||||
<td>short</td>
|
||||
<td>2b</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x16</td>
|
||||
<td>16</td>
|
||||
<td>int16[2]</td>
|
||||
<td>int</td>
|
||||
<td>2s64</td>
|
||||
<td>vs64</td>
|
||||
<td></td>
|
||||
<td>0x36</td>
|
||||
<td>3</td>
|
||||
<td>bool[3]</td>
|
||||
<td>int</td>
|
||||
<td>3b</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x17</td>
|
||||
<td>16</td>
|
||||
<td>uint16[2]</td>
|
||||
<td>int</td>
|
||||
<td>2u64</td>
|
||||
<td>vu64</td>
|
||||
<td></td>
|
||||
<td>0x37</td>
|
||||
<td>4</td>
|
||||
<td>bool[4]</td>
|
||||
<td>int</td>
|
||||
<td>4b</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x18</td>
|
||||
<td>8</td>
|
||||
<td>float[2]</td>
|
||||
<td>int</td>
|
||||
<td>2f</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x38</td>
|
||||
<td>16</td>
|
||||
<td>bool[16]</td>
|
||||
<td>int</td>
|
||||
<td>vb</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x19</td>
|
||||
<td>16</td>
|
||||
<td>double[2]</td>
|
||||
<td>int</td>
|
||||
<td>2d</td>
|
||||
<td>vd</td>
|
||||
<td></td>
|
||||
<td>0x38</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1a</td>
|
||||
<td>3</td>
|
||||
<td>int8[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x39</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1b</td>
|
||||
<td>3</td>
|
||||
<td>uint8[3]</td>
|
||||
<td>int</td>
|
||||
<td>3u8</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3a</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1c</td>
|
||||
<td>6</td>
|
||||
<td>int16[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3b</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1d</td>
|
||||
<td>6</td>
|
||||
<td>uint16[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s16</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3c</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1e</td>
|
||||
<td>12</td>
|
||||
<td>int32[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3d</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x1f</td>
|
||||
<td>12</td>
|
||||
<td>uint32[3]</td>
|
||||
<td>int</td>
|
||||
<td>3u32</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3e</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x20</td>
|
||||
<td>24</td>
|
||||
<td>int64[3]</td>
|
||||
<td>int</td>
|
||||
<td>3s64</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0x3f</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Strings should be encoded and decoded according to the encoding specified in the packet header. Null termination is
|
||||
optional, however should be stripped during decoding.</p>
|
||||
<p>All of these IDs are <code>& 0x3F</code>. Any value can be turned into an array by setting the 7<sup>th</sup> bit
|
||||
high (<code>| 0x40</code>). Arrays of this form, in the data section, will be an aligned <code>size: u32</code>
|
||||
immediately followed by <code>size</code> bytes' worth of (unaligned!) values of the unmasked type.</p>
|
||||
|
||||
<details>
|
||||
<summary>Source code details</summary>
|
||||
<p>The full table for these values can be found in libavs. This table contains the names of every tag, along
|
||||
with additional information such as how many bytes that data type requires, and which parsing function
|
||||
should be used.</p>
|
||||
<figure>
|
||||
<img src="./images/types_table.png">
|
||||
<figcaption><code>libavs-win32.dll:0x100782a8</code></figcaption>
|
||||
</figure>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Note about the <code>array</code> type:</summary>
|
||||
<p>While I'm not totally sure, I have a suspicion this type is used internally as a pseudo-type. Trying to
|
||||
identify its function as a parsable type has some obvious blockers:</p>
|
||||
|
||||
<p>All of the types have convenient <code>printf</code>-using helper functions that are used to emit them when
|
||||
serializing XML. All except one.</p>
|
||||
<img src="./images/no_array.png">
|
||||
<p>If we have a look inside the function that populates node sizes (<code>libavs-win32.dll:0x1000cf00</code>),
|
||||
it has an explicit case, however is the same fallback as the default case.</p>
|
||||
<img src="./images/no_array_2.png">
|
||||
|
||||
<p>In the same function, however, we can find a second (technically first) check for the array type.</p>
|
||||
<img src="./images/yes_array.png">
|
||||
<p>This seems to suggest that internally arrays are represented as a normal node, with the <code>array</code>
|
||||
type, however when serializing it's converted into the array types we're used to (well, will be after the
|
||||
next sections) by masking 0x40 onto the contained type.</p>
|
||||
<p>Also of interest from this snippet is the fact that <code>void</code>, <code>bin</code>, <code>str</code>,
|
||||
and <code>attr</code> cannot be arrays. <code>void</code> and <code>attr</code> make sense, however
|
||||
<code>str</code> and <code>bin</code> are more interesting. I suspect this is because konami want to be able
|
||||
to preallocate the memory, which wouldn't be possible with these variable length structures.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<h2 id="data">The data section</h2>
|
||||
|
||||
<p>This is where all the actual packet data is. For the most part, parsing this is the easy part. We traverse our
|
||||
schema, and read values out of the packet according to the value indicated in the schema. Unfortunately, konami
|
||||
decided all data should be aligned very specifically, and that gaps left during alignment should be backfilled
|
||||
later. This makes both reading and writing somewhat more complicated, however the system can be fairly easily
|
||||
understood.</p>
|
||||
<p>Firstly, we divide the payload up into 4 byte chunks. Each chunk can be allocated to either store individual
|
||||
bytes, shorts, or ints (these are the buckets in the table above). When reading or writing a value, we first
|
||||
check if a chunk allocated to the desired type's bucket is available and has free/as-yet-unread space within it.
|
||||
If so, we will store/read our data to/from there. If there is no such chunk, we claim the next unclaimed chunk
|
||||
for our bucket.</p>
|
||||
<p>For example, imagine we write the sequence <code>byte, int, byte, short, byte, int, short</code>. The final output
|
||||
should look like:</p>
|
||||
|
||||
<table class="code">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
<td>12</td>
|
||||
<td>13</td>
|
||||
<td>14</td>
|
||||
<td>15</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>byte</td>
|
||||
<td>byte</td>
|
||||
<td>byte</td>
|
||||
<td></td>
|
||||
<td colspan="4">int</td>
|
||||
<td colspan="2">short</td>
|
||||
<td colspan="2">short</td>
|
||||
<td colspan="4">int</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>While this might seem a silly system compared to just not aligning values, it is at least possible to intuit that it
|
||||
helps reduce wasted space. It should be noted that any variable-length structure, such as a string or an array,
|
||||
claims all chunks it encroaches on for the <code>int</code> bucket, disallowing the storage of bytes or shorts
|
||||
within them.</p>
|
||||
|
||||
<details>
|
||||
<summary>Implementing a packer</summary>
|
||||
<p>While the intuitive way to understand the packing algorithm is via chunks and buckets, a far more efficient
|
||||
implementation can be made that uses three pointers. Rather than try to explain in words, hopefully this python
|
||||
implementation should suffice as explanation:
|
||||
<pre><code>class Packer:
|
||||
def __init__(self, offset=0):
|
||||
self._word_cursor = offset
|
||||
self._short_cursor = offset
|
||||
self._byte_cursor = offset
|
||||
self._boundary = offset % 4
|
||||
|
||||
def _next_block(self):
|
||||
self._word_cursor += 4
|
||||
return self._word_cursor - 4
|
||||
|
||||
def request_allocation(self, size):
|
||||
if size == 0:
|
||||
return self._word_cursor
|
||||
elif size == 1:
|
||||
if self._byte_cursor % 4 == self._boundary:
|
||||
self._byte_cursor = self._next_block() + 1
|
||||
else:
|
||||
self._byte_cursor += 1
|
||||
return self._byte_cursor - 1
|
||||
elif size == 2:
|
||||
if self._short_cursor % 4 == self._boundary:
|
||||
self._short_cursor = self._next_block() + 2
|
||||
else:
|
||||
self._short_cursor += 2
|
||||
return self._short_cursor - 2
|
||||
else:
|
||||
old_cursor = self._word_cursor
|
||||
for _ in range(math.ceil(size / 4)):
|
||||
self._word_cursor += 4
|
||||
return old_cursor
|
||||
|
||||
def notify_skipped(self, no_bytes):
|
||||
for _ in range(math.ceil(no_bytes / 4)):
|
||||
self.request_allocation(4)</code></pre>
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<a href="./transport.html">Prev page</a> | <a href="./protocol.html">Next page</a>
|
||||
{% endblock %}
|
13
templates/pages/proto/apsmanager.html
Normal file
13
templates/pages/proto/apsmanager.html
Normal file
@ -0,0 +1,13 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>apsmanager</code></h1>
|
||||
<h2 id="getstat"><code>apsmanager.getstat</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<apsmanager method="getstat" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<apsmanager status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
212
templates/pages/proto/cardmng.html
Normal file
212
templates/pages/proto/cardmng.html
Normal file
@ -0,0 +1,212 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>cardmng</code></h1>
|
||||
<p>As the name might imply, this service is responsible for handling interactions with physical e-Amusement cards.
|
||||
e-Amusement currently has two different types of cards in circulation. There are classic e-Amusement cards
|
||||
making use of a magnetic stripe, and the newer RFID cards using FeliCa (these are probably what you have). They
|
||||
are identified in requests using the <code>cardtype</code> attribute as in the below table.
|
||||
</p>
|
||||
<p>e-Amusement cards have a "card number" and a "card id". Confusingly, neither is a number. The card number is the
|
||||
one printed on your card. The card ID is your KONAMI ID. You can (and should) read about the algorithm used for
|
||||
these IDs on <a href="../cardid.html">the Card IDs page</a>.</p>
|
||||
<p>In the interest of not wasting space, <code>cardid</code> and <code>cardtype</code> will be omitted from
|
||||
individual breakdowns where their meaning is obvious.</p>
|
||||
|
||||
<h4>Card types:</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td><code>cardtype</code></td>
|
||||
<td>Meaning</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td><code>1</code></td>
|
||||
<td>Old style magnetic stripe card</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>2</code></td>
|
||||
<td>FeliCa RFID card</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<ul>
|
||||
<li><code><a href="#inquire">cardmng.inquire</a></code></li>
|
||||
<li><code><a href="#getrefid">cardmng.getrefid</a></code></li>
|
||||
<li><code><a href="#bindmodel">cardmng.bindmodel</a></code></li>
|
||||
<li><code><a href="#bindcard">cardmng.bindcard</a></code></li>
|
||||
<li><code><a href="#authpass">cardmng.authpass</a></code></li>
|
||||
<li><code><a href="#getkeepspan">cardmng.getkeepspan</a></code></li>
|
||||
<li><code><a href="#getkeepremain">cardmng.getkeepremain</a></code></li>
|
||||
<li><code><a href="#getdatalist">cardmng.getdatalist</a></code></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2 id="inquire"><code>cardmng.inquire</code></h2>
|
||||
<p>Request information about a card that has been inserted or touched against a reader.</p>
|
||||
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="inquire" cardid="" cardtype="" update="" model*="" />
|
||||
</call></code></pre>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>update</code></td>
|
||||
<td>Should the tracked last play time be updated by this inquiry? (Just a guess)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" refid="" dataid="" pcode="" newflag="" binded="" expired=" ecflag="" useridflag="" extidflag="" lastupdate="" />
|
||||
</response></code></pre>
|
||||
<p>To handle this request, we first must lookup if this <code>cardid</code> has ever been seen by our servers
|
||||
before. If not, we abort with a <code>112</code> status. Otherwise, we proceeed to check if this card has been
|
||||
seen for this specific game. If we have never seen this card used on this game, it is possible this card was
|
||||
used with an older version of this game, and migration is supported, in which case we report as if we had found
|
||||
a profile for this game.</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>refid</code></td>
|
||||
<td>A reference to this card to be used in other requests</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dataid</code></td>
|
||||
<td>Appears to be set the same as <code>refid</code>; presumably to allow different keys for game state vs
|
||||
login details.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>newflag</code></td>
|
||||
<td>Inverse of <code>binded</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>binded</code></td>
|
||||
<td>Has a profile ever been created for this game (or an older version, requiring a migration)
|
||||
(<code>1</code> or <code>0</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>expired</code></td>
|
||||
<td>? Just set to <code>0</code>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2 id="getrefid"><code>cardmng.getrefid</code></h2>
|
||||
<p>Register a new card to this server.</p>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="getrefid" cardtype="" cardid=" newflag="" passwd="" model*="" />
|
||||
</call></code></pre>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>newflag</code></td>
|
||||
<td>?</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>passwd</code></td>
|
||||
<td>The pin for this new user. <i>Should</i> always be a four digit number (and that's worth validating),
|
||||
but it's passed as a string so could feasibly be anything desired.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" refid="" dataid="" pcode="" />
|
||||
</response></code></pre>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>refid</code></td>
|
||||
<td>A reference to this card to be used in other requests</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dataid</code></td>
|
||||
<td>Appears to be set the same as <code>refid</code>; presumably to allow different keys for game state vs
|
||||
login details.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>pcode</code></td>
|
||||
<td>? Not present in captured data.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2 id="bindmodel"><code>cardmng.bindmodel</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="bindmodel" refid="" newflag="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" dataid="" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="bindcard"><code>cardmng.bindcard</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="bindcard" cardtype="" newid="" refid="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="authpass"><code>cardmng.authpass</code></h2>
|
||||
<p>Test a pin for a card. This request notably uses the <code>refid</code>, so required a
|
||||
<code>cardmng.inquire</code> call to be made first.
|
||||
</p>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="authpass" refid="" pass="" model*="" />
|
||||
</call></code></pre>
|
||||
<table>
|
||||
<tr>
|
||||
<td><code>refid</code></td>
|
||||
<td>The reference we received either during <code>cardmng.inquire</code> or <code>cardmng.getrefid</code>
|
||||
(the latter for new cards)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>pass</code></td>
|
||||
<td>The pin to test. See <code>cardmng.getrefid</code>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
<p>If the pin is valid, status should be <code>0</code>. Otherwise, <code>116</code>.</p>
|
||||
|
||||
<h2 id="getkeepspan"><code>cardmng.getkeepspan</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="getkeepspan" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" keepspan="" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="getkeepremain"><code>cardmng.getkeepremain</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="getkeepremain" refid="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>" keepremain="" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="getdatalist"><code>cardmng.getdatalist</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<cardmng method="getdatalist" refid="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<cardmng status="<i>status</i>">
|
||||
<item[]>
|
||||
<mcode __type="str" />
|
||||
<dataid __type="str" />
|
||||
<regtime __type="str" />
|
||||
<lasttime __type="str" />
|
||||
<exptime __type="str" />
|
||||
<expflag __type="u8" />
|
||||
</item[]>
|
||||
</cardmng>
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
34
templates/pages/proto/dlstatus.html
Normal file
34
templates/pages/proto/dlstatus.html
Normal file
@ -0,0 +1,34 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>dlstatus</code></h1>
|
||||
<h2 id="done"><code>dlstatus.done</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<dlstatus method="done">
|
||||
<url>
|
||||
<param __type="str" />
|
||||
</url>
|
||||
<name __type="str" />
|
||||
<size __type="s32" />
|
||||
</dlstatus>
|
||||
</call></code></pre>
|
||||
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<dlstatus status="<i>status</i>">
|
||||
<progress __type="s32" />
|
||||
</dlstatus>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="progress"><code>dlstatus.progress</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<dlstatus method="progress" />
|
||||
<progress __type="s32" />
|
||||
</dlstatus>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<dlstatus status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
@ -1,29 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>eacoin</code></h1>
|
||||
<h2 id="checkin"><code>eacoin.checkin</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>eacoin</code></h1>
|
||||
<h2 id="checkin"><code>eacoin.checkin</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="checkin">
|
||||
<cardtype __type="str" />
|
||||
<cardid __type="str" />
|
||||
@ -31,8 +11,8 @@
|
||||
<ectype __type="str" />
|
||||
</eacoin>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>">
|
||||
<sequence __type="s16" />
|
||||
<acstatus __type="u8" />
|
||||
@ -43,21 +23,21 @@
|
||||
</eacoin>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="checkout"><code>eacoin.checkout</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="checkout"><code>eacoin.checkout</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="checkout">
|
||||
<sessid __type="str" />
|
||||
</eacoin>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="consume"><code>eacoin.consume</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="consume"><code>eacoin.consume</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="consume" esid="">
|
||||
<sessid __type="str" />
|
||||
<sequence __type="s16" />
|
||||
@ -67,8 +47,8 @@
|
||||
<detail __type="str" />
|
||||
</eacoin>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>">
|
||||
<acstatus __type="u8" />
|
||||
<autocharge __type="u8" />
|
||||
@ -76,88 +56,88 @@
|
||||
</eacoin>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="getbalance"><code>eacoin.getbalance</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="getbalance"><code>eacoin.getbalance</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="getbalance">
|
||||
<sessid __type="str" />
|
||||
</eacoin>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>">
|
||||
<acstatus __type="u8" />
|
||||
<balance __type="s32" />
|
||||
</eacoin>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="getecstatus"><code>eacoin.getecstatus</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="getecstatus"><code>eacoin.getecstatus</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="getecstatus" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>">
|
||||
<ectype __type="str" />
|
||||
<ecstatus __type="u8" />
|
||||
</eacoin>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="touch"><code>eacoin.touch</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="touch"><code>eacoin.touch</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="touch">
|
||||
<sessid __type="str" />
|
||||
</eacoin>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="opchpass"><code>eacoin.opchpass</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="opchpass"><code>eacoin.opchpass</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="opchpass">
|
||||
<passwd __type="str" />
|
||||
<newpasswd __type="str" />
|
||||
</eacoin>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="opcheckin"><code>eacoin.opcheckin</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="opcheckin"><code>eacoin.opcheckin</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="opcheckin">
|
||||
<passwd __type="str" />
|
||||
</eacoin>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>">
|
||||
<sessid __type="str" />
|
||||
</eacoin>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="opcheckout"><code>eacoin.opcheckout</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="opcheckout"><code>eacoin.opcheckout</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="opcheckout">
|
||||
<sessid __type="str" />
|
||||
</eacoin>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="getlog"><code>eacoin.getlog</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="getlog"><code>eacoin.getlog</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eacoin method="getlog">
|
||||
<sessid __type="str" />
|
||||
<logtype __type="str" />
|
||||
@ -168,8 +148,8 @@
|
||||
<sesstype __type="str" />
|
||||
</eacoin>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eacoin status="<i>status</i>">
|
||||
<processing __type="u8" />
|
||||
<topic>
|
||||
@ -197,4 +177,4 @@
|
||||
</history>
|
||||
</eacoin>
|
||||
</response></code></pre>
|
||||
</body>
|
||||
{% endblock %}
|
17
templates/pages/proto/esign.html
Normal file
17
templates/pages/proto/esign.html
Normal file
@ -0,0 +1,17 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>esign</code></h1>
|
||||
<h2 id="request"><code>esign.request</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<esign method="request">
|
||||
<i>placeholder</i>
|
||||
</esign>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<esign status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</esign>
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
30
templates/pages/proto/esoc.html
Normal file
30
templates/pages/proto/esoc.html
Normal file
@ -0,0 +1,30 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>esoc</code></h1>
|
||||
<h2 id="read"><code>esoc.read</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<esoc method="read">
|
||||
<senddata />
|
||||
</esoc>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<esoc status="<i>status</i>">
|
||||
<recvdata />
|
||||
</esoc>
|
||||
</response></code></pre>
|
||||
<p>Go figure.</p>
|
||||
|
||||
<h2 id="write"><code>esoc.write</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<esoc method="write">
|
||||
<senddata />
|
||||
</esoc>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<esoc status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
38
templates/pages/proto/eventlog.html
Normal file
38
templates/pages/proto/eventlog.html
Normal file
@ -0,0 +1,38 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>eventlog</code></h1>
|
||||
<h2 id="write"><code>eventlog.write</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<eventlog method="write">
|
||||
<retrycnt __type="u32" />
|
||||
<data>
|
||||
<eventid __type="str" />
|
||||
<eventorder __type="s32" />
|
||||
<pcbtime __type="u64" />
|
||||
<gamesession __type="s64" />
|
||||
<strdata1 __type="str" />
|
||||
<strdata2 __type="str" />
|
||||
<numdata1 __type="s64" />
|
||||
<numdata2 __type="s64" />
|
||||
<locationid __type="str" />
|
||||
</data>
|
||||
</eventlog>
|
||||
</call></code></pre>
|
||||
<p>Event ID list:</p>
|
||||
<ul>
|
||||
<li><code>G_GAMED</code></li>
|
||||
<li><code>S_ERROR</code></li>
|
||||
<li><code>S_PWRON</code> <b>TODO: find more!</b></li>
|
||||
<li><code>T_OTDEMO</code></li>
|
||||
</ul>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<eventlog status="<i>status</i>">
|
||||
<gamesession __type="s64" />
|
||||
<logsendflg __type="s32" />
|
||||
<logerrlevel __type="s32" />
|
||||
<evtidnosendflg __type="s32" />
|
||||
</eventlog>
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
@ -1,33 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>facility</code></h1>
|
||||
<h2 id="get"><code>facility.get</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>facility</code></h1>
|
||||
<h2 id="get"><code>facility.get</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<facility method="get" privateip*="" encoding*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<facility expire=""\ status="<i>status</i>">
|
||||
<calendar*>
|
||||
<year __type="s16" />
|
||||
@ -83,58 +63,58 @@
|
||||
</share>
|
||||
</facility>
|
||||
</response></code></pre>
|
||||
<p><i>I'm not totally sure what type <code>share/eapass/valid</code> is meant to be, but it's optional, so I'd
|
||||
suggest just not bothering and leaving it out :).</i></p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Country</td>
|
||||
<td>Code</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<p><i>I'm not totally sure what type <code>share/eapass/valid</code> is meant to be, but it's optional, so I'd
|
||||
suggest just not bothering and leaving it out :).</i></p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Hong Kong</td>
|
||||
<td><code>HK</code></td>
|
||||
<td>Country</td>
|
||||
<td>Code</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Taiwan</td>
|
||||
<td><code>TW</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Korea</td>
|
||||
<td><code>KR</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>USA</td>
|
||||
<td><code>US</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Thailand</td>
|
||||
<td><code>TH</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Indonesia</td>
|
||||
<td><code>ID</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Singapore</td>
|
||||
<td><code>SG</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Phillipines</td>
|
||||
<td><code>PH</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Macao</td>
|
||||
<td><code>MO</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Japan</td>
|
||||
<td><code>JP</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p><code>globalip</code> (and associated ports) shold be the IP:port of the cabinet.</p>
|
||||
<p><code>region</code> is used for Japan, and has the value <code>JP-[prefecture]</code> where prefecture ranges
|
||||
from 1 through 47.</p>
|
||||
<p><b>TODO: Compile the list of regions</b></p>
|
||||
</body>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>Hong Kong</td>
|
||||
<td><code>HK</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Taiwan</td>
|
||||
<td><code>TW</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Korea</td>
|
||||
<td><code>KR</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>USA</td>
|
||||
<td><code>US</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Thailand</td>
|
||||
<td><code>TH</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Indonesia</td>
|
||||
<td><code>ID</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Singapore</td>
|
||||
<td><code>SG</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Phillipines</td>
|
||||
<td><code>PH</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Macao</td>
|
||||
<td><code>MO</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Japan</td>
|
||||
<td><code>JP</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p><code>globalip</code> (and associated ports) shold be the IP:port of the cabinet.</p>
|
||||
<p><code>region</code> is used for Japan, and has the value <code>JP-[prefecture]</code> where prefecture ranges
|
||||
from 1 through 47.</p>
|
||||
<p><b>TODO: Compile the list of regions</b></p>
|
||||
{% endblock %}
|
@ -1,387 +1,367 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="../..">Contents</a></td>
|
||||
<td><a href="../../transport.html">Transport layer</a></td>
|
||||
<td><a href="../../packet.html">Packet format</a></td>
|
||||
<td><a href="../../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1 id="game"><code>game</code></h1>
|
||||
<h2 id="sample"><code>game.sv4_sample</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1 id="game"><code>game</code></h1>
|
||||
<h2 id="sample"><code>game.sv4_sample</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_sample">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="new"><code>game.sv4_new</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="new"><code>game.sv4_new</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_new">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="load"><code>game.sv4_load</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="load"><code>game.sv4_load</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_load">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="load_m"><code>game.sv4_load_m</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="load_m"><code>game.sv4_load_m</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_load_m">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="save"><code>game.sv4_save</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="save"><code>game.sv4_save</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_save">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="save_m"><code>game.sv4_save_m</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="save_m"><code>game.sv4_save_m</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_save_m">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="common"><code>game.sv4_common</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="common"><code>game.sv4_common</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_common">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="shop"><code>game.sv4_shop</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="shop"><code>game.sv4_shop</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_shop">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="hiscore"><code>game.sv4_hiscore</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="hiscore"><code>game.sv4_hiscore</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_hiscore">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="buy"><code>game.sv4_buy</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="buy"><code>game.sv4_buy</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_buy">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="exception"><code>game.sv4_exception</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="exception"><code>game.sv4_exception</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_exception">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="entry_s"><code>game.sv4_entry_s</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="entry_s"><code>game.sv4_entry_s</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_entry_s">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="entry_e"><code>game.sv4_entry_e</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="entry_e"><code>game.sv4_entry_e</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_entry_e">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="frozen"><code>game.sv4_frozen</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="frozen"><code>game.sv4_frozen</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_frozen">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="lounce"><code>game.sv4_lounce</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_lounce">
|
||||
<h2 id="lounge"><code>game.sv4_lounge</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_lounge">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="save_e"><code>game.sv4_save_e</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="save_e"><code>game.sv4_save_e</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_save_e">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="save_pb"><code>game.sv4_save_pb</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="save_pb"><code>game.sv4_save_pb</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_save_pb">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="save_c"><code>game.sv4_save_c</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="save_c"><code>game.sv4_save_c</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_save_c">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="play_s"><code>game.sv4_play_s</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="play_s"><code>game.sv4_play_s</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_play_s">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="play_e"><code>game.sv4_play_e</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="play_e"><code>game.sv4_play_e</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_play_e">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="serial"><code>game.sv4_serial</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="serial"><code>game.sv4_serial</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_serial">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="save_fi"><code>game.sv4_save_fi</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="save_fi"><code>game.sv4_save_fi</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_save_fi">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="print"><code>game.sv4_print</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="print"><code>game.sv4_print</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_print">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="print_h"><code>game.sv4_print_h</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="print_h"><code>game.sv4_print_h</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_print_h">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="load_r"><code>game.sv4_load_r</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="load_r"><code>game.sv4_load_r</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_load_r">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="save_campaign"><code>game.sv4_save_campaign</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="save_campaign"><code>game.sv4_save_campaign</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<game method="sv4_save_campaign">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<game status="<i>status</i>">
|
||||
<i>placeholder</i>
|
||||
</game>
|
||||
</response></code></pre>
|
||||
</body>
|
||||
{% endblock %}
|
@ -1,29 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>matching</code></h1>
|
||||
<h2 id="request"><code>matching.request</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>matching</code></h1>
|
||||
<h2 id="request"><code>matching.request</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<matching method="request">
|
||||
<info>
|
||||
<version __type="s32" />
|
||||
@ -46,8 +26,8 @@
|
||||
</data>
|
||||
</matching>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<matching status="<i>status</i>">
|
||||
<hostid __type="s64" />
|
||||
<result __type="s32" />
|
||||
@ -58,9 +38,9 @@
|
||||
</matching>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="wait"><code>matching.wait</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="wait"><code>matching.wait</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<matching method="wait">
|
||||
<info>
|
||||
<version __type="s32" />
|
||||
@ -72,17 +52,17 @@
|
||||
</data>
|
||||
</matching>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<matching status="<i>status</i>">
|
||||
<result __type="s32" />
|
||||
<prwtime __type="s32" />
|
||||
</matching>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="finish"><code>matching.finish</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="finish"><code>matching.finish</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<matching method="finish">
|
||||
<info>
|
||||
<version __type="s32" />
|
||||
@ -94,10 +74,10 @@
|
||||
</data>
|
||||
</matching>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<matching status="<i>status</i>">
|
||||
<result __type="s32" />
|
||||
</matching>
|
||||
</response></code></pre>
|
||||
</body>
|
||||
{% endblock %}
|
15
templates/pages/proto/message.html
Normal file
15
templates/pages/proto/message.html
Normal file
@ -0,0 +1,15 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>message</code></h1>
|
||||
<h2 id="get"><code>message.get</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<message method="get" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<message expire="" status="<i>status</i>">
|
||||
<item[] name="" start="" end="" data="" />
|
||||
</message>
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
27
templates/pages/proto/package.html
Normal file
27
templates/pages/proto/package.html
Normal file
@ -0,0 +1,27 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>package</code></h1>
|
||||
<h2 id="list"><code>package.list</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<package method="list" pkgtype="<i>pkgtype</i>" model*="" />
|
||||
</call></code></pre>
|
||||
<p><code>all</code> is the only currently observed value for <code>pkgtype</code></p>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<package status="<i>status</i>">
|
||||
<item[] url="" />
|
||||
</package>
|
||||
</response></code></pre>
|
||||
<p>A list of all packages available for download.</p>
|
||||
|
||||
<h2 id="intend"><code>package.intend</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<package method="intend" url="" model*="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<package status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
21
templates/pages/proto/pcbevent.html
Normal file
21
templates/pages/proto/pcbevent.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>pcbevent</code></h1>
|
||||
<h2 id="put"><code>pcbevent.put</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<pcbevent method="put">
|
||||
<time __type="time" />
|
||||
<seq __type="u32" />
|
||||
<item[]>
|
||||
<name __type="str" />
|
||||
<value __type="s32" />
|
||||
<time __type="time" />
|
||||
</item[]>
|
||||
</pcbevent>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<pcbevent status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
19
templates/pages/proto/pcbtracker.html
Normal file
19
templates/pages/proto/pcbtracker.html
Normal file
@ -0,0 +1,19 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>pcbtracker</code></h1>
|
||||
<h2 id="alive"><code>pcbtracker.alive</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<pcbtracker method="alive" model*="" hardid="" softid="" accountid="" agree="" ecflag="" />
|
||||
</call></code></pre>
|
||||
<p><code>ecflag</code> here is determining if the arcade operator allows the use of paseli on this machine.</p>
|
||||
<p><code>agree@</code> and <code>ecflag@</code> appear to either be totally non present, or present with a value of
|
||||
<code>"1"</code>, but then again I may be reading the code wrong, so take that with a pinch of salt.
|
||||
</p>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<pcbtracker status="" time="" limit="" ecenable="" eclimit="" >
|
||||
</response></code></pre>
|
||||
<p>As you might guess, <code>ecenable@</code> is therefore the flag to determine if paseli is enabled (i.e. the
|
||||
arcade operator and the server both allow its use).</p>
|
||||
{% endblock %}
|
@ -1,29 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>playerdata</code></h1>
|
||||
<h2 id="usergamedata_send"><code>playerdata.usergamedata_send</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>playerdata</code></h1>
|
||||
<h2 id="usergamedata_send"><code>playerdata.usergamedata_send</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<playerdata method="usergamedata_send">
|
||||
<retrycnt __type="u32" />
|
||||
<info>
|
||||
@ -40,16 +20,16 @@
|
||||
</data>
|
||||
</playerdata>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<playerdata status="<i>status</i>">
|
||||
<result __type="s32" />
|
||||
</playerdata>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="usergamedata_recv"><code>playerdata.usergamedata_recv</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="usergamedata_recv"><code>playerdata.usergamedata_recv</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<playerdata method="usergamedata_recv">
|
||||
<info>
|
||||
<version __type="u32" />
|
||||
@ -62,7 +42,7 @@
|
||||
</data>
|
||||
</playerdata>
|
||||
</call></code></pre>
|
||||
<pre><code><call <i>...</i>>
|
||||
<pre><code><call <i>...</i>>
|
||||
<playerdata method="usergamedata_recv">
|
||||
<data>
|
||||
<refid __type="str">
|
||||
@ -72,8 +52,8 @@
|
||||
</data>
|
||||
</playerdata>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<playerdata status="<i>status</i>">
|
||||
<player>
|
||||
<result>
|
||||
@ -88,12 +68,12 @@
|
||||
</playerdata>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="usergamedata_inheritance"><code>playerdata.usergamedata_inheritance</code></h2>
|
||||
<p>See: <code>playerdata.usergamedata_recv</code></p>
|
||||
<h2 id="usergamedata_inheritance"><code>playerdata.usergamedata_inheritance</code></h2>
|
||||
<p>See: <code>playerdata.usergamedata_recv</code></p>
|
||||
|
||||
<h2 id="usergamedata_condrecv"><code>playerdata.usergamedata_condrecv</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="usergamedata_condrecv"><code>playerdata.usergamedata_condrecv</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<playerdata method="usergamedata_condrecv">
|
||||
<info>
|
||||
<version __type="s32" />
|
||||
@ -112,8 +92,8 @@
|
||||
</info>
|
||||
</playerdata>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<playerdata status="<i>status</i>">
|
||||
<player>
|
||||
<result __type="s32" />
|
||||
@ -127,9 +107,9 @@
|
||||
</playerdata>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="usergamedata_scorerank"><code>playerdata.usergamedata_scorerank</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="usergamedata_scorerank"><code>playerdata.usergamedata_scorerank</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<playerdata method="usergamedata_scorerank">
|
||||
<info>
|
||||
<version __type="s32" />
|
||||
@ -143,8 +123,8 @@
|
||||
</data>
|
||||
</playerdata>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<playerdata status="<i>status</i>">
|
||||
<rank>
|
||||
<result __type="s32" />
|
||||
@ -153,4 +133,4 @@
|
||||
</rank>
|
||||
</playerdata>
|
||||
</response></code></pre>
|
||||
</body>
|
||||
{% endblock %}
|
50
templates/pages/proto/services.html
Normal file
50
templates/pages/proto/services.html
Normal file
@ -0,0 +1,50 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>services</code></h1>
|
||||
<h2 id="get"><code>services.get</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<services method="get" model*="" >
|
||||
<info>
|
||||
<AVS2 __type="str"><i>AVS2 version</i></AVS2>
|
||||
</info>
|
||||
</services>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<services expire="" method="get" mode="" status="<i>status</i>">
|
||||
<item[] name="<i>service</i>" url="<i>url</i>" />
|
||||
</services>
|
||||
</response></code></pre>
|
||||
<p>Known services are:</p>
|
||||
<ul>
|
||||
<li><code>ntp</code></li>
|
||||
<li><code>keepalive</code></li>
|
||||
<li><code>cardmng</code></li>
|
||||
<li><code>facility</code></li>
|
||||
<li><code>message</code></li>
|
||||
<li><code>numbering</code></li>
|
||||
<li><code>package</code></li>
|
||||
<li><code>pcbevent</code></li>
|
||||
<li><code>pcbtracker</code></li>
|
||||
<li><code>pkglist</code></li>
|
||||
<li><code>posevent</code></li>
|
||||
<li><code>userdata</code></li>
|
||||
<li><code>userid</code></li>
|
||||
<li><code>eacoin</code></li>
|
||||
<li><code>local</code></li>
|
||||
<li><code>local2</code></li>
|
||||
<li><code>lobby</code></li>
|
||||
<li><code>lobby2</code></li>
|
||||
<li><code>dlstatus</code></li>
|
||||
<li><code>netlog</code></li>
|
||||
<li><code>sidmgr</code></li>
|
||||
<li><code>globby</code></li>
|
||||
</ul>
|
||||
<p>Most of these will usually just return the URL to the eAmuse server (or your fake one ;D). <code>ntp</code> is a
|
||||
notable exception, unless you're planning on reimplementing NTP. <code>keepalive</code> will likely alsop be a
|
||||
custom URL with query parameters pre-baked.</p>
|
||||
<p><code>mode</code> is one of <code>operation</code>, <code>debug</code>, <code>test</code>, or
|
||||
<code>factory</code>.
|
||||
</p>
|
||||
{% endblock %}
|
74
templates/pages/proto/sidmgr.html
Normal file
74
templates/pages/proto/sidmgr.html
Normal file
@ -0,0 +1,74 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>sidmgr</code></h1>
|
||||
<h2 id="create"><code>sidmgr.create</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="create">
|
||||
<cardtype __type="str" />
|
||||
<cardid __type="str" />
|
||||
<cardgid __type="str" />
|
||||
<steal __type="u8" />
|
||||
</sidmgr>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>">
|
||||
<state __type="u32" />
|
||||
<e_count __type="u8" />
|
||||
<last __type="time" />
|
||||
<locked __type="time" />
|
||||
<sid __type="str" />
|
||||
<cardid_status __type="u8" />
|
||||
<refid __type="str" />
|
||||
</sidmgr>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="open"><code>sidmgr.open</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="open" sid="" >
|
||||
<pass __type="str" />
|
||||
</sidmgr>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>">
|
||||
<state __type="u32" />
|
||||
<refid __type="str" />
|
||||
<locked __type="time" />
|
||||
</sidmgr>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="touch"><code>sidmgr.touch</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="touch" sid="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="branch"><code>sidmgr.branch</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="branch" sid="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="close"><code>sidmgr.close</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<sidmgr method="close" sid="" />
|
||||
<cause __type="u32" />
|
||||
</sidmgr>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<sidmgr status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
@ -1,29 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>e-Amusement API</title>
|
||||
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="..">Contents</a></td>
|
||||
<td><a href="../transport.html">Transport layer</a></td>
|
||||
<td><a href="../packet.html">Packet format</a></td>
|
||||
<td><a href="../protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1><code>system</code></h1>
|
||||
<h2 id="getmaster"><code>system.getmaster</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>system</code></h1>
|
||||
<h2 id="getmaster"><code>system.getmaster</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<system method="getmaster">
|
||||
<data>
|
||||
<gamekind __type="str" />
|
||||
@ -32,8 +12,8 @@
|
||||
</data>
|
||||
</system>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<system status="<i>status</i>">
|
||||
<result __type="s32" />
|
||||
<strdata1 __type="str" />
|
||||
@ -42,9 +22,9 @@
|
||||
</system>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="getlocationiplist"><code>system.getlocationiplist</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="getlocationiplist"><code>system.getlocationiplist</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<system method="getlocationiplist">
|
||||
<data>
|
||||
<locationid __type="str" />
|
||||
@ -52,8 +32,8 @@
|
||||
</data>
|
||||
</system>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<system status="<i>status</i>">
|
||||
<result __type="s32" />
|
||||
<iplist>
|
||||
@ -65,9 +45,9 @@
|
||||
</system>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="xrpcproxy"><code>system.xrpcproxy</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="xrpcproxy"><code>system.xrpcproxy</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<system method="xrpcproxy">
|
||||
<info>
|
||||
<version __type="s32" />
|
||||
@ -79,8 +59,8 @@
|
||||
</data>
|
||||
</system>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<system status="<i>status</i>">
|
||||
<result __type="s32" />
|
||||
<pwrtime __type="s32" />
|
||||
@ -101,9 +81,9 @@
|
||||
</system>
|
||||
</response></code></pre>
|
||||
|
||||
<h2 id="convcardnumber"><code>system.convcardnumber</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<h2 id="convcardnumber"><code>system.convcardnumber</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<system method="convcardnumber">
|
||||
<info>
|
||||
<version __type="s32" />
|
||||
@ -114,8 +94,8 @@
|
||||
</data>
|
||||
</system>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<system status="<i>status</i>">
|
||||
<result __type="s32" />
|
||||
<data>
|
||||
@ -123,4 +103,4 @@
|
||||
</data>
|
||||
</system>
|
||||
</response></code></pre>
|
||||
</body>
|
||||
{% endblock %}
|
20
templates/pages/proto/traceroute.html
Normal file
20
templates/pages/proto/traceroute.html
Normal file
@ -0,0 +1,20 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>traceroute</code></h1>
|
||||
<h2 id="send"><code>traceroute.send</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<traceroute proto="" method="send">
|
||||
<hop[]>
|
||||
<valid __type="bool">
|
||||
<addr __type="ip4">
|
||||
<usec __type="u64">
|
||||
</hop[]>
|
||||
</traceroute>
|
||||
</call></code></pre>
|
||||
<p><code>hop</code> repeats for every hop (unsurprisingly)</p>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<traceroute status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
28
templates/pages/proto/userdata.html
Normal file
28
templates/pages/proto/userdata.html
Normal file
@ -0,0 +1,28 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1><code>userdata</code></h1>
|
||||
<h2 id="read"><code>userdata.read</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<userdata method="read" card*="" model*="" label="" />
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<userdata status="<i>status</i>" time="">
|
||||
<b[] __type="" />
|
||||
</userdata>
|
||||
</response></code></pre>
|
||||
<p><code>__type</code> here can be either <code>bin</code> or <code>str</code></p>
|
||||
|
||||
<h2 id="write"><code>userdata.write</code></h2>
|
||||
<h3>Request:</h3>
|
||||
<pre><code><call <i>...</i>>
|
||||
<userdata method="write" card="" time="" model*="" label*="" >
|
||||
<b[] __type="str" />
|
||||
</userdata>
|
||||
</call></code></pre>
|
||||
<h3>Response:</h3>
|
||||
<pre><code><response>
|
||||
<userdata status="<i>status</i>" />
|
||||
</response></code></pre>
|
||||
{% endblock %}
|
263
templates/pages/protocol.html
Normal file
263
templates/pages/protocol.html
Normal file
@ -0,0 +1,263 @@
|
||||
{% extends "base.html" %}
|
||||
{% 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>,
|
||||
with its body being encoded data as described in the previous sections. In addition to the
|
||||
<code>X-Compress:</code> and <code>X-Eamuse-Info:</code> headers previously detailed, there is also a
|
||||
<code>X-PCB-ID:</code> header. that can be set. Your machine's PCB ID uniquely defines the physical board. This
|
||||
header is added in out-bound requests, and allows the server to identify you. Importantly, it's also the value
|
||||
that the server uses to identify which machines are authorized to be on the network, and which are not.
|
||||
</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>
|
||||
<pre><code><call model="<i>model</i>" srcid="<i>srcid</i>" tag="<i>tag</i>">
|
||||
<<i>module</i> method="<i>method</i>" <i>...attributes</i>>
|
||||
<i>children</i>
|
||||
</<i>module</i>>
|
||||
</call></code></pre>
|
||||
<p>The responses follow a similar format:</p>
|
||||
<pre><code><response>
|
||||
<<i>module</i> status="<i>status</i>" <i>...attributes</i>>
|
||||
<i>children</i>
|
||||
</<i>module</i>>
|
||||
</response></code></pre>
|
||||
<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.
|
||||
These are namespaces under the <code>game.%s</code> module and, in the case of SDVX 4, are all
|
||||
<code>game.sv4_<i>method</i></code>. I may or may not document the SDVX 4 specific methods, but I've listed them
|
||||
here anyway for completeness.
|
||||
</p>
|
||||
<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>
|
||||
|
||||
<h2>Possible XRPC requests</h2>
|
||||
|
||||
<ul>
|
||||
<li><code><a href="proto/eventlog.html">eventlog.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/eventlog.html#eventlog.write">eventlog.write</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/playerdata.html">playerdata.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_send">playerdata.usergamedata_send</a></code></li>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_recv">playerdata.usergamedata_recv</a></code></li>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_inheritance">playerdata.usergamedata_inheritance</a></code>
|
||||
</li>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_condrecv">playerdata.usergamedata_condrecv</a></code>
|
||||
</li>
|
||||
<li><code><a href="proto/playerdata.html#usergamedata_scorerank">playerdata.usergamedata_scorerank</a></code>
|
||||
</li>
|
||||
</ul>
|
||||
<li><code><a href="proto/matching.html">matching.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/matching.html#request">matching.request</a></code></li>
|
||||
<li><code><a href="proto/matching.html#wait">matching.wait</a></code></li>
|
||||
<li><code><a href="proto/matching.html#finish">matching.finish</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/system.html">system.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/system.html#getmaster">system.getmaster</a></code></li>
|
||||
<li><code><a href="proto/system.html#getlocationiplist">system.getlocationiplist</a></code></li>
|
||||
<li><code><a href="proto/system.html#xrpcproxy">system.xrpcproxy</a></code></li>
|
||||
<li><code><a href="proto/system.html#convcardnumber">system.convcardnumber</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/esoc.html">esoc.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/esoc.html#read">esoc.read</a></code></li>
|
||||
<li><code><a href="proto/esoc.html#write">esoc.write</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/cardmng.html">cardmng.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/cardmng.html#inquire">cardmng.inquire</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#getrefid">cardmng.getrefid</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#bindmodel">cardmng.bindmodel</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#bindcard">cardmng.bindcard</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#authpass">cardmng.authpass</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#getkeepspan">cardmng.getkeepspan</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#getkeepremain">cardmng.getkeepremain</a></code></li>
|
||||
<li><code><a href="proto/cardmng.html#getdatalist">cardmng.getdatalist</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/esign.html">esign.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/esign.html#request">esign.request</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/package.html">package.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/package.html#list">package.list</a></code></li>
|
||||
<li><code><a href="proto/package.html#intend">package.intend</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/userdata.html">userdata.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/userdata.html#read">userdata.read</a></code></li>
|
||||
<li><code><a href="proto/userdata.html#write">userdata.write</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/services.html">services.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/services.html#get">services.get</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/pcbtracker.html">pcbtracker.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/pcbtracker.html#alive">pcbtracker.alive</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/pcbevent.html">pcbevent.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/pcbevent.html#put">pcbevent.put</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/message.html">message.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/message.html#get">message.get</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/facility.html">facility.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/facility.html#get">facility.get</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/apsmanager.html">apsmanager.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/apsmanager.html#getstat">apsmanager.getstat</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/sidmgr.html">sidmgr.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/sidmgr.html#create">sidmgr.create</a></code></li>
|
||||
<li><code><a href="proto/sidmgr.html#open">sidmgr.open</a></code></li>
|
||||
<li><code><a href="proto/sidmgr.html#touch">sidmgr.touch</a></code></li>
|
||||
<li><code><a href="proto/sidmgr.html#branch">sidmgr.branch</a></code></li>
|
||||
<li><code><a href="proto/sidmgr.html#close">sidmgr.close</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/dlstatus.html">dlstatus.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/dlstatus.html#done">dlstatus.done</a></code></li>
|
||||
<li><code><a href="proto/dlstatus.html#progress">dlstatus.progress</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/eacoin.html">eacoin.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/eacoin.html#checkin">eacoin.checkin</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#checkout">eacoin.checkout</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#consume">eacoin.consume</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#getbalance">eacoin.getbalance</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#getecstatus">eacoin.getecstatus</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#touch">eacoin.touch</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#opchpass">eacoin.opchpass</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#opcheckin">eacoin.opcheckin</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#opcheckout">eacoin.opcheckout</a></code></li>
|
||||
<li><code><a href="proto/eacoin.html#getlog">eacoin.getlog</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/traceroute.html">traceroute.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/traceroute.html#send">traceroute.send</a></code></li>
|
||||
</ul>
|
||||
<li><code><a href="proto/game/sv4.html">game.%s</a></code></li>
|
||||
<ul>
|
||||
<li><code><a href="proto/game/sv4.html#sample">game.sv4_sample</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#new">game.sv4_new</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#load">game.sv4_load</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#load_m">game.sv4_load_m</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save">game.sv4_save</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_m">game.sv4_save_m</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#common">game.sv4_common</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#shop">game.sv4_shop</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#hiscore">game.sv4_hiscore</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#buy">game.sv4_buy</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#exception">game.sv4_exception</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#entry_s">game.sv4_entry_s</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#entry_e">game.sv4_entry_e</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#frozen">game.sv4_frozen</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#lounge">game.sv4_lounge</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_e">game.sv4_save_e</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_pb">game.sv4_save_pb</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_c">game.sv4_save_c</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#play_s">game.sv4_play_s</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#play_e">game.sv4_play_e</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#serial">game.sv4_serial</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_fi">game.sv4_save_fi</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#print">game.sv4_print</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#print_h">game.sv4_print_h</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#load_r">game.sv4_load_r</a></code></li>
|
||||
<li><code><a href="proto/game/sv4.html#save_campaign">game.sv4_save_campaign</a></code></li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<b>Totally undocumented services (based on <code>services.get</code>):</b>
|
||||
<ul>
|
||||
<li><code>numbering</code></li>
|
||||
<li><code>pkglist</code></li>
|
||||
<li><code>userid</code></li>
|
||||
<li><code>local</code></li>
|
||||
<li><code>local2</code></li>
|
||||
<li><code>lobby</code></li>
|
||||
<li><code>lobby2</code></li>
|
||||
<li><code>netlog</code></li>
|
||||
<li><code>globby</code></li>
|
||||
</ul>
|
||||
<p>I'll try and figure these out in due course, promise!</p>
|
||||
{% endblock %}
|
52
templates/pages/transport.html
Normal file
52
templates/pages/transport.html
Normal file
@ -0,0 +1,52 @@
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h1>Network format</h1>
|
||||
|
||||
<p>eAmuse packets are sent and received over HTTP (no S), with requests being in the body of <code>POST</code> requests,
|
||||
and replies being in the, well, reply.</p>
|
||||
<p>The packets are typically both encrypted and compressed. The compression format used is indicated by the
|
||||
<code>X-Compress</code> header, and valid values are
|
||||
</p>
|
||||
<ul>
|
||||
<li><code>none</code></li>
|
||||
<li><code>lz77</code></li>
|
||||
</ul>
|
||||
<details>
|
||||
<summary>Source code details</summary>
|
||||
<figure>
|
||||
<img src="./images/lz77.png">
|
||||
<figcaption><code>libavs-win32-ea3.dll:0x1000fa29</code></figcaption>
|
||||
</figure>
|
||||
</details>
|
||||
<p>Encryption is performed <b>after</b> compression, and uses RC4. RC4 is symmetric, so decryption is performed the same
|
||||
as encryption. That is, <code>packet = encrypt(compress(data))</code> and
|
||||
<code>data = decompress(decrypt(data))</code>.
|
||||
</p>
|
||||
|
||||
<h2 id="keys">Encryption keys</h2>
|
||||
<p>Encryption is not performed using a single static key. Instead, each request and response has its own key that is
|
||||
generated.</p>
|
||||
<p>These keys are generated baesd on the <code>X-Eamuse-Info</code> header.</p>
|
||||
<p>This header loosely follows the format <code>1-[0-9a-f]{8}-[0-9a-f]{4}</code>. This corresponds to
|
||||
<code>[version]-[serial]-[salt]</code>. <b>TODO: Confirm this</b>
|
||||
</p>
|
||||
<p>Our per-packet key is then generated using <code>md5(serial | salt | KEY)</code>. Identifying <code>KEY</code> is
|
||||
left as an exercise for the reader, however should not be especially challenging. <span style="color: #fff">Check
|
||||
the page source if you're stuck.</span></p>
|
||||
<!-- It's 69d74627d985ee2187161570d08d93b12455035b6df0d8205df5, if you were wondering. libavs-win32-ea3.dll:0x10054160 -->
|
||||
|
||||
<h2 id="lz77">LZ77</h2>
|
||||
<p>Packets are compressed using lzss. The compressed data structure is a repeating cycle of an 8 bit flags byte,
|
||||
followed by 8 values. Each value is either a single literal byte, if the corresponding bit in the preceeding flag is
|
||||
high, or is a two byte lookup into the window.</p>
|
||||
<p>The lookup bytes are structured as <code>pppppppp ppppllll</code> where <code>p</code> is a 12 bit index in the
|
||||
window, and <code>l</code> is a 4 bit integer that determines how many times to repeat the value located at that
|
||||
index in the window.</p>
|
||||
|
||||
<p>The exact algorithm used for compression is not especially important, as long as it follows this format. One can
|
||||
feasibly perform no compression at all, and instead insert <code>0xFF</code> every 8 bytes (starting at index 0), to
|
||||
indicate that all values are literals. While obviously poor for compression, this is an easy way to test without
|
||||
first implementing a compressor.</p>
|
||||
|
||||
<a href="./index.html">Prev page</a> | <a href="./packet.html">Next page</a>
|
||||
{% endblock %}
|
@ -1,54 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Transport | eAmuse API</title>
|
||||
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href=".">Contents</a></td>
|
||||
<td><a href="./transport.html">Transport layer</a></td>
|
||||
<td><a href="./packet.html">Packet format</a></td>
|
||||
<td><a href="./protocol.html">Application Protocol</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>Network format</h1>
|
||||
|
||||
<p>eAmuse packets are sent and received over HTTP (no S), with requests being in the body of <code>POST</code> requests, and replies being in the, well, reply.</p>
|
||||
<p>The packets are typically both encrypted and compressed. The compression format used is indicated by the <code>X-Compress</code> header, and valid values are</p>
|
||||
<ul>
|
||||
<li><code>none</code></li>
|
||||
<li><code>lz77</code></li>
|
||||
</ul>
|
||||
<details>
|
||||
<summary>Source code details</summary>
|
||||
<figure>
|
||||
<img src="./images/lz77.png">
|
||||
<figcaption><code>libavs-win32-ea3.dll:0x1000fa29</code></figcaption>
|
||||
</figure>
|
||||
</details>
|
||||
<p>Encryption is performed <b>after</b> compression, and uses RC4. RC4 is symmetric, so decryption is performed the same as encryption. That is, <code>packet = encrypt(compress(data))</code> and <code>data = decompress(decrypt(data))</code>.</p>
|
||||
|
||||
<h2 id="keys">Encryption keys</h2>
|
||||
<p>Encryption is not performed using a single static key. Instead, each request and response has its own key that is generated.</p>
|
||||
<p>These keys are generated baesd on the <code>X-Eamuse-Info</code> header.</p>
|
||||
<p>This header loosely follows the format <code>1-[0-9a-f]{8}-[0-9a-f]{4}</code>. This corresponds to <code>[version]-[serial]-[salt]</code>. <b>TODO: Confirm this</b></p>
|
||||
<p>Our per-packet key is then generated using <code>md5(serial | salt | KEY)</code>. Identifying <code>KEY</code> is left as an exercise for the reader, however should not be especially challenging. <span style="color: #fff">Check the page source if you're stuck.</span></p>
|
||||
<!-- It's 69d74627d985ee2187161570d08d93b12455035b6df0d8205df5, if you were wondering. libavs-win32-ea3.dll:0x10054160 -->
|
||||
|
||||
<h2 id="lz77">LZ77</h2>
|
||||
<p>Packets are compressed using lzss. The compressed data structure is a repeating cycle of an 8 bit flags byte, followed by 8 values. Each value is either a single literal byte, if the corresponding bit in the preceeding flag is high, or is a two byte lookup into the window.</p>
|
||||
<p>The lookup bytes are structured as <code>pppppppp ppppllll</code> where <code>p</code> is a 12 bit index in the window, and <code>l</code> is a 4 bit integer that determines how many times to repeat the value located at that index in the window.</p>
|
||||
|
||||
<p>The exact algorithm used for compression is not especially important, as long as it follows this format. One can feasibly perform no compression at all, and instead insert <code>0xFF</code> every 8 bytes (starting at index 0), to indicate that all values are literals. While obviously poor for compression, this is an easy way to test without first implementing a compressor.</p>
|
||||
|
||||
<a href="./index.html">Prev page</a> | <a href="./packet.html">Next page</a>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user