1 /* Be aware that the original version of this file is located in 2 * src/arch/android/AnVICE/src-proto/com/locnet/vice/DosBoxLauncher.java 3 * 4 * when making changes only make them to the file in the proper location 5 */ 6 7 /* 8 * DosBoxLauncher.java 9 * 10 * Written by 11 * Locnet <android.locnet@gmail.com> 12 * 13 * This file is part of VICE, the Versatile Commodore Emulator. 14 * See README for copyright notice. 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License as published by 18 * the Free Software Foundation; either version 2 of the License, or 19 * (at your option) any later version. 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 29 * 02111-1307 USA. 30 * 31 */ 32 33 package com.locnet.vice; 34 35 import java.nio.Buffer; 36 import java.nio.ByteBuffer; 37 38 import com.locnet.vice.Globals; 39 import com.locnet.vice.PreConfig; 40 41 import android.app.Activity; 42 import android.content.Context; 43 import android.content.Intent; 44 import android.content.SharedPreferences; 45 import android.content.res.Configuration; 46 import android.graphics.Bitmap; 47 import android.os.Bundle; 48 import android.preference.PreferenceManager; 49 import android.view.ContextMenu; 50 import android.view.Menu; 51 import android.view.MenuItem; 52 import android.view.View; 53 import android.view.inputmethod.InputMethodManager; 54 55 public class DosBoxLauncher extends Activity { 56 public static final int SPLASH_TIMEOUT_MESSAGE = -1; 57 public static final int SHOW_IM_PICKER_MESSAGE = -2; 58 public static final int TURBO_MESSAGE = -3; 59 public static final int RESET_JOY_BUTTON_MESSAGE = -4; 60 public static final int RESET_JOY_DIRECTION_MESSAGE = -5; 61 nativeInit()62 public static native void nativeInit(); nativeShutDown()63 public static native void nativeShutDown(); nativeSetOption(int option, int value, String value2)64 public static native int nativeSetOption(int option, int value, String value2); nativeStart(Bitmap bitmap, int width, int height)65 public native void nativeStart(Bitmap bitmap, int width, int height); nativePause(int state)66 public static native void nativePause(int state); nativeStop()67 public static native void nativeStop(); nativeReset()68 public static native void nativeReset(); nativeSaveState(String filename, int num)69 public static native void nativeSaveState(String filename, int num); nativeLoadState(String filename, int num)70 public static native void nativeLoadState(String filename, int num); nativeAudioWriteBuffer(short audioBuffer[])71 public static native int nativeAudioWriteBuffer(short audioBuffer[]); nativeSetRomHandling(int state)72 public static native void nativeSetRomHandling(int state); 73 74 public DosBoxSurfaceView mSurfaceView = null; 75 public DosBoxAudio mAudioDevice = null; 76 public DosBoxThread mDosBoxThread = null; 77 78 public boolean mPrefRefreshHackOn = true; 79 public boolean mPrefCycleHackOn = true; 80 public boolean mPrefScaleFilterOn = false; 81 public boolean mPrefSoundModuleOn = true; 82 public boolean mPrefOnscreenButtonOn = true; 83 public boolean mPrefHardkeyOn = true; 84 public String mPrefKeyMapping = DosBoxMenuUtility.DEFAULT_KEY_MAPPING; 85 public int mPrefCycles = 0; 86 public int mPrefFrameskip = 0; 87 public int mPrefMemorySize = 4; 88 public int mPrefScaleFactor = 100; 89 public boolean mPrefTapClickOn = true; 90 public int mPrefMouseSensitivity = DosBoxMenuUtility.DEFAULT_MOUSE_SENSITIVITY; 91 public float mMouseScale = 1.0f; 92 public boolean mPrefForceKeyboardOn = false; 93 public boolean mPrefUseLeftAltOn = true; 94 public boolean mTurboOn = false; 95 public boolean mPrefSoundOn = true; 96 public boolean mPrefShowInfoOn = false; 97 public boolean mPrefFastMouseOn = false; 98 public int mPrefJoyKeySet = DosBoxMenuUtility.JOYKEY_SET_DPAD; 99 public boolean mPrefAlwaysShowJoystick = false; 100 public boolean mPrefLargeJoystick = false; 101 public boolean mPrefTrueDriveOn = false; 102 public boolean mPrefKeyUpDelay = true; 103 public boolean mPrefBetterVideoOn = false; 104 public int mPrefScaleMode = DosBoxSurfaceView.SCALE_MODE_CUSTOM; 105 public int mJoyPort = 0; 106 107 @Override onCreate(Bundle savedInstanceState)108 protected void onCreate(Bundle savedInstanceState) { 109 super.onCreate(savedInstanceState); 110 { 111 Intent intent = getIntent(); 112 int message = intent.getIntExtra(PreConfig.EXTRA_MESSAGE, 0); 113 114 if (PreConfig.MACHINE_TYPE != PreConfig.MACHINE_ALL) { 115 /* @VICE@ will be replaced during build time with the name of the library needed by the android build script. */ 116 System.loadLibrary("@VICE@"); 117 } else { 118 if (message == PreConfig.MACHINE_X64) { 119 System.loadLibrary("x64"); 120 } 121 if (message == PreConfig.MACHINE_X64SC) { 122 System.loadLibrary("x64sc"); 123 } 124 if (message == PreConfig.MACHINE_XSCPU64) { 125 System.loadLibrary("xscpu64"); 126 } 127 if (message == PreConfig.MACHINE_X64DTV) { 128 System.loadLibrary("x64dtv"); 129 } 130 if (message == PreConfig.MACHINE_X128) { 131 System.loadLibrary("x128"); 132 } 133 if (message == PreConfig.MACHINE_XCBM2) { 134 System.loadLibrary("xcbm2"); 135 } 136 if (message == PreConfig.MACHINE_XCBM5X0) { 137 System.loadLibrary("xcbm5x0"); 138 } 139 if (message == PreConfig.MACHINE_XPET) { 140 System.loadLibrary("xpet"); 141 } 142 if (message == PreConfig.MACHINE_XPLUS4) { 143 System.loadLibrary("xplus4"); 144 } 145 if (message == PreConfig.MACHINE_XVIC) { 146 System.loadLibrary("xvic"); 147 } 148 } 149 } 150 151 nativeSetRomHandling(PreConfig.ROMS_TYPE); 152 153 mSurfaceView = new DosBoxSurfaceView(this); 154 setContentView(mSurfaceView); 155 registerForContextMenu(mSurfaceView); 156 157 DosBoxMenuUtility.loadPreference(this); 158 159 //TODO 160 DosBoxMenuUtility.copyConfigFile(this); 161 162 initDosBox(); 163 startDosBox(); 164 } 165 166 @Override onDestroy()167 protected void onDestroy() { 168 shutDownDosBox(); 169 170 mSurfaceView.shutDown(); 171 mSurfaceView = null; 172 173 super.onDestroy(); 174 } 175 176 @Override onPause()177 protected void onPause() { 178 pauseDosBox(true); 179 super.onPause(); 180 } 181 182 @Override onResume()183 protected void onResume() { 184 super.onResume(); 185 pauseDosBox(false); 186 } 187 188 @Override onConfigurationChanged(Configuration newConfig)189 public void onConfigurationChanged(Configuration newConfig) { 190 super.onConfigurationChanged(newConfig); 191 } 192 193 @Override onCreateOptionsMenu(Menu menu)194 public boolean onCreateOptionsMenu(Menu menu) { 195 super.onCreateOptionsMenu(menu); 196 return DosBoxMenuUtility.doCreateOptionsMenu(menu); 197 } 198 199 @Override onPrepareOptionsMenu(Menu menu)200 public boolean onPrepareOptionsMenu (Menu menu) { 201 super.onPrepareOptionsMenu(menu); 202 return DosBoxMenuUtility.doPrepareOptionsMenu(this, menu); 203 } 204 205 @Override onOptionsItemSelected(MenuItem item)206 public boolean onOptionsItemSelected(MenuItem item) { 207 if (DosBoxMenuUtility.doOptionsItemSelected(this, item)) { 208 return true; 209 } 210 return super.onOptionsItemSelected(item); 211 } 212 213 @Override onMenuOpened(int featureId, Menu menu)214 public boolean onMenuOpened(int featureId, Menu menu) { 215 return super.onMenuOpened(featureId, menu); 216 } 217 218 @Override onOptionsMenuClosed(Menu menu)219 public void onOptionsMenuClosed(Menu menu) { 220 super.onOptionsMenuClosed(menu); 221 } 222 223 @Override onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)224 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { 225 super.onCreateContextMenu(menu, v, menuInfo); 226 DosBoxMenuUtility.doCreateContextMenu(this, menu, v, menuInfo); 227 } 228 229 @Override onContextItemSelected(MenuItem item)230 public boolean onContextItemSelected(MenuItem item) { 231 if (DosBoxMenuUtility.doContextItemSelected(this, item)) { 232 return true; 233 } 234 return super.onOptionsItemSelected(item); 235 } 236 237 @Override onActivityResult(final int requestCode, final int resultCode, final Intent extras)238 protected void onActivityResult(final int requestCode, final int resultCode, final Intent extras) { 239 String path = null; 240 241 if (requestCode == Globals.PREFKEY_F1_INT) { 242 path = (resultCode == RESULT_OK) ? extras.getStringExtra("currentFile") : "/sdcard/df0.adf"; 243 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CHANGE_DISK, 1, path); 244 } else if (requestCode == Globals.PREFKEY_F2_INT) { 245 path = (resultCode == RESULT_OK) ? extras.getStringExtra("currentFile") : "/sdcard/df1.adf"; 246 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CHANGE_DISK, 2, path); 247 } else if (requestCode == Globals.PREFKEY_F3_INT) { 248 path = (resultCode == RESULT_OK) ? extras.getStringExtra("currentFile") : "/sdcard/df2.adf"; 249 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CHANGE_DISK, 3, path); 250 } else if (requestCode == Globals.PREFKEY_F4_INT) { 251 path = (resultCode == RESULT_OK) ? extras.getStringExtra("currentFile") : "/sdcard/df3.adf"; 252 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CHANGE_DISK, 4, path); 253 } 254 } 255 pauseDosBox(boolean pause)256 void pauseDosBox(boolean pause) { 257 if (pause) { 258 mDosBoxThread.mDosBoxRunning = false; 259 nativePause(1); 260 if (mAudioDevice != null) { 261 mAudioDevice.pause(); 262 } 263 } else { 264 nativePause(0); 265 mDosBoxThread.mDosBoxRunning = true; 266 } 267 } 268 initDosBox()269 void initDosBox() { 270 mAudioDevice = new DosBoxAudio(this); 271 272 nativeInit(); 273 274 //TODO 275 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CYCLES, 0, null); 276 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_FRAMESKIP, mPrefFrameskip, null); 277 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_SOUND_ON, (mPrefSoundOn) ? 1 : 0, null); 278 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_SHOW_INFO_ON, (mPrefShowInfoOn) ? 1 : 0, null); 279 { 280 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); 281 String rPath = sp.getString(Globals.PREFKEY_ROM, null); 282 String f1P = sp.getString(Globals.PREFKEY_F1, null); 283 String f2P = sp.getString(Globals.PREFKEY_F2, null); 284 String f3P = sp.getString(Globals.PREFKEY_F3, null); 285 String f4P = sp.getString(Globals.PREFKEY_F4, null); 286 boolean ntsc = sp.getBoolean(PreConfig.PREF_KEY_NTSC_ON, getResources().getBoolean(R.bool.pref_default_ntsc_on)); 287 boolean trueDrive = sp.getBoolean(PreConfig.PREF_KEY_TRUE_DRIVE_ON, getResources().getBoolean(R.bool.pref_default_true_drive_on)); 288 boolean screenBorder = sp.getBoolean(PreConfig.PREF_KEY_SCREEN_BORDER_ON, getResources().getBoolean(R.bool.pref_default_screen_border_on)); 289 290 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_SCREEN_BORDER_ON, (screenBorder) ? 1 : -1, null); 291 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_TRUE_DRIVE_ON, (trueDrive) ? 1 : -1, null); 292 { 293 if (PreConfig.ROMS_TYPE == PreConfig.ROMS_EXTERNAL) { 294 if ((rPath == null) || (rPath.length() == 0)) { 295 /* @VICE_DATA_PATH@ will be replaced during build time with the name of the path for the roms by the android build-script. */ 296 /* @VICE_DATA_FILE@ will be replaced during build time with the name of the kernal by the android build-script. */ 297 rPath = "/sdcard/@VICE_DATA_PATH@/@VICE_DATA_FILE@"; 298 } 299 int pos = rPath.lastIndexOf('/'); 300 if (pos >= 0) { 301 /* @VICE_DATA_PATH@ will be replaced during build time with the name of the path for the roms by the android build-script. */ 302 rPath = rPath.substring(0, pos); // /sdcard/@VICE_DATA_PATH@ 303 } 304 pos = rPath.lastIndexOf('/'); 305 if (pos >= 0) { 306 rPath = rPath.substring(0, pos); // /sdcard 307 } 308 rPath = rPath + "/"; 309 /* @VICE_DATA_PATH@ will be replaced during build time with the name of the path for the roms by the android build-script. */ 310 DosBoxMenuUtility.copyDataFile(this, rPath + "@VICE_DATA_PATH@/"); 311 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CHANGE_ROM, 0, rPath); 312 } 313 } 314 315 //TODO 316 int floppyCount = 4; 317 318 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CHANGE_DISK, -1, (floppyCount >= 1) ? f1P : null); 319 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CHANGE_DISK, -2, (floppyCount >= 1) ? f2P : null); 320 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CHANGE_DISK, -3, (floppyCount >= 1) ? f3P : null); 321 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_CHANGE_DISK, -4, (floppyCount >= 1) ? f4P : null); 322 323 nativeSetOption(DosBoxMenuUtility.DOSBOX_OPTION_ID_NTSC, ntsc ? 1 : 0, null); 324 } 325 mDosBoxThread = new DosBoxThread(this); 326 } 327 shutDownDosBox()328 void shutDownDosBox() { 329 boolean retry; 330 retry = true; 331 while (retry) { 332 try { 333 mDosBoxThread.join(); 334 retry = false; 335 } 336 catch (InterruptedException e) { // try again shutting down the thread 337 } 338 } 339 340 nativeShutDown(); 341 342 if (mAudioDevice != null) { 343 mAudioDevice.shutDownAudio(); 344 mAudioDevice = null; 345 } 346 mDosBoxThread = null; 347 } 348 startDosBox()349 void startDosBox() { 350 if (mDosBoxThread != null) { 351 mDosBoxThread.start(); 352 } 353 354 if ((mSurfaceView != null) && (mSurfaceView.mVideoThread != null)) { 355 mSurfaceView.mVideoThread.start(); 356 } 357 } 358 stopDosBox()359 void stopDosBox() { 360 nativePause(0); //it won't die if not running 361 362 //stop audio AFTER above 363 if (mAudioDevice != null) { 364 mAudioDevice.pause(); 365 } 366 367 mSurfaceView.mVideoThread.setRunning(false); 368 369 nativeStop(); 370 } 371 resetDosBox()372 void resetDosBox() { 373 nativeReset(); 374 } 375 callbackExit()376 public void callbackExit() { 377 if (mDosBoxThread != null) { 378 mDosBoxThread.doExit(); 379 } 380 } 381 callbackVideoRedraw(int w, int h, int s, int e)382 public void callbackVideoRedraw(int w, int h, int s, int e) { 383 mSurfaceView.mSrc_width = w; 384 mSurfaceView.mSrc_height = h; 385 synchronized (mSurfaceView.mDirty) { 386 if (mSurfaceView.mDirty) { 387 mSurfaceView.mStartLine = Math.min(mSurfaceView.mStartLine, s); 388 mSurfaceView.mEndLine = Math.max(mSurfaceView.mEndLine, e); 389 } else { 390 mSurfaceView.mStartLine = s; 391 mSurfaceView.mEndLine = e; 392 } 393 mSurfaceView.mDirty = true; 394 } 395 } 396 callbackVideoSetMode(int w, int h)397 public Bitmap callbackVideoSetMode(int w, int h) { 398 mSurfaceView.mSrc_width = w; 399 mSurfaceView.mSrc_height = h; 400 mSurfaceView.resetScreen(false); 401 Bitmap newBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565); 402 if (newBitmap != null) { 403 mSurfaceView.mBitmap = null; 404 mSurfaceView.mBitmap = newBitmap; 405 406 //locnet, 2011-04-28, support 2.1 or below 407 mSurfaceView.mVideoBuffer = null; 408 mSurfaceView.mVideoBuffer = ByteBuffer.allocateDirect(w * h * 2); 409 410 return mSurfaceView.mBitmap; 411 } 412 return null; 413 } 414 415 //locnet, 2011-04-28, support 2.1 or below callbackVideoGetBuffer()416 public Buffer callbackVideoGetBuffer() { 417 if (mSurfaceView != null) { 418 return mSurfaceView.mVideoBuffer; 419 } else { 420 return null; 421 } 422 } 423 callbackAudioInit(int rate, int channels, int encoding, int bufSize)424 public int callbackAudioInit(int rate, int channels, int encoding, int bufSize) { 425 if (mAudioDevice != null) { 426 return mAudioDevice.initAudio(rate, channels, encoding, bufSize); 427 } else { 428 return 0; 429 } 430 } 431 callbackAudioWriteBuffer(int size)432 public void callbackAudioWriteBuffer(int size) { 433 if (mAudioDevice != null) { 434 mAudioDevice.AudioWriteBuffer(size); 435 } 436 } 437 callbackAudioGetBuffer()438 public short[] callbackAudioGetBuffer() { 439 if (mAudioDevice != null) { 440 return mAudioDevice.mAudioBuffer; 441 } else { 442 return null; 443 } 444 } 445 446 class DosBoxThread extends Thread { 447 DosBoxLauncher mParent; 448 public boolean mDosBoxRunning = false; 449 DosBoxThread(DosBoxLauncher parent)450 DosBoxThread(DosBoxLauncher parent) { 451 mParent = parent; 452 } 453 run()454 public void run() { 455 mDosBoxRunning = true; 456 nativeStart(mSurfaceView.mBitmap, mSurfaceView.mBitmap.getWidth(), mSurfaceView.mBitmap.getHeight()); 457 //will never return to here; 458 } 459 doExit()460 public void doExit() { 461 if (mSurfaceView != null) { 462 InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 463 if (imm != null) { 464 imm.hideSoftInputFromWindow(mSurfaceView.getWindowToken(), 0); 465 } 466 } 467 mDosBoxRunning = false; 468 } 469 } 470 } 471