diff --git a/assets/default b/assets/default new file mode 100644 index 0000000..7dc9db6 --- /dev/null +++ b/assets/default @@ -0,0 +1,21 @@ +# testing: +# g_cfg_rom_path = /mnt/sdcard/ROM.03 +# 0 = unlimited 1 = 1mhz 2 = 2.8mhz 3 = 8mhz +g_limit_speed = 2 + +# By default no disk images are loaded until the user inserts one. +# +# Put your custom config here and KEGS will use it on power on. + +# s5d1 = /mnt/sdcard/Downloads/DELTA_DEMO.2MG +# s6d1 = /mnt/sdcard/Downloads/karateka.dsk +# s7d1 = /mnt/sdcard/Downloads/Hard Drive 1.hdv +# s7d2 = /mnt/sdcard/Downloads/Hard Drive 2.hdv +# +# s7d11 = :Partition Name:/path/to/image + +# The BRAM below tells it to boot Slot 5. +# +# Delete all the below lines to get the default. +# +# For custom BRAM, copy config_kegs to here while KEGS is running. diff --git a/jni/android_driver.c b/jni/android_driver.c index 3f516d5..cfc1d6e 100644 --- a/jni/android_driver.c +++ b/jni/android_driver.c @@ -292,6 +292,26 @@ x_update_color(int col_num, int red, int green, int blue, word32 rgb) { } +// This typically sets g_config_kegs_name to the full path of 'config.kegs'. +void android_config_init(char *output, int maxlen) { + output[0] = 0; + + jclass cls = (*g_env)->GetObjectClass(g_env, g_thiz); + jmethodID mid = (*g_env)->GetMethodID(g_env, cls, "getConfigFile", "()Ljava/lang/String;"); + (*g_env)->DeleteLocalRef(g_env, cls); + if (mid == NULL) { + return; + } + jstring config_path = (*g_env)->CallObjectMethod(g_env, g_thiz, mid); + if (config_path == NULL) { + return; + } + const char *nativeString = (*g_env)->GetStringUTFChars(g_env, config_path, 0); + strncpy(output, nativeString, maxlen - 1); + output[maxlen - 1] = 0; + (*g_env)->ReleaseStringUTFChars(g_env, config_path, nativeString); + (*g_env)->DeleteLocalRef(g_env, config_path); +} // Instead of 'KegsView$KegsThread', the $ is encoded as _00024. // (not any more, but it was KegsView_00024KegsThread_mainLoop) diff --git a/jni/config_kegs.c b/jni/config_kegs.c index d8af1bf..76d4e7d 100644 --- a/jni/config_kegs.c +++ b/jni/config_kegs.c @@ -339,9 +339,14 @@ config_init() // Find the config.kegs file g_config_kegs_name[0] = 0; +#ifdef __ANDROID__ + extern void android_config_init(char *, int); + android_config_init(&g_config_kegs_name[0], sizeof(g_config_kegs_name)); +#else can_create = 1; setup_kegs_file(&g_config_kegs_name[0], sizeof(g_config_kegs_name), 0, can_create, &g_config_kegs_name_list[0]); +#endif config_parse_config_kegs_file(); } @@ -687,6 +692,7 @@ config_parse_config_kegs_file() g_highest_smartport_unit = -1; cfg_get_base_path(&g_cfg_cwd_str[0], g_config_kegs_name, 0); +#if !defined(__ANDROID__) if(g_cfg_cwd_str[0] != 0) { ret = chdir(&g_cfg_cwd_str[0]); if(ret != 0) { @@ -696,6 +702,7 @@ config_parse_config_kegs_file() /* In any case, copy the directory path to g_cfg_cwd_str */ (void)getcwd(&g_cfg_cwd_str[0], CFG_PATH_MAX); +#endif fconf = fopen(g_config_kegs_name, "r"); if(fconf == 0) { diff --git a/jni/sim65816.c b/jni/sim65816.c index 53885ad..ab35651 100644 --- a/jni/sim65816.c +++ b/jni/sim65816.c @@ -20,7 +20,6 @@ const char rcsid_sim65816_c[] = "@(#)$KmKId: sim65816.c,v 1.367 2004-11-22 02:39 #define vsnprintf _vsnprintf #endif - #define PC_LOG_LEN (8*1024) int g_speed_fast ; // OG Expose fast parameter @@ -1215,7 +1214,14 @@ setup_kegs_file(char *outname, int maxlen, int ok_if_missing, outname[0] = 0; +#ifdef __ANDROID__ + extern char g_cfg_cwd_str[]; + // For this to work, g_config_kegs_name must have already been set. + const char *tmp_paths[2] = { g_cfg_cwd_str, 0 }; + path_ptr = &tmp_paths[0]; +#else path_ptr = &g_kegs_default_paths[0]; +#endif save_path_ptr = path_ptr; while(*path_ptr) { diff --git a/src/com/froop/app/kegs/ConfigFile.java b/src/com/froop/app/kegs/ConfigFile.java new file mode 100644 index 0000000..014e35d --- /dev/null +++ b/src/com/froop/app/kegs/ConfigFile.java @@ -0,0 +1,84 @@ +package com.froop.app.kegs; + +import android.content.Context; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +class ConfigFile { + public static final String ROM03 = "ROM.03"; + public static final String ROM01 = "ROM.01"; + + private static final String mConfigFile = "config.kegs"; + private static final String mConfigDefault = "default"; + + private Context mContext; + private String mConfigPath; + + ConfigFile(Context context) { + mContext = context; + mConfigPath = mContext.getExternalFilesDir(null).getPath(); + } + + public String getConfigFile() { + return mConfigPath + "/" + mConfigFile; + } + + public String getConfigPath() { + return mConfigPath; + } + + public void ensureAssetCopied(String assetName) { + // Make sure there's a user-readable copy of whatever from assets. + final File local_copy = new File(mConfigPath, assetName); + if (local_copy != null && local_copy.exists()) { + // Assume that whatever is there will work. + return; + } + + try { + new CopyHelper(mContext.getAssets().open(assetName), + mConfigPath, assetName).copy(); + } catch (java.io.IOException e) { + // KEGS will just fail. + return; + } + } + + public void defaultConfig() { + ensureAssetCopied(mConfigDefault); + // Then, copy whatever is there over to the actual 'config.kegs' file. + try { + new CopyHelper(new FileInputStream(new File(mConfigPath, mConfigDefault)), + mConfigPath, mConfigFile).copy(); + } catch (java.io.IOException e) { + // KEGS will just fail. + return; + } + } + + public void internalConfig(String configName) { + // Overwrite 'config.kegs' with a config from the assets directory. + try { + new CopyHelper(mContext.getAssets().open(configName), + mConfigPath, mConfigFile).copy(); + } catch (java.io.IOException e) { + // KEGS will just fail. + return; + } + } + + public String whichRomFile() { + File rom = new File(mConfigPath, ROM03); + if (rom != null && rom.exists()) { + return rom.getPath(); + } + + rom = new File(mConfigPath, ROM01); + if (rom != null && rom.exists()) { + return rom.getPath(); + } + + return null; + } +} diff --git a/src/com/froop/app/kegs/CopyHelper.java b/src/com/froop/app/kegs/CopyHelper.java new file mode 100644 index 0000000..d2b1c4c --- /dev/null +++ b/src/com/froop/app/kegs/CopyHelper.java @@ -0,0 +1,48 @@ +package com.froop.app.kegs; + +import android.util.Log; +import java.io.File; +import java.io.InputStream; +import java.io.FileOutputStream; + +public class CopyHelper { + private InputStream mInput; + private String mDir; + private String mFile; + private static final String mTmp = "tmp_"; + + CopyHelper(InputStream input, String dir, String filename) { + mInput = input; + mDir = dir; + mFile = filename; + } + + public void copy() throws java.io.IOException { + Log.e("kegs", "CopyHelper to " + mDir + "/" + mFile); + final File dir = new File(mDir); + dir.mkdirs(); + + final File output_file = new File(mDir, mTmp + mFile); + final File final_file = new File(mDir, mFile); + if (output_file == null || final_file == null) { + throw new java.io.IOException("null File in " + mDir); + } + + output_file.delete(); + output_file.createNewFile(); + + byte buf[] = new byte[4096]; + FileOutputStream out = new FileOutputStream(output_file); + do { + int numread = mInput.read(buf); + if (numread <= 0) { + break; + } else { + out.write(buf, 0, numread); + } + } while (true); + out.close(); + output_file.renameTo(final_file); + mInput.close(); + } +} diff --git a/src/com/froop/app/kegs/KegsMain.java b/src/com/froop/app/kegs/KegsMain.java index 349f2a6..a055f98 100644 --- a/src/com/froop/app/kegs/KegsMain.java +++ b/src/com/froop/app/kegs/KegsMain.java @@ -30,6 +30,7 @@ public class KegsMain extends Activity implements KegsKeyboard.StickyReset { private static final String FRAGMENT_SPEED = "speed"; private static final String FRAGMENT_DISKIMAGE = "diskimage"; + private ConfigFile mConfigFile; private KegsThread mKegsThread; // For the software renderer, use 'KegsView' here and in res/layout/main.xml @@ -104,7 +105,8 @@ public class KegsMain extends Activity implements KegsKeyboard.StickyReset { protected Boolean doInBackground(String ... raw_romfile) { mRomfile = raw_romfile[0]; return new DownloadHelper().save( - "http://jsan.co/" + mRomfile, Config.mPath.getPath() + "/" + mRomfile); + "http://jsan.co/KEGS/" + mRomfile, + mConfigFile.getConfigPath() + "/" + mRomfile); } protected void onPostExecute(Boolean success) { final DialogFragment frag = (DialogFragment)getFragmentManager().findFragmentByTag(FRAGMENT_DOWNLOAD); @@ -117,7 +119,7 @@ public class KegsMain extends Activity implements KegsKeyboard.StickyReset { dialog.show(getFragmentManager(), FRAGMENT_ERROR); } } else { - Config.defaultConfig(mRomfile); + mConfigFile.defaultConfig(); getThread().setReady(true); } } @@ -301,7 +303,10 @@ public class KegsMain extends Activity implements KegsKeyboard.StickyReset { mKegsView = (KegsViewGL)findViewById(R.id.kegsview); - mKegsThread = new KegsThread(mKegsView.getBitmap()); + mConfigFile = new ConfigFile(this); + + mKegsThread = new KegsThread(mConfigFile.getConfigFile(), + mKegsView.getBitmap()); mKegsThread.registerUpdateScreenInterface(mKegsView); workaroundScreenSize(); @@ -336,12 +341,15 @@ public class KegsMain extends Activity implements KegsKeyboard.StickyReset { findViewById(R.id.key_up).setOnClickListener(mButtonClick); findViewById(R.id.key_down).setOnClickListener(mButtonClick); - final String romfile = Config.whichRomFile(); +// TODO: Kick this off in the background for built in images. +// mConfigFile.ensureAssetCopied("XMAS_DEMO.2MG"); + + final String romfile = mConfigFile.whichRomFile(); if (romfile == null) { final DialogFragment chooseRom = new RomDialogFragment(); chooseRom.show(getFragmentManager(), FRAGMENT_ROM); } else { - Config.defaultConfig(romfile); + mConfigFile.defaultConfig(); getThread().setReady(true); } } diff --git a/src/com/froop/app/kegs/KegsThread.java b/src/com/froop/app/kegs/KegsThread.java index 0f124b6..3c99507 100644 --- a/src/com/froop/app/kegs/KegsThread.java +++ b/src/com/froop/app/kegs/KegsThread.java @@ -12,6 +12,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; class KegsThread extends Thread { private ConcurrentLinkedQueue mEventQueue = new ConcurrentLinkedQueue(); + private String mConfigFile; // full path to config_kegs private Bitmap mBitmap; private final ReentrantLock mPauseLock = new ReentrantLock(); private final ReentrantLock mPowerWait = new ReentrantLock(); @@ -25,7 +26,8 @@ class KegsThread extends Thread { } private UpdateScreen mUpdateScreen; - public KegsThread(Bitmap bitmap) { + public KegsThread(String configFile, Bitmap bitmap) { + mConfigFile = configFile; mBitmap = bitmap; } @@ -51,6 +53,10 @@ class KegsThread extends Thread { } } + private String getConfigFile() { + return mConfigFile; + } + // See jni/android_driver.c:mainLoop() private native void mainLoop(Bitmap b, ConcurrentLinkedQueue q); diff --git a/src/com/froop/app/kegs/RomDialogFragment.java b/src/com/froop/app/kegs/RomDialogFragment.java index cc8cb16..4e600ca 100644 --- a/src/com/froop/app/kegs/RomDialogFragment.java +++ b/src/com/froop/app/kegs/RomDialogFragment.java @@ -19,9 +19,9 @@ public class RomDialogFragment extends DialogFragment { if (item == 0) { ((KegsMain)getActivity()).finish(); } else if (item == 1) { - ((KegsMain)getActivity()).getRomFile(Config.mROM01); + ((KegsMain)getActivity()).getRomFile(ConfigFile.ROM01); } else if (item == 2) { - ((KegsMain)getActivity()).getRomFile(Config.mROM03); + ((KegsMain)getActivity()).getRomFile(ConfigFile.ROM03); } } });