ios: Don't use performSelector to schedule every frame, the rarch_iterate method runs the UI loop internally; Split dirent_list code out of dirlist.m.

This commit is contained in:
meancoot 2013-02-07 19:03:57 -05:00
parent 80c0d35f58
commit 33d57ee3a0
5 changed files with 187 additions and 141 deletions

View File

@ -12,6 +12,7 @@
962979EF16C3EA3E00E6DCE0 /* ioseagl_ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = 962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */; };
962979F616C43B9500E6DCE0 /* ic_dir.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F416C43B9500E6DCE0 /* ic_dir.png */; };
962979F716C43B9500E6DCE0 /* ic_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F516C43B9500E6DCE0 /* ic_file.png */; };
96297A0116C4767F00E6DCE0 /* dirent_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 962979FF16C4767F00E6DCE0 /* dirent_list.c */; };
96AFAE2A16C1D4EA009DE44C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2916C1D4EA009DE44C /* UIKit.framework */; };
96AFAE2C16C1D4EA009DE44C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2B16C1D4EA009DE44C /* Foundation.framework */; };
96AFAE2E16C1D4EA009DE44C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2D16C1D4EA009DE44C /* CoreGraphics.framework */; };
@ -86,6 +87,8 @@
962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioseagl_ctx.c; sourceTree = "<group>"; };
962979F416C43B9500E6DCE0 /* ic_dir.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_dir.png; path = "../android/phoenix/res/drawable-xhdpi/ic_dir.png"; sourceTree = "<group>"; };
962979F516C43B9500E6DCE0 /* ic_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_file.png; path = "../android/phoenix/res/drawable-xhdpi/ic_file.png"; sourceTree = "<group>"; };
962979FF16C4767F00E6DCE0 /* dirent_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dirent_list.c; sourceTree = "<group>"; };
96297A0016C4767F00E6DCE0 /* dirent_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dirent_list.h; sourceTree = "<group>"; };
96AFAE2516C1D4EA009DE44C /* RetroArch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArch.app; sourceTree = BUILT_PRODUCTS_DIR; };
96AFAE2916C1D4EA009DE44C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
96AFAE2B16C1D4EA009DE44C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@ -330,6 +333,8 @@
96AFAE3316C1D4EA009DE44C /* RetroArch */ = {
isa = PBXGroup;
children = (
962979FF16C4767F00E6DCE0 /* dirent_list.c */,
96297A0016C4767F00E6DCE0 /* dirent_list.h */,
962979EB16C3E86F00E6DCE0 /* gameview.m */,
962979EC16C3E86F00E6DCE0 /* gameview.h */,
96AFAE3C16C1D4EA009DE44C /* AppDelegate.h */,
@ -787,6 +792,7 @@
9629797716C3CD2400E6DCE0 /* dirlist.m in Sources */,
962979ED16C3E86F00E6DCE0 /* gameview.m in Sources */,
962979EF16C3EA3E00E6DCE0 /* ioseagl_ctx.c in Sources */,
96297A0116C4767F00E6DCE0 /* dirent_list.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -0,0 +1,97 @@
#include <sys/stat.h>
#include <dirent.h>
#include <stddef.h>
#include "general.h"
#include "dirent_list.h"
static int compare_dirent(const void *left, const void *right)
{
const struct dirent* l = (const struct dirent*) left;
const struct dirent* r = (const struct dirent*) right;
// Directories first
if (l->d_type != r->d_type)
return (l->d_type) ? -1 : 1;
// Name
return strcmp(l->d_name, r->d_name);
}
static bool is_dirent_verboten(const struct dirent* entry)
{
if (!entry) return true;
if (strcmp(entry->d_name, ".") == 0) return true;
//if (strcmp(entry->d_name, "..") == 0) return true;
return false;
}
struct dirent_list* build_dirent_list(const char* path)
{
struct dirent_list* result = 0;
DIR* dir = opendir(path);
if (dir)
{
struct dirent* ent = 0;
// Count the number of items
size_t count = 0;
while ((ent = readdir(dir)))
{
count += is_dirent_verboten(ent) ? 0 : 1;
}
rewinddir(dir);
// String buffer for 'stat'ing
char* stat_path = malloc(strlen(path) + sizeof(ent->d_name));
strcpy(stat_path, path);
uint32_t last_index = strlen(stat_path);
// Build and fill the result
result = malloc(sizeof(struct dirent_list));
result->count = count;
result->entries = malloc(sizeof(struct dirent) * count);
size_t index = 0;
while ((ent = readdir(dir)))
{
if (is_dirent_verboten(ent)) continue;
memcpy(&result->entries[index], ent, sizeof(struct dirent));
// Chage dirent.d_type to a boolean indication if it is a directory
struct stat stat_buf;
strcat(strcat(stat_path, "/"), ent->d_name);
stat(stat_path, &stat_buf);
result->entries[index].d_type = S_ISDIR(stat_buf.st_mode) ? 1 : 0;
stat_path[last_index] = 0;
index ++;
}
closedir(dir);
free(stat_path);
qsort(result->entries, result->count, sizeof(struct dirent), &compare_dirent);
}
return result;
}
void free_dirent_list(struct dirent_list* list)
{
if (list) free(list->entries);
free(list);
}
const struct dirent* get_dirent_at_index(struct dirent_list* list, unsigned index)
{
if (!list) return 0;
return (index < list->count) ? &list->entries[index] : 0;
}
unsigned get_dirent_list_count(struct dirent_list* list)
{
return list ? list->count : 0;
}

View File

@ -0,0 +1,33 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2013 - Hans-Kristian Arntzen
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_IOS_DIRENT_LIST_H
#define __RARCH_IOS_DIRENT_LIST_H
#include <dirent.h>
struct dirent_list
{
size_t count;
struct dirent* entries;
};
struct dirent_list* build_dirent_list(const char* path);
void free_dirent_list(struct dirent_list* list);
const struct dirent* get_dirent_at_index(struct dirent_list* list, unsigned index);
unsigned get_dirent_list_count(struct dirent_list* list);
#endif

View File

@ -6,100 +6,10 @@
// Copyright (c) 2013 RetroArch. All rights reserved.
//
#include <sys/stat.h>
#include <dirent.h>
#include "dirent_list.h"
#import "dirlist.h"
#import "gameview.h"
struct dirent_list
{
size_t count;
struct dirent* entries;
};
const struct dirent* get_dirent_at_index(struct dirent_list* list, unsigned index)
{
if (!list) return 0;
return (index < list->count) ? &list->entries[index] : 0;
}
unsigned get_dirent_list_count(struct dirent_list* list)
{
return list ? list->count : 0;
}
void free_dirent_list(struct dirent_list* list)
{
if (list) free(list->entries);
free(list);
}
static int compare_dirent(const void *left, const void *right)
{
const struct dirent* l = (const struct dirent*) left;
const struct dirent* r = (const struct dirent*) right;
// Directories first
if (l->d_type != r->d_type)
return (l->d_type) ? -1 : 1;
// Name
return strcmp(l->d_name, r->d_name);
}
struct dirent_list* build_dirent_list(const char* path)
{
struct dirent_list* result = 0;
DIR* dir = opendir(path);
if (dir)
{
struct dirent* ent = 0;
// Count the number of items
size_t count = 0;
while ((ent = readdir(dir)))
{
count += (strcmp(ent->d_name, ".") ? 1 : 0);
}
rewinddir(dir);
// String buffer for 'stat'ing
char* stat_path = malloc(strlen(path) + sizeof(ent->d_name));
strcpy(stat_path, path);
uint32_t last_index = strlen(stat_path);
// Build and fill the result
result = malloc(sizeof(struct dirent_list));
result->count = count;
result->entries = malloc(sizeof(struct dirent) * count);
size_t index = 0;
while ((ent = readdir(dir)))
{
if (strcmp(ent->d_name, ".") == 0) continue;
memcpy(&result->entries[index], ent, sizeof(struct dirent));
// Chage dirent.d_type to a boolean indication if it is a directory
struct stat stat_buf;
strcat(stat_path, "/");
strcat(stat_path, ent->d_name);
stat(stat_path, &stat_buf);
result->entries[index].d_type = S_ISDIR(stat_buf.st_mode) ? 1 : 0;
stat_path[last_index] = 0;
index ++;
}
closedir(dir);
free(stat_path);
qsort(result->entries, result->count, sizeof(struct dirent), &compare_dirent);
}
return result;
}
@implementation dirlist_view
{
char path[4096];
@ -146,7 +56,6 @@ struct dirent_list* build_dirent_list(const char* path)
char* last_slash = strrchr(path, '/');
if (last_slash) *last_slash = 0;
path[0] = (path[0] == 0) ? '/' : path[0];
printf("%s\n", path);
}
else
{
@ -170,7 +79,7 @@ struct dirent_list* build_dirent_list(const char* path)
strcat(path, "/");
strcat(path, item->d_name);
extern void ios_load_game(const char*);
extern void ios_run_game(const char*);
ios_load_game(path);
}
}

View File

@ -23,23 +23,63 @@ static float screen_scale;
static bool ra_initialized = false;
static bool ra_done = false;
void ios_load_game(const char* file_name)
{
if(!ra_initialized && file_name)
{
const char* libretro = [[[NSBundle mainBundle] pathForResource:@"libretro" ofType:@"dylib"] UTF8String];
const char* overlay = [[[NSBundle mainBundle] pathForResource:@"overlay" ofType:@"cfg"] UTF8String];
strcpy(g_settings.input.overlay, overlay ? overlay : "");
const char* argv[] = {"retroarch", "-L", libretro, file_name, 0};
if (rarch_main_init(6, (char**)argv) == 0)
{
rarch_init_msg_queue();
ra_initialized = TRUE;
[current_view performSelector:@selector(rarch_iterate:) withObject:nil afterDelay:0.2f];
}
}
}
void ios_close_game()
{
if (ra_initialized)
{
rarch_main_deinit();
rarch_deinit_msg_queue();
#ifdef PERF_TEST
rarch_perf_log();
#endif
rarch_main_clear_state();
ra_done = true;
}
ra_initialized = false;
}
@implementation game_view
{
EAGLContext *gl_context;
}
- (void)schedule_iterate
{
if (ra_initialized && !ra_done)
[self performSelector:@selector(rarch_iterate:) withObject:nil afterDelay:0.002f];
}
- (void)rarch_iterate:(id)sender
{
if (ra_initialized && !ra_done)
ra_done = !rarch_main_iterate();
[self schedule_iterate];
{
while (!ra_done && rarch_main_iterate())
{
while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource);
}
ios_close_game();
ra_done = true;
}
}
- (void)viewDidLoad
@ -83,42 +123,3 @@ void get_game_view_size(unsigned *width, unsigned *height)
*height = gl_view.bounds.size.height * screen_scale;
}
}
void ios_close_game()
{
if (ra_initialized)
{
rarch_main_deinit();
rarch_deinit_msg_queue();
#ifdef PERF_TEST
rarch_perf_log();
#endif
rarch_main_clear_state();
ra_done = true;
}
ra_initialized = false;
}
void ios_load_game(const char* file_name)
{
if(!ra_initialized && file_name)
{
const char* libretro = [[[NSBundle mainBundle] pathForResource:@"libretro" ofType:@"dylib"] UTF8String];
const char* overlay = [[[NSBundle mainBundle] pathForResource:@"overlay" ofType:@"cfg"] UTF8String];
strcpy(g_settings.input.overlay, overlay ? overlay : "");
const char* argv[] = {"retroarch", "-L", libretro, file_name, 0};
if (rarch_main_init(6, (char**)argv) == 0)
{
rarch_init_msg_queue();
ra_initialized = TRUE;
if (current_view) [current_view schedule_iterate];
}
}
}