├── res └── drawable-xhdpi │ └── ouya_icon.png ├── .gitignore ├── LaunchRomActivity.java.tpl ├── cleanup.sh ├── project.properties ├── ant.properties ├── README.rst ├── AndroidManifest.xml ├── prepare-game.sh └── src └── de └── cweiske └── ouya └── romlauncher └── LaunchSnesActivity.java /res/drawable-xhdpi/ouya_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cweiske/ouya-romlauncher/master/res/drawable-xhdpi/ouya_icon.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /assets/game/ 3 | /gen/ 4 | /.classpath 5 | /.project 6 | /.settings 7 | /local.properties 8 | /src/romlauncher/ 9 | -------------------------------------------------------------------------------- /LaunchRomActivity.java.tpl: -------------------------------------------------------------------------------- 1 | package FIXME_PACKAGE; 2 | 3 | import de.cweiske.ouya.romlauncher.LaunchSnesActivity; 4 | 5 | public class LaunchRomActivity extends LaunchSnesActivity 6 | { 7 | protected String getAssetFilename() 8 | { 9 | return "FIXME_FILENAME"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | #clean up from last run 5 | git checkout AndroidManifest.xml build.xml res/drawable-xhdpi/ouya_icon.png 6 | 7 | [ -d assets/game ] && rm -r assets/game 8 | [ -d bin ] && rm -r bin 9 | [ -d gen ] && rm -r gen 10 | [ -d src/romlauncher ] && rm -r src/romlauncher 11 | 12 | exit 0 13 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-16 15 | 16 | -------------------------------------------------------------------------------- /ant.properties: -------------------------------------------------------------------------------- 1 | # This file is used to override default values used by the Ant build system. 2 | # 3 | # This file must be checked into Version Control Systems, as it is 4 | # integral to the build system of your project. 5 | 6 | # This file is only used by the Ant script. 7 | 8 | # You can use this to override default values such as 9 | # 'source.dir' for the location of your java source folder and 10 | # 'out.dir' for the location of your output folder. 11 | 12 | # You can also use it define how the release builds are signed by declaring 13 | # the following properties: 14 | # 'key.store' for the location of your keystore and 15 | # 'key.alias' for the name of the key to use. 16 | # The password will be asked during the build when you use the 'release' target. 17 | 18 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ******************************* 2 | Generic OUYA SNES game launcher 3 | ******************************* 4 | Based on this code you can pack up a SNES game and make it 5 | directly available in the OUYA launcher, just as a normal game. 6 | 7 | When running it, the game file is extracted and 8 | `Snes9x EX+`__ is started with it. 9 | 10 | __ http://www.explusalpha.com/home/snes9x-ex 11 | 12 | 13 | Packing a game 14 | ============== 15 | Run ``prepare-game.sh``:: 16 | 17 | $ ./prepare-game.sh "Super Pac-Man" superpacman ~/public-domain/superpacman.smc 18 | Game title: Super Pac-Man 19 | Full package path: romlauncher.superpacman 20 | Game file: superpacman.smc 21 | All prepared. 22 | Put a 732x412 image into res/drawable-xhdpi/ouya_icon.png 23 | 24 | Now adjust the launcher image ``ouya_icon.png`` and build/run it 25 | with the Android Developer Tools Eclipse IDE, or via command line:: 26 | 27 | $ ant release 28 | 29 | The generated ``.apk`` file will be located in the ``bin/`` folder. 30 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /prepare-game.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | #clean up from last run 5 | ./cleanup.sh 6 | 7 | if [ $# -lt 3 ]; then 8 | echo "Usage: ./prepare-game.sh title java.package path-to-game.smc [cover.png]" 9 | exit 10 | fi 11 | 12 | title=$1 13 | package=$2 14 | fullpackage="romlauncher.$package" 15 | filepath=$3 16 | filename=`basename "$filepath"` 17 | 18 | echo "Game title: $title" 19 | echo "Full package path: $fullpackage" 20 | echo "Game file: $filename" 21 | 22 | #prepare manifest 23 | sed -i\ 24 | -e "s/FIXME_PACKAGE/$package/" \ 25 | build.xml 26 | 27 | #prepare build file 28 | sed -i\ 29 | -e "s/FIXME_PACKAGE/$fullpackage/" \ 30 | -e "s/FIXME_TITLE/$title/" \ 31 | AndroidManifest.xml 32 | 33 | #copy game 34 | mkdir -p assets/game 35 | cp "$filepath" assets/game/ 36 | 37 | #prepare launcher 38 | mkdir -p "src/romlauncher/$package" 39 | sed -e "s/FIXME_PACKAGE/$fullpackage/"\ 40 | -e "s/FIXME_FILENAME/$filename/"\ 41 | LaunchRomActivity.java.tpl\ 42 | > src/romlauncher/$package/LaunchRomActivity.java 43 | 44 | if [ $# -gt 3 ]; then 45 | image=$4 46 | cp "$image" res/drawable-xhdpi/ouya_icon.png 47 | echo "Image copied" 48 | else 49 | echo "Put a 732x412 image into res/drawable-xhdpi/ouya_icon.png" 50 | fi 51 | 52 | echo "All prepared." 53 | -------------------------------------------------------------------------------- /src/de/cweiske/ouya/romlauncher/LaunchSnesActivity.java: -------------------------------------------------------------------------------- 1 | package de.cweiske.ouya.romlauncher; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | 9 | import android.app.Activity; 10 | import android.content.ComponentName; 11 | import android.content.Intent; 12 | import android.content.res.AssetManager; 13 | import android.net.Uri; 14 | import android.os.Bundle; 15 | import android.os.Environment; 16 | 17 | abstract public class LaunchSnesActivity extends Activity 18 | { 19 | abstract protected String getAssetFilename(); 20 | 21 | /** 22 | * Called when the activity is first created. 23 | */ 24 | @Override 25 | public void onCreate(Bundle savedInstanceState) 26 | { 27 | super.onCreate(savedInstanceState); 28 | 29 | File extractedFile = extractFile(getAssetFilename()); 30 | if (extractedFile == null) { 31 | System.err.println("Failed to extract file " + getAssetFilename()); 32 | finish(); 33 | return; 34 | } 35 | 36 | Intent intent = new Intent(); 37 | intent.setComponent(new ComponentName("com.explusalpha.Snes9xPlus", "com.imagine.BaseActivity")); 38 | intent.setAction("android.intent.action.VIEW"); 39 | intent.setData(Uri.fromFile(extractedFile)); 40 | 41 | startActivity(intent); 42 | finish(); 43 | return; 44 | } 45 | 46 | protected File extractFile(String assetFilename) 47 | { 48 | //File cacheDir = this.getExternalCacheDir(); 49 | //File cacheDir = getExternalFilesDir(null); 50 | File cacheDir = Environment.getExternalStorageDirectory(); 51 | if (cacheDir == null) { 52 | return null; 53 | } 54 | File dir = new File( 55 | cacheDir.toString() 56 | + File.separator 57 | + "gamelauncher" 58 | ); 59 | if (!dir.exists()) { 60 | dir.mkdirs(); 61 | } 62 | 63 | File targetFile = new File(dir.toString() + File.separator + assetFilename); 64 | if (targetFile.exists()) { 65 | return targetFile; 66 | } 67 | 68 | AssetManager assetManager = this.getAssets(); 69 | try { 70 | InputStream in = assetManager.open("game/" + assetFilename); 71 | copyFile(in, new FileOutputStream(targetFile)); 72 | return targetFile; 73 | } catch (IOException e) { 74 | e.printStackTrace(); 75 | } 76 | return null; 77 | } 78 | 79 | protected void copyFile(InputStream in, OutputStream out) throws IOException 80 | { 81 | byte[] buffer = new byte[1024]; 82 | int read; 83 | while((read = in.read(buffer)) != -1){ 84 | out.write(buffer, 0, read); 85 | } 86 | } 87 | } 88 | --------------------------------------------------------------------------------