From 2da6e2b05621cc68b909bcc452da5ceaf3e0b739 Mon Sep 17 00:00:00 2001
From: Bottersnike
Contents | -Transport layer | -Packet format | -Application Protocol | -
Why?
-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).
-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 httac
and xrpc
. 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.
These pages are very much a work in progress, and are being written as 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).
-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.
-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.
- -Across these pages there are a number of code snippets. They roughly break down into three categories:
-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?).
- -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.
-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.).
-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).
-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. -
- - Next page - -This site intentionally looks not-great. I don't feel like changing that, and honestly quite like the - aesthetic.
-\ No newline at end of file +{% endblock %} \ No newline at end of file diff --git a/docs.py b/docs.py new file mode 100644 index 0000000..421a970 --- /dev/null +++ b/docs.py @@ -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) \ No newline at end of file diff --git a/freeze.py b/freeze.py new file mode 100644 index 0000000..9ccb94b --- /dev/null +++ b/freeze.py @@ -0,0 +1,7 @@ +from flask_frozen import Freezer +from docs import app + +freezer = Freezer(app) + +if __name__ == '__main__': + freezer.freeze() \ No newline at end of file diff --git a/index.html b/index.html deleted file mode 100644 index f120af7..0000000 --- a/index.html +++ /dev/null @@ -1,106 +0,0 @@ - - - -
- - - -
- - - - -
- -