I wrote a replacement API for the OUYA gaming console because the original one had been shut down, making useless bricks out of the OUYAs in your living rooms.
If you just want to get the discover store running on your OUYA, have a look at the instructions.
OUYA?
At the beginning of 2014 I bought the android-based OUYA gaming console to have a device in the living room that I could use to play old Super Nintendo games on. The console did not use Google Play to install games with, but had its own "Discover" store that was hosted by OUYA itself.
In 2015, Razer bought OUYA to fill its own Cortex store with the 1200+ games that were available for the OUYA already. At that time they said:
If you already own the hardware, we're going to be keeping the lights on for at least a year.
In may 2019, Razer sent an e-mail to all registered users and developers:
From: Razer <no.reply@razer.com> Subject: OUYA & Razer Forge TV Services Shutdown Date: Wed, 22 May 2019 04:07:17 +0000 Reply-To: no.reply@razer.comDear Developer,
We would like to inform you that the Forge TV Games store and OUYA service will cease operations on 6-25-2019
This email serves as notice of termination of the Marketplace Agreement, in accordance with section 9 of the agreement, with effect on 5-25-2019.
Thank you for the support which you have extended us these past years. It has been a privilege to have worked with you and to have had you as part of our community.
- Razer
FAQ: https://support.razer.com/console/razer-forge-tv/
Server shutdown
With the OUYA server not available anymore, the OUYA cannot be used anymore:
- If you buy a used OUYA, or did a factory reset, you're stuck at the startup screen at which you have to login or register with the server.
- You cannot install any of the games, because the "Discover" store is gone.
- Games you have already bought are back into demo mode because the server does not confirm that you really bought them.
A group of people formed that were determined to preserve what OUYA had, and they coordinated in the OUYA Saviors Discord chat server. I decided to let them do their work and went on with my life.
In november I went back to see what they managed to do and found... not much. No working replacement server software, only the "work in progress" BrewyaOnOuya store that let your OUYA login.
With a heavy heart I stepped in and did it myself.
Games!
To build a game store, I needed a list of games and their meta data like title, description, categorization/genres, images and download links. There was no such game data repository :/
Game data schema
My plan was to have a git repsitory with one file for each game that contains all data about it, including an .apk download link. This game data repository could then be used to fill the store.
At first I analyzed the API: The list of games ("discover") contained title, genres and an image, but not the description. The detail page API had the description and .apk file information, but the website. The app data API had the website, the "like count" and the video URL that were missing in the other API responses.
In the end of the first day I had a big HTML table that listed every data point a game could have.
On day two I build the schema for the data files, and manually added the first game - Bloo Kid 2.
On day 3 I found that "apps" and "details" were not the same, and that my API backup did not have "apps" data. I got a "apps" data backup from Devin Rich (@szeraax) and integrated their fields into my schema.
The next two days were filled with doing refinements to the schema, and at the end of day 5 my store API generation script was good enough so that I could use the OUYA to register, browse the store, look at game details and download and install a game!
All the games
Now I had the proof that the game data schema was usable for an actual store, and I began to build a script that created the game data files from the API backups I had, and from the games that Jason Scott put into the Internet Archive.
During that work I found that the app uuid was not an UUID for the application itself but for the release. Also, details responses allowed videos and images in custom order, which I had not seen yet. That and some other observations required schema adjustments.
Another big issue were the images and videos. The API backup files contained image URLs to cloudfront.net, filepicker.io and amazonaws.com. The amazon bucket was still available, but the other two were down already. Some games in the Internet Archive had copies of those images; they had the same file name as they had on cloudfront. I had backed up some others, and got another large backup from @blackcharcz in chat.
In the end, only 419 of the 20159 images could not be recovered. The images are currently hosted on ouya.cweiske.de/game-images/, and I asked Jason Scott to import them into the Internet Archive. The whole import process took a bit under two weeks of work.
You can find the OUYA game meta data in a git repository: ouya-saviors/ouya-game-data.
Server
I laid the basis for the server already in 2013 when I built an image store that converted the discover section to an image browser, and in 2015 when I documented the OUYA server API.
A normal API server would need to manage users and allow registration, support uploads of new games and updates to existing games. It would need to track user downloads, purchases and maybe even the Push to OUYA feature.
To have all of that, a programming language and a database would be required, which means constant maintenance and adjustments when the Python or PHP version gets updated. Another big issue is security - if someone finds a bug in the code, the libraries, the framework or the interpreter they could be able to break in and do bad things with the server.
I did not want to have any of those issues and thus had decided very early that I would build a script that creates a couple of static files, which would be served by a web server without any dynamics in it.
Limitations of static
My server's user registration API responds with "OK", but does not even look at the data the user sends to it. The "login" API route returns static data: A hard-coded session ID, and a static name "stouyapi". Every user is the same.
The "agreements" API does not track which marketplace terms you have already read and confirmed, it only says that you already did :) If the OUYA sends a crash report, the server says "ok" but does not look at the data.
Game rating submissions are ignored as well; the number of votes and average rating is taken from the static game data files and will never change. The server also does not track which user messages you have read or not.
PUT
It turned out that it is impossible to let Apache 2.4 return static responses to PUT requests - it needs a scripting language for that.
Apache's own content handler returns "405 Method not allowed" if it gets a HTTP PUT request, even if there is a rewrite rule that says "return 200 OK". So I had to resort to providing an empty-json.php PHP script that has to be registered as PUT handler in the Apache configuration:
Script PUT /empty-json.php
Without it, the OUYA will forever try to submit the user's public key and the marketplace agreement status.
Categorization
The "hard" part was creating the "Discover" menu because I could not remember how the original thing looked like. In the meantime @szeraax had implemented game data import and a first discover section in his BrewyaOnOuya store, and I took some ideas from there:
- A row of "last updated" games
- A row of "best rated" games
- My own favorites, "cweiske's picks"
- Categories with games for "2 players", "3 players" and "4 players"
- Games grouped by content rating: Everyone, 9+, 12+ and 17+
- Categories for all the original genres
- A category for each letter
Each category begins with a "last updated" and a "best rated" row, and then lists 4 games per row. That way you scroll vertically instead of the horizontal scrolling in the original OUYA store, but it gives you the chance to really see all of the games.
Using the server
When the OUYA saviors chat server was launched, a former OUYA employee joined and gave us some information that helped us very much.
One of those important bits of information was that there was a ini-style config file that the OUYA developers used when they programmed: The configuration file ouya_config.properties. Just connect to the OUYA via USB, and create a plain text file with that name in the auto-mounted root folder.
Setting the options OUYA_SERVER_URL and OUYA_STATUS_SERVER_URL will immediately change the server that the OUYA uses, and lets us point our OUYAs to the new server in the easiest way imaginable.
Success
My stouyapi store went live on november 22, 3 weeks after I began to work on the project. The first gamers are using it already.
stouyapi's source code is on my git server (github mirror). I use the ouya-game-data repository to build it.
The next big task is getting all the now unpurchasable games into a fully playable state...
Screenshots
Also on: Twitter, ouya.world.