diff --git a/360/main.c b/360/main.c index 05b8c8fa47..0525981e24 100644 --- a/360/main.c +++ b/360/main.c @@ -320,7 +320,7 @@ begin_shutdown: if(path_file_exists(SYS_CONFIG_FILE)) rarch_config_save(SYS_CONFIG_FILE); - menu_deinit(); + menu_free(); video_xdk360.stop(); input_xdk360.free(NULL); rarch_exec(); diff --git a/360/menu.cpp b/360/menu.cpp index 657b344653..312b7ec123 100644 --- a/360/menu.cpp +++ b/360/menu.cpp @@ -70,10 +70,12 @@ static void filebrowser_fetch_directory_entries(const char *path, filebrowser_t rompath_title->SetText(strw_buffer); romlist->DeleteItems(0, romlist->GetItemCount()); - romlist->InsertItems(0, browser->file_count); - for(unsigned i = 0; i < browser->file_count; i++) + romlist->InsertItems(0, browser->current_dir.size); + for(unsigned i = 0; i < browser->current_dir.size; i++) { - rarch_convert_char_to_wchar(strw_buffer, browser->cur[i].d_name, sizeof(strw_buffer)); + char fname_tmp[256]; + fill_pathname_base(fname_tmp, browser->current_dir.elems[i], sizeof(fname_tmp)); + rarch_convert_char_to_wchar(strw_buffer, fname_tmp, sizeof(strw_buffer)); romlist->SetText(i, strw_buffer); } } @@ -524,13 +526,12 @@ HRESULT CRetroArchFileBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHandle if(hObjPressed == m_romlist) { int index = m_romlist.GetCurSel(); - if(browser.cur[index].d_type != FILE_ATTRIBUTE_DIRECTORY) + if(path_file_exists(browser.current_dir.elems[index])) { struct retro_system_info info; retro_get_system_info(&info); bool block_zip_extract = info.block_extract; - - const char * strbuffer = rarch_convert_wchar_to_const_char((const wchar_t*)m_romlist.GetText(index)); + const char * strbuffer = rarch_convert_wchar_to_const_char((const wchar_t*)m_romlist.GetText(index)); if((strstr(strbuffer, ".zip") || strstr(strbuffer, ".ZIP")) && !block_zip_extract) { @@ -545,7 +546,7 @@ HRESULT CRetroArchFileBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHandle rarch_settings_change(S_START_RARCH); } } - else if(browser.cur[index].d_type == FILE_ATTRIBUTE_DIRECTORY) + else if(path_is_directory(browser.current_dir.elems[index])) { const char * strbuffer = rarch_convert_wchar_to_const_char((const wchar_t *)m_romlist.GetText(index)); @@ -578,7 +579,7 @@ HRESULT CRetroArchShaderBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHand if(hObjPressed == m_shaderlist) { int index = m_shaderlist.GetCurSel(); - if(tmp_browser.cur[index].d_type != FILE_ATTRIBUTE_DIRECTORY) + if(path_file_exists(tmp_browser.current_dir.elems[index])) { const char * strbuffer = rarch_convert_wchar_to_const_char((const wchar_t *)m_shaderlist.GetText(index)); @@ -599,7 +600,7 @@ HRESULT CRetroArchShaderBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHand if (g_console.info_msg_enable) rarch_settings_msg(S_MSG_SHADER_LOADING_SUCCEEDED, S_DELAY_180); } - else if(tmp_browser.cur[index].d_type == FILE_ATTRIBUTE_DIRECTORY) + else if(path_is_directory(tmp_browser.current_dir.elems[index])) { const char * strbuffer = rarch_convert_wchar_to_const_char((const wchar_t *)m_shaderlist.GetText(index)); snprintf(path, sizeof(path), "%s\\%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmp_browser), strbuffer); @@ -619,13 +620,13 @@ HRESULT CRetroArchCoreBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHandle if(hObjPressed == m_romlist) { int index = m_romlist.GetCurSel(); - if(tmp_browser.cur[index].d_type != FILE_ATTRIBUTE_DIRECTORY) + if(path_file_exists(tmp_browser.current_dir.elems[index])) { const char * strbuffer = rarch_convert_wchar_to_const_char((const wchar_t *)m_romlist.GetText(index)); snprintf(g_console.launch_app_on_exit, sizeof(g_console.launch_app_on_exit), "%s\\%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmp_browser), strbuffer); rarch_settings_change(S_RETURN_TO_LAUNCHER); } - else if(tmp_browser.cur[index].d_type == FILE_ATTRIBUTE_DIRECTORY) + else if(path_is_directory(tmp_browser.current_dir.elems[index])) { const char * strbuffer = rarch_convert_wchar_to_const_char((const wchar_t *)m_romlist.GetText(index)); snprintf(path, sizeof(path), "%s%s\\", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmp_browser), strbuffer); @@ -838,8 +839,10 @@ int menu_init (void) return 0; } -void menu_deinit (void) +void menu_free (void) { + filebrowser_free(&browser); + filebrowser_free(&tmp_browser); app.Uninit(); } diff --git a/360/menu.h b/360/menu.h index fbb3978eea..b7041b6d8e 100644 --- a/360/menu.h +++ b/360/menu.h @@ -215,7 +215,7 @@ class CRetroArchControls: public CXuiSceneImpl }; int menu_init (void); -void menu_deinit (void); +void menu_free (void); void menu_loop (void); extern CRetroArch app; diff --git a/Makefile b/Makefile index 93238a1a9d..863a2f607f 100644 --- a/Makefile +++ b/Makefile @@ -164,6 +164,11 @@ ifeq ($(HAVE_SDL_IMAGE), 1) DEFINES += $(SDL_IMAGE_CFLAGS) endif +ifeq ($(HAVE_LIBPNG), 1) + LIBS += $(LIBPNG_LIBS) + DEFINES += $(LIBPNG_CFLAGS) +endif + ifeq ($(HAVE_FFMPEG), 1) OBJ += record/ffemu.o LIBS += $(AVCODEC_LIBS) $(AVFORMAT_LIBS) $(AVUTIL_LIBS) $(SWSCALE_LIBS) diff --git a/Makefile.win b/Makefile.win index 9f282a6e90..b20ab47429 100644 --- a/Makefile.win +++ b/Makefile.win @@ -32,7 +32,6 @@ libretro ?= -lretro LIBS = -lm DEFINES = -I. -DHAVE_CONFIGFILE -DHAVE_SDL -DHAVE_SCREENSHOTS -DHAVE_BSV_MOVIE -DPACKAGE_VERSION=\"0.9.6\" LDFLAGS = -L. -static-libgcc -LDCXXFLAGS = -s ifeq ($(TDM_GCC),) LDCXXFLAGS += -static-libstdc++ @@ -153,7 +152,14 @@ ifneq ($(V), 1) Q := @ endif -CFLAGS += -Wall -Wno-unused-result -O3 -I. +ifeq ($(DEBUG), 1) + CFLAGS += -O0 -g +else + CFLAGS += -O3 + LDCXXFLAGS += -s +endif + +CFLAGS += -Wall -Wno-unused-result -I. ifeq ($(CXX_BUILD), 1) CFLAGS += -std=c++0x -xc++ -D__STDC_CONSTANT_MACROS else diff --git a/android/.classpath b/android/.classpath new file mode 100644 index 0000000000..a4763d1eec --- /dev/null +++ b/android/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/android/.project b/android/.project new file mode 100644 index 0000000000..4af1961cac --- /dev/null +++ b/android/.project @@ -0,0 +1,33 @@ + + + RetroArch + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/android/.settings/org.eclipse.jdt.core.prefs b/android/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..f77b31c2d2 --- /dev/null +++ b/android/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml new file mode 100644 index 0000000000..7e450a1267 --- /dev/null +++ b/android/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + diff --git a/android/bin/classes/com/retroarch/BuildConfig.class b/android/bin/classes/com/retroarch/BuildConfig.class new file mode 100644 index 0000000000..2ecbee69f1 Binary files /dev/null and b/android/bin/classes/com/retroarch/BuildConfig.class differ diff --git a/android/bin/classes/com/retroarch/MainActivity.class b/android/bin/classes/com/retroarch/MainActivity.class new file mode 100644 index 0000000000..d5fba4e868 Binary files /dev/null and b/android/bin/classes/com/retroarch/MainActivity.class differ diff --git a/android/bin/classes/com/retroarch/R$attr.class b/android/bin/classes/com/retroarch/R$attr.class new file mode 100644 index 0000000000..f85362c78b Binary files /dev/null and b/android/bin/classes/com/retroarch/R$attr.class differ diff --git a/android/bin/classes/com/retroarch/R$drawable.class b/android/bin/classes/com/retroarch/R$drawable.class new file mode 100644 index 0000000000..62036ee00a Binary files /dev/null and b/android/bin/classes/com/retroarch/R$drawable.class differ diff --git a/android/bin/classes/com/retroarch/R$layout.class b/android/bin/classes/com/retroarch/R$layout.class new file mode 100644 index 0000000000..78c6034104 Binary files /dev/null and b/android/bin/classes/com/retroarch/R$layout.class differ diff --git a/android/bin/classes/com/retroarch/R$string.class b/android/bin/classes/com/retroarch/R$string.class new file mode 100644 index 0000000000..e0ffa75cf2 Binary files /dev/null and b/android/bin/classes/com/retroarch/R$string.class differ diff --git a/android/bin/classes/com/retroarch/R.class b/android/bin/classes/com/retroarch/R.class new file mode 100644 index 0000000000..5f0f1bbb20 Binary files /dev/null and b/android/bin/classes/com/retroarch/R.class differ diff --git a/android/bin/jarlist.cache b/android/bin/jarlist.cache new file mode 100644 index 0000000000..1b5ec3f9c5 --- /dev/null +++ b/android/bin/jarlist.cache @@ -0,0 +1,3 @@ +# cache for current jar dependecy. DO NOT EDIT. +# format is +# Encoding is UTF-8 diff --git a/android/gen/com/retroarch/BuildConfig.java b/android/gen/com/retroarch/BuildConfig.java new file mode 100644 index 0000000000..f7b068bd97 --- /dev/null +++ b/android/gen/com/retroarch/BuildConfig.java @@ -0,0 +1,6 @@ +/** Automatically generated file. DO NOT MODIFY */ +package com.retroarch; + +public final class BuildConfig { + public final static boolean DEBUG = true; +} \ No newline at end of file diff --git a/android/gen/com/retroarch/R.java b/android/gen/com/retroarch/R.java new file mode 100644 index 0000000000..083d090c3b --- /dev/null +++ b/android/gen/com/retroarch/R.java @@ -0,0 +1,42 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package com.retroarch; + +public final class R { + public static final class attr { + } + public static final class drawable { + public static final int ic_action_close=0x7f020000; + public static final int ic_action_history=0x7f020001; + public static final int ic_action_load=0x7f020002; + public static final int ic_action_open=0x7f020003; + public static final int ic_action_quit=0x7f020004; + public static final int ic_action_save=0x7f020005; + public static final int ic_action_settings=0x7f020006; + public static final int ic_launcher=0x7f020007; + } + public static final class id { + public static final int close=0x7f060001; + public static final int history=0x7f060004; + public static final int load=0x7f060002; + public static final int open=0x7f060000; + public static final int quit=0x7f060006; + public static final int save=0x7f060003; + public static final int settings=0x7f060005; + } + public static final class layout { + public static final int main=0x7f030000; + } + public static final class menu { + public static final int main_menu=0x7f050000; + } + public static final class string { + public static final int app_name=0x7f040001; + public static final int hello=0x7f040000; + } +} diff --git a/android/proguard-project.txt b/android/proguard-project.txt new file mode 100644 index 0000000000..f2fe1559a2 --- /dev/null +++ b/android/proguard-project.txt @@ -0,0 +1,20 @@ +# 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 *; +#} diff --git a/android/project.properties b/android/project.properties new file mode 100644 index 0000000000..0840b4a059 --- /dev/null +++ b/android/project.properties @@ -0,0 +1,14 @@ +# 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-15 diff --git a/android/res/drawable-hdpi/ic_action_close.png b/android/res/drawable-hdpi/ic_action_close.png new file mode 100644 index 0000000000..1c74f6df01 Binary files /dev/null and b/android/res/drawable-hdpi/ic_action_close.png differ diff --git a/android/res/drawable-hdpi/ic_action_history.png b/android/res/drawable-hdpi/ic_action_history.png new file mode 100644 index 0000000000..0d324e3cd0 Binary files /dev/null and b/android/res/drawable-hdpi/ic_action_history.png differ diff --git a/android/res/drawable-hdpi/ic_action_load.png b/android/res/drawable-hdpi/ic_action_load.png new file mode 100644 index 0000000000..3ef03ab59a Binary files /dev/null and b/android/res/drawable-hdpi/ic_action_load.png differ diff --git a/android/res/drawable-hdpi/ic_action_open.png b/android/res/drawable-hdpi/ic_action_open.png new file mode 100644 index 0000000000..41233c5e00 Binary files /dev/null and b/android/res/drawable-hdpi/ic_action_open.png differ diff --git a/android/res/drawable-hdpi/ic_action_quit.png b/android/res/drawable-hdpi/ic_action_quit.png new file mode 100644 index 0000000000..10dc28fcbb Binary files /dev/null and b/android/res/drawable-hdpi/ic_action_quit.png differ diff --git a/android/res/drawable-hdpi/ic_action_save.png b/android/res/drawable-hdpi/ic_action_save.png new file mode 100644 index 0000000000..dbc044c9d8 Binary files /dev/null and b/android/res/drawable-hdpi/ic_action_save.png differ diff --git a/android/res/drawable-hdpi/ic_action_settings.png b/android/res/drawable-hdpi/ic_action_settings.png new file mode 100644 index 0000000000..c73c92ec96 Binary files /dev/null and b/android/res/drawable-hdpi/ic_action_settings.png differ diff --git a/android/res/drawable-hdpi/ic_launcher.png b/android/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000..ea7613b8c4 Binary files /dev/null and b/android/res/drawable-hdpi/ic_launcher.png differ diff --git a/android/res/drawable-ldpi/ic_action_close.png b/android/res/drawable-ldpi/ic_action_close.png new file mode 100644 index 0000000000..65bf37c1d7 Binary files /dev/null and b/android/res/drawable-ldpi/ic_action_close.png differ diff --git a/android/res/drawable-ldpi/ic_action_history.png b/android/res/drawable-ldpi/ic_action_history.png new file mode 100644 index 0000000000..85f2127777 Binary files /dev/null and b/android/res/drawable-ldpi/ic_action_history.png differ diff --git a/android/res/drawable-ldpi/ic_action_load.png b/android/res/drawable-ldpi/ic_action_load.png new file mode 100644 index 0000000000..92ae2f321e Binary files /dev/null and b/android/res/drawable-ldpi/ic_action_load.png differ diff --git a/android/res/drawable-ldpi/ic_action_open.png b/android/res/drawable-ldpi/ic_action_open.png new file mode 100644 index 0000000000..a291177360 Binary files /dev/null and b/android/res/drawable-ldpi/ic_action_open.png differ diff --git a/android/res/drawable-ldpi/ic_action_quit.png b/android/res/drawable-ldpi/ic_action_quit.png new file mode 100644 index 0000000000..203696e713 Binary files /dev/null and b/android/res/drawable-ldpi/ic_action_quit.png differ diff --git a/android/res/drawable-ldpi/ic_action_save.png b/android/res/drawable-ldpi/ic_action_save.png new file mode 100644 index 0000000000..929966cacb Binary files /dev/null and b/android/res/drawable-ldpi/ic_action_save.png differ diff --git a/android/res/drawable-ldpi/ic_action_settings.png b/android/res/drawable-ldpi/ic_action_settings.png new file mode 100644 index 0000000000..7a3dc396bc Binary files /dev/null and b/android/res/drawable-ldpi/ic_action_settings.png differ diff --git a/android/res/drawable-ldpi/ic_launcher.png b/android/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000000..f969b747a2 Binary files /dev/null and b/android/res/drawable-ldpi/ic_launcher.png differ diff --git a/android/res/drawable-mdpi/ic_action_close.png b/android/res/drawable-mdpi/ic_action_close.png new file mode 100644 index 0000000000..af5a18a5fa Binary files /dev/null and b/android/res/drawable-mdpi/ic_action_close.png differ diff --git a/android/res/drawable-mdpi/ic_action_history.png b/android/res/drawable-mdpi/ic_action_history.png new file mode 100644 index 0000000000..e75db82cb5 Binary files /dev/null and b/android/res/drawable-mdpi/ic_action_history.png differ diff --git a/android/res/drawable-mdpi/ic_action_load.png b/android/res/drawable-mdpi/ic_action_load.png new file mode 100644 index 0000000000..659c27fc84 Binary files /dev/null and b/android/res/drawable-mdpi/ic_action_load.png differ diff --git a/android/res/drawable-mdpi/ic_action_open.png b/android/res/drawable-mdpi/ic_action_open.png new file mode 100644 index 0000000000..9d0c7c070b Binary files /dev/null and b/android/res/drawable-mdpi/ic_action_open.png differ diff --git a/android/res/drawable-mdpi/ic_action_quit.png b/android/res/drawable-mdpi/ic_action_quit.png new file mode 100644 index 0000000000..369120e38c Binary files /dev/null and b/android/res/drawable-mdpi/ic_action_quit.png differ diff --git a/android/res/drawable-mdpi/ic_action_save.png b/android/res/drawable-mdpi/ic_action_save.png new file mode 100644 index 0000000000..45c25de467 Binary files /dev/null and b/android/res/drawable-mdpi/ic_action_save.png differ diff --git a/android/res/drawable-mdpi/ic_action_settings.png b/android/res/drawable-mdpi/ic_action_settings.png new file mode 100644 index 0000000000..522c8a9cf5 Binary files /dev/null and b/android/res/drawable-mdpi/ic_action_settings.png differ diff --git a/android/res/drawable-mdpi/ic_launcher.png b/android/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000..84f2bca830 Binary files /dev/null and b/android/res/drawable-mdpi/ic_launcher.png differ diff --git a/android/res/drawable-xhdpi/ic_action_close.png b/android/res/drawable-xhdpi/ic_action_close.png new file mode 100644 index 0000000000..1c74f6df01 Binary files /dev/null and b/android/res/drawable-xhdpi/ic_action_close.png differ diff --git a/android/res/drawable-xhdpi/ic_action_history.png b/android/res/drawable-xhdpi/ic_action_history.png new file mode 100644 index 0000000000..0d324e3cd0 Binary files /dev/null and b/android/res/drawable-xhdpi/ic_action_history.png differ diff --git a/android/res/drawable-xhdpi/ic_action_load.png b/android/res/drawable-xhdpi/ic_action_load.png new file mode 100644 index 0000000000..3ef03ab59a Binary files /dev/null and b/android/res/drawable-xhdpi/ic_action_load.png differ diff --git a/android/res/drawable-xhdpi/ic_action_open.png b/android/res/drawable-xhdpi/ic_action_open.png new file mode 100644 index 0000000000..41233c5e00 Binary files /dev/null and b/android/res/drawable-xhdpi/ic_action_open.png differ diff --git a/android/res/drawable-xhdpi/ic_action_quit.png b/android/res/drawable-xhdpi/ic_action_quit.png new file mode 100644 index 0000000000..041de185be Binary files /dev/null and b/android/res/drawable-xhdpi/ic_action_quit.png differ diff --git a/android/res/drawable-xhdpi/ic_action_save.png b/android/res/drawable-xhdpi/ic_action_save.png new file mode 100644 index 0000000000..dbc044c9d8 Binary files /dev/null and b/android/res/drawable-xhdpi/ic_action_save.png differ diff --git a/android/res/drawable-xhdpi/ic_action_settings.png b/android/res/drawable-xhdpi/ic_action_settings.png new file mode 100644 index 0000000000..c73c92ec96 Binary files /dev/null and b/android/res/drawable-xhdpi/ic_action_settings.png differ diff --git a/android/res/drawable-xhdpi/ic_launcher.png b/android/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000..a113106a99 Binary files /dev/null and b/android/res/drawable-xhdpi/ic_launcher.png differ diff --git a/android/res/layout/main.xml b/android/res/layout/main.xml new file mode 100644 index 0000000000..bc12cd8231 --- /dev/null +++ b/android/res/layout/main.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/android/res/menu/main_menu.xml b/android/res/menu/main_menu.xml new file mode 100644 index 0000000000..bdf9374246 --- /dev/null +++ b/android/res/menu/main_menu.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml new file mode 100644 index 0000000000..1e2ffa990e --- /dev/null +++ b/android/res/values/strings.xml @@ -0,0 +1,7 @@ + + + + Hello World, MainActivity! + RetroArch + + \ No newline at end of file diff --git a/android/src/com/retroarch/MainActivity.java b/android/src/com/retroarch/MainActivity.java new file mode 100644 index 0000000000..957f352602 --- /dev/null +++ b/android/src/com/retroarch/MainActivity.java @@ -0,0 +1,69 @@ +package com.retroarch; + +import android.app.ActionBar; +import android.app.Activity; +import android.content.Context; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.Toast; +import android.opengl.GLSurfaceView; +import android.os.Bundle; + +public class MainActivity extends Activity +{ + private GLSurfaceView ctx_gl; + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + ctx_gl = new rgl_context(this); + setContentView(ctx_gl); + } + + public boolean onCreateOptionsMenu(Menu menu) + { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main_menu, menu); + return true; + } + + public boolean onOptionsItemSelected(MenuItem item) + { + switch (item.getItemId()) + { + case R.id.quit: + android.os.Process.killProcess(android.os.Process.myPid()); + return true; + default: + Toast.makeText(this, "MenuItem " + item.getTitle() + " selected.", Toast.LENGTH_SHORT).show(); + return true; + } + } + + @Override + protected void onPause() + { + super.onPause(); + ctx_gl.onPause(); + } + + @Override + protected void onResume() + { + super.onResume(); + ctx_gl.onResume(); + } +} + +class rgl_context extends GLSurfaceView +{ + public rgl_context(Context context) + { + super(context); + setEGLContextClientVersion(2); + setRenderer(new rgl()); + } +} \ No newline at end of file diff --git a/android/src/com/retroarch/audio_android.java b/android/src/com/retroarch/audio_android.java new file mode 100644 index 0000000000..c12d649fd4 --- /dev/null +++ b/android/src/com/retroarch/audio_android.java @@ -0,0 +1,130 @@ +package com.retroarch; + +import android.media.AudioFormat; +import android.media.AudioManager; +import android.media.AudioTrack; + +public class audio_android +{ + private static AudioTrack _track; + private static int _minSamples; + private static float _volume = AudioTrack.getMaxVolume(); + + private static int _rate; + private static int _bits; + private static int _channels; + + + private audio_android() + { + + } + + + public static void pause() + { + if (_track != null && _track.getPlayState() != AudioTrack.PLAYSTATE_PAUSED) + _track.pause(); + } + + + public static void resume() + { + if (_track != null && _track.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) + _track.play(); + } + + public int getMinSamples() + { + return _minSamples; + } + + + public static int write(short[] data, int size) + { + int retVal = 0; + if (_track == null) + return retVal; + + retVal = _track.write(data, 0, size); + + return retVal; + } + + + void set_volume(int vol) + { + final float min = AudioTrack.getMinVolume(); + final float max = AudioTrack.getMaxVolume(); + _volume = min + (max - min) * vol / 100; + + if (_track != null) + _track.setStereoVolume(_volume, _volume); + } + + + public static void free() + { + if (_track != null) + { + _track.pause(); + _track.release(); + _track = null; + } + } + + + public static boolean init(int rate, int bits, int channels) + { + _track = null; + _rate = rate; + _bits = bits; + _channels = channels; + + // generate format + int format = (_bits == 16 + ? AudioFormat.ENCODING_PCM_16BIT + : AudioFormat.ENCODING_PCM_8BIT); + + // determine channel config + int channelConfig = (_channels == 2 + ? AudioFormat.CHANNEL_OUT_STEREO + : AudioFormat.CHANNEL_OUT_MONO); + + int bufferSize = AudioTrack.getMinBufferSize(_rate, channelConfig, + format); + + _minSamples = bufferSize; + + try + { + _track = new AudioTrack( + AudioManager.STREAM_MUSIC, + _rate, + channelConfig, + format, + bufferSize, + AudioTrack.MODE_STREAM); + + if (_track.getState() == AudioTrack.STATE_UNINITIALIZED) + _track = null; + + } + catch (IllegalArgumentException e) + { + _track = null; + return false; + } + + // set max volume + _track.setStereoVolume(_volume, _volume); + + return true; + } + + + public static int getMaxBufferSize() + { + return _minSamples; + } +} diff --git a/android/src/com/retroarch/rgl.java b/android/src/com/retroarch/rgl.java new file mode 100644 index 0000000000..7c71ca21fb --- /dev/null +++ b/android/src/com/retroarch/rgl.java @@ -0,0 +1,95 @@ +package com.retroarch; + +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.nio.ByteOrder; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLES20; +import android.opengl.GLSurfaceView; + +public class rgl implements GLSurfaceView.Renderer +{ + private int cprg; + private int v_position_handle; + private FloatBuffer triangle_vbo; + + private void triangles_init() + { + float triangle_coords[] = { + // X, Y, Z + -0.5f, -0.25f, 0, + 0.5f, -0.25f, 0, + 0.0f, 0.559016994f, 0 + }; + + ByteBuffer vbb = ByteBuffer.allocateDirect(triangle_coords.length * 4); + vbb.order(ByteOrder.nativeOrder()); + triangle_vbo = vbb.asFloatBuffer(); + triangle_vbo.put(triangle_coords); + triangle_vbo.position(0); + } + + private void shader_init() + { + final String vprg = + "attribute vec4 vPosition; \n" + + "void main(){ \n" + + " gl_Position = vPosition; \n" + + "} \n"; + final String fprg = + "precision mediump float; \n" + + "void main(){ \n" + + " gl_FragColor = vec4 (0.63671875, 0.76953125, 0.22265625, 1.0); \n" + + "} \n"; + + int vertex_shader, fragment_shader; + + vertex_shader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); + + GLES20.glShaderSource(vertex_shader, vprg); + GLES20.glCompileShader(vertex_shader); + + fragment_shader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); + + GLES20.glShaderSource(fragment_shader, fprg); + GLES20.glCompileShader(fragment_shader); + + cprg = GLES20.glCreateProgram(); + GLES20.glAttachShader(cprg, vertex_shader); + GLES20.glAttachShader(cprg, fragment_shader); + GLES20.glLinkProgram(cprg); + + //get handle to the vertex shader's vPosition member + v_position_handle = GLES20.glGetAttribLocation(cprg, "vPosition"); +; } + + public void onSurfaceCreated(GL10 unused, EGLConfig config) + { + //background color + GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + + triangles_init(); + shader_init(); + } + + public void onDrawFrame(GL10 unused) + { + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + GLES20.glUseProgram(cprg); + + // Triangle + GLES20.glVertexAttribPointer(v_position_handle, 3, GLES20.GL_FLOAT, false, 12, triangle_vbo); + GLES20.glEnableVertexAttribArray(v_position_handle); + + GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); + } + + public void onSurfaceChanged(GL10 unused, int width, int height) + { + GLES20.glViewport(0, 0, width, height); + } +} diff --git a/config.features.h b/config.features.h index 6060a4ab73..d05067885d 100644 --- a/config.features.h +++ b/config.features.h @@ -110,6 +110,12 @@ static const bool _sdl_image_supp = true; static const bool _sdl_image_supp = false; #endif +#ifdef HAVE_LIBPNG +static const bool _libpng_supp = true; +#else +static const bool _libpng_supp = false; +#endif + #ifdef HAVE_FBO static const bool _fbo_supp = true; #else diff --git a/console/fileio/file_browser.c b/console/fileio/file_browser.c index b5fc50b23f..039f0f792c 100644 --- a/console/fileio/file_browser.c +++ b/console/fileio/file_browser.c @@ -14,216 +14,37 @@ * If not, see . */ -#ifdef _XBOX -#include -#endif #include "file_browser.h" -static int less_than_key(const void * a, const void * b) -{ - DirectoryEntry * a_dir = (DirectoryEntry*)a; - DirectoryEntry * b_dir = (DirectoryEntry*)b; - - /* compare a directory to a file directory is always lesser than*/ - if ((a_dir->d_type == FS_TYPES_DIRECTORY && b_dir->d_type == FS_TYPES_FILE)) - return -1; - else if (a_dir->d_type == FS_TYPES_FILE && b_dir->d_type == FS_TYPES_DIRECTORY) - return 1; - - return strcasecmp(a_dir->d_name, b_dir->d_name); -} - -static const char * filebrowser_get_extension(const char * filename) -{ - const char * ext = strrchr(filename, '.'); - - if (ext) - return ext+1; - else - return ""; -} - -static void filebrowser_clear_current_entries(filebrowser_t * filebrowser) -{ - for(uint32_t i = 0; i < MAX_FILE_LIMIT; i++) - { - filebrowser->cur[filebrowser->file_count].d_type = 0; - filebrowser->cur[filebrowser->file_count].d_namlen = 0; - strlcpy(filebrowser->cur[filebrowser->file_count].d_name, "\0", sizeof(filebrowser->cur[filebrowser->file_count].d_name)); - } -} - static void filebrowser_parse_directory(filebrowser_t * filebrowser, const char * path, const char * extensions) { - int error = 0; -#if defined(_XBOX) - filebrowser->file_count = 0; + strlcpy(filebrowser->dir[filebrowser->directory_stack_size], path, + sizeof(filebrowser->dir[filebrowser->directory_stack_size])); - WIN32_FIND_DATA ffd; - HANDLE hFind = INVALID_HANDLE_VALUE; + filebrowser->current_dir.elems = dir_list_new(path, extensions, true); + filebrowser->current_dir.size = dir_list_size(filebrowser->current_dir.elems); + filebrowser->current_dir.ptr = 0; - char path_buf[PATH_MAX]; - - if (strlcpy(path_buf, path, sizeof(path_buf)) >= sizeof(path_buf)) - { - error = 1; - goto error; - } - if (strlcat(path_buf, "\\*", sizeof(path_buf)) >= sizeof(path_buf)) - { - error = 1; - goto error; - } - - hFind = FindFirstFile(path_buf, &ffd); - if (hFind == INVALID_HANDLE_VALUE) - { - error = 1; - goto error; - } - - do - { - strlcpy(filebrowser->dir[filebrowser->directory_stack_size], path, sizeof(filebrowser->dir[filebrowser->directory_stack_size])); - bool found_dir = false; - - if(!(ffd.dwFileAttributes & FS_TYPES_DIRECTORY)) - { - char tmp_extensions[512]; - strlcpy(tmp_extensions, extensions, sizeof(tmp_extensions)); - const char * current_extension = filebrowser_get_extension(ffd.cFileName); - bool found_rom = false; - - if(current_extension) - { - char * pch = strtok(tmp_extensions, "|"); - while (pch != NULL) - { - if(strcmp(current_extension, pch) == 0) - { - found_rom = true; - break; - } - pch = strtok(NULL, "|"); - } - } - - if(!found_rom) - continue; - } - else if (ffd.dwFileAttributes & FS_TYPES_DIRECTORY) - found_dir = true; - - filebrowser->cur[filebrowser->file_count].d_type = found_dir ? FS_TYPES_DIRECTORY : FS_TYPES_FILE; - snprintf(filebrowser->cur[filebrowser->file_count].d_name, sizeof(filebrowser->cur[filebrowser->file_count].d_name), ffd.cFileName); - - filebrowser->file_count++; - }while (FindNextFile(hFind, &ffd) != 0 && (filebrowser->file_count + 1) < MAX_FILE_LIMIT); -#elif defined(__CELLOS_LV2__) - int fd; - - /* bad path*/ - if (strcmp(path,"") == 0) - { - error = 1; - goto error; - } - - /* delete old path*/ - filebrowser_clear_current_entries(filebrowser); - - if (cellFsOpendir(path, &fd) == CELL_FS_SUCCEEDED) - { - uint64_t nread = 0; - - strlcpy(filebrowser->dir[filebrowser->directory_stack_size], path, sizeof(filebrowser->dir[filebrowser->directory_stack_size])); - - filebrowser->file_count = 0; - filebrowser->currently_selected = 0; - - CellFsDirent dirent; - - while (cellFsReaddir(fd, &dirent, &nread) == CELL_FS_SUCCEEDED) - { - if (nread == 0) - break; - - if ((dirent.d_type != FS_TYPES_FILE) && (dirent.d_type != FS_TYPES_DIRECTORY)) - continue; - - if (dirent.d_type == FS_TYPES_DIRECTORY && !(strcmp(dirent.d_name, "."))) - continue; - - if (dirent.d_type == FS_TYPES_FILE) - { - char tmp_extensions[512]; - strlcpy(tmp_extensions, extensions, sizeof(tmp_extensions)); - const char * current_extension = filebrowser_get_extension(dirent.d_name); - bool found_rom = false; - - if(current_extension) - { - char * pch = strtok(tmp_extensions, "|"); - while (pch != NULL) - { - if(strcmp(current_extension, pch) == 0) - { - found_rom = true; - break; - } - pch = strtok(NULL, "|"); - } - } - - if(!found_rom) - continue; - } - - filebrowser->cur[filebrowser->file_count].d_type = dirent.d_type; - filebrowser->cur[filebrowser->file_count].d_namlen = dirent.d_namlen; - strlcpy(filebrowser->cur[filebrowser->file_count].d_name, dirent.d_name, sizeof(filebrowser->cur[filebrowser->file_count].d_name)); - - ++filebrowser->file_count; - } - - cellFsClosedir(fd); - } - else - { - error = 1; - goto error; - } -#endif - qsort(filebrowser->cur, filebrowser->file_count, sizeof(DirectoryEntry), less_than_key); - error: - if(error) - { - RARCH_ERR("Failed to open directory: \"%s\"\n", path); - } -#ifdef _XBOX - FindClose(hFind); -#endif + dir_list_sort(filebrowser->current_dir.elems, true); } void filebrowser_new(filebrowser_t * filebrowser, const char * start_dir, const char * extensions) { - filebrowser_clear_current_entries(filebrowser); filebrowser->directory_stack_size = 0; strlcpy(filebrowser->extensions, extensions, sizeof(filebrowser->extensions)); - filebrowser_parse_directory(filebrowser, start_dir, filebrowser->extensions); + filebrowser_parse_directory(filebrowser, start_dir, extensions); } - -void filebrowser_reset_start_directory(filebrowser_t * filebrowser, const char * start_dir, -const char * extensions) +void filebrowser_free(filebrowser_t * filebrowser) { - filebrowser->directory_stack_size = 0; - strlcpy(filebrowser->extensions, extensions, sizeof(filebrowser->extensions)); + dir_list_free(filebrowser->current_dir.elems); - filebrowser_parse_directory(filebrowser, start_dir, filebrowser->extensions); + filebrowser->current_dir.elems = NULL; + filebrowser->current_dir.size = 0; + filebrowser->current_dir.ptr = 0; } void filebrowser_push_directory(filebrowser_t * filebrowser, const char * path, @@ -244,3 +65,8 @@ void filebrowser_pop_directory (filebrowser_t * filebrowser) filebrowser_parse_directory(filebrowser, filebrowser->dir[filebrowser->directory_stack_size], filebrowser->extensions); } + +const char * filebrowser_get_current_path (filebrowser_t *filebrowser) +{ + return filebrowser->current_dir.elems[filebrowser->current_dir.ptr]; +} diff --git a/console/fileio/file_browser.h b/console/fileio/file_browser.h index 6fb77f70e1..6759876403 100644 --- a/console/fileio/file_browser.h +++ b/console/fileio/file_browser.h @@ -17,89 +17,63 @@ #ifndef FILEBROWSER_H_ #define FILEBROWSER_H_ -#define MAXJOLIET 255 #define MAX_DIR_STACK 25 #include #include -#ifdef __CELLOS_LV2__ -#include -#include -#include -#define FS_MAX_PATH 256 -#define FS_MAX_FS_PATH_LENGTH 255 -#define MAX_FILE_LIMIT 8192 -#elif defined(_XBOX) -#define FS_MAX_PATH MAX_PATH -#define FS_MAX_FS_PATH_LENGTH 2048 -#define MAX_FILE_LIMIT 4096 -#endif - -#if defined(_XBOX) -#define FS_TYPES_DIRECTORY (FILE_ATTRIBUTE_DIRECTORY) -#define FS_TYPES_FILE (FILE_ATTRIBUTE_NORMAL) -#elif defined(__CELLOS_LV2__) -#define FS_TYPES_DIRECTORY (CELL_FS_TYPE_DIRECTORY) -#define FS_TYPES_FILE (CELL_FS_TYPE_REGULAR) -#endif - -typedef struct { - uint8_t d_type; - uint8_t d_namlen; - char d_name[FS_MAX_PATH]; -} DirectoryEntry; - typedef struct { - uint32_t file_count; /* amount of files in current dir*/ - uint32_t currently_selected; /* currently select browser entry*/ uint32_t directory_stack_size; - char dir[MAX_DIR_STACK][FS_MAX_FS_PATH_LENGTH]; /* info of the current directory*/ - DirectoryEntry cur[MAX_FILE_LIMIT]; /* current file listing*/ - char extensions[FS_MAX_PATH]; /* allowed extensions*/ + char dir[MAX_DIR_STACK][512]; + struct { + char **elems; + size_t size; + size_t ptr; + } current_dir; + char extensions[PATH_MAX]; } filebrowser_t; -void filebrowser_new(filebrowser_t * filebrowser, const char * start_dir, const char * extensions); -void filebrowser_reset_start_directory(filebrowser_t * filebrowser, const char * start_dir, const char * extensions); +void filebrowser_new(filebrowser_t *filebrowser, const char * start_dir, const char * extensions); +void filebrowser_free(filebrowser_t *filebrowser); void filebrowser_push_directory(filebrowser_t * filebrowser, const char * path, bool with_extension); void filebrowser_pop_directory (filebrowser_t * filebrowser); #define FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(filebrowser) (filebrowser.dir[filebrowser.directory_stack_size]) -#define FILEBROWSER_GET_CURRENT_DIRECTORY_FILE_COUNT(filebrowser) (filebrowser.file_count) -#define FILEBROWSER_GOTO_ENTRY(filebrowser, i) filebrowser.currently_selected = i; +#define FILEBROWSER_GET_CURRENT_DIRECTORY_FILE_COUNT(filebrowser) (filebrowser.current_dir.size) +#define FILEBROWSER_GOTO_ENTRY(filebrowser, i) filebrowser.current_dir.ptr = i; #define FILEBROWSER_INCREMENT_ENTRY(filebrowser) \ { \ - filebrowser.currently_selected++; \ - if (filebrowser.currently_selected >= filebrowser.file_count) \ - filebrowser.currently_selected = 0; \ + filebrowser.current_dir.ptr++; \ + if (filebrowser.current_dir.ptr >= filebrowser.current_dir.size) \ + filebrowser.current_dir.ptr = 0; \ } #define FILEBROWSER_INCREMENT_ENTRY_POINTER(filebrowser) \ { \ - filebrowser->currently_selected++; \ - if (filebrowser->currently_selected >= filebrowser->file_count) \ - filebrowser->currently_selected = 0; \ + filebrowser->current_dir.ptr++; \ + if (filebrowser->current_dir.ptr >= filebrowser->current_dir.size) \ + filebrowser->current_dir.ptr = 0; \ } #define FILEBROWSER_DECREMENT_ENTRY(filebrowser) \ { \ - filebrowser.currently_selected--; \ - if (filebrowser.currently_selected >= filebrowser.file_count) \ - filebrowser.currently_selected = filebrowser.file_count - 1; \ + filebrowser.current_dir.ptr--; \ + if (filebrowser.current_dir.ptr >= filebrowser.current_dir.size) \ + filebrowser.current_dir.ptr = filebrowser.current_dir.size - 1; \ } #define FILEBROWSER_DECREMENT_ENTRY_POINTER(filebrowser) \ { \ - filebrowser->currently_selected--; \ - if (filebrowser->currently_selected >= filebrowser->file_count) \ - filebrowser->currently_selected = filebrowser->file_count - 1; \ + filebrowser->current_dir.ptr--; \ + if (filebrowser->current_dir.ptr >= filebrowser->current_dir.size) \ + filebrowser->current_dir.ptr = filebrowser->current_dir.size - 1; \ } -#define FILEBROWSER_GET_CURRENT_FILENAME(filebrowser) (filebrowser.cur[filebrowser.currently_selected].d_name) -#define FILEBROWSER_GET_CURRENT_ENTRY_INDEX(filebrowser) (filebrowser.currently_selected) -#define FILEBROWSER_IS_CURRENT_A_FILE(filebrowser) (filebrowser.cur[filebrowser.currently_selected].d_type == CELL_FS_TYPE_REGULAR) -#define FILEBROWSER_IS_CURRENT_A_DIRECTORY(filebrowser) (filebrowser.cur[filebrowser.currently_selected].d_type == CELL_FS_TYPE_DIRECTORY) +#define FILEBROWSER_GET_CURRENT_FILENAME(filebrowser) (filebrowser.current_dir.elems[filebrowser.current_dir.ptr]) +#define FILEBROWSER_GET_CURRENT_ENTRY_INDEX(filebrowser) (filebrowser.current_dir.ptr) +#define FILEBROWSER_IS_CURRENT_A_FILE(filebrowser) (path_file_exists(filebrowser.current_dir.elems[filebrowser.current_dir.ptr])) +#define FILEBROWSER_IS_CURRENT_A_DIRECTORY(filebrowser) (path_is_directory(filebrowser.current_dir.elems[filebrowser.current_dir.ptr])) #endif /* FILEBROWSER_H_ */ diff --git a/console/libretro_mgmt.c b/console/libretro_mgmt.c index 48ed9a6dca..f023339ebf 100644 --- a/console/libretro_mgmt.c +++ b/console/libretro_mgmt.c @@ -43,13 +43,10 @@ const char *rarch_manage_libretro_install(const char *full_path, const char *pat // file first. RARCH_LOG("Upgrading emulator core...\n"); -#if defined(__CELLOS_LV2__) - ret = cellFsUnlink(tmp_pathnewfile); - if (ret == CELL_FS_SUCCEEDED) -#elif defined(_XBOX) - ret = DeleteFile(tmp_pathnewfile); - if (ret != 0) -#endif + + ret = remove(tmp_pathnewfile); + + if (ret == 0) { RARCH_LOG("Succeeded in removing pre-existing libretro core: [%s].\n", tmp_pathnewfile); } @@ -58,26 +55,21 @@ const char *rarch_manage_libretro_install(const char *full_path, const char *pat } //now attempt the renaming. -#if defined(__CELLOS_LV2__) - ret = cellFsRename(full_path, tmp_pathnewfile); + ret = rename(full_path, tmp_pathnewfile); - if (ret != CELL_FS_SUCCEEDED) -#elif defined(_XBOX) - ret = MoveFileExA(full_path, tmp_pathnewfile, NULL); if (ret == 0) -#endif - { - RARCH_ERR("Failed to rename CORE executable.\n"); - } - else { RARCH_LOG("Libsnes core [%s] renamed to: [%s].\n", full_path, tmp_pathnewfile); retstr = tmp_pathnewfile; goto done; } + else + { + RARCH_ERR("Failed to rename CORE executable.\n"); + RARCH_WARN("CORE executable was not found, or some other errors occurred. Will attempt to load libretro core path from config file.\n"); + } } - RARCH_WARN("CORE executable was not found, or some other errors occurred. Will attempt to load libretro core path from config file.\n"); done: return retstr; } diff --git a/console/salamander/main.c b/console/salamander/main.c index 8fb038e22e..9b26aaaaac 100644 --- a/console/salamander/main.c +++ b/console/salamander/main.c @@ -87,9 +87,9 @@ static void find_and_set_first_file(void) // we can find in the RetroArch cores directory #if defined(_XBOX) - char ** dir_list = dir_list_new("game:\\", ".xex", false); + char ** dir_list = dir_list_new("game:\\", "xex", false); #elif defined(__CELLOS_LV2__) - char ** dir_list = dir_list_new(LIBRETRO_DIR_PATH, ".SELF", false); + char ** dir_list = dir_list_new(LIBRETRO_DIR_PATH, "SELF", false); #endif if (!dir_list) diff --git a/driver.c b/driver.c index 9f4fb80cdf..3cbf5f2d18 100644 --- a/driver.c +++ b/driver.c @@ -403,6 +403,12 @@ static void init_filter(void) if (*g_settings.video.filter_path == '\0') return; + if (g_extern.system.rgb32) + { + RARCH_WARN("libretro implementation uses XRGB8888 format. CPU filters only support 0RGB1555.\n"); + return; + } + RARCH_LOG("Loading bSNES filter from \"%s\"\n", g_settings.video.filter_path); g_extern.filter.lib = dylib_load(g_settings.video.filter_path); if (!g_extern.filter.lib) @@ -417,6 +423,7 @@ static void init_filter(void) (void (*)(uint32_t*, uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned))dylib_proc(g_extern.filter.lib, "filter_render"); + if (!g_extern.filter.psize || !g_extern.filter.prender) { RARCH_ERR("Failed to find functions in filter...\n"); @@ -428,28 +435,30 @@ static void init_filter(void) g_extern.filter.active = true; struct retro_game_geometry *geom = &g_extern.system.av_info.geometry; - unsigned width = geom->max_width; + unsigned width = geom->max_width; unsigned height = geom->max_height; g_extern.filter.psize(&width, &height); - unsigned pow2_x = next_pow2(width); - unsigned pow2_y = next_pow2(height); + unsigned pow2_x = next_pow2(width); + unsigned pow2_y = next_pow2(height); unsigned maxsize = pow2_x > pow2_y ? pow2_x : pow2_y; g_extern.filter.scale = maxsize / RARCH_SCALE_BASE; - g_extern.filter.buffer = (uint32_t*)malloc(RARCH_SCALE_BASE * RARCH_SCALE_BASE * g_extern.filter.scale * g_extern.filter.scale * sizeof(uint32_t)); - g_extern.filter.pitch = RARCH_SCALE_BASE * g_extern.filter.scale * sizeof(uint32_t); + g_extern.filter.buffer = (uint32_t*)malloc(RARCH_SCALE_BASE * RARCH_SCALE_BASE * + g_extern.filter.scale * g_extern.filter.scale * sizeof(uint32_t)); rarch_assert(g_extern.filter.buffer); - g_extern.filter.colormap = (uint32_t*)malloc(32768 * sizeof(uint32_t)); + g_extern.filter.pitch = RARCH_SCALE_BASE * g_extern.filter.scale * sizeof(uint32_t); + + g_extern.filter.colormap = (uint32_t*)malloc(0x10000 * sizeof(uint32_t)); rarch_assert(g_extern.filter.colormap); // Set up conversion map from 16-bit XRGB1555 to 32-bit ARGB. - for (unsigned i = 0; i < 32768; i++) + for (unsigned i = 0; i < 0x10000; i++) { - unsigned r = (i >> 10) & 31; - unsigned g = (i >> 5) & 31; - unsigned b = (i >> 0) & 31; + unsigned r = (i >> 10) & 0x1f; + unsigned g = (i >> 5) & 0x1f; + unsigned b = (i >> 0) & 0x1f; r = (r << 3) | (r >> 2); g = (g << 3) | (g >> 2); @@ -477,17 +486,14 @@ static void init_shader_dir(void) if (!*g_settings.video.shader_dir) return; - g_extern.shader_dir.elems = dir_list_new(g_settings.video.shader_dir, ".shader", false); - g_extern.shader_dir.size = 0; - g_extern.shader_dir.ptr = 0; - if (g_extern.shader_dir.elems) - { - while (g_extern.shader_dir.elems[g_extern.shader_dir.size]) - { - RARCH_LOG("Found shader \"%s\"\n", g_extern.shader_dir.elems[g_extern.shader_dir.size]); - g_extern.shader_dir.size++; - } - } + g_extern.shader_dir.elems = dir_list_new(g_settings.video.shader_dir, "shader", false); + g_extern.shader_dir.size = dir_list_size(g_extern.shader_dir.elems); + g_extern.shader_dir.ptr = 0; + + dir_list_sort(g_extern.shader_dir.elems, false); + + for (unsigned i = 0; i < g_extern.shader_dir.size; i++) + RARCH_LOG("Found shader \"%s\"\n", g_extern.shader_dir.elems[i]); } static void deinit_shader_dir(void) @@ -495,8 +501,8 @@ static void deinit_shader_dir(void) // It handles NULL, no worries :D dir_list_free(g_extern.shader_dir.elems); g_extern.shader_dir.elems = NULL; - g_extern.shader_dir.size = 0; - g_extern.shader_dir.ptr = 0; + g_extern.shader_dir.size = 0; + g_extern.shader_dir.ptr = 0; } #endif @@ -559,7 +565,7 @@ void init_video_input(void) video.force_aspect = g_settings.video.force_aspect; video.smooth = g_settings.video.smooth; video.input_scale = scale; - video.rgb32 = g_extern.filter.active; + video.rgb32 = g_extern.filter.active || g_extern.system.rgb32; const input_driver_t *tmp = driver.input; driver.video_data = video_init_func(&video, &driver.input, &driver.input_data); diff --git a/dynamic.c b/dynamic.c index 61120b5818..6b24ab2322 100644 --- a/dynamic.c +++ b/dynamic.c @@ -331,6 +331,31 @@ static bool environment_cb(unsigned cmd, void *data) RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n", g_settings.system_directory); break; + case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT: + { + enum retro_pixel_format pix_fmt = *(const enum retro_pixel_format*)data; + bool rgb32 = false; + switch (pix_fmt) + { + case RETRO_PIXEL_FORMAT_0RGB1555: + rgb32 = false; + RARCH_LOG("Environ SET_PIXEL_FORMAT: 0RGB1555.\n"); + break; + +#ifndef RARCH_CONSOLE + case RETRO_PIXEL_FORMAT_XRGB8888: + rgb32 = true; + RARCH_LOG("Environ SET_PIXEL_FORMAT: XRGB8888.\n"); + break; +#endif + default: + return false; + } + + g_extern.system.rgb32 = rgb32; + break; + } + default: RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd); return false; diff --git a/file.h b/file.h index 2ad5972181..b4f4179bb0 100644 --- a/file.h +++ b/file.h @@ -24,10 +24,6 @@ #include #include "general.h" -#ifdef __CELLOS_LV2__ -#include -#endif - // Generic file, path and directory handling. ssize_t read_file(const char *path, void **buf); @@ -44,6 +40,8 @@ bool init_rom_file(enum rarch_game_type type); // If ext is NULL, any file will be picked. // If non-NULL, only files with extension ext are added. char **dir_list_new(const char *dir, const char *ext, bool include_dirs); +size_t dir_list_size(char * const *dir_list); +void dir_list_sort(char **dir_list, bool dir_first); void dir_list_free(char **dir_list); bool path_is_directory(const char *path); diff --git a/file_path.c b/file_path.c index 009c56106c..860f3cf69e 100644 --- a/file_path.c +++ b/file_path.c @@ -20,9 +20,10 @@ #include #include #include "compat/strl.h" +#include "compat/posix_string.h" #ifdef __CELLOS_LV2__ -#include +#define S_ISDIR(x) (x & CELL_FS_S_IFDIR) #endif #if defined(_WIN32) && !defined(_XBOX) @@ -43,141 +44,273 @@ #endif // Yep, this is C alright ;) -char **dir_list_new(const char *dir, const char *ext, bool include_dirs) +struct string_list { - size_t cur_ptr = 0; - size_t cur_size = 32; - char **dir_list = NULL; + char **data; + size_t size; + size_t cap; +}; -#ifdef _WIN32 - WIN32_FIND_DATA ffd; - HANDLE hFind = INVALID_HANDLE_VALUE; +static bool string_list_capacity(struct string_list *list, size_t cap) +{ + rarch_assert(cap > list->size); - char path_buf[PATH_MAX]; + char **new_data = (char**)realloc(list->data, cap * sizeof(char*)); + if (!new_data) + return false; - if (strlcpy(path_buf, dir, sizeof(path_buf)) >= sizeof(path_buf)) - goto error; -#ifdef _XBOX - if (strlcat(path_buf, "*", sizeof(path_buf)) >= sizeof(path_buf)) -#else - if (strlcat(path_buf, "/*", sizeof(path_buf)) >= sizeof(path_buf)) -#endif + list->data = new_data; + list->cap = cap; + return true; +} + +static bool string_list_init(struct string_list *list) +{ + memset(list, 0, sizeof(*list)); + return string_list_capacity(list, 32); +} + +static bool string_list_append(struct string_list *list, const char *elem) +{ + if (list->size + 1 >= list->cap && !string_list_capacity(list, list->cap * 2)) + return false; + + if (!(list->data[list->size] = strdup(elem))) + return false; + + list->size++; + return true; +} + +static char **string_list_finalize(struct string_list *list) +{ + rarch_assert(list->cap > list->size); + + list->data[list->size] = NULL; + return list->data; +} + +static void string_list_cleanup(struct string_list *list) +{ + for (size_t i = 0; i < list->size; i++) + free(list->data[i]); + free(list->data); + memset(list, 0, sizeof(*list)); +} + +static void string_list_free(char **list) +{ + if (!list) + return; + + char **orig = list; + while (*list) + free(*list++); + free(orig); +} + +static char **string_split(const char *str, const char *delim) +{ + char *copy = NULL; + const char *tmp = NULL; + struct string_list list; + + if (!string_list_init(&list)) goto error; - if (ext) + copy = strdup(str); + if (!copy) + return NULL; + + tmp = strtok(copy, delim); + while (tmp) { - if (strlcat(path_buf, ext, sizeof(path_buf)) >= sizeof(path_buf)) - goto error; - } - - hFind = FindFirstFile(path_buf, &ffd); - if (hFind == INVALID_HANDLE_VALUE) - goto error; -#else - DIR *directory = NULL; - const struct dirent *entry = NULL; - - directory = opendir(dir); - if (!directory) - goto error; -#endif - - dir_list = (char**)calloc(cur_size, sizeof(char*)); - if (!dir_list) - goto error; - -#ifdef _WIN32 // Hard to read? Blame non-POSIX heathens! - do -#else - while ((entry = readdir(directory))) -#endif - { - // Not a perfect search of course, but hopefully good enough in practice. -#ifdef _WIN32 - if (include_dirs) - { - if (ext && !strstr(ffd.cFileName, ext) && !path_is_directory(ffd.cFileName)) - continue; - } - else - { - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - continue; - if (ext && !strstr(ffd.cFileName, ext)) - continue; - } -#else - if (include_dirs) - { - if (ext && !strstr(entry->d_name, ext) && !path_is_directory(entry->d_name)) - continue; - } - else - { - if (ext && !strstr(entry->d_name, ext)) - continue; - } -#endif - - dir_list[cur_ptr] = (char*)malloc(PATH_MAX); - if (!dir_list[cur_ptr]) + if (!string_list_append(&list, tmp)) goto error; - strlcpy(dir_list[cur_ptr], dir, PATH_MAX); -#ifndef _XBOX - strlcat(dir_list[cur_ptr], "/", PATH_MAX); -#endif -#ifdef _WIN32 - strlcat(dir_list[cur_ptr], ffd.cFileName, PATH_MAX); -#else - strlcat(dir_list[cur_ptr], entry->d_name, PATH_MAX); -#endif - - cur_ptr++; - if (cur_ptr + 1 == cur_size) // Need to reserve for NULL. - { - cur_size *= 2; - dir_list = (char**)realloc(dir_list, cur_size * sizeof(char*)); - if (!dir_list) - goto error; - - // Make sure it's all NULL'd out since we cannot rely on realloc to do this. - memset(dir_list + cur_ptr, 0, (cur_size - cur_ptr) * sizeof(char*)); - } + tmp = strtok(NULL, delim); } -#if defined(_WIN32) - while (FindNextFile(hFind, &ffd) != 0); -#endif -#ifdef _WIN32 - FindClose(hFind); -#else - closedir(directory); -#endif - return dir_list; + free(copy); + return string_list_finalize(&list); error: - RARCH_ERR("Failed to open directory: \"%s\"\n", dir); -#ifdef _WIN32 - if (hFind != INVALID_HANDLE_VALUE) - FindClose(hFind); -#else - if (directory) - closedir(directory); -#endif - dir_list_free(dir_list); + string_list_cleanup(&list); + free(copy); return NULL; } -void dir_list_free(char **dir_list) +static bool string_list_find_elem(char * const *list, const char *elem) +{ + if (!list) + return false; + + for (; *list; list++) + if (strcmp(*list, elem) == 0) + return true; + + return false; +} + +static const char *path_get_extension(const char *path) +{ + const char *ext = strrchr(path, '.'); + if (ext) + return ext + 1; + else + return ""; +} + +size_t dir_list_size(char * const *dir_list) +{ + if (!dir_list) + return 0; + + size_t size = 0; + while (*dir_list++) + size++; + + return size; +} + +static int qstrcmp_plain(const void *a, const void *b) +{ + return strcasecmp(*(const char * const*)a, *(const char * const*)b); +} + +static int qstrcmp_dir(const void *a_, const void *b_) +{ + const char *a = *(const char * const*)a_; + const char *b = *(const char * const*)b_; + + // Sort directories before files. + int a_dir = path_is_directory(a); + int b_dir = path_is_directory(b); + if (a_dir != b_dir) + return b_dir - a_dir; + + return strcasecmp(a, b); +} + +void dir_list_sort(char **dir_list, bool dir_first) { if (!dir_list) return; - char **orig = dir_list; - while (*dir_list) - free(*dir_list++); - free(orig); + qsort(dir_list, dir_list_size(dir_list), sizeof(char*), dir_first ? qstrcmp_dir : qstrcmp_plain); +} + +#ifdef _WIN32 // Because the API is just fucked up ... +char **dir_list_new(const char *dir, const char *ext, bool include_dirs) +{ + struct string_list list; + if (!string_list_init(&list)) + return NULL; + + HANDLE hFind = INVALID_HANDLE_VALUE; + WIN32_FIND_DATA ffd; + + char path_buf[PATH_MAX]; + snprintf(path_buf, sizeof(path_buf), "%s\\*", dir); + + char **ext_list = NULL; + if (ext) + ext_list = string_split(ext, "|"); + + hFind = FindFirstFile(path_buf, &ffd); + if (hFind == INVALID_HANDLE_VALUE) + goto error; + + do + { + const char *name = ffd.cFileName; + const char *file_ext = path_get_extension(name); + bool is_dir = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + + if (!include_dirs && is_dir) + continue; + + if (!is_dir && ext_list && !string_list_find_elem(ext_list, file_ext)) + continue; + + char file_path[PATH_MAX]; + snprintf(file_path, sizeof(file_path), "%s\\%s", dir, name); + + if (!string_list_append(&list, file_path)) + goto error; + } + while (FindNextFile(hFind, &ffd) != 0); + + FindClose(hFind); + string_list_free(ext_list); + return string_list_finalize(&list); + +error: + RARCH_ERR("Failed to open directory: \"%s\"\n", dir); + if (hFind != INVALID_HANDLE_VALUE) + FindClose(hFind); + + string_list_cleanup(&list); + string_list_free(ext_list); + return NULL; +} +#else +char **dir_list_new(const char *dir, const char *ext, bool include_dirs) +{ + struct string_list list; + if (!string_list_init(&list)) + return NULL; + + DIR *directory = NULL; + const struct dirent *entry = NULL; + + char **ext_list = NULL; + if (ext) + ext_list = string_split(ext, "|"); + + directory = opendir(dir); + if (!directory) + goto error; + + while ((entry = readdir(directory))) + { + const char *name = entry->d_name; + const char *file_ext = path_get_extension(name); + bool is_dir = entry->d_type == DT_DIR; + + if (!include_dirs && is_dir) + continue; + + if (!is_dir && ext_list && !string_list_find_elem(ext_list, file_ext)) + continue; + + char file_path[PATH_MAX]; + snprintf(file_path, sizeof(file_path), "%s/%s", dir, name); + + if (!string_list_append(&list, file_path)) + goto error; + } + + closedir(directory); + + string_list_free(ext_list); + return string_list_finalize(&list); + +error: + RARCH_ERR("Failed to open directory: \"%s\"\n", dir); + + if (directory) + closedir(directory); + + string_list_cleanup(&list); + string_list_free(ext_list); + return NULL; +} +#endif + +void dir_list_free(char **dir_list) +{ + string_list_free(dir_list); } bool path_is_directory(const char *path) @@ -185,12 +318,6 @@ bool path_is_directory(const char *path) #ifdef _WIN32 DWORD ret = GetFileAttributes(path); return (ret & FILE_ATTRIBUTE_DIRECTORY) && (ret != INVALID_FILE_ATTRIBUTES); -#elif defined(__CELLOS_LV2__) - CellFsStat buf; - if (cellFsStat(path, &buf) < 0) - return false; - - return buf.st_mode & CELL_FS_S_IFDIR; #else struct stat buf; if (stat(path, &buf) < 0) diff --git a/general.h b/general.h index fc59c3a0f2..8a4f022c4e 100644 --- a/general.h +++ b/general.h @@ -332,6 +332,7 @@ struct global unsigned rotation; bool shutdown; unsigned performance_level; + bool rgb32; } system; struct diff --git a/libretro.h b/libretro.h index 28ea262041..8aa579e863 100755 --- a/libretro.h +++ b/libretro.h @@ -150,7 +150,19 @@ extern "C" { // The returned value can be NULL. // If so, no such directory is defined, // and it's up to the implementation to find a suitable directory. + // +#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 + // const enum retro_pixel_format * -- + // Sets the internal pixel format used by the implementation. + // The default pixel format is RETRO_PIXEL_FORMAT_XRGB1555. + // If the call returns false, the frontend does not support this pixel format. + // This function should be called inside retro_load_game() or retro_get_system_av_info(). +enum retro_pixel_format +{ + RETRO_PIXEL_FORMAT_0RGB1555 = 0, // 0RGB1555, native endian. 0 bit must be set to 0. + RETRO_PIXEL_FORMAT_XRGB8888 // XRGB8888, native endian. X bits are ignored. +}; struct retro_message { @@ -225,7 +237,7 @@ struct retro_game_info // Environment callback. Gives implementations a way of performing uncommon tasks. Extensible. typedef bool (*retro_environment_t)(unsigned cmd, void *data); -// Render a frame. Pixel format is 15-bit XRGB1555 native endian. +// Render a frame. Pixel format is 15-bit 0RGB1555 native endian unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). // Width and height specify dimensions of buffer. // Pitch specifices length in bytes between two lines in buffer. typedef void (*retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); diff --git a/ps3/main.c b/ps3/main.c index 1ae53780b1..9fc59bc64d 100644 --- a/ps3/main.c +++ b/ps3/main.c @@ -78,7 +78,7 @@ char MULTIMAN_EXECUTABLE[PATH_MAX]; int rarch_main(int argc, char *argv[]); -SYS_PROCESS_PARAM(1001, 0x100000) +SYS_PROCESS_PARAM(1001, 0x200000) #undef main @@ -418,8 +418,8 @@ begin_shutdown: rarch_main_deinit(); input_ps3.free(NULL); - video_gl.stop(); + menu_free(); if(g_console.oskutil_handle.is_running) oskutil_unload(&g_console.oskutil_handle); diff --git a/ps3/menu.c b/ps3/menu.c index 27b513d51f..03ce0c48ad 100644 --- a/ps3/menu.c +++ b/ps3/menu.c @@ -220,7 +220,7 @@ static void browser_update(filebrowser_t * b) if (CTRL_LSTICK_DOWN(state)) { - if(b->currently_selected < b->file_count-1) + if(b->current_dir.ptr < b->current_dir.size-1) { FILEBROWSER_INCREMENT_ENTRY_POINTER(b); set_delay = DELAY_SMALLEST; @@ -229,7 +229,7 @@ static void browser_update(filebrowser_t * b) if (CTRL_DOWN(state)) { - if(b->currently_selected < b->file_count-1) + if(b->current_dir.ptr < b->current_dir.size-1) { FILEBROWSER_INCREMENT_ENTRY_POINTER(b); set_delay = DELAY_SMALLEST; @@ -238,7 +238,7 @@ static void browser_update(filebrowser_t * b) if (CTRL_LSTICK_UP(state)) { - if(b->currently_selected > 0) + if(b->current_dir.ptr > 0) { FILEBROWSER_DECREMENT_ENTRY_POINTER(b); set_delay = DELAY_SMALLEST; @@ -247,7 +247,7 @@ static void browser_update(filebrowser_t * b) if (CTRL_UP(state)) { - if(b->currently_selected > 0) + if(b->current_dir.ptr > 0) { FILEBROWSER_DECREMENT_ENTRY_POINTER(b); set_delay = DELAY_SMALLEST; @@ -256,66 +256,66 @@ static void browser_update(filebrowser_t * b) if (CTRL_RIGHT(state)) { - b->currently_selected = (MIN(b->currently_selected + 5, b->file_count-1)); + b->current_dir.ptr = (MIN(b->current_dir.ptr + 5, b->current_dir.size-1)); set_delay = DELAY_SMALL; } if (CTRL_LSTICK_RIGHT(state)) { - b->currently_selected = (MIN(b->currently_selected + 5, b->file_count-1)); + b->current_dir.ptr = (MIN(b->current_dir.ptr + 5, b->current_dir.size-1)); set_delay = DELAY_SMALLEST; } if (CTRL_LEFT(state)) { - if (b->currently_selected <= 5) - b->currently_selected = 0; + if (b->current_dir.ptr <= 5) + b->current_dir.ptr = 0; else - b->currently_selected -= 5; + b->current_dir.ptr -= 5; set_delay = DELAY_SMALL; } if (CTRL_LSTICK_LEFT(state)) { - if (b->currently_selected <= 5) - b->currently_selected = 0; + if (b->current_dir.ptr <= 5) + b->current_dir.ptr = 0; else - b->currently_selected -= 5; + b->current_dir.ptr -= 5; set_delay = DELAY_SMALLEST; } if (CTRL_R1(state)) { - b->currently_selected = (MIN(b->currently_selected + NUM_ENTRY_PER_PAGE, b->file_count-1)); + b->current_dir.ptr = (MIN(b->current_dir.ptr + NUM_ENTRY_PER_PAGE, b->current_dir.size-1)); set_delay = DELAY_MEDIUM; } if (CTRL_R2(state)) { - b->currently_selected = (MIN(b->currently_selected + 50, b->file_count-1)); - if(!b->currently_selected) - b->currently_selected = 0; + b->current_dir.ptr = (MIN(b->current_dir.ptr + 50, b->current_dir.size-1)); + if(!b->current_dir.ptr) + b->current_dir.ptr = 0; set_delay = DELAY_SMALL; } if (CTRL_L2(state)) { - if (b->currently_selected <= 50) - b->currently_selected= 0; + if (b->current_dir.ptr <= 50) + b->current_dir.ptr= 0; else - b->currently_selected -= 50; + b->current_dir.ptr -= 50; set_delay = DELAY_SMALL; } if (CTRL_L1(state)) { - if (b->currently_selected <= NUM_ENTRY_PER_PAGE) - b->currently_selected= 0; + if (b->current_dir.ptr <= NUM_ENTRY_PER_PAGE) + b->current_dir.ptr= 0; else - b->currently_selected -= NUM_ENTRY_PER_PAGE; + b->current_dir.ptr -= NUM_ENTRY_PER_PAGE; set_delay = DELAY_MEDIUM; } @@ -330,11 +330,11 @@ static void browser_update(filebrowser_t * b) static void browser_render(filebrowser_t * b) { gl_t *gl = driver.video_data; - uint32_t file_count = b->file_count; + uint32_t file_count = b->current_dir.size; int current_index, page_number, page_base, i; float currentX, currentY, ySpacing; - current_index = b->currently_selected; + current_index = b->current_dir.ptr; page_number = current_index / NUM_ENTRY_PER_PAGE; page_base = page_number * NUM_ENTRY_PER_PAGE; @@ -344,8 +344,10 @@ static void browser_render(filebrowser_t * b) for ( i = page_base; i < file_count && i < page_base + NUM_ENTRY_PER_PAGE; ++i) { + char fname_tmp[256]; + fill_pathname_base(fname_tmp, b->current_dir.elems[i], sizeof(fname_tmp)); currentY = currentY + ySpacing; - cellDbgFontPuts(currentX, currentY, FONT_SIZE, i == current_index ? RED : b->cur[i].d_type == CELL_FS_TYPE_DIRECTORY ? GREEN : WHITE, b->cur[i].d_name); + cellDbgFontPuts(currentX, currentY, FONT_SIZE, i == current_index ? RED : WHITE, fname_tmp); gl_render_msg_post(gl); } gl_render_msg_post(gl); @@ -818,8 +820,7 @@ static void apply_scaling (unsigned init_mode) static void select_file(uint32_t menu_id) { - char extensions[256], title[256], object[256], comment[256], dir_path[PATH_MAX], - path[PATH_MAX], *separatorslash; + char extensions[256], title[256], object[256], comment[256], dir_path[PATH_MAX], path[PATH_MAX]; uint64_t state, diff_state, button_was_pressed; gl_t * gl = driver.video_data; @@ -881,7 +882,7 @@ static void select_file(uint32_t menu_id) if(IS_TIMER_EXPIRED(gl)) { if (CTRL_START(button_was_pressed)) - filebrowser_reset_start_directory(&tmpBrowser, "/", extensions); + filebrowser_new(&tmpBrowser, "/", extensions); if (CTRL_CROSS(button_was_pressed)) { @@ -889,19 +890,17 @@ static void select_file(uint32_t menu_id) { /*if 'filename' is in fact '..' - then pop back directory instead of adding '..' to filename path */ - if(tmpBrowser.currently_selected == 0) + if(tmpBrowser.current_dir.ptr == 0) filebrowser_pop_directory(&tmpBrowser); else { - separatorslash = (strcmp(FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmpBrowser),"/") == 0) ? "" : "/"; - snprintf(path, sizeof(path), "%s%s%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmpBrowser), separatorslash, FILEBROWSER_GET_CURRENT_FILENAME(tmpBrowser)); + snprintf(path, sizeof(path), FILEBROWSER_GET_CURRENT_FILENAME(tmpBrowser)); filebrowser_push_directory(&tmpBrowser, path, true); } } else if (FILEBROWSER_IS_CURRENT_A_FILE(tmpBrowser)) { - snprintf(path, sizeof(path), "%s/%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmpBrowser), FILEBROWSER_GET_CURRENT_FILENAME(tmpBrowser)); - printf("path: %s\n", path); + snprintf(path, sizeof(path), FILEBROWSER_GET_CURRENT_FILENAME(tmpBrowser)); switch(menu_id) { @@ -962,7 +961,7 @@ static void select_file(uint32_t menu_id) static void select_directory(uint32_t menu_id) { - char path[1024], newpath[1024], *separatorslash; + char path[1024], newpath[1024]; uint64_t state, diff_state, button_was_pressed; gl_t * gl = driver.video_data; @@ -981,13 +980,13 @@ static void select_directory(uint32_t menu_id) if(IS_TIMER_EXPIRED(gl)) { if (CTRL_START(button_was_pressed)) - filebrowser_reset_start_directory(&tmpBrowser, "/","empty"); + filebrowser_new(&tmpBrowser, "/","empty"); if (CTRL_SQUARE(button_was_pressed)) { if(FILEBROWSER_IS_CURRENT_A_DIRECTORY(tmpBrowser)) { - snprintf(path, sizeof(path), "%s/%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmpBrowser), FILEBROWSER_GET_CURRENT_FILENAME(tmpBrowser)); + snprintf(path, sizeof(path), FILEBROWSER_GET_CURRENT_FILENAME(tmpBrowser)); switch(menu_id) { case PATH_SAVESTATES_DIR_CHOICE: @@ -1035,12 +1034,11 @@ static void select_directory(uint32_t menu_id) /* if 'filename' is in fact '..' - then pop back directory instead of * adding '..' to filename path */ - if(tmpBrowser.currently_selected == 0) + if(tmpBrowser.current_dir.ptr == 0) filebrowser_pop_directory(&tmpBrowser); else { - separatorslash = (strcmp(FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmpBrowser),"/") == 0) ? "" : "/"; - snprintf(newpath, sizeof(newpath), "%s%s%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmpBrowser), separatorslash, FILEBROWSER_GET_CURRENT_FILENAME(tmpBrowser)); + snprintf(newpath, sizeof(newpath), FILEBROWSER_GET_CURRENT_FILENAME(tmpBrowser)); filebrowser_push_directory(&tmpBrowser, newpath, false); } } @@ -1895,7 +1893,7 @@ static void select_setting(menu * menu_obj) static void select_rom(void) { - char newpath[1024], *separatorslash; + char newpath[1024]; uint64_t state, diff_state, button_was_pressed; gl_t * gl = driver.video_data; @@ -1914,7 +1912,7 @@ static void select_rom(void) } if (CTRL_START(button_was_pressed)) - filebrowser_reset_start_directory(&browser, "/", rarch_console_get_rom_ext()); + filebrowser_new(&browser, "/", rarch_console_get_rom_ext()); if (CTRL_CROSS(button_was_pressed)) { @@ -1922,14 +1920,13 @@ static void select_rom(void) { /*if 'filename' is in fact '..' - then pop back directory instead of adding '..' to filename path */ - if(browser.currently_selected == 0) + if(browser.current_dir.ptr == 0) { filebrowser_pop_directory(&browser); } else { - separatorslash = (strcmp(FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(browser),"/") == 0) ? "" : "/"; - snprintf(newpath, sizeof(newpath), "%s%s%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(browser), separatorslash, FILEBROWSER_GET_CURRENT_FILENAME(browser)); + snprintf(newpath, sizeof(newpath), FILEBROWSER_GET_CURRENT_FILENAME(browser)); filebrowser_push_directory(&browser, newpath, true); } } @@ -1940,13 +1937,13 @@ static void select_rom(void) retro_get_system_info(&info); bool block_zip_extract = info.block_extract; - snprintf(rom_path_temp, sizeof(rom_path_temp), "%s/%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(browser), FILEBROWSER_GET_CURRENT_FILENAME(browser)); + snprintf(rom_path_temp, sizeof(rom_path_temp), FILEBROWSER_GET_CURRENT_FILENAME(browser)); if((strstr(rom_path_temp, ".zip") || strstr(rom_path_temp, ".ZIP")) && !block_zip_extract) rarch_extract_zipfile(rom_path_temp); else { - snprintf(g_console.rom_path, sizeof(g_console.rom_path), "%s/%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(browser), FILEBROWSER_GET_CURRENT_FILENAME(browser)); + snprintf(g_console.rom_path, sizeof(g_console.rom_path), FILEBROWSER_GET_CURRENT_FILENAME(browser)); rarch_settings_change(S_START_RARCH); } } @@ -2462,6 +2459,12 @@ void menu_init (void) filebrowser_new(&browser, g_console.default_rom_startup_dir, rarch_console_get_rom_ext()); } +void menu_free (void) +{ + filebrowser_free(&browser); + filebrowser_free(&tmpBrowser); +} + void menu_loop(void) { gl_t * gl = driver.video_data; diff --git a/ps3/menu.h b/ps3/menu.h index 5034605575..ebf7b3e02d 100644 --- a/ps3/menu.h +++ b/ps3/menu.h @@ -157,5 +157,6 @@ enum void menu_init (void); void menu_loop (void); +void menu_free (void); #endif /* MENU_H_ */ diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 9300e8e183..dfc724f720 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -21,7 +21,6 @@ else HAVE_RPI=no fi - if [ "$LIBRETRO" ]; then echo "Explicit libsnes used, disabling dynamic libsnes loading ..." HAVE_DYNAMIC='no' @@ -93,6 +92,7 @@ fi check_pkgconf XML libxml-2.0 check_pkgconf SDL_IMAGE SDL_image +check_pkgconf LIBPNG libpng if [ "$HAVE_THREADS" != 'no' ]; then if [ "$HAVE_FFMPEG" != 'no' ]; then @@ -140,6 +140,6 @@ check_pkgconf PYTHON python3 add_define_make OS "$OS" # Creates config.mk and config.h. -VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY NETWORK_CMD SOCKET_LEGACY FBO STRL PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM FFMPEG_AVCODEC_ENCODE_AUDIO2 FFMPEG_AVCODEC_ENCODE_VIDEO2 X264RGB SINC BSV_MOVIE RPI" +VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE LIBPNG DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY NETWORK_CMD SOCKET_LEGACY FBO STRL PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM FFMPEG_AVCODEC_ENCODE_AUDIO2 FFMPEG_AVCODEC_ENCODE_VIDEO2 X264RGB SINC BSV_MOVIE RPI" create_config_make config.mk $VARS -create_config_header config.h $VARS \ No newline at end of file +create_config_header config.h $VARS diff --git a/qb/config.params.sh b/qb/config.params.sh index 3a2f311363..676e53b7e8 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -21,6 +21,7 @@ HAVE_PULSE=auto # Enable PulseAudio support HAVE_FREETYPE=auto # Enable FreeType support HAVE_XVIDEO=auto # Enable XVideo support HAVE_SDL_IMAGE=auto # Enable SDL_image support +HAVE_LIBPNG=auto # Enable libpng support HAVE_PYTHON=auto # Enable Python 3 support for shaders HAVE_SINC=yes # Disable SINC resampler HAVE_BSV_MOVIE=yes # Disable BSV movie support diff --git a/retroarch.c b/retroarch.c index 10045a9533..b3cb31915c 100644 --- a/retroarch.c +++ b/retroarch.c @@ -499,6 +499,7 @@ static void print_features(void) _PSUPP(cg, "Cg", "Cg pixel shaders"); _PSUPP(xml, "XML", "bSNES XML pixel shaders"); _PSUPP(sdl_image, "SDL_image", "SDL_image image loading"); + _PSUPP(libpng, "libpng", "libpng screenshot support"); _PSUPP(fbo, "FBO", "OpenGL render-to-texture (multi-pass shaders)"); _PSUPP(dynamic, "Dynamic", "Dynamic run-time loading of libretro library"); _PSUPP(ffmpeg, "FFmpeg", "On-the-fly recording of gameplay with libavcodec"); @@ -1175,7 +1176,7 @@ static void init_recording(void) params.filename = g_extern.record_path; params.fps = fps; params.samplerate = samplerate; - params.rgb32 = false; + params.rgb32 = g_extern.system.rgb32; if (g_extern.record_width || g_extern.record_height) { diff --git a/screenshot.c b/screenshot.c index 5be6b7d8df..b111453838 100644 --- a/screenshot.c +++ b/screenshot.c @@ -22,9 +22,80 @@ #include #include "general.h" -// Simple 24bpp .BMP writer. +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif -static void write_header(FILE *file, unsigned width, unsigned height) +#ifdef HAVE_LIBPNG +#include +#endif + +#ifdef HAVE_LIBPNG +static png_structp png_ptr; +static png_infop png_info_ptr; + +static void destroy_png(void) +{ + if (png_ptr) + png_destroy_write_struct(&png_ptr, &png_info_ptr); +} + +static bool write_header_png(FILE *file, unsigned width, unsigned height) +{ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + return false; + + if (setjmp(png_jmpbuf(png_ptr))) + goto error; + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + goto error; + + png_init_io(png_ptr, file); + + png_set_IHDR(png_ptr, png_info_ptr, width, height, 8, + PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_write_info(png_ptr, png_info_ptr); + png_set_compression_level(png_ptr, 9); + + return true; + +error: + destroy_png(); + return false; +} + +static void dump_lines_png(uint8_t **lines, int height) +{ + if (setjmp(png_jmpbuf(png_ptr))) + { + RARCH_ERR("PNG: dump_lines_png() failed!\n"); + goto end; + } + + // PNG is top-down, BMP is bottom-up. + for (int i = 0, j = height - 1; i < j; i++, j--) + { + uint8_t *tmp = lines[i]; + lines[i] = lines[j]; + lines[j] = tmp; + } + + png_set_rows(png_ptr, png_info_ptr, lines); + png_write_png(png_ptr, png_info_ptr, PNG_TRANSFORM_BGR, NULL); + png_write_end(png_ptr, NULL); + +end: + destroy_png(); +} + +#else + +static bool write_header_bmp(FILE *file, unsigned width, unsigned height) { unsigned line_size = (width * 3 + 3) & ~3; unsigned size = line_size * height + 54; @@ -49,9 +120,17 @@ static void write_header(FILE *file, unsigned width, unsigned height) 0, 0, 0, 0 }; - fwrite(header, 1, sizeof(header), file); + return fwrite(header, 1, sizeof(header), file) == sizeof(header); } +static void dump_lines_file(FILE *file, uint8_t **lines, size_t line_size, unsigned height) +{ + for (unsigned i = 0; i < height; i++) + fwrite(lines[i], 1, line_size, file); +} + +#endif + static void dump_line_bgr(uint8_t *line, const uint8_t *src, unsigned width) { memcpy(line, src, width * 3); @@ -78,31 +157,42 @@ static void dump_content(FILE *file, const void *frame, const uint16_t *frame16 = (const uint16_t*)frame; if (!bgr24) - pitch /= 2; + pitch /= sizeof(uint16_t); - unsigned line_size = (width * 3 + 3) & ~3; - uint8_t *line = (uint8_t*)calloc(1, line_size); - if (!line) + uint8_t **lines = (uint8_t**)calloc(height, sizeof(uint8_t*)); + if (!lines) return; + size_t line_size = (width * 3 + 3) & ~3; + + for (int i = 0; i < height; i++) + { + lines[i] = (uint8_t*)calloc(1, line_size); + if (!lines[i]) + goto end; + } + if (bgr24) // BGR24 byte order. Can directly copy. { for (int j = 0; j < height; j++, frame_bgr += pitch) - { - dump_line_bgr(line, frame_bgr, width); - fwrite(line, 1, line_size, file); - } + dump_line_bgr(lines[j], frame_bgr, width); } else // ARGB1555 { for (int j = 0; j < height; j++, frame16 += pitch) - { - dump_line_16(line, frame16, width); - fwrite(line, 1, line_size, file); - } + dump_line_16(lines[j], frame16, width); } - free(line); +#ifdef HAVE_LIBPNG + dump_lines_png(lines, height); +#else + dump_lines_file(file, lines, line_size, height); +#endif + +end: + for (int i = 0; i < height; i++) + free(lines[i]); + free(lines); } bool screenshot_dump(const char *folder, const void *frame, @@ -111,8 +201,14 @@ bool screenshot_dump(const char *folder, const void *frame, time_t cur_time; time(&cur_time); +#ifdef HAVE_LIBPNG +#define IMG_EXT "png" +#else +#define IMG_EXT "bmp" +#endif + char timefmt[128]; - strftime(timefmt, sizeof(timefmt), "RetroArch-%m%d-%H%M%S.bmp", localtime(&cur_time)); + strftime(timefmt, sizeof(timefmt), "RetroArch-%m%d-%H%M%S." IMG_EXT, localtime(&cur_time)); char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s/%s", folder, timefmt); @@ -124,11 +220,18 @@ bool screenshot_dump(const char *folder, const void *frame, return false; } - write_header(file, width, height); - dump_content(file, frame, width, height, pitch, bgr24); +#ifdef HAVE_LIBPNG + bool ret = write_header_png(file, width, height); +#else + bool ret = write_header_bmp(file, width, height); +#endif + + if (ret) + dump_content(file, frame, width, height, pitch, bgr24); + else + RARCH_ERR("Failed to write image header.\n"); fclose(file); - - return true; + return ret; }