(Android andretro) get rid of andretro

This commit is contained in:
twinaphex 2013-11-01 07:49:07 +01:00
parent 08305ec877
commit 297be8eb56
72 changed files with 0 additions and 4636 deletions

View File

@ -1,31 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.andretro"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity android:name=".browser.ModuleActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".browser.DirectoryActivity"></activity>
<activity android:name=".RetroDisplay"></activity>
<activity android:name=".settings.SettingActivity"></activity>
<activity android:name=".browser.StateList"></activity>
</application>
</manifest>

View File

@ -1,6 +0,0 @@
Building:
* Put any compiled module libraries in Andretro/jni/modules, the file must be named like libretro_{MODNAME}.so.
* Ensure a matching libretro_{MODNAME}.so.xml exists in the Andretro/assets directory. The xml file contains basic information used by the file browser before the .so itself is loaded.
* In the Andretro directory, run the ndk-build script supplied with the Android NDK.
* In the Andretro directory, run 'ant debug install' to install to the device. The java code can alternatively be built with the included eclipse project.

View File

@ -1,17 +0,0 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.

View File

@ -1,19 +0,0 @@
<retro>
<system fullname="Nintendo Entertainment System" shortname="NES"/>
<module libraryname="FCEUmm" extensions="fds|nes|unif"/>
<input>
<port shortname="p1" fullname="Player 1" defaultdevice="pad">
<device shortname="pad" fullname="Gamepad">
<button shortname="up" fullname="Up" mappedkey="UP"/>
<button shortname="down" fullname="Down" mappedkey="DOWN"/>
<button shortname="left" fullname="Left" mappedkey="LEFT"/>
<button shortname="right" fullname="Right" mappedkey="RIGHT"/>
<button shortname="select" fullname="Select" mappedkey="SELECT"/>
<button shortname="start" fullname="Start" mappedkey="START"/>
<button shortname="b" fullname="B" mappedkey="B"/>
<button shortname="a" fullname="A" mappedkey="A"/>
</device>
</port>
</input>
</retro>

View File

@ -1,28 +0,0 @@
<retro>
<system fullname="Final Burn Alpha" shortname="fba"/>
<module libraryname="FB Alpha" extensions="zip"/>
<input>
<port shortname="p1" fullname="Player 1" defaultdevice="pad">
<device shortname="pad" fullname="Gamepad">
<button shortname="up" fullname="Up" mappedkey="UP"/>
<button shortname="down" fullname="Down" mappedkey="DOWN"/>
<button shortname="left" fullname="Left" mappedkey="LEFT"/>
<button shortname="right" fullname="Right" mappedkey="RIGHT"/>
<button shortname="select" fullname="Select" mappedkey="SELECT"/>
<button shortname="start" fullname="Start" mappedkey="START"/>
<button shortname="b" fullname="B" mappedkey="B"/>
<button shortname="a" fullname="A" mappedkey="A"/>
<button shortname="x" fullname="X" mappedkey="X"/>
<button shortname="y" fullname="Y" mappedkey="Y"/>
<button shortname="l1" fullname="L1" mappedkey="L1"/>
<button shortname="r1" fullname="R1" mappedkey="R1"/>
<button shortname="l2" fullname="L2" mappedkey="L2"/>
<button shortname="r2" fullname="R2" mappedkey="R2"/>
<button shortname="l3" fullname="L3" mappedkey="L3"/>
<button shortname="r3" fullname="R3" mappedkey="R3"/>
</device>
</port>
</input>
</retro>

View File

@ -1,20 +0,0 @@
<retro>
<system fullname="Nintendo Gameboy" shortname="GB"/>
<module libraryname="gambatte" extensions="gb|gbc|dmg"/>
<input>
<port shortname="p1" fullname="Player 1" defaultdevice="pad">
<device shortname="pad" fullname="Gamepad">
<button shortname="up" fullname="Up" mappedkey="UP"/>
<button shortname="down" fullname="Down" mappedkey="DOWN"/>
<button shortname="left" fullname="Left" mappedkey="LEFT"/>
<button shortname="right" fullname="Right" mappedkey="RIGHT"/>
<button shortname="select" fullname="Select" mappedkey="SELECT"/>
<button shortname="start" fullname="Start" mappedkey="START"/>
<button shortname="b" fullname="B" mappedkey="B"/>
<button shortname="a" fullname="A" mappedkey="A"/>
</device>
</port>
</input>
</retro>

View File

@ -1,23 +0,0 @@
<retro>
<system fullname="Sega Genesis/Megadrive" shortname="MD"/>
<module libraryname="Genesis Plus GX" extensions="md|smd|bin|cue|gen|bin|sms|gg|sg"/>
<input>
<port shortname="p1" fullname="Player 1" defaultdevice="pad">
<device shortname="pad" fullname="Gamepad">
<button shortname="up" fullname="Up" mappedkey="UP"/>
<button shortname="down" fullname="Down" mappedkey="DOWN"/>
<button shortname="left" fullname="Left" mappedkey="LEFT"/>
<button shortname="right" fullname="Right" mappedkey="RIGHT"/>
<button shortname="start" fullname="Start" mappedkey="START"/>
<button shortname="a" fullname="A" mappedkey="Y"/>
<button shortname="b" fullname="B" mappedkey="B"/>
<button shortname="c" fullname="C" mappedkey="A"/>
<button shortname="x" fullname="X" mappedkey="L1"/>
<button shortname="y" fullname="Y" mappedkey="X"/>
<button shortname="z" fullname="Z" mappedkey="R1"/>
<button shortname="mode" fullname="Mode" mappedkey="SELECT"/>
</device>
</port>
</input>
</retro>

View File

@ -1,24 +0,0 @@
<retro>
<system fullname="PlayStation1 (PCSX ReARMed)" shortname="PS1"/>
<module libraryname="PCSX ReARMed" extensions="bin|cue|img|mdf|pbp|cbn|toc"/>
<input>
<port shortname="p1" fullname="Player 1" defaultdevice="pad">
<device shortname="pad" fullname="Gamepad">
<button shortname="up" fullname="Up" mappedkey="UP"/>
<button shortname="down" fullname="Down" mappedkey="DOWN"/>
<button shortname="left" fullname="Left" mappedkey="LEFT"/>
<button shortname="right" fullname="Right" mappedkey="RIGHT"/>
<button shortname="select" fullname="Select" mappedkey="SELECT"/>
<button shortname="start" fullname="Start" mappedkey="START"/>
<button shortname="b" fullname="B" mappedkey="B"/>
<button shortname="a" fullname="A" mappedkey="A"/>
<button shortname="x" fullname="X" mappedkey="X"/>
<button shortname="y" fullname="Y" mappedkey="Y"/>
<button shortname="l" fullname="L" mappedkey="L1"/>
<button shortname="r" fullname="R" mappedkey="R1"/>
</device>
</port>
</input>
</retro>

View File

@ -1,29 +0,0 @@
<retro>
<system fullname="DOOM" shortname="doom"/>
<module libraryname="prboom" extensions="wad|iwad"/>
<input>
<port shortname="p1" fullname="Player 1" defaultdevice="pad">
<device shortname="pad" fullname="Gamepad">
<button shortname="up" fullname="Up" mappedkey="UP"/>
<button shortname="down" fullname="Down" mappedkey="DOWN"/>
<button shortname="left" fullname="Left" mappedkey="LEFT"/>
<button shortname="right" fullname="Right" mappedkey="RIGHT"/>
<button shortname="strafeleft" fullname="Strafe Left" mappedkey="L1"/>
<button shortname="straferight" fullname="Strafe Right" mappedkey="R1"/>
<button shortname="fire" fullname="Fire" mappedkey="X"/>
<button shortname="use" fullname="Use" mappedkey="A"/>
<button shortname="run" fullname="Run" mappedkey="Y"/>
<button shortname="strafe" fullname="Strafe" mappedkey="B"/>
<button shortname="menu" fullname="Menu" mappedkey="START"/>
<button shortname="map" fullname="Map" mappedkey="SELECT"/>
<button shortname="prevweapon" fullname="Previous Weapon" mappedkey="L2"/>
<button shortname="nextweapon" fullname="Next Weapon" mappedkey="R2"/>
</device>
</port>
</input>
</retro>

View File

@ -1,24 +0,0 @@
<retro>
<system fullname="Super Nintendo Entertainment System" shortname="SNES"/>
<module libraryname="SNES9x Next" extensions="smc|fig|sfc|gd3|gd7|dx2|bsx|swc"/>
<input>
<port shortname="p1" fullname="Player 1" defaultdevice="pad">
<device shortname="pad" fullname="Gamepad">
<button shortname="up" fullname="Up" mappedkey="UP"/>
<button shortname="down" fullname="Down" mappedkey="DOWN"/>
<button shortname="left" fullname="Left" mappedkey="LEFT"/>
<button shortname="right" fullname="Right" mappedkey="RIGHT"/>
<button shortname="select" fullname="Select" mappedkey="SELECT"/>
<button shortname="start" fullname="Start" mappedkey="START"/>
<button shortname="b" fullname="B" mappedkey="B"/>
<button shortname="a" fullname="A" mappedkey="A"/>
<button shortname="x" fullname="X" mappedkey="X"/>
<button shortname="y" fullname="Y" mappedkey="Y"/>
<button shortname="l" fullname="L" mappedkey="L1"/>
<button shortname="r" fullname="R" mappedkey="R1"/>
</device>
</port>
</input>
</retro>

View File

@ -1,28 +0,0 @@
<retro>
<system fullname="Atari 2600" shortname="a2600"/>
<module libraryname="Stella" extensions="a26|bin"/>
<input>
<port shortname="p1" fullname="Player 1" defaultdevice="pad">
<device shortname="pad" fullname="Gamepad">
<button shortname="up" fullname="Up" mappedkey="UP"/>
<button shortname="down" fullname="Down" mappedkey="DOWN"/>
<button shortname="left" fullname="Left" mappedkey="LEFT"/>
<button shortname="right" fullname="Right" mappedkey="RIGHT"/>
<button shortname="select" fullname="Select" mappedkey="SELECT"/>
<button shortname="start" fullname="Start" mappedkey="START"/>
<button shortname="b" fullname="B" mappedkey="B"/>
<button shortname="a" fullname="A" mappedkey="A"/>
<button shortname="x" fullname="X" mappedkey="X"/>
<button shortname="y" fullname="Y" mappedkey="Y"/>
<button shortname="l1" fullname="L1" mappedkey="L1"/>
<button shortname="r1" fullname="R1" mappedkey="R1"/>
<button shortname="l2" fullname="L2" mappedkey="L2"/>
<button shortname="r2" fullname="R2" mappedkey="R2"/>
<button shortname="l3" fullname="L3" mappedkey="L3"/>
<button shortname="r3" fullname="R3" mappedkey="R3"/>
</device>
</port>
</input>
</retro>

View File

@ -1,22 +0,0 @@
<retro>
<system fullname="Nintendo Gameboy Advance" shortname="GBA"/>
<module libraryname="VBA Next" extensions="gba"/>
<input>
<port shortname="p1" fullname="Player 1" defaultdevice="pad">
<device shortname="pad" fullname="Gamepad">
<button shortname="up" fullname="Up" mappedkey="UP"/>
<button shortname="down" fullname="Down" mappedkey="DOWN"/>
<button shortname="left" fullname="Left" mappedkey="LEFT"/>
<button shortname="right" fullname="Right" mappedkey="RIGHT"/>
<button shortname="select" fullname="Select" mappedkey="SELECT"/>
<button shortname="start" fullname="Start" mappedkey="START"/>
<button shortname="b" fullname="B" mappedkey="B"/>
<button shortname="a" fullname="A" mappedkey="A"/>
<button shortname="l" fullname="L" mappedkey="L1"/>
<button shortname="r" fullname="R" mappedkey="R1"/>
</device>
</port>
</input>
</retro>

View File

@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="andretro" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@ -1,23 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_CPP_FEATURES := exceptions rtti
LOCAL_SRC_FILES = Driver.cpp
LOCAL_MODULE := retroiface
LOCAL_LDLIBS := -llog -lz -lGLESv2
include $(BUILD_SHARED_LIBRARY)
# Include all present sub-modules
FOCAL_PATH := $(LOCAL_PATH)
define function
$(eval RETRO_MODULE_OBJECT := $(1))
$(eval include $(FOCAL_PATH)/modules/Android.mk)
endef
$(foreach m,$(wildcard $(FOCAL_PATH)/modules/*.so),$(eval $(call function,$(m))))

View File

@ -1 +0,0 @@
APP_STL := gnustl_static

View File

@ -1,177 +0,0 @@
#ifndef MJNI_COMMON_H
#define MJNI_COMMON_H
#include <string>
#include <map>
#include <vector>
#include <jni.h>
#include <android/log.h>
#include <fstream>
#include <exception>
#define Log(...) __android_log_print(ANDROID_LOG_INFO, "andretro", __VA_ARGS__);
class FileReader
{
private:
std::vector<uint8_t> data;
public:
FileReader()
{
}
FileReader(const char* aPath)
{
load(aPath);
}
bool load(const char* aPath)
{
close();
// Open new file
if(aPath)
{
FILE* file = fopen(aPath, "rb");
if(file)
{
fseek(file, 0, SEEK_END);
data.resize(ftell(file));
fseek(file, 0, SEEK_SET);
fread(&data[0], data.size(), 1, file);
fclose(file);
return true;
}
}
return false;
}
void close()
{
data.clear();
}
bool isOpen() const
{
return 0 < data.size();
}
const uint8_t* base() const
{
return &data[0];
}
size_t size() const
{
return data.size();
}
};
// Makes no guarantees about aData if read fails!
bool ReadFile(const char* aPath, void* aData, size_t aLength)
{
FILE* file = fopen(aPath, "rb");
if(file)
{
bool result = 1 == fread(aData, aLength, 1, file);
fclose(file);
return result;
}
return false;
}
bool DumpFile(const char* aPath, const void* aData, size_t aLength)
{
FILE* file = fopen(aPath, "wb");
if(file)
{
bool result = 1 == fwrite(aData, aLength, 1, file);
fclose(file);
return result;
}
return false;
}
struct JavaClass
{
std::map<std::string, jfieldID> fields;
JavaClass(JNIEnv* aEnv, jclass aClass, int aFieldCount, const char* const* aNames, const char* const* aSigs)
{
if(!aEnv || !aClass || !aNames || !aSigs || !aFieldCount)
{
throw std::exception();
}
for(int i = 0; i != aFieldCount; i ++)
{
fields[aNames[i]] = aEnv->GetFieldID(aClass, aNames[i], aSigs[i]);
if(fields[aNames[i]] == 0)
{
throw std::exception();
}
}
}
jfieldID operator[](const char* aName)
{
return fields[aName];
}
};
// jstring wrapper
struct JavaChars
{
JNIEnv* env;
jstring string;
const char* chars;
JavaChars(JNIEnv* aEnv, jstring aString)
{
env = aEnv;
string = aString;
chars = env->GetStringUTFChars(string, 0);
}
~JavaChars()
{
env->ReleaseStringUTFChars(string, chars);
}
operator const char*() const
{
return chars;
}
// No copy
private:
JavaChars(const JavaChars&);
JavaChars& operator= (const JavaChars&);
};
// Build a string with checking (later anyway)
inline jstring JavaString(JNIEnv* aEnv, const char* aString)
{
jstring string = aEnv->NewStringUTF(aString ? aString : "(NULL)");
if(string)
{
return string;
}
throw std::exception();
}
#endif

View File

@ -1,558 +0,0 @@
#include <jni.h>
#include <dlfcn.h>
#include <GLES2/gl2.h>
#include <memory>
#include "Common.h"
#include "../../../libretro.h"
#include "Library.h"
#include "Rewinder.h"
namespace
{
Library* module;
FileReader ROM;
Rewinder rewinder;
bool dontProcess;
char* systemDirectory;
JNIEnv* env;
jobject videoFrame;
jint rotation;
retro_system_info systemInfo;
retro_system_av_info avInfo;
std::auto_ptr<JavaClass> avInfo_class;
std::auto_ptr<JavaClass> systemInfo_class;
std::auto_ptr<JavaClass> frame_class;
}
namespace VIDEO
{
typedef void (*andretro_video_refresh)(const void* data, unsigned width, unsigned height, size_t pitch);
unsigned pixelFormat;
template<typename T, int FORMAT, int TYPE>
static void refresh_noconv(const void *data, unsigned width, unsigned height, size_t pitch)
{
const unsigned pixelPitch = pitch / sizeof(T);
if(pixelPitch == width)
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, FORMAT, TYPE, data);
}
else
{
T outPixels[width * height];
T* outPixels_t = outPixels;
const T* inPixels = (const T*)data;
for(int i = 0; i != height; i ++, inPixels += pixelPitch, outPixels_t += width)
{
memcpy(outPixels_t, inPixels, width * sizeof(T));
}
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, FORMAT, TYPE, outPixels);
}
}
// retro_video_refresh for 0RGB1555: deprecated
static void refresh_15(const void *data, unsigned width, unsigned height, size_t pitch)
{
uint16_t outPixels[width * height];
uint16_t* outPixels_t = outPixels;
const uint16_t* inPixels = (const uint16_t*)data;
const unsigned pixelPitch = pitch / 2;
for(int i = 0; i != height; i ++, inPixels += pixelPitch - width)
{
for(int j = 0; j != width; j ++)
{
(*outPixels_t++) = (*inPixels++) << 1;
}
}
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, outPixels);
}
static void retro_video_refresh_imp(const void *data, unsigned width, unsigned height, size_t pitch)
{
if(!dontProcess)
{
static const andretro_video_refresh refreshByMode[3] = {&refresh_15, &refresh_noconv<uint32_t, GL_RGBA, GL_UNSIGNED_BYTE>, &refresh_noconv<uint16_t, GL_RGB, GL_UNSIGNED_SHORT_5_6_5>};
if(data)
{
refreshByMode[pixelFormat](data, width, height, pitch);
}
env->SetIntField(videoFrame, (*frame_class)["width"], width);
env->SetIntField(videoFrame, (*frame_class)["height"], height);
env->SetIntField(videoFrame, (*frame_class)["pixelFormat"], VIDEO::pixelFormat);
env->SetIntField(videoFrame, (*frame_class)["rotation"], rotation);
env->SetFloatField(videoFrame, (*frame_class)["aspect"], avInfo.geometry.aspect_ratio);
}
}
static void createTexture()
{
const GLenum formats[3] = {GL_RGBA, GL_RGBA, GL_RGB};
const GLenum types[3] = {GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5};
if(pixelFormat < 3)
{
glTexImage2D(GL_TEXTURE_2D, 0, formats[pixelFormat], 1024, 1024, 0, formats[pixelFormat], types[pixelFormat], 0);
}
}
}
namespace INPUT
{
jint keyboard[RETROK_LAST];
jint joypads[8];
int16_t touchData[3];
static void retro_input_poll_imp(void)
{
// Joystick
jintArray js = (jintArray)env->GetObjectField(videoFrame, (*frame_class)["buttons"]);
env->GetIntArrayRegion(js, 0, 8, joypads);
// Keyboard
jintArray kbd = (jintArray)env->GetObjectField(videoFrame, (*frame_class)["keyboard"]);
env->GetIntArrayRegion(kbd, 0, RETROK_LAST, keyboard);
// Pointer
touchData[0] = env->GetShortField(videoFrame, (*frame_class)["touchX"]);
touchData[1] = env->GetShortField(videoFrame, (*frame_class)["touchY"]);
touchData[2] = env->GetShortField(videoFrame, (*frame_class)["touched"]) ? 1 : 0;
}
static int16_t retro_input_state_imp(unsigned port, unsigned device, unsigned index, unsigned id)
{
switch(device)
{
case RETRO_DEVICE_JOYPAD: return (joypads[port] >> id) & 1;
case RETRO_DEVICE_KEYBOARD: return (id < RETROK_LAST) ? keyboard[id] : 0;
case RETRO_DEVICE_POINTER: return (id < 3) ? touchData[id] : 0;
}
return 0;
}
}
namespace AUDIO
{
static uint32_t audioLength;
static int16_t buffer[48000];
static inline void prepareFrame()
{
audioLength = 0;
}
static inline void endFrame()
{
if(!dontProcess)
{
jshortArray audioData = (jshortArray)env->GetObjectField(videoFrame, (*frame_class)["audio"]);
env->SetShortArrayRegion(audioData, 0, audioLength, buffer);
env->SetIntField(videoFrame, (*frame_class)["audioSamples"], audioLength);
}
}
static void retro_audio_sample_imp(int16_t left, int16_t right)
{
if(!dontProcess)
{
buffer[audioLength++] = left;
buffer[audioLength++] = right;
}
}
static size_t retro_audio_sample_batch_imp(const int16_t *data, size_t frames)
{
if(!dontProcess)
{
memcpy(&buffer[audioLength], data, frames * 4);
audioLength += frames * 2;
}
return frames;
}
}
// Callbacks
//
// Environment callback. Gives implementations a way of performing uncommon tasks. Extensible.
static bool retro_environment_imp(unsigned cmd, void *data)
{
if(RETRO_ENVIRONMENT_SET_ROTATION == cmd)
{
rotation = (*(unsigned*)data) & 3;
return true;
}
else if(RETRO_ENVIRONMENT_GET_OVERSCAN == cmd)
{
// TODO: true causes snes9x-next to shit a brick
*(uint8_t*)data = false;
return true;
}
else if(RETRO_ENVIRONMENT_GET_CAN_DUPE == cmd)
{
*(uint8_t*)data = true;
return true;
}
else if(RETRO_ENVIRONMENT_GET_VARIABLE == cmd)
{
// TODO
return false;
}
else if(RETRO_ENVIRONMENT_SET_VARIABLES == cmd)
{
// HACK
return false;
}
else if(RETRO_ENVIRONMENT_SET_MESSAGE == cmd)
{
// TODO
return false;
}
else if(RETRO_ENVIRONMENT_SHUTDOWN == cmd)
{
// TODO
return false;
}
else if(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL == cmd)
{
// TODO
return false;
}
else if(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY == cmd)
{
*(const char**)data = systemDirectory;
return true;
}
else if(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT == cmd)
{
unsigned newFormat = *(unsigned*)data;
if(newFormat < 3 && newFormat != 1)
{
VIDEO::pixelFormat = newFormat;
VIDEO::createTexture();
return true;
}
return false;
}
return false;
}
//
#define JNIFUNC(RET, FUNCTION) extern "C" RET Java_org_libretro_LibRetro_ ## FUNCTION
#define JNIARGS JNIEnv* aEnv, jclass aClass
JNIFUNC(jboolean, loadLibrary)(JNIARGS, jstring path, jstring systemDir)
{
JavaChars libname(aEnv, path);
delete module;
module = 0;
try
{
module = new Library(libname);
systemDirectory = strdup(JavaChars(aEnv, systemDir));
chdir(systemDirectory);
return true;
}
catch(...)
{
return false;
}
}
JNIFUNC(void, unloadLibrary)(JNIARGS)
{
delete module;
module = 0;
free(systemDirectory);
systemDirectory = 0;
memset(&systemInfo, 0, sizeof(systemInfo));
rotation = 0;
}
JNIFUNC(void, init)(JNIARGS)
{
module->set_environment(retro_environment_imp);
VIDEO::pixelFormat = 0;
VIDEO::createTexture();
module->init();
module->get_system_info(&systemInfo);
}
JNIFUNC(void, deinit)(JNIARGS)
{
module->deinit();
}
JNIFUNC(jint, apiVersion)(JNIARGS)
{
return module->api_version();
}
JNIFUNC(void, getSystemInfo)(JNIARGS, jobject aSystemInfo)
{
aEnv->SetObjectField(aSystemInfo, (*systemInfo_class)["libraryName"], JavaString(aEnv, systemInfo.library_name));
aEnv->SetObjectField(aSystemInfo, (*systemInfo_class)["libraryVersion"], JavaString(aEnv, systemInfo.library_version));
aEnv->SetObjectField(aSystemInfo, (*systemInfo_class)["validExtensions"], JavaString(aEnv, systemInfo.valid_extensions));
aEnv->SetBooleanField(aSystemInfo, (*systemInfo_class)["needFullPath"], systemInfo.need_fullpath);
aEnv->SetBooleanField(aSystemInfo, (*systemInfo_class)["blockExtract"], systemInfo.block_extract);
}
JNIFUNC(void, getSystemAVInfo)(JNIARGS, jobject aAVInfo)
{
aEnv->SetIntField(aAVInfo, (*avInfo_class)["baseWidth"], avInfo.geometry.base_width);
aEnv->SetIntField(aAVInfo, (*avInfo_class)["baseHeight"], avInfo.geometry.base_height);
aEnv->SetIntField(aAVInfo, (*avInfo_class)["maxWidth"], avInfo.geometry.max_width);
aEnv->SetIntField(aAVInfo, (*avInfo_class)["maxHeight"], avInfo.geometry.max_height);
aEnv->SetFloatField(aAVInfo, (*avInfo_class)["aspectRatio"], avInfo.geometry.aspect_ratio);
aEnv->SetDoubleField(aAVInfo, (*avInfo_class)["fps"], avInfo.timing.fps);
aEnv->SetDoubleField(aAVInfo, (*avInfo_class)["sampleRate"], avInfo.timing.sample_rate);
}
JNIFUNC(void, setControllerPortDevice)(JNIARGS, jint port, jint device)
{
module->set_controller_port_device(port, device);
}
JNIFUNC(void, reset)(JNIARGS)
{
module->reset();
}
JNIFUNC(void, run)(JNIARGS, jobject aVideo)
{
// TODO
env = aEnv;
videoFrame = aVideo;
if(env->GetBooleanField(videoFrame, (*frame_class)["restarted"]))
{
VIDEO::createTexture();
env->SetBooleanField(videoFrame, (*frame_class)["restarted"], false);
}
const int count = env->GetIntField(videoFrame, (*frame_class)["framesToRun"]);
const bool rewind = env->GetBooleanField(videoFrame, (*frame_class)["rewind"]);
for(int i = 0; i < count; i ++)
{
dontProcess = !(i == (count - 1));
const bool rewound = rewind && rewinder.eatFrame(module);
if(!rewind || rewound)
{
AUDIO::prepareFrame();
module->run();
AUDIO::endFrame();
if(!rewind)
{
rewinder.stashFrame(module);
}
}
}
}
JNIFUNC(jint, serializeSize)(JNIARGS)
{
return module->serialize_size();
}
JNIFUNC(void, cheatReset)(JNIARGS)
{
module->cheat_reset();
}
JNIFUNC(void, cheatSet)(JNIARGS, jint index, jboolean enabled, jstring code)
{
JavaChars codeN(aEnv, code);
module->cheat_set(index, enabled, codeN);
}
JNIFUNC(bool, loadGame)(JNIARGS, jstring path)
{
JavaChars fileName(aEnv, path);
retro_game_info info = {fileName, 0, 0, 0};
if(!systemInfo.need_fullpath)
{
if(ROM.load(fileName))
{
info.data = ROM.base();
info.size = ROM.size();
}
else
{
return false;
}
}
if(module->load_game(&info))
{
module->get_system_av_info(&avInfo);
module->set_video_refresh(VIDEO::retro_video_refresh_imp);
module->set_audio_sample(AUDIO::retro_audio_sample_imp);
module->set_audio_sample_batch(AUDIO::retro_audio_sample_batch_imp);
module->set_input_poll(INPUT::retro_input_poll_imp);
module->set_input_state(INPUT::retro_input_state_imp);
rewinder.gameLoaded(module);
return true;
}
return false;
}
JNIFUNC(void, unloadGame)(JNIARGS)
{
module->unload_game();
memset(&avInfo, 0, sizeof(avInfo));
ROM.close();
}
JNIFUNC(jint, getRegion)(JNIARGS)
{
return module->get_region();
}
JNIFUNC(jobject, getMemoryData)(JNIARGS, int aID)
{
void* const memoryData = module->get_memory_data(aID);
const size_t memorySize = module->get_memory_size(aID);
return (memoryData && memorySize) ? aEnv->NewDirectByteBuffer(memoryData, memorySize) : 0;
}
JNIFUNC(int, getMemorySize)(JNIARGS, int aID)
{
return module->get_memory_size(aID);
}
// Extensions: Rewinder
JNIFUNC(void, setupRewinder)(JNIARGS, int aSize)
{
rewinder.setSize(aSize);
}
// Extensions: Read or write a memory region into a specified file.
JNIFUNC(jboolean, writeMemoryRegion)(JNIARGS, int aID, jstring aFileName)
{
const size_t size = module->get_memory_size(aID);
void* const data = module->get_memory_data(aID);
if(size && data)
{
DumpFile(JavaChars(aEnv, aFileName), data, size);
}
return true;
}
JNIFUNC(jboolean, readMemoryRegion)(JNIARGS, int aID, jstring aFileName)
{
const size_t size = module->get_memory_size(aID);
void* const data = module->get_memory_data(aID);
if(size && data)
{
ReadFile(JavaChars(aEnv, aFileName), data, size);
}
return true;
}
// Extensions: Serialize/Unserialize using a file
JNIFUNC(jboolean, serializeToFile)(JNIARGS, jstring aPath)
{
const size_t size = module->serialize_size();
if(size > 0)
{
uint8_t buffer[size];
if(module->serialize(buffer, size))
{
return DumpFile(JavaChars(aEnv, aPath), buffer, size);
}
}
return false;
}
JNIFUNC(jboolean, unserializeFromFile)(JNIARGS, jstring aPath)
{
const size_t size = module->serialize_size();
if(size > 0)
{
uint8_t buffer[size];
if(ReadFile(JavaChars(aEnv, aPath), buffer, size))
{
return module->unserialize(buffer, size);
}
}
return false;
}
// Preload native class data
JNIFUNC(jboolean, nativeInit)(JNIARGS)
{
try
{
{
static const char* const n[] = {"libraryName", "libraryVersion", "validExtensions", "needFullPath", "blockExtract"};
static const char* const s[] = {"Ljava/lang/String;", "Ljava/lang/String;", "Ljava/lang/String;", "Z", "Z"};
systemInfo_class.reset(new JavaClass(aEnv, aEnv->FindClass("org/libretro/LibRetro$SystemInfo"), sizeof(n) / sizeof(n[0]), n, s));
}
{
static const char* const n[] = {"baseWidth", "baseHeight", "maxWidth", "maxHeight", "aspectRatio", "fps", "sampleRate"};
static const char* const s[] = {"I", "I", "I", "I", "F", "D", "D"};
avInfo_class.reset(new JavaClass(aEnv, aEnv->FindClass("org/libretro/LibRetro$AVInfo"), sizeof(n) / sizeof(n[0]), n, s));
}
{
static const char* const n[] = {"restarted", "framesToRun", "rewind", "width", "height", "pixelFormat", "rotation", "aspect", "keyboard", "buttons", "touchX", "touchY", "touched", "audio", "audioSamples"};
static const char* const s[] = {"Z", "I", "Z", "I", "I", "I", "I", "F", "[I", "[I", "S", "S", "Z", "[S", "I"};
frame_class.reset(new JavaClass(aEnv, aEnv->FindClass("org/libretro/LibRetro$VideoFrame"), sizeof(n) / sizeof(n[0]), n, s));
}
return true;
}
catch(...)
{
return false;
}
}

View File

@ -1,109 +0,0 @@
#ifndef RETRO_LIB_HHH
#define RETRO_LIB_HHH
#include <dlfcn.h>
#include <exception>
#include <android/log.h>
#include "../../../libretro.h"
#define LOG(...) __android_log_print(ANDROID_LOG_ERROR, "Andretro", __VA_ARGS__)
class Library
{
public:
Library(const char* aPath) :
handle(openLib(aPath)),
set_environment((void (*)(retro_environment_t))getFn("retro_set_environment")),
set_video_refresh((void (*)(retro_video_refresh_t))getFn("retro_set_video_refresh")),
set_audio_sample((void (*)(retro_audio_sample_t))getFn("retro_set_audio_sample")),
set_audio_sample_batch((void (*)(retro_audio_sample_batch_t))getFn("retro_set_audio_sample_batch")),
set_input_poll((void (*)(retro_input_poll_t))getFn("retro_set_input_poll")),
set_input_state((void (*)(retro_input_state_t))getFn("retro_set_input_state")),
init((void (*)(void))getFn("retro_init")),
deinit((void (*)(void))getFn("retro_deinit")),
api_version((unsigned (*)(void))getFn("retro_api_version")),
get_system_info((void (*)(struct retro_system_info *info))getFn("retro_get_system_info")),
get_system_av_info((void (*)(struct retro_system_av_info *info))getFn("retro_get_system_av_info")),
set_controller_port_device((void (*)(unsigned port, unsigned device))getFn("retro_set_controller_port_device")),
reset((void (*)(void))getFn("retro_reset")),
run((void (*)(void))getFn("retro_run")),
serialize_size((size_t (*)(void))getFn("retro_serialize_size")),
serialize((bool (*)(void *data, size_t size))getFn("retro_serialize")),
unserialize((bool (*)(const void *data, size_t size))getFn("retro_unserialize")),
cheat_reset((void (*)(void))getFn("retro_cheat_reset")),
cheat_set((void (*)(unsigned index, bool enabled, const char *code))getFn("retro_cheat_set")),
load_game((bool (*)(const struct retro_game_info *game))getFn("retro_load_game")),
load_game_special((bool (*)(unsigned game_type,const struct retro_game_info *info, size_t num_info))getFn("retro_load_game_special")),
unload_game((void (*)(void))getFn("retro_unload_game")),
get_region((unsigned (*)(void))getFn("retro_get_region")),
get_memory_data((void *(*)(unsigned id))getFn("retro_get_memory_data")),
get_memory_size((size_t (*)(unsigned id))getFn("retro_get_memory_size"))
{
}
~Library()
{
if(handle)
{
dlclose(handle);
}
}
void* const handle;
void (* const set_environment)(retro_environment_t);
void (* const set_video_refresh)(retro_video_refresh_t);
void (* const set_audio_sample)(retro_audio_sample_t);
void (* const set_audio_sample_batch)(retro_audio_sample_batch_t);
void (* const set_input_poll)(retro_input_poll_t);
void (* const set_input_state)(retro_input_state_t);
void (* const init)(void);
void (* const deinit)(void);
unsigned (* const api_version)(void);
void (* const get_system_info)(struct retro_system_info *info);
void (* const get_system_av_info)(struct retro_system_av_info *info);
void (* const set_controller_port_device)(unsigned port, unsigned device);
void (* const reset)(void);
void (* const run)(void);
size_t (* const serialize_size)(void);
bool (* const serialize)(void *data, size_t size);
bool (* const unserialize)(const void *data, size_t size);
void (* const cheat_reset)(void);
void (* const cheat_set)(unsigned index, bool enabled, const char *code);
bool (* const load_game)(const struct retro_game_info *game);
bool (* const load_game_special)(unsigned game_type,const struct retro_game_info *info, size_t num_info);
void (* const unload_game)(void);
unsigned (* const get_region)(void);
void *(* const get_memory_data)(unsigned id);
size_t (* const get_memory_size)(unsigned id);
private:
void* openLib(const char* aPath)
{
void* result = dlopen(aPath, RTLD_NOW | RTLD_LOCAL);
if(!result)
{
LOG("openLib failed: %s\n", dlerror());
throw std::exception();
}
return result;
}
void* getFn(const char* aName)
{
void* result = dlsym(handle, aName);
if(!result)
{
LOG("getFn failed: %s\n", dlerror());
throw std::exception();
}
return result;
}
};
#endif

View File

@ -1,118 +0,0 @@
#ifndef ANDRETRO_REWINDER_H
#define ANDRETRO_REWINDER_H
#include <vector>
#include <deque>
#include <stdint.h>
#include <zlib.h>
#include "Library.h"
#include "Common.h"
class Rewinder
{
struct Frame
{
Frame(uint32_t aLocation, uint32_t aSize) :
location(aLocation), size(aSize)
{
}
bool overlaps(const Frame& aOther) const
{
const uint32_t myLow = location;
const uint32_t myHigh = location + size;
const uint32_t yourLow = aOther.location;
const uint32_t yourHigh = aOther.location + aOther.size;
return (myLow < yourHigh && yourLow < myHigh);
}
uint32_t location;
uint32_t size;
};
std::vector<uint8_t> data;
std::vector<uint8_t> buffer;
std::vector<uint8_t> compressBuffer;
uint32_t nextFrame;
std::deque<Frame> frames;
public:
Rewinder() :
data(0), buffer(0), nextFrame(0)
{
}
void gameLoaded(const Library* aModule)
{
buffer.resize(aModule->serialize_size());
compressBuffer.resize(compressBound(aModule->serialize_size()));
nextFrame = 0;
frames.clear();
}
void setSize(int aSize)
{
data.resize((aSize >= 0) ? aSize : 0);
nextFrame = 0;
frames.clear();
}
void stashFrame(const Library* aModule)
{
if(buffer.size() && data.size())
{
if(aModule->serialize(&buffer[0], buffer.size()))
{
uLongf len = compressBuffer.size();
if(Z_OK == compress(&compressBuffer[0], &len, &buffer[0], buffer.size()))
{
nextFrame = ((data.size() - nextFrame) < len) ? 0 : nextFrame;
memcpy(&data[nextFrame], &compressBuffer[0], len);
// Add to list
frames.push_back(Frame(nextFrame, len));
nextFrame += len;
// Remove any dead entries from the list
while((frames.size() > 1) && frames.front().overlaps(frames.back()))
{
frames.pop_front();
}
}
}
}
}
bool eatFrame(const Library* aModule)
{
if(buffer.size() && data.size())
{
if(!frames.empty())
{
const Frame loadFrame = frames.back();
frames.pop_back();
nextFrame = loadFrame.location;
uLongf len = buffer.size();
if(Z_OK == uncompress(&buffer[0], &len, &data[loadFrame.location], loadFrame.size))
{
return aModule->unserialize(&buffer[0], buffer.size());
}
}
else
{
return false;
}
}
return true;
}
};
#endif

View File

@ -1,6 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := $(notdir $(RETRO_MODULE_OBJECT))
LOCAL_SRC_FILES := $(notdir $(RETRO_MODULE_OBJECT))
include $(PREBUILT_SHARED_LIBRARY)

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="UseCompoundDrawables">
<ignore path="res/layout/directory_list_item.xml" />
</issue>
</lint>

View File

@ -1,20 +0,0 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -1,14 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-16

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/hack_message"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:inputType="text" >
</EditText>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="@+id/icon"
android:layout_width="192dp"
android:layout_height="192dp"
android:layout_gravity="center"
android:contentDescription="@string/file_type_icon"
android:padding="8dp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="0.5"
android:textSize="18sp" />
</LinearLayout>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="2" >
</GridView>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="48dp">
<ImageView
android:id="@+id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="@string/file_type_icon"
android:padding="8dp" />
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="0.5"
android:textSize="18sp" />
</LinearLayout>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<org.andretro.input.view.InputGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/base"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<android.opengl.GLSurfaceView
android:id="@+id/renderer"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.opengl.GLSurfaceView>
</org.andretro.input.view.InputGroup>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/goto_root" android:title="@string/root_directory" android:showAsAction="always"></item>
<item android:id="@+id/input_method_select" android:title="@string/input_method" android:showAsAction="ifRoom"></item>
<item android:id="@+id/system_settings" android:title="@string/system_settings"></item>
</menu>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/save_state" android:title="@string/save_state"></item>
<item android:id="@+id/load_state" android:title="@string/load_state"></item>
<item android:id="@+id/reset" android:title="@string/reset"></item>
<item android:id="@+id/input_method_select" android:title="@string/input_method" android:showAsAction="always"></item>
<item android:id="@+id/system_settings" android:title="@string/system_settings"></item>
<item android:id="@+id/show_on_screen_input" android:checkable="true" android:title="@string/show_on_screen_input" android:checked="true"></item>
<item android:id="@+id/screenshot" android:title="@string/screenshot"></item>
<item android:id="@+id/pause" android:title="@string/pause" android:checkable="true" android:checked="false"></item>
</menu>

View File

@ -1,7 +0,0 @@
<group>
<ButtonDiamond horzanchor="left" vertanchor="bottom" horzmargin="20" vertmargin="20" width="200" height="200" upbits="16" downbits="32" leftbits="64" rightbits="128"/>
<ButtonDiamond horzanchor="right" vertanchor="bottom" horzmargin="20" vertmargin="20" width="200" height="200" upbits="512" downbits="1" leftbits="2" rightbits="256" />
<ButtonDuo horzanchor="center" vertanchor="bottom" horzmargin="20" vertmargin="20" width="200" height="50" leftbits="4" rightbits="8"/>
<Button horzanchor="right" vertanchor="top" horzmargin="20" vertmargin="20" width="50" height="50" bits="2048" />
<Button horzanchor="left" vertanchor="top" horzmargin="20" vertmargin="20" width="50" height="50" bits="1024" />
</group>

View File

@ -1,9 +0,0 @@
precision mediump float;
varying vec2 texCoord;
uniform sampler2D texUnit;
void main()
{
gl_FragColor = texture2D(texUnit, texCoord);
}

View File

@ -1,14 +0,0 @@
attribute vec2 pos;
attribute vec2 tex;
varying vec2 texCoord;
void main()
{
gl_Position.x = pos.x;
gl_Position.y = pos.y;
gl_Position.z = 0.0;
gl_Position.w = 1.0;
texCoord = tex;
}

View File

@ -1,26 +0,0 @@
<resources>
<string name="app_name">Andretro</string>
<string name="load_state">Load State</string>
<string name="save_state">Save State</string>
<string name="reset">Reset</string>
<string name="root_directory">SD Card Root</string>
<string name="input_settings">Input Settings</string>
<string name="input_method">Input Method</string>
<string name="show_on_screen_input">On Screen Input</string>
<string name="system_settings">System Settings</string>
<string-array name="aspect_mode_values">
<item >Default</item>
<item >4:3</item>
<item >Pixel Aspect</item>
</string-array>
<string-array name="orientation_modes">
<item >Sensor</item>
<item >Landscape</item>
<item >Portrait</item>
</string-array>
<string name="file_type_icon">File type icon</string>
<string name="screenshot">Take Screenshot</string>
<string name="pause">Pause</string>
</resources>

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Fast Forward">
<org.andretro.settings.ButtonSetting android:title="Fast Forward Key" android:key="fast_forward_key" android:persistent="true" android:defaultValue="69"/>
<EditTextPreference android:title="Fast Forward Speed" android:key="fast_forward_speed" android:summary="Multiplier for fast forward mode." android:defaultValue="4" android:persistent="true"/>
<CheckBoxPreference android:title="Use Fast Forward Mode By Default" android:key="fast_forward_default" android:summary="The toggle button will run the game at normal speed." android:persistent="true" android:defaultValue="false"/>
</PreferenceCategory>
<PreferenceCategory android:title="Rewind">
<org.andretro.settings.ButtonSetting android:title="Rewind Key" android:key="rewind_key" android:persistent="true" android:defaultValue="68"/>
<CheckBoxPreference android:title="Enable Population of the Rewind Buffer" android:key="rewind_enabled" android:summary="Will use memory and processor resources." android:persistent="true" android:defaultValue="false"/>
<EditTextPreference android:title="Size of the Rewind Buffer" android:key="rewind_buffer_size" android:summary="Size is in megabytes." android:defaultValue="16" android:persistent="true"/>
</PreferenceCategory>
<PreferenceCategory android:title="Scaling">
<CheckBoxPreference android:title="Linear Filtering" android:persistent="true" android:key="scaling_smooth" android:summary="Use a smoothing effect when scaling the image." android:defaultValue="true"/>
<ListPreference android:defaultValue="Default" android:entryValues="@array/aspect_mode_values" android:summary="Force an aspect ratio on the game's image." android:persistent="true" android:title="Aspect Ratio" android:key="scaling_aspect_mode" android:entries="@array/aspect_mode_values"/>
<ListPreference android:key="scaling_orientation" android:title="Orientation" android:summary="Force a screen orientation" android:persistent="true" android:defaultValue="Sensor" android:entryValues="@array/orientation_modes" android:entries="@array/orientation_modes"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@ -1,81 +0,0 @@
package org.andretro;
import android.content.*;
import android.os.*;
import android.app.*;
public class QuestionDialog extends android.support.v4.app.DialogFragment
{
public interface QuestionHandler
{
void onAnswer(int aID, QuestionDialog aDialog, boolean aPositive);
}
/**
* Build a question dialog with the specified strings.
*
* @param aID The ID to pass to callback.
* @param aTitle The title of the dialog.
* @param aMessage The message to display in the dialog.
* @param aPositive The text on the positive button of the dialog.
* @param aNegative The text on the negative button of the dialog.
* @return The dialog.
*/
public static QuestionDialog newInstance(int aID, String aTitle, String aMessage, String aPositive, String aNegative, Bundle aUserData)
{
// Create the output
QuestionDialog result = new QuestionDialog();
// Fill the details
Bundle args = new Bundle();
args.putInt("id", aID);
args.putString("title", aTitle);
args.putString("message", aMessage);
args.putString("positive", aPositive);
args.putString("negative", aNegative);
args.putBundle("userdata", aUserData);
result.setArguments(args);
// Done
return result;
}
Bundle getUserData()
{
return getArguments().getBundle("userdata");
}
@Override public Dialog onCreateDialog(Bundle aState)
{
final Bundle args = getArguments();
final int id = args.getInt("id");
// TODO: Use string resources
AlertDialog result = new AlertDialog.Builder(getActivity())
.setTitle(args.getString("title"))
.setMessage(args.getString("message"))
.setPositiveButton(args.getString("positive"), new DialogInterface.OnClickListener()
{
@Override public void onClick(DialogInterface UNUSED, int aWhich)
{
((QuestionHandler)getActivity()).onAnswer(id, QuestionDialog.this, true);
}
})
.setNegativeButton(args.getString("negative"), new DialogInterface.OnClickListener()
{
@Override public void onClick(DialogInterface UNUSED, int aWhich)
{
((QuestionHandler)getActivity()).onAnswer(id, QuestionDialog.this, false);
}
})
.create();
return result;
}
@Override public void onCancel(DialogInterface aDialog)
{
((QuestionHandler)getActivity()).onAnswer(getArguments().getInt("id"), QuestionDialog.this, false);
super.onCancel(aDialog);
}
}

View File

@ -1,225 +0,0 @@
package org.andretro;
import org.andretro.browser.*;
import org.andretro.emulator.*;
import org.andretro.settings.*;
import org.andretro.system.*;
import org.andretro.system.video.*;
import java.io.*;
import android.view.*;
import android.view.inputmethod.*;
import android.opengl.*;
import android.os.*;
import android.content.*;
import android.widget.*;
import android.graphics.*;
public class RetroDisplay extends android.support.v4.app.FragmentActivity implements QuestionDialog.QuestionHandler
{
private static final int CLOSE_GAME_QUESTION = 1;
private WindowManager windowManager;
GLSurfaceView view;
private boolean questionOpen;
private boolean isPaused;
private boolean showActionBar;
private String moduleName;
ModuleInfo moduleInfo;
@Override public void onCreate(Bundle aState)
{
super.onCreate(aState);
// Setup window
windowManager = WindowManager.createBest();
windowManager.setActivity(this);
windowManager.windowCreating();
// Read state
questionOpen = (null == aState) ? false : aState.getBoolean("questionOpen", false);
windowManager.setOnScreenInput((null == aState) ? true : aState.getBoolean("onScreenInput", true));
isPaused = (null == aState) ? false : aState.getBoolean("isPaused", false);
showActionBar = (null == aState) ? true : aState.getBoolean("showActionBar", true);
moduleName = getIntent().getStringExtra("moduleName");
moduleInfo = ModuleInfo.getInfoAbout(this, new File(moduleName));
// Setup the view
setContentView(R.layout.retro_display);
view = (GLSurfaceView)findViewById(R.id.renderer);
view.setEGLContextClientVersion(2);
view.setRenderer(Present.createRenderer(this));
view.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
view.setKeepScreenOn(true);
if(!Game.hasGame())
{
Game.queueCommand(new Commands.LoadGame(this, moduleName, new File(getIntent().getStringExtra("path"))));
}
windowManager.windowCreated();
}
@Override public void onResume()
{
super.onResume();
windowManager.setupDisplay();
view.onResume();
}
@Override public void onPause()
{
super.onPause();
view.onPause();
}
// QuestionDialog.QuestionHandler
@Override public void onAnswer(int aID, QuestionDialog aDialog, boolean aPositive)
{
if(CLOSE_GAME_QUESTION == aID && questionOpen)
{
Game.queueCommand(new Commands.Pause(false));
if(aPositive)
{
Game.queueCommand(new Commands.CloseGame().setCallback(new CommandQueue.Callback(this, new Runnable()
{
@Override public void run()
{
System.exit(0);
}
})));
}
questionOpen = false;
windowManager.setupDisplay();
}
}
@Override public boolean dispatchTouchEvent(MotionEvent aEvent)
{
if(aEvent.getActionMasked() == MotionEvent.ACTION_DOWN)
{
windowManager.screenTouched(aEvent);
}
// if(aEvent.getActionMasked() == MotionEvent.ACTION_DOWN || aEvent.getActionMasked() == MotionEvent.ACTION_MOVE)
// {
// final Rect imageArea = VertexData.getImageArea();
//
// final float xBase = (float)(aEvent.getX() - imageArea.left) / (float)imageArea.width();
// final float yBase = (float)(aEvent.getY() - imageArea.top) / (float)imageArea.height();
//
// Input.setTouchData((short)(((xBase - .5f) * 2.0f) * 32767.0f), (short)(((yBase - .5f) * 2.0f) * 32767.0f), true);
// }
// else if(aEvent.getActionMasked() == MotionEvent.ACTION_UP)
// {
// Input.setTouchData((short)0, (short)0, false);
// }
return super.dispatchTouchEvent(aEvent);
}
@Override public boolean dispatchKeyEvent(KeyEvent aEvent)
{
int keyCode = aEvent.getKeyCode();
// Keys to never handle as game input
if(keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_MENU)
{
return super.dispatchKeyEvent(aEvent);
}
// Update game input structure
Input.processEvent(aEvent);
return true;
}
@Override public void onBackPressed()
{
if(Game.hasGame())
{
if(!questionOpen)
{
Game.queueCommand(new Commands.Pause(true));
QuestionDialog.newInstance(CLOSE_GAME_QUESTION, "Really Close Game?", "All unsaved data will be lost.", "Yes", "No", null).show(getSupportFragmentManager(), "mainfragment");
questionOpen = true;
}
}
else
{
System.exit(0);
}
}
@Override protected void onSaveInstanceState(Bundle aState)
{
super.onSaveInstanceState(aState);
aState.putBoolean("questionOpen", questionOpen);
aState.putBoolean("onScreenInput", windowManager.getOnScreenInput());
aState.putBoolean("onPause", isPaused);
aState.putBoolean("showActionBar", showActionBar);
}
// Menu
@Override public boolean onCreateOptionsMenu(Menu aMenu)
{
super.onCreateOptionsMenu(aMenu);
getMenuInflater().inflate(R.menu.retro_display, aMenu);
aMenu.findItem(R.id.show_on_screen_input).setChecked(windowManager.getOnScreenInput());
aMenu.findItem(R.id.pause).setChecked(isPaused);
return true;
}
private void runCommandWithText(CommandQueue.BaseCommand aCommand, final String aText)
{
Game.queueCommand(aCommand.setCallback(new CommandQueue.Callback(this, new Runnable()
{
@Override public void run()
{
Toast.makeText(getApplicationContext(), aText, Toast.LENGTH_SHORT).show();
}
}
)));
}
@Override public boolean onOptionsItemSelected(MenuItem aItem)
{
int itemID = aItem.getItemId();
switch(itemID)
{
case R.id.show_on_screen_input:
{
windowManager.setOnScreenInput(!aItem.isChecked());
aItem.setChecked(windowManager.getOnScreenInput());
return true;
}
case R.id.pause:
{
isPaused = !isPaused;
aItem.setChecked(isPaused);
runCommandWithText(new Commands.Pause(isPaused), "Game " + (isPaused ? "Paused" : "Unpaused"));
return true;
}
case R.id.input_method_select: ((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE)).showInputMethodPicker(); return true;
case R.id.screenshot: runCommandWithText(new Commands.TakeScreenShot(), "Screenshot Saved"); return true;
case R.id.reset: runCommandWithText(new Commands.Reset(), "Game Reset"); return true;
case R.id.save_state: startActivity(new Intent(this, StateList.class).putExtra("moduleName", moduleName).putExtra("loading", false)); return true;
case R.id.load_state: startActivity(new Intent(this, StateList.class).putExtra("moduleName", moduleName).putExtra("loading", true)); return true;
case R.id.system_settings: startActivity(new Intent(this, SettingActivity.class).putExtra("moduleName", moduleName)); return true;
default: return super.onOptionsItemSelected(aItem);
}
}
}

View File

@ -1,224 +0,0 @@
package org.andretro;
import org.andretro.input.view.*;
import org.andretro.system.*;
import android.annotation.*;
import android.app.*;
import android.view.*;
abstract class WindowManager
{
protected RetroDisplay activity;
protected boolean onScreenInput = true;
private boolean windowCreated;
public void setOnScreenInput(boolean aState)
{
if(onScreenInput != aState)
{
onScreenInput = aState;
if(windowCreated)
{
setupDisplay();
}
}
}
public boolean getOnScreenInput()
{
return onScreenInput;
}
public void setActivity(RetroDisplay aActivity)
{
activity = aActivity;
}
/**
* Called to set any paramters that need to be set before the window is created.
*/
public void windowCreating() { }
public void windowCreated()
{
windowCreated = true;
}
public void screenTouched(MotionEvent aEvent) { }
public void setupDisplay()
{
InputGroup inputBase = (InputGroup)activity.findViewById(R.id.base);
inputBase.removeChildren();
if(onScreenInput)
{
inputBase.loadInputLayout(activity, activity.moduleInfo, activity.getResources().openRawResource(R.raw.default_retro_pad));
}
Input.setOnScreenInput(onScreenInput ? inputBase : null);
}
static public WindowManager createBest()
{
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
{
return new WindowManager_JellyBean();
}
else if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
{
return new WindowManager_IceCreamSandwich();
}
else
{
return new WindowManager_GingerBread();
}
}
}
class WindowManager_GingerBread extends WindowManager
{
@Override public void windowCreating()
{
super.windowCreating();
activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
}
@TargetApi(11) class WindowManager_ICSBase extends WindowManager
{
protected boolean uiFullscreen = false;
protected int uiFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
@Override public void windowCreating()
{
super.windowCreating();
activity.requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
}
@Override public void setupDisplay()
{
super.setupDisplay();
activity.view.setSystemUiVisibility(uiFlags);
}
protected void setActionBarState()
{
final ActionBar bar = activity.getActionBar();
if(null != bar && !uiFullscreen)
{
bar.show();
}
else if(null != bar && uiFullscreen)
{
bar.hide();
}
}
protected boolean touchedOverActionBar(float aY)
{
final float barSize = 82.0f;
return aY <= barSize;
}
protected boolean toggleFullscreenOverActionBar(float aY)
{
final ActionBar bar = activity.getActionBar();
if(bar != null)
{
final boolean top = touchedOverActionBar(aY);
if(top == uiFullscreen)
{
uiFullscreen = !uiFullscreen;
return true;
}
}
return false;
}
}
@TargetApi(11) class WindowManager_IceCreamSandwich extends WindowManager_ICSBase
{
@Override public void setupDisplay()
{
super.setupDisplay();
super.setActionBarState();
}
@Override public void screenTouched(MotionEvent aEvent)
{
super.screenTouched(aEvent);
if(toggleFullscreenOverActionBar(aEvent.getY()))
{
setupDisplay();
}
}
}
@TargetApi(11) class WindowManager_JellyBean extends WindowManager_ICSBase
{
@Override public void windowCreated()
{
super.windowCreated();
activity.view.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener()
{
@Override public void onSystemUiVisibilityChange(int aVisibility)
{
if(!onScreenInput)
{
uiFullscreen = (aVisibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
}
}
});
}
@Override public void setupDisplay()
{
uiFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
if(!onScreenInput)
{
uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
if(uiFullscreen)
{
uiFlags |= View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
}
else
{
super.setActionBarState();
}
super.setupDisplay();
}
@Override public void screenTouched(MotionEvent aEvent)
{
super.screenTouched(aEvent);
if(!onScreenInput)
{
if(!touchedOverActionBar(aEvent.getY()))
{
uiFullscreen = true;
setupDisplay();
}
}
else if(toggleFullscreenOverActionBar(aEvent.getY()))
{
setupDisplay();
}
}
}

View File

@ -1,177 +0,0 @@
package org.andretro.browser;
import org.andretro.*;
import org.andretro.settings.*;
import org.andretro.emulator.*;
import java.util.*;
import java.io.*;
import android.content.*;
import android.app.*;
import android.os.*;
import android.widget.*;
import android.view.*;
import android.view.inputmethod.*;
import android.graphics.drawable.*;
class FileWrapper implements IconAdapterItem
{
public final File file;
protected final int typeIndex;
protected final boolean enabled;
public FileWrapper(File aFile, boolean aIsEnabled)
{
file = aFile;
typeIndex = (file.isDirectory() ? 1 : 0) + (file.isFile() ? 2 : 0);
enabled = aIsEnabled;
}
@Override public boolean isEnabled()
{
return enabled;
}
@Override public String getText()
{
return file.getName();
}
@Override public int getIconResourceId()
{
return file.isFile() ? R.drawable.file : R.drawable.folder;
}
@Override public Drawable getIconDrawable()
{
return null;
}
public int compareTo(FileWrapper aOther)
{
if(null != aOther)
{
// Who says ternary is hard to follow
if(isEnabled() == aOther.isEnabled())
{
return (typeIndex == aOther.typeIndex) ? file.compareTo(aOther.file) : ((typeIndex < aOther.typeIndex) ? -1 : 1);
}
else
{
return isEnabled() ? -1 : 1;
}
}
return -1;
}
}
public class DirectoryActivity extends Activity implements AdapterView.OnItemClickListener
{
private IconAdapter<FileWrapper> adapter;
private boolean inRoot;
private String moduleName;
private ModuleInfo moduleInfo;
@Override public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.line_list);
inRoot = getIntent().getBooleanExtra("inRoot", false);
moduleName = getIntent().getStringExtra("moduleName");
moduleInfo = ModuleInfo.getInfoAbout(this, new File(moduleName));
// Setup the list
adapter = new IconAdapter<FileWrapper>(this, R.layout.line_list_item);
ListView list = (ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(this);
// Load Directory
final String path = getIntent().getStringExtra("path");;
wrapFiles(new File(path));
setTitle(path);
}
@Override public void onItemClick(AdapterView<?> aListView, View aView, int aPosition, long aID)
{
final File selected = adapter.getItem(aPosition).file;
final Intent intent = new Intent(this, selected.isFile() ? RetroDisplay.class : DirectoryActivity.class)
.putExtra("path", selected.getAbsolutePath())
.putExtra("moduleName", moduleName)
.putExtra("inRoot", inRoot);
startActivity(intent);
}
@Override public boolean onCreateOptionsMenu(Menu aMenu)
{
super.onCreateOptionsMenu(aMenu);
getMenuInflater().inflate(R.menu.directory_list, aMenu);
if(inRoot)
{
aMenu.removeItem(R.id.goto_root);
}
return true;
}
@Override public boolean onOptionsItemSelected(MenuItem aItem)
{
if(R.id.goto_root == aItem.getItemId())
{
startActivity(new Intent(this, DirectoryActivity.class)
.putExtra("inRoot", true)
.putExtra("path", "/mnt/")
.putExtra("moduleName", moduleName));
return true;
}
if(R.id.input_method_select == aItem.getItemId())
{
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showInputMethodPicker();
return true;
}
if(aItem.getItemId() == R.id.system_settings)
{
startActivity(new Intent(this, SettingActivity.class)
.putExtra("moduleName", moduleName));
return true;
}
return super.onOptionsItemSelected(aItem);
}
private void wrapFiles(File aDirectory)
{
if(null == aDirectory || !aDirectory.isDirectory())
{
throw new IllegalArgumentException("Directory is not valid.");
}
// Copy new items
for(File file: aDirectory.listFiles())
{
adapter.add(new FileWrapper(file, file.isDirectory() || moduleInfo.isFileValid(file)));
}
// Sort items
adapter.sort(new Comparator<FileWrapper>()
{
@Override public int compare(FileWrapper aLeft, FileWrapper aRight)
{
return aLeft.compareTo(aRight);
};
});
// Update
adapter.notifyDataSetChanged();
}
}

View File

@ -1,79 +0,0 @@
package org.andretro.browser;
import org.andretro.*;
import android.app.*;
import android.content.*;
import android.graphics.drawable.*;
import android.view.*;
import android.widget.*;
interface IconAdapterItem
{
public abstract boolean isEnabled();
public abstract String getText();
public abstract int getIconResourceId();
public abstract Drawable getIconDrawable();
}
class IconAdapter<T extends IconAdapterItem> extends ArrayAdapter<T>
{
private final int layout;
public IconAdapter(Activity aContext, int aLayout)
{
super(aContext, aLayout);
layout = aLayout;
}
@Override public View getView(int aPosition, View aConvertView, ViewGroup aParent)
{
// Build the view
if(aConvertView == null)
{
LayoutInflater inflater = (LayoutInflater)aParent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
aConvertView = inflater.inflate(layout, aParent, false);
}
// Fill the view
IconAdapterItem item = getItem(aPosition);
final boolean enabled = item.isEnabled();
TextView textView = (TextView)aConvertView.findViewById(R.id.name);
if(null != textView)
{
textView.setText(item.getText());
textView.setEnabled(enabled);
}
ImageView imageView = (ImageView)aConvertView.findViewById(R.id.icon);
if(null != imageView)
{
if(enabled)
{
final int id = item.getIconResourceId();
if(0 != id)
{
imageView.setImageResource(id);
}
else
{
imageView.setImageDrawable(item.getIconDrawable());
}
}
else
{
imageView.setImageDrawable(null);
}
}
return aConvertView;
}
@Override public boolean isEnabled(int aPosition)
{
return getItem(aPosition).isEnabled();
}
}

View File

@ -1,116 +0,0 @@
package org.andretro.browser;
import org.andretro.*;
import org.andretro.emulator.*;
import org.andretro.system.*;
import java.io.*;
import android.content.*;
import android.app.*;
import android.os.*;
import android.widget.*;
import android.view.*;
import android.view.inputmethod.*;
import android.graphics.drawable.*;
class ModuleWrapper implements IconAdapterItem
{
public final File file;
public final ModuleInfo info;
public ModuleWrapper(Context aContext, File aFile) throws IOException
{
file = aFile;
info = ModuleInfo.getInfoAbout(aContext, aFile);
}
@Override public boolean isEnabled()
{
return true;
}
@Override public String getText()
{
return info.name;
}
@Override public int getIconResourceId()
{
return 0;
}
@Override public Drawable getIconDrawable()
{
return null;
}
}
public class ModuleActivity extends Activity implements AdapterView.OnItemClickListener
{
// HACK: Hard path
private static final String modulePath = "/data/data/org.andretro/lib/";
private IconAdapter<ModuleWrapper> adapter;
@Override public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.line_list);
// Setup the list
adapter = new IconAdapter<ModuleWrapper>(this, R.layout.line_list_item);
ListView list = (ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(this);
setTitle("Select Emulator");
for(final File lib: new File(modulePath).listFiles())
{
if(lib.getName().startsWith("libretro_"))
{
try
{
adapter.add(new ModuleWrapper(this, lib));;
}
catch(Exception e)
{
Logger.d("Couldn't add module: " + lib.getPath());
}
}
}
}
@Override public void onItemClick(AdapterView<?> aListView, View aView, int aPosition, long aID)
{
final ModuleWrapper item = adapter.getItem(aPosition);
startActivity(new Intent(ModuleActivity.this, DirectoryActivity.class)
.putExtra("path", item.info.getDataPath() + "/Games")
.putExtra("moduleName", item.file.getAbsolutePath()));
}
@Override public boolean onCreateOptionsMenu(Menu aMenu)
{
super.onCreateOptionsMenu(aMenu);
getMenuInflater().inflate(R.menu.directory_list, aMenu);
aMenu.removeItem(R.id.goto_root);
aMenu.removeItem(R.id.system_settings);
return true;
}
@Override public boolean onOptionsItemSelected(MenuItem aItem)
{
if(R.id.input_method_select == aItem.getItemId())
{
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showInputMethodPicker();
return true;
}
return super.onOptionsItemSelected(aItem);
}
}

View File

@ -1,94 +0,0 @@
package org.andretro.browser;
import org.andretro.*;
import org.andretro.emulator.*;
import android.app.*;
import android.graphics.drawable.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import java.io.*;
import java.util.*;
import java.text.*;
class SlotWrapper implements IconAdapterItem
{
public final int slot;
public final boolean enabled;
public final String text;
public final Drawable thumbNail;
public SlotWrapper(int aSlot, boolean aLoading)
{
slot = aSlot;
final File slotFile = new File(Game.getGameDataName("SaveStates", "st" + aSlot));
final boolean hasSlotFile = slotFile.isFile() && slotFile.exists();
final String slotFileDate = hasSlotFile ? DateFormat.getDateTimeInstance().format(new Date(slotFile.lastModified())) : "EMPTY";
enabled = !aLoading || hasSlotFile;
text = "Slot " + aSlot + " (" + slotFileDate + ")";
// Get thumb
final File thumbFile = new File(Game.getGameDataName("SaveStates", "tb" + aSlot));
thumbNail = thumbFile.isFile() ? Drawable.createFromPath(thumbFile.getAbsolutePath()) : null;
}
@Override public boolean isEnabled()
{
return enabled;
}
@Override public String getText()
{
return text;
}
@Override public int getIconResourceId()
{
return 0;
}
@Override public Drawable getIconDrawable()
{
return thumbNail;
}
}
public class StateList extends Activity implements AdapterView.OnItemClickListener
{
private IconAdapter<SlotWrapper> adapter;
private boolean loading;
@Override public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.icon_grid_list);
loading = getIntent().getBooleanExtra("loading", false);
// Setup the list
adapter = new IconAdapter<SlotWrapper>(this, R.layout.icon_grid_item);
GridView list = (GridView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(this);
setTitle(loading ? "Load State" : "Save State");
// Add data
for(int i = 0; i != 10; i ++)
{
adapter.add(new SlotWrapper(i, loading));
}
}
@Override public void onItemClick(AdapterView<?> aListView, View aView, int aPosition, long aID)
{
Game.queueCommand(new Commands.StateAction(loading, aPosition));
finish();
}
}

View File

@ -1,188 +0,0 @@
package org.andretro.emulator;
import java.io.*;
import java.text.*;
import java.util.*;
import android.content.*;
import android.content.pm.*;
import android.view.*;
import android.app.*;
import org.andretro.system.*;
import org.andretro.system.video.*;
import org.libretro.LibRetro;
public final class Commands
{
public static final class LoadGame extends CommandQueue.BaseCommand
{
private final Activity activity;
private final String library;
private final File file;
public LoadGame(Activity aActivity, String aLibrary, File aFile)
{
activity = aActivity;
library = aLibrary;
file = aFile;
if(null == activity || null == library || null == aFile)
{
throw new NullPointerException("Neither aActivity, aLibrary nor aFile may be null");
}
}
@Override protected void perform()
{
Game.loadGame(activity, library, file);
}
}
public static final class CloseGame extends CommandQueue.BaseCommand
{
@Override protected void perform()
{
Game.closeGame();
}
}
public static final class Reset extends CommandQueue.BaseCommand
{
@Override protected void perform()
{
LibRetro.reset();
}
}
public static final class TakeScreenShot extends CommandQueue.BaseCommand
{
@Override protected void perform()
{
Game.screenShotName = Game.getGameDataName("ScreenShots", DateFormat.getDateTimeInstance().format(new Date()) + ".png");
}
}
public static final class StateAction extends CommandQueue.BaseCommand
{
private final boolean load;
private final int slot;
public StateAction(boolean aLoad, int aSlot)
{
load = aLoad;
slot = aSlot;
if(slot < 0 || slot > 9)
{
throw new RuntimeException("Slot must be in the range of 0-9");
}
}
@Override protected void perform()
{
if(load)
{
LibRetro.unserializeFromFile(Game.getGameDataName("SaveStates", "st" + slot));
}
else
{
LibRetro.serializeToFile(Game.getGameDataName("SaveStates", "st" + slot));
Game.screenShotName = Game.getGameDataName("SaveStates", "tb" + slot);
}
}
}
public static final class Pause extends CommandQueue.BaseCommand
{
private final boolean pause;
public Pause(boolean aPause)
{
pause = aPause;
}
@Override protected void perform()
{
if(0 == Game.pauseDepth && !pause)
{
throw new RuntimeException("Internal Error: Emulator was unpaused too many times (Please Report).");
}
Game.pauseDepth += pause ? 1 : -1;
}
}
public static final class RefreshInput extends CommandQueue.BaseCommand
{
@Override protected void perform()
{
// TODO
LibRetro.setControllerPortDevice(0, LibRetro.RETRO_DEVICE_JOYPAD);
}
}
public static final class RefreshSettings extends CommandQueue.BaseCommand
{
private final SharedPreferences settings;
public RefreshSettings(SharedPreferences aSettings)
{
settings = aSettings;
if(null == aSettings)
{
throw new RuntimeException("aSettings may not be null.");
}
}
@Override protected void perform()
{
// Scaling
Present.Texture.setSmoothMode(settings.getBoolean("scaling_smooth", true));
final String aspectMode = settings.getString("scaling_aspect_mode", "Default");
if("Default".equals(aspectMode))
{
VertexData.setForcedAspect(false, 0.0f);
}
else if("4:3".equals(aspectMode))
{
VertexData.setForcedAspect(true, 1.3333333f);
}
else if("Pixel".equals(aspectMode))
{
VertexData.setForcedAspect(true, -1.0f);
}
else
{
VertexData.setForcedAspect(false, 0.0f);
}
// Orientation
final String orientMode = settings.getString("scaling_orientation", "Sensor");
if("Portrait".equals(orientMode))
{
Game.loadingActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else if("Landscape".equals(orientMode))
{
Game.loadingActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
else
{
Game.loadingActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
// Fast forward
Game.fastForwardDefault = settings.getBoolean("fast_forward_default", false);
Game.fastForwardSpeed = Integer.parseInt(settings.getString("fast_forward_speed", "4"));
Game.fastForwardKey = settings.getInt("fast_forward_key", KeyEvent.KEYCODE_BUTTON_R2);
// Rewind
final boolean rewindEnabled = settings.getBoolean("rewind_enabled", false);
final int rewindDataSize = Integer.parseInt(settings.getString("rewind_buffer_size", "16")) * 1024 * 1024;
LibRetro.setupRewinder(rewindEnabled ? rewindDataSize : 0);
Game.rewindKey = settings.getInt("rewind_key", KeyEvent.KEYCODE_BUTTON_L2);
}
}
}

View File

@ -1,199 +0,0 @@
package org.andretro.emulator;
import java.util.*;
import android.content.*;
import org.w3c.dom.*;
public final class Doodads
{
private static abstract class NamedInput
{
/**
* The short name of the input. Best used for setting keys.
*/
public final String name;
/**
* The friendly name of the input. Best used for display.
*/
public final String fullName;
/**
* Construct a new NamedInput.
* @param aShort The setting name of the input. May not be null.
* @param aFull The display name of the input. May not be null.
*/
NamedInput(String aShort, String aFull)
{
if(null == aShort || null == aFull)
{
throw new IllegalArgumentException("Neither name of a NamedInput may be null.");
}
name = aShort;
fullName = aFull;
}
}
private static abstract class GroupedInput <E extends NamedInput> extends NamedInput
{
/**
* List of input objects.
*/
protected final ArrayList<E> inputs;
/**
* Create a new GroupedInput.
* @param aShort Setting name for the input. May not be null.
* @param aFull Display name for the input. May not be null.
* @param aCount Number of devices in this set.
*/
GroupedInput(String aShort, String aFull)
{
super(aShort, aFull);
inputs = new ArrayList<E>();
}
public int getCount()
{
return inputs.size();
}
public ArrayList<E> getAll()
{
return inputs;
}
public E getItem(int aIndex)
{
return inputs.get(aIndex);
}
public E getItem(String aName)
{
for(E i: inputs)
{
if(aName.equals(i.name))
{
return i;
}
}
return null;
}
}
public final static class Button extends NamedInput
{
public final String configKey;
public final int bitOffset;
private int keyCode;
public static final String[] names = {"UP", "DOWN", "LEFT", "RIGHT", "A", "B", "X", "Y", "SELECT", "START", "L1", "R1", "L2", "R2", "L3", "R3"};
public static final int[] offsets = {4, 5, 6, 7, 8, 0, 9, 1, 2, 3, 10, 11, 12, 13, 14, 15};
Button(SharedPreferences aPreferences, String aKeyBase, Element aData)
{
super(aData.getAttribute("shortname"), aData.getAttribute("fullname"));
// Get configKey
configKey = aKeyBase + "_" + name;
// Get value
keyCode = aPreferences.getInt(configKey, 0);
// Grab native data
final String keyName = aData.getAttribute("mappedkey");
for(int i = 0; i != 16; i ++)
{
if(names[i].equals(keyName))
{
bitOffset = offsets[i];
return;
}
}
throw new RuntimeException("Mapped key " + keyName + " not found");
}
public int getKeyCode()
{
return keyCode;
}
public void setKeyCode(int aKeyCode)
{
keyCode = aKeyCode;
}
}
public final static class Device extends GroupedInput<Button>
{
Device(SharedPreferences aPreferences, String aKeyBase, Element aData)
{
super(aData.getAttribute("shortname"), aData.getAttribute("fullname"));
final NodeList buttons = aData.getElementsByTagName("button");
for(int i = 0; i != buttons.getLength(); i ++)
{
inputs.add(i, new Button(aPreferences, aKeyBase + "_" + name, (Element)buttons.item(i)));
}
}
}
public final static class Port extends GroupedInput<Device>
{
public final String defaultDevice;
private final String currentDevice;
Port(SharedPreferences aPreferences, String aKeyBase, Element aData)
{
super(aData.getAttribute("shortname"), aData.getAttribute("fullname"));
defaultDevice = aData.getAttribute("defaultdevice");
currentDevice = aPreferences.getString(aKeyBase + "_" + name, defaultDevice);
final NodeList devices = aData.getElementsByTagName("device");
for(int i = 0; i != devices.getLength(); i ++)
{
inputs.add(i, new Device(aPreferences, aKeyBase + "_" + name, (Element)devices.item(i)));
}
}
public String getCurrentDevice()
{
return currentDevice;
}
}
public final static class Set extends GroupedInput<Port>
{
Set(SharedPreferences aPreferences, String aKeyBase, Element aData)
{
super("root", "root");
final NodeList ports = aData.getElementsByTagName("port");
for(int i = 0; i != ports.getLength(); i ++)
{
inputs.add(new Port(aPreferences, aKeyBase, (Element)ports.item(i)));
}
}
// Implement
public Doodads.Port getPort(int aPort)
{
return getItem(aPort);
}
public Doodads.Device getDevice(int aPort, int aDevice)
{
return getItem(aPort).getItem(aDevice);
}
public Doodads.Button getButton(int aPort, int aDevice, int aIndex)
{
return getItem(aPort).getItem(aDevice).getItem(aIndex);
}
}
}

View File

@ -1,167 +0,0 @@
package org.andretro.emulator;
import org.andretro.system.*;
import org.libretro.*;
import java.io.*;
import android.app.*;
public final class Game
{
// Singleton
static
{
System.loadLibrary("retroiface");
if(!LibRetro.nativeInit())
{
throw new RuntimeException("Failed to initialize JNI classes.");
}
}
// Thread
private static final CommandQueue eventQueue = new CommandQueue();
public static void queueCommand(final CommandQueue.BaseCommand aCommand)
{
eventQueue.queueCommand(aCommand);
}
// Game Info
static int pauseDepth;
// Fast forward
static int fastForwardKey;
static int fastForwardSpeed = 1;
static boolean fastForwardDefault;
static int rewindKey;
static String screenShotName;
// Functions to retrieve game data, careful as the data may be null, or outdated!
public static String getGameDataName(String aSubDirectory, String aExtension)
{
final File dir = new File(moduleInfo.getDataPath() + "/" + aSubDirectory);
if(!dir.exists() && !dir.mkdirs())
{
throw new RuntimeException("Failed to make data directory");
}
return moduleInfo.getDataPath() + "/" + aSubDirectory + "/" + dataName + "." + aExtension;
}
// LIBRARY
static Activity loadingActivity;
private static ModuleInfo moduleInfo;
private static boolean gameLoaded;
private static boolean gameClosed;
private static LibRetro.SystemInfo systemInfo = new LibRetro.SystemInfo();
private static LibRetro.AVInfo avInfo = new LibRetro.AVInfo();
private static String dataName;
static void loadGame(Activity aActivity, String aLibrary, File aFile)
{
if(!gameLoaded && !gameClosed && null != aFile && aFile.isFile())
{
moduleInfo = ModuleInfo.getInfoAbout(aActivity, new File(aLibrary));
if(LibRetro.loadLibrary(aLibrary, moduleInfo.getDataPath()))
{
LibRetro.init();
if(LibRetro.loadGame(aFile.getAbsolutePath()))
{
// System info
LibRetro.getSystemInfo(systemInfo);
LibRetro.getSystemAVInfo(avInfo);
// Filesystem stuff
dataName = aFile.getName().split("\\.(?=[^\\.]+$)")[0];
LibRetro.readMemoryRegion(LibRetro.RETRO_MEMORY_SAVE_RAM, getGameDataName("SaveRAM", "srm"));
LibRetro.readMemoryRegion(LibRetro.RETRO_MEMORY_RTC, getGameDataName("SaveRAM", "rtc"));
// Load settings
loadingActivity = aActivity;
new Commands.RefreshSettings(aActivity.getSharedPreferences(moduleInfo.getDataName(), 0)).run();
new Commands.RefreshInput().run();
gameLoaded = true;
}
}
}
else
{
gameLoaded = true;
gameClosed = true;
throw new RuntimeException("Failed to load game");
}
}
static void closeGame()
{
if(gameLoaded && !gameClosed)
{
LibRetro.writeMemoryRegion(LibRetro.RETRO_MEMORY_SAVE_RAM, getGameDataName("SaveRAM", "srm"));
LibRetro.writeMemoryRegion(LibRetro.RETRO_MEMORY_RTC, getGameDataName("SaveRAM", "rtc"));
LibRetro.unloadGame();
LibRetro.deinit();
LibRetro.unloadLibrary();
// Shutdown any audio device
Audio.close();
gameClosed = true;
}
}
public static boolean hasGame()
{
return gameLoaded && !gameClosed;
}
// LOOP
public static boolean doFrame(LibRetro.VideoFrame aFrame)
{
eventQueue.pump();
if(gameLoaded && !gameClosed && 0 == pauseDepth)
{
// Fast forward
aFrame.rewind = Input.isPressed(rewindKey);
final boolean fastKeyPressed = Input.isPressed(fastForwardKey);
final int frameToggle = fastForwardDefault ? 1 : fastForwardSpeed;
final int frameTarget = fastForwardDefault ? fastForwardSpeed : 1;
aFrame.framesToRun = (fastKeyPressed) ? frameToggle : frameTarget;
// Write any pending screen shots
if(null != screenShotName && !aFrame.restarted)
{
PngWriter.write(screenShotName);
screenShotName = null;
}
// Get input data
Input.poolKeyboard(aFrame.keyboard);
aFrame.buttons[0] = Input.getBits(moduleInfo.inputData.getDevice(0, 0));
aFrame.touchX = Input.getTouchX();
aFrame.touchY = Input.getTouchY();
aFrame.touched = Input.getTouched();
//Emulate
LibRetro.run(aFrame);
// Present
if(0 != aFrame.audioSamples)
{
Audio.write((int)avInfo.sampleRate, aFrame.audio, aFrame.audioSamples);
}
return true;
}
return false;
}
}

View File

@ -1,107 +0,0 @@
package org.andretro.emulator;
import android.content.*;
import android.os.*;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import org.w3c.dom.*;
public class ModuleInfo
{
// TODO: Make them not public!
public String name;
public String shortName;
public String libraryName;
public String[] extensions;
public String dataPath;
private Document document;
private Element onScreenInputData;
public final Doodads.Set inputData;
private static final Map<String, ModuleInfo> cache = new HashMap<String, ModuleInfo>();
public static ModuleInfo getInfoAbout(final Context aContext, final File aFile)
{
final String key = aFile.getName() + ".xml";
if(cache.containsKey(key))
{
return cache.get(key);
}
else
{
ModuleInfo newInfo = new ModuleInfo(aContext, aFile);
cache.put(key, newInfo);
return newInfo;
}
}
private ModuleInfo(final Context aContext, final File aFile)
{
try
{
// Why does xml have to be so god damned difficult?
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(aContext.getAssets().open(aFile.getName() + ".xml"));
final XPath xpath = XPathFactory.newInstance().newXPath();
// Read system info
Element system = (Element)xpath.evaluate("/retro/system", document, XPathConstants.NODE);
name = system.getAttribute("fullname");
shortName = system.getAttribute("shortname");
// Read module info
Element module = (Element)xpath.evaluate("/retro/module", document, XPathConstants.NODE);
libraryName = module.getAttribute("libraryname");
extensions = module.getAttribute("extensions").split("\\|");
Arrays.sort(extensions);
// Read input element
onScreenInputData = (Element)xpath.evaluate("/retro/onscreeninput", document, XPathConstants.NODE);
inputData = new Doodads.Set(aContext.getSharedPreferences(libraryName, 0), "input", (Element)xpath.evaluate("/retro/input", document, XPathConstants.NODE));
// Quick check hack
if(null == name || null == shortName || null == libraryName || null == extensions)
{
throw new Exception("Not all elements present in xml");
}
// Build Directories
dataPath = Environment.getExternalStorageDirectory().getPath() + "/andretro/" + libraryName;
new File(dataPath + "/Games").mkdirs();
}
catch(final Exception e)
{
throw new RuntimeException(e);
}
}
public String getDataName()
{
return libraryName;
}
public String getDataPath()
{
return dataPath;
}
public boolean isFileValid(File aFile)
{
final String path = aFile.getAbsolutePath();
final int dot = path.lastIndexOf(".");
final String extension = (dot < 0) ? null : path.substring(dot + 1).toLowerCase();
return (null == extension) ? false : (0 <= Arrays.binarySearch(extensions, extension));
}
public Element getOnScreenInputDefinition()
{
return onScreenInputData;
}
}

View File

@ -1,29 +0,0 @@
package org.andretro.input.view;
import org.andretro.*;
import android.annotation.SuppressLint;
import android.content.*;
import android.widget.*;
import org.w3c.dom.*;
@SuppressLint("ViewConstructor")
public class Button extends ImageView implements InputGroup.InputHandler
{
int touchCount = 0;
int bits;
public Button(Context aContext, Element aElement)
{
super(aContext);
setImageResource(R.drawable.button);
bits = InputGroup.getInt(aElement, "bits");
}
@Override public int getBits(int aX, int aY)
{
return bits;
}
}

View File

@ -1,42 +0,0 @@
package org.andretro.input.view;
import org.andretro.*;
import org.w3c.dom.*;
import android.annotation.*;
import android.content.*;
import android.widget.*;
@SuppressLint("ViewConstructor")
public class ButtonDiamond extends ImageView implements InputGroup.InputHandler
{
private final int bits[] = new int[4];
public ButtonDiamond(Context aContext, Element aElement)
{
super(aContext);
setImageResource(R.drawable.dpad);
bits[0] = InputGroup.getInt(aElement, "upbits");
bits[1] = InputGroup.getInt(aElement, "downbits");
bits[2] = InputGroup.getInt(aElement, "leftbits");
bits[3] = InputGroup.getInt(aElement, "rightbits");
}
@Override public int getBits(int aX, int aY)
{
final int w = getWidth() / 3;
final int h = getHeight() / 3;
final int x = aX - getLeft();
final int y = aY - getTop();
int result = 0;
result |= (x < w) ? bits[2] : 0;
result |= (x > w * 2) ? bits[3] : 0;
result |= (y < h) ? bits[0] : 0;
result |= (y > h * 2) ? bits[1] : 0;
return result;
}
}

View File

@ -1,35 +0,0 @@
package org.andretro.input.view;
import org.andretro.*;
import org.w3c.dom.*;
import android.annotation.*;
import android.content.*;
import android.widget.*;
@SuppressLint("ViewConstructor")
public class ButtonDuo extends ImageView implements InputGroup.InputHandler
{
int currentBits = 0;
int bits[] = new int[2];
public ButtonDuo(Context aContext, Element aElement)
{
super(aContext);
setImageResource(R.drawable.buttonduo);
bits[0] = InputGroup.getInt(aElement, "leftbits");
bits[1] = InputGroup.getInt(aElement, "rightbits");
}
@Override public int getBits(int aX, int aY)
{
final int x = aX - getLeft();
final int width = getWidth() / 3;
int result = (x < width * 2) ? bits[0] : 0;
result |= (x > width) ? bits[1] : 0;
return result;
}
}

View File

@ -1,186 +0,0 @@
package org.andretro.input.view;
import org.andretro.emulator.*;
import android.util.*;
import android.view.*;
import android.content.*;
import android.widget.*;
import android.app.*;
import android.graphics.*;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
public class InputGroup extends RelativeLayout
{
public static interface InputHandler
{
int getBits(int aX, int aY);
}
private static class Handler
{
final Rect area = new Rect();
final View view;
public Handler(View aHandler)
{
if(!(aHandler instanceof InputHandler))
{
throw new RuntimeException("aHandler must be an object that implements the InputHandler interface.");
}
view = aHandler;
}
public int getBits(int aX, int aY)
{
final InputHandler handler = (InputHandler)view;
area.left = view.getLeft();
area.right = view.getRight();
area.top = view.getTop();
area.bottom = view.getBottom();
return area.contains(aX, aY) ? handler.getBits(aX, aY) : 0;
}
}
private ArrayList<Handler> handlers = new ArrayList<Handler>();
private int currentBits;
public InputGroup(Context aContext, AttributeSet aAttributes)
{
super(aContext, aAttributes);
setFocusableInTouchMode(true);
}
@Override public boolean onTouchEvent(MotionEvent aEvent)
{
currentBits = 0;
final int count = aEvent.getPointerCount();
for(int i = 0; i != count; i ++)
{
if(aEvent.getActionMasked() != MotionEvent.ACTION_UP || i != aEvent.getActionIndex())
{
for(Handler j: handlers)
{
currentBits |= j.getBits((int)aEvent.getX(i), (int)aEvent.getY(i));
}
}
}
return true;
}
public int getBits()
{
return currentBits;
}
public void removeChildren()
{
final List<View> toRemove = new ArrayList<View>();
for(int i = 0; i != getChildCount(); i ++)
{
final View thisOne = getChildAt(i);
if(thisOne instanceof InputHandler)
{
toRemove.add(thisOne);
}
}
for(final View view: toRemove)
{
removeView(view);
}
handlers.clear();
}
public void loadInputLayout(final Activity aContext, final ModuleInfo aModule, final InputStream aFile)
{
try
{
removeChildren();
// Get the default from the module, if it's null read the default from aFile
Element inputElement = aModule.getOnScreenInputDefinition();
if(null == inputElement)
{
inputElement = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(aFile).getDocumentElement();
}
// Build the views
NodeList inputs = inputElement.getChildNodes();
for(int i = 0; i != inputs.getLength(); i ++)
{
if(Node.ELEMENT_NODE == inputs.item(i).getNodeType())
{
Element input = (Element)inputs.item(i);
final Class<? extends View> clazz = Class.forName("org.andretro.input.view." + input.getNodeName()).asSubclass(View.class);
View inputView = clazz.getConstructor(Context.class, Element.class).newInstance(aContext, input);
addView(inputView, extractAnchorData(input));
handlers.add(new Handler(inputView));
}
}
}
catch(final Exception e)
{
aContext.runOnUiThread(new Runnable()
{
@Override public void run()
{
String message = e.getMessage();
message = (message == null) ? "No Message" : message;
Toast.makeText(aContext, "Failed to load controls from " + aFile + "\n" + e.getClass().toString() + "\n" + message, Toast.LENGTH_LONG).show();
}
});
}
}
// Anchor mapping
private RelativeLayout.LayoutParams extractAnchorData(Element aElement)
{
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(getInt(aElement, "width"), getInt(aElement, "height"));
final int horizontalAnchorMode = horizontalAnchor.get(aElement.getAttribute("horzanchor"));
final int horizontalMargin = getInt(aElement, "horzmargin");
params.leftMargin = (horizontalAnchorMode == RelativeLayout.ALIGN_PARENT_LEFT) ? horizontalMargin : 0;;
params.rightMargin = (horizontalAnchorMode == RelativeLayout.ALIGN_PARENT_RIGHT) ? horizontalMargin : 0;;
params.addRule(horizontalAnchorMode);
final int verticalAnchorMode = verticalAnchor.get(aElement.getAttribute("vertanchor"));
final int verticalMargin = getInt(aElement, "vertmargin");
params.topMargin = (verticalAnchorMode == RelativeLayout.ALIGN_PARENT_TOP) ? verticalMargin : 0;
params.bottomMargin = (verticalAnchorMode == RelativeLayout.ALIGN_PARENT_BOTTOM) ? verticalMargin : 0;
params.addRule(verticalAnchorMode);
return params;
}
private static final Map<String, Integer> horizontalAnchor = new HashMap<String, Integer>();
private static final Map<String, Integer> verticalAnchor = new HashMap<String, Integer>();
static
{
horizontalAnchor.put("left", RelativeLayout.ALIGN_PARENT_LEFT);
horizontalAnchor.put("center", RelativeLayout.CENTER_HORIZONTAL);
horizontalAnchor.put("right", RelativeLayout.ALIGN_PARENT_RIGHT);
verticalAnchor.put("top", RelativeLayout.ALIGN_PARENT_TOP);
verticalAnchor.put("center", RelativeLayout.CENTER_VERTICAL);
verticalAnchor.put("bottom", RelativeLayout.ALIGN_PARENT_BOTTOM);
}
public static int getInt(Element aElement, String aAttribute)
{
final String value = aElement.getAttribute(aAttribute);
return ("".equals(value)) ? 0 : Integer.parseInt(value);
}
}

View File

@ -1,86 +0,0 @@
package org.andretro.settings;
import org.andretro.*;
import android.annotation.*;
import android.content.*;
import android.os.*;
import android.preference.*;
import android.view.*;
import android.widget.*;
import android.util.*;
public class ButtonSetting extends DialogPreference
{
@TargetApi(12) public ButtonSetting(Context aContext, AttributeSet aAttributes)
{
super(aContext, aAttributes);
// HACK: Set a layout that forces the dialog to get key focus
// TODO: Make the layout better looking!
setDialogLayoutResource(R.layout.dialog_focus_hack);
setDialogTitle("Waiting for input");
setDialogMessage(getTitle());
}
@TargetApi(12) public ButtonSetting(Context aContext, String aKey, String aName, int aDefault)
{
super(aContext, null);
setKey(aKey);
setTitle(aName);
setPersistent(true);
setDefaultValue(aDefault);
// HACK: Set a layout that forces the dialog to get key focus
// TODO: Make the layout better looking!
setDialogLayoutResource(R.layout.dialog_focus_hack);
setDialogTitle("Waiting for input");
setDialogMessage(aName);
}
@Override protected void onAttachedToActivity()
{
super.onAttachedToActivity();
refreshSummary();
}
@Override protected void showDialog(Bundle aState)
{
super.showDialog(aState);
// HACK: Set the message in the hacked layout
((EditText)getDialog().findViewById(R.id.hack_message)).setText(getDialogMessage());
getDialog().setOnKeyListener(new DialogInterface.OnKeyListener()
{
@Override public boolean onKey(DialogInterface aDialog, int aKeyCode, KeyEvent aEvent)
{
persistInt(aKeyCode);
valueChanged(aKeyCode);
refreshSummary();
getDialog().dismiss();
return false;
}
});
}
@TargetApi(12) private void refreshSummary()
{
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR1)
{
setSummary(KeyEvent.keyCodeToString(getPersistedInt(0)));
}
else
{
setSummary(Integer.toString(getPersistedInt(0)));
}
}
protected void valueChanged(int aKeyCode)
{
}
}

View File

@ -1,76 +0,0 @@
package org.andretro.settings;
import org.andretro.*;
import org.andretro.emulator.*;
import android.preference.*;
import android.content.*;
import android.os.*;
import java.io.*;
@SuppressWarnings("deprecation")
public class SettingActivity extends PreferenceActivity
{
private String moduleName;
private ModuleInfo moduleInfo;
@Override public void onCreate(Bundle aState)
{
super.onCreate(aState);
moduleName = getIntent().getStringExtra("moduleName");
moduleInfo = ModuleInfo.getInfoAbout(this, new File(moduleName));
getPreferenceManager().setSharedPreferencesName(moduleInfo.getDataName());
// Add the input subsection
PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(this);
PreferenceCategory inputCategory = new PreferenceCategory(this);
inputCategory.setTitle("Input");
screen.addPreference(inputCategory);
// Add all pads (TODO: Just port 1 for now)
PreferenceScreen inputScreen = getPreferenceManager().createPreferenceScreen(this);
inputScreen.setTitle("Port 1");
Doodads.Device device = moduleInfo.inputData.getDevice(0, 0);
for(Doodads.Button i: device.getAll())
{
inputScreen.addPreference(new Button(this, i));
}
inputCategory.addPreference(inputScreen);
// Add the rest of the system settings
setPreferenceScreen(screen);
addPreferencesFromResource(R.xml.preferences);
}
@Override public void onPause()
{
super.onPause();
if(Game.hasGame())
{
Game.queueCommand(new Commands.RefreshSettings(getPreferenceManager().getSharedPreferences()));
}
}
private static class Button extends ButtonSetting
{
final Doodads.Button button;
public Button(Context aContext, final Doodads.Button aButton)
{
super(aContext, aButton.configKey, aButton.fullName, 0);
button = aButton;
}
@Override protected void valueChanged(int aKeyCode)
{
button.setKeyCode(aKeyCode);
}
}
}

View File

@ -1,72 +0,0 @@
package org.andretro.system;
import android.media.*;
/**
* A stateless audio stream.
*
* Underlying audio object is created and managed transparently. User only needs to call write().
* @author jason
*
*/
public final class Audio
{
private static AudioTrack audio;
private static int rate;
private static boolean failed;
public synchronized static void open(int aRate)
{
close();
rate = aRate;
try
{
final int bufferSize = AudioTrack.getMinBufferSize(aRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
audio = new AudioTrack(AudioManager.STREAM_MUSIC, aRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
audio.setStereoVolume(1, 1);
audio.play();
failed = false;
}
catch(Exception e)
{
audio = null;
failed = true;
}
}
public synchronized static void close()
{
if(null != audio)
{
audio.stop();
audio.release();
}
audio = null;
}
public synchronized static void write(int aRate, short aSamples[], int aCount)
{
// Check args
if(null == aSamples || aCount < 0 || aCount >= aSamples.length)
{
throw new IllegalArgumentException("Invalid audio stream chunk.");
}
// Create audio if needed
if((null == audio && !failed) || aRate != rate)
{
open(aRate);
}
// Write samples
if(null != audio)
{
audio.write(aSamples, 0, aCount);
}
}
}

View File

@ -1,74 +0,0 @@
package org.andretro.system;
import java.util.concurrent.*;
import android.app.*;
public class CommandQueue
{
private final BlockingQueue<BaseCommand> eventQueue = new ArrayBlockingQueue<BaseCommand>(8);
/**
* Must be called before any other function
* @param aThread
*/
public void queueCommand(final BaseCommand aCommand)
{
// Put the event in the queue and notify any waiting clients that it's present. (This will wake the waiting emulator if needed.)
eventQueue.add(aCommand);
}
public void pump()
{
// Run all events
for(BaseCommand i = eventQueue.poll(); null != i; i = eventQueue.poll())
{
i.run();
}
}
public static class Callback
{
private final Runnable callback;
private final Activity activity;
public Callback(Activity aActivity, Runnable aCallback)
{
callback = aCallback;
activity = aActivity;
if(null == callback || null == activity)
{
throw new RuntimeException("Neither aCallback nor aActivity may be null.");
}
}
public void perform()
{
activity.runOnUiThread(callback);
}
}
public static abstract class BaseCommand implements Runnable
{
private Callback finishedCallback;
public BaseCommand setCallback(Callback aFinished)
{
finishedCallback = aFinished;
return this;
}
@Override public final void run()
{
perform();
if(null != finishedCallback)
{
finishedCallback.perform();
}
}
abstract protected void perform();
}
}

View File

@ -1,191 +0,0 @@
package org.andretro.system;
import static android.view.KeyEvent.*;
import static org.libretro.LibRetro.*;
import org.andretro.input.view.*;
import android.view.*;
import java.util.*;
import org.andretro.emulator.Doodads;
/**
* Static class to manage input state for the emulator view.
* @author jason
*
*/
public final class Input
{
private static Set<Integer> keys = new TreeSet<Integer>();
private static InputGroup onscreenInput;
private static short touchX;
private static short touchY;
private static boolean touched;
// Called by UI
public synchronized static void processEvent(KeyEvent aEvent)
{
if(aEvent.getAction() == KeyEvent.ACTION_DOWN)
{
keys.add(aEvent.getKeyCode());
}
else if(aEvent.getAction() == KeyEvent.ACTION_UP)
{
keys.remove(aEvent.getKeyCode());
}
}
public synchronized static void clear()
{
keys.clear();
}
public synchronized static void setOnScreenInput(InputGroup aInput)
{
onscreenInput = aInput;
}
public synchronized static void setTouchData(short aX, short aY, boolean aTouched)
{
touchX = aX;
touchY = aY;
touched = aTouched;
}
// Called by emulator
public static synchronized int getBits(Doodads.Device aDevice)
{
int result = (null != onscreenInput) ? onscreenInput.getBits() : 0;
for(Doodads.Button i: aDevice.getAll())
{
if(keys.contains(i.getKeyCode()))
{
result |= (1 << i.bitOffset);
}
}
return result;
}
public static synchronized boolean isPressed(int aKeyCode)
{
return keys.contains(aKeyCode);
}
public static synchronized void poolKeyboard(int[] aKeyState)
{
for(int i = 0; i != mappingTable.length / 2; i ++)
{
final int retroID = mappingTable[i * 2 + 0];
final int androidID = mappingTable[i * 2 + 1];
aKeyState[retroID] = keys.contains(androidID) ? 1 : 0;
}
}
public static synchronized short getTouchX()
{
return touchX;
}
public static synchronized short getTouchY()
{
return touchY;
}
public static synchronized boolean getTouched()
{
return touched;
}
// KEYBOARD
private static final int[] mappingTable =
{
RETROK_LEFT, KEYCODE_DPAD_LEFT,
RETROK_RIGHT, KEYCODE_DPAD_RIGHT,
RETROK_UP, KEYCODE_DPAD_UP,
RETROK_DOWN, KEYCODE_DPAD_DOWN,
RETROK_RETURN, KEYCODE_ENTER,
RETROK_TAB, KEYCODE_TAB,
RETROK_DELETE, KEYCODE_DEL,
RETROK_RSHIFT, KEYCODE_SHIFT_RIGHT,
RETROK_LSHIFT, KEYCODE_SHIFT_LEFT,
RETROK_LCTRL, KEYCODE_CTRL_LEFT,
RETROK_END, KEYCODE_MOVE_END,
RETROK_HOME, KEYCODE_MOVE_HOME,
RETROK_PAGEDOWN, KEYCODE_PAGE_DOWN,
RETROK_PAGEUP, KEYCODE_PAGE_UP,
RETROK_LALT, KEYCODE_ALT_LEFT,
RETROK_SPACE, KEYCODE_SPACE,
RETROK_ESCAPE, KEYCODE_ESCAPE,
// RETROK_BACKSPACE, KEYCODE,
RETROK_KP_ENTER, KEYCODE_NUMPAD_ENTER,
RETROK_KP_PLUS, KEYCODE_NUMPAD_ADD,
RETROK_KP_MINUS, KEYCODE_NUMPAD_SUBTRACT,
RETROK_KP_MULTIPLY, KEYCODE_NUMPAD_MULTIPLY,
RETROK_KP_DIVIDE, KEYCODE_NUMPAD_DIVIDE,
// RETROK_BACKQUOTE, KEYCODE,
// RETROK_PAUSE, KEYCODE,
RETROK_KP0, KEYCODE_NUMPAD_0,
RETROK_KP1, KEYCODE_NUMPAD_1,
RETROK_KP2, KEYCODE_NUMPAD_2,
RETROK_KP3, KEYCODE_NUMPAD_3,
RETROK_KP4, KEYCODE_NUMPAD_4,
RETROK_KP5, KEYCODE_NUMPAD_5,
RETROK_KP6, KEYCODE_NUMPAD_6,
RETROK_KP7, KEYCODE_NUMPAD_7,
RETROK_KP8, KEYCODE_NUMPAD_8,
RETROK_KP9, KEYCODE_NUMPAD_9,
RETROK_0, KEYCODE_0,
RETROK_1, KEYCODE_1,
RETROK_2, KEYCODE_2,
RETROK_3, KEYCODE_3,
RETROK_4, KEYCODE_4,
RETROK_5, KEYCODE_5,
RETROK_6, KEYCODE_6,
RETROK_7, KEYCODE_7,
RETROK_8, KEYCODE_8,
RETROK_9, KEYCODE_9,
RETROK_F1, KEYCODE_F1,
RETROK_F2, KEYCODE_F2,
RETROK_F3, KEYCODE_F3,
RETROK_F4, KEYCODE_F4,
RETROK_F5, KEYCODE_F5,
RETROK_F6, KEYCODE_F6,
RETROK_F7, KEYCODE_F7,
RETROK_F8, KEYCODE_F8,
RETROK_F9, KEYCODE_F9,
RETROK_F10, KEYCODE_F10,
RETROK_F11, KEYCODE_F11,
RETROK_F12, KEYCODE_F12,
RETROK_a, KEYCODE_A,
RETROK_b, KEYCODE_B,
RETROK_c, KEYCODE_C,
RETROK_d, KEYCODE_D,
RETROK_e, KEYCODE_E,
RETROK_f, KEYCODE_F,
RETROK_g, KEYCODE_G,
RETROK_h, KEYCODE_H,
RETROK_i, KEYCODE_I,
RETROK_j, KEYCODE_J,
RETROK_k, KEYCODE_K,
RETROK_l, KEYCODE_L,
RETROK_m, KEYCODE_M,
RETROK_n, KEYCODE_N,
RETROK_o, KEYCODE_O,
RETROK_p, KEYCODE_P,
RETROK_q, KEYCODE_Q,
RETROK_r, KEYCODE_R,
RETROK_s, KEYCODE_S,
RETROK_t, KEYCODE_T,
RETROK_u, KEYCODE_U,
RETROK_v, KEYCODE_V,
RETROK_w, KEYCODE_W,
RETROK_x, KEYCODE_X,
RETROK_y, KEYCODE_Y,
RETROK_z, KEYCODE_Z,
};
}

View File

@ -1,11 +0,0 @@
package org.andretro.system;
import android.util.Log;
public class Logger
{
public static void d(String m)
{
Log.d("andretro", m);
}
}

View File

@ -1,9 +0,0 @@
package org.andretro.system;
public class PngWriter
{
public static boolean write(final String aFileName)
{
return false;
}
}

View File

@ -1,124 +0,0 @@
package org.andretro.system;
import org.andretro.R;
import org.andretro.emulator.*;
import org.libretro.*;
import org.andretro.system.video.*;
import java.io.*;
import javax.microedition.khronos.opengles.*;
import android.content.*;
import android.opengl.*;
import static android.opengl.GLES20.*;
// NOT THREAD SAFE
public final class Present implements GLSurfaceView.Renderer
{
final LibRetro.VideoFrame frame = new LibRetro.VideoFrame();
public static class Texture
{
private static final int id[] = new int[1];
private static boolean smoothMode = true;
private static void create()
{
glGenTextures(1, id, 0);
glBindTexture(GL_TEXTURE_2D, id[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
setSmoothMode(smoothMode);
}
public static void setSmoothMode(boolean aEnable)
{
smoothMode = aEnable;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aEnable ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aEnable ? GL_LINEAR : GL_NEAREST);
}
}
private static int programID;
private static String vertexShader;
private static String fragmentShader;
// OpenGL Renderer
private static String getShaderString(final InputStream aSource)
{
String source = "";
try
{
source = new java.util.Scanner(aSource).useDelimiter("\\A").next();
aSource.close();
}
catch(IOException e)
{
}
return source;
}
private static int buildShader(int aType, final String aSource)
{
int result = glCreateShader(aType);
glShaderSource(result, aSource);
glCompileShader(result);
int[] state = new int[1];
glGetShaderiv(result, GL_COMPILE_STATUS, state, 0);
if(0 == state[0])
{
System.out.println(glGetShaderInfoLog(result));
}
return result;
}
public static GLSurfaceView.Renderer createRenderer(Context aContext)
{
vertexShader = getShaderString(aContext.getResources().openRawResource(R.raw.vertex_shader));
fragmentShader = getShaderString(aContext.getResources().openRawResource(R.raw.fragment_shader));
return new Present();
}
@Override public void onSurfaceCreated(GL10 gl, javax.microedition.khronos.egl.EGLConfig config)
{
// Program
programID = glCreateProgram();
glAttachShader(programID, buildShader(GL_VERTEX_SHADER, vertexShader));
glAttachShader(programID, buildShader(GL_FRAGMENT_SHADER, fragmentShader));
glBindAttribLocation(programID, 0, "pos");
glBindAttribLocation(programID, 1, "tex");
glLinkProgram(programID);
glUseProgram(programID);
// Objects
Texture.create();
VertexData.create();
}
@Override public void onSurfaceChanged(GL10 gl, int aWidth, int aHeight)
{
glViewport(0, 0, aWidth, aHeight);
VertexData.setScreenSize(aWidth, aHeight);
frame.restarted = true;
}
@Override public void onDrawFrame(GL10 gl)
{
if(Game.doFrame(frame))
{
VertexData.setImageData(frame.width, frame.height, frame.aspect, frame.rotation);
}
VertexData.draw();
}
}

View File

@ -1,148 +0,0 @@
package org.andretro.system.video;
import static android.opengl.GLES20.*;
import android.graphics.*;
import java.nio.*;
class Size
{
public final float aspect;
public final float w;
public final float h;
public Size(Point aPoint)
{
w = (float)aPoint.x;
h = (float)aPoint.y;
aspect = (w / h);
}
}
public class VertexData
{
private static final float TEXTURESIZE = 1024.0f;
private static final int BUFFERSIZE = (16 * 4);
private static final int[] id = new int[1];
private static final float[] vertexData = new float[]
{
-1, 1, 0, 0, 1, 1, 1, 0, -1, -1, 0, 1, 1, -1, 1, 1,
-1, 1, 1, 0, 1, 1, 1, 1, -1, -1, 0, 0, 1, -1, 0, 1,
-1, 1, 1, 1, 1, 1, 0, 1, -1, -1, 1, 0, 1, -1, 0, 0,
-1, 1, 0, 1, 1, 1, 0, 0, -1, -1, 1, 1, 1, -1, 1, 0
};
private static final Point screenSize = new Point();
private static final Point imageSize = new Point();
private static final Rect imageArea = new Rect();
private static float aspect;
private static int rotate;
private static boolean aspectMode = false;
private static float aspectForce = 0.0f;
private static boolean needUpdate = true;
public static void create()
{
glGenBuffers(1, id, 0);
glBindBuffer(GL_ARRAY_BUFFER, id[0]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 4 * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 4 * 4, 4 * 2);
needUpdate = true;
}
public static void setScreenSize(int aWidth, int aHeight)
{
needUpdate = needUpdate || !screenSize.equals(aWidth, aHeight);
screenSize.set(aWidth, aHeight);
}
public static void setImageData(int aWidth, int aHeight, float aAspect, int aRotate)
{
needUpdate = needUpdate || !imageSize.equals(aWidth, aHeight) || (aRotate != rotate) || (aAspect != aspect);
imageSize.set(aWidth, aHeight);
aspect = aAspect;
rotate = aRotate;
}
public static void setForcedAspect(boolean aUseCustom, float aAspect)
{
needUpdate = needUpdate || (aUseCustom != aspectMode) || (aUseCustom && (aAspect != aspectForce));
aspectMode = aUseCustom;
aspectForce = aAspect;
}
public static Point getScreenSize()
{
// TODO: Ensure it can't be changed!
return screenSize;
}
public static Rect getImageArea()
{
// TODO: Ensure it can't be changed!
return imageArea;
}
public static void draw()
{
if(needUpdate)
{
update();
needUpdate = false;
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
private static void update()
{
final FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(BUFFERSIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
final Size scrS = new Size(screenSize);
final Size imgS = new Size(imageSize);
float inputAspect = getBestImageAspect(imgS, (rotate & 1) == 1);
float width = (!(scrS.aspect < inputAspect)) ? scrS.h * inputAspect : scrS.w;
float height = (scrS.aspect < inputAspect) ? scrS.w / inputAspect : scrS.h;
for(int i = 0; i != 4; i ++)
{
int idx = (i * 4) + (rotate * 16);
vertexBuffer.put((i * 4) + 0, (vertexData[idx + 0] * width) / scrS.w);
vertexBuffer.put((i * 4) + 1, (vertexData[idx + 1] * height) / scrS.h);
vertexBuffer.put((i * 4) + 2, ((vertexData[idx + 2] * imgS.w) - (.5f * vertexData[idx + 2])) / TEXTURESIZE);
vertexBuffer.put((i * 4) + 3, ((vertexData[idx + 3] * imgS.h) - (.5f * vertexData[idx + 3])) / TEXTURESIZE);
}
glBufferData(GL_ARRAY_BUFFER, BUFFERSIZE, vertexBuffer.position(0), GL_STATIC_DRAW);
// Calculate the position of the upper left pixel of the screen
imageArea.left = (int)(scrS.w - width) / 2;
imageArea.top = (int)(scrS.h - height) / 2;
imageArea.right = imageArea.left + (int)width;
imageArea.bottom = imageArea.top + (int)height;
}
private static float getBestImageAspect(Size aImageSize, boolean aInvert)
{
float result = aImageSize.aspect;
if(aspectMode && aspectForce > 0.0f) result = aspectForce;
else if(!aspectMode && aspect > 0.0f) result = aspect;
return aInvert ? (1.0f / result) : result;
}
}

View File

@ -1,319 +0,0 @@
package org.libretro;
import java.nio.*;
public final class LibRetro
{
public static final int RETRO_API_VERSION = 1;
public static final int RETRO_DEVICE_MASK = 0xff;
public static final int RETRO_DEVICE_NONE = 0;
public static final int RETRO_DEVICE_JOYPAD = 1;
public static final int RETRO_DEVICE_MOUSE = 2;
public static final int RETRO_DEVICE_KEYBOARD = 3;
public static final int RETRO_DEVICE_LIGHTGUN = 4;
public static final int RETRO_DEVICE_ANALOG = 5;
public static final int RETRO_DEVICE_POINTER = 6;
public static final int RETRO_DEVICE_JOYPAD_MULTITAP = ((1 << 8) | RETRO_DEVICE_JOYPAD);
public static final int RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE = ((1 << 8) | RETRO_DEVICE_LIGHTGUN);
public static final int RETRO_DEVICE_LIGHTGUN_JUSTIFIER = ((2 << 8) | RETRO_DEVICE_LIGHTGUN);
public static final int RETRO_DEVICE_LIGHTGUN_JUSTIFIERS = ((3 << 8) | RETRO_DEVICE_LIGHTGUN);
public static final int RETRO_DEVICE_ID_JOYPAD_B = 0;
public static final int RETRO_DEVICE_ID_JOYPAD_Y = 1;
public static final int RETRO_DEVICE_ID_JOYPAD_SELECT = 2;
public static final int RETRO_DEVICE_ID_JOYPAD_START = 3;
public static final int RETRO_DEVICE_ID_JOYPAD_UP = 4;
public static final int RETRO_DEVICE_ID_JOYPAD_DOWN = 5;
public static final int RETRO_DEVICE_ID_JOYPAD_LEFT = 6;
public static final int RETRO_DEVICE_ID_JOYPAD_RIGHT = 7;
public static final int RETRO_DEVICE_ID_JOYPAD_A = 8;
public static final int RETRO_DEVICE_ID_JOYPAD_X = 9;
public static final int RETRO_DEVICE_ID_JOYPAD_L = 10;
public static final int RETRO_DEVICE_ID_JOYPAD_R = 11;
public static final int RETRO_DEVICE_ID_JOYPAD_L2 = 12;
public static final int RETRO_DEVICE_ID_JOYPAD_R2 = 13;
public static final int RETRO_DEVICE_ID_JOYPAD_L3 = 14;
public static final int RETRO_DEVICE_ID_JOYPAD_R3 = 15;
public static final int RETRO_DEVICE_INDEX_ANALOG_LEFT = 0;
public static final int RETRO_DEVICE_INDEX_ANALOG_RIGHT = 1;
public static final int RETRO_DEVICE_ID_ANALOG_X = 0;
public static final int RETRO_DEVICE_ID_ANALOG_Y = 1;
public static final int RETRO_DEVICE_ID_MOUSE_X = 0;
public static final int RETRO_DEVICE_ID_MOUSE_Y = 1;
public static final int RETRO_DEVICE_ID_MOUSE_LEFT = 2;
public static final int RETRO_DEVICE_ID_MOUSE_RIGHT = 3;
public static final int RETRO_DEVICE_ID_LIGHTGUN_X = 0;
public static final int RETRO_DEVICE_ID_LIGHTGUN_Y = 1;
public static final int RETRO_DEVICE_ID_LIGHTGUN_TRIGGER = 2;
public static final int RETRO_DEVICE_ID_LIGHTGUN_CURSOR = 3;
public static final int RETRO_DEVICE_ID_LIGHTGUN_TURBO = 4;
public static final int RETRO_DEVICE_ID_LIGHTGUN_PAUSE = 5;
public static final int RETRO_DEVICE_ID_LIGHTGUN_START = 6;
public static final int RETRO_REGION_NTSC = 0;
public static final int RETRO_REGION_PAL = 1;
public static final int RETRO_MEMORY_MASK = 0xff;
public static final int RETRO_MEMORY_SAVE_RAM = 0;
public static final int RETRO_MEMORY_RTC = 1;
public static final int RETRO_MEMORY_SYSTEM_RAM = 2;
public static final int RETRO_MEMORY_VIDEO_RAM = 3;
public static final int RETRO_MEMORY_SNES_BSX_RAM = ((1 << 8) | RETRO_MEMORY_SAVE_RAM);
public static final int RETRO_MEMORY_SNES_BSX_PRAM = ((2 << 8) | RETRO_MEMORY_SAVE_RAM);
public static final int RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM = ((3 << 8) | RETRO_MEMORY_SAVE_RAM);
public static final int RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM = ((4 << 8) | RETRO_MEMORY_SAVE_RAM);
public static final int RETRO_MEMORY_SNES_GAME_BOY_RAM = ((5 << 8) | RETRO_MEMORY_SAVE_RAM);
public static final int RETRO_MEMORY_SNES_GAME_BOY_RTC = ((6 << 8) | RETRO_MEMORY_RTC);
public static final int RETRO_GAME_TYPE_BSX = 0x101;
public static final int RETRO_GAME_TYPE_BSX_SLOTTED = 0x102;
public static final int RETRO_GAME_TYPE_SUFAMI_TURBO = 0x103;
public static final int RETRO_GAME_TYPE_SUPER_GAME_BOY = 0x104;
public static final int RETRO_PIXEL_FORMAT_0RGB1555 = 0;
public static final int RETRO_PIXEL_FORMAT_XRGB8888 = 1;
public static final int RETRO_PIXEL_FORMAT_RGB565 = 2;
public static final int RETROK_UNKNOWN = 0;
public static final int RETROK_FIRST = 0;
public static final int RETROK_BACKSPACE = 8;
public static final int RETROK_TAB = 9;
public static final int RETROK_CLEAR = 12;
public static final int RETROK_RETURN = 13;
public static final int RETROK_PAUSE = 19;
public static final int RETROK_ESCAPE = 27;
public static final int RETROK_SPACE = 32;
public static final int RETROK_EXCLAIM = 33;
public static final int RETROK_QUOTEDBL = 34;
public static final int RETROK_HASH = 35;
public static final int RETROK_DOLLAR = 36;
public static final int RETROK_AMPERSAND = 38;
public static final int RETROK_QUOTE = 39;
public static final int RETROK_LEFTPAREN = 40;
public static final int RETROK_RIGHTPAREN = 41;
public static final int RETROK_ASTERISK = 42;
public static final int RETROK_PLUS = 43;
public static final int RETROK_COMMA = 44;
public static final int RETROK_MINUS = 45;
public static final int RETROK_PERIOD = 46;
public static final int RETROK_SLASH = 47;
public static final int RETROK_0 = 48;
public static final int RETROK_1 = 49;
public static final int RETROK_2 = 50;
public static final int RETROK_3 = 51;
public static final int RETROK_4 = 52;
public static final int RETROK_5 = 53;
public static final int RETROK_6 = 54;
public static final int RETROK_7 = 55;
public static final int RETROK_8 = 56;
public static final int RETROK_9 = 57;
public static final int RETROK_COLON = 58;
public static final int RETROK_SEMICOLON = 59;
public static final int RETROK_LESS = 60;
public static final int RETROK_EQUALS = 61;
public static final int RETROK_GREATER = 62;
public static final int RETROK_QUESTION = 63;
public static final int RETROK_AT = 64;
public static final int RETROK_LEFTBRACKET = 91;
public static final int RETROK_BACKSLASH = 92;
public static final int RETROK_RIGHTBRACKET = 93;
public static final int RETROK_CARET = 94;
public static final int RETROK_UNDERSCORE = 95;
public static final int RETROK_BACKQUOTE = 96;
public static final int RETROK_a = 97;
public static final int RETROK_b = 98;
public static final int RETROK_c = 99;
public static final int RETROK_d = 100;
public static final int RETROK_e = 101;
public static final int RETROK_f = 102;
public static final int RETROK_g = 103;
public static final int RETROK_h = 104;
public static final int RETROK_i = 105;
public static final int RETROK_j = 106;
public static final int RETROK_k = 107;
public static final int RETROK_l = 108;
public static final int RETROK_m = 109;
public static final int RETROK_n = 110;
public static final int RETROK_o = 111;
public static final int RETROK_p = 112;
public static final int RETROK_q = 113;
public static final int RETROK_r = 114;
public static final int RETROK_s = 115;
public static final int RETROK_t = 116;
public static final int RETROK_u = 117;
public static final int RETROK_v = 118;
public static final int RETROK_w = 119;
public static final int RETROK_x = 120;
public static final int RETROK_y = 121;
public static final int RETROK_z = 122;
public static final int RETROK_DELETE = 127;
public static final int RETROK_KP0 = 256;
public static final int RETROK_KP1 = 257;
public static final int RETROK_KP2 = 258;
public static final int RETROK_KP3 = 259;
public static final int RETROK_KP4 = 260;
public static final int RETROK_KP5 = 261;
public static final int RETROK_KP6 = 262;
public static final int RETROK_KP7 = 263;
public static final int RETROK_KP8 = 264;
public static final int RETROK_KP9 = 265;
public static final int RETROK_KP_PERIOD = 266;
public static final int RETROK_KP_DIVIDE = 267;
public static final int RETROK_KP_MULTIPLY = 268;
public static final int RETROK_KP_MINUS = 269;
public static final int RETROK_KP_PLUS = 270;
public static final int RETROK_KP_ENTER = 271;
public static final int RETROK_KP_EQUALS = 272;
public static final int RETROK_UP = 273;
public static final int RETROK_DOWN = 274;
public static final int RETROK_RIGHT = 275;
public static final int RETROK_LEFT = 276;
public static final int RETROK_INSERT = 277;
public static final int RETROK_HOME = 278;
public static final int RETROK_END = 279;
public static final int RETROK_PAGEUP = 280;
public static final int RETROK_PAGEDOWN = 281;
public static final int RETROK_F1 = 282;
public static final int RETROK_F2 = 283;
public static final int RETROK_F3 = 284;
public static final int RETROK_F4 = 285;
public static final int RETROK_F5 = 286;
public static final int RETROK_F6 = 287;
public static final int RETROK_F7 = 288;
public static final int RETROK_F8 = 289;
public static final int RETROK_F9 = 290;
public static final int RETROK_F10 = 291;
public static final int RETROK_F11 = 292;
public static final int RETROK_F12 = 293;
public static final int RETROK_F13 = 294;
public static final int RETROK_F14 = 295;
public static final int RETROK_F15 = 296;
public static final int RETROK_NUMLOCK = 300;
public static final int RETROK_CAPSLOCK = 301;
public static final int RETROK_SCROLLOCK = 302;
public static final int RETROK_RSHIFT = 303;
public static final int RETROK_LSHIFT = 304;
public static final int RETROK_RCTRL = 305;
public static final int RETROK_LCTRL = 306;
public static final int RETROK_RALT = 307;
public static final int RETROK_LALT = 308;
public static final int RETROK_RMETA = 309;
public static final int RETROK_LMETA = 310;
public static final int RETROK_LSUPER = 311;
public static final int RETROK_RSUPER = 312;
public static final int RETROK_MODE = 313;
public static final int RETROK_COMPOSE = 314;
public static final int RETROK_HELP = 315;
public static final int RETROK_PRINT = 316;
public static final int RETROK_SYSREQ = 317;
public static final int RETROK_BREAK = 318;
public static final int RETROK_MENU = 319;
public static final int RETROK_POWER = 320;
public static final int RETROK_EURO = 321;
public static final int RETROK_UNDO = 322;
public static final int RETROK_LAST = 323;
public static final int RETRO_ENVIRONMENT_SET_ROTATION = 1; // const unsigned * --
public static final int RETRO_ENVIRONMENT_GET_OVERSCAN = 2; // bool * --
public static final int RETRO_ENVIRONMENT_GET_CAN_DUPE = 3; // bool * --
public static final int RETRO_ENVIRONMENT_GET_VARIABLE = 4; // struct retro_variable * --
public static final int RETRO_ENVIRONMENT_SET_VARIABLES = 5; // const struct retro_variable * --
public static final int RETRO_ENVIRONMENT_SET_MESSAGE = 6; // const struct retro_message * --
public static final int RETRO_ENVIRONMENT_SHUTDOWN = 7; // N/A (NULL) --
public static final int RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL = 8;
public static final int RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY = 9;
public static final int RETRO_ENVIRONMENT_SET_PIXEL_FORMAT = 10;
public static class SystemInfo
{
public String libraryName;
public String libraryVersion;
public String validExtensions;
public boolean needFullPath;
public boolean blockExtract;
}
public static class AVInfo
{
public int baseWidth;
public int baseHeight;
public int maxWidth;
public int maxHeight;
public float aspectRatio;
public double fps;
public double sampleRate;
}
public static class VideoFrame
{
public boolean restarted = true;
public int framesToRun;
public boolean rewind;
public int width;
public int height;
public int pixelFormat;
public int rotation;
public float aspect;
public final int[] keyboard = new int[RETROK_LAST];
public final int[] buttons = new int[8];
public short touchX;
public short touchY;
public boolean touched;
public final short[] audio = new short[48000];
public int audioSamples;
}
public static native boolean loadLibrary(String aPath, String aSystemDirectory);
public static native void unloadLibrary();
public static native void init();
public static native void deinit();
public static native int apiVersion();
public static native void getSystemInfo(SystemInfo aInfo);
public static native void getSystemAVInfo(AVInfo aInfo);
public static native void setControllerPortDevice(int aPort, int aDevice);
public static native void reset();
public static native void run(VideoFrame aVideo);
public static native int serializeSize();
// public static native boolean serialize(byte[] aData, int aSize);
// public static native boolean unserialize(byte[] aData, int aSize);
public static native void cheatReset();
public static native void cheatSet(int aIndex, boolean aEnabled, String aCode);
public static native boolean loadGame(String aPath);
public static native void unloadGame();
public static native int getRegion();
public static native int getMemorySize(int aID);
public static native ByteBuffer getMemoryData(int aID);
// Helpers
public static native void setupRewinder(int aDataSize); // 0 or less disables
public static native boolean writeMemoryRegion(int aID, String aFileName);
public static native boolean readMemoryRegion(int aID, String aFileBase);
public static native boolean serializeToFile(String aPath);
public static native boolean unserializeFromFile(String aPath);
public static native boolean nativeInit();
}