1
1
Fork 0
mirror of https://github.com/QB64-Phoenix-Edition/QB64pe.git synced 2024-06-26 17:10:38 +00:00

Implements the _DIR$("desktop") function which returns OS specific paths.

Implements changes to allow programs to run on ARMBI-v7 Android devices which also provides a massive performance boost to but runtime and startup time.
Implements changes to allow programs to run on x86-based Android devices.
Fix to ensure variables allocated in the "stack" are aligned on appropriate boundaries which would have otherwise crashed on Android.
Fix to _DEVICES to ensure variables are aligned on appropriate boundaries which would have otherwise crashed on Android (includes some refactoring).
Added permissions to allow reading from/writing to external storage. Use the _DIR$(...) function to help locate appropriate paths.
This commit is contained in:
Galleondragon 2016-03-20 18:56:10 +11:00
parent ff2802131a
commit 0ea631d375
8 changed files with 425 additions and 296 deletions

View file

@ -73,6 +73,9 @@
#define int64 __int64
#endif
//#include <Shlobj.h>
#include <shfolder.h>
#include <float.h>
#include <winbase.h>
@ -92,7 +95,7 @@
#include <time.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
//OS/compiler specific includes
#ifdef QB64_WINDOWS
@ -435,7 +438,23 @@ struct device_struct{
int32 balls;
int32 hats;
};
//device_struct constants
#define QUEUED_EVENTS_LIMIT 1024
#define DEVICETYPE_CONTROLLER 1
#define DEVICETYPE_KEYBOARD 2
#define DEVICETYPE_MOUSE 3
struct mem_block{
ptrszint offset;

View file

@ -52,6 +52,7 @@
#ifdef QB64_WINDOWS
#include <fcntl.h>
#include <shellapi.h>
#endif
@ -1165,7 +1166,9 @@ int32 mem_lock_freed_max=1000;//number of allocated entries
int32 mem_lock_freed_n=0;//number of entries
ptrszint *mem_lock_freed=(ptrszint*)malloc(sizeof(ptrszint)*mem_lock_freed_max);
inline void new_mem_lock(){
//inline removed because it is incompatible with Android studio x86 build
void new_mem_lock(){
if (mem_lock_freed_n){
mem_lock_tmp=(mem_lock*)mem_lock_freed[--mem_lock_freed_n];
}else{
@ -1175,7 +1178,7 @@ inline void new_mem_lock(){
mem_lock_tmp->id=++mem_lock_id;
}
inline void free_mem_lock(mem_lock *lock){
void free_mem_lock(mem_lock *lock){
lock->id=0;//invalidate lock
if (lock->type==1) free(lock->offset);//malloc type
//add to freed list
@ -1270,6 +1273,18 @@ extern int32 device_last;
extern int32 device_max;
extern device_struct *devices;
extern uint8 getDeviceEventButtonValue(device_struct *device, int32 eventIndex, int32 objectIndex);
extern void setDeviceEventButtonValue(device_struct *device, int32 eventIndex, int32 objectIndex, uint8 value);
extern float getDeviceEventAxisValue(device_struct *device, int32 eventIndex, int32 objectIndex);
extern void setDeviceEventAxisValue(device_struct *device, int32 eventIndex, int32 objectIndex, float value);
extern float getDeviceEventWheelValue(device_struct *device, int32 eventIndex, int32 objectIndex);
extern void setDeviceEventWheelValue(device_struct *device, int32 eventIndex, int32 objectIndex, float value);
extern void setupDevice(device_struct *device);
extern int32 createDeviceEvent(device_struct *device);
extern void commitDeviceEvent(device_struct *device);
extern ontimer_struct *ontimer;
extern onkey_struct *onkey;
extern int32 onkey_inprogress;
@ -7414,6 +7429,7 @@ extern uint8 *mem_static_pointer;
extern uint8 *mem_static_limit;
uint8 *mem_static_malloc(uint32 size){
size+=7; size-=(size&7);//align to 8 byte boundry
if ((mem_static_pointer+=size)<mem_static_limit) return mem_static_pointer-size;
mem_static_size=(mem_static_size<<1)+size;
mem_static=(uint8*)malloc(mem_static_size);
@ -28670,7 +28686,7 @@ void sub__maptriangle(int32 cull_options,float sx1,float sy1,float sx2,float sy2
if (d->type==1){
if (i==i2){
if (axis<d->lastaxis){
f=*(float*)(d->events+(d->event_size*(d->queued_events-1))+d->lastbutton+axis*4);
f=getDeviceEventAxisValue(d,d->queued_events-1,axis);
if (f>-0.01&&f<=0.01) f=0;
v=qbr_float_to_long(f*127.0)+127;
if (v>254) v=254;
@ -28716,7 +28732,7 @@ void sub__maptriangle(int32 cull_options,float sx1,float sy1,float sx2,float sy2
return 0;
}else{
//method 2: currently down
v=*(d->events+(d->event_size*(d->queued_events-1))+(button-1));
v=getDeviceEventButtonValue(d,d->queued_events-1,button-1);
if (v) return -1; else return 0;
}
}//button exists
@ -29474,6 +29490,155 @@ qbs *func__startdir(){
return temp;
}
qbs *rootDir=NULL;//the dir moved to when program begins
char *android_dir_downloads=NULL;
char *android_dir_documents=NULL;
char *android_dir_pictures=NULL;
char *android_dir_music=NULL;
char *android_dir_video=NULL;
char *android_dir_dcim=NULL;
qbs *func__dir(qbs* context_in){
static qbs *context=NULL;
if (!context){context=qbs_new(0,0);}
qbs_set(context,qbs_ucase(context_in));
if (qbs_equal(qbs_ucase(context),qbs_new_txt("TEXT"))||qbs_equal(qbs_ucase(context),qbs_new_txt("DOCUMENT"))||qbs_equal(qbs_ucase(context),qbs_new_txt("DOCUMENTS"))||qbs_equal(qbs_ucase(context),qbs_new_txt("MY DOCUMENTS"))){
#ifdef QB64_ANDROID
mkdir(android_dir_documents,0770);
return qbs_new_txt(android_dir_documents);
#endif
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,5,NULL,0,osPath))){ //Documents
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\"));
}
#endif
}
if (qbs_equal(qbs_ucase(context),qbs_new_txt("MUSIC"))||qbs_equal(qbs_ucase(context),qbs_new_txt("AUDIO"))||qbs_equal(qbs_ucase(context),qbs_new_txt("SOUND"))||qbs_equal(qbs_ucase(context),qbs_new_txt("SOUNDS"))||qbs_equal(qbs_ucase(context),qbs_new_txt("MY MUSIC"))){
#ifdef QB64_ANDROID
mkdir(android_dir_music,0770);
return qbs_new_txt(android_dir_music);
#endif
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,13,NULL,0,osPath))){ //Music
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\"));
}
#endif
}
if (qbs_equal(qbs_ucase(context),qbs_new_txt("PICTURE"))||qbs_equal(qbs_ucase(context),qbs_new_txt("PICTURES"))||qbs_equal(qbs_ucase(context),qbs_new_txt("IMAGE"))||qbs_equal(qbs_ucase(context),qbs_new_txt("IMAGES"))||qbs_equal(qbs_ucase(context),qbs_new_txt("MY PICTURES"))){
#ifdef QB64_ANDROID
mkdir(android_dir_pictures,0770);
return qbs_new_txt(android_dir_pictures);
#endif
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,39,NULL,0,osPath))){//Pictures
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\"));
}
#endif
}
if (qbs_equal(qbs_ucase(context),qbs_new_txt("DCIM"))||qbs_equal(qbs_ucase(context),qbs_new_txt("CAMERA"))||qbs_equal(qbs_ucase(context),qbs_new_txt("CAMERA ROLL"))||qbs_equal(qbs_ucase(context),qbs_new_txt("PHOTO"))||qbs_equal(qbs_ucase(context),qbs_new_txt("PHOTOS"))){
#ifdef QB64_ANDROID
mkdir(android_dir_dcim,0770);
return qbs_new_txt(android_dir_dcim);
#endif
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,39,NULL,0,osPath))){//Pictures
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\"));
}
#endif
}
if (qbs_equal(qbs_ucase(context),qbs_new_txt("MOVIE"))||qbs_equal(qbs_ucase(context),qbs_new_txt("MOVIES"))||qbs_equal(qbs_ucase(context),qbs_new_txt("VIDEO"))||qbs_equal(qbs_ucase(context),qbs_new_txt("VIDEOS"))||qbs_equal(qbs_ucase(context),qbs_new_txt("MY VIDEOS"))){
#ifdef QB64_ANDROID
mkdir(android_dir_video,0770);
return qbs_new_txt(android_dir_video);
#endif
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,14,NULL,0,osPath))){ //Videos
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\"));
}
#endif
}
if (qbs_equal(qbs_ucase(context),qbs_new_txt("DOWNLOAD"))||qbs_equal(qbs_ucase(context),qbs_new_txt("DOWNLOADS"))){
#ifdef QB64_ANDROID
mkdir(android_dir_downloads,0770);
return qbs_new_txt(android_dir_downloads);
#endif
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,0x0028,NULL,0,osPath))){//user folder
//XP & SHGetFolderPathA do not support the concept of a Downloads folder, however it can be constructed
mkdir((char*)((qbs_add(qbs_new_txt(osPath),qbs_new_txt_len("\\Downloads\0",11)))->chr));
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\Downloads\\"));
}
#endif
}
if (qbs_equal(qbs_ucase(context),qbs_new_txt("DESKTOP"))){
#ifdef QB64_ANDROID
mkdir(android_dir_downloads,0770);
return qbs_new_txt(android_dir_downloads);
#endif
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,0,NULL,0,osPath))){ //Desktop
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\"));
}
#endif
}
if (qbs_equal(qbs_ucase(context),qbs_new_txt("APPDATA"))||qbs_equal(qbs_ucase(context),qbs_new_txt("APPLICATION DATA"))||qbs_equal(qbs_ucase(context),qbs_new_txt("PROGRAM DATA"))||qbs_equal(qbs_ucase(context),qbs_new_txt("DATA"))){
#ifdef QB64_ANDROID
return qbs_add(rootDir,qbs_new_txt("/"));
#endif
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,0x001a,NULL,0,osPath))){ //CSIDL_APPDATA (%APPDATA%)
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\"));
}
#endif
}
if (qbs_equal(qbs_ucase(context),qbs_new_txt("LOCALAPPDATA"))||qbs_equal(qbs_ucase(context),qbs_new_txt("LOCAL APPLICATION DATA"))||qbs_equal(qbs_ucase(context),qbs_new_txt("LOCAL PROGRAM DATA"))||qbs_equal(qbs_ucase(context),qbs_new_txt("LOCAL DATA"))){
#ifdef QB64_ANDROID
return qbs_add(rootDir,qbs_new_txt("/"));
#endif
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,0x001c,NULL,0,osPath))){ //CSIDL_LOCAL_APPDATA (%LOCALAPPDATA%)
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\"));
}
#endif
}
//general fallback location
#ifdef QB64_WINDOWS
CHAR osPath[MAX_PATH];
if(SUCCEEDED(SHGetFolderPathA(NULL,0,NULL,0,osPath))){ //desktop
return qbs_add(qbs_new_txt(osPath),qbs_new_txt("\\"));
}
return qbs_new_txt(".\\");//current location
#else
#ifdef QB64_ANDROID
mkdir(android_dir_downloads,0770);
return qbs_new_txt(android_dir_downloads);
#endif
return qbs_new_txt("./");//current location
#endif
}
extern void set_dynamic_info();
@ -29519,7 +29684,6 @@ qbs *func__startdir(){
env->ReleaseStringUTFChars( jpath, app_dir);
// Pre-extract assets, to avoid Android-specific file opening
AAssetManager* mgr = app->activity->assetManager;
/* Old code which pulled all root directory assets, in QB64 assets are specified in code so this just wastes time
@ -29533,13 +29697,78 @@ qbs *func__startdir(){
#include "../temp/assets.txt"
//get _DIR$(...) paths
{//upscope
jfieldID fieldId;
jclass envClass = env->FindClass("android/os/Environment");
char** targetString;
jstring jstrParam;
char* s;
jstring sType;
for (int i=1;i<=6;i++){
if (i==1){
targetString=&android_dir_dcim;
fieldId=env->GetStaticFieldID(envClass, "DIRECTORY_DCIM", "Ljava/lang/String;");
}
if (i==2){
targetString=&android_dir_downloads;
fieldId=env->GetStaticFieldID(envClass, "DIRECTORY_DOWNLOADS", "Ljava/lang/String;");
}
if (i==3){
targetString=&android_dir_documents;
fieldId=env->GetStaticFieldID(envClass, "DIRECTORY_DOCUMENTS", "Ljava/lang/String;");
}
if (i==4){
targetString=&android_dir_pictures;
fieldId=env->GetStaticFieldID(envClass, "DIRECTORY_PICTURES", "Ljava/lang/String;");
}
if (i==5){
targetString=&android_dir_music;
fieldId=env->GetStaticFieldID(envClass, "DIRECTORY_MUSIC", "Ljava/lang/String;");
}
if (i==6){
targetString=&android_dir_video;
fieldId=env->GetStaticFieldID(envClass, "DIRECTORY_MOVIES", "Ljava/lang/String;");
}
//retrieve jstring representation of environment variable
jstrParam = (jstring)env->GetStaticObjectField(envClass, fieldId);
s = env->GetStringUTFChars(jstrParam, NULL);
LOGI("String name of Environment.Variable: %s", s);
env->ReleaseStringUTFChars(jstrParam, s);
//use jstring representation to retrieve folder name
sType=jstrParam;
jmethodID midEnvironmentGetExternalStoragePublicDirectory = env->GetStaticMethodID(envClass, "getExternalStoragePublicDirectory", "(Ljava/lang/String;)Ljava/io/File;");
jobject oExternalStorageDirectory = NULL;
oExternalStorageDirectory = env->CallStaticObjectMethod(envClass, midEnvironmentGetExternalStoragePublicDirectory, sType);
jclass cFile = env->GetObjectClass(oExternalStorageDirectory);
jmethodID midFileGetAbsolutePath = env->GetMethodID(cFile, "getAbsolutePath", "()Ljava/lang/String;");
env->DeleteLocalRef(cFile);
jstring extStoragePath = (jstring)env->CallObjectMethod(oExternalStorageDirectory, midFileGetAbsolutePath);
const char* extStoragePathString = env->GetStringUTFChars(extStoragePath, NULL);
LOGI("Path: %s", extStoragePathString);// /storage/emulated/0/Download
*targetString=(char*)calloc(1,strlen(extStoragePathString)+2);
memcpy(*targetString,extStoragePathString,strlen(extStoragePathString));
(*targetString)[strlen(extStoragePathString)]=47;//append "/"
env->ReleaseStringUTFChars(extStoragePath, extStoragePathString);
env->DeleteLocalRef(sType);
}
}//downscope
//JavaVMAttachArgs args = { JNI_VERSION_1_6, NULL, NULL };
//vm->AttachCurrentThread( &env, &args );
//not sure why we do this...
//jmethodID activityConstructor = env->GetMethodID(app->activity->clazz, "<init>", "()V");
//jobject object = env->NewObject(app->activity->clazz, activityConstructor);
@ -29968,6 +30197,9 @@ qbs_set(startDir,func__cwd());
#endif
#endif
rootDir=qbs_new(0,0);
qbs_set(rootDir,func__cwd());
unknown_opcode_mess=qbs_new(0,0);
qbs_set(unknown_opcode_mess,qbs_new_txt_len("Unknown Opcode ( )\0",20));
@ -30324,39 +30556,27 @@ qbs_set(startDir,func__cwd());
//Init _DEVICEs
i=1;
//setup default _DEVICE(s)
i=0;
//keyboard
devices[i].type=2;
i++;
devices[i].type=DEVICETYPE_KEYBOARD;
devices[i].name="[KEYBOARD][BUTTON]";
devices[i].lastbutton=512;
//calculate queue message size
x=512+8;
devices[i].event_size=x;
//create initial 'current' and 'previous' events
devices[i].events=(uint8*)calloc(2,x);
devices[i].max_events=2;
devices[i].queued_events=2;
devices[i].connected=1;
devices[i].used=1;
devices[i].description="Keyboard";
i++;
setupDevice(&devices[i]);
//mouse
devices[i].type=3;
i++;
devices[i].type=DEVICETYPE_MOUSE;
devices[i].name="[MOUSE][BUTTON][AXIS][WHEEL]";
devices[i].lastbutton=3;
devices[i].lastaxis=2;
devices[i].lastwheel=3;
//calculate queue message size
x=devices[i].lastbutton+devices[i].lastaxis*4+devices[i].lastwheel*4+8;
devices[i].event_size=x;
//create initial 'current' and 'previous' events
devices[i].events=(uint8*)calloc(2,x);
devices[i].max_events=2;
devices[i].queued_events=2;
devices[i].connected=1;
devices[i].used=1;
devices[i].description="Mouse";
setupDevice(&devices[i]);
device_last=i;
@ -32938,29 +33158,14 @@ QB64_GAMEPAD_INIT();
keydown_special:
static device_struct *d;
d=&devices[1];//keyboard
if (*(d->events+((d->queued_events-1)*d->event_size)+code)!=1){//don't add message if already on
uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=(QUEUED_EVENTS_LIMIT/4)){//note: default event limit divied by 4
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
*(d->events+(d->queued_events*d->event_size)+code)=1;
if (special==2){special=1; d->queued_events++; goto keydown_special;}
if (special==1) *(d->events+(d->queued_events*d->event_size)+code)=0;
d->queued_events++;
if (getDeviceEventButtonValue(d,d->queued_events-1,code)!=1){//don't add message if already on
int32 eventIndex=createDeviceEvent(d);
setDeviceEventButtonValue(d,eventIndex,code,1);
if (special==2){special=1; commitDeviceEvent(d); goto keydown_special;}//jump to ~5 lines above to add a 2nd key event
if (special==1) setDeviceEventButtonValue(d,eventIndex,code,0);
commitDeviceEvent(d);
}//not 1
}//core devices required
@ -32982,27 +33187,12 @@ QB64_GAMEPAD_INIT();
static device_struct *d;
d=&devices[1];//keyboard
if (*(d->events+((d->queued_events-1)*d->event_size)+code)!=0){//don't add message if already on
uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=(QUEUED_EVENTS_LIMIT/4)){//note: default event limit divied by 4
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
*(d->events+(d->queued_events*d->event_size)+code)=0;
d->queued_events++;
if (getDeviceEventButtonValue(d,d->queued_events-1,code)!=0){//don't add message if already off
int32 eventIndex=createDeviceEvent(d);
setDeviceEventButtonValue(d,eventIndex,code,0);
commitDeviceEvent(d);
}//not 1
}//core devices required
@ -33311,4 +33501,4 @@ sub__limit( 10 );
sub__display();
}while(1);
//infinite loop (this function never exits)
}
}

View file

@ -1950,26 +1950,11 @@ if (src_hardware_img->source_state.PO2_fix){
button--;
static device_struct *d;
d=&devices[2];//mouse
static uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
*(d->events+(d->queued_events*d->event_size)+button)=0;
d->queued_events++;
int32 eventIndex=createDeviceEvent(d);
setDeviceEventButtonValue(d,eventIndex,button,0);
commitDeviceEvent(d);
}//valid range
}//core devices required
@ -2010,26 +1995,11 @@ if (src_hardware_img->source_state.PO2_fix){
button--;
static device_struct *d;
d=&devices[2];//mouse
static uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
*(d->events+(d->queued_events*d->event_size)+button)=1;
d->queued_events++;
int32 eventIndex=createDeviceEvent(d);
setDeviceEventButtonValue(d,eventIndex,button,1);
commitDeviceEvent(d);
//1-3
}else{
//not 1-3
@ -2039,45 +2009,15 @@ if (src_hardware_img->source_state.PO2_fix){
if (button==4) f=-1; else f=1;
static device_struct *d;
d=&devices[2];//mouse
static uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4+(3-1)*4)=f;
d->queued_events++;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4+(3-1)*4)=0;
d->queued_events++;
int32 eventIndex=createDeviceEvent(d);
setDeviceEventWheelValue(d,eventIndex,2,f);
commitDeviceEvent(d);
eventIndex=createDeviceEvent(d);
setDeviceEventWheelValue(d,eventIndex,2,0);
commitDeviceEvent(d);
}//4-5
}//not 1-3
}//core devices required
@ -2132,25 +2072,8 @@ if (src_hardware_img->source_state.PO2_fix){
if (!device_mouse_relative){
static device_struct *d;
d=&devices[2];//mouse
static uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
int32 eventIndex=createDeviceEvent(d);
static float fx,fy;
static int32 z;
fx=x;
@ -2169,59 +2092,30 @@ if (src_hardware_img->source_state.PO2_fix){
fy=fy/(float)(z-1);//0 to 1
fy*=2.0;//0 to 2
fy-=1.0;//-1 to 1
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton)=fx;
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+4)=fy;
d->queued_events++;
setDeviceEventAxisValue(d,eventIndex,0,fx);
setDeviceEventAxisValue(d,eventIndex,1,fy);
commitDeviceEvent(d);
}else{
static device_struct *d;
d=&devices[2];//mouse
static uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
int32 eventIndex=createDeviceEvent(d);
static float fx,fy;
static int32 z;
fx=xrel;
fy=yrel;
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4)=fx;
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4+4)=fy;
d->queued_events++;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
setDeviceEventWheelValue(d,eventIndex,0,fx);
setDeviceEventWheelValue(d,eventIndex,1,fy);
commitDeviceEvent(d);
eventIndex=createDeviceEvent(d);
fx=0;
fy=0;
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4)=fx;
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4+4)=fy;
d->queued_events++;
setDeviceEventWheelValue(d,eventIndex,0,fx);
setDeviceEventWheelValue(d,eventIndex,1,fy);
commitDeviceEvent(d);
}
}//core devices required
}

View file

@ -73,26 +73,10 @@ void onButtonDown(struct Gamepad_device * device, unsigned int buttonID, double
}
}//within supported range
uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
*(d->events+(d->queued_events*d->event_size)+button)=1;
d->queued_events++;
int32 eventIndex=createDeviceEvent(d);
setDeviceEventButtonValue(d,eventIndex,button,1);
commitDeviceEvent(d);
//set STRIG_button_pressed for button
if (button>=0&&button<=255){
d->STRIG_button_pressed[button]=1;
@ -120,26 +104,11 @@ void onButtonUp(struct Gamepad_device * device, unsigned int buttonID, double ti
if (d->used==1){
if (d->type==1){
if (d->handle_int==device->deviceID){
uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
*(d->events+(d->queued_events*d->event_size)+button)=0;
d->queued_events++;
int32 eventIndex=createDeviceEvent(d);
setDeviceEventButtonValue(d,eventIndex,button,0);
commitDeviceEvent(d);
}//js index
}//type==1
}//used
@ -163,24 +132,7 @@ void onAxisMoved(struct Gamepad_device * device, unsigned int axisID, float valu
if (d->used==1){
if (d->type==1){
if (d->handle_int==device->deviceID){
uint8 *cp,*cp2;
if (d->queued_events==d->max_events){//expand/shift event buffer
if (d->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
d->queued_events--;
}else{
cp=(uint8*)calloc(d->max_events*2,d->event_size);
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
cp2=d->events;
d->events=cp;
free(cp2);
d->max_events*=2;
}
}
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
//make required changes
float f;
f=value;
/*
@ -189,10 +141,11 @@ void onAxisMoved(struct Gamepad_device * device, unsigned int axisID, float valu
*/
if (f>1.0) f=1.0;
if (f<-1.0) f=-1.0;
int32 o;
o=d->lastbutton+axis*4;
*(float*)(d->events+(d->queued_events*d->event_size)+o)=f;
d->queued_events++;
int32 eventIndex=createDeviceEvent(d);
setDeviceEventAxisValue(d,eventIndex,axis,f);
commitDeviceEvent(d);
}//js index
}//type==1
}//used
@ -248,7 +201,7 @@ if (i>device_max){
device_max*=2;
}
memset(&devices[i],0,sizeof(device_struct));
devices[i].type=1;
devices[i].type=DEVICETYPE_CONTROLLER;
devices[i].description=strdup(device->description);
devices[i].handle_int=device->deviceID;
devices[i].buttons=device->numButtons;
@ -265,15 +218,9 @@ if (devices[i].lastbutton) strcat (name,"[BUTTON]");
if (devices[i].lastaxis) strcat (name,"[AXIS]");
if (devices[i].lastwheel) strcat (name,"[WHEEL]");
devices[i].name=strdup(name);
//calculate queue message size
x=devices[i].lastbutton+(devices[i].lastaxis+devices[i].lastwheel)*4+8;
devices[i].event_size=x;
//create initial 'current' and 'previous' events
devices[i].events=(uint8*)calloc(2,x);
devices[i].max_events=2;
devices[i].queued_events=2;
devices[i].connected=1;
devices[i].used=1;
setupDevice(&devices[i]);
device_last=i;
}

View file

@ -122,6 +122,9 @@ void requestKeyboardOverlayImage(int32 handle){
//extern functions
extern qbs *func__dir(qbs* context);
extern int32 func__scaledwidth();
extern int32 func__scaledheight();
@ -1398,6 +1401,64 @@ int32 device_last=0;//last used device
int32 device_max=1000;//number of allocated indexes
device_struct *devices=(device_struct*)calloc(1000+1,sizeof(device_struct));
//device_struct helper functions
uint8 getDeviceEventButtonValue(device_struct *device, int32 eventIndex, int32 objectIndex){
return *(device->events+eventIndex*device->event_size+device->lastaxis*4+device->lastwheel*4+objectIndex);
}
void setDeviceEventButtonValue(device_struct *device, int32 eventIndex, int32 objectIndex, uint8 value){
*(device->events+eventIndex*device->event_size+device->lastaxis*4+device->lastwheel*4+objectIndex)=value;
}
float getDeviceEventAxisValue(device_struct *device, int32 eventIndex, int32 objectIndex){
return *(float*)(device->events+eventIndex*device->event_size+objectIndex*4);
}
void setDeviceEventAxisValue(device_struct *device, int32 eventIndex, int32 objectIndex, float value){
*(float*)(device->events+eventIndex*device->event_size+objectIndex*4)=value;
}
float getDeviceEventWheelValue(device_struct *device, int32 eventIndex, int32 objectIndex){
return *(float*)(device->events+eventIndex*device->event_size+device->lastaxis*4+objectIndex*4);
}
void setDeviceEventWheelValue(device_struct *device, int32 eventIndex, int32 objectIndex, float value){
*(float*)(device->events+eventIndex*device->event_size+device->lastaxis*4+objectIndex*4)=value;
}
void setupDevice(device_struct *device){
int32 size=device->lastaxis*4+device->lastwheel*4+device->lastbutton;
size+=8;//for appended ordering index
size+=7; size=size-(size&7);//align to closest 8-byte boundary
device->event_size=size;
device->events=(uint8*)calloc(2,device->event_size);//create initial 'current' and 'previous' events
device->max_events=2;
device->queued_events=2;
device->connected=1;
device->used=1;
}
int32 createDeviceEvent(device_struct *device){
uint8 *cp,*cp2;
if (device->queued_events==device->max_events){//expand/shift event buffer
if (device->max_events>=QUEUED_EVENTS_LIMIT){
//discard base message
memmove(device->events,device->events+device->event_size,(device->queued_events-1)*device->event_size);
device->queued_events--;
}else{
cp=(uint8*)calloc(device->max_events*2,device->event_size);//create new buffer
memcpy(cp,device->events,device->queued_events*device->event_size);//copy events from old buffer into new buffer
cp2=device->events;
device->events=cp;
device->max_events*=2;
free(cp2);
}
}
//copy previous event data into new event
memmove(device->events+device->queued_events*device->event_size,device->events+(device->queued_events-1)*device->event_size,device->event_size);
*(int64*)(device->events+(device->queued_events*device->event_size)+(device->event_size-8))=device_event_index++;//set global event index
int32 eventIndex=device->queued_events;
return eventIndex;
}
void commitDeviceEvent(device_struct *device){
device->queued_events++;
}
int32 func__devices(){
return device_last;
}
@ -1458,7 +1519,7 @@ if (device_selected<1||device_selected>device_last){error(5); return 0;}
static device_struct *d; d=&devices[device_selected];
if (!passed) i=1;
if (i<1||i>d->lastbutton){error(5); return 0;}
if (*(d->events+d->event_size+(i-1))) return -1;
if (getDeviceEventButtonValue(d,1,i-1)) return -1;
return 0;
}
@ -1468,8 +1529,8 @@ static device_struct *d; d=&devices[device_selected];
if (!passed) i=1;
if (i<1||i>d->lastbutton){error(5); return 0;}
static int32 old_value,value;
value=*(d->events+d->event_size+(i-1));
old_value=*(d->events+(i-1));
value=getDeviceEventButtonValue(d,1,i-1);
old_value=getDeviceEventButtonValue(d,0,i-1);
if (value>old_value) return -1;
if (value<old_value) return 1;
return 0;
@ -1480,7 +1541,7 @@ if (device_selected<1||device_selected>device_last){error(5); return 0;}
static device_struct *d; d=&devices[device_selected];
if (!passed) i=1;
if (i<1||i>d->lastaxis){error(5); return 0;}
return *(float*)(d->events+d->event_size+d->lastbutton+(i-1)*4);
return getDeviceEventAxisValue(d,1,i-1);
}
float func__wheel(int32 i,int32 passed){
@ -1488,7 +1549,7 @@ if (device_selected<1||device_selected>device_last){error(5); return 0;}
static device_struct *d; d=&devices[device_selected];
if (!passed) i=1;
if (i<1||i>d->lastwheel){error(5); return 0;}
return *(float*)(d->events+d->event_size+d->lastbutton+d->lastaxis*4+(i-1)*4);
return getDeviceEventWheelValue(d,1,i-1);
}
int32 func__lastbutton(int32 di,int32 passed){

View file

@ -5,6 +5,9 @@
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="11" />

View file

@ -1,8 +1,12 @@
APP_PLATFORM := android-10
#APP_PLATFORM := android-9
#APP_ABI := armeabi-v7a
APP_ABI := armeabi
#APP_ABI := armeabi
# Android 4+ (Ice Cream Sandwich) requires an ARMv7 processor. (Some custom versions of Android 4+ have been made for ARMv6)
# Therefore, there isn't much point producing armeabi binaries
APP_ABI := armeabi-v7a
APP_ABI += x86
APP_STL := gnustl_static

View file

@ -2837,3 +2837,14 @@ id.subfunc = 1
id.callname = "func__startdir"
id.ret = STRINGTYPE - ISPOINTER
regid
'Return a path that best represents the context provided e.g. _DIR$("DESKTOP")
clearid
id.n = "_DIR"
id.musthave = "$"
id.subfunc = 1
id.callname = "func__dir"
id.args = 1
id.arg = MKL$(STRINGTYPE - ISPOINTER)
id.ret = STRINGTYPE - ISPOINTER
regid