Comio stuff

This commit is contained in:
Bottersnike 2022-04-24 23:35:53 +01:00
parent 0d264daf1f
commit 4544d8e2d2
6 changed files with 480 additions and 6 deletions

29
docs.py
View File

@ -1,3 +1,4 @@
from dataclasses import dataclass
import datetime
import re
import os
@ -19,7 +20,7 @@ TOC_HTAG_LEVELS = {"1", "2"}
HOST = "https://bsnk.me"
TEMPLATES = "templates"
PAGES_BASE = "pages"
STATIC = ["images"]
STATIC = ["images", "static"]
ROOT = os.environ.get("EA_ROOT", "")
@ -42,6 +43,7 @@ SEGA_CONTENTS = {
"intro.html": ("Introduction to RingEdge 2", ()),
"hardware": ("Hardware", ()),
"software": ("Software", {
"jvs.html": "JVS",
"drivers": ("Device drivers", {
"columba.html": "columba",
"mxsram.html": "mxsram",
@ -51,16 +53,15 @@ SEGA_CONTENTS = {
"mxparallel.html": "mxparallel",
"mxsmbus.html": "mxsmbus",
}),
"jvs.html": "JVS",
"security": ("Security", {
"game.html": "Game encryption",
"dongle.html": "Dongles",
"keychip.html": "Keychips",
})
}),
}),
"network": ("Networking", {
"allnet.html": "ALL.Net"
})
}),
}
CONTENTS = {
"": EAMUSE_CONTENTS,
@ -68,6 +69,25 @@ CONTENTS = {
}
@dataclass
class Part:
id: str
name: str
description: str = None
page: str = None
PARTS = {
"838-14971": Part("838-14971", "Aime NFC daughter board", "NFC RW BD TN32MSEC003S")
}
def part(id):
if (part := PARTS.get(id)):
return f'<span class="part" tabindex="0">{part.name}<span><span>Part number</span><span>{part.id}</span><span>Description</span><span>{part.description}</span></span></span>'
return f'<span class="part">{id}</span>'
def generate_xrpc_list():
output = "<ul>"
proto = TEMPLATES + "/" + PAGES_BASE + "/proto"
@ -270,6 +290,7 @@ for base, _, files in os.walk(TEMPLATES + "/" + PAGES_BASE):
generate_xrpc_list=generate_xrpc_list,
generate_toc=lambda start=1: generate_toc(base, name, route, start),
generate_footer=lambda: generate_footer(base, name, route),
part=part,
)
return handler

BIN
static/JVST_VER3.pdf Normal file

Binary file not shown.

BIN
static/jvs_wip.pdf Normal file

Binary file not shown.

View File

@ -174,6 +174,55 @@ footer>*:last-child {
}
.part {
text-decoration: underline dotted;
text-underline-offset: 2px;
position: relative;
display: inline;
cursor: help;
}
.part span {
display: block;
}
.part>span {
display: none;
position: absolute;
left: 0;
width: 100%;
top: 100%;
margin: 4px;
border: 1px solid currentColor;
padding: 8px;
background-color: inherit;
}
.part>span>span:nth-child(2n - 1) {
font-weight: 600;
}
.part>span>span:nth-child(2n) {
margin-left: 1rem;
}
.part:hover>span, .part:focus>span, .part>span:hover {
display: block;
}
figure>figcaption:first-child {
margin-bottom: 8px;
}
mark {
background-color: unset;
color: unset;
font-family: monospace;
font-size: 1.2em;
text-decoration: underline;
text-underline-offset: 1px;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #000;
@ -189,7 +238,7 @@ footer>*:last-child {
}
code {
background-color: #150a0d;
background-color: #221115;
}
.highlight, img:not(.graphic) {
@ -209,6 +258,7 @@ footer>*:last-child {
background: #1c0d11;
border-color: #3b2b2f;
}
details code {
background: #000;
}

View File

@ -0,0 +1,292 @@
{% extends "sega.html" %}
{% block title %}JVS{% endblock %}
{% block body %}
<h1>JAMMA Video Standard - Alternative version</h1>
<p><b>Note:</b> This page assumes you have read the documentation regarding <a href="./jvs.html">the JAMMA video
standard</a>. If you have not, it is recommended to read that first.</p>
<h2 id="frame">Packet framing</h2>
<figure>
<figcaption>Request packet (master->slave)</figcaption>
<table>
<tr>
<td>E0<sub>h</sub></td>
<td>n</td>
<td>Dest</td>
<td>Seq</td>
<td><mark>CMD</mark></td>
<td><mark>D</mark><sub>0</sub></td>
<td><mark>D</mark><sub>1</sub></td>
<td><mark>D</mark><sub>2</sub></td>
<td>...</td>
<td><mark>D</mark><sub>n-5</sub></td>
<td><mark>SUM</mark></td>
</tr>
</table>
</figure>
<figure>
<figcaption>Response packet (slave->master)</figcaption>
<table>
<tr>
<td>E0<sub>h</sub></td>
<td><mark>n</mark></td>
<td>Src</td>
<td>Seq</td>
<td>Status</td>
<td><mark>CMD</mark></td>
<td>Report</td>
<td><mark>D</mark><sub>0</sub></td>
<td><mark>D</mark><sub>1</sub></td>
<td><mark>D</mark><sub>2</sub></td>
<td>...</td>
<td><mark>D</mark><sub>n-7</sub></td>
<td><mark>SUM</mark></td>
</tr>
</table>
</figure>
<h2 id="body">Commands and responses</h2>
<p>Response packets of this format include a source address, which should match the destination in the request. The
sequence number of both the request and response should be the same (? todo: verify this), and should be modulo 32
(20<sub>h</sub>).</p>
<p>While the packet format would suggest it supports multiple commands, I have never observed more than a single command
per packet. Response packets include the command number between their packet status and report status bytes.
</p>
<h2 id="commands">Individual commands</h2>
<p>The following is a reference table for communication with an {{ part("838-14971")|safe }}. Endpoints required for
MIFARE cards are marked with <mark>M</mark>, FeliCa <mark>F</mark>, and LEDs <mark>L</mark>.</p>
<table style="width: 100%">
<thead>
<tr>
<td>Req</td>
<td>Name</td>
<td>Code</td>
<td>Description</td>
<td>Request Size</td>
<td>Response Size</td>
</tr>
</thead>
<tbody>
<tr>
<td><mark>MF</mark></td>
<td>Get Firmware Version</td>
<td><code>30</code></td>
<td>Retrive the firmware version string</td>
<td>0</td>
<td>1+</td>
</tr>
<tr>
<td><mark>MF</mark></td>
<td>Get Hardware Version</td>
<td><code>32</code></td>
<td>Retrive the hardware version string</td>
<td>0</td>
<td>1+</td>
</tr>
<tr>
<td><mark>MF</mark></td>
<td>Radio On</td>
<td><code>40</code></td>
<td>Enable the NFC radio</td>
<td>2</td>
<td>0</td>
</tr>
<tr>
<td><mark>MF</mark></td>
<td>Radio Off</td>
<td><code>41</code></td>
<td>Disable the NFC radio</td>
<td></td>
<td>0</td>
</tr>
<tr>
<td><mark>MF</mark></td>
<td>Poll</td>
<td><code>42</code></td>
<td>Retreive a list of NFC devices</td>
<td>0</td>
<td>3+</td>
</tr>
<tr>
<td><mark>M</mark></td>
<td>Select MIFARE tag</td>
<td><code>43</code></td>
<td></td>
<td>1+</td>
<td>0</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>44</code></td>
<td></td>
<td>1+</td>
<td></td>
</tr>
<tr>
<td><mark>MF</mark></td>
<td>Set MIFARE Classic key</td>
<td><code>50</code></td>
<td>Provide the key used for MIFARE decryption</td>
<td>1+</td>
<td>0</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>51</code></td>
<td></td>
<td>1+</td>
<td></td>
</tr>
<tr>
<td><mark>M</mark></td>
<td>Read MIFARE block</td>
<td><code>52</code></td>
<td>Read a secified block from a MIFARE Classic device</td>
<td></td>
<td></td>
</tr>
<tr>
<td><mark>MF</mark></td>
<td>Set Aime key??</td>
<td><code>54</code></td>
<td>/shrug</td>
<td>1+</td>
<td>0</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>55</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>60</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>61</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><mark>MFL</mark></td>
<td>Reset</td>
<td><code>62</code></td>
<td>Reset the device to an initial state</td>
<td></td>
<td>0</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>70</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><mark>F</mark></td>
<td>FeliCa communication</td>
<td><code>72</code></td>
<td>Proxy the enframed command to a present FeliCa device</td>
<td>Variable</td>
<td>Variable</td>
</tr>
<tr>
<td colspan="6">LED commands (address <code>08</code>)</td>
</tr>
<tr>
<td><mark>L</mark></td>
<td>Reset</td>
<td><code>10</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>Set timeout</td>
<td><code>11</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>Set timeout response</td>
<td><code>14</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><mark>L</mark></td>
<td>Set LED colour</td>
<td><code>82</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>Set LED count</td>
<td><code>86</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><mark>L</mark></td>
<td>Get board info</td>
<td><code>f0</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>Get board status</td>
<td><code>f1</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>Get firmware sum</td>
<td><code>f2</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>Get protocol version</td>
<td><code>f3</code></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>Bootloader</td>
<td><code>fd</code></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
{% endblock %}

View File

@ -1,4 +1,115 @@
{% extends "sega.html" %}
{% block title %}{% endblock %}
{% block title %}JVS{% endblock %}
{% block body %}
<h1>JAMMA Video Standard</h1>
<a href="{{ROOT}}/static/JVST_VER3.pdf">A copy of the JVS standard can be found here</a>. The astute reader may observe
it is in Japanese. A rather excelent translation can be <a href="http://daifukkat.su/files/jvs_wip.pdf">found here</a>.
<p>JVS is a communication standard designed for I/O devices in arcade macines. It typically operates over RS485 serial,
however the framing format can and sometimes is used outside of this context.</p>
<p>This page documents the canonical JVS structure. Some devices, notably the {{ part("838-14971")|safe }}, use a slight
variant on the format. <a href="./comio.html">The differences between the two formats are document here</a>.
</p>
<h2>Escaping</h2>
<p>Every packet sent begins with the <mark>SYNC</mark> byte, <code>0xe0</code>. Read buffers should be continually
flushed until this
byte is observed.</p>
<p>As such, <code>0xe0</code> is reserved, and is escaped. A byte is escaped using <mark>MARK</mark>, <code>0xd0</code>,
followed by
the byte's value subtract one. While any byte can be escaped, the only two that require escaping are
<mark>SYNC</mark> and <mark>MARK</mark>, escaped as <code>D0 DF</code> and <code>D0 CF</code> respectively. All
operations on packets, such as checksums and length calculation, are performed on the <b>unescaped</b> packet.
</p>
<h2 id="frame">Packet framing</h2>
<figure>
<figcaption>Request packet (master->slave)</figcaption>
<table>
<tr>
<td>E0<sub>h</sub></td>
<td>Dest</td>
<td>n</td>
<td><mark>D</mark><sub>0</sub></td>
<td><mark>D</mark><sub>1</sub></td>
<td><mark>D</mark><sub>2</sub></td>
<td>...</td>
<td><mark>D</mark><sub>n-2</sub></td>
<td><mark>SUM</mark></td>
</tr>
</table>
</figure>
<figure>
<figcaption>Response packet (slave->master)</figcaption>
<table>
<tr>
<td>E0<sub>h</sub></td>
<td>Dest</td>
<td><mark>n</mark></td>
<td>Status</td>
<td><mark>D</mark><sub>0</sub></td>
<td><mark>D</mark><sub>1</sub></td>
<td><mark>D</mark><sub>2</sub></td>
<td>...</td>
<td><mark>D</mark><sub>n-3</sub></td>
<td><mark>SUM</mark></td>
</tr>
</table>
</figure>
<p><mark>SUM</mark> is calculated by summing all bytes in the packet, excluding <mark>SYNC</mark> and <mark>SUM</mark>
itself. <code>n</code> indicates the number of bytes succeeding itself. Due to the existance of the checksum,
<code>n=0</code> is nonsensical.
</p>
<h2 id="body">Commands and responses</h2>
<p>A request packet may contain multiple commands within it. <code>D<sub>0</sub></code> always contains the first
command. It is followed by <code>m</code> bytes of data, typically a constant number per command but not always (see
the command reference), at which point either we have consumed <code>n-1</code> bytes and the next byte is
<mark>SUM</mark>, or the next byte is another command and we repeat.
</p>
<table>
<tr>
<td><mark>CMD</mark><sub>0</sub></td>
<td><mark>D</mark><sub>0,0</sub></td>
<td><mark>D</mark><sub>0,1</sub></td>
<td>...</td>
<td><mark>CMD</mark><sub>1</sub></td>
<td><mark>D</mark><sub>1,0</sub></td>
<td><mark>D</mark><sub>1,1</sub></td>
<td>...</td>
<td><mark>CMD</mark><sub>2</sub></td>
<td><mark>D</mark><sub>2,0</sub></td>
<td><mark>D</mark><sub>2,1</sub></td>
<td>...</td>
<td><mark>SUM</mark></td>
</tr>
</table>
<p>Response packets are structured similarly, however the <mark>CMD</mark> byte is not present, instead relying on the
response to be ordered exactly the same as the request. The data of each command is preceeded by a report code,
indicating that individual command's status. The below diagram also includes the entire-packet status byte too for
clarity.</p>
<table>
<tr>
<td>Status</td>
<td>Report<sub>0</sub></td>
<td><mark>D</mark><sub>0,0</sub></td>
<td><mark>D</mark><sub>0,1</sub></td>
<td>...</td>
<td>Report<sub>1</sub></td>
<td><mark>D</mark><sub>1,0</sub></td>
<td><mark>D</mark><sub>1,1</sub></td>
<td>...</td>
<td>Report<sub>2</sub></td>
<td><mark>D</mark><sub>2,0</sub></td>
<td><mark>D</mark><sub>2,1</sub></td>
<td>...</td>
<td><mark>SUM</mark></td>
</tr>
</table>
<h2 id="commands">Individual commands</h2>
<p>I may document these at some point in the future, but honestly the <a
href="http://daifukkat.su/files/jvs_wip.pdf">translated reference</a> linked at the top of this page does a
great job.</p>
{% endblock %}