Christians Tagebuch: gamestick

The latest posts in full-text for feed readers.


GameStick: Purchases implemented

The PlayJam GameStick community server software got another feature: Purchases. You are now able to buy games (instead of having all of them available for free) and in-game products like levels and powerups.

Your wallet has an infinite amount of money, so you don't risk going broke :)

Purchasing games

All games - even already installed ones - have to be bought now. After buying, the game download starts automatically.

The purchase dialog is a web view, displaying a HTML page delivered by the server. I had no idea how it looked like - there were no screenshots to find with my Google-Fu. In the end I found a video of Lee Chapman demoing the Gamestick, and near the end he buys Riptide.

I took screenshots, resized and warped them until they had the correct aspect ratio and size. Then I re-built the layout in HTML and CSS that a 2013 browser understands.

There was no documentation about the purchase requests and responses. The requests were easy to document since I could see them in the server logs, but the responses were hard: Some of them are handled in the Java library, while others are passed to the Marmalade UI and parsed there. The important things like "success, download now" were of course in the compiled C code, and I was forced to use Ghidra to make a bit sense of it.

The magic words are:

{
    "body": {
        "success": true,
        "message": null,
        "action": "CLOSEPAYMENT"
    }
}

Purchasing a game

Implementing purchases fixed a long-standing bug: The "uninstalled apps" view in the settings crashed, probably the Marmalade interface was never meant to handle 188 games. Now only the purchased games are listed there - without crashing.

Uninstalled apps

In-game products

A number of games have in-game products: "Top Gear: Stunt School" allows to buy nuts, dollars and permits. In "Pacman Tournaments" you can buy tokens (3500 for 99.99USD!), "Rise of Glory" lets you spend money on airplane packs and in Prince of Persia you can buy coins (1000 for 1.99, 100000 for 99.99$).

Of course we did not have backups and I had to decompile the game apk files to find the product IDs that they used. Products had to be registered at the server, and the game only asks the server which products are available.

More often than not, decompiling did not work because the game was made with Unity or some other engine, and I miss the tools to unpack those files. In this cases I let the server return all products ids from 1 to 1000, with prices from 0.01€ to 10.00€, and could immediately see which products were used. This did of course only work on some games; others crashed when they received more than 15 products.

OUYA games were much easier in this regard: They send all supported product keys to the server, making it a breeze to quickly add products for unsupported games. Although, easier only after I broke their DRM :)

At one point I was finished and had only find products for the last game, Repulze. Then I saw that - instead of sending integer number product IDs, just as all other games do - this game sends string keys like com.pixelbite.repulze.iap.toolkit_pack1! I had to modify the database, parts of the purchase API and the game data schema to support that :(

But now this feature is really complete, and you can purchase things in the following games:

  • Falling Bird
  • Pac Man Tournaments (does not work; needs defunct Namco server)
  • MIMPI
  • Prince of Persia
  • Repulze
  • Top Gear: Stunt School Revolution
  • Sky Gamblers: Rise of Glory

Start buying in-game product Confirm Purchase successful

Game archival status

In 2024-09 we had 163 of 188 games archived. Thanks to GameStick fans Kazdan, Krzysiu, Ryo and TheMartinMess22 we have 170 now, a whopping 90.4%!

Newly rescued games:

  • Canabalt HD (Kittehface Software)
  • Dead Rushing (Dancing Cat Development)
  • Finger Hoola+ (Plantpot)
  • Sci-Fighters (Headup Games)
  • ShaqDown (One Spear)
  • Spacecat (Platty Soft)
  • Wasteland Bar Fight (Kybernesis)

Also on: Mastodon, Twitter.

Published on 2025-06-25 in


PlayJam GameStick timeline

A collection of links regarding the history of the PlayJam GameStick microconsole.

Short version
Age Date Event
2013-01-02 Kickstarter funding campaign started
1 month 2013-02-01 Kickstarter funding campaign ended, 5691 supporters, 647.658$
10 months 2013-10-24 First Review at golem.de
11 months 2013-11-20 German backers receive Gamesticks: GameStick ist da!
1y 5m 2014-05-08 Last firmware update 0.9.2071
1y 5m 2014-05-31 Kickstarter docks were shipped
1y 8m 2014-08-15 Inventory sell-off begins: GameStick for 19.99$
3 years 2016-01-05 PlayJam says GameStick will be running in the forseeable future
3y 2m 2016-03-09 Last Facebook post by PlayJam
4 years 2017-01-09 Official server shutdown

Detailed timeline

Date Category Event
2012-12-10 PlayJam First PlayJam tweet: We are live with our pre-launch campaign. Follow us! Visit http://GameStick.tv or like us on http://facebook.com/GameStickNews
2013-01-02 Kickstarter Kickstarter funding campaign started
2013-01-03 Kickstarter Update #1: GameStick Day 1 - Wow.
2013-01-09 Kickstarter Update #4: 320.000$ reached: Stretch Goals Announced!
2013-01-11 Kickstarter Update #6: Stretch goal 1 reached: Stretch #1 Reached!
2013-01-18 Kickstarter Update #8: 400.000$ reached: You spoke and we listened..
2013-01-30 Kickstarter Update #13: Miracast support: Working with Miracast
2013-02-01 Kickstarter Kickstarter funding campaign ended, 5691 supporters, 647.658$: Wow! What a result! Incredible! Blown Away!
2013-03-19 Kickstarter Update #17: Developer unit in production: Dev Kits, Partnerships and Further Updates
2013-04-19 Kickstarter Update #23: GameStick DEV kit Unboxing Video
2013-05-27 Kickstarter Update #29: GameStick Features on the BBC.
2013-06-13 Kickstarter Update #34: Companion app: Demo showing PlayJam's Companion App working the GameStick UI
2013-10-23 Kickstarter Update #45: Shipping stalled: Shipping update.
2013-10-24 Review Golem.de: Playjams Gamestick im Test: Die Android-Konsole für zwischendurch
2013-10-30 Review Eurogamer: GameStick review: Stick it.
2013-11-05 Review Techradar: PlayJam GameStick review: The latest Android console doesn't get the formula right
2013-11-07 Kickstarter Update #46: Sticks are shipping, Dock shipping delayed: Update - Feedback.
2013-11-11 Review Engadget: GameStick review: Android console gaming still awaits its king
2013-11-11 Store 45 games available: Engadget review
2013-11-15 Store Over 50 games available: GameStick: Aktuelle Spieleliste
2013-11-20 Kickstarter Germans backers receive Gamesticks: GameStick ist da! Die Verpackung…
2013-12-04 GameStick Firmware update 0.9.2049: (source)
2013-12-12 GameStick Firmware update 0.9.2049 report: GameStick Software-Update 0.9.2049
2014-01-19 Store 68 games available (source)
2014-02-03 GameStick Firmware update 0.9.2058: (source)
2014-02-06 Kickstarter E-Mail: Docks are still not shipping: Dear Backers, Let me start by apologizing for the lack of news and or updates on the GameStick project over recent months - in particular on the status of the docks.[...]
2014-04-04 Kickstarter Last Kickstarter page update #47: Dock situation: Update. (archived copy)
2014-05-01 Store 84 games available (source)
2014-05-08 GameStick Firmware update 0.9.2071 (source)
2014-05-21 Kickstarter E-Mail to Backers: Dock will be shipped next week Update: GameStick Dock
2014-05-30 Store 90 games available (source)
2014-05-31 Kickstarter TopFree got its kickstarter dock: GameStick Dock im Praxistest
2014-07-12 Review Telegraph PlayJam article, 35000 units at GameStop: Get ready for TV gaming to move up a gear
2014-08-15 Sell-off Price at GameStop: GameStick 19.99$ (source)
2014-08-21 Sell-off Price at GameStop: Dock 15$ (source)
2014-09-01 Sell-off Price at GameStop.com: GameStick 19.99$ (GameStick für $19.99, source 2)
2014-09-18 Sell-off PlayJam sells off inventory on ebay Gamestick Sell off?
2014-09-23 GameStick Custom Firmware CFW 1.4 (source)
2014-12-05 Sell-off Price in GameStop store: GameStick 17$, Dock 5$ (source)
2015-01-05 Sell-off Price at Gamestop: Controller 9$ (source)
2015-10-20 PlayJam GameStick website redirects to flareplay.com, only zone.gamestick.tv still available: Neue PlayJam-Konsole FlarePlay und kostenlose AGameAWeek Collection für GameStick
2015-11-23 PlayJam Playjam Titan prototype device sent to shanti: PlayJam Titan, (Gen 2 Gamestick?)
2016-01-05 PlayJam PlayJam says GameStick will be running in the forseeable future: Tweet
2016-02-26 PlayJam Last Tweet by @PlayJam
2016-03-09 PlayJam Last Facebook post by PlayJam
2016-05-15 Store 177 games available (source)
2016-10-09 Store Game download not possible since months: GameStick ist „tot“
2017-01-09 PlayJam Server shutdown (taken from topfree screenshot)
2017-01-11 Store Topfree blog post about server shutdown with screenshot of Gamestick homepage: GameStick: Das offizielle Ende
2017-01-12 Store 177 games available (source)
2017-11-09 Store Shutdown: "Store closed earlier this year": Comment: No - they closed the store earlier in the year. As far as I know you can't download anything from the GameStick servers any more.

Published on 2025-04-11 in


GameStick: Remove melted rubber coating

2013 PlayJam GameStick devices have a all-around rubber coating, and the controllers have a rubberized bottom. After 11 years, the coating's chemicals dissolved, leaving a sticky mess that sticks to your fingers when touching it.

GameStick controller with sticky bottom

It is possible to get rid of the coating by rubbing it off with Isopropanol (Isopropyl alcohol), an old sock and a pair of surgical gloves.

Cleaned controller

The rubber coating was mentioned in the 2013-07-11 Kickstarter Update #36: The Golden Sample:

  • Put a rubberized coating on the bottom of the controller. This gives the finish a really nice quality feel.
  • Used a rubber coating on the GameStick so that it did not scratch when inserted in to the controller. It really looks and feels fantastic as a result.

Also on: Mastodon, Twitter

Published on 2024-12-31 in ,


GameStick Companion app skins

The PlayJam GameStick had native support for using mobile phones as game controllers via its Companion app. Youtube still has a the official demo video showing it' usage.

When starting the app, it would show the GameStick and you could connect to it. Then the GameStick would deliver a branded controller skin to the app, which then displayed a custom controller interface for the game (or the standard one if the game had no own).

While looking through the files of a GameStick backup, I found some of the cached files in the /data/com.playjam.ca.service/files/ directory: .bundle and .meta files. The .bundle files are just Zip archives that contain an XML configuration file, background, button and stick images.

I took the time and built some little scripts to convert the XML configuration file via XSLT into a SVG image, and a script to embed the bitmap image files into the svg file. They can be found in the companion-app repository on Codeberg.

Game controller images

System default

Evac Final Freeway 2R Fishy Rush Kosmik Revenge MAGNETOID HD - Robo Runner Metaloid Reactor Guardian Oddy Smog's Misadventure Quantic Pinball Raiden Legacy Riptide Shadowgun Ski Safari Slingshot racing Smash Cops Stalagflight Stop the Birds Tales of Illyria 1

Also on: Mastodon, Twitter.

Published on 2024-12-15 in


GameStick server delivers firmware updates

My PlayJam GameStick replacement server is now able to deliver firmware updates to the GameSticks: Version 2049 to 2058, and 2058 to 2071.

Firmware images

The GameStick server was shut down in 2017, long before we tried to preserve the system. We thus could not download firmware images from the server, but GameStick Fans member Ryo found the firmware files for 2058 and 2071 somewhere on the internet and collected them for us.

Joe, a new GameStick Fan who joined in 2024-11, found the firmware image for 2049 on his stick.

Those full firmware images are ~180 MiB large and fully reset your GameStick - all settings and games are wiped. They can't be used for automatic updates.

Firmware updates

After I manged to build a firmware update that enables the Android debug bridge, Ryo found an official firmware update on one of his GameSticks in 2023: Update-2058-to-2071.img. It was located in the /cache/ folder and only 3.2 MiB large.

Another stick contained Update-2049-to-2058.img (9.9 MiB).

Those .img files are small downloads and keep all the settings and games as they are - the right ones for automatic updates.

Firmware update process

The initial request to check for firmware updates is pretty standard: A HTTP POST request to http://update.gamestickservices.net/check.php (actually 2 different domains and one hard-coded IP address), which returns a JSON structure that tells the stick if a firmware update is available, the textual changelog and if the stick must install it ("forced update") - and of course the download URL.

By reading the decompiled OOBE code, I figured out that the download URL gets modified and URL parameters are appended:

  • &i=-2 - return the total size of the download
  • &i=-1 - return the number of chunks
  • &i=0, &i=1 etc. - download the firmware parts

The firmware update is split into parts (chunks) of 100 kiB, and each chunk is "encrypted" by XORing it with the magic number 0x5b, and the binary SHA1 sum is put before the data itself.

My guess is that the developers did that to prevent people installing their own updates - a measure that was already defied in 2014-03, known as the lukepanic hack method. That hack supposedly (I don't have the files) opens a web server and delivers a custom firmware update :)

Server implementation

My server now contains a script that takes a firmware update, splits it into chunks, encrypts and signs them - so that the download files can be delivered statically.

All firmware images and updates known to us have been uploaded to the Internet Archive: 0.9.2049, 0.9.2059 and 0.9.2071.

Next we'd really like to have a developer firmware, and also know that there was a 0.9.2079 version we do not possess yet. Let's hope we'll find more sticks with cached firmware files on them.

Screenshots

Console UI update process

Firmware update notification Update 0.9.2058 is downloading Download finished Update is installing Android is upgrading Firmware is up to date! .. or not :) Update now to 0.9.2071 Update boot screen Now really up to date

OOBE update process

Searching for updates during setup Downloading 2058 update Update downloaded Firmware is up to date

Also on: Mastodon, Twitter.

Published on 2024-12-03 in


GameStick server improvements

I've been continuing work on the Playjam GameStick replacement server and managed to implement two features: Achievements and leaderboards.

Achievements

Achievements are things you reached in a game, e.g. jumping onto 3 enemies without touching the ground in Bloo Kid 1, a "Triple hit".

Whenever a player unlocks an achievement, the game sends that information to the server - a simple set-complete API call with the ID of the achievement and the session ID of the user. The server then has to store it in a database, and return it when requested.

Achievements can be requested in several locations:

  • The GameStick's main user interface lets you look at a list of all games you have achievements for.
  • The achievement overview lets you inspect all achievements for each game in detail.
  • Games fetch the list of achievements when they start, and want the information if the user has unlocked them already. This is helpful when you have multiple GameSticks and want to continue where you left off on the other stick.

GameStick UI: profile GameStick UI: Games with achievements GameStick UI: Game achievement details

Each of those locations had its own API call. Implementing the first and the last were easy, but the per-game achievement overview in the GameStick UI was pretty hard - the JSON structure was not parsed by the low-level GameStick database interface, but was handed off unparsed to the Marmalade-based UI, which parsed it and then crashed.

Guessing the property name for the achievement list yielded no results. Since the Marmalade SDk compiled code into C, it is pretty hard to decompile.

Fortunately, I found a Ghidra plugin for Marmalade, and after fixing a bug I could load the Console.s3e file into Ghidra. After some looking I found the property name for the achievement list: gameList.

Ghidra: Console.s3e analysis

All achievements were unfortunately registered at the server, and we have no backups of them. This means the games have to be decompiled and inspected to find out which achievements exists, what their title and description is. The achievements on the server also had images, which are lost forever.

Currently the game metadata repository has achievement information for Bloo Kid, Boulder Dash, Prince of Persia and ShaqDown.

Achievements in Bloo Kid Achievements in Prince of Persia

Leaderboards

Unlike the OUYA, the GameStick had native support for high score lists (but only one per game).

After implementing achievements, leaderboards were quickly done - the only API calls required for all games I know are saving the current score, and fetching the top 50 scores.

A couple of games provide high score lists: FallingBird, FourColorTaxi, GridLock, Magnetoid and Prince of Persia.

Stop the birds unfortunately fails to show the leaderboard for yet unknown reasons.

Leaderboard: 4 color taxi Leaderboard: Falling bird Leaderboard: Gridlock Leaderboard: Magnetoid Leaderboard: Prince of Persia

Also on: Mastodon, Twitter.

Published on 2024-10-30 in


86.7% of all GameStick games archived

This week the GameStick Fans community reached a milestone: Of the 188 games that were once available for the PlayJam GameStick, 163 have been archived and only 25 remain missing. That's 86.7%; a huge success for the project that started in 2024-04.

Playjam GameStick user interface

Obtaining apks

The lack of a GameStick community meant that nobody had backed up the available games before PlayJam announced the micro console's death in 2017.

After collecting cache files from GameSticks, 37 games could be downloaded from their AWS S3 URLs without authentication.

Another way to get the games is to contact the developers, but we had only limited success in getting answers to our e-mails, let alone .apk that the developers often did not have anymore.

Extracting installed games from existing GameSticks was the third option to get the game .apk files into our hands. It took a while and quite some effort until we were able to copy files off GameSticks - the devices were locked down and allowed neither file access nor sideloading.

The following people helped by copying games off their GameSticks or contacting developers to get .apks directly from them:

  • Alex Shorts
  • Andyweli
  • cweiske
  • eyehorus (Wayne)
  • jrronimo
  • Kazdan R. Azahn (KRAZ Pro.)
  • Lee Chapman
  • Ryo
  • Toast (Liam)

Missing games

We do not yet have the .apk files for the following GameStick games:

# Game name Developer
1Animalz: Super SquadInvaderGames
2Baa Baa BomberRatJar Games
3Beast Boxing TurboGoodHustle
4Canabalt HDKittehface Software
5CR FootySacred Duck Games
6Crumble ZoneRebel Twins
7CUBISTICPytebyte
8Dead RushingDancing Cat Development
9Dr. Bulbaceous Puzzle SolverWetgenes
10EDGEMobigame
11Finger Hoola+Plantpot
12Furfur and NubloDevilishGames
13Fuz RushJet Stone Studios
14Groundskeeper 2OrangePixel
15Nimble QuestNimblebit
16OrborunTiny Lab Productions
17Pix'N Love RushAdvanced Mobile Applications
18REDKnife Media
19Sci-FightersHeadup Games
20ShaqDownOne Spear
21SpaceCatPlatty Soft
22Space GruntsOrangePixel
23Space Vermin GameDisciples
24Usagi YojimboHappy Giant
25Wasteland Bar FightKybernesis

If you have a GameStick with one or more of this games - follow the apk rescue instructions, or ask for help in chat.

Archived games

The following games have been backed up and archived in the GameStick library at the Internet Archive.

Recent gameplay videos can be found on Wayne’s Gaming Den "PlayJam GameStick" playlist

Game name Developer
100 RoguesFusion Reactions
4-Color TaxiShadowBrain Games
Alien SpindomeAGameAWeek
Alpha CollexionAGameAWeek
Alpha WaveHardline Studios
Animal BattleOvogame
Animal Math Games for KidsEggroll Games
AquaVentureJellyfish Games
Asteroid 2012M-Spacemedia
Back to BedBedtime Digital Games
Battlebow - Shoot the Demons HDHaybyte Studios
Beasts BattleBadim
Beat DriftLunarPixelGames
Beta CollexionAGameAWeek
BionflytheOmenbit
BlastTraxAGameAWeek
Blockman Gets HungryAGameAWeek
Blockman WorldsAGameAWeek
Bloo Kidwinterworks GmbH
Boson XIan Mclarty
Boulder Dash - The FULL CollectionFirst Star Software
BounceABallAGameAWeek
BoxsplodingsAGameAWeek
Brave WarriorsGeorgeGames
Catcha Catcha AliensHotsauce Interactive
ChuckABallAGameAWeek
codestormPOLYGAMe d i g i t a l
Cro-Mag Rallycitizen12 studio
Crypt of BaconthulhuHamster Republic Productions
Cube DefenderPark Posse Games
Cyberflow Larissa Davidova
Dark IncursionBig Blue Bubble
D-GLESKokak
Disc BlasterAGameAWeek
Diversionezone.com
Epic Eric232 Studios Ltd
EvacHexage
Every Good Bird Deserves FlappynessAGameAWeek
Expendable RearmedRetrobomb
ExperimentHeadup Games
ExZeus 2HyperDevbox Japan
Falling BirdOne Legged Seagull
Final Freeway 2ROyatsukai Games
Fishy RushSilenGames
Fist of Awesomeifightbears
FlappynougImogia Games
Fly to the Moon!Badim
Fox Tales: The Skeleton KingWon-O-Soft
Freeeshrealtech VR
FutrinoAGameAWeek
Future Classics - 1986 EditionAGameAWeek
Galaga Special EditionNamco Bandai
GameStick Media PlayerPlayJam
Gene Effect Lightstorm3D GmbH
Genius Greedy MouseSpace Fractal
Greenie's Little Adventure AGameAWeek
GridlockLudometrics
GunslugsOrangePixel
Harpoons and BallsAGameAWeek
Haunt the House: TerrortownSFB Games
Haymaker Team Haymaker
Hazard RushSurreal Street
Heroes of LootOrangePixel
Hero of ManyTrickster Arts
Hoppy BobbyAGameAWeek
Icy Towerfreelunchdesign
INDY500® Arcade RacingHyperDevbox Japan
Invisible Munky 2AGameAWeek
It Takes TwoEpiphany
Karl's Tiny AdventureAGameAWeek
Knightmare TowerJuicy Beast
Kosmik Revengerealtech VR
LoveThe Bancast
LvLnTanuki Entertainment, Inc.
Magic RampageAsantee Games
MAGNETOID HD - Robo RunnerRoom 247 Studio
Maldita Castilla Locomalito
Metaloid Reactor Guardian Retro Revolution Games
MIMPISilicon Jelly
MiniSquadronAdvanced Mobile Applications
MiseriaRatJar Games
Momonga Pinball AdventuresPaladin Studios
MotorbikebaKno Games
Muffin KnightAngry Mob Games
Munky Blocks dxAGameAWeek
My Little Rescue HelicopterAGameAWeek
NeonPlat ExtremeAGameAWeek
NeonPlat's Cosmic AdventureAGameAWeek
Night Riders, 3D Arcade Racingbaka-neko.fr
No Gravityrealtech VR
Oddy Smog's Misadventure Play Medusa
OverdroyRoberto T. Fauri
PAC-MAN + TournamentsNamco Bandai
Panic FlightAdvanced Mobile Applications
Paragon InfiniteBipolarDesign
Particle Arcade ShooterDianox Games
Penguin ParadeAGameAWeek
Platdude in A Bit of A DoAGameAWeek
Platdude in A Bit of a SpinAGameAWeek
Platdude in A TubeAGameAWeek
Platdude in Battling OstrichesAGameAWeek
Platdude in SpaceAGameAWeek
Platdude in Swamp GolfAGameAWeek
Platdude in The Spirit CollectorAGameAWeek
PoperlyAGameAWeek
Prince of Persia: The Shadow and the FlameUbisoft
Puzzle 2 HDAdvanced Mobile Applications
Quantic PinballShineResearch
RadiantHexage
Raiden LegacyDotemu
Reckless GetawayPixelbite
RepulzePixelbite
RetroBallAGameAWeek
RetroidTaurris
Retro RacingJamie Woodhouse
RiptideVector Unit
Royal OffenseBadim
Saturday Morning RPGMighty Rabbit Studios
Sela The Space PirateFeili Chen
Shadow BladeDead Mage
ShadowGunMadfinger
Sheep in Helldavid.cm
Shuttle Quest 2kTACSGames
Ski SafariDefiant Development
Sky Gamblers: Rise of GloryNamco Bandai
Sky HeroKokonut Studio
Slingshot RacingSnowbolt
Smash CopsHutch
SoccertronForgotten Systems
Soldier NightmareGeorgeGames
Soul PowerGhost Time Games
Sound RideOutOfTheBit Ltd
Space Ax'RIOT digital
SpaceBallGeorgeGames
Space Clusters DXAGameAWeek
Space Station A6-100AGameAWeek
SpikeDislike2AGameAWeek
SpikeDislike3AGameAWeek
Spiky TowerAGameAWeek
StalagflightStalagflight Team
Stop The BirdsHaybyte Studios
Stop The BotsScary Robot Productions
Super Grid RunRefresh Creations
Super Mega WormDeceased Pixel
Tales of Illyria 1Little Killerz
Tales of Illyria 2 - Beyond the Iron WallLittle Killerz
Tales of PocoroCurved Cat Games
The Button AffairModern Dream
The Chronicles of PandoraSuprnova Entertainment
The Other BrothersSimian Squared
The Tribloos 2Bumpkin Brothers
Tim-Tim "The Mighty Gnome"" Spoonweaver Studios
TOFU Media CenterPivos
Top Gear: Stunt School RevolutionBBC Games
Towelfight 2Butterscotch Shenanigans
TURBINEGeorgeGames
TurboFly HDOsaris Games
Twin RobotsThinice
unwindJijjy
VectorNekki
Vendetta Guild Software
Zombie Kill of the WeekPanic Art Studios
Zzap LinesAGameAWeek

Also on: Mastodon, Twitter.

Published on 2024-09-08 in


ADB access on GameStick

I'm on the quest to make PlayJam GameStick micro consoles usable again. Building a replacement server is underway, and collecting game information is nearly finished - but not much progress has been made obtaining the actual .apk files.

37 apks could be downloaded from the PlayJam Amazon AWS S3 bucket, but the rest of them are not accessible although we know the URLs. They are probably only accessible with a temporary access token that the GameStick server once generated.

We contacted a number of developers and asked for the apks, but most don't have them anymore - they are lost. Some developers don't even remember having programmed for the GameStick :) And many don't react on e-mails.

The last resort is to get the .apk files off the GameSticks that have them installed. PlayJam wanted to prevent that, so they locked the GameStick down, preventing access to the Android settings, disabling the adb daemon and even removing the functionality to sideload games (which was available in early firmwares).

Telnet server

Simply starting the Android settings or adbd via the advanced launcher TOFU plugin did not work. I needed to find a way to inspect the GameStick and run applications on them to see what worked. Because adb access was not available, I decided to build my own telnet server that would run as TOFU plugin on the GameStick.

I found a nice Python 2 socket server example and used that as base to build my own server that I could connect to with a telnet client. Development was easy because I could run the server locally. Only at the end I built a TOFU plugin that simply started the telnet server script.

One thing I learned was that the shell (my server) needs to take care of storing the current working directory, and also needs to implement change directory commands - those cannot be delegated to the system. After 2.5 hours I had a telnet server that ran on the GameStick, and I could finally inspect the file system and run programs:

cweiske:~/dev/gamestick/sync/tofu-plugin> telnet gamestick 5023
Trying 192.168.3.41...
Connected to gamestick.
Escape character is '^]'.
/> ls
acct
backup
boot
cache
[...]
/> whoami
u0_a40
/> am start -n com.android.settings/.Settings
[Errno 13] Permission denied

Now I could try to open the Android settings (which still fails) and start adbd - it turned out that running programs on the GameStick is only possible as root:

$ telnet gamestick 5023
Trying 192.168.3.41...
Connected to gamestick.
Escape character is '^]'.
/> su -c start adbd
/> quit
Connection closed by foreign host.

cweiske:~/dev/gamestick/sync/tofu-plugin> adb connect gamestick
already connected to gamestick:5555
cweiske:~/dev/gamestick/sync/tofu-plugin> adb shell
root@android:/ # pwd
/
root@android:/ # ls /data
GameStick
GameStickCache

Plugins

The result of this endeavour are two TOFU plugins:

Update 2023-06: An adbd-enabling firmware image is available at codeberg.org/gamestick-fans/firmware-adb-enabler/ - see GameStick: Black screen after OOBE.

Starting a telnet server with a TOFU plugin Starting adbd via TOFU plugin

Published on 2023-05-07 in


GameStick: Black screen after OOBE

Work on my own server for the abandoned PlayJam GameStick micro console continued, and two weeks ago I deemed it good enough to make it public for others to test.

To make sure everything works fine I removed the GameStick host name entries from my local DNS server, factory reset the GameStick and started the initial setup. It all worked fine as expected, but after completing setup the screen went black and stayed that way. Only notifications that a Gamepad was connected/disconnected or the internet connection was established were shown in the bottom right corner. The GameStick did not react to gamepad nor keyboard input.

Black screen with a notification

Since had reinstalled the 2071 firmware as part of my test, I had no access to adb - for that I had to install and start the TOFU media player, install and run my "start adb" plugin. None of this was an option since the main UI ("Console") did not load.

Git backups

Flashing firmware 2058 gave the same black screen that 2071 showed.

I suspected something to be off with my API and changed the connect API responses to known-to-work versions from git history of the playjam gamestick API code, but that did not help. Minimizing them did not help either.

Next I tried to replace the profile API with a version that I used when I got it working for the first time, but that did also not help.

I also suspected the session IDs to have invalid characters, but changing them did not yield any results. The black screen stayed.

Another thing that the official connect API responses had were UI translation strings, so I integrated them - but no avail.

The first three days of poking in the dark were over.

Cache files

During development I had collected a number of server responses that were cached on different GameSticks (Toast, Cataphoresis, Ryo, Kazdan, Lee Chapman). I let my server return those files, but the screen still stayed black.

Since I knew that the UI did not show the latest data when they were downloaded from the server, I had to boot the GameStick once to the black screen, wait for it to download all API data, and rebooted again to see if the new data made any difference.

Nothing.

I also replaced the small .jpg profile images with original large .png files.

From previous experiments I knew that OOBE in firmware 2071 did not show the profile image, while 2058 does. So I tried to find out what changed between those two firmware versions: 2058 used the custom JSON handler, while 2071 had completely switched to a Gson to parse and hydrate the API responses.

There were no differences to find in the parsed properties. Day 4 over.

Android emulator

My main problem was that I did not have error logs because the PlayJam developers had disabled adbd on the GameStick. My next idea was to install all the GameStick .apk files inside the Android emulator and see the error in its logs.

Fortunately I could configure a 4.1 Android system for the emulator, start it and install all com.playjam.* apk files that were part of the 2071 firmware. I could start OOBE, but it would hang in the 5th step, the activation. Logs said that it could not obtain the hardware ID which is needed in requests to the API server.

I dived deep into the decompiled code, found out how the GameStick loads its hardware ID, built an Android app that provides a system service that starts on boot and sends out the com.playjam.SYSTEM_INFO intent with a fake hardware ID and firmware version information.

I learned the hard way that building an app with only a service and without any user interface will never be marked as "activated", and thus its services will never be started by the Android system. So I had to build a dummy UI activity that started the service once.

In the end, my service worked and the GameStick apks could fetch the correct API from the server, and OOBE finished.

The Console UI had some errors because certain files and folders were missing in the /data user partition. I copied them over from the firmware image, and the GameStick intro video played!

GameStick boot/intro video

Unfortunately the UI crashed while the spinner was rotating, because playing a sound did not work in the emulator:

W/AudioPolicyManagerBase(  654): getOutput() could not find output for stream 3, samplingRate 0,format 0, channels 3, flags 0
E/AudioTrack-Java( 2246): [ android.media.AudioTrack ] getMinBufferSize(): error querying hardware
W/dalvikvm( 2246): JNI WARNING: JNI method called with exception pending
W/dalvikvm( 2246):              in Lcom/ideaworks3d/marmalade/LoaderThread;.runOnOSTickNative:()V (GetObjectClass)
W/dalvikvm( 2246): Pending exception is:
I/dalvikvm( 2246): java.lang.NullPointerException:
I/dalvikvm( 2246): 	at com.ideaworks3d.marmalade.SoundPlayer.start(SoundPlayer.java:75)
I/dalvikvm( 2246): 	at com.ideaworks3d.marmalade.LoaderThread.soundStart(LoaderThread.java:856)

But this was a kind of success: The intro video was not visible on my real factory-reset GameStick.

Day 6 over.

Gamestick Console loading inside Android emulator

GameStick CFW

So my GameStick stays completely black but the emulator shows the intro video: I needed to get back to real hardware. One thing I had not yet tried was CFW 1.4, the Custom FirmWare by shanti (GameStickers.net: [ROM] CFW v1.3 - Updated 1.4 is out :D, archived version). It hopefully has adbd enabled, which would give me logs.

I flashed it onto the GameStick, and it booted into a standard Android user interface (the whole point of the firmware was to get an usable Android without any restrictions). Then I installed all the com.playjam.*.apk files and populated /data as I had when using the emulator.

The results were good: OOBE worked, intro video plays, the spinner is visible and then the normal UI starts and is usable - only game images did not load.

But while it was nice that I got the official UI working on custom firmware, I did not find out why the official firmware stayed black.

Day 7 was gone.

Custom firmware

When inspecting the CFW 1.4 files I noticed /system/build.prop which contained three additional lines:

persist.service.adb.enable=1
persist.service.debuggable=1
persist.sys.usb.config=mass_storage,adb

If the official firmware had this, I'd get proper error logs and could see the error messages.

I learned that the GameStick firmware .img files are standard Android OTA .zip files and not some custom format.

I also learned that firmware files need to be signed, so I used the standard java method for signing:

$ signapk -a 4 --min-sdk-version 16 --disable-v2 certs/certificate.pem certs/key.pk8 image.tmp.zip image.signed.img

.. but when trying to flash that image I got:

Verifying update package...
Installation aborted.

I tried different parameter combinations (align/noalign, v1/v2) but all failed.

Android system recovery: Firmware installation fail

Then I read all 28 pages of the archived CFW thread on gamestickers.net and found someone who asked how the image was signed. shanti had answered:

here is the program I used: "Sign-em! 2.0"
http://forum.xda-developers.com/showthread.php?t=1966007

I got the linux version and found it used signapk.jar. After finding that I saw that it used some internal old Sun Java class sun.misc.BASE64Encoder that was not available anymore in any recent OpenJDK :(

Android system recovery normally only installs firmware images that have been signed by one of a number of white-listed keys. The GameStick's recovery seems to allow all properly signed images, regardless which signing key was used.
This is the reason the CFW was possible at all - on OUYA, custom firmwares could only be installed when using a custom bootloader, but not with the stock recovery that requires firmwares to be signed by a key that only OUYA possessed.

Then I found the next XDA thread post that linked to HemanthJabalpuri/signapk which contained MinSignApk 1.0 that ran on current Java versions!

I signed my firmware image with MinSignApk, and could flash it!

Android system recovery: Firmware installation success

Update 2023-06: An adbd-enabling firmware image is available at codeberg.org/gamestick-fans/firmware-adb-enabler/

Errors

Now that I had flashed my custom firmware 2071+adb I finally saw the errors:

Download directory

I/ActivityManager( 3509): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 pkg=com.playjam.gamestick.console cmp=com.playjam.gamestick.console/.Main u=0} from pid 3754
D/GameStick( 4262): ****************************************
D/GameStick( 4262): Failed to create download directory

The directory existed, so I removed it:

$ adb shell rmdir /data/data/com.playjam.consoledev/files/Downloads

Next boot, the GameStick would create the directory, and the following it would complain again. So this was not the problem.

readAsciiLine

I/ActivityManager( 4479): Displayed com.playjam.gamestick.console/.Main: +313ms (total +1s416ms)
W/System.err( 4628): java.io.EOFException
W/System.err( 4628): 	at libcore.io.Streams.readAsciiLine(Streams.java:203)

The firmware update check needs to return its JSON on a single line, otherwise parsing would fail. I modified the server.

OpenTextureFile

D/PlayjamKeyboard( 3685): Starting for type : 0/0
I/marmalade( 4262): PJException error has occurred : 62 c:/_work/dev/marmalade_main/menu_head/src/PNGFile.cpp OpenTextureFile open png Error : empty file name

This finally looked like the real problem. I removed all game information from the API in case the game images were the culprit, as well as the profile images. Still the same error.

Day 8 was over.

The next day I tried more image related changes:

  • Use .png profile images
  • Provide a lastAchievementImageUrl as .png
  • Remove profile images again

A race condition

While booting the GameStick I came across a very special error:

W/DatabaseService:ConnectDownloader( 3794): Failed to duplicate connect data for console : /data/GameStick/ConsoleResources/315f7b66-fae7-4ab3-9d46-bf41942694b6.json => /data/GameStickCache/reg_server_response.json

Reading through the source code led to me understanding that process:

  1. GameStick user interface requests the game data in mode cache_then_fresh. This means that cached data should be returned immediately, but a background request to get fresh data would be started afterwards.
  2. The cached response data is returned gets parsed by ConnectDownloader
  3. In the background, the new data are fetched from the server.
  4. New data download finishes and the old cached data file gets deleted.
  5. ConnectDownloader finishes parsing the old file and wants to copy it to a different place, so that the "console" UI process can use it.

The last step failed because downloading fresh data (500 kiB!) was faster than parsing cached data.

This could only happen on my local setup: GameStick's WiFi reception is so bad that I could not use my normal access points. Instead I enable an access point on my laptop whenever I do GameStick development, and the GameStick only needs to transmit data some 30cm to my laptop. Since the API server is running on the same machine, data transmission is much faster than usual, leading to that race condition.

This problem was fixed with a sleep(2) call to slow down the API.

/data

The GameStick still gave the OpenTextureFile error with no hint about the file it tried to read.

I tried my luck, built a 2058 firmware with adbd and did get a more verbose error:

I/marmalade( 5452): PJException error has occurred : 97 c:/_work/dev/marmalade_main/menu_head/src/PNGFile.cpp OpenTextureFile open png Error : Cannot open file raw:///data/GameStickCache/Assets/textures/placeholder3.png

That was very strange. I knew that the firmware image contains nearly 1000 files in the /data folder, and confirmed that this particular file also exists in both 2058 and 2071 firmware files.

It turned out that /data/GameStickCache/Assets/ was completely missing on my device, as well as /data/GameStickCache/Resources/. What the heck?

Now I remembered that when flashing firmware via system recovery, I always do two steps to get a nice clean system:

  1. Apply update(*.img)
  2. Wipe data/factory reset

But the GameStick firmware installation process already populates the user data partition /data/! Wiping user data after installation removes all the asset files that are needed by the console user interface, leaving a broken system.

Now it also made sense that I did not see this problems on the emulator and the CFW setup: I knew those files were missing and had manually copied them from the firmware update into /data.

Day 9 had finally brought relief.

Fin

The key takaway is that the PlayJam developers did not follow standard Android conventions and put necessary system data onto the user partition.

When flashing a GameStick, always wipe user data first, and then flash the firmware .img file. Never the other way round.

Published on 2023-06-19 in ,


GameStick server: Semi-public alpha

My replacement server for the PlayJam GameStick micro console is ready for semi-public testing. It allows you to finish the initial setup (OOBE), list all the games, and download + play 130 of them.

It's not complete yet: We know of games that cannot be controlled properly because button mappings are missing, and achievements are not yet stored on the server. Firmware updates are not distributed. Probably many other issues are waiting to be found.

It is semi-public because GameStick devices have to be white-listed by me.

Whitelisting process

When your GameStick is stuck in the initial setup, attach a keyboard. On the language selection screen, type "hardware" and your GameStick's hardware ID will be shown in the top left corner.

Send that hardware ID by mail to me via cweiske+gamestick@cweiske.de or join the GameStick Fans Discord chat server and contact me there.

If the hardware ID does not appear, continue until WiFi setup and complete it. The GameStick will contact my server automatically and I can read the ID from the logs. Open ip.cweiske.de in your browser and send me that IP address, so I can correlate IP and hardware ID.

Setup process

The GameStick setup in screenshots:

The Gamestick OOBE lets you select the language, setup WiFi and shows a verification code:

GameStick Setup: Language selection GameStick Setup: WiFi setup GameStick Setup: Verification code

Then you need to continue in your browser: Enter a name, select a profile image and choose the age rating for games.

GameStick Setup: Web: Verification code input GameStick Setup: Web: Profile setup GameStick Setup: Profile setup (mobile view) GameStick Setup: Web: Success

When you finish setup in the browser, the GameStick will show your "Gamer tag" (name) and the profile image (only on firmware 2058, non on 2071):

GameStick Setup: Success (firmware 2058)

Afterwards the boot video will play and you'll the the main user interface that you can use to download + play games:

GameStick main user interface screen

Games names beginning with !! indicate that they cannot be downloaded. We currently have .apk files for 131 of the 188 games.

Also on: Mastodon, Reddit, Twitter.

Published on 2023-06-19 in