diff --git a/CHANGES.md b/CHANGES.md index 29d55435d6..668b53f938 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,15 +1,22 @@ -# 1.7.0 (future) +# 1.7.1 (future) + +# 1.7.0 - CHEEVOS: Add badges for achievements, shows thumbnail images of achievements. - CHEEVOS: Leaderboard support. - CHEEVOS: Only disable savestates on hardcore mode if achievements are not available. +- COMMANDLINE: Fix fullscreen toggle switch. - COMMON: Add 'Automatically Load Content To Playlist' feature, enabled by default. - COMMON: Fix slowmotion ratio always being reset back to 1. - COMMON: Optimized NBIO implementations now for Apple, Windows, and Linux. Uses mmap for Linux/Windows/BSD if/when available. File I/O should now be much faster for loading images inside the menu. - COMMON: Native Blissbox support now for latest firmware as of writing (2.0). Implementation through libusb and/or native Windows HID. - COMMON: New lightgun API. +- COMMON: New VFS (Virtual File System) API. - COMMON: Fixed some playlist bugs. - COMMON: New snow shader. +- COMMON: Fix Quick Menu title, no longer shows 'Select File'. - COMMON: Fix loading cores that require no content one after another. +- COMMON: Map Delete key to Y button for non-unified menu keyboard controls. +- COMMON: Fix for relative paths being normalised and generating a duplicate history entry. - EMSCRIPTEN: Fix references to browserfs. - FREEBSD: Support libusb HID input driver. - HAIKU: Buildfix. @@ -21,20 +28,31 @@ - LOCALIZATION: Update Italian translation. - LOCALIZATION: Update Japanese translation. - LOCALIZATION: Update Portuguese-Brazilian translation. +- LOCALIZATION: Update Polish translation. - LOCALIZATION: Update Russian translation. +- MENU: Snowflake menu shader effect. - OSX/PPC: Fix the GL2 renderchain, had to use EXT versions of framebuffer/renderbuffer functions. +- PS3: HTTP requests / downloads should now work. +- PS3: Core Updater now works. +- PS3: Improved font rendering, enable STB Unicode font renderer. +- PSP: Make it work with Vita's Adrenaline. +- PSP: Fix audio sync. - PSP: Fix content loading, port should be functional again. -- PSP: Us 64MB when available. +- PSP: Use 64MB when available. - SCANNER: Fix crash from Windows-incompatible format string. - VITA: Improve packaging, installation times. - WIIU: Disabled the controller patcher for now since it was the source of many stability issues. +- VULKAN: Various stability fixes for WSI. - WINDOWS: Add MSVC 2017 solution. - WINDOWS: Get rid of the empty console window in MSVC 2010 builds. - WINDOWS: Raw input driver now supports new lightgun code. - WINDOWS: Use configured OSD/text message color on GDI driver. - WINDOWS/XINPUT: Populate XInput VID/PID from DInput so autoconfig doesn't rely solely on joypad names +- WINDOWS/XINPUT: Fix crash that occurs in some situations with Steam running and a Steam Controller plugged in. - WINDOWS: Improve version reporting under System Information. - WINDOWS: Support window transparency. +- WINDOWS: Correct usage of GetWindowPlacement per MS docs, fixes game window position on Win95/98. +- WINDOWS: Added Visual Studio 2017 support. # 1.6.9 - COMMON: Small memory leak. diff --git a/Makefile.common b/Makefile.common index 1ba0da7f23..e342c9ef7e 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1428,13 +1428,14 @@ ifeq ($(HAVE_BUILTINZLIB),1) $(DEPS_DIR)/libz/uncompr.o \ $(DEPS_DIR)/libz/zutil.o else -ifeq ($(HAVE_ZLIB),1) +ifeq ($(HAVE_ZLIB), 1) OBJ += $(ZLIB_OBJS) endif endif -ifeq ($(HAVE_7ZIP),1) -ifeq ($(HAVE_FLAC),1) +ifeq ($(HAVE_7ZIP), 1) +ifeq ($(HAVE_ZLIB), 1) +ifeq ($(HAVE_FLAC), 1) DEFINES += -DHAVE_CHD -DWANT_SUBCODE -DWANT_RAW_DATA_SECTOR CFLAGS += -I$(LIBRETRO_COMM_DIR)/formats/libchdr OBJ += $(LIBRETRO_COMM_DIR)/formats/libchdr/bitstream.o \ @@ -1445,6 +1446,7 @@ ifeq ($(HAVE_FLAC),1) $(LIBRETRO_COMM_DIR)/streams/chd_stream.o endif endif +endif # Video4Linux 2 @@ -1624,6 +1626,29 @@ OBJ += gfx/video_filters/2xsai.o \ gfx/video_filters/phosphor2x.o endif +ifeq ($(WANT_IOSUHAX), 1) +DEFINES += -I$(DEPS_DIR)/libiosuhax +CFLAGS += -I$(DEPS_DIR)/libiosuhax +OBJ += $(DEPS_DIR)/libiosuhax/iosuhax.o \ + $(DEPS_DIR)/libiosuhax/iosuhax_devoptab.o \ + $(DEPS_DIR)/libiosuhax/iosuhax_disc_interface.o +endif + +ifeq ($(WANT_LIBFAT), 1) +DEFINES += -I$(DEPS_DIR)/libfat/include +CFLAGS += -I$(DEPS_DIR)/libfat/include +OBJ += $(DEPS_DIR)/libfat/cache.o \ + $(DEPS_DIR)/libfat/directory.o \ + $(DEPS_DIR)/libfat/disc.o \ + $(DEPS_DIR)/libfat/fatdir.o \ + $(DEPS_DIR)/libfat/fatfile.o \ + $(DEPS_DIR)/libfat/file_allocation_table.o \ + $(DEPS_DIR)/libfat/filetime.o \ + $(DEPS_DIR)/libfat/libfat.o \ + $(DEPS_DIR)/libfat/lock.o \ + $(DEPS_DIR)/libfat/partition.o +endif + ifeq ($(HAVE_STATIC_AUDIO_FILTERS), 1) OBJ += libretro-common/audio/dsp_filters/echo.o \ libretro-common/audio/dsp_filters/eq.o \ diff --git a/Makefile.griffin b/Makefile.griffin index 5e2217dd6e..20c8951280 100644 --- a/Makefile.griffin +++ b/Makefile.griffin @@ -844,6 +844,7 @@ else ifeq ($(platform), vita) else ifneq (,$(findstring msvc,$(platform))) ifeq ($(platform), windows_msvc2003_x86) CFLAGS += -Wp64 + LDFLAGS += -SUBSYSTEM:WINDOWS -ENTRY:mainCRTStartup endif CFLAGS += -O2 -DNDEBUG -MT -TP diff --git a/Makefile.ps3 b/Makefile.ps3 index b23e55327a..3ebd8e444a 100644 --- a/Makefile.ps3 +++ b/Makefile.ps3 @@ -63,7 +63,19 @@ endif PPU_SRCS = griffin/griffin.c -DEFINES += -DHAVE_MENU -DHAVE_RGUI -DHAVE_XMB -DHAVE_LIBRETRODB -DHAVE_MATERIALUI -DHAVE_SHADERPIPELINE -DRARCH_INTERNAL -DMSB_FIRST -DHAVE_OVERLAY -DHAVE_CC_RESAMPLER -DHAVE_STB_VORBIS +DEFINES += -DHAVE_MENU -DHAVE_RGUI -DHAVE_XMB -DHAVE_LIBRETRODB -DHAVE_MATERIALUI -DHAVE_SHADERPIPELINE -DRARCH_INTERNAL -DMSB_FIRST -DHAVE_OVERLAY -DHAVE_CC_RESAMPLER -DHAVE_STB_VORBIS -DHAVE_STB_FONT + +ifeq ($(DEX_BUILD), 1) +DEFINES += -DDEX_BUILD +endif + +ifeq ($(CEX_BUILD), 1) +DEFINES += -DCEX_BUILD +endif + +ifeq ($(ODE_BUILD), 1) +DEFINES += -DODE_BUILD +endif ifeq ($(HAVE_GCMGL), 1) DEFINES += -DHAVE_GCMGL diff --git a/Makefile.ps3.cobra b/Makefile.ps3.cobra index d3f95fee52..db6db7db02 100644 --- a/Makefile.ps3.cobra +++ b/Makefile.ps3.cobra @@ -63,6 +63,18 @@ PPU_SRCS = griffin/griffin.c DEFINES += -DHAVE_RGUI -DHAVE_MATERIALUI -DHAVE_XMB -DHAVE_MENU -DRARCH_INTERNAL +ifeq ($(DEX_BUILD), 1) +DEFINES += -DDEX_BUILD +endif + +ifeq ($(CEX_BUILD), 1) +DEFINES += -DCEX_BUILD +endif + +ifeq ($(ODE_BUILD), 1) +DEFINES += -DODE_BUILD +endif + ifeq ($(HAVE_GCMGL), 1) DEFINES += -DHAVE_GCMGL GL_LIBS := -L. -lrgl_ps3 diff --git a/Makefile.ps3.salamander b/Makefile.ps3.salamander index 0d716a2e8f..49c8c9a719 100644 --- a/Makefile.ps3.salamander +++ b/Makefile.ps3.salamander @@ -27,6 +27,18 @@ STRIP = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-strip.exe INCFLAGS = -I. -Idefines -Ilibretro-common/include -Ideps/libz DEFINES = -D__CELLOS_LV2__ -DIS_SALAMANDER -DRARCH_CONSOLE -DHAVE_SYSUTILS -DHAVE_SYSMODULES -DHAVE_RARCH_EXEC +ifeq ($(DEX_BUILD), 1) +DEFINES += -DDEX_BUILD +endif + +ifeq ($(CEX_BUILD), 1) +DEFINES += -DCEX_BUILD +endif + +ifeq ($(ODE_BUILD), 1) +DEFINES += -DODE_BUILD +endif + PPU_CFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES) PPU_CXXFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES) diff --git a/Makefile.wiiu b/Makefile.wiiu index b3389af1af..86f91e57ee 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -73,6 +73,8 @@ else # WANT_IFADDRS = 1 HAVE_STATIC_VIDEO_FILTERS = 1 HAVE_STATIC_AUDIO_FILTERS = 1 + WANT_LIBFAT = 1 + WANT_IOSUHAX = 1 include Makefile.common BLACKLIST := @@ -141,7 +143,7 @@ CFLAGS += -ffast-math -Werror=implicit-function-declaration #CFLAGS += -Wall #todo: remove -DWIIU and use the built-in macros instead (HW_WUP or __wiiu__). -CFLAGS += -DWIIU -DMSB_FIRST +CFLAGS += -DWIIU -DMSB_FIRST -D__WUT__ CFLAGS += -DHAVE_MAIN CFLAGS += -DHAVE_UPDATE_ASSETS CFLAGS += -DRARCH_INTERNAL -DRARCH_CONSOLE @@ -166,7 +168,15 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -D_GNU_SOURCE LDFLAGS += -Wl,--gc-sections -LIBS := $(WHOLE_START) -lretro_wiiu $(WHOLE_END) -lm -lfat -liosuhax +LIBS := $(WHOLE_START) -lretro_wiiu $(WHOLE_END) -lm + +ifneq ($(WANT_LIBFAT), 1) +LIBS += -lfat +endif + +ifneq ($(WANT_IOSUHAX), 1) +LIBS += -liosuhax +endif RPX_OBJ = wiiu/system/stubs_rpl.o diff --git a/README.md b/README.md index c1f633fbd2..35d0b90d6c 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ RetroArch also emphasizes on being easy to integrate into various launcher front RetroArch has been ported to the following platforms: + - DOS - Windows - Linux - FreeBSD diff --git a/audio/drivers/xaudio.c b/audio/drivers/xaudio.c index f3c81a1741..f267cb04e0 100644 --- a/audio/drivers/xaudio.c +++ b/audio/drivers/xaudio.c @@ -45,6 +45,12 @@ typedef struct xaudio2 xaudio2_t; #define MAX_BUFFERS_MASK (MAX_BUFFERS - 1) +#ifndef COINIT_MULTITHREADED +#define COINIT_MULTITHREADED 0x00 +#endif + +#define XAUDIO2_WRITE_AVAILABLE(handle) ((handle)->bufsize * (MAX_BUFFERS - (handle)->buffers - 1)) + typedef struct { xaudio2_t *xa; @@ -190,10 +196,6 @@ static void xaudio2_free(xaudio2_t *handle) #endif } -#ifndef COINIT_MULTITHREADED -#define COINIT_MULTITHREADED 0x00 -#endif - static xaudio2_t *xaudio2_new(unsigned samplerate, unsigned channels, size_t size, unsigned device) { @@ -251,15 +253,9 @@ error: return NULL; } -static size_t xaudio2_write_avail(xaudio2_t *handle) -{ - return handle->bufsize * (MAX_BUFFERS - handle->buffers - 1); -} - -static size_t xaudio2_write(xaudio2_t *handle, const void *buf, size_t bytes_) +static size_t xaudio2_write(xaudio2_t *handle, const uint8_t *buffer, size_t bytes_) { unsigned bytes = bytes_; - const uint8_t *buffer = (const uint8_t*)buf; while (bytes) { @@ -344,7 +340,7 @@ static ssize_t xa_write(void *data, const void *buf, size_t size) if (xa->nonblock) { - size_t avail = xaudio2_write_avail(xa->xa); + size_t avail = XAUDIO2_WRITE_AVAILABLE(xa->xa); if (avail == 0) return 0; @@ -352,7 +348,7 @@ static ssize_t xa_write(void *data, const void *buf, size_t size) size = avail; } - ret = xaudio2_write(xa->xa, buf, size); + ret = xaudio2_write(xa->xa, (const uint8_t*)buf, size); if (ret == 0 && size > 0) return -1; return ret; @@ -408,7 +404,7 @@ static void xa_free(void *data) static size_t xa_write_avail(void *data) { xa_t *xa = (xa_t*)data; - return xaudio2_write_avail(xa->xa); + return XAUDIO2_WRITE_AVAILABLE(xa->xa); } static size_t xa_buffer_size(void *data) diff --git a/bootstrap/psp1/kernel_functions_prx/main.c b/bootstrap/psp1/kernel_functions_prx/main.c index 08ae0bf0ba..2f4412b363 100644 --- a/bootstrap/psp1/kernel_functions_prx/main.c +++ b/bootstrap/psp1/kernel_functions_prx/main.c @@ -55,9 +55,10 @@ void exitspawn_kernel(const char *fileName, SceSize args, void *argp) game_param.unk4 = 0; game_param.unk5 = 0x10000; - pspSdkSetK1(0); - sceKernelSuspendAllUserThreads(); - sceKernelLoadExecVSHMs2(fileName, &game_param); + int k1 = pspSdkSetK1(0); + //sceKernelSuspendAllUserThreads(); + int ret = sceKernelLoadExecVSHMs2(fileName, &game_param); + pspSdkSetK1(k1); } int module_start(SceSize args, void *argp) diff --git a/command.c b/command.c index 0745ec1d22..0b3f966bab 100644 --- a/command.c +++ b/command.c @@ -1957,6 +1957,10 @@ bool command_event(enum event_command cmd, void *data) cheevos_toggle_hardcore_mode(); #endif break; + /* this fallthrough is on purpose, it should do + a CMD_EVENT_REINIT too */ + case CMD_EVENT_REINIT_FROM_TOGGLE: + retroarch_unset_forced_fullscreen(); case CMD_EVENT_REINIT: video_driver_reinit(); /* Poll input to avoid possibly stale data to corrupt things. */ @@ -2567,15 +2571,21 @@ TODO: Add a setting for these tweaks */ case CMD_EVENT_FULLSCREEN_TOGGLE: { settings_t *settings = config_get_ptr(); - bool new_fullscreen_state = !settings->bools.video_fullscreen; + bool new_fullscreen_state = !settings->bools.video_fullscreen + && !retroarch_is_forced_fullscreen(); if (!video_driver_has_windowed()) return false; - /* If we go fullscreen we drop all drivers and - * reinitialize to be safe. */ + /* we toggled manually, write the new value to settings */ configuration_set_bool(settings, settings->bools.video_fullscreen, new_fullscreen_state); + /* we toggled manually, the cli arg is irrelevant now */ + if (retroarch_is_forced_fullscreen()) + retroarch_unset_forced_fullscreen(); + + /* If we go fullscreen we drop all drivers and + * reinitialize to be safe. */ command_event(CMD_EVENT_REINIT, NULL); if (settings->bools.video_fullscreen) video_driver_hide_mouse(); diff --git a/command.h b/command.h index 858fcd820f..dd5099f9bc 100644 --- a/command.h +++ b/command.h @@ -61,6 +61,8 @@ enum event_command /* Quits RetroArch. */ CMD_EVENT_QUIT, /* Reinitialize all drivers. */ + CMD_EVENT_REINIT_FROM_TOGGLE, + /* Reinitialize all drivers. */ CMD_EVENT_REINIT, /* Toggles cheevos hardcore mode. */ CMD_EVENT_CHEEVOS_HARDCORE_MODE_TOGGLE, diff --git a/config.def.h b/config.def.h index 50036db322..6eaa94cb2e 100644 --- a/config.def.h +++ b/config.def.h @@ -298,11 +298,7 @@ static bool xmb_show_add = true; #endif #endif -#if defined(HAVE_LIBRETRODB) && !defined(RARCH_CONSOLE) && !defined(EMSCRIPTEN) -static bool automatically_add_content_to_playlist = true; -#else static bool automatically_add_content_to_playlist = false; -#endif static float menu_framebuffer_opacity = 0.900; @@ -689,6 +685,12 @@ static char buildbot_server_url[] = ""; #endif #elif defined(WIIU) static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/nintendo/wiiu/latest/"; +#elif defined(__CELLOS_LV2__) && defined(DEX_BUILD) +static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/playstation/ps3/latest/dex-ps3/"; +#elif defined(__CELLOS_LV2__) && defined(CEX_BUILD) +static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/playstation/ps3/latest/cex-ps3/"; +#elif defined(__CELLOS_LV2__) && defined(ODE_BUILD) +static char buildbot_server_url[] = "http://buildbot.libretro.com/nightly/playstation/ps3/latest/ode-ps3/"; #else static char buildbot_server_url[] = ""; #endif diff --git a/configuration.c b/configuration.c index db278743c7..6138b56aab 100644 --- a/configuration.c +++ b/configuration.c @@ -1578,11 +1578,6 @@ static void config_set_defaults(void) #endif settings->floats.video_scale = scale; - if (retroarch_is_forced_fullscreen()) - { - configuration_set_bool(settings, settings->bools.video_fullscreen, true); - } - if (g_defaults.settings.video_threaded_enable != video_threaded) video_driver_set_threaded(g_defaults.settings.video_threaded_enable); @@ -2377,9 +2372,6 @@ static bool config_load_file(const char *path, bool set_defaults, *bool_settings[i].ptr = tmp; } - if (!retroarch_is_forced_fullscreen()) - CONFIG_GET_BOOL_BASE(conf, settings, bools.video_fullscreen, "video_fullscreen"); - #ifdef HAVE_NETWORKGAMEPAD for (i = 0; i < MAX_USERS; i++) { diff --git a/cores/libretro-ffmpeg/ffmpeg_core.c b/cores/libretro-ffmpeg/ffmpeg_core.c index 1842f59809..e7703702f5 100644 --- a/cores/libretro-ffmpeg/ffmpeg_core.c +++ b/cores/libretro-ffmpeg/ffmpeg_core.c @@ -272,7 +272,7 @@ void CORE_PREFIX(retro_set_environment)(retro_environment_t cb) { static const struct retro_variable vars[] = { #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) - { "ffmpeg_temporal_interp", "Temporal Interpolation; enabled|disabled" }, + { "ffmpeg_temporal_interp", "Temporal Interpolation; disabled|enabled" }, #ifdef HAVE_GL_FFT { "ffmpeg_fft_resolution", "FFT Resolution; 1280x720|1920x1080|2560x1440|3840x2160|640x360|320x180" }, { "ffmpeg_fft_multisample", "FFT Multisample; 1x|2x|4x" }, diff --git a/cores/libretro-imageviewer/Makefile b/cores/libretro-imageviewer/Makefile index 2699b3c5a5..9916b3eeee 100644 --- a/cores/libretro-imageviewer/Makefile +++ b/cores/libretro-imageviewer/Makefile @@ -1,20 +1,20 @@ image_core.so: image_core.c gcc \ -g \ + -DHAVE_STB_IMAGE \ image_core.c \ - ../../libretro-common/file/file_path.c \ - ../../libretro-common/lists/dir_list.c \ - ../../libretro-common/compat/compat_strl.c \ + -I../../libretro-common/include/ \ + -I../../deps/stb/ \ ../../libretro-common/compat/compat_strcasestr.c \ - ../../libretro-common/lists/string_list.c \ + ../../libretro-common/compat/compat_strl.c \ + ../../libretro-common/file/file_path.c \ ../../libretro-common/file/retro_dirent.c \ + ../../libretro-common/lists/dir_list.c \ + ../../libretro-common/lists/string_list.c \ ../../libretro-common/streams/file_stream.c \ ../../libretro-common/vfs/vfs_implementation.c \ - -o image_core.so \ - -DHAVE_STB_IMAGE \ - -I ../../libretro-common/include/ \ - -I../../deps/stb \ - -Wl,--no-undefined \ -shared \ -fPIC \ - -lm + -Wl,--no-undefined \ + -lm \ + -o image_core.so diff --git a/ctr/gpu_old.c b/ctr/gpu_old.c index 8061d48650..b8e117e685 100644 --- a/ctr/gpu_old.c +++ b/ctr/gpu_old.c @@ -307,11 +307,17 @@ void GPU_FinishDrawing() GPUCMD_AddWrite(GPUREG_EARLYDEPTH_CLEAR, 0x00000001); } -void GPUCMD_Finalize(void) + +void GPU_Finalize(void) { GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x8, 0x00000000); GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 0x00000001); GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 0x00000001); +#if 0 + GPUCMD_Split(NULL, NULL); +#else GPUCMD_AddWrite(GPUREG_FINALIZE, 0x12345678); - GPUCMD_AddWrite(GPUREG_FINALIZE, 0x12345678); //not the cleanest way of guaranteeing 0x10-byte size but whatever good enough for now + //not the cleanest way of guaranteeing 0x10-byte size but whatever good enough for now + GPUCMD_AddWrite(GPUREG_FINALIZE,0x12345678); +#endif } diff --git a/ctr/gpu_old.h b/ctr/gpu_old.h index deac6bf7f2..287209e162 100644 --- a/ctr/gpu_old.h +++ b/ctr/gpu_old.h @@ -236,5 +236,4 @@ void GPU_DrawElements(GPU_Primitive_t primitive, u32* indexArray, u32 n) DEPRECA */ void GPU_FinishDrawing() DEPRECATED; -/// Finalizes the GPU command buffer. -void GPUCMD_Finalize(void) DEPRECATED; +void GPU_Finalize(void) DEPRECATED; diff --git a/deps/libfat/bit_ops.h b/deps/libfat/bit_ops.h new file mode 100644 index 0000000000..b3d894ec1a --- /dev/null +++ b/deps/libfat/bit_ops.h @@ -0,0 +1,61 @@ +/* + bit_ops.h + Functions for dealing with conversion of data between types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BIT_OPS_H +#define _BIT_OPS_H + +#include + +/*----------------------------------------------------------------- +Functions to deal with little endian values stored in uint8_t arrays +-----------------------------------------------------------------*/ +static inline uint16_t u8array_to_u16 (const uint8_t* item, int offset) +{ + return ( item[offset] | (item[offset + 1] << 8)); +} + +static inline uint32_t u8array_to_u32 (const uint8_t* item, int offset) +{ + return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); +} + +static inline void u16_to_u8array (uint8_t* item, int offset, uint16_t value) +{ + item[offset] = (uint8_t) value; + item[offset + 1] = (uint8_t)(value >> 8); +} + +static inline void u32_to_u8array (uint8_t* item, int offset, uint32_t value) +{ + item[offset] = (uint8_t) value; + item[offset + 1] = (uint8_t)(value >> 8); + item[offset + 2] = (uint8_t)(value >> 16); + item[offset + 3] = (uint8_t)(value >> 24); +} + +#endif /* _BIT_OPS_H */ diff --git a/deps/libfat/cache.c b/deps/libfat/cache.c new file mode 100644 index 0000000000..be3ba2e599 --- /dev/null +++ b/deps/libfat/cache.c @@ -0,0 +1,336 @@ +/* + cache.c + The cache is not visible to the user. It should be flushed + when any file is closed or changes are made to the filesystem. + + This cache implements a least-used-page replacement policy. This will + distribute sectors evenly over the pages, so if less than the maximum + pages are used at once, they should all eventually remain in the cache. + This also has the benefit of throwing out old sectors, so as not to keep + too many stale pages around. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "common.h" +#include "cache.h" +#include "disc.h" + +#include "mem_allocate.h" +#include "bit_ops.h" +#include "file_allocation_table.h" + +#define CACHE_FREE UINT_MAX + +CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, unsigned int bytesPerSector) +{ + CACHE* cache; + unsigned int i; + CACHE_ENTRY* cacheEntries; + + if (numberOfPages < 2) + numberOfPages = 2; + + if (sectorsPerPage < 8) + sectorsPerPage = 8; + + cache = (CACHE*) _FAT_mem_allocate (sizeof(CACHE)); + if (cache == NULL) + return NULL; + + cache->disc = discInterface; + cache->endOfPartition = endOfPartition; + cache->numberOfPages = numberOfPages; + cache->sectorsPerPage = sectorsPerPage; + cache->bytesPerSector = bytesPerSector; + + + cacheEntries = (CACHE_ENTRY*) _FAT_mem_allocate ( sizeof(CACHE_ENTRY) * numberOfPages); + if (cacheEntries == NULL) + { + _FAT_mem_free (cache); + return NULL; + } + + for (i = 0; i < numberOfPages; i++) + { + cacheEntries[i].sector = CACHE_FREE; + cacheEntries[i].count = 0; + cacheEntries[i].last_access = 0; + cacheEntries[i].dirty = false; + cacheEntries[i].cache = (uint8_t*) _FAT_mem_align ( sectorsPerPage * bytesPerSector ); + } + + cache->cacheEntries = cacheEntries; + + return cache; +} + +void _FAT_cache_destructor (CACHE* cache) +{ + unsigned int i; + /* Clear out cache before destroying it */ + _FAT_cache_flush(cache); + + /* Free memory in reverse allocation order */ + for (i = 0; i < cache->numberOfPages; i++) + _FAT_mem_free (cache->cacheEntries[i].cache); + _FAT_mem_free (cache->cacheEntries); + _FAT_mem_free (cache); +} + + +static u32 accessCounter = 0; + +static u32 accessTime(){ + accessCounter++; + return accessCounter; +} + + +static CACHE_ENTRY* _FAT_cache_getPage(CACHE *cache,sec_t sector) +{ + unsigned int i; + CACHE_ENTRY* cacheEntries = cache->cacheEntries; + unsigned int numberOfPages = cache->numberOfPages; + unsigned int sectorsPerPage = cache->sectorsPerPage; + + bool foundFree = false; + unsigned int oldUsed = 0; + unsigned int oldAccess = UINT_MAX; + + for(i=0;i=cacheEntries[i].sector && sector<(cacheEntries[i].sector + cacheEntries[i].count)) + { + cacheEntries[i].last_access = accessTime(); + return &(cacheEntries[i]); + } + + if(foundFree==false && (cacheEntries[i].sector==CACHE_FREE || cacheEntries[i].last_accessdisc,cacheEntries[oldUsed].sector,cacheEntries[oldUsed].count,cacheEntries[oldUsed].cache)) return NULL; + cacheEntries[oldUsed].dirty = false; + } + + sector = (sector/sectorsPerPage)*sectorsPerPage; /* align base sector to page size */ + sec_t next_page = sector + sectorsPerPage; + if(next_page > cache->endOfPartition) next_page = cache->endOfPartition; + + if(!_FAT_disc_readSectors(cache->disc,sector,next_page-sector,cacheEntries[oldUsed].cache)) return NULL; + + cacheEntries[oldUsed].sector = sector; + cacheEntries[oldUsed].count = next_page-sector; + cacheEntries[oldUsed].last_access = accessTime(); + + return &(cacheEntries[oldUsed]); +} + +bool _FAT_cache_readSectors(CACHE *cache,sec_t sector,sec_t numSectors,void *buffer) +{ + sec_t sec; + sec_t secs_to_read; + CACHE_ENTRY *entry; + uint8_t *dest = (uint8_t *)buffer; + + while(numSectors>0) + { + entry = _FAT_cache_getPage(cache,sector); + if(entry==NULL) return false; + + sec = sector - entry->sector; + secs_to_read = entry->count - sec; + if(secs_to_read>numSectors) secs_to_read = numSectors; + + memcpy(dest,entry->cache + (sec*cache->bytesPerSector),(secs_to_read*cache->bytesPerSector)); + + dest += (secs_to_read*cache->bytesPerSector); + sector += secs_to_read; + numSectors -= secs_to_read; + } + + return true; +} + +/* +Reads some data from a cache page, determined by the sector number +*/ +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size) +{ + sec_t sec; + CACHE_ENTRY *entry; + + if (offset + size > cache->bytesPerSector) return false; + + entry = _FAT_cache_getPage(cache,sector); + if(entry==NULL) return false; + + sec = sector - entry->sector; + memcpy(buffer,entry->cache + ((sec*cache->bytesPerSector) + offset),size); + + return true; +} + +bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes) +{ + uint8_t buf[4]; + if (!_FAT_cache_readPartialSector(cache, buf, sector, offset, num_bytes)) return false; + + switch(num_bytes) + { + case 1: *value = buf[0]; break; + case 2: *value = u8array_to_u16(buf,0); break; + case 4: *value = u8array_to_u32(buf,0); break; + default: return false; + } + return true; +} + +/* +Writes some data to a cache page, making sure it is loaded into memory first. +*/ +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) +{ + sec_t sec; + CACHE_ENTRY *entry; + + if (offset + size > cache->bytesPerSector) return false; + + entry = _FAT_cache_getPage(cache,sector); + if(entry==NULL) return false; + + sec = sector - entry->sector; + memcpy(entry->cache + ((sec*cache->bytesPerSector) + offset),buffer,size); + + entry->dirty = true; + return true; +} + +bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size) +{ + uint8_t buf[4] = {0, 0, 0, 0}; + + switch(size) + { + case 1: buf[0] = value; break; + case 2: u16_to_u8array(buf, 0, value); break; + case 4: u32_to_u8array(buf, 0, value); break; + default: return false; + } + + return _FAT_cache_writePartialSector(cache, buf, sector, offset, size); +} + +/* +Writes some data to a cache page, zeroing out the page first +*/ +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) +{ + sec_t sec; + CACHE_ENTRY *entry; + + if (offset + size > cache->bytesPerSector) return false; + + entry = _FAT_cache_getPage(cache,sector); + if(entry==NULL) return false; + + sec = sector - entry->sector; + memset(entry->cache + (sec*cache->bytesPerSector),0,cache->bytesPerSector); + memcpy(entry->cache + ((sec*cache->bytesPerSector) + offset),buffer,size); + + entry->dirty = true; + return true; +} + + +bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer) +{ + sec_t sec; + sec_t secs_to_write; + CACHE_ENTRY* entry; + const uint8_t *src = (const uint8_t *)buffer; + + while(numSectors>0) + { + entry = _FAT_cache_getPage(cache,sector); + if(entry==NULL) return false; + + sec = sector - entry->sector; + secs_to_write = entry->count - sec; + if(secs_to_write>numSectors) secs_to_write = numSectors; + + memcpy(entry->cache + (sec*cache->bytesPerSector),src,(secs_to_write*cache->bytesPerSector)); + + src += (secs_to_write*cache->bytesPerSector); + sector += secs_to_write; + numSectors -= secs_to_write; + + entry->dirty = true; + } + return true; +} + +/* +Flushes all dirty pages to disc, clearing the dirty flag. +*/ +bool _FAT_cache_flush (CACHE* cache) +{ + unsigned int i; + + for (i = 0; i < cache->numberOfPages; i++) + { + if (cache->cacheEntries[i].dirty) + { + if (!_FAT_disc_writeSectors (cache->disc, cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache)) + return false; + } + cache->cacheEntries[i].dirty = false; + } + + return true; +} + +void _FAT_cache_invalidate (CACHE* cache) +{ + unsigned int i; + _FAT_cache_flush(cache); + for (i = 0; i < cache->numberOfPages; i++) + { + cache->cacheEntries[i].sector = CACHE_FREE; + cache->cacheEntries[i].last_access = 0; + cache->cacheEntries[i].count = 0; + cache->cacheEntries[i].dirty = false; + } +} diff --git a/deps/libfat/cache.h b/deps/libfat/cache.h new file mode 100644 index 0000000000..07bb14c23e --- /dev/null +++ b/deps/libfat/cache.h @@ -0,0 +1,128 @@ +/* + cache.h + The cache is not visible to the user. It should be flushed + when any file is closed or changes are made to the filesystem. + + This cache implements a least-used-page replacement policy. This will + distribute sectors evenly over the pages, so if less than the maximum + pages are used at once, they should all eventually remain in the cache. + This also has the benefit of throwing out old sectors, so as not to keep + too many stale pages around. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _CACHE_H +#define _CACHE_H + +#include "common.h" +#include "disc.h" + +typedef struct { + sec_t sector; + unsigned int count; + unsigned int last_access; + bool dirty; + uint8_t* cache; +} CACHE_ENTRY; + +typedef struct { + const DISC_INTERFACE* disc; + sec_t endOfPartition; + unsigned int numberOfPages; + unsigned int sectorsPerPage; + unsigned int bytesPerSector; + CACHE_ENTRY* cacheEntries; +} CACHE; + +/* +Read data from a sector in the cache +If the sector is not in the cache, it will be swapped in +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size); + +bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes); + +/* +Write data to a sector in the cache +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start writing to +size is the amount of data to write +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); + +bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int num_bytes); + +/* +Write data to a sector in the cache, zeroing the sector first +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start writing to +size is the amount of data to write +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); + +/* +Read several sectors from the cache +*/ +bool _FAT_cache_readSectors (CACHE* cache, sec_t sector, sec_t numSectors, void* buffer); + +/* +Read a full sector from the cache +*/ +static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, sec_t sector) { + return _FAT_cache_readPartialSector (cache, buffer, sector, 0, cache->bytesPerSector); +} + +/* +Write a full sector to the cache +*/ +static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, sec_t sector) { + return _FAT_cache_writePartialSector (cache, buffer, sector, 0, cache->bytesPerSector); +} + +bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer); + +/* +Write any dirty sectors back to disc and clear out the contents of the cache +*/ +bool _FAT_cache_flush (CACHE* cache); + +/* +Clear out the contents of the cache without writing any dirty sectors first +*/ +void _FAT_cache_invalidate (CACHE* cache); + +CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, unsigned int bytesPerSector); + +void _FAT_cache_destructor (CACHE* cache); + +#endif // _CACHE_H + diff --git a/deps/libfat/common.h b/deps/libfat/common.h new file mode 100644 index 0000000000..b38889ee5f --- /dev/null +++ b/deps/libfat/common.h @@ -0,0 +1,92 @@ +/* + common.h + Common definitions and included files for the FATlib + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _COMMON_H +#define _COMMON_H + +#include +#include +#include + +/* When compiling for NDS, make sure NDS is defined */ +#ifndef NDS + #if defined ARM9 || defined ARM7 + #define NDS + #endif +#endif + +/* Platform specific includes */ +#if defined (__wiiu__) + #include + typedef uint8_t u8; + typedef uint16_t u16; + typedef int32_t s32; + typedef uint32_t u32; + typedef int mutex_t; +#elif defined(__gamecube__) || defined (__wii__) + #include + #include + #include +#elif defined(NDS) + #include + #include + #include +#elif defined(GBA) + #include + #include +#endif + +/* Platform specific options */ +#if defined (__wiiu__) + #define DEFAULT_CACHE_PAGES 4 + #define DEFAULT_SECTORS_PAGE 64 +#if 0 +#define USE_LWP_LOCK +#define USE_RTC_TIME +#endif +#elif defined (__wii__) + #define DEFAULT_CACHE_PAGES 4 + #define DEFAULT_SECTORS_PAGE 64 + #define USE_LWP_LOCK + #define USE_RTC_TIME +#elif defined (__gamecube__) + #define DEFAULT_CACHE_PAGES 4 + #define DEFAULT_SECTORS_PAGE 64 + #define USE_LWP_LOCK + #define USE_RTC_TIME +#elif defined (NDS) + #define DEFAULT_CACHE_PAGES 16 + #define DEFAULT_SECTORS_PAGE 8 + #define USE_RTC_TIME +#elif defined (GBA) + #define DEFAULT_CACHE_PAGES 2 + #define DEFAULT_SECTORS_PAGE 8 + #define LIMIT_SECTORS 128 +#endif + +#endif /* _COMMON_H */ diff --git a/deps/libfat/directory.c b/deps/libfat/directory.c new file mode 100644 index 0000000000..40f896aab4 --- /dev/null +++ b/deps/libfat/directory.c @@ -0,0 +1,1180 @@ +/* + directory.c + Reading, writing and manipulation of the directory structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include + +#include "directory.h" +#include "common.h" +#include "partition.h" +#include "file_allocation_table.h" +#include "bit_ops.h" +#include "filetime.h" + +/* Directory entry codes */ +#define DIR_ENTRY_LAST 0x00 +#define DIR_ENTRY_FREE 0xE5 + +typedef unsigned short ucs2_t; + +/* Long file name directory entry */ +enum LFN_offset +{ + LFN_offset_ordinal = 0x00, /* Position within LFN */ + LFN_offset_char0 = 0x01, + LFN_offset_char1 = 0x03, + LFN_offset_char2 = 0x05, + LFN_offset_char3 = 0x07, + LFN_offset_char4 = 0x09, + LFN_offset_flag = 0x0B, /* Should be equal to ATTRIB_LFN */ + LFN_offset_reserved1 = 0x0C, /* Always 0x00 */ + LFN_offset_checkSum = 0x0D, /* Checksum of short file name (alias) */ + LFN_offset_char5 = 0x0E, + LFN_offset_char6 = 0x10, + LFN_offset_char7 = 0x12, + LFN_offset_char8 = 0x14, + LFN_offset_char9 = 0x16, + LFN_offset_char10 = 0x18, + LFN_offset_reserved2 = 0x1A, /* Always 0x0000 */ + LFN_offset_char11 = 0x1C, + LFN_offset_char12 = 0x1E +}; +static const int LFN_offset_table[13]={0x01,0x03,0x05,0x07,0x09,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E}; + +#define LFN_END 0x40 +#define LFN_DEL 0x80 + +static const char ILLEGAL_ALIAS_CHARACTERS[] = "\\/:;*?\"<>|&+,=[] "; +static const char ILLEGAL_LFN_CHARACTERS[] = "\\/:*?\"<>|"; + +/* + Returns number of UCS-2 characters needed to encode an LFN + Returns -1 if it is an invalid LFN + */ +#define ABOVE_UCS_RANGE 0xF0 +static int _FAT_directory_lfnLength (const char* name) +{ + unsigned int i; + int ucsLength; + const char* tempName = name; + size_t nameLength = strnlen(name, NAME_MAX); + + /* Make sure the name is short enough to be valid */ + if ( nameLength >= NAME_MAX) + return -1; + + /* Make sure it doesn't contain any invalid characters */ + if (strpbrk (name, ILLEGAL_LFN_CHARACTERS) != NULL) + return -1; + + /* Make sure the name doesn't contain any control codes or codes not representable in UCS-2 */ + for (i = 0; i < nameLength; i++) + { + unsigned char ch = (unsigned char) name[i]; + if (ch < 0x20 || ch >= ABOVE_UCS_RANGE) + return -1; + } + + /* Convert to UCS-2 and get the resulting length */ + ucsLength = mbsrtowcs(NULL, &tempName, MAX_LFN_LENGTH, NULL); + if (ucsLength < 0 || ucsLength >= MAX_LFN_LENGTH) + return -1; + + /* Otherwise it is valid */ + return ucsLength; +} + +/* + Convert a multibyte encoded string into a NUL-terminated UCS-2 string, storing at most len characters + return number of characters stored + */ +static size_t _FAT_directory_mbstoucs2 (ucs2_t* dst, const char* src, size_t len) +{ + mbstate_t ps = {0}; + wchar_t tempChar; + int bytes; + size_t count = 0; + + while (count < len-1 && *src != '\0') + { + bytes = mbrtowc (&tempChar, src, MB_CUR_MAX, &ps); + if (bytes > 0) + { + *dst = (ucs2_t)tempChar; + src += bytes; + dst++; + count++; + } + else if (bytes == 0) + break; + else + return -1; + } + *dst = '\0'; + + return count; +} + +/* + Convert a UCS-2 string into a NUL-terminated multibyte string, storing at most len chars + return number of chars stored, or (size_t)-1 on error + */ +static size_t _FAT_directory_ucs2tombs (char* dst, const ucs2_t* src, size_t len) +{ + mbstate_t ps = {0}; + size_t count = 0; + int bytes; + char buff[MB_CUR_MAX]; + int i; + + while (count < len - 1 && *src != '\0') + { + bytes = wcrtomb (buff, *src, &ps); + if (bytes < 0) + return -1; + if (count + bytes < len && bytes > 0) + { + for (i = 0; i < bytes; i++) + *dst++ = buff[i]; + src++; + count += bytes; + } + else + break; + } + *dst = L'\0'; + + return count; +} + +/* + Case-independent comparison of two multibyte encoded strings + */ +static int _FAT_directory_mbsncasecmp (const char* s1, const char* s2, size_t len1) +{ + wchar_t wc1, wc2; + mbstate_t ps1 = {0}; + mbstate_t ps2 = {0}; + size_t b1 = 0; + size_t b2 = 0; + + if (len1 == 0) + return 0; + + do + { + s1 += b1; + s2 += b2; + b1 = mbrtowc(&wc1, s1, MB_CUR_MAX, &ps1); + b2 = mbrtowc(&wc2, s2, MB_CUR_MAX, &ps2); + if ((int)b1 < 0 || (int)b2 < 0) + break; + len1 -= b1; + } while (len1 > 0 && towlower(wc1) == towlower(wc2) && wc1 != 0); + + return towlower(wc1) - towlower(wc2); +} + + +static bool _FAT_directory_entryGetAlias (const u8* entryData, char* destName) +{ + char c; + bool caseInfo; + int i = 0; + int j = 0; + + destName[0] = '\0'; + if (entryData[0] != DIR_ENTRY_FREE) + { + if (entryData[0] == '.') + { + destName[0] = '.'; + if (entryData[1] == '.') + { + destName[1] = '.'; + destName[2] = '\0'; + } + else + destName[1] = '\0'; + } + else + { + /* Copy the filename from the dirEntry to the string */ + caseInfo = entryData[DIR_ENTRY_caseInfo] & CASE_LOWER_BASE; + for (i = 0; (i < 8) && (entryData[DIR_ENTRY_name + i] != ' '); i++) + { + c = entryData[DIR_ENTRY_name + i]; + destName[i] = (caseInfo ? tolower((unsigned char)c) : c); + } + /* Copy the extension from the dirEntry to the string */ + if (entryData[DIR_ENTRY_extension] != ' ') + { + destName[i++] = '.'; + caseInfo = entryData[DIR_ENTRY_caseInfo] & CASE_LOWER_EXT; + for ( j = 0; (j < 3) && (entryData[DIR_ENTRY_extension + j] != ' '); j++) + { + c = entryData[DIR_ENTRY_extension + j]; + destName[i++] = (caseInfo ? tolower((unsigned char)c) : c); + } + } + destName[i] = '\0'; + } + } + + return (destName[0] != '\0'); +} + +uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData) +{ + /* Only use high 16 bits of start cluster when we are certain they are correctly defined */ + if (partition->filesysType == FS_FAT32) + return u8array_to_u16(entryData,DIR_ENTRY_cluster) | (u8array_to_u16(entryData, DIR_ENTRY_clusterHigh) << 16); + return u8array_to_u16(entryData,DIR_ENTRY_cluster); +} + +static bool _FAT_directory_incrementDirEntryPosition (PARTITION* partition, DIR_ENTRY_POSITION* entryPosition, bool extendDirectory) +{ + DIR_ENTRY_POSITION position = *entryPosition; + uint32_t tempCluster; + + /* Increment offset, wrapping at the end of a sector */ + ++ position.offset; + if (position.offset == partition->bytesPerSector / DIR_ENTRY_DATA_SIZE) + { + position.offset = 0; + /* Increment sector when wrapping */ + ++ position.sector; + /* But wrap at the end of a cluster */ + if ((position.sector == partition->sectorsPerCluster) && (position.cluster != FAT16_ROOT_DIR_CLUSTER)) + { + position.sector = 0; + /* Move onto the next cluster, making sure there is another cluster to go to */ + tempCluster = _FAT_fat_nextCluster(partition, position.cluster); + if (tempCluster == CLUSTER_EOF) + { + if (extendDirectory) + { + tempCluster = _FAT_fat_linkFreeClusterCleared (partition, position.cluster); + if (!_FAT_fat_isValidCluster(partition, tempCluster)) + return false; /* This will only happen if the disc is full */ + } + else + return false; /* Got to the end of the directory, not extending it */ + } + position.cluster = tempCluster; + } + else if ((position.cluster == FAT16_ROOT_DIR_CLUSTER) && (position.sector == (partition->dataStart - partition->rootDirStart))) + return false; /* Got to end of root directory, can't extend it */ + } + *entryPosition = position; + return true; +} + +bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) +{ + DIR_ENTRY_POSITION entryEnd; + uint8_t entryData[0x20]; + ucs2_t lfn[MAX_LFN_LENGTH]; + bool notFound, found; + int lfnPos; + uint8_t chkSum; + bool lfnExists; + int i; + uint8_t lfnChkSum = 0; + DIR_ENTRY_POSITION entryStart = entry->dataEnd; + + /* Make sure we are using the correct root directory, in case of FAT32 */ + if (entryStart.cluster == FAT16_ROOT_DIR_CLUSTER) + entryStart.cluster = partition->rootDirCluster; + + entryEnd = entryStart; + + lfnExists = false; + + found = false; + notFound = false; + + while (!found && !notFound) + { + if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) + { + notFound = true; + break; + } + + _FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, + entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + if (entryData[DIR_ENTRY_attributes] == ATTRIB_LFN) + { + /* It's an LFN */ + if (entryData[LFN_offset_ordinal] & LFN_DEL) + lfnExists = false; + else if (entryData[LFN_offset_ordinal] & LFN_END) + { + /* Last part of LFN, make sure it isn't deleted using previous if(Thanks MoonLight) */ + entryStart = entryEnd; /* This is the start of a directory entry */ + lfnExists = true; + lfnPos = (entryData[LFN_offset_ordinal] & ~LFN_END) * 13; + if (lfnPos > MAX_LFN_LENGTH - 1) + lfnPos = MAX_LFN_LENGTH - 1; + lfn[lfnPos] = '\0'; /* Set end of lfn to null character */ + lfnChkSum = entryData[LFN_offset_checkSum]; + } + if (lfnChkSum != entryData[LFN_offset_checkSum]) + lfnExists = false; + if (lfnExists) + { + lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; + for (i = 0; i < 13; i++) + { + if (lfnPos + i < MAX_LFN_LENGTH - 1) + lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8); + } + } + } + /* This is a volume name, don't bother with it */ + else if (entryData[DIR_ENTRY_attributes] & ATTRIB_VOL) { } + else if (entryData[0] == DIR_ENTRY_LAST) + notFound = true; + else if ((entryData[0] != DIR_ENTRY_FREE) && (entryData[0] > 0x20) && !(entryData[DIR_ENTRY_attributes] & ATTRIB_VOL)) + { + if (lfnExists) + { + /* Calculate file checksum */ + chkSum = 0; + /* NOTE: The operation is an unsigned char rotate right */ + for (i=0; i < 11; i++) + chkSum = ((chkSum & 1) ? 0x80 : 0) + (chkSum >> 1) + entryData[i]; + + if (chkSum != lfnChkSum) + { + lfnExists = false; + entry->filename[0] = '\0'; + } + } + + if (lfnExists) + { + /* Failed to convert the file name to UTF-8. Maybe the wrong locale is set? */ + if (_FAT_directory_ucs2tombs (entry->filename, lfn, NAME_MAX) == (size_t)-1) + return false; + } + else + { + entryStart = entryEnd; + _FAT_directory_entryGetAlias (entryData, entry->filename); + } + found = true; + } + } + + /* If no file is found, return false */ + if (notFound) + return false; + + /* Fill in the directory entry struct */ + entry->dataStart = entryStart; + entry->dataEnd = entryEnd; + memcpy (entry->entryData, entryData, DIR_ENTRY_DATA_SIZE); + return true; +} + +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster) +{ + entry->dataStart.cluster = dirCluster; + entry->dataStart.sector = 0; + entry->dataStart.offset = -1; /* Start before the beginning of the directory */ + + entry->dataEnd = entry->dataStart; + + return _FAT_directory_getNextEntry (partition, entry); +} + +bool _FAT_directory_getRootEntry (PARTITION* partition, DIR_ENTRY* entry) +{ + entry->dataStart.cluster = 0; + entry->dataStart.sector = 0; + entry->dataStart.offset = 0; + + entry->dataEnd = entry->dataStart; + + memset (entry->filename, '\0', NAME_MAX); + entry->filename[0] = '.'; + + memset (entry->entryData, 0, DIR_ENTRY_DATA_SIZE); + memset (entry->entryData, ' ', 11); + entry->entryData[0] = '.'; + + entry->entryData[DIR_ENTRY_attributes] = ATTRIB_DIR; + + u16_to_u8array (entry->entryData, DIR_ENTRY_cluster, partition->rootDirCluster); + u16_to_u8array (entry->entryData, DIR_ENTRY_clusterHigh, partition->rootDirCluster >> 16); + + return true; +} + +bool _FAT_directory_getVolumeLabel (PARTITION* partition, char *label) +{ + DIR_ENTRY entry; + DIR_ENTRY_POSITION entryEnd; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + int i; + bool end; + + _FAT_directory_getRootEntry(partition, &entry); + + entryEnd = entry.dataEnd; + + /* Make sure we are using the correct root directory, in case of FAT32 */ + if (entryEnd.cluster == FAT16_ROOT_DIR_CLUSTER) + entryEnd.cluster = partition->rootDirCluster; + + label[0]='\0'; + label[11]='\0'; + end = false; + + /* this entry should be among the first 3 entries in the root directory table, + * if not, then system can have trouble displaying the right volume label */ + + while(!end) + { + /* error reading */ + if(!_FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, + entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE)) + return false; + + if (entryData[DIR_ENTRY_attributes] == ATTRIB_VOL && entryData[0] != DIR_ENTRY_FREE) + { + for (i = 0; i < 11; i++) + label[i] = entryData[DIR_ENTRY_name + i]; + return true; + } + else if (entryData[0] == DIR_ENTRY_LAST) + end = true; + + if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) + end = true; + } + return false; +} + +bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) +{ + DIR_ENTRY_POSITION entryStart = entry->dataStart; + DIR_ENTRY_POSITION entryEnd = entry->dataEnd; + bool entryStillValid; + bool finished; + ucs2_t lfn[MAX_LFN_LENGTH]; + int i; + int lfnPos; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + + memset (entry->filename, '\0', NAME_MAX); + + /* Create an empty directory entry to overwrite the old ones with */ + for ( entryStillValid = true, finished = false; + entryStillValid && !finished; + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &entryStart, false)) + { + _FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, + entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + if ((entryStart.cluster == entryEnd.cluster) + && (entryStart.sector == entryEnd.sector) + && (entryStart.offset == entryEnd.offset)) + { + /* Copy the entry data and stop, since this is the + * last section of the directory entry */ + memcpy (entry->entryData, entryData, DIR_ENTRY_DATA_SIZE); + finished = true; + } + else + { + /* Copy the long file name data */ + lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; + for (i = 0; i < 13; i++) + { + if (lfnPos + i < MAX_LFN_LENGTH - 1) + lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8); + } + } + } + + if (!entryStillValid) + return false; + + entryStart = entry->dataStart; + if ((entryStart.cluster == entryEnd.cluster) + && (entryStart.sector == entryEnd.sector) + && (entryStart.offset == entryEnd.offset)) + { + /* Since the entry doesn't have a long file name, extract the short filename */ + if (!_FAT_directory_entryGetAlias (entry->entryData, entry->filename)) + return false; + } + else + { + /* Encode the long file name into a multibyte string */ + if (_FAT_directory_ucs2tombs (entry->filename, lfn, NAME_MAX) == (size_t)-1) + return false; + } + + return true; +} + + + +bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd) +{ + size_t dirnameLength; + const char* nextPathPosition; + uint32_t dirCluster; + bool foundFile; + char alias[MAX_ALIAS_LENGTH]; + const char *pathPosition = path; + bool found = false; + bool notFound = false; + + /* Set pathEnd to the end of the path string */ + if (pathEnd == NULL) + pathEnd = strchr (path, '\0'); + + if (pathPosition[0] == DIR_SEPARATOR) + { + /* Start at root directory */ + dirCluster = partition->rootDirCluster; + /* Consume separator(s) */ + while (pathPosition[0] == DIR_SEPARATOR) + pathPosition++; + /* If the path is only specifying a directory in the form of "/" return it */ + if (pathPosition >= pathEnd) + { + _FAT_directory_getRootEntry (partition, entry); + found = true; + } + } + /* Start in current working directory */ + else + dirCluster = partition->cwdCluster; + + while (!found && !notFound) + { + /* Get the name of the next required subdirectory within the path */ + nextPathPosition = strchr (pathPosition, DIR_SEPARATOR); + if (nextPathPosition != NULL) + dirnameLength = nextPathPosition - pathPosition; + else + dirnameLength = strlen(pathPosition); + + /* The path is too long to bother with */ + if (dirnameLength > NAME_MAX) + return false; + + /* Check for "." or ".." when the dirCluster is root cluster + * These entries do not exist, so we must fake it */ + if ((dirCluster == partition->rootDirCluster) + && ((strncmp(".", pathPosition, dirnameLength) == 0) + || (strncmp("..", pathPosition, dirnameLength) == 0))) + { + foundFile = true; + _FAT_directory_getRootEntry(partition, entry); + } + else + { + /* Look for the directory within the path */ + foundFile = _FAT_directory_getFirstEntry (partition, entry, dirCluster); + + while (foundFile && !found && !notFound) + { + /* It hasn't already found the file + * Check if the filename matches */ + if ((dirnameLength == strnlen(entry->filename, NAME_MAX)) + && (_FAT_directory_mbsncasecmp(pathPosition, entry->filename, dirnameLength) == 0)) + found = true; + + /* Check if the alias matches */ + _FAT_directory_entryGetAlias (entry->entryData, alias); + if ((dirnameLength == strnlen(alias, MAX_ALIAS_LENGTH)) + && (strncasecmp(pathPosition, alias, dirnameLength) == 0)) + found = true; + + /* Make sure that we aren't trying to follow a file instead of a directory in the path */ + if (found && !(entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) && (nextPathPosition != NULL)) + found = false; + + if (!found) + foundFile = _FAT_directory_getNextEntry (partition, entry); + } + } + + if (!foundFile) + { + /* Check that the search didn't get to the end of the directory */ + notFound = true; + found = false; + } + /* Check that we reached the end of the path */ + else if ((nextPathPosition == NULL) || (nextPathPosition >= pathEnd)) + found = true; + else if (entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) + { + dirCluster = _FAT_directory_entryGetCluster (partition, entry->entryData); + if (dirCluster == CLUSTER_ROOT) + dirCluster = partition->rootDirCluster; + pathPosition = nextPathPosition; + /* Consume separator(s) */ + while (pathPosition[0] == DIR_SEPARATOR) + pathPosition++; + /* The requested directory was found */ + if (pathPosition >= pathEnd) + found = true; + else + found = false; + } + } + + if (found && !notFound) + { + /* On FAT32 it should specify an actual cluster for the root entry, + * not cluster 0 as on FAT16 */ + if (partition->filesysType == FS_FAT32 && (entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) && + _FAT_directory_entryGetCluster (partition, entry->entryData) == CLUSTER_ROOT) + _FAT_directory_getRootEntry (partition, entry); + return true; + } + + return false; +} + +bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry) +{ + DIR_ENTRY_POSITION entryStart = entry->dataStart; + DIR_ENTRY_POSITION entryEnd = entry->dataEnd; + bool entryStillValid; + bool finished; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + + /* Create an empty directory entry to overwrite the old ones with */ + for ( entryStillValid = true, finished = false; + entryStillValid && !finished; + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &entryStart, false)) + { + _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + entryData[0] = DIR_ENTRY_FREE; + _FAT_cache_writePartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + if ((entryStart.cluster == entryEnd.cluster) && (entryStart.sector == entryEnd.sector) && (entryStart.offset == entryEnd.offset)) + finished = true; + } + + if (!entryStillValid) + return false; + + return true; +} + +static bool _FAT_directory_findEntryGap (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster, size_t size) +{ + DIR_ENTRY_POSITION gapStart; + DIR_ENTRY_POSITION gapEnd; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + size_t dirEntryRemain; + bool endOfDirectory, entryStillValid; + + /* Scan Dir for free entry */ + gapEnd.offset = 0; + gapEnd.sector = 0; + gapEnd.cluster = dirCluster; + + gapStart = gapEnd; + + entryStillValid = true; + dirEntryRemain = size; + endOfDirectory = false; + + while (entryStillValid && !endOfDirectory && (dirEntryRemain > 0)) + { + _FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector, + gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + if (entryData[0] == DIR_ENTRY_LAST) + { + if (dirEntryRemain == size) + gapStart = gapEnd; + -- dirEntryRemain; + endOfDirectory = true; + } + else if (entryData[0] == DIR_ENTRY_FREE) + { + if (dirEntryRemain == size) + gapStart = gapEnd; + -- dirEntryRemain; + } + else + dirEntryRemain = size; + + if (!endOfDirectory && (dirEntryRemain > 0)) + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &gapEnd, true); + } + + /* Make sure the scanning didn't fail */ + if (!entryStillValid) + return false; + + /* Save the start entry, since we know it is valid */ + entry->dataStart = gapStart; + + if (endOfDirectory) + { + memset (entryData, DIR_ENTRY_LAST, DIR_ENTRY_DATA_SIZE); + dirEntryRemain += 1; /* Increase by one to take account of End Of Directory Marker */ + + while ((dirEntryRemain > 0) && entryStillValid) + { + /* Get the gapEnd before incrementing it, so the second to last one is saved */ + entry->dataEnd = gapEnd; + /* Increment gapEnd, moving onto the next entry */ + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &gapEnd, true); + -- dirEntryRemain; + /* Fill the entry with blanks */ + _FAT_cache_writePartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector, + gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + } + if (!entryStillValid) + return false; + } + else + entry->dataEnd = gapEnd; + + return true; +} + +static bool _FAT_directory_entryExists (PARTITION* partition, const char* name, uint32_t dirCluster) +{ + DIR_ENTRY tempEntry; + bool foundFile; + char alias[MAX_ALIAS_LENGTH]; + size_t dirnameLength = strnlen(name, NAME_MAX); + + if (dirnameLength >= NAME_MAX) + return false; + + /* Make sure the entry doesn't already exist */ + foundFile = _FAT_directory_getFirstEntry (partition, &tempEntry, dirCluster); + + while (foundFile) + { + /* It hasn't already found the file + * Check if the filename matches */ + if ((dirnameLength == strnlen(tempEntry.filename, NAME_MAX)) + && (_FAT_directory_mbsncasecmp(name, tempEntry.filename, dirnameLength) == 0)) + return true; + + /* Check if the alias matches */ + _FAT_directory_entryGetAlias (tempEntry.entryData, alias); + if ((strncasecmp(name, alias, MAX_ALIAS_LENGTH) == 0)) + return true; + foundFile = _FAT_directory_getNextEntry (partition, &tempEntry); + } + return false; +} + +/* + Creates an alias for a long file name. If the alias is not an exact match for the + filename, it returns the number of characters in the alias. If the two names match, + it returns 0. If there was an error, it returns -1. + */ +static int _FAT_directory_createAlias (char* alias, const char* lfn) +{ + bool lossyConversion = false; /* Set when the alias had to be modified to be valid */ + int lfnPos = 0; + int aliasPos = 0; + wchar_t lfnChar; + int oemChar; + mbstate_t ps = {0}; + int bytesUsed = 0; + const char* lfnExt; + int aliasExtLen; + + /* Strip leading periods */ + while (lfn[lfnPos] == '.') + { + lfnPos ++; + lossyConversion = true; + } + + /* Primary portion of alias */ + while (aliasPos < 8 && lfn[lfnPos] != '.' && lfn[lfnPos] != '\0') + { + bytesUsed = mbrtowc(&lfnChar, lfn + lfnPos, NAME_MAX - lfnPos, &ps); + if (bytesUsed < 0) + return -1; + + oemChar = wctob(towupper((wint_t)lfnChar)); + + /* Case of letter was changed */ + if (wctob((wint_t)lfnChar) != oemChar) + lossyConversion = true; + + if (oemChar == ' ') + { + /* Skip spaces in filename */ + lossyConversion = true; + lfnPos += bytesUsed; + continue; + } + + if (oemChar == EOF) + { + oemChar = '_'; /* Replace unconvertable characters with underscores */ + lossyConversion = true; + } + + if (strchr (ILLEGAL_ALIAS_CHARACTERS, oemChar) != NULL) + { + /* Invalid Alias character */ + oemChar = '_'; /* Replace illegal characters with underscores */ + lossyConversion = true; + } + + alias[aliasPos] = (char)oemChar; + aliasPos++; + lfnPos += bytesUsed; + } + + /* Name was more than 8 characters long */ + if (lfn[lfnPos] != '.' && lfn[lfnPos] != '\0') + lossyConversion = true; + + /* Alias extension */ + lfnExt = strrchr (lfn, '.'); + /* More than one period in name */ + if (lfnExt != NULL && lfnExt != strchr (lfn, '.')) + lossyConversion = true; + + if (lfnExt != NULL && lfnExt[1] != '\0') + { + lfnExt++; + alias[aliasPos] = '.'; + aliasPos++; + memset (&ps, 0, sizeof(ps)); + for (aliasExtLen = 0; aliasExtLen < MAX_ALIAS_EXT_LENGTH && *lfnExt != '\0'; aliasExtLen++) + { + bytesUsed = mbrtowc(&lfnChar, lfnExt, NAME_MAX - lfnPos, &ps); + if (bytesUsed < 0) + return -1; + oemChar = wctob(towupper((wint_t)lfnChar)); + + /* Case of letter was changed */ + if (wctob((wint_t)lfnChar) != oemChar) + lossyConversion = true; + if (oemChar == ' ') + { + /* Skip spaces in alias */ + lossyConversion = true; + lfnExt += bytesUsed; + continue; + } + if (oemChar == EOF) + { + oemChar = '_'; /* Replace unconvertable characters with underscores */ + lossyConversion = true; + } + if (strchr (ILLEGAL_ALIAS_CHARACTERS, oemChar) != NULL) + { + /* Invalid Alias character */ + oemChar = '_'; /* Replace illegal characters with underscores */ + lossyConversion = true; + } + + alias[aliasPos] = (char)oemChar; + aliasPos++; + lfnExt += bytesUsed; + } + /* Extension was more than 3 characters long */ + if (*lfnExt != '\0') + lossyConversion = true; + } + + alias[aliasPos] = '\0'; + if (lossyConversion) + return aliasPos; + return 0; +} + +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster) +{ + size_t entrySize; + uint8_t lfnEntry[DIR_ENTRY_DATA_SIZE]; + int i,j; /* Must be signed for use when decrementing in for loop */ + char *tmpCharPtr; + DIR_ENTRY_POSITION curEntryPos; + bool entryStillValid; + uint8_t aliasCheckSum = 0; + char alias [MAX_ALIAS_LENGTH]; + int aliasLen; + int lfnLen; + + /* Remove trailing spaces */ + for (i = strlen (entry->filename) - 1; (i >= 0) && (entry->filename[i] == ' '); --i) + entry->filename[i] = '\0'; + +#if 0 + /* Remove leading spaces */ + for (i = 0; entry->filename[i] == ' '; ++i) ; + if (i > 0) + memmove (entry->filename, entry->filename + i, strlen (entry->filename + i)); +#endif + + /* Make sure the filename is not 0 length */ + if (strnlen (entry->filename, NAME_MAX) < 1) + return false; + + /* Make sure the filename is at least a valid LFN */ + lfnLen = _FAT_directory_lfnLength (entry->filename); + if (lfnLen < 0) + return false; + + /* Remove junk in filename */ + i = strlen (entry->filename); + memset (entry->filename + i, '\0', NAME_MAX - i); + + /* Make sure the entry doesn't already exist */ + if (_FAT_directory_entryExists (partition, entry->filename, dirCluster)) + return false; + + /* Clear out alias, so we can generate a new one */ + memset (entry->entryData, ' ', 11); + + if ( strncmp(entry->filename, ".", NAME_MAX) == 0) + { + /* "." entry */ + entry->entryData[0] = '.'; + entrySize = 1; + } + else if ( strncmp(entry->filename, "..", NAME_MAX) == 0) + { + /* ".." entry */ + entry->entryData[0] = '.'; + entry->entryData[1] = '.'; + entrySize = 1; + } + else + { + /* Normal file name */ + aliasLen = _FAT_directory_createAlias (alias, entry->filename); + if (aliasLen < 0) + return false; + /* It's a normal short filename */ + else if (aliasLen == 0) + entrySize = 1; + else + { + /* It's a long filename with an alias */ + entrySize = ((lfnLen + LFN_ENTRY_LENGTH - 1) / LFN_ENTRY_LENGTH) + 1; + + /* Generate full alias for all cases except when + * the alias is simply an upper case version of the LFN + * and there isn't already a file with that name + */ + if (strncasecmp (alias, entry->filename, MAX_ALIAS_LENGTH) != 0 || + _FAT_directory_entryExists (partition, alias, dirCluster)) + { + /* expand primary part to 8 characters long by padding the end with underscores */ + i = 0; + j = MAX_ALIAS_PRI_LENGTH; + /* Move extension to last 3 characters */ + while (alias[i] != '.' && alias[i] != '\0') i++; + + if (i < j) + { + memmove (alias + j, alias + i, aliasLen - i + 1); + /* Pad primary component */ + memset (alias + i, '_', j - i); + } + + /* Generate numeric tail */ + for (i = 1; i <= MAX_NUMERIC_TAIL; i++) + { + j = i; + tmpCharPtr = alias + MAX_ALIAS_PRI_LENGTH - 1; + while (j > 0) + { + *tmpCharPtr = '0' + (j % 10); /* ASCII numeric value */ + tmpCharPtr--; + j /= 10; + } + *tmpCharPtr = '~'; + if (!_FAT_directory_entryExists (partition, alias, dirCluster)) + break; + } + + /* Couldn't get a valid alias */ + if (i > MAX_NUMERIC_TAIL) + return false; + } + } + + /* Copy alias or short file name into directory entry data */ + for (i = 0, j = 0; (j < 8) && (alias[i] != '.') && (alias[i] != '\0'); i++, j++) + entry->entryData[j] = alias[i]; + while (j < 8) + { + entry->entryData[j] = ' '; + ++ j; + } + if (alias[i] == '.') + { + /* Copy extension */ + ++ i; + while ((alias[i] != '\0') && (j < 11)) + { + entry->entryData[j] = alias[i]; + ++ i; + ++ j; + } + } + while (j < 11) + { + entry->entryData[j] = ' '; + ++ j; + } + + /* Generate alias checksum + * NOTE: The operation is an unsigned char rotate right */ + for (i=0; i < ALIAS_ENTRY_LENGTH; i++) + aliasCheckSum = ((aliasCheckSum & 1) ? 0x80 : 0) + (aliasCheckSum >> 1) + entry->entryData[i]; + } + + /* Find or create space for the entry */ + if (_FAT_directory_findEntryGap (partition, entry, dirCluster, entrySize) == false) + return false; + + /* Write out directory entry */ + curEntryPos = entry->dataStart; + + { + /* lfn is only pushed onto the stack here, reducing overall stack usage */ + ucs2_t lfn[MAX_LFN_LENGTH] = {0}; + _FAT_directory_mbstoucs2 (lfn, entry->filename, MAX_LFN_LENGTH); + + for (entryStillValid = true, i = entrySize; entryStillValid && i > 0; + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &curEntryPos, false), -- i ) + { + if (i > 1) + { + /* Long filename entry */ + lfnEntry[LFN_offset_ordinal] = (i - 1) | ((size_t)i == entrySize ? LFN_END : 0); + for (j = 0; j < 13; j++) + { + if (lfn [(i - 2) * 13 + j] == '\0') + { + if ((j > 1) && (lfn [(i - 2) * 13 + (j-1)] == '\0')) + u16_to_u8array (lfnEntry, LFN_offset_table[j], 0xffff); /* Padding */ + else + u16_to_u8array (lfnEntry, LFN_offset_table[j], 0x0000); /* Terminating null character */ + } + else + u16_to_u8array (lfnEntry, LFN_offset_table[j], lfn [(i - 2) * 13 + j]); + } + + lfnEntry[LFN_offset_checkSum] = aliasCheckSum; + lfnEntry[LFN_offset_flag] = ATTRIB_LFN; + lfnEntry[LFN_offset_reserved1] = 0; + u16_to_u8array (lfnEntry, LFN_offset_reserved2, 0); + _FAT_cache_writePartialSector (partition->cache, lfnEntry, _FAT_fat_clusterToSector(partition, curEntryPos.cluster) + curEntryPos.sector, curEntryPos.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + } + else + { + /* Alias & file data */ + _FAT_cache_writePartialSector (partition->cache, entry->entryData, _FAT_fat_clusterToSector(partition, curEntryPos.cluster) + curEntryPos.sector, curEntryPos.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + } + } + } + + return true; +} + +bool _FAT_directory_chdir (PARTITION* partition, const char* path) +{ + DIR_ENTRY entry; + + if (!_FAT_directory_entryFromPath (partition, &entry, path, NULL)) + return false; + + if (!(entry.entryData[DIR_ENTRY_attributes] & ATTRIB_DIR)) + return false; + + partition->cwdCluster = _FAT_directory_entryGetCluster (partition, entry.entryData); + + return true; +} + +void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st) +{ + /* Fill in the stat struct + * Some of the values are faked for the sake of compatibility */ + st->st_dev = _FAT_disc_hostType(partition->disc); /* The device is the 32bit ioType value */ + st->st_ino = (ino_t)(_FAT_directory_entryGetCluster(partition, entry->entryData)); /* The file serial number is the start cluster */ + st->st_mode = (_FAT_directory_isDirectory(entry) ? S_IFDIR : S_IFREG) | + (S_IRUSR | S_IRGRP | S_IROTH) | + (_FAT_directory_isWritable (entry) ? (S_IWUSR | S_IWGRP | S_IWOTH) : 0); /* Mode bits based on dirEntry ATTRIB byte */ + st->st_nlink = 1; /* Always one hard link on a FAT file */ + st->st_uid = 1; /* Faked for FAT */ + st->st_gid = 2; /* Faked for FAT */ + st->st_rdev = st->st_dev; + st->st_size = u8array_to_u32 (entry->entryData, DIR_ENTRY_fileSize); /* File size */ + st->st_atime = _FAT_filetime_to_time_t ( + 0, + u8array_to_u16 (entry->entryData, DIR_ENTRY_aDate) + ); + st->st_spare1 = 0; + st->st_mtime = _FAT_filetime_to_time_t ( + u8array_to_u16 (entry->entryData, DIR_ENTRY_mTime), + u8array_to_u16 (entry->entryData, DIR_ENTRY_mDate) + ); + st->st_spare2 = 0; + st->st_ctime = _FAT_filetime_to_time_t ( + u8array_to_u16 (entry->entryData, DIR_ENTRY_cTime), + u8array_to_u16 (entry->entryData, DIR_ENTRY_cDate) + ); + st->st_spare3 = 0; + st->st_blksize = partition->bytesPerSector; /* Prefered file I/O block size */ + st->st_blocks = (st->st_size + partition->bytesPerSector - 1) / partition->bytesPerSector; /* File size in blocks */ + st->st_spare4[0] = 0; + st->st_spare4[1] = 0; +} diff --git a/deps/libfat/directory.h b/deps/libfat/directory.h new file mode 100644 index 0000000000..826bf6d13b --- /dev/null +++ b/deps/libfat/directory.h @@ -0,0 +1,181 @@ +/* + directory.h + Reading, writing and manipulation of the directory structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _DIRECTORY_H +#define _DIRECTORY_H + +#include +#include + +#include "common.h" +#include "partition.h" + +#define DIR_ENTRY_DATA_SIZE 0x20 +#define MAX_LFN_LENGTH 256 +#define MAX_ALIAS_LENGTH 13 +#define LFN_ENTRY_LENGTH 13 +#define ALIAS_ENTRY_LENGTH 11 +#define MAX_ALIAS_EXT_LENGTH 3 +#define MAX_ALIAS_PRI_LENGTH 8 +#define MAX_NUMERIC_TAIL 999999 +#define FAT16_ROOT_DIR_CLUSTER 0 + +#define DIR_SEPARATOR '/' + +/* File attributes */ +#define ATTRIB_ARCH 0x20 /* Archive */ +#define ATTRIB_DIR 0x10 /* Directory */ +#define ATTRIB_LFN 0x0F /* Long file name */ +#define ATTRIB_VOL 0x08 /* Volume */ +#define ATTRIB_SYS 0x04 /* System */ +#define ATTRIB_HID 0x02 /* Hidden */ +#define ATTRIB_RO 0x01 /* Read only */ + +#define CASE_LOWER_EXT 0x10 /* WinNT lowercase extension */ +#define CASE_LOWER_BASE 0x08 /* WinNT lowercase basename */ + +typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE; + +typedef struct { + uint32_t cluster; + sec_t sector; + int32_t offset; +} DIR_ENTRY_POSITION; + +typedef struct { + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + DIR_ENTRY_POSITION dataStart; /* Points to the start of the LFN entries of a file, or the alias for no LFN */ + DIR_ENTRY_POSITION dataEnd; /* Always points to the file/directory's alias entry */ + char filename[NAME_MAX]; +} DIR_ENTRY; + +/* Directory entry offsets */ +enum DIR_ENTRY_offset { + DIR_ENTRY_name = 0x00, + DIR_ENTRY_extension = 0x08, + DIR_ENTRY_attributes = 0x0B, + DIR_ENTRY_caseInfo = 0x0C, + DIR_ENTRY_cTime_ms = 0x0D, + DIR_ENTRY_cTime = 0x0E, + DIR_ENTRY_cDate = 0x10, + DIR_ENTRY_aDate = 0x12, + DIR_ENTRY_clusterHigh = 0x14, + DIR_ENTRY_mTime = 0x16, + DIR_ENTRY_mDate = 0x18, + DIR_ENTRY_cluster = 0x1A, + DIR_ENTRY_fileSize = 0x1C +}; + +/* +Returns true if the file specified by entry is a directory +*/ +static inline bool _FAT_directory_isDirectory (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) != 0); +} + +static inline bool _FAT_directory_isWritable (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO) == 0); +} + +static inline bool _FAT_directory_isDot (DIR_ENTRY* entry) { + return ((entry->filename[0] == '.') && ((entry->filename[1] == '\0') || + ((entry->filename[1] == '.') && entry->filename[2] == '\0'))); +} + +/* +Reads the first directory entry from the directory starting at dirCluster +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); + +/* +Reads the next directory entry after the one already pointed to by entry +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Gets the directory entry corrsponding to the supplied path +entry will be destroyed even if no directory entry is found +pathEnd specifies the end of the path string, for cutting strings short if needed + specify NULL to use the full length of path + pathEnd is only a suggestion, and the path string will be searched up until the next PATH_SEPARATOR + after pathEND. +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd); + +/* +Changes the current directory to the one specified by path +Returns true on success, false on failure +*/ +bool _FAT_directory_chdir (PARTITION* partition, const char* path); + +/* +Removes the directory entry specified by entry +Assumes that entry is valid +Returns true on success, false on failure +*/ +bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Add a directory entry to the directory specified by dirCluster +The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are +updated with the new directory entry position and alias. +Returns true on success, false on failure +*/ +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); + +/* +Get the start cluster of a file from it's entry data +*/ +uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData); + +/* +Fill in the file name and entry data of DIR_ENTRY* entry. +Assumes that the entry's dataStart and dataEnd are correct +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry); + +/* +Fill in a stat struct based on a file entry +*/ +void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st); + +/* +Get volume label +*/ +bool _FAT_directory_getVolumeLabel (PARTITION* partition, char *label); + +#endif /* _DIRECTORY_H */ diff --git a/deps/libfat/disc.c b/deps/libfat/disc.c new file mode 100644 index 0000000000..15397e9953 --- /dev/null +++ b/deps/libfat/disc.c @@ -0,0 +1,139 @@ +/* + disc.c + Interface to the low level disc functions. Used by the higher level + file system code. + + Copyright (c) 2008 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "disc.h" + +/* +The list of interfaces consists of a series of name/interface pairs. +The interface is returned via a simple function. This allows for +platforms where the interface has to be "assembled" before it can +be used, like DLDI on the NDS. For cases where a simple struct +is available, wrapper functions are used. +The list is terminated by a NULL/NULL entry. +*/ + +/* ====================== Wii U ====================== */ +#if defined (__wiiu__) +#include + +static const DISC_INTERFACE* get_io_wiiu_sd (void) +{ + return &IOSUHAX_sdio_disc_interface; +} + +static const DISC_INTERFACE* get_io_wiiu_usb (void) +{ + return &IOSUHAX_usb_disc_interface; +} + +const INTERFACE_ID _FAT_disc_interfaces[] = { + {"sd", get_io_wiiu_sd}, + {"usb", get_io_wiiu_usb}, + {NULL, NULL} +}; + +/* ====================== Wii ====================== */ +#elif defined (__wii__) +#include +#include +#include + +static const DISC_INTERFACE* get_io_wiisd (void) +{ + return &__io_wiisd; +} +static const DISC_INTERFACE* get_io_usbstorage (void) +{ + return &__io_usbstorage; +} + +static const DISC_INTERFACE* get_io_gcsda (void) +{ + return &__io_gcsda; +} + +static const DISC_INTERFACE* get_io_gcsdb (void) +{ + return &__io_gcsdb; +} + +const INTERFACE_ID _FAT_disc_interfaces[] = { + {"sd", get_io_wiisd}, + {"usb", get_io_usbstorage}, + {"carda", get_io_gcsda}, + {"cardb", get_io_gcsdb}, + {NULL, NULL} +}; + +/* ==================== Gamecube ==================== */ +#elif defined (__gamecube__) +#include + +static const DISC_INTERFACE* get_io_gcsda (void) +{ + return &__io_gcsda; +} +static const DISC_INTERFACE* get_io_gcsdb (void) +{ + return &__io_gcsdb; +} + +const INTERFACE_ID _FAT_disc_interfaces[] = { + {"carda", get_io_gcsda}, + {"cardb", get_io_gcsdb}, + {NULL, NULL} +}; + +/* ====================== NDS ====================== */ +#elif defined (NDS) +#include +#include + +static const DISC_INTERFACE* get_io_dsisd (void) +{ + return isDSiMode() ? &__io_dsisd : NULL; +} + +const INTERFACE_ID _FAT_disc_interfaces[] = { + {"sd", get_io_dsisd}, + {"fat", dldiGetInternal}, + {NULL, NULL} +}; + +/* ====================== GBA ====================== */ +#elif defined (GBA) +#include + +const INTERFACE_ID _FAT_disc_interfaces[] = { + {"fat", discGetInterface}, + {NULL, NULL} +}; + +#endif + diff --git a/deps/libfat/disc.h b/deps/libfat/disc.h new file mode 100644 index 0000000000..ef9e2057ba --- /dev/null +++ b/deps/libfat/disc.h @@ -0,0 +1,119 @@ +/* + disc.h + Interface to the low level disc functions. Used by the higher level + file system code. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef _DISC_H +#define _DISC_H + +#include "common.h" + +/* +A list of all default devices to try at startup, +terminated by a {NULL,NULL} entry. +*/ +typedef struct +{ + const char* name; + const DISC_INTERFACE* (*getInterface)(void); +} INTERFACE_ID; +extern const INTERFACE_ID _FAT_disc_interfaces[]; + +/* +Check if a disc is inserted +Return true if a disc is inserted and ready, false otherwise +*/ +static inline bool _FAT_disc_isInserted (const DISC_INTERFACE* disc) +{ + return disc->isInserted(); +} + +/* +Read numSectors sectors from a disc, starting at sector. +numSectors is between 1 and LIMIT_SECTORS if LIMIT_SECTORS is defined, +else it is at least 1 +sector is 0 or greater +buffer is a pointer to the memory to fill +*/ +static inline bool _FAT_disc_readSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, void* buffer) +{ + return disc->readSectors (sector, numSectors, buffer); +} + +/* +Write numSectors sectors to a disc, starting at sector. +numSectors is between 1 and LIMIT_SECTORS if LIMIT_SECTORS is defined, +else it is at least 1 +sector is 0 or greater +buffer is a pointer to the memory to read from +*/ +static inline bool _FAT_disc_writeSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, const void* buffer) +{ + return disc->writeSectors (sector, numSectors, buffer); +} + +/* +Reset the card back to a ready state +*/ +static inline bool _FAT_disc_clearStatus (const DISC_INTERFACE* disc) +{ + return disc->clearStatus(); +} + +/* +Initialise the disc to a state ready for data reading or writing +*/ +static inline bool _FAT_disc_startup (const DISC_INTERFACE* disc) +{ + return disc->startup(); +} + +/* +Put the disc in a state ready for power down. +Complete any pending writes and disable the disc if necessary +*/ +static inline bool _FAT_disc_shutdown (const DISC_INTERFACE* disc) +{ + return disc->shutdown(); +} + +/* +Return a 32 bit value unique to each type of interface +*/ +static inline uint32_t _FAT_disc_hostType (const DISC_INTERFACE* disc) +{ + return disc->ioType; +} + +/* +Return a 32 bit value that specifies the capabilities of the disc +*/ +static inline uint32_t _FAT_disc_features (const DISC_INTERFACE* disc) +{ + return disc->features; +} + +#endif /* _DISC_H */ diff --git a/deps/libfat/fatdir.c b/deps/libfat/fatdir.c new file mode 100644 index 0000000000..682a9c6635 --- /dev/null +++ b/deps/libfat/fatdir.c @@ -0,0 +1,666 @@ +/* + fatdir.c + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include + +#include "fatdir.h" + +#include "cache.h" +#include "file_allocation_table.h" +#include "partition.h" +#include "directory.h" +#include "bit_ops.h" +#include "filetime.h" +#include "lock.h" + + +int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) +{ + PARTITION* partition = NULL; + DIR_ENTRY dirEntry; + + /* Get the partition this file is on */ + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) + { + r->_errno = ENODEV; + return -1; + } + + /* Move the path pointer to the start of the actual path */ + if (strchr (path, ':') != NULL) + path = strchr (path, ':') + 1; + if (strchr (path, ':') != NULL) + { + r->_errno = EINVAL; + return -1; + } + + _FAT_lock(&partition->lock); + + /* Search for the file on the disc */ + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) + { + _FAT_unlock(&partition->lock); + r->_errno = ENOENT; + return -1; + } + + /* Fill in the stat struct */ + _FAT_directory_entryStat (partition, &dirEntry, st); + + _FAT_unlock(&partition->lock); + return 0; +} + +int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink) +{ + r->_errno = ENOTSUP; + return -1; +} + +int _FAT_unlink_r (struct _reent *r, const char *path) +{ + PARTITION* partition = NULL; + DIR_ENTRY dirEntry; + DIR_ENTRY dirContents; + uint32_t cluster; + bool nextEntry; + bool errorOccured = false; + + /* Get the partition this directory is on */ + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) + { + r->_errno = ENODEV; + return -1; + } + + /* Make sure we aren't trying to write to a read-only disc */ + if (partition->readOnly) + { + r->_errno = EROFS; + return -1; + } + + /* Move the path pointer to the start of the actual path */ + if (strchr (path, ':') != NULL) + path = strchr (path, ':') + 1; + if (strchr (path, ':') != NULL) + { + r->_errno = EINVAL; + return -1; + } + + _FAT_lock(&partition->lock); + + /* Search for the file on the disc */ + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) + { + _FAT_unlock(&partition->lock); + r->_errno = ENOENT; + return -1; + } + + cluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); + + /* If this is a directory, make sure it is empty */ + if (_FAT_directory_isDirectory (&dirEntry)) + { + nextEntry = _FAT_directory_getFirstEntry (partition, &dirContents, cluster); + + while (nextEntry) + { + if (!_FAT_directory_isDot (&dirContents)) + { + /* The directory had something in it that isn't a reference to itself or it's parent */ + _FAT_unlock(&partition->lock); + r->_errno = ENOTEMPTY; + return -1; + } + nextEntry = _FAT_directory_getNextEntry (partition, &dirContents); + } + } + + if (_FAT_fat_isValidCluster(partition, cluster)) + { + /* Remove the cluster chain for this file */ + if (!_FAT_fat_clearLinks (partition, cluster)) + { + r->_errno = EIO; + errorOccured = true; + } + } + + /* Remove the directory entry for this file */ + if (!_FAT_directory_removeEntry (partition, &dirEntry)) + { + r->_errno = EIO; + errorOccured = true; + } + + /* Flush any sectors in the disc cache */ + if (!_FAT_cache_flush(partition->cache)) + { + r->_errno = EIO; + errorOccured = true; + } + + _FAT_unlock(&partition->lock); + if (errorOccured) + return -1; + return 0; +} + +int _FAT_chdir_r (struct _reent *r, const char *path) +{ + PARTITION* partition = NULL; + + /* Get the partition this directory is on */ + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) + { + r->_errno = ENODEV; + return -1; + } + + /* Move the path pointer to the start of the actual path */ + if (strchr (path, ':') != NULL) + path = strchr (path, ':') + 1; + if (strchr (path, ':') != NULL) + { + r->_errno = EINVAL; + return -1; + } + + _FAT_lock(&partition->lock); + + /* Try changing directory */ + if (_FAT_directory_chdir (partition, path)) + { + /* Successful */ + _FAT_unlock(&partition->lock); + return 0; + } + + /* Failed */ + _FAT_unlock(&partition->lock); + r->_errno = ENOTDIR; + return -1; +} + +int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) +{ + DIR_ENTRY oldDirEntry; + DIR_ENTRY newDirEntry; + const char *pathEnd; + uint32_t dirCluster; + + /* Get the partition this directory is on */ + PARTITION *partition = _FAT_partition_getPartitionFromPath (oldName); + if (partition == NULL) + { + r->_errno = ENODEV; + return -1; + } + + _FAT_lock(&partition->lock); + + /* Make sure the same partition is used for the old and new names */ + if (partition != _FAT_partition_getPartitionFromPath (newName)) + { + _FAT_unlock(&partition->lock); + r->_errno = EXDEV; + return -1; + } + + /* Make sure we aren't trying to write to a read-only disc */ + if (partition->readOnly) + { + _FAT_unlock(&partition->lock); + r->_errno = EROFS; + return -1; + } + + /* Move the path pointer to the start of the actual path */ + if (strchr (oldName, ':') != NULL) + oldName = strchr (oldName, ':') + 1; + if (strchr (oldName, ':') != NULL) + { + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + if (strchr (newName, ':') != NULL) + newName = strchr (newName, ':') + 1; + if (strchr (newName, ':') != NULL) + { + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + + /* Search for the file on the disc */ + if (!_FAT_directory_entryFromPath (partition, &oldDirEntry, oldName, NULL)) + { + _FAT_unlock(&partition->lock); + r->_errno = ENOENT; + return -1; + } + + /* Make sure there is no existing file / directory with the new name */ + if (_FAT_directory_entryFromPath (partition, &newDirEntry, newName, NULL)) + { + _FAT_unlock(&partition->lock); + r->_errno = EEXIST; + return -1; + } + + /* Create the new file entry + * Get the directory it has to go in */ + pathEnd = strrchr (newName, DIR_SEPARATOR); + if (pathEnd == NULL) + { + /* No path was specified */ + dirCluster = partition->cwdCluster; + pathEnd = newName; + } + else + { + /* Path was specified -- get the right dirCluster + * Recycling newDirEntry, since it needs to be recreated anyway */ + if (!_FAT_directory_entryFromPath (partition, &newDirEntry, newName, pathEnd) || + !_FAT_directory_isDirectory(&newDirEntry)) + { + _FAT_unlock(&partition->lock); + r->_errno = ENOTDIR; + return -1; + } + dirCluster = _FAT_directory_entryGetCluster (partition, newDirEntry.entryData); + /* Move the pathEnd past the last DIR_SEPARATOR */ + pathEnd += 1; + } + + /* Copy the entry data */ + memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY)); + + /* Set the new name */ + strncpy (newDirEntry.filename, pathEnd, NAME_MAX - 1); + + /* Write the new entry */ + if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) + { + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + + /* Remove the old entry */ + if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) + { + _FAT_unlock(&partition->lock); + r->_errno = EIO; + return -1; + } + + /* Flush any sectors in the disc cache */ + if (!_FAT_cache_flush (partition->cache)) + { + _FAT_unlock(&partition->lock); + r->_errno = EIO; + return -1; + } + + _FAT_unlock(&partition->lock); + return 0; +} + +int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) +{ + PARTITION* partition = NULL; + bool fileExists; + DIR_ENTRY dirEntry; + const char* pathEnd; + uint32_t parentCluster, dirCluster; + uint8_t newEntryData[DIR_ENTRY_DATA_SIZE]; + + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) + { + r->_errno = ENODEV; + return -1; + } + + /* Move the path pointer to the start of the actual path */ + if (strchr (path, ':') != NULL) + path = strchr (path, ':') + 1; + if (strchr (path, ':') != NULL) + { + r->_errno = EINVAL; + return -1; + } + + _FAT_lock(&partition->lock); + + /* Search for the file/directory on the disc */ + fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); + + /* Make sure it doesn't exist */ + if (fileExists) + { + _FAT_unlock(&partition->lock); + r->_errno = EEXIST; + return -1; + } + + if (partition->readOnly) + { + /* We can't write to a read-only partition */ + _FAT_unlock(&partition->lock); + r->_errno = EROFS; + return -1; + } + + /* Get the directory it has to go in */ + pathEnd = strrchr (path, DIR_SEPARATOR); + if (pathEnd == NULL) + { + /* No path was specified */ + parentCluster = partition->cwdCluster; + pathEnd = path; + } + else + { + /* Path was specified -- get the right parentCluster + * Recycling dirEntry, since it needs to be recreated anyway */ + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) || + !_FAT_directory_isDirectory(&dirEntry)) + { + _FAT_unlock(&partition->lock); + r->_errno = ENOTDIR; + return -1; + } + parentCluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); + /* Move the pathEnd past the last DIR_SEPARATOR */ + pathEnd += 1; + } + /* Create the entry data */ + strncpy (dirEntry.filename, pathEnd, NAME_MAX - 1); + memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); + + /* Set the creation time and date */ + dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0; + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_mTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_mDate, _FAT_filetime_getDateFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_aDate, _FAT_filetime_getDateFromRTC()); + + /* Set the directory attribute */ + dirEntry.entryData[DIR_ENTRY_attributes] = ATTRIB_DIR; + + /* Get a cluster for the new directory */ + dirCluster = _FAT_fat_linkFreeClusterCleared (partition, CLUSTER_FREE); + if (!_FAT_fat_isValidCluster(partition, dirCluster)) + { + /* No space left on disc for the cluster */ + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cluster, dirCluster); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_clusterHigh, dirCluster >> 16); + + /* Write the new directory's entry to it's parent */ + if (!_FAT_directory_addEntry (partition, &dirEntry, parentCluster)) + { + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + + /* Create the dot entry within the directory */ + memset (newEntryData, 0, DIR_ENTRY_DATA_SIZE); + memset (newEntryData, ' ', 11); + newEntryData[DIR_ENTRY_name] = '.'; + newEntryData[DIR_ENTRY_attributes] = ATTRIB_DIR; + u16_to_u8array (newEntryData, DIR_ENTRY_cluster, dirCluster); + u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, dirCluster >> 16); + + /* Write it to the directory, erasing that sector in the process */ + _FAT_cache_eraseWritePartialSector ( partition->cache, newEntryData, + _FAT_fat_clusterToSector (partition, dirCluster), 0, DIR_ENTRY_DATA_SIZE); + + + /* Create the double dot entry within the directory */ + + /* if ParentDir == Rootdir then ".."" always link to Cluster 0 */ + if(parentCluster == partition->rootDirCluster) + parentCluster = FAT16_ROOT_DIR_CLUSTER; + + newEntryData[DIR_ENTRY_name + 1] = '.'; + u16_to_u8array (newEntryData, DIR_ENTRY_cluster, parentCluster); + u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, parentCluster >> 16); + + /* Write it to the directory */ + _FAT_cache_writePartialSector ( partition->cache, newEntryData, + _FAT_fat_clusterToSector (partition, dirCluster), DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + /* Flush any sectors in the disc cache */ + if (!_FAT_cache_flush(partition->cache)) + { + _FAT_unlock(&partition->lock); + r->_errno = EIO; + return -1; + } + + _FAT_unlock(&partition->lock); + return 0; +} + +int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) +{ + PARTITION* partition = NULL; + unsigned int freeClusterCount; + + /* Get the partition of the requested path */ + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) + { + r->_errno = ENODEV; + return -1; + } + + _FAT_lock(&partition->lock); + + if(memcmp(&buf->f_flag, "SCAN", 4) == 0) + { + /* Special command was given to sync the numberFreeCluster */ + _FAT_partition_createFSinfo(partition); + } + + if(partition->filesysType == FS_FAT32) + freeClusterCount = partition->fat.numberFreeCluster; + else + freeClusterCount = _FAT_fat_freeClusterCount (partition); + + /* FAT clusters = POSIX blocks */ + buf->f_bsize = partition->bytesPerCluster; /* File system block size. */ + buf->f_frsize = partition->bytesPerCluster; /* Fundamental file system block size. */ + + buf->f_blocks = partition->fat.lastCluster - CLUSTER_FIRST + 1; /* Total number of blocks on file system in units of f_frsize. */ + buf->f_bfree = freeClusterCount; /* Total number of free blocks. */ + buf->f_bavail = freeClusterCount; /* Number of free blocks available to non-privileged process. */ + + /* Treat requests for info on inodes as clusters */ + buf->f_files = partition->fat.lastCluster - CLUSTER_FIRST + 1; /* Total number of file serial numbers. */ + buf->f_ffree = freeClusterCount; /* Total number of free file serial numbers. */ + buf->f_favail = freeClusterCount; /* Number of file serial numbers available to non-privileged process. */ + + /* File system ID. 32bit ioType value */ + buf->f_fsid = _FAT_disc_hostType(partition->disc); + + /* Bit mask of f_flag values. */ + buf->f_flag = ST_NOSUID /* No support for ST_ISUID and ST_ISGID file mode bits */ + | (partition->readOnly ? ST_RDONLY /* Read only file system */ : 0 ) ; + /* Maximum filename length. */ + buf->f_namemax = NAME_MAX; + + _FAT_unlock(&partition->lock); + return 0; +} + +DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) +{ + DIR_ENTRY dirEntry; + DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + bool fileExists; + + state->partition = _FAT_partition_getPartitionFromPath (path); + if (state->partition == NULL) + { + r->_errno = ENODEV; + return NULL; + } + + /* Move the path pointer to the start of the actual path */ + if (strchr (path, ':') != NULL) + path = strchr (path, ':') + 1; + if (strchr (path, ':') != NULL) + { + r->_errno = EINVAL; + return NULL; + } + + _FAT_lock(&state->partition->lock); + + /* Get the start cluster of the directory */ + fileExists = _FAT_directory_entryFromPath (state->partition, &dirEntry, path, NULL); + + if (!fileExists) + { + _FAT_unlock(&state->partition->lock); + r->_errno = ENOENT; + return NULL; + } + + /* Make sure it is a directory */ + if (! _FAT_directory_isDirectory (&dirEntry)) + { + _FAT_unlock(&state->partition->lock); + r->_errno = ENOTDIR; + return NULL; + } + + /* Save the start cluster for use when resetting the directory data */ + state->startCluster = _FAT_directory_entryGetCluster (state->partition, dirEntry.entryData); + + /* Get the first entry for use with a call to dirnext */ + state->validEntry = + _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); + + /* We are now using this entry */ + state->inUse = true; + _FAT_unlock(&state->partition->lock); + return (DIR_ITER*) state; +} + +int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState) +{ + DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + + _FAT_lock(&state->partition->lock); + + /* Make sure we are still using this entry */ + if (!state->inUse) + { + _FAT_unlock(&state->partition->lock); + r->_errno = EBADF; + return -1; + } + + /* Get the first entry for use with a call to dirnext */ + state->validEntry = + _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); + + _FAT_unlock(&state->partition->lock); + return 0; +} + +int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat) +{ + DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + + _FAT_lock(&state->partition->lock); + + /* Make sure we are still using this entry */ + if (!state->inUse) + { + _FAT_unlock(&state->partition->lock); + r->_errno = EBADF; + return -1; + } + + /* Make sure there is another file to report on */ + if (! state->validEntry) + { + _FAT_unlock(&state->partition->lock); + return -1; + } + + /* Get the filename */ + strncpy (filename, state->currentEntry.filename, NAME_MAX); + /* Get the stats, if requested */ + if (filestat != NULL) + _FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat); + + /* Look for the next entry for use next time */ + state->validEntry = + _FAT_directory_getNextEntry (state->partition, &(state->currentEntry)); + + _FAT_unlock(&state->partition->lock); + return 0; +} + +int _FAT_dirclose_r (struct _reent *r, DIR_ITER *dirState) +{ + DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + + /* We are no longer using this entry */ + _FAT_lock(&state->partition->lock); + state->inUse = false; + _FAT_unlock(&state->partition->lock); + + return 0; +} diff --git a/deps/libfat/fatdir.h b/deps/libfat/fatdir.h new file mode 100644 index 0000000000..426dd30bcd --- /dev/null +++ b/deps/libfat/fatdir.h @@ -0,0 +1,73 @@ +/* + fatdir.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _FATDIR_H +#define _FATDIR_H + +#include +#include +#include +#include +#include "common.h" +#include "directory.h" + +typedef struct { + PARTITION* partition; + DIR_ENTRY currentEntry; + uint32_t startCluster; + bool inUse; + bool validEntry; +} DIR_STATE_STRUCT; + +extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); + +extern int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); + +extern int _FAT_unlink_r (struct _reent *r, const char *name); + +extern int _FAT_chdir_r (struct _reent *r, const char *name); + +extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); + +extern int _FAT_mkdir_r (struct _reent *r, const char *path, int mode); + +extern int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf); + +/* +Directory iterator functions +*/ +extern DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path); +extern int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState); +extern int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat); +extern int _FAT_dirclose_r (struct _reent *r, DIR_ITER *dirState); + + +#endif // _FATDIR_H diff --git a/deps/libfat/fatfile.c b/deps/libfat/fatfile.c new file mode 100644 index 0000000000..ce176dc3a5 --- /dev/null +++ b/deps/libfat/fatfile.c @@ -0,0 +1,1235 @@ +/* + fatfile.c + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2009-10-23 oggzee: fixes for cluster aligned file size (write, truncate, seek) +*/ + + +#include "fatfile.h" + +#include +#include +#include +#include +#include + +#include "cache.h" +#include "file_allocation_table.h" +#include "bit_ops.h" +#include "filetime.h" +#include "lock.h" + +bool _FAT_findEntry(const char *path, DIR_ENTRY *dirEntry) { + PARTITION *partition = _FAT_partition_getPartitionFromPath(path); + + /* Check Partition */ + if( !partition ) + return false; + + /* Move the path pointer to the start of the actual path */ + if (strchr (path, ':') != NULL) + path = strchr (path, ':') + 1; + if (strchr (path, ':') != NULL) + return false; + + /* Search for the file on the disc */ + return _FAT_directory_entryFromPath (partition, dirEntry, path, NULL); + +} + +int FAT_getAttr(const char *file) { + DIR_ENTRY dirEntry; + if (!_FAT_findEntry(file,&dirEntry)) return -1; + + return dirEntry.entryData[DIR_ENTRY_attributes]; +} + +int FAT_setAttr(const char *file, uint8_t attr) { + + /* Defines... */ + DIR_ENTRY_POSITION entryEnd; + PARTITION *partition = NULL; + DIR_ENTRY dirEntry; + + /* Get Partition */ + partition = _FAT_partition_getPartitionFromPath( file ); + + /* Check Partition */ + if( !partition ) + return -1; + + /* Move the path pointer to the start of the actual path */ + if (strchr (file, ':') != NULL) + file = strchr (file, ':') + 1; + if (strchr (file, ':') != NULL) + return -1; + + /* Get DIR_ENTRY */ + if( !_FAT_directory_entryFromPath (partition, &dirEntry, file, NULL) ) + return -1; + + /* Get Entry-End */ + entryEnd = dirEntry.dataEnd; + + /* Lock Partition */ + _FAT_lock(&partition->lock); + + + /* Write Data */ + _FAT_cache_writePartialSector ( + partition->cache /* Cache to write */ + , &attr /* Value to be written */ + , _FAT_fat_clusterToSector( partition , entryEnd.cluster ) + entryEnd.sector /* cluster */ + , entryEnd.offset * DIR_ENTRY_DATA_SIZE + DIR_ENTRY_attributes /* offset */ + , 1 /* Size in bytes */ + ); + + /* Flush any sectors in the disc cache */ + if ( !_FAT_cache_flush( partition->cache ) ) + { + _FAT_unlock(&partition->lock); /* Unlock Partition */ + return -1; + } + + /* Unlock Partition */ + _FAT_unlock(&partition->lock); + + return 0; +} + + +int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) { + PARTITION* partition = NULL; + bool fileExists; + DIR_ENTRY dirEntry; + const char* pathEnd; + uint32_t dirCluster; + FILE_STRUCT* file = (FILE_STRUCT*) fileStruct; + partition = _FAT_partition_getPartitionFromPath (path); + + if (partition == NULL) + { + r->_errno = ENODEV; + return -1; + } + + /* Move the path pointer to the start of the actual path */ + if (strchr (path, ':') != NULL) + path = strchr (path, ':') + 1; + + if (strchr (path, ':') != NULL) + { + r->_errno = EINVAL; + return -1; + } + + /* Determine which mode the file is openned for */ + if ((flags & 0x03) == O_RDONLY) + { + /* Open the file for read-only access */ + file->read = true; + file->write = false; + file->append = false; + } + else if ((flags & 0x03) == O_WRONLY) + { + /* Open file for write only access */ + file->read = false; + file->write = true; + file->append = false; + } + else if ((flags & 0x03) == O_RDWR) + { + /* Open file for read/write access */ + file->read = true; + file->write = true; + file->append = false; + } else { + r->_errno = EACCES; + return -1; + } + + /* Make sure we aren't trying to write to a read-only disc */ + if (file->write && partition->readOnly) + { + r->_errno = EROFS; + return -1; + } + + /* Search for the file on the disc */ + _FAT_lock(&partition->lock); + fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); + + /* The file shouldn't exist if we are trying to create it */ + if ((flags & O_CREAT) && (flags & O_EXCL) && fileExists) + { + _FAT_unlock(&partition->lock); + r->_errno = EEXIST; + return -1; + } + + /* It should not be a directory if we're opening a file, */ + if (fileExists && _FAT_directory_isDirectory(&dirEntry)) + { + _FAT_unlock(&partition->lock); + r->_errno = EISDIR; + return -1; + } + + /* We haven't modified the file yet */ + file->modified = false; + + /* If the file doesn't exist, create it if we're allowed to */ + if (!fileExists) + { + if (flags & O_CREAT) + { + if (partition->readOnly) + { + /* We can't write to a read-only partition */ + _FAT_unlock(&partition->lock); + r->_errno = EROFS; + return -1; + } + /* Create the file + * Get the directory it has to go in */ + pathEnd = strrchr (path, DIR_SEPARATOR); + if (pathEnd == NULL) + { + /* No path was specified */ + dirCluster = partition->cwdCluster; + pathEnd = path; + } + else + { + /* Path was specified -- get the right dirCluster + * Recycling dirEntry, since it needs to be recreated anyway */ + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) || + !_FAT_directory_isDirectory(&dirEntry)) + { + _FAT_unlock(&partition->lock); + r->_errno = ENOTDIR; + return -1; + } + dirCluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); + /* Move the pathEnd past the last DIR_SEPARATOR */ + pathEnd += 1; + } + /* Create the entry data */ + strncpy (dirEntry.filename, pathEnd, NAME_MAX - 1); + memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); + + /* Set the creation time and date */ + dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0; + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC()); + + if (!_FAT_directory_addEntry (partition, &dirEntry, dirCluster)) + { + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + + /* File entry is modified */ + file->modified = true; + } + else + { + /* file doesn't exist, and we aren't creating it */ + _FAT_unlock(&partition->lock); + r->_errno = ENOENT; + return -1; + } + } + + file->filesize = u8array_to_u32 (dirEntry.entryData, DIR_ENTRY_fileSize); + +#if 0 + /* Allow LARGEFILEs with undefined results + * Make sure that the file size can fit in the available space */ + if (!(flags & O_LARGEFILE) && (file->filesize >= (1<<31))) + { + r->_errno = EFBIG; + return -1; + } +#endif + + /* Make sure we aren't trying to write to a read-only file */ + if (file->write && !_FAT_directory_isWritable(&dirEntry)) { + _FAT_unlock(&partition->lock); + r->_errno = EROFS; + return -1; + } + + /* Associate this file with a particular partition */ + file->partition = partition; + + file->startCluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); + + /* Truncate the file if requested */ + if ((flags & O_TRUNC) && file->write && (file->startCluster != 0)) { + _FAT_fat_clearLinks (partition, file->startCluster); + file->startCluster = CLUSTER_FREE; + file->filesize = 0; + /* File is modified since we just cut it all off */ + file->modified = true; + } + + /* Remember the position of this file's directory entry */ + file->dirEntryStart = dirEntry.dataStart; /* Points to the start of the LFN entries of a file, or the alias for no LFN */ + file->dirEntryEnd = dirEntry.dataEnd; + + /* Reset read/write pointer */ + file->currentPosition = 0; + file->rwPosition.cluster = file->startCluster; + file->rwPosition.sector = 0; + file->rwPosition.byte = 0; + + if (flags & O_APPEND) + { + file->append = true; + + /* Set append pointer to the end of the file */ + file->appendPosition.cluster = _FAT_fat_lastCluster (partition, file->startCluster); + file->appendPosition.sector = (file->filesize % partition->bytesPerCluster) / partition->bytesPerSector; + file->appendPosition.byte = file->filesize % partition->bytesPerSector; + + /* Check if the end of the file is on the end of a cluster */ + if ( (file->filesize > 0) && ((file->filesize % partition->bytesPerCluster)==0) ){ + /* Set flag to allocate a new cluster */ + file->appendPosition.sector = partition->sectorsPerCluster; + file->appendPosition.byte = 0; + } + } else { + file->append = false; + /* Use something sane for the append pointer, so the whole file struct contains known values */ + file->appendPosition = file->rwPosition; + } + + file->inUse = true; + + /* Insert this file into the double-linked list of open files */ + partition->openFileCount += 1; + if (partition->firstOpenFile) { + file->nextOpenFile = partition->firstOpenFile; + partition->firstOpenFile->prevOpenFile = file; + } else { + file->nextOpenFile = NULL; + } + file->prevOpenFile = NULL; + partition->firstOpenFile = file; + + _FAT_unlock(&partition->lock); + + return (int) file; +} + +/* +Synchronizes the file data to disc. +Does no locking of its own -- lock the partition before calling. +Returns 0 on success, an error code on failure. +*/ +int _FAT_syncToDisc (FILE_STRUCT* file) { + uint8_t dirEntryData[DIR_ENTRY_DATA_SIZE]; + + if (!file || !file->inUse) { + return EBADF; + } + + if (file->write && file->modified) { + /* Load the old entry */ + _FAT_cache_readPartialSector (file->partition->cache, dirEntryData, + _FAT_fat_clusterToSector(file->partition, file->dirEntryEnd.cluster) + file->dirEntryEnd.sector, + file->dirEntryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + // Write new data to the directory entry + // File size + u32_to_u8array (dirEntryData, DIR_ENTRY_fileSize, file->filesize); + + // Start cluster + u16_to_u8array (dirEntryData, DIR_ENTRY_cluster, file->startCluster); + u16_to_u8array (dirEntryData, DIR_ENTRY_clusterHigh, file->startCluster >> 16); + + // Modification time and date + u16_to_u8array (dirEntryData, DIR_ENTRY_mTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntryData, DIR_ENTRY_mDate, _FAT_filetime_getDateFromRTC()); + + // Access date + u16_to_u8array (dirEntryData, DIR_ENTRY_aDate, _FAT_filetime_getDateFromRTC()); + + // Set archive attribute + dirEntryData[DIR_ENTRY_attributes] |= ATTRIB_ARCH; + + // Write the new entry + _FAT_cache_writePartialSector (file->partition->cache, dirEntryData, + _FAT_fat_clusterToSector(file->partition, file->dirEntryEnd.cluster) + file->dirEntryEnd.sector, + file->dirEntryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush(file->partition->cache)) { + return EIO; + } + } + + file->modified = false; + + return 0; +} + + +int _FAT_close_r (struct _reent *r, void *fd) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + int ret = 0; + + if (!file->inUse) { + r->_errno = EBADF; + return -1; + } + + _FAT_lock(&file->partition->lock); + + if (file->write) { + ret = _FAT_syncToDisc (file); + if (ret != 0) { + r->_errno = ret; + ret = -1; + } + } + + file->inUse = false; + + // Remove this file from the double-linked list of open files + file->partition->openFileCount -= 1; + if (file->nextOpenFile) { + file->nextOpenFile->prevOpenFile = file->prevOpenFile; + } + if (file->prevOpenFile) { + file->prevOpenFile->nextOpenFile = file->nextOpenFile; + } else { + file->partition->firstOpenFile = file->nextOpenFile; + } + + _FAT_unlock(&file->partition->lock); + + return ret; +} + +ssize_t _FAT_read_r (struct _reent *r, void *fd, char *ptr, size_t len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + CACHE* cache; + FILE_POSITION position; + uint32_t tempNextCluster; + unsigned int tempVar; + size_t remain; + bool flagNoError = true; + + // Short circuit cases where len is 0 (or less) + if (len <= 0) + return 0; + + /* Make sure we can actually read from the file */ + if ((file == NULL) || !file->inUse || !file->read) { + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + _FAT_lock(&partition->lock); + + /* Don't try to read if the read pointer is past the end of file */ + if (file->currentPosition >= file->filesize || file->startCluster == CLUSTER_FREE) + { + r->_errno = EOVERFLOW; + _FAT_unlock(&partition->lock); + return 0; + } + + // Don't read past end of file + if (len + file->currentPosition > file->filesize) { + r->_errno = EOVERFLOW; + len = file->filesize - file->currentPosition; + } + + remain = len; + position = file->rwPosition; + cache = file->partition->cache; + + // Align to sector + tempVar = partition->bytesPerSector - position.byte; + if (tempVar > remain) { + tempVar = remain; + } + + if ((tempVar < partition->bytesPerSector) && flagNoError) + { + _FAT_cache_readPartialSector ( cache, ptr, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, + position.byte, tempVar); + + remain -= tempVar; + ptr += tempVar; + + position.byte += tempVar; + if (position.byte >= partition->bytesPerSector) { + position.byte = 0; + position.sector++; + } + } + + /* align to cluster + * tempVar is number of sectors to read */ + if (remain > (partition->sectorsPerCluster - position.sector) * partition->bytesPerSector) { + tempVar = partition->sectorsPerCluster - position.sector; + } else { + tempVar = remain / partition->bytesPerSector; + } + + if ((tempVar > 0) && flagNoError) { + if (! _FAT_cache_readSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, + tempVar, ptr)) + { + flagNoError = false; + r->_errno = EIO; + } else { + ptr += tempVar * partition->bytesPerSector; + remain -= tempVar * partition->bytesPerSector; + position.sector += tempVar; + } + } + + /* Move onto next cluster + * It should get to here without reading anything if a cluster is due to be allocated */ + if ((position.sector >= partition->sectorsPerCluster) && flagNoError) { + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if ((remain == 0) && (tempNextCluster == CLUSTER_EOF)) { + position.sector = partition->sectorsPerCluster; + } else if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + r->_errno = EIO; + flagNoError = false; + } else { + position.sector = 0; + position.cluster = tempNextCluster; + } + } + + /* Read in whole clusters, contiguous blocks at a time */ + while ((remain >= partition->bytesPerCluster) && flagNoError) { + uint32_t chunkEnd; + uint32_t nextChunkStart = position.cluster; + size_t chunkSize = 0; + + do { + chunkEnd = nextChunkStart; + nextChunkStart = _FAT_fat_nextCluster (partition, chunkEnd); + chunkSize += partition->bytesPerCluster; + } while ((nextChunkStart == chunkEnd + 1) && +#ifdef LIMIT_SECTORS + (chunkSize + partition->bytesPerCluster <= LIMIT_SECTORS * partition->bytesPerSector) && +#endif + (chunkSize + partition->bytesPerCluster <= remain)); + + if (!_FAT_cache_readSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster), + chunkSize / partition->bytesPerSector, ptr)) + { + flagNoError = false; + r->_errno = EIO; + break; + } + ptr += chunkSize; + remain -= chunkSize; + + /* Advance to next cluster */ + if ((remain == 0) && (nextChunkStart == CLUSTER_EOF)) { + position.sector = partition->sectorsPerCluster; + position.cluster = chunkEnd; + } else if (!_FAT_fat_isValidCluster(partition, nextChunkStart)) { + r->_errno = EIO; + flagNoError = false; + } else { + position.sector = 0; + position.cluster = nextChunkStart; + } + } + + /* Read remaining sectors */ + tempVar = remain / partition->bytesPerSector; /* Number of sectors left */ + if ((tempVar > 0) && flagNoError) { + if (!_FAT_cache_readSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster), + tempVar, ptr)) + { + flagNoError = false; + r->_errno = EIO; + } else { + ptr += tempVar * partition->bytesPerSector; + remain -= tempVar * partition->bytesPerSector; + position.sector += tempVar; + } + } + + // Last remaining sector + // Check if anything is left + if ((remain > 0) && flagNoError) { + _FAT_cache_readPartialSector ( cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + position.byte += remain; + remain = 0; + } + + // Length read is the wanted length minus the stuff not read + len = len - remain; + + // Update file information + file->rwPosition = position; + file->currentPosition += len; + + _FAT_unlock(&partition->lock); + return len; +} + +// if current position is on the cluster border and more data has to be written +// then get next cluster or allocate next cluster +// this solves the over-allocation problems when file size is aligned to cluster size +// return true on succes, false on error +static bool _FAT_check_position_for_next_cluster(struct _reent *r, + FILE_POSITION *position, PARTITION* partition, size_t remain, bool *flagNoError) +{ + uint32_t tempNextCluster; + // do nothing if no more data to write + if (remain == 0) return true; + if (flagNoError && *flagNoError == false) return false; + if (position->sector > partition->sectorsPerCluster) { + // invalid arguments - internal error + r->_errno = EINVAL; + goto err; + } + if (position->sector == partition->sectorsPerCluster) { + // need to advance to next cluster + tempNextCluster = _FAT_fat_nextCluster(partition, position->cluster); + if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) { + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position->cluster); + } + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + goto err; + } + position->sector = 0; + position->cluster = tempNextCluster; + } + return true; +err: + if (flagNoError) *flagNoError = false; + return false; +} + +/* +Extend a file so that the size is the same as the rwPosition +*/ +static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) { + PARTITION* partition = file->partition; + CACHE* cache = file->partition->cache; + FILE_POSITION position; + uint8_t zeroBuffer [partition->bytesPerSector]; + memset(zeroBuffer, 0, partition->bytesPerSector); + uint32_t remain; + uint32_t tempNextCluster; + unsigned int sector; + + position.byte = file->filesize % partition->bytesPerSector; + position.sector = (file->filesize % partition->bytesPerCluster) / partition->bytesPerSector; + // It is assumed that there is always a startCluster + // This will be true when _FAT_file_extend_r is called from _FAT_write_r + position.cluster = _FAT_fat_lastCluster (partition, file->startCluster); + + remain = file->currentPosition - file->filesize; + + if ((remain > 0) && (file->filesize > 0) && (position.sector == 0) && (position.byte == 0)) { + // Get a new cluster on the edge of a cluster boundary + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + return false; + } + position.cluster = tempNextCluster; + position.sector = 0; + } + + if (remain + position.byte < partition->bytesPerSector) { + // Only need to clear to the end of the sector + _FAT_cache_writePartialSector (cache, zeroBuffer, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, remain); + position.byte += remain; + } else { + if (position.byte > 0) { + _FAT_cache_writePartialSector (cache, zeroBuffer, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, + partition->bytesPerSector - position.byte); + remain -= (partition->bytesPerSector - position.byte); + position.byte = 0; + position.sector ++; + } + + while (remain >= partition->bytesPerSector) { + if (position.sector >= partition->sectorsPerCluster) { + position.sector = 0; + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + return false; + } + position.cluster = tempNextCluster; + } + + sector = _FAT_fat_clusterToSector (partition, position.cluster) + position.sector; + _FAT_cache_writeSectors (cache, sector, 1, zeroBuffer); + + remain -= partition->bytesPerSector; + position.sector ++; + } + + // error already marked + if (!_FAT_check_position_for_next_cluster(r, &position, partition, remain, NULL)) + return false; + + if (remain > 0) + { + _FAT_cache_writePartialSector (cache, zeroBuffer, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + position.byte = remain; + } + } + + file->rwPosition = position; + file->filesize = file->currentPosition; + return true; +} + +ssize_t _FAT_write_r (struct _reent *r, void *fd, const char *ptr, size_t len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + CACHE* cache; + FILE_POSITION position; + uint32_t tempNextCluster; + unsigned int tempVar; + size_t remain; + bool flagNoError = true; + bool flagAppending = false; + + /* Make sure we can actually write to the file */ + if ((file == NULL) || !file->inUse || !file->write) { + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + cache = file->partition->cache; + _FAT_lock(&partition->lock); + + /* Only write up to the maximum file size, taking into account wrap-around of ints */ + if (len + file->filesize > FILE_MAX_SIZE || len + file->filesize < file->filesize) { + len = FILE_MAX_SIZE - file->filesize; + } + + /* Short circuit cases where len is 0 (or less) */ + if (len <= 0) { + _FAT_unlock(&partition->lock); + return 0; + } + + remain = len; + + /* Get a new cluster for the start of the file if required */ + if (file->startCluster == CLUSTER_FREE) { + tempNextCluster = _FAT_fat_linkFreeCluster (partition, CLUSTER_FREE); + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + /* Couldn't get a cluster, so abort immediately */ + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + file->startCluster = tempNextCluster; + + /* Appending starts at the begining for a 0 byte file */ + file->appendPosition.cluster = file->startCluster; + file->appendPosition.sector = 0; + file->appendPosition.byte = 0; + + file->rwPosition.cluster = file->startCluster; + file->rwPosition.sector = 0; + file->rwPosition.byte = 0; + } + + if (file->append) { + position = file->appendPosition; + flagAppending = true; + } else { + // If the write pointer is past the end of the file, extend the file to that size + if (file->currentPosition > file->filesize) { + if (!_FAT_file_extend_r (r, file)) { + _FAT_unlock(&partition->lock); + return -1; + } + } + + // Write at current read pointer + position = file->rwPosition; + + // If it is writing past the current end of file, set appending flag + if (len + file->currentPosition > file->filesize) { + flagAppending = true; + } + } + + // Move onto next cluster if needed + _FAT_check_position_for_next_cluster(r, &position, partition, remain, &flagNoError); + + // Align to sector + tempVar = partition->bytesPerSector - position.byte; + if (tempVar > remain) { + tempVar = remain; + } + + if ((tempVar < partition->bytesPerSector) && flagNoError) { + // Write partial sector to disk + _FAT_cache_writePartialSector (cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, tempVar); + + remain -= tempVar; + ptr += tempVar; + position.byte += tempVar; + + + // Move onto next sector + if (position.byte >= partition->bytesPerSector) { + position.byte = 0; + position.sector ++; + } + } + + // Align to cluster + // tempVar is number of sectors to write + if (remain > (partition->sectorsPerCluster - position.sector) * partition->bytesPerSector) { + tempVar = partition->sectorsPerCluster - position.sector; + } else { + tempVar = remain / partition->bytesPerSector; + } + + if ((tempVar > 0 && tempVar < partition->sectorsPerCluster) && flagNoError) { + if (!_FAT_cache_writeSectors (cache, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, tempVar, ptr)) + { + flagNoError = false; + r->_errno = EIO; + } else { + ptr += tempVar * partition->bytesPerSector; + remain -= tempVar * partition->bytesPerSector; + position.sector += tempVar; + } + } + + // Write whole clusters + while ((remain >= partition->bytesPerCluster) && flagNoError) { + // allocate next cluster + _FAT_check_position_for_next_cluster(r, &position, partition, remain, &flagNoError); + if (!flagNoError) break; + // set indexes to the current position + uint32_t chunkEnd = position.cluster; + uint32_t nextChunkStart = position.cluster; + size_t chunkSize = partition->bytesPerCluster; + FILE_POSITION next_position = position; + + // group consecutive clusters + while (flagNoError && +#ifdef LIMIT_SECTORS + (chunkSize + partition->bytesPerCluster <= LIMIT_SECTORS * partition->bytesPerSector) && +#endif + (chunkSize + partition->bytesPerCluster < remain)) + { + // pretend to use up all sectors in next_position + next_position.sector = partition->sectorsPerCluster; + // get or allocate next cluster + _FAT_check_position_for_next_cluster(r, &next_position, partition, + remain - chunkSize, &flagNoError); + if (!flagNoError) break; // exit loop on error + nextChunkStart = next_position.cluster; + if (nextChunkStart != chunkEnd + 1) break; // exit loop if not consecutive + chunkEnd = nextChunkStart; + chunkSize += partition->bytesPerCluster; + } + + if ( !_FAT_cache_writeSectors (cache, + _FAT_fat_clusterToSector(partition, position.cluster), chunkSize / partition->bytesPerSector, ptr)) + { + flagNoError = false; + r->_errno = EIO; + break; + } + ptr += chunkSize; + remain -= chunkSize; + + if ((chunkEnd != nextChunkStart) && _FAT_fat_isValidCluster(partition, nextChunkStart)) { + // new cluster is already allocated (because it was not consecutive) + position.cluster = nextChunkStart; + position.sector = 0; + } else { + // Allocate a new cluster when next writing the file + position.cluster = chunkEnd; + position.sector = partition->sectorsPerCluster; + } + } + + // allocate next cluster if needed + _FAT_check_position_for_next_cluster(r, &position, partition, remain, &flagNoError); + + // Write remaining sectors + tempVar = remain / partition->bytesPerSector; // Number of sectors left + if ((tempVar > 0) && flagNoError) { + if (!_FAT_cache_writeSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster), tempVar, ptr)) + { + flagNoError = false; + r->_errno = EIO; + } else { + ptr += tempVar * partition->bytesPerSector; + remain -= tempVar * partition->bytesPerSector; + position.sector += tempVar; + } + } + + // Last remaining sector + if ((remain > 0) && flagNoError) { + if (flagAppending) { + _FAT_cache_eraseWritePartialSector ( cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + } else { + _FAT_cache_writePartialSector ( cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + } + position.byte += remain; + remain = 0; + } + + + // Amount written is the originally requested amount minus stuff remaining + len = len - remain; + + // Update file information + file->modified = true; + if (file->append) { + // Appending doesn't affect the read pointer + file->appendPosition = position; + file->filesize += len; + } else { + // Writing also shifts the read pointer + file->rwPosition = position; + file->currentPosition += len; + if (file->filesize < file->currentPosition) { + file->filesize = file->currentPosition; + } + } + _FAT_unlock(&partition->lock); + + return len; +} + + +off_t _FAT_seek_r (struct _reent *r, void *fd, off_t pos, int dir) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + uint32_t cluster, nextCluster; + int clusCount; + off_t newPosition; + uint32_t position; + + if ((file == NULL) || (file->inUse == false)) { + // invalid file + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + _FAT_lock(&partition->lock); + + switch (dir) { + case SEEK_SET: + newPosition = pos; + break; + case SEEK_CUR: + newPosition = (off_t)file->currentPosition + pos; + break; + case SEEK_END: + newPosition = (off_t)file->filesize + pos; + break; + default: + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + + if ((pos > 0) && (newPosition < 0)) { + _FAT_unlock(&partition->lock); + r->_errno = EOVERFLOW; + return -1; + } + + // newPosition can only be larger than the FILE_MAX_SIZE on platforms where + // off_t is larger than 32 bits. + if (newPosition < 0 || ((sizeof(newPosition) > 4) && newPosition > (off_t)FILE_MAX_SIZE)) { + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + + position = (uint32_t)newPosition; + + // Only change the read/write position if it is within the bounds of the current filesize, + // or at the very edge of the file + if (position <= file->filesize && file->startCluster != CLUSTER_FREE) { + // Calculate where the correct cluster is + // how many clusters from start of file + clusCount = position / partition->bytesPerCluster; + cluster = file->startCluster; + if (position >= file->currentPosition) { + // start from current cluster + int currentCount = file->currentPosition / partition->bytesPerCluster; + if (file->rwPosition.sector == partition->sectorsPerCluster) { + currentCount--; + } + clusCount -= currentCount; + cluster = file->rwPosition.cluster; + } + // Calculate the sector and byte of the current position, + // and store them + file->rwPosition.sector = (position % partition->bytesPerCluster) / partition->bytesPerSector; + file->rwPosition.byte = position % partition->bytesPerSector; + + nextCluster = _FAT_fat_nextCluster (partition, cluster); + while ((clusCount > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) { + clusCount--; + cluster = nextCluster; + nextCluster = _FAT_fat_nextCluster (partition, cluster); + } + + // Check if ran out of clusters and it needs to allocate a new one + if (clusCount > 0) { + if ((clusCount == 1) && (file->filesize == position) && (file->rwPosition.sector == 0)) { + // Set flag to allocate a new cluster + file->rwPosition.sector = partition->sectorsPerCluster; + file->rwPosition.byte = 0; + } else { + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + } + + file->rwPosition.cluster = cluster; + } + + // Save position + file->currentPosition = position; + + _FAT_unlock(&partition->lock); + return position; +} + + + +int _FAT_fstat_r (struct _reent *r, void *fd, struct stat *st) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + DIR_ENTRY fileEntry; + + if ((file == NULL) || (file->inUse == false)) { + // invalid file + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + _FAT_lock(&partition->lock); + + // Get the file's entry data + fileEntry.dataStart = file->dirEntryStart; + fileEntry.dataEnd = file->dirEntryEnd; + + if (!_FAT_directory_entryFromPosition (partition, &fileEntry)) { + _FAT_unlock(&partition->lock); + r->_errno = EIO; + return -1; + } + + // Fill in the stat struct + _FAT_directory_entryStat (partition, &fileEntry, st); + + // Fix stats that have changed since the file was openned + st->st_ino = (ino_t)(file->startCluster); // The file serial number is the start cluster + st->st_size = file->filesize; // File size + + _FAT_unlock(&partition->lock); + return 0; +} + +int _FAT_ftruncate_r (struct _reent *r, void *fd, off_t len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + int ret=0; + uint32_t newSize = (uint32_t)len; + + if (len < 0) { + // Trying to truncate to a negative size + r->_errno = EINVAL; + return -1; + } + + if ((sizeof(len) > 4) && len > (off_t)FILE_MAX_SIZE) { + // Trying to extend the file beyond what FAT supports + r->_errno = EFBIG; + return -1; + } + + if (!file || !file->inUse) { + // invalid file + r->_errno = EBADF; + return -1; + } + + if (!file->write) { + // Read-only file + r->_errno = EINVAL; + return -1; + } + + partition = file->partition; + _FAT_lock(&partition->lock); + + if (newSize > file->filesize) { + // Expanding the file + FILE_POSITION savedPosition; + uint32_t savedOffset; + // Get a new cluster for the start of the file if required + if (file->startCluster == CLUSTER_FREE) { + uint32_t tempNextCluster = _FAT_fat_linkFreeCluster (partition, CLUSTER_FREE); + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort immediately + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + file->startCluster = tempNextCluster; + + file->rwPosition.cluster = file->startCluster; + file->rwPosition.sector = 0; + file->rwPosition.byte = 0; + } + // Save the read/write pointer + savedPosition = file->rwPosition; + savedOffset = file->currentPosition; + // Set the position to the new size + file->currentPosition = newSize; + // Extend the file to the new position + if (!_FAT_file_extend_r (r, file)) { + ret = -1; + } + // Set the append position to the new rwPointer + if (file->append) { + file->appendPosition = file->rwPosition; + } + // Restore the old rwPointer; + file->rwPosition = savedPosition; + file->currentPosition = savedOffset; + } else if (newSize < file->filesize){ + // Shrinking the file + if (len == 0) { + // Cutting the file down to nothing, clear all clusters used + _FAT_fat_clearLinks (partition, file->startCluster); + file->startCluster = CLUSTER_FREE; + + file->appendPosition.cluster = CLUSTER_FREE; + file->appendPosition.sector = 0; + file->appendPosition.byte = 0; + } else { + // Trimming the file down to the required size + unsigned int chainLength; + uint32_t lastCluster; + + // Drop the unneeded end of the cluster chain. + // If the end falls on a cluster boundary, drop that cluster too, + // then set a flag to allocate a cluster as needed + chainLength = ((newSize-1) / partition->bytesPerCluster) + 1; + lastCluster = _FAT_fat_trimChain (partition, file->startCluster, chainLength); + + if (file->append) { + file->appendPosition.byte = newSize % partition->bytesPerSector; + // Does the end of the file fall on the edge of a cluster? + if (newSize % partition->bytesPerCluster == 0) { + // Set a flag to allocate a new cluster + file->appendPosition.sector = partition->sectorsPerCluster; + } else { + file->appendPosition.sector = (newSize % partition->bytesPerCluster) / partition->bytesPerSector; + } + file->appendPosition.cluster = lastCluster; + } + } + } else { + // Truncating to same length, so don't do anything + } + + file->filesize = newSize; + file->modified = true; + + _FAT_unlock(&partition->lock); + return ret; +} + +int _FAT_fsync_r (struct _reent *r, void *fd) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + int ret = 0; + + if (!file->inUse) { + r->_errno = EBADF; + return -1; + } + + _FAT_lock(&file->partition->lock); + + ret = _FAT_syncToDisc (file); + if (ret != 0) { + r->_errno = ret; + ret = -1; + } + + _FAT_unlock(&file->partition->lock); + + return ret; +} diff --git a/deps/libfat/fatfile.h b/deps/libfat/fatfile.h new file mode 100644 index 0000000000..984c3d01c5 --- /dev/null +++ b/deps/libfat/fatfile.h @@ -0,0 +1,105 @@ +/* + fatfile.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _FATFILE_H +#define _FATFILE_H + +#include +#include + +#include "common.h" +#include "partition.h" +#include "directory.h" + +#define FILE_MAX_SIZE ((uint32_t)0xFFFFFFFF) /* 4GiB - 1B */ + +typedef struct { + u32 cluster; + sec_t sector; + s32 byte; +} FILE_POSITION; + +struct _FILE_STRUCT; + +struct _FILE_STRUCT { + uint32_t filesize; + uint32_t startCluster; + uint32_t currentPosition; + FILE_POSITION rwPosition; + FILE_POSITION appendPosition; + DIR_ENTRY_POSITION dirEntryStart; /* Points to the start of the LFN entries of a file, or the alias for no LFN */ + DIR_ENTRY_POSITION dirEntryEnd; /* Always points to the file's alias entry */ + PARTITION* partition; + struct _FILE_STRUCT* prevOpenFile; /* The previous entry in a double-linked list of open files */ + struct _FILE_STRUCT* nextOpenFile; /* The next entry in a double-linked list of open files */ + bool read; + bool write; + bool append; + bool inUse; + bool modified; +}; + +typedef struct _FILE_STRUCT FILE_STRUCT; + +int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode); + +int _FAT_close_r (struct _reent *r, void *fd); + +ssize_t _FAT_write_r (struct _reent *r,void *fd, const char *ptr, size_t len); + +ssize_t _FAT_read_r (struct _reent *r, void *fd, char *ptr, size_t len); + +off_t _FAT_seek_r (struct _reent *r, void *fd, off_t pos, int dir); + +int _FAT_fstat_r (struct _reent *r, void *fd, struct stat *st); + +int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); + +int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); + +int _FAT_unlink_r (struct _reent *r, const char *name); + +int _FAT_chdir_r (struct _reent *r, const char *name); + +int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); + +int _FAT_ftruncate_r (struct _reent *r, void *fd, off_t len); + +int _FAT_fsync_r (struct _reent *r, void *fd); + +/* +Synchronizes the file data to disc. +Does no locking of its own -- lock the partition before calling. +Returns 0 on success, an error code on failure. +*/ +extern int _FAT_syncToDisc (FILE_STRUCT* file); + +#endif /* _FATFILE_H */ diff --git a/deps/libfat/file_allocation_table.c b/deps/libfat/file_allocation_table.c new file mode 100644 index 0000000000..959cbdf481 --- /dev/null +++ b/deps/libfat/file_allocation_table.c @@ -0,0 +1,395 @@ +/* + file_allocation_table.c + Reading, writing and manipulation of the FAT structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "file_allocation_table.h" +#include "partition.h" +#include "mem_allocate.h" +#include + +/* +Gets the cluster linked from input cluster +*/ +uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster) +{ + uint32_t nextCluster = CLUSTER_FREE; + sec_t sector; + int offset; + + if (cluster == CLUSTER_FREE) + return CLUSTER_FREE; + + switch (partition->filesysType) + { + case FS_UNKNOWN: + return CLUSTER_ERROR; + break; + + case FS_FAT12: + { + u32 nextCluster_h; + sector = partition->fat.fatStart + (((cluster * 3) / 2) / partition->bytesPerSector); + offset = ((cluster * 3) / 2) % partition->bytesPerSector; + + + _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u8)); + + offset++; + + if (offset >= partition->bytesPerSector) + { + offset = 0; + sector++; + } + nextCluster_h = 0; + + _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster_h, sector, offset, sizeof(u8)); + nextCluster |= (nextCluster_h << 8); + + if (cluster & 0x01) + nextCluster = nextCluster >> 4; + else + nextCluster &= 0x0FFF; + + if (nextCluster >= 0x0FF7) + nextCluster = CLUSTER_EOF; + + break; + } + case FS_FAT16: + sector = partition->fat.fatStart + ((cluster << 1) / partition->bytesPerSector); + offset = (cluster % (partition->bytesPerSector >> 1)) << 1; + + _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u16)); + + if (nextCluster >= 0xFFF7) + nextCluster = CLUSTER_EOF; + break; + + case FS_FAT32: + sector = partition->fat.fatStart + ((cluster << 2) / partition->bytesPerSector); + offset = (cluster % (partition->bytesPerSector >> 2)) << 2; + + _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u32)); + + if (nextCluster >= 0x0FFFFFF7) + nextCluster = CLUSTER_EOF; + break; + + default: + return CLUSTER_ERROR; + break; + } + + return nextCluster; +} + +/* +writes value into the correct offset within a partition's FAT, based +on the cluster number. +*/ +static bool _FAT_fat_writeFatEntry (PARTITION* partition, uint32_t cluster, uint32_t value) +{ + sec_t sector; + int offset; + uint32_t oldValue; + + if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) + { + return false; + } + + switch (partition->filesysType) + { + case FS_UNKNOWN: + return false; + break; + + case FS_FAT12: + sector = partition->fat.fatStart + (((cluster * 3) / 2) / partition->bytesPerSector); + offset = ((cluster * 3) / 2) % partition->bytesPerSector; + + if (cluster & 0x01) + { + + _FAT_cache_readLittleEndianValue (partition->cache, &oldValue, sector, offset, sizeof(u8)); + + value = (value << 4) | (oldValue & 0x0F); + + _FAT_cache_writeLittleEndianValue (partition->cache, value & 0xFF, sector, offset, sizeof(u8)); + + offset++; + if (offset >= partition->bytesPerSector) + { + offset = 0; + sector++; + } + + _FAT_cache_writeLittleEndianValue (partition->cache, (value >> 8) & 0xFF, sector, offset, sizeof(u8)); + + } else { + + _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u8)); + + offset++; + if (offset >= partition->bytesPerSector) + { + offset = 0; + sector++; + } + + _FAT_cache_readLittleEndianValue (partition->cache, &oldValue, sector, offset, sizeof(u8)); + + value = ((value >> 8) & 0x0F) | (oldValue & 0xF0); + + _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u8)); + } + + break; + + case FS_FAT16: + sector = partition->fat.fatStart + ((cluster << 1) / partition->bytesPerSector); + offset = (cluster % (partition->bytesPerSector >> 1)) << 1; + + _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u16)); + + break; + + case FS_FAT32: + sector = partition->fat.fatStart + ((cluster << 2) / partition->bytesPerSector); + offset = (cluster % (partition->bytesPerSector >> 2)) << 2; + + _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u32)); + + break; + + default: + return false; + break; + } + + return true; +} + +/*----------------------------------------------------------------- +gets the first available free cluster, sets it +to end of file, links the input cluster to it then returns the +cluster number +If an error occurs, return CLUSTER_ERROR +-----------------------------------------------------------------*/ +uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster) +{ + uint32_t firstFree; + uint32_t curLink; + uint32_t lastCluster; + bool loopedAroundFAT = false; + + lastCluster = partition->fat.lastCluster; + + if (cluster > lastCluster) + return CLUSTER_ERROR; + + /* Check if the cluster already has a link, and return it if so */ + curLink = _FAT_fat_nextCluster(partition, cluster); + if ((curLink >= CLUSTER_FIRST) && (curLink <= lastCluster)) + return curLink; /* Return the current link - don't allocate a new one */ + + /* Get a free cluster */ + firstFree = partition->fat.firstFree; + /* Start at first valid cluster */ + if (firstFree < CLUSTER_FIRST) + firstFree = CLUSTER_FIRST; + + /* Search until a free cluster is found */ + while (_FAT_fat_nextCluster(partition, firstFree) != CLUSTER_FREE) + { + firstFree++; + if (firstFree > lastCluster) + { + if (loopedAroundFAT) + { + /* If couldn't get a free cluster then return an error */ + partition->fat.firstFree = firstFree; + return CLUSTER_ERROR; + } + + /* Try looping back to the beginning of the FAT + * This was suggested by loopy */ + firstFree = CLUSTER_FIRST; + loopedAroundFAT = true; + } + } + partition->fat.firstFree = firstFree; + if(partition->fat.numberFreeCluster) + partition->fat.numberFreeCluster--; + partition->fat.numberLastAllocCluster = firstFree; + + /* Update the linked from FAT entry */ + if ((cluster >= CLUSTER_FIRST) && (cluster <= lastCluster)) + _FAT_fat_writeFatEntry (partition, cluster, firstFree); + /* Create the linked to FAT entry */ + _FAT_fat_writeFatEntry (partition, firstFree, CLUSTER_EOF); + + return firstFree; +} + +/*----------------------------------------------------------------- +gets the first available free cluster, sets it +to end of file, links the input cluster to it, clears the new +cluster to 0 valued bytes, then returns the cluster number +If an error occurs, return CLUSTER_ERROR +-----------------------------------------------------------------*/ +uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster) +{ + uint32_t i; + uint8_t *emptySector; + + /* Link the cluster */ + uint32_t newCluster = _FAT_fat_linkFreeCluster(partition, cluster); + + if (newCluster == CLUSTER_FREE || newCluster == CLUSTER_ERROR) + return CLUSTER_ERROR; + + emptySector = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector); + + /* Clear all the sectors within the cluster */ + memset (emptySector, 0, partition->bytesPerSector); + for (i = 0; i < partition->sectorsPerCluster; i++) + { + _FAT_cache_writeSectors (partition->cache, + _FAT_fat_clusterToSector (partition, newCluster) + i, + 1, emptySector); + } + + _FAT_mem_free(emptySector); + + return newCluster; +} + + +/*----------------------------------------------------------------- +_FAT_fat_clearLinks +frees any cluster used by a file +-----------------------------------------------------------------*/ +bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster) +{ + uint32_t nextCluster; + + if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) + return false; + + /* If this clears up more space in the FAT before the current free pointer, move it backwards */ + if (cluster < partition->fat.firstFree) + partition->fat.firstFree = cluster; + + while ((cluster != CLUSTER_EOF) && (cluster != CLUSTER_FREE) && (cluster != CLUSTER_ERROR)) + { + /* Store next cluster before erasing the link */ + nextCluster = _FAT_fat_nextCluster (partition, cluster); + + /* Erase the link */ + _FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE); + + if(partition->fat.numberFreeCluster < (partition->numberOfSectors/partition->sectorsPerCluster)) + partition->fat.numberFreeCluster++; + /* Move onto next cluster */ + cluster = nextCluster; + } + + return true; +} + +/*----------------------------------------------------------------- +_FAT_fat_trimChain +Drop all clusters past the chainLength. +If chainLength is 0, all clusters are dropped. +If chainLength is 1, the first cluster is kept and the rest are +dropped, and so on. +Return the last cluster left in the chain. +-----------------------------------------------------------------*/ +uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength) +{ + uint32_t nextCluster; + + if (chainLength == 0) + { + /* Drop the entire chain */ + _FAT_fat_clearLinks (partition, startCluster); + return CLUSTER_FREE; + } + + /* Find the last cluster in the chain, and the one after it */ + chainLength--; + nextCluster = _FAT_fat_nextCluster (partition, startCluster); + while ((chainLength > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) + { + chainLength--; + startCluster = nextCluster; + nextCluster = _FAT_fat_nextCluster (partition, startCluster); + } + + /* Drop all clusters after the last in the chain */ + if (nextCluster != CLUSTER_FREE && nextCluster != CLUSTER_EOF) + _FAT_fat_clearLinks (partition, nextCluster); + + /* Mark the last cluster in the chain as the end of the file */ + _FAT_fat_writeFatEntry (partition, startCluster, CLUSTER_EOF); + + return startCluster; +} + +/*----------------------------------------------------------------- +_FAT_fat_lastCluster +Trace the cluster links until the last one is found +-----------------------------------------------------------------*/ +uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster) +{ + while ((_FAT_fat_nextCluster(partition, cluster) != CLUSTER_FREE) && (_FAT_fat_nextCluster(partition, cluster) != CLUSTER_EOF)) + cluster = _FAT_fat_nextCluster(partition, cluster); + return cluster; +} + +/*----------------------------------------------------------------- +_FAT_fat_freeClusterCount +Return the number of free clusters available +-----------------------------------------------------------------*/ +unsigned int _FAT_fat_freeClusterCount (PARTITION* partition) +{ + unsigned int count = 0; + uint32_t curCluster; + + for (curCluster = CLUSTER_FIRST; curCluster <= partition->fat.lastCluster; curCluster++) + { + if (_FAT_fat_nextCluster(partition, curCluster) == CLUSTER_FREE) + count++; + } + + return count; +} + diff --git a/deps/libfat/file_allocation_table.h b/deps/libfat/file_allocation_table.h new file mode 100644 index 0000000000..e420dfeadf --- /dev/null +++ b/deps/libfat/file_allocation_table.h @@ -0,0 +1,70 @@ +/* + file_allocation_table.h + Reading, writing and manipulation of the FAT structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FAT_H +#define _FAT_H + +#include "common.h" +#include "partition.h" + +#define CLUSTER_EOF_16 0xFFFF +#define CLUSTER_EOF 0x0FFFFFFF +#define CLUSTER_FREE 0x00000000 +#define CLUSTER_ROOT 0x00000000 +#define CLUSTER_FIRST 0x00000002 +#define CLUSTER_ERROR 0xFFFFFFFF + +#define CLUSTERS_PER_FAT12 4085 +#define CLUSTERS_PER_FAT16 65525 + + +uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster); + +uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster); +uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster); + +bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster); + +uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength); + +uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster); + +unsigned int _FAT_fat_freeClusterCount (PARTITION* partition); + +static inline sec_t _FAT_fat_clusterToSector (PARTITION* partition, uint32_t cluster) { + return (cluster >= CLUSTER_FIRST) ? + ((cluster - CLUSTER_FIRST) * (sec_t)partition->sectorsPerCluster) + partition->dataStart : + partition->rootDirStart; +} + +static inline bool _FAT_fat_isValidCluster (PARTITION* partition, uint32_t cluster) { + return (cluster >= CLUSTER_FIRST) && (cluster <= partition->fat.lastCluster /* This will catch CLUSTER_ERROR */); +} + +#endif /* _FAT_H */ diff --git a/deps/libfat/filetime.c b/deps/libfat/filetime.c new file mode 100644 index 0000000000..72c70d1e16 --- /dev/null +++ b/deps/libfat/filetime.c @@ -0,0 +1,111 @@ +/* + filetime.c + Conversion of file time and date values to various other types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include "filetime.h" +#include "common.h" + +#define MAX_HOUR 23 +#define MAX_MINUTE 59 +#define MAX_SECOND 59 + +#define MAX_MONTH 11 +#define MIN_MONTH 0 +#define MAX_DAY 31 +#define MIN_DAY 1 + +uint16_t _FAT_filetime_getTimeFromRTC (void) +{ +#ifdef USE_RTC_TIME + struct tm timeParts; + time_t epochTime; + + if (time(&epochTime) == (time_t)-1) + return 0; + localtime_r(&epochTime, &timeParts); + + /* Check that the values are all in range. + * If they are not, return 0 (no timestamp) */ + if ((timeParts.tm_hour < 0) || (timeParts.tm_hour > MAX_HOUR)) + return 0; + if ((timeParts.tm_min < 0) || (timeParts.tm_min > MAX_MINUTE)) + return 0; + if ((timeParts.tm_sec < 0) || (timeParts.tm_sec > MAX_SECOND)) + return 0; + + return ( + ((timeParts.tm_hour & 0x1F) << 11) | + ((timeParts.tm_min & 0x3F) << 5) | + ((timeParts.tm_sec >> 1) & 0x1F) + ); +#else + return 0; +#endif +} + + +uint16_t _FAT_filetime_getDateFromRTC (void) +{ +#ifdef USE_RTC_TIME + struct tm timeParts; + time_t epochTime; + + if (time(&epochTime) == (time_t)-1) + return 0; + localtime_r(&epochTime, &timeParts); + + if ((timeParts.tm_mon < MIN_MONTH) || (timeParts.tm_mon > MAX_MONTH)) return 0; + if ((timeParts.tm_mday < MIN_DAY) || (timeParts.tm_mday > MAX_DAY)) return 0; + + return ( + (((timeParts.tm_year - 80) & 0x7F) <<9) | /* Adjust for MS-FAT base year (1980 vs 1900 for tm_year) */ + (((timeParts.tm_mon + 1) & 0xF) << 5) | + (timeParts.tm_mday & 0x1F) + ); +#else + return 0; +#endif +} + +time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d) +{ + struct tm timeParts; + + timeParts.tm_hour = t >> 11; + timeParts.tm_min = (t >> 5) & 0x3F; + timeParts.tm_sec = (t & 0x1F) << 1; + + timeParts.tm_mday = d & 0x1F; + timeParts.tm_mon = ((d >> 5) & 0x0F) - 1; + timeParts.tm_year = (d >> 9) + 80; + + timeParts.tm_isdst = 0; + + return mktime(&timeParts); +} diff --git a/deps/libfat/filetime.h b/deps/libfat/filetime.h new file mode 100644 index 0000000000..7088c1ae6d --- /dev/null +++ b/deps/libfat/filetime.h @@ -0,0 +1,41 @@ +/* + filetime.h + Conversion of file time and date values to various other types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FILETIME_H +#define _FILETIME_H + +#include "common.h" +#include + +uint16_t _FAT_filetime_getTimeFromRTC (void); +uint16_t _FAT_filetime_getDateFromRTC (void); + +time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d); + + +#endif /* _FILETIME_H */ diff --git a/deps/libfat/include/fat.h b/deps/libfat/include/fat.h new file mode 100644 index 0000000000..d466ffee89 --- /dev/null +++ b/deps/libfat/include/fat.h @@ -0,0 +1,124 @@ +/* + fat.h + Simple functionality for startup, mounting and unmounting of FAT-based devices. + + Copyright (c) 2006 - 2012 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _LIBFAT_H +#define _LIBFAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* When compiling for NDS, make sure NDS is defined */ +#ifndef NDS + #if defined ARM9 || defined ARM7 + #define NDS + #endif +#endif + +#include + +#if defined (__wiiu__) +# include +#elif defined(__gamecube__) || defined (__wii__) +# include +#else +# ifdef NDS +# include +# else +# include +# endif +#endif + +/* +Initialise any inserted block-devices. +Add the fat device driver to the devoptab, making it available for standard file functions. +cacheSize: The number of pages to allocate for each inserted block-device +setAsDefaultDevice: if true, make this the default device driver for file operations +*/ +extern bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice); + +/* +Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. +*/ +extern bool fatInitDefault (void); + +/* +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +This will mount the active partition or the first valid partition on the disc, +and will use a cache size optimized for the host system. +*/ +extern bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); + +/* +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +If startSector = 0, it will mount the active partition of the first valid partition on +the disc. Otherwise it will try to mount the partition starting at startSector. +cacheSize specifies the number of pages to allocate for the cache. +This will not startup the disc, so you need to call interface->startup(); first. +*/ +extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage); + +/* +Unmount the partition specified by name. +If there are open files, it will attempt to synchronise them to disc. +*/ +extern void fatUnmount (const char* name); + +/* +Get Volume Label +*/ +extern void fatGetVolumeLabel (const char* name, char *label); + +/* File attributes */ +#define ATTR_ARCHIVE 0x20 /* Archive */ +#define ATTR_DIRECTORY 0x10 /* Directory */ +#define ATTR_VOLUME 0x08 /* Volume */ +#define ATTR_SYSTEM 0x04 /* System */ +#define ATTR_HIDDEN 0x02 /* Hidden */ +#define ATTR_READONLY 0x01 /* Read only */ + +/* +Methods to modify DOS File Attributes +*/ +int FAT_getAttr(const char *file); +int FAT_setAttr(const char *file, uint8_t attr ); + +#define LIBFAT_FEOS_MULTICWD + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBFAT_H */ diff --git a/deps/libfat/include/libfatversion.h b/deps/libfat/include/libfatversion.h new file mode 100644 index 0000000000..a306565704 --- /dev/null +++ b/deps/libfat/include/libfatversion.h @@ -0,0 +1,10 @@ +#ifndef __LIBFATVERSION_H__ +#define __LIBFATVERSION_H__ + +#define _LIBFAT_MAJOR_ 1 +#define _LIBFAT_MINOR_ 1 +#define _LIBFAT_PATCH_ 0 + +#define _LIBFAT_STRING "libFAT Release 1.1.0" + +#endif /* __LIBFATVERSION_H__ */ diff --git a/deps/libfat/libfat.c b/deps/libfat/libfat.c new file mode 100644 index 0000000000..34e58c4186 --- /dev/null +++ b/deps/libfat/libfat.c @@ -0,0 +1,264 @@ +/* + libfat.c + Simple functionality for startup, mounting and unmounting of FAT-based devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "partition.h" +#include "fatfile.h" +#include "fatdir.h" +#include "lock.h" +#include "mem_allocate.h" +#include "disc.h" + +static const devoptab_t dotab_fat = { + "fat", + sizeof (FILE_STRUCT), + _FAT_open_r, + _FAT_close_r, + _FAT_write_r, + _FAT_read_r, + _FAT_seek_r, + _FAT_fstat_r, + _FAT_stat_r, + _FAT_link_r, + _FAT_unlink_r, + _FAT_chdir_r, + _FAT_rename_r, + _FAT_mkdir_r, + sizeof (DIR_STATE_STRUCT), + _FAT_diropen_r, + _FAT_dirreset_r, + _FAT_dirnext_r, + _FAT_dirclose_r, + _FAT_statvfs_r, + _FAT_ftruncate_r, + _FAT_fsync_r, + NULL, /* Device data */ + NULL, /* chmod_r */ + NULL /* fchmod_r */ +}; + +bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage) +{ + char devname[10]; + PARTITION* partition; + devoptab_t* devops; + char* nameCopy; + + if(!name || strlen(name) > 8 || !interface) + return false; + + if(!interface->startup()) + return false; + + if(!interface->isInserted()) + return false; + + strcpy(devname, name); + strcat(devname, ":"); + if(FindDevice(devname) >= 0) + return true; + + devops = _FAT_mem_allocate (sizeof(devoptab_t) + strlen(name) + 1); + if (!devops) + return false; + /* Use the space allocated at the end of the devoptab struct for storing the name */ + nameCopy = (char*)(devops+1); + + /* Initialize the file system */ + partition = _FAT_partition_constructor (interface, cacheSize, SectorsPerPage, startSector); + if (!partition) + { + _FAT_mem_free (devops); + return false; + } + + /* Add an entry for this device to the devoptab table */ + memcpy (devops, &dotab_fat, sizeof(dotab_fat)); + strcpy (nameCopy, name); + devops->name = nameCopy; + devops->deviceData = partition; + + AddDevice (devops); + + return true; +} + +bool fatMountSimple (const char* name, const DISC_INTERFACE* interface) +{ + return fatMount (name, interface, 0, DEFAULT_CACHE_PAGES, DEFAULT_SECTORS_PAGE); +} + +void fatUnmount (const char* name) +{ + devoptab_t *devops; + PARTITION* partition; + + if(!name) + return; + + devops = (devoptab_t*)GetDeviceOpTab (name); + if (!devops) + return; + + /* Perform a quick check to make sure we're dealing with a libfat controlled device */ + if (devops->open_r != dotab_fat.open_r) + return; + + if (RemoveDevice (name) == -1) + return; + + partition = (PARTITION*)devops->deviceData; + _FAT_partition_destructor (partition); + _FAT_mem_free (devops); +} + +bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice) +{ + int i; + int defaultDevice = -1; + const DISC_INTERFACE *disc; + + for (i = 0; + _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; + i++) + { + disc = _FAT_disc_interfaces[i].getInterface(); + if (!disc) + continue; + + if (fatMount (_FAT_disc_interfaces[i].name, disc, 0, cacheSize, DEFAULT_SECTORS_PAGE)) + { + /* The first device to successfully mount is set as the default */ + if (defaultDevice < 0) + defaultDevice = i; + } + } + + /* None of our devices mounted */ + if (defaultDevice < 0) + return false; + + if (setAsDefaultDevice) + { + char filePath[PATH_MAX]; + strcpy (filePath, _FAT_disc_interfaces[defaultDevice].name); + strcat (filePath, ":/"); +#ifdef ARGV_MAGIC + if ( __system_argv->argvMagic == ARGV_MAGIC && __system_argv->argc >= 1 && strrchr( __system_argv->argv[0], '/' )!=NULL ) + { + /* Check the app's path against each of our mounted devices, to see + * if we can support it. If so, change to that path. */ + for (i = 0; + _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; + i++) + { + if ( !strncasecmp( __system_argv->argv[0], _FAT_disc_interfaces[i].name, + strlen(_FAT_disc_interfaces[i].name))) + { + char *lastSlash; + strcpy(filePath, __system_argv->argv[0]); + lastSlash = strrchr( filePath, '/' ); + + if ( NULL != lastSlash) + { + if ( *(lastSlash - 1) == ':') + lastSlash++; + *lastSlash = 0; + } + } + } + } +#endif + chdir (filePath); + } + + return true; +} + +bool fatInitDefault (void) +{ + return fatInit (DEFAULT_CACHE_PAGES, true); +} + +void fatGetVolumeLabel (const char* name, char *label) +{ + devoptab_t *devops; + PARTITION* partition; + char *buf; + int namelen,i; + + if(!name || !label) + return; + + namelen = strlen(name); + buf=(char*)_FAT_mem_allocate(sizeof(char)*namelen+2); + strcpy(buf,name); + + if (name[namelen-1] == '/') + { + buf[namelen-1]='\0'; + namelen--; + } + + if (name[namelen-1] != ':') + { + buf[namelen]=':'; + buf[namelen+1]='\0'; + } + + devops = (devoptab_t*)GetDeviceOpTab(buf); + + for(i=0;buf[i]!='\0' && buf[i]!=':';i++); + if (!devops || strncasecmp(buf,devops->name,i)) + { + _FAT_mem_free(buf); + return; + } + + _FAT_mem_free(buf); + + /* Perform a quick check to make sure we're dealing with a libfat controlled device */ + if (devops->open_r != dotab_fat.open_r) + return; + + partition = (PARTITION*)devops->deviceData; + + if(!_FAT_directory_getVolumeLabel(partition, label)) + { + strncpy(label,partition->label,11); + label[11]='\0'; + } + if(!strncmp(label, "NO NAME", 7)) + label[0]='\0'; +} diff --git a/deps/libfat/lock.c b/deps/libfat/lock.c new file mode 100644 index 0000000000..8c55d77f3e --- /dev/null +++ b/deps/libfat/lock.c @@ -0,0 +1,29 @@ +#include "common.h" + +#ifndef USE_LWP_LOCK + +#ifndef mutex_t +typedef int mutex_t; +#endif + +void __attribute__ ((weak)) _FAT_lock_init(mutex_t *mutex) +{ + return; +} + +void __attribute__ ((weak)) _FAT_lock_deinit(mutex_t *mutex) +{ + return; +} + +void __attribute__ ((weak)) _FAT_lock(mutex_t *mutex) +{ + return; +} + +void __attribute__ ((weak)) _FAT_unlock(mutex_t *mutex) +{ + return; +} + +#endif /* USE_LWP_LOCK */ diff --git a/deps/libfat/lock.h b/deps/libfat/lock.h new file mode 100644 index 0000000000..8a44ec9181 --- /dev/null +++ b/deps/libfat/lock.h @@ -0,0 +1,72 @@ +/* + lock.h + + Copyright (c) 2008 Sven Peter + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _LOCK_H +#define _LOCK_H + +#include "common.h" + +#ifdef USE_LWP_LOCK + +static inline void _FAT_lock_init(mutex_t *mutex) +{ + LWP_MutexInit(mutex, false); +} + +static inline void _FAT_lock_deinit(mutex_t *mutex) +{ + LWP_MutexDestroy(*mutex); +} + +static inline void _FAT_lock(mutex_t *mutex) +{ + LWP_MutexLock(*mutex); +} + +static inline void _FAT_unlock(mutex_t *mutex) +{ + LWP_MutexUnlock(*mutex); +} + +#else + +/* We still need a blank lock type */ +#ifndef mutex_t +typedef int mutex_t; +#endif + +void _FAT_lock_init(mutex_t *mutex); +void _FAT_lock_deinit(mutex_t *mutex); +void _FAT_lock(mutex_t *mutex); +void _FAT_unlock(mutex_t *mutex); + +#endif /* USE_LWP_LOCK */ + + +#endif /* _LOCK_H */ + diff --git a/deps/libfat/mem_allocate.h b/deps/libfat/mem_allocate.h new file mode 100644 index 0000000000..35ad3966b6 --- /dev/null +++ b/deps/libfat/mem_allocate.h @@ -0,0 +1,55 @@ +/* + mem_allocate.h + Memory allocation and destruction calls + Replace these calls with custom allocators if + malloc is unavailable + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MEM_ALLOCATE_H +#define _MEM_ALLOCATE_H + +#include + +static inline void* _FAT_mem_allocate (size_t size) +{ + return malloc (size); +} + +static inline void* _FAT_mem_align (size_t size) +{ +#ifdef __wii__ + return memalign (32, size); +#else + return malloc (size); +#endif +} + +static inline void _FAT_mem_free (void* mem) +{ + free (mem); +} + +#endif /* _MEM_ALLOCATE_H */ diff --git a/deps/libfat/partition.c b/deps/libfat/partition.c new file mode 100644 index 0000000000..0080b6e93c --- /dev/null +++ b/deps/libfat/partition.c @@ -0,0 +1,464 @@ +/* + partition.c + Functions for mounting and dismounting partitions + on various block devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "partition.h" +#include "bit_ops.h" +#include "file_allocation_table.h" +#include "directory.h" +#include "mem_allocate.h" +#include "fatfile.h" + +#include +#include +#include + +/* +Data offsets +*/ + +/* BIOS Parameter Block offsets */ +enum BPB +{ + BPB_jmpBoot = 0x00, + BPB_OEMName = 0x03, + /* BIOS Parameter Block */ + BPB_bytesPerSector = 0x0B, + BPB_sectorsPerCluster = 0x0D, + BPB_reservedSectors = 0x0E, + BPB_numFATs = 0x10, + BPB_rootEntries = 0x11, + BPB_numSectorsSmall = 0x13, + BPB_mediaDesc = 0x15, + BPB_sectorsPerFAT = 0x16, + BPB_sectorsPerTrk = 0x18, + BPB_numHeads = 0x1A, + BPB_numHiddenSectors = 0x1C, + BPB_numSectors = 0x20, + /* Ext BIOS Parameter Block for FAT16 */ + BPB_FAT16_driveNumber = 0x24, + BPB_FAT16_reserved1 = 0x25, + BPB_FAT16_extBootSig = 0x26, + BPB_FAT16_volumeID = 0x27, + BPB_FAT16_volumeLabel = 0x2B, + BPB_FAT16_fileSysType = 0x36, + /* Bootcode */ + BPB_FAT16_bootCode = 0x3E, + /* FAT32 extended block */ + BPB_FAT32_sectorsPerFAT32 = 0x24, + BPB_FAT32_extFlags = 0x28, + BPB_FAT32_fsVer = 0x2A, + BPB_FAT32_rootClus = 0x2C, + BPB_FAT32_fsInfo = 0x30, + BPB_FAT32_bkBootSec = 0x32, + /* Ext BIOS Parameter Block for FAT32 */ + BPB_FAT32_driveNumber = 0x40, + BPB_FAT32_reserved1 = 0x41, + BPB_FAT32_extBootSig = 0x42, + BPB_FAT32_volumeID = 0x43, + BPB_FAT32_volumeLabel = 0x47, + BPB_FAT32_fileSysType = 0x52, + /* Bootcode */ + BPB_FAT32_bootCode = 0x5A, + BPB_bootSig_55 = 0x1FE, + BPB_bootSig_AA = 0x1FF +}; + +/* File system information block offsets */ +enum FSIB +{ + FSIB_SIG1 = 0x00, + FSIB_SIG2 = 0x1e4, + FSIB_numberOfFreeCluster = 0x1e8, + FSIB_numberLastAllocCluster = 0x1ec, + FSIB_bootSig_55 = 0x1FE, + FSIB_bootSig_AA = 0x1FF +}; + +static const char FAT_SIG[3] = {'F', 'A', 'T'}; +static const char FS_INFO_SIG1[4] = {'R', 'R', 'a', 'A'}; +static const char FS_INFO_SIG2[4] = {'r', 'r', 'A', 'a'}; + +sec_t FindFirstValidPartition_buf(const DISC_INTERFACE* disc, uint8_t *sectorBuffer) +{ + uint8_t part_table[16*4]; + uint8_t *ptr; + int i; + + /* Read first sector of disc */ + if (!_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) + return 0; + + memcpy(part_table,sectorBuffer+0x1BE,16*4); + ptr = part_table; + + for(i=0;i<4;i++,ptr+=16) + { + sec_t part_lba = u8array_to_u32(ptr, 0x8); + + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || + !memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + return part_lba; + + if(ptr[4]==0) + continue; + + if(ptr[4]==0x0F) + { + sec_t part_lba2=part_lba; + sec_t next_lba2=0; + int n; + + for(n=0;n<8;n++) /* max 8 logic partitions */ + { + if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) + return 0; + + part_lba2 = part_lba + next_lba2 + u8array_to_u32(sectorBuffer, 0x1C6) ; + next_lba2 = u8array_to_u32(sectorBuffer, 0x1D6); + + if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) + return 0; + + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || + !memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + return part_lba2; + + if(next_lba2==0) break; + } + } + else + { + if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) + return 0; + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || + !memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + return part_lba; + } + } + return 0; +} + +sec_t FindFirstValidPartition(const DISC_INTERFACE* disc) +{ + uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(MAX_SECTOR_SIZE); + if (!sectorBuffer) + return 0; + sec_t ret = FindFirstValidPartition_buf(disc, sectorBuffer); + _FAT_mem_free(sectorBuffer); + return ret; +} + + +PARTITION* _FAT_partition_constructor_buf (const DISC_INTERFACE* disc, + uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector, + uint8_t *sectorBuffer) +{ + PARTITION* partition; + uint32_t clusterCount; + + /* Read first sector of disc */ + if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) + return NULL; + + /* Make sure it is a valid MBR or boot sector */ + if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || ((sectorBuffer[BPB_bootSig_AA] != 0xAA) +#if defined(__gamecube__) || defined (__wii__) || defined (__wiiu__) + && (sectorBuffer[BPB_bootSig_AA] != 0xAB) +#endif + )) + return NULL; + + /* We're told where to start the partition, so just accept it */ + if (startSector != 0) { } + /* Check if there is a FAT string, which indicates this is a boot sector */ + else if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + startSector = 0; + /* Check for FAT32 */ + else if (!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + startSector = 0; + else + { + startSector = FindFirstValidPartition_buf(disc, sectorBuffer); + if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) + return NULL; + } + + /* Now verify that this is indeed a FAT partition */ + if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) && + memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + return NULL; + + partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION)); + if (partition == NULL) + return NULL; + + /* Init the partition lock */ + _FAT_lock_init(&partition->lock); + + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT16_volumeLabel), 11); + else + strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT32_volumeLabel), 11); + partition->label[11] = '\0'; + + /* Set partition's disc interface */ + partition->disc = disc; + + /* Store required information about the file system */ + partition->fat.sectorsPerFat = u8array_to_u16(sectorBuffer, BPB_sectorsPerFAT); + if (partition->fat.sectorsPerFat == 0) + partition->fat.sectorsPerFat = u8array_to_u32( sectorBuffer, BPB_FAT32_sectorsPerFAT32); + + partition->numberOfSectors = u8array_to_u16( sectorBuffer, BPB_numSectorsSmall); + if (partition->numberOfSectors == 0) + partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors); + + partition->bytesPerSector = u8array_to_u16(sectorBuffer, BPB_bytesPerSector); + if(partition->bytesPerSector < MIN_SECTOR_SIZE || partition->bytesPerSector > MAX_SECTOR_SIZE) + { + /* Unsupported sector size */ + _FAT_mem_free(partition); + return NULL; + } + + partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster]; + partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster; + partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors); + + partition->rootDirStart = partition->fat.fatStart + (sectorBuffer[BPB_numFATs] * partition->fat.sectorsPerFat); + partition->dataStart = partition->rootDirStart + + (( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); + + partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector; + + /* FS info sector */ + partition->fsInfoSector = startSector + (u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) ? u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) : 1); + + /* Store info about FAT */ + clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster; + + partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1; + partition->fat.firstFree = CLUSTER_FIRST; + partition->fat.numberFreeCluster = 0; + partition->fat.numberLastAllocCluster = 0; + + if (clusterCount < CLUSTERS_PER_FAT12) + partition->filesysType = FS_FAT12; /* FAT12 volume */ + else if (clusterCount < CLUSTERS_PER_FAT16) + partition->filesysType = FS_FAT16; /* FAT16 volume */ + else + partition->filesysType = FS_FAT32; /* FAT32 volume */ + + if (partition->filesysType != FS_FAT32) + partition->rootDirCluster = FAT16_ROOT_DIR_CLUSTER; + else + { + /* Set up for the FAT32 way */ + partition->rootDirCluster = u8array_to_u32(sectorBuffer, BPB_FAT32_rootClus); + /* Check if FAT mirroring is enabled */ + if (!(sectorBuffer[BPB_FAT32_extFlags] & 0x80)) + { + /* Use the active FAT */ + partition->fat.fatStart = partition->fat.fatStart + ( partition->fat.sectorsPerFat * (sectorBuffer[BPB_FAT32_extFlags] & 0x0F)); + } + } + + /* Create a cache to use */ + partition->cache = _FAT_cache_constructor (cacheSize, sectorsPerPage, partition->disc, startSector+partition->numberOfSectors, partition->bytesPerSector); + + /* Set current directory to the root */ + partition->cwdCluster = partition->rootDirCluster; + + /* Check if this disc is writable, and set the + * readOnly property appropriately */ + partition->readOnly = !(_FAT_disc_features(disc) & FEATURE_MEDIUM_CANWRITE); + + /* There are currently no open files on this partition */ + partition->openFileCount = 0; + partition->firstOpenFile = NULL; + + _FAT_partition_readFSinfo(partition); + + return partition; +} + +PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector) +{ + PARTITION *ret = NULL; + uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(MAX_SECTOR_SIZE); + if (!sectorBuffer) + return NULL; + + ret = _FAT_partition_constructor_buf(disc, cacheSize, + sectorsPerPage, startSector, sectorBuffer); + _FAT_mem_free(sectorBuffer); + return ret; +} + + +void _FAT_partition_destructor (PARTITION* partition) +{ + FILE_STRUCT* nextFile; + + _FAT_lock(&partition->lock); + + /* Synchronize open files */ + nextFile = partition->firstOpenFile; + while (nextFile) + { + _FAT_syncToDisc (nextFile); + nextFile = nextFile->nextOpenFile; + } + + /* Write out the fs info sector */ + _FAT_partition_writeFSinfo(partition); + + /* Free memory used by the cache, writing it to disc at the same time */ + _FAT_cache_destructor (partition->cache); + + /* Unlock the partition and destroy the lock */ + _FAT_unlock(&partition->lock); + _FAT_lock_deinit(&partition->lock); + + /* Free memory used by the partition */ + _FAT_mem_free (partition); +} + +PARTITION* _FAT_partition_getPartitionFromPath (const char* path) +{ + const devoptab_t *devops = GetDeviceOpTab (path); + + if (!devops) + return NULL; + + return (PARTITION*)devops->deviceData; +} + +void _FAT_partition_createFSinfo(PARTITION * partition) +{ + int i; + uint8_t *sectorBuffer; + + if(partition->readOnly || partition->filesysType != FS_FAT32) + return; + + sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector); + if (!sectorBuffer) + return; + memset(sectorBuffer, 0, partition->bytesPerSector); + + for(i = 0; i < 4; ++i) + { + sectorBuffer[FSIB_SIG1+i] = FS_INFO_SIG1[i]; + sectorBuffer[FSIB_SIG2+i] = FS_INFO_SIG2[i]; + } + + partition->fat.numberFreeCluster = _FAT_fat_freeClusterCount(partition); + u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster); + u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster); + + sectorBuffer[FSIB_bootSig_55] = 0x55; + sectorBuffer[FSIB_bootSig_AA] = 0xAA; + + _FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer); + + _FAT_mem_free(sectorBuffer); +} + +void _FAT_partition_readFSinfo(PARTITION * partition) +{ + uint8_t *sectorBuffer = NULL; + if(partition->filesysType != FS_FAT32) + return; + + sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector); + if (!sectorBuffer) + return; + memset(sectorBuffer, 0, partition->bytesPerSector); + + /* Read first sector of disc */ + if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) + { + _FAT_mem_free(sectorBuffer); + return; + } + + /* sector does not yet exist, create one! */ + if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) != 0 || + memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4) != 0 || + u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster) == 0) + _FAT_partition_createFSinfo(partition); + else + { + partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster); + partition->fat.numberLastAllocCluster = u8array_to_u32(sectorBuffer, FSIB_numberLastAllocCluster); + } + _FAT_mem_free(sectorBuffer); +} + +void _FAT_partition_writeFSinfo(PARTITION * partition) +{ + uint8_t *sectorBuffer = NULL; + if(partition->filesysType != FS_FAT32) + return; + + sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector); + if (!sectorBuffer) + return; + memset(sectorBuffer, 0, partition->bytesPerSector); + /* Read first sector of disc */ + if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) + { + _FAT_mem_free(sectorBuffer); + return; + } + + if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) || memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4)) + { + _FAT_mem_free(sectorBuffer); + return; + } + + u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster); + u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster); + + /* Write first sector of disc */ + _FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer); + _FAT_mem_free(sectorBuffer); +} + +uint32_t* _FAT_getCwdClusterPtr(const char* name) +{ + PARTITION *partition = _FAT_partition_getPartitionFromPath(name); + + if (!partition) + return NULL; + + return &partition->cwdCluster; +} diff --git a/deps/libfat/partition.h b/deps/libfat/partition.h new file mode 100644 index 0000000000..e4aecccd27 --- /dev/null +++ b/deps/libfat/partition.h @@ -0,0 +1,107 @@ +/* + partition.h + Functions for mounting and dismounting partitions + on various block devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _PARTITION_H +#define _PARTITION_H + +#include "common.h" +#include "cache.h" +#include "lock.h" + +#define MIN_SECTOR_SIZE 512 +#define MAX_SECTOR_SIZE 4096 + +/* Filesystem type */ +typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; + +typedef struct { + sec_t fatStart; + uint32_t sectorsPerFat; + uint32_t lastCluster; + uint32_t firstFree; + uint32_t numberFreeCluster; + uint32_t numberLastAllocCluster; +} FAT; + +typedef struct { + const DISC_INTERFACE* disc; + CACHE* cache; + /* Info about the partition */ + FS_TYPE filesysType; + uint64_t totalSize; + sec_t rootDirStart; + uint32_t rootDirCluster; + uint32_t numberOfSectors; + sec_t dataStart; + uint32_t bytesPerSector; + uint32_t sectorsPerCluster; + uint32_t bytesPerCluster; + uint32_t fsInfoSector; + FAT fat; + /* Values that may change after construction */ + uint32_t cwdCluster; /* Current working directory cluster */ + int openFileCount; + struct _FILE_STRUCT* firstOpenFile; /* The start of a linked list of files */ + mutex_t lock; /* A lock for partition operations */ + bool readOnly; /* If this is set, then do not try writing to the disc */ + char label[12]; /* Volume label */ +} PARTITION; + +/* +Mount the supplied device and return a pointer to the struct necessary to use it +*/ +PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t SectorsPerPage, sec_t startSector); + +/* +Dismount the device and free all structures used. +Will also attempt to synchronise all open files to disc. +*/ +void _FAT_partition_destructor (PARTITION* partition); + +/* +Return the partition specified in a path, as taken from the devoptab. +*/ +PARTITION* _FAT_partition_getPartitionFromPath (const char* path); + +/* +Create the fs info sector. +*/ +void _FAT_partition_createFSinfo(PARTITION * partition); + +/* +Read the fs info sector data. +*/ +void _FAT_partition_readFSinfo(PARTITION * partition); + +/* +Write the fs info sector data. +*/ +void _FAT_partition_writeFSinfo(PARTITION * partition); + +#endif /* _PARTITION_H */ diff --git a/deps/libiosuhax/iosuhax.c b/deps/libiosuhax/iosuhax.c new file mode 100644 index 0000000000..0a2f8221b8 --- /dev/null +++ b/deps/libiosuhax/iosuhax.c @@ -0,0 +1,966 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include +#include +#include "os_functions.h" +#include "iosuhax.h" + +#define IOSUHAX_MAGIC_WORD 0x4E696365 + +#define IOCTL_MEM_WRITE 0x00 +#define IOCTL_MEM_READ 0x01 +#define IOCTL_SVC 0x02 +#define IOCTL_MEMCPY 0x04 +#define IOCTL_REPEATED_WRITE 0x05 +#define IOCTL_KERN_READ32 0x06 +#define IOCTL_KERN_WRITE32 0x07 + +#define IOCTL_FSA_OPEN 0x40 +#define IOCTL_FSA_CLOSE 0x41 +#define IOCTL_FSA_MOUNT 0x42 +#define IOCTL_FSA_UNMOUNT 0x43 +#define IOCTL_FSA_GETDEVICEINFO 0x44 +#define IOCTL_FSA_OPENDIR 0x45 +#define IOCTL_FSA_READDIR 0x46 +#define IOCTL_FSA_CLOSEDIR 0x47 +#define IOCTL_FSA_MAKEDIR 0x48 +#define IOCTL_FSA_OPENFILE 0x49 +#define IOCTL_FSA_READFILE 0x4A +#define IOCTL_FSA_WRITEFILE 0x4B +#define IOCTL_FSA_STATFILE 0x4C +#define IOCTL_FSA_CLOSEFILE 0x4D +#define IOCTL_FSA_SETFILEPOS 0x4E +#define IOCTL_FSA_GETSTAT 0x4F +#define IOCTL_FSA_REMOVE 0x50 +#define IOCTL_FSA_REWINDDIR 0x51 +#define IOCTL_FSA_CHDIR 0x52 +#define IOCTL_FSA_RENAME 0x53 +#define IOCTL_FSA_RAW_OPEN 0x54 +#define IOCTL_FSA_RAW_READ 0x55 +#define IOCTL_FSA_RAW_WRITE 0x56 +#define IOCTL_FSA_RAW_CLOSE 0x57 +#define IOCTL_FSA_CHANGEMODE 0x58 +#define IOCTL_FSA_FLUSHVOLUME 0x59 +#define IOCTL_CHECK_IF_IOSUHAX 0x5B + +static int iosuhaxHandle = -1; + +int IOSUHAX_Open(const char *dev) +{ + if(iosuhaxHandle >= 0) + return iosuhaxHandle; + + iosuhaxHandle = IOS_Open((char*)(dev ? dev : "/dev/iosuhax"), 0); + if(iosuhaxHandle >= 0 && dev) /* make sure device is actually iosuhax */ + { + unsigned int res = 0; + IOS_Ioctl(iosuhaxHandle, IOCTL_CHECK_IF_IOSUHAX, (void*)0, 0, &res, 4); + if(res != IOSUHAX_MAGIC_WORD) + { + IOS_Close(iosuhaxHandle); + iosuhaxHandle = -1; + } + } + + return iosuhaxHandle; +} + +int IOSUHAX_Close(void) +{ + if(iosuhaxHandle < 0) + return 0; + + int res = IOS_Close(iosuhaxHandle); + iosuhaxHandle = -1; + return res; +} + +int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, size + 4); + if(!io_buf) + return -2; + + io_buf[0] = address; + memcpy(io_buf + 1, buffer, size); + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_WRITE, io_buf, size + 4, 0, 0); + + free(io_buf); + return res; +} + +int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + return IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_READ, &address, sizeof(address), out_buffer, size); +} + +int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + uint32_t io_buf[3]; + io_buf[0] = dst; + io_buf[1] = src; + io_buf[2] = size; + + return IOS_Ioctl(iosuhaxHandle, IOCTL_MEMCPY, io_buf, sizeof(io_buf), 0, 0); +} + +int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + uint32_t arguments[9]; + arguments[0] = svc_id; + + if(args && arg_cnt) + { + if(arg_cnt > 8) + arg_cnt = 8; + + memcpy(arguments + 1, args, arg_cnt * 4); + } + + int result; + int ret = IOS_Ioctl(iosuhaxHandle, IOCTL_SVC, arguments, (1 + arg_cnt) * 4, &result, sizeof(result)); + if(ret < 0) + return ret; + + return result; +} + +int IOSUHAX_FSA_Open(void) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + int fsaFd; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPEN, 0, 0, &fsaFd, sizeof(fsaFd)); + if(res < 0) + return res; + + return fsaFd; +} + +int IOSUHAX_FSA_Close(int fsaFd) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSE, &fsaFd, sizeof(fsaFd), &fsaFd, sizeof(fsaFd)); + if(res < 0) + return res; + + return fsaFd; +} + +int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 6; + + int io_buf_size = (sizeof(uint32_t) * input_cnt) + strlen(device_path) + strlen(volume_path) + arg_string_len + 3; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + memset(io_buf, 0, io_buf_size); + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = io_buf[1] + strlen(device_path) + 1; + io_buf[3] = flags; + io_buf[4] = arg_string_len ? ( io_buf[2] + strlen(volume_path) + 1) : 0; + io_buf[5] = arg_string_len; + + strcpy(((char*)io_buf) + io_buf[1], device_path); + strcpy(((char*)io_buf) + io_buf[2], volume_path); + + if(arg_string_len) + memcpy(((char*)io_buf) + io_buf[4], arg_string, arg_string_len); + + int mountRes; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_MOUNT, io_buf, io_buf_size, &mountRes, sizeof(mountRes)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return mountRes; +} + +int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = flags; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_UNMOUNT, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_FlushVolume(int fsaFd, const char *volume_path) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(volume_path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], volume_path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_FLUSHVOLUME, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = type; + strcpy(((char*)io_buf) + io_buf[1], device_path); + + uint32_t out_buf[1 + 0x64 / 4]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETDEVICEINFO, io_buf, io_buf_size, out_buf, sizeof(out_buf)); + if(res < 0) + { + free(io_buf); + return res; + } + + memcpy(out_data, out_buf + 1, 0x64); + free(io_buf); + return out_buf[0]; +} + +int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = flags; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_MAKEDIR, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result_vec[2]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENDIR, io_buf, io_buf_size, result_vec, sizeof(result_vec)); + if(res < 0) + { + free(io_buf); + return res; + } + + *outHandle = result_vec[1]; + free(io_buf); + return result_vec[0]; +} + +int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = handle; + + int result_vec_size = 4 + sizeof(directoryEntry_s); + uint8_t *result_vec = (uint8_t*) memalign(0x20, result_vec_size); + if(!result_vec) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READDIR, io_buf, io_buf_size, result_vec, result_vec_size); + if(res < 0) + { + free(result_vec); + free(io_buf); + return res; + } + + int result = *(int*)result_vec; + memcpy(out_data, result_vec + 4, sizeof(directoryEntry_s)); + free(io_buf); + free(result_vec); + return result; +} + +int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = dirHandle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REWINDDIR, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_CloseDir(int fsaFd, int handle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = handle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEDIR, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHDIR, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + strlen(mode) + 2; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = io_buf[1] + strlen(path) + 1; + strcpy(((char*)io_buf) + io_buf[1], path); + strcpy(((char*)io_buf) + io_buf[2], mode); + + int result_vec[2]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_OPENFILE, io_buf, io_buf_size, result_vec, sizeof(result_vec)); + if(res < 0) + { + free(io_buf); + return res; + } + + *outHandle = result_vec[1]; + free(io_buf); + return result_vec[0]; +} + +int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 5; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = fileHandle; + io_buf[4] = flags; + + int out_buf_size = ((size * cnt + 0x40) + 0x3F) & ~0x3F; + + uint32_t *out_buffer = (uint32_t*)memalign(0x40, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_READFILE, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(out_buffer); + free(io_buf); + return res; + } + + /* ! data is put to offset 0x40 to align the buffer output */ + memcpy(data, ((uint8_t*)out_buffer) + 0x40, size * cnt); + + int result = out_buffer[0]; + + free(out_buffer); + free(io_buf); + return result; +} + +int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 5; + + int io_buf_size = ((sizeof(uint32_t) * input_cnt + size * cnt + 0x40) + 0x3F) & ~0x3F; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = size; + io_buf[2] = cnt; + io_buf[3] = fileHandle; + io_buf[4] = flags; + + /* ! data is put to offset 0x40 to align the buffer input */ + memcpy(((uint8_t*)io_buf) + 0x40, data, size * cnt); + + int result; + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_WRITEFILE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + free(io_buf); + return result; +} + +int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int out_buf_size = 4 + sizeof(fileStat_s); + uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_STATFILE, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(io_buf); + free(out_buffer); + return res; + } + + int result = out_buffer[0]; + memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); + + free(io_buf); + free(out_buffer); + return result; +} + +int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CLOSEFILE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = fileHandle; + io_buf[2] = position; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_SETFILEPOS, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], path); + + int out_buf_size = 4 + sizeof(fileStat_s); + uint32_t *out_buffer = (uint32_t*)memalign(0x20, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_GETSTAT, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(io_buf); + free(out_buffer); + return res; + } + + int result = out_buffer[0]; + memcpy(out_data, out_buffer + 1, sizeof(fileStat_s)); + + free(io_buf); + free(out_buffer); + return result; +} + +int IOSUHAX_FSA_Remove(int fsaFd, const char *path) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_REMOVE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 3; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + io_buf[2] = mode; + strcpy(((char*)io_buf) + io_buf[1], path); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_CHANGEMODE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + +int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = sizeof(uint32_t) * input_cnt; + strcpy(((char*)io_buf) + io_buf[1], device_path); + + int result_vec[2]; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_OPEN, io_buf, io_buf_size, result_vec, sizeof(result_vec)); + if(res < 0) + { + free(io_buf); + return res; + } + + if(outHandle) + *outHandle = result_vec[1]; + + free(io_buf); + return result_vec[0]; +} + +int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 6; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = block_size; + io_buf[2] = block_cnt; + io_buf[3] = (sector_offset >> 32) & 0xFFFFFFFF; + io_buf[4] = sector_offset & 0xFFFFFFFF; + io_buf[5] = device_handle; + + int out_buf_size = ((block_size * block_cnt + 0x40) + 0x3F) & ~0x3F; + + uint32_t *out_buffer = (uint32_t*)memalign(0x40, out_buf_size); + if(!out_buffer) + { + free(io_buf); + return -2; + } + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_READ, io_buf, io_buf_size, out_buffer, out_buf_size); + if(res < 0) + { + free(out_buffer); + free(io_buf); + return res; + } + + /* ! data is put to offset 0x40 to align the buffer output */ + memcpy(data, ((uint8_t*)out_buffer) + 0x40, block_size * block_cnt); + + int result = out_buffer[0]; + + free(out_buffer); + free(io_buf); + return result; +} + +int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 6; + + int io_buf_size = ((sizeof(uint32_t) * input_cnt + block_size * block_cnt + 0x40) + 0x3F) & ~0x3F; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = block_size; + io_buf[2] = block_cnt; + io_buf[3] = (sector_offset >> 32) & 0xFFFFFFFF; + io_buf[4] = sector_offset & 0xFFFFFFFF; + io_buf[5] = device_handle; + + /* ! data is put to offset 0x40 to align the buffer input */ + memcpy(((uint8_t*)io_buf) + 0x40, data, block_size * block_cnt); + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_WRITE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} + + +int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle) +{ + if(iosuhaxHandle < 0) + return iosuhaxHandle; + + const int input_cnt = 2; + + int io_buf_size = sizeof(uint32_t) * input_cnt; + + uint32_t *io_buf = (uint32_t*)memalign(0x20, io_buf_size); + if(!io_buf) + return -2; + + io_buf[0] = fsaFd; + io_buf[1] = device_handle; + + int result; + + int res = IOS_Ioctl(iosuhaxHandle, IOCTL_FSA_RAW_CLOSE, io_buf, io_buf_size, &result, sizeof(result)); + if(res < 0) + { + free(io_buf); + return res; + } + + free(io_buf); + return result; +} diff --git a/deps/libiosuhax/iosuhax.h b/deps/libiosuhax/iosuhax.h new file mode 100644 index 0000000000..25b7367cad --- /dev/null +++ b/deps/libiosuhax/iosuhax.h @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef _LIB_IOSUHAX_H_ +#define _LIB_IOSUHAX_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define IOS_ERROR_UNKNOWN_VALUE 0xFFFFFFD6 +#define IOS_ERROR_INVALID_ARG 0xFFFFFFE3 +#define IOS_ERROR_INVALID_SIZE 0xFFFFFFE9 +#define IOS_ERROR_UNKNOWN 0xFFFFFFF7 +#define IOS_ERROR_NOEXISTS 0xFFFFFFFA + +typedef struct +{ + uint32_t flag; + uint32_t permission; + uint32_t owner_id; + uint32_t group_id; + uint32_t size; // size in bytes + uint32_t physsize; // physical size on disk in bytes + uint32_t unk[3]; + uint32_t id; + uint32_t ctime; + uint32_t mtime; + uint32_t unk2[0x0D]; +}fileStat_s; + +typedef struct +{ + fileStat_s stat; + char name[0x100]; +}directoryEntry_s; + +#define DIR_ENTRY_IS_DIRECTORY 0x80000000 + +#define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0) +#define FSA_MOUNTFLAGS_GLOBAL (1 << 1) + +int IOSUHAX_Open(const char *dev); // if dev == NULL the default path /dev/iosuhax will be used +int IOSUHAX_Close(void); + +int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size); // IOSU external input +int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size); // IOSU external output +int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size); // IOSU internal memcpy only + +int IOSUHAX_SVC(uint32_t svc_id, uint32_t * args, uint32_t arg_cnt); + +int IOSUHAX_FSA_Open(); +int IOSUHAX_FSA_Close(int fsaFd); + +int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_path, uint32_t flags, const char* arg_string, int arg_string_len); +int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags); +int IOSUHAX_FSA_FlushVolume(int fsaFd, const char* volume_path); + +int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint32_t* out_data); + +int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags); +int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle); +int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data); +int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle); +int IOSUHAX_FSA_CloseDir(int fsaFd, int handle); +int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path); + +int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* outHandle); +int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); +int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags); +int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data); +int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle); +int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position); +int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data); +int IOSUHAX_FSA_Remove(int fsaFd, const char *path); +int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode); + +int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle); +int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle); +int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint32_t block_cnt, uint64_t sector_offset, int device_handle); +int IOSUHAX_FSA_RawClose(int fsaFd, int device_handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/deps/libiosuhax/iosuhax_devoptab.c b/deps/libiosuhax/iosuhax_devoptab.c new file mode 100644 index 0000000000..75875bb3ca --- /dev/null +++ b/deps/libiosuhax/iosuhax_devoptab.c @@ -0,0 +1,974 @@ +/*************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "os_functions.h" +#include "iosuhax.h" + +typedef struct _fs_dev_private_t { + char *mount_path; + int fsaFd; + int mounted; + void *pMutex; +} fs_dev_private_t; + +typedef struct _fs_dev_file_state_t { + fs_dev_private_t *dev; + int fd; /* File descriptor */ + int flags; /* Opening flags */ + int read; /* True if allowed to read from file */ + int write; /* True if allowed to write to file */ + int append; /* True if allowed to append to file */ + uint32_t pos; /* Current position within the file (in bytes) */ + uint32_t len; /* Total length of the file (in bytes) */ + struct _fs_dev_file_state_t *prevOpenFile; /* The previous entry in a double-linked FILO list of open files */ + struct _fs_dev_file_state_t *nextOpenFile; /* The next entry in a double-linked FILO list of open files */ +} fs_dev_file_state_t; + +typedef struct _fs_dev_dir_entry_t { + fs_dev_private_t *dev; + int dirHandle; +} fs_dev_dir_entry_t; + +static fs_dev_private_t *fs_dev_get_device_data(const char *path) +{ + const devoptab_t *devoptab = NULL; + char name[128] = {0}; + int i; + + /* Get the device name from the path */ + strncpy(name, path, 127); + strtok(name, ":/"); + + // Search the devoptab table for the specified device name + // NOTE: We do this manually due to a 'bug' in GetDeviceOpTab + // which ignores names with suffixes and causes names + // like "ntfs" and "ntfs1" to be seen as equals + for (i = 3; i < STD_MAX; i++) { + devoptab = devoptab_list[i]; + if (devoptab && devoptab->name) { + if (strcmp(name, devoptab->name) == 0) { + return (fs_dev_private_t *)devoptab->deviceData; + } + } + } + + return NULL; +} + +static char *fs_dev_real_path (const char *path, fs_dev_private_t *dev) +{ + /* Sanity check */ + if (!path) + return NULL; + + /* Move the path pointer to the start of the actual path */ + if (strchr(path, ':') != NULL) { + path = strchr(path, ':') + 1; + } + + int mount_len = strlen(dev->mount_path); + + char *new_name = (char*)malloc(mount_len + strlen(path) + 1); + if(new_name) { + strcpy(new_name, dev->mount_path); + strcpy(new_name + mount_len, path); + return new_name; + } + return new_name; +} + +static int fs_dev_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fileStruct; + + file->dev = dev; + /* Determine which mode the file is opened for */ + file->flags = flags; + + const char *mode_str; + + if ((flags & 0x03) == O_RDONLY) { + file->read = 1; + file->write = 0; + file->append = 0; + mode_str = "r"; + } else if ((flags & 0x03) == O_WRONLY) { + file->read = 0; + file->write = 1; + file->append = (flags & O_APPEND); + mode_str = file->append ? "a" : "w"; + } else if ((flags & 0x03) == O_RDWR) { + file->read = 1; + file->write = 1; + file->append = (flags & O_APPEND); + mode_str = file->append ? "a+" : "r+"; + } else { + r->_errno = EACCES; + return -1; + } + + int fd = -1; + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(path, dev); + if(!path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_OpenFile(dev->fsaFd, real_path, mode_str, &fd); + + free(real_path); + + if(result == 0) + { + fileStat_s stats; + result = IOSUHAX_FSA_StatFile(dev->fsaFd, fd, &stats); + if(result != 0) { + IOSUHAX_FSA_CloseFile(dev->fsaFd, fd); + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + file->fd = fd; + file->pos = 0; + file->len = stats.size; + OSUnlockMutex(dev->pMutex); + return (int)file; + } + + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; +} + + +static int fs_dev_close_r (struct _reent *r, int fd) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + int result = IOSUHAX_FSA_CloseFile(file->dev->fsaFd, file->fd); + + OSUnlockMutex(file->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static off_t fs_dev_seek_r (struct _reent *r, int fd, off_t pos, int dir) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + switch(dir) + { + case SEEK_SET: + file->pos = pos; + break; + case SEEK_CUR: + file->pos += pos; + break; + case SEEK_END: + file->pos = file->len + pos; + break; + default: + r->_errno = EINVAL; + return -1; + } + + int result = IOSUHAX_FSA_SetFilePos(file->dev->fsaFd, file->fd, file->pos); + + OSUnlockMutex(file->dev->pMutex); + + if(result == 0) + { + return file->pos; + } + + return result; +} + +static ssize_t fs_dev_write_r (struct _reent *r, int fd, const char *ptr, size_t len) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + if(!file->write) + { + r->_errno = EACCES; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + size_t done = 0; + + while(done < len) + { + size_t write_size = len - done; + + int result = IOSUHAX_FSA_WriteFile(file->dev->fsaFd, ptr + done, 0x01, write_size, file->fd, 0); + if(result < 0) + { + r->_errno = result; + break; + } + else if(result == 0) + { + if(write_size > 0) + done = 0; + break; + } + else + { + done += result; + file->pos += result; + } + } + + OSUnlockMutex(file->dev->pMutex); + return done; +} + +static ssize_t fs_dev_read_r (struct _reent *r, int fd, char *ptr, size_t len) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return 0; + } + + if(!file->read) + { + r->_errno = EACCES; + return 0; + } + + OSLockMutex(file->dev->pMutex); + + size_t done = 0; + + while(done < len) + { + size_t read_size = len - done; + + int result = IOSUHAX_FSA_ReadFile(file->dev->fsaFd, ptr + done, 0x01, read_size, file->fd, 0); + if(result < 0) + { + r->_errno = result; + done = 0; + break; + } + else if(result == 0) + { + /*! TODO: error on read_size > 0 */ + break; + } + else + { + done += result; + file->pos += result; + } + } + + OSUnlockMutex(file->dev->pMutex); + return done; +} + + +static int fs_dev_fstat_r (struct _reent *r, int fd, struct stat *st) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(file->dev->pMutex); + + /* Zero out the stat buffer */ + memset(st, 0, sizeof(struct stat)); + + fileStat_s stats; + int result = IOSUHAX_FSA_StatFile(file->dev->fsaFd, fd, &stats); + if(result != 0) { + r->_errno = result; + OSUnlockMutex(file->dev->pMutex); + return -1; + } + + st->st_mode = S_IFREG; + st->st_size = stats.size; + st->st_blocks = (stats.size + 511) >> 9; + st->st_nlink = 1; + + /* Fill in the generic entry stats */ + st->st_dev = stats.id; + st->st_uid = stats.owner_id; + st->st_gid = stats.group_id; + st->st_ino = stats.id; + st->st_atime = stats.mtime; + st->st_ctime = stats.ctime; + st->st_mtime = stats.mtime; + OSUnlockMutex(file->dev->pMutex); + return 0; +} + +static int fs_dev_ftruncate_r (struct _reent *r, int fd, off_t len) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + r->_errno = ENOTSUP; + /* TODO */ + return -1; +} + +static int fs_dev_fsync_r (struct _reent *r, int fd) +{ + fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd; + if(!file->dev) { + r->_errno = ENODEV; + return -1; + } + + r->_errno = ENOTSUP; + /* TODO */ + return -1; +} + +static int fs_dev_stat_r (struct _reent *r, const char *path, struct stat *st) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + // Zero out the stat buffer + memset(st, 0, sizeof(struct stat)); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + fileStat_s stats; + + int result = IOSUHAX_FSA_GetStat(dev->fsaFd, real_path, &stats); + + free(real_path); + + if(result < 0) { + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + + // mark root also as directory + st->st_mode = ((stats.flag & 0x80000000) || (strlen(dev->mount_path) + 1 == strlen(real_path)))? S_IFDIR : S_IFREG; + st->st_nlink = 1; + st->st_size = stats.size; + st->st_blocks = (stats.size + 511) >> 9; + // Fill in the generic entry stats + st->st_dev = stats.id; + st->st_uid = stats.owner_id; + st->st_gid = stats.group_id; + st->st_ino = stats.id; + st->st_atime = stats.mtime; + st->st_ctime = stats.ctime; + st->st_mtime = stats.mtime; + + OSUnlockMutex(dev->pMutex); + + return 0; +} + +static int fs_dev_link_r (struct _reent *r, const char *existing, const char *newLink) +{ + r->_errno = ENOTSUP; + return -1; +} + +static int fs_dev_unlink_r (struct _reent *r, const char *name) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(name); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(name, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_Remove(dev->fsaFd, real_path); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return result; +} + +static int fs_dev_chdir_r (struct _reent *r, const char *name) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(name); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(name, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_ChangeDir(dev->fsaFd, real_path); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int fs_dev_rename_r (struct _reent *r, const char *oldName, const char *newName) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(oldName); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_oldpath = fs_dev_real_path(oldName, dev); + if(!real_oldpath) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + char *real_newpath = fs_dev_real_path(newName, dev); + if(!real_newpath) { + r->_errno = ENOMEM; + free(real_oldpath); + OSUnlockMutex(dev->pMutex); + return -1; + } + + //! TODO + int result = -ENOTSUP; + + free(real_oldpath); + free(real_newpath); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; + +} + +static int fs_dev_mkdir_r (struct _reent *r, const char *path, int mode) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_MakeDir(dev->fsaFd, real_path, mode); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int fs_dev_chmod_r (struct _reent *r, const char *path, int mode) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + int result = IOSUHAX_FSA_ChangeMode(dev->fsaFd, real_path, mode); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) { + r->_errno = result; + return -1; + } + + return 0; +} + +static int fs_dev_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dev->pMutex); + + // Zero out the stat buffer + memset(buf, 0, sizeof(struct statvfs)); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return -1; + } + + uint64_t size; + + int result = IOSUHAX_FSA_GetDeviceInfo(dev->fsaFd, real_path, 0x00, (uint32_t*)&size); + + free(real_path); + + if(result < 0) { + r->_errno = result; + OSUnlockMutex(dev->pMutex); + return -1; + } + + // File system block size + buf->f_bsize = 512; + + // Fundamental file system block size + buf->f_frsize = 512; + + // Total number of blocks on file system in units of f_frsize + buf->f_blocks = size >> 9; // this is unknown + + // Free blocks available for all and for non-privileged processes + buf->f_bfree = buf->f_bavail = size >> 9; + + // Number of inodes at this point in time + buf->f_files = 0xffffffff; + + // Free inodes available for all and for non-privileged processes + buf->f_ffree = 0xffffffff; + + // File system id + buf->f_fsid = (int)dev; + + // Bit mask of f_flag values. + buf->f_flag = 0; + + // Maximum length of filenames + buf->f_namemax = 255; + + OSUnlockMutex(dev->pMutex); + + return 0; +} + +static DIR_ITER *fs_dev_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path) +{ + fs_dev_private_t *dev = fs_dev_get_device_data(path); + if(!dev) { + r->_errno = ENODEV; + return NULL; + } + + fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; + + OSLockMutex(dev->pMutex); + + char *real_path = fs_dev_real_path(path, dev); + if(!real_path) { + r->_errno = ENOMEM; + OSUnlockMutex(dev->pMutex); + return NULL; + } + + int dirHandle; + + int result = IOSUHAX_FSA_OpenDir(dev->fsaFd, real_path, &dirHandle); + + free(real_path); + + OSUnlockMutex(dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return NULL; + } + + dirIter->dev = dev; + dirIter->dirHandle = dirHandle; + + return dirState; +} + +static int fs_dev_dirclose_r (struct _reent *r, DIR_ITER *dirState) +{ + fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + int result = IOSUHAX_FSA_CloseDir(dirIter->dev->fsaFd, dirIter->dirHandle); + + OSUnlockMutex(dirIter->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static int fs_dev_dirreset_r (struct _reent *r, DIR_ITER *dirState) +{ + fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + int result = IOSUHAX_FSA_RewindDir(dirIter->dev->fsaFd, dirIter->dirHandle); + + OSUnlockMutex(dirIter->dev->pMutex); + + if(result < 0) + { + r->_errno = result; + return -1; + } + return 0; +} + +static int fs_dev_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) +{ + fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct; + if(!dirIter->dev) { + r->_errno = ENODEV; + return -1; + } + + OSLockMutex(dirIter->dev->pMutex); + + directoryEntry_s * dir_entry = malloc(sizeof(directoryEntry_s)); + + int result = IOSUHAX_FSA_ReadDir(dirIter->dev->fsaFd, dirIter->dirHandle, dir_entry); + if(result < 0) + { + free(dir_entry); + r->_errno = result; + OSUnlockMutex(dirIter->dev->pMutex); + return -1; + } + + // Fetch the current entry + strcpy(filename, dir_entry->name); + + if(st) + { + memset(st, 0, sizeof(struct stat)); + st->st_mode = (dir_entry->stat.flag & 0x80000000) ? S_IFDIR : S_IFREG; + st->st_nlink = 1; + st->st_size = dir_entry->stat.size; + st->st_blocks = (dir_entry->stat.size + 511) >> 9; + st->st_dev = dir_entry->stat.id; + st->st_uid = dir_entry->stat.owner_id; + st->st_gid = dir_entry->stat.group_id; + st->st_ino = dir_entry->stat.id; + st->st_atime = dir_entry->stat.mtime; + st->st_ctime = dir_entry->stat.ctime; + st->st_mtime = dir_entry->stat.mtime; + } + + free(dir_entry); + OSUnlockMutex(dirIter->dev->pMutex); + return 0; +} + +// NTFS device driver devoptab +static const devoptab_t devops_fs = { + NULL, /* Device name */ + sizeof (fs_dev_file_state_t), + fs_dev_open_r, + fs_dev_close_r, + fs_dev_write_r, + fs_dev_read_r, + fs_dev_seek_r, + fs_dev_fstat_r, + fs_dev_stat_r, + fs_dev_link_r, + fs_dev_unlink_r, + fs_dev_chdir_r, + fs_dev_rename_r, + fs_dev_mkdir_r, + sizeof (fs_dev_dir_entry_t), + fs_dev_diropen_r, + fs_dev_dirreset_r, + fs_dev_dirnext_r, + fs_dev_dirclose_r, + fs_dev_statvfs_r, + fs_dev_ftruncate_r, + fs_dev_fsync_r, + fs_dev_chmod_r, + NULL, /* fs_dev_fchmod_r */ + NULL /* Device data */ +}; + +static int fs_dev_add_device (const char *name, const char *mount_path, int fsaFd, int isMounted) +{ + devoptab_t *dev = NULL; + char *devname = NULL; + char *devpath = NULL; + int i; + + // Sanity check + if (!name) { + errno = EINVAL; + return -1; + } + + // Allocate a devoptab for this device + dev = (devoptab_t *) malloc(sizeof(devoptab_t) + strlen(name) + 1); + if (!dev) { + errno = ENOMEM; + return -1; + } + + // Use the space allocated at the end of the devoptab for storing the device name + devname = (char*)(dev + 1); + strcpy(devname, name); + + // create private data + fs_dev_private_t *priv = (fs_dev_private_t *)malloc(sizeof(fs_dev_private_t) + strlen(mount_path) + 1); + if(!priv) { + free(dev); + errno = ENOMEM; + return -1; + } + + devpath = (char*)(priv+1); + strcpy(devpath, mount_path); + + // setup private data + priv->mount_path = devpath; + priv->fsaFd = fsaFd; + priv->mounted = isMounted; + priv->pMutex = malloc(OS_MUTEX_SIZE); + + if(!priv->pMutex) { + free(dev); + free(priv); + errno = ENOMEM; + return -1; + } + + OSInitMutex(priv->pMutex); + + // Setup the devoptab + memcpy(dev, &devops_fs, sizeof(devoptab_t)); + dev->name = devname; + dev->deviceData = priv; + + // Add the device to the devoptab table (if there is a free slot) + for (i = 3; i < STD_MAX; i++) { + if (devoptab_list[i] == devoptab_list[0]) { + devoptab_list[i] = dev; + return 0; + } + } + + // failure, free all memory + free(priv); + free(dev); + + // If we reach here then there are no free slots in the devoptab table for this device + errno = EADDRNOTAVAIL; + return -1; +} + +static int fs_dev_remove_device (const char *path) +{ + const devoptab_t *devoptab = NULL; + char name[128] = {0}; + int i; + + // Get the device name from the path + strncpy(name, path, 127); + strtok(name, ":/"); + + // Find and remove the specified device from the devoptab table + // NOTE: We do this manually due to a 'bug' in RemoveDevice + // which ignores names with suffixes and causes names + // like "ntfs" and "ntfs1" to be seen as equals + for (i = 3; i < STD_MAX; i++) { + devoptab = devoptab_list[i]; + if (devoptab && devoptab->name) { + if (strcmp(name, devoptab->name) == 0) { + devoptab_list[i] = devoptab_list[0]; + + if(devoptab->deviceData) + { + fs_dev_private_t *priv = (fs_dev_private_t *)devoptab->deviceData; + + if(priv->mounted) + IOSUHAX_FSA_Unmount(priv->fsaFd, priv->mount_path, 2); + + if(priv->pMutex) + free(priv->pMutex); + free(devoptab->deviceData); + } + + free((devoptab_t*)devoptab); + return 0; + } + } + } + + return -1; +} + +int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path) +{ + int isMounted = 0; + + if(dev_path) + { + isMounted = 1; + + int res = IOSUHAX_FSA_Mount(fsaFd, dev_path, mount_path, 2, 0, 0); + if(res != 0) + { + return res; + } + } + + return fs_dev_add_device(virt_name, mount_path, fsaFd, isMounted); +} + +int unmount_fs(const char *virt_name) +{ + return fs_dev_remove_device(virt_name); +} diff --git a/deps/libiosuhax/iosuhax_devoptab.h b/deps/libiosuhax/iosuhax_devoptab.h new file mode 100644 index 0000000000..2c7d5d227c --- /dev/null +++ b/deps/libiosuhax/iosuhax_devoptab.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2015 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef __IOSUHAX_DEVOPTAB_H_ +#define __IOSUHAX_DEVOPTAB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//! virtual name example: sd or odd (for sd:/ or odd:/ access) +//! fsaFd: fd received by IOSUHAX_FSA_Open(); +//! dev_path: (optional) if a device should be mounted to the mount_path. If NULL no IOSUHAX_FSA_Mount is not executed. +//! mount_path: path to map to virtual device name +int mount_fs(const char *virt_name, int fsaFd, const char *dev_path, const char *mount_path); +int unmount_fs(const char *virt_name); + +#ifdef __cplusplus +} +#endif + +#endif // __IOSUHAX_DEVOPTAB_H_ diff --git a/deps/libiosuhax/iosuhax_disc_interface.c b/deps/libiosuhax/iosuhax_disc_interface.c new file mode 100644 index 0000000000..90c206df87 --- /dev/null +++ b/deps/libiosuhax/iosuhax_disc_interface.c @@ -0,0 +1,262 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include +#include +#include "iosuhax.h" +#include "iosuhax_disc_interface.h" + +#define FSA_REF_SD 0x01 +#define FSA_REF_USB 0x02 + +static int initialized = 0; + +static int fsaFdSd = 0; +static int fsaFdUsb = 0; +static int sdioFd = 0; +static int usbFd = 0; + +static void IOSUHAX_disc_io_initialize(void) +{ + if(initialized == 0) + { + initialized = 1; + fsaFdSd = -1; + fsaFdUsb = -1; + sdioFd = -1; + usbFd = -1; + } +} + +static bool IOSUHAX_disc_io_fsa_open(int fsaFd) +{ + IOSUHAX_disc_io_initialize(); + + if(IOSUHAX_Open(NULL) < 0) + return false; + + if(fsaFd == FSA_REF_SD) + { + if(fsaFdSd < 0) + { + fsaFdSd = IOSUHAX_FSA_Open(); + } + + if(fsaFdSd >= 0) + return true; + } + else if(fsaFd == FSA_REF_USB) + { + if(fsaFdUsb < 0) + { + fsaFdUsb = IOSUHAX_FSA_Open(); + } + + if(fsaFdUsb >= 0) + return true; + } + + return false; +} + +static void IOSUHAX_disc_io_fsa_close(int fsaFd) +{ + if(fsaFd == FSA_REF_SD) + { + if(fsaFdSd >= 0) + { + IOSUHAX_FSA_Close(fsaFdSd); + fsaFdSd = -1; + } + } + else if(fsaFd == FSA_REF_USB) + { + if(fsaFdUsb >= 0) + { + IOSUHAX_FSA_Close(fsaFdUsb); + fsaFdUsb = -1; + } + } +} + +static bool IOSUHAX_sdio_startup(void) +{ + if(!IOSUHAX_disc_io_fsa_open(FSA_REF_SD)) + return false; + + if(sdioFd < 0) + { + int res = IOSUHAX_FSA_RawOpen(fsaFdSd, "/dev/sdcard01", &sdioFd); + if(res < 0) + { + IOSUHAX_disc_io_fsa_close(FSA_REF_SD); + sdioFd = -1; + } + } + + return (sdioFd >= 0); +} + +static bool IOSUHAX_sdio_isInserted(void) +{ + //! TODO: check for SD card inserted with IOSUHAX_FSA_GetDeviceInfo() + return initialized && (fsaFdSd >= 0) && (sdioFd >= 0); +} + +static bool IOSUHAX_sdio_clearStatus(void) +{ + return true; +} + +static bool IOSUHAX_sdio_shutdown(void) +{ + if(!IOSUHAX_sdio_isInserted()) + return false; + + IOSUHAX_FSA_RawClose(fsaFdSd, sdioFd); + IOSUHAX_disc_io_fsa_close(FSA_REF_SD); + sdioFd = -1; + return true; +} + +static bool IOSUHAX_sdio_readSectors(uint32_t sector, uint32_t numSectors, void* buffer) +{ + if(!IOSUHAX_sdio_isInserted()) + return false; + + int res = IOSUHAX_FSA_RawRead(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); + if(res < 0) + { + return false; + } + + return true; +} + +static bool IOSUHAX_sdio_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer) +{ + if(!IOSUHAX_sdio_isInserted()) + return false; + + int res = IOSUHAX_FSA_RawWrite(fsaFdSd, buffer, 512, numSectors, sector, sdioFd); + if(res < 0) + { + return false; + } + + return true; +} + +const DISC_INTERFACE IOSUHAX_sdio_disc_interface = +{ + DEVICE_TYPE_WII_U_SD, + FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_SD, + IOSUHAX_sdio_startup, + IOSUHAX_sdio_isInserted, + IOSUHAX_sdio_readSectors, + IOSUHAX_sdio_writeSectors, + IOSUHAX_sdio_clearStatus, + IOSUHAX_sdio_shutdown +}; + +static bool IOSUHAX_usb_startup(void) +{ + if(!IOSUHAX_disc_io_fsa_open(FSA_REF_USB)) + return false; + + if(usbFd < 0) + { + int res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb01", &usbFd); + if(res < 0) + { + res = IOSUHAX_FSA_RawOpen(fsaFdUsb, "/dev/usb02", &usbFd); + if(res < 0) + { + IOSUHAX_disc_io_fsa_close(FSA_REF_USB); + usbFd = -1; + } + } + } + return (usbFd >= 0); +} + +static bool IOSUHAX_usb_isInserted(void) +{ + return initialized && (fsaFdUsb >= 0) && (usbFd >= 0); +} + +static bool IOSUHAX_usb_clearStatus(void) +{ + return true; +} + +static bool IOSUHAX_usb_shutdown(void) +{ + if(!IOSUHAX_usb_isInserted()) + return false; + + IOSUHAX_FSA_RawClose(fsaFdUsb, usbFd); + IOSUHAX_disc_io_fsa_close(FSA_REF_USB); + usbFd = -1; + return true; +} + +static bool IOSUHAX_usb_readSectors(uint32_t sector, uint32_t numSectors, void* buffer) +{ + if(!IOSUHAX_usb_isInserted()) + return false; + + int res = IOSUHAX_FSA_RawRead(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); + if(res < 0) + { + return false; + } + + return true; +} + +static bool IOSUHAX_usb_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer) +{ + if(!IOSUHAX_usb_isInserted()) + return false; + + int res = IOSUHAX_FSA_RawWrite(fsaFdUsb, buffer, 512, numSectors, sector, usbFd); + if(res < 0) + { + return false; + } + + return true; +} + +const DISC_INTERFACE IOSUHAX_usb_disc_interface = +{ + DEVICE_TYPE_WII_U_USB, + FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_USB, + IOSUHAX_usb_startup, + IOSUHAX_usb_isInserted, + IOSUHAX_usb_readSectors, + IOSUHAX_usb_writeSectors, + IOSUHAX_usb_clearStatus, + IOSUHAX_usb_shutdown +}; diff --git a/deps/libiosuhax/iosuhax_disc_interface.h b/deps/libiosuhax/iosuhax_disc_interface.h new file mode 100644 index 0000000000..0ce479547b --- /dev/null +++ b/deps/libiosuhax/iosuhax_disc_interface.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef _IOSUHAX_DISC_INTERFACE_H_ +#define _IOSUHAX_DISC_INTERFACE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEVICE_TYPE_WII_U_SD (('W'<<24)|('U'<<16)|('S'<<8)|'D') +#define DEVICE_TYPE_WII_U_USB (('W'<<24)|('U'<<16)|('S'<<8)|'B') +#define FEATURE_WII_U_SD 0x00001000 +#define FEATURE_WII_U_USB 0x00002000 + +#ifndef OGC_DISC_IO_INCLUDE +typedef uint32_t sec_t; + +#define FEATURE_MEDIUM_CANREAD 0x00000001 +#define FEATURE_MEDIUM_CANWRITE 0x00000002 + +typedef bool (* FN_MEDIUM_STARTUP)(void) ; +typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; +typedef bool (* FN_MEDIUM_READSECTORS)(uint32_t sector, uint32_t numSectors, void* buffer) ; +typedef bool (* FN_MEDIUM_WRITESECTORS)(uint32_t sector, uint32_t numSectors, const void* buffer) ; +typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; +typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; + +struct DISC_INTERFACE_STRUCT { + unsigned long ioType ; + unsigned long features ; + FN_MEDIUM_STARTUP startup ; + FN_MEDIUM_ISINSERTED isInserted ; + FN_MEDIUM_READSECTORS readSectors ; + FN_MEDIUM_WRITESECTORS writeSectors ; + FN_MEDIUM_CLEARSTATUS clearStatus ; + FN_MEDIUM_SHUTDOWN shutdown ; +} ; + +typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE ; +#endif + +extern const DISC_INTERFACE IOSUHAX_sdio_disc_interface; +extern const DISC_INTERFACE IOSUHAX_usb_disc_interface; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/deps/libiosuhax/os_functions.h b/deps/libiosuhax/os_functions.h new file mode 100644 index 0000000000..5f5d3a1865 --- /dev/null +++ b/deps/libiosuhax/os_functions.h @@ -0,0 +1,44 @@ +#ifndef __OS_FUNCTIONS_H_ +#define __OS_FUNCTIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define OS_MUTEX_SIZE 44 + +#ifndef __WUT__ +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Mutex functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern void (* OSInitMutex)(void* mutex); +extern void (* OSLockMutex)(void* mutex); +extern void (* OSUnlockMutex)(void* mutex); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! IOS function +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int (*IOS_Ioctl)(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); +extern int (*IOS_Open)(char *path, unsigned int mode); +extern int (*IOS_Close)(int fd); +#else +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! Mutex functions +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern void OSInitMutex(void* mutex); +extern void OSLockMutex(void* mutex); +extern void OSUnlockMutex(void* mutex); + +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//! IOS function +//!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +extern int IOS_Ioctl(int fd, unsigned int request, void *input_buffer,unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len); +extern int IOS_Open(char *path, unsigned int mode); +extern int IOS_Close(int fd); +#endif // __WUT__ + +#ifdef __cplusplus +} +#endif + +#endif // __OS_FUNCTIONS_H_ diff --git a/deps/stb/stb_truetype.h b/deps/stb/stb_truetype.h index 4e1b8a97e7..13bb283f16 100644 --- a/deps/stb/stb_truetype.h +++ b/deps/stb/stb_truetype.h @@ -2428,8 +2428,9 @@ STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); if (windings) { diff --git a/dist-scripts/dist-cores.sh b/dist-scripts/dist-cores.sh index 0f10e57e95..7d9b957556 100755 --- a/dist-scripts/dist-cores.sh +++ b/dist-scripts/dist-cores.sh @@ -73,6 +73,7 @@ elif [ $PLATFORM = "dex-ps3" ] ; then platform=ps3 SALAMANDER=yes EXT=a +OPTS=DEX_BUILD=1 EXE_PATH=${CELL_SDK}/host-win32/bin MAKE_FSELF_NPDRM=${EXE_PATH}/make_fself_npdrm.exe @@ -84,6 +85,7 @@ elif [ $PLATFORM = "cex-ps3" ]; then platform=ps3 SALAMANDER=yes EXT=a +OPTS=CEX_BUILD=1 EXE_PATH=${CELL_SDK}/host-win32/bin SCETOOL_PATH=${PS3TOOLS_PATH}/scetool/scetool.exe @@ -98,6 +100,7 @@ elif [ $PLATFORM = "ode-ps3" ]; then platform=ps3 SALAMANDER=yes EXT=a +OPTS=ODE_BUILD=1 EXE_PATH=${CELL_SDK}/host-win32/bin GENPS3ISO_PATH=${PS3TOOLS_PATH}/ODE/genps3iso_v2.5 @@ -124,7 +127,7 @@ fi # Compile Salamander core if [ $SALAMANDER = "yes" ]; then - make -C ../ -f Makefile.${platform}.salamander || exit 1 + make -C ../ -f Makefile.${platform}.salamander $OPTS || exit 1 if [ $PLATFORM = "psp1" ] ; then mv -f ../EBOOT.PBP ../pkg/${platform}/EBOOT.PBP fi @@ -193,16 +196,16 @@ for f in `ls -v *_${platform}.${EXT}`; do # Compile core if [ $MAKEFILE_GRIFFIN = "yes" ]; then - make -C ../ -f Makefile.griffin platform=${platform} $whole_archive $big_stack -j3 || exit 1 + make -C ../ -f Makefile.griffin $OPTS platform=${platform} $whole_archive $big_stack -j3 || exit 1 elif [ $PLATFORM = "emscripten" ]; then echo "BUILD COMMAND: make -C ../ -f Makefile.emscripten PTHREAD=$pthread ASYNC=$async LTO=$lto -j7 TARGET=${name}_libretro.js" - make -C ../ -f Makefile.emscripten PTHREAD=$pthread ASYNC=$async LTO=$lto -j7 TARGET=${name}_libretro.js || exit 1 + make -C ../ -f Makefile.emscripten $OPTS PTHREAD=$pthread ASYNC=$async LTO=$lto -j7 TARGET=${name}_libretro.js || exit 1 elif [ $PLATFORM = "unix" ]; then make -C ../ -f Makefile LINK=g++ $whole_archive $big_stack -j3 || exit 1 elif [ $PLATFORM = "ctr" ]; then - make -C ../ -f Makefile.${platform} LIBRETRO=$name $whole_archive $big_stack -j3 || exit 1 + make -C ../ -f Makefile.${platform} $OPTS LIBRETRO=$name $whole_archive $big_stack -j3 || exit 1 else - make -C ../ -f Makefile.${platform} $whole_archive $big_stack -j3 || exit 1 + make -C ../ -f Makefile.${platform} $OPTS $whole_archive $big_stack -j3 || exit 1 fi # Do manual executable step @@ -354,17 +357,20 @@ fi # Packaging if [ $PLATFORM = "dex-ps3" ] ; then + rsync -av ../pkg/${platform}/SSNE10000/USRDIR/cores/*.SELF ../pkg/${platform}/${PLATFORM}/ $MAKE_FSELF_NPDRM -c ../retroarch-salamander_${platform}.elf ../pkg/${platform}/SSNE10000/USRDIR/EBOOT.BIN rm -rf ../retroarch-salamander_${platform}.elf $MAKE_PACKAGE_NPDRM ../pkg/${platform}_dex/package.conf ../pkg/${platform}/SSNE10000 mv UP0001-SSNE10000_00-0000000000000001.pkg ../pkg/${platform}/RetroArch.PS3.DEX.PS3.pkg elif [ $PLATFORM = "cex-ps3" ] ; then + rsync -av ../pkg/${platform}/SSNE10000/USRDIR/cores/*.SELF ../pkg/${platform}/${PLATFORM}/ $SCETOOL_PATH $SCETOOL_FLAGS_EBOOT ../retroarch-salamander_${platform}.elf ../pkg/${platform}/SSNE10000/USRDIR/EBOOT.BIN rm -rf ../retroarch-salamander_${platform}.elf (cd ../tools/ps3/ps3py && python2 setup.py build) find ../tools/ps3/ps3py/build -name '*.dll' -exec cp {} ../tools/ps3/ps3py \; ../tools/ps3/ps3py/pkg.py --contentid UP0001-SSNE10000_00-0000000000000001 ../pkg/${platform}/SSNE10000/ ../pkg/${platform}/RetroArch.PS3.CEX.PS3.pkg elif [ $PLATFORM = "ode-ps3" ] ; then + rsync -av ../pkg/${platform}_iso/PS3_GAME/USRDIR/cores/*.SELF ../pkg/${platform}/${PLATFORM}/ $SCETOOL_PATH $SCETOOL_FLAGS_ODE ../retroarch-salamander_${platform}.elf ../pkg/${platform}_iso/PS3_GAME/USRDIR/EBOOT.BIN rm -rf ../retroarch-salamander_${platform}.elf diff --git a/frontend/drivers/platform_ctr.c b/frontend/drivers/platform_ctr.c index 015d7e0ae4..1aeee71a80 100644 --- a/frontend/drivers/platform_ctr.c +++ b/frontend/drivers/platform_ctr.c @@ -49,7 +49,7 @@ #endif static enum frontend_fork ctr_fork_mode = FRONTEND_FORK_NONE; -static const char* elf_path_cst = "sdmc:/retroarch/test.3dsx"; +static const char* elf_path_cst = "sdmc:/retroarch/test.3dsx"; static void frontend_ctr_get_environment_settings(int *argc, char *argv[], void *args, void *params_data) @@ -151,7 +151,7 @@ static void frontend_ctr_exec(const char *path, bool should_load_game) DEBUG_STR(path); strlcpy(param.args, elf_path_cst, sizeof(param.args)); - len = strlen(param.args) + 1; + len = strlen(param.args) + 1; param.argc = 1; RARCH_LOG("Attempt to load core: [%s].\n", path); @@ -172,11 +172,13 @@ static void frontend_ctr_exec(const char *path, bool should_load_game) } else { - u32 app_ID_low; char app_ID_str[11]; - FILE* fp = fopen(path, "rb"); + u32 app_ID_low = 0; + FILE* fp = fopen(path, "rb"); size_t bytes_read = fread(app_ID_str, 1, sizeof(app_ID_str), fp); + fclose(fp); + if(bytes_read <= 0) { RARCH_LOG("error reading APP_ID from: [%s].\n", path); diff --git a/frontend/drivers/platform_ps3.c b/frontend/drivers/platform_ps3.c index 6e959f45ca..ffb573c4ab 100644 --- a/frontend/drivers/platform_ps3.c +++ b/frontend/drivers/platform_ps3.c @@ -254,6 +254,15 @@ static void frontend_ps3_get_environment_settings(int *argc, char *argv[], fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_PLAYLIST], g_defaults.dirs[DEFAULT_DIR_CORE], "playlists", sizeof(g_defaults.dirs[DEFAULT_DIR_PLAYLIST])); + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS], + g_defaults.dirs[DEFAULT_DIR_CORE], + "downloads", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS])); + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CHEATS], + g_defaults.dirs[DEFAULT_DIR_CORE], "cheats", + sizeof(g_defaults.dirs[DEFAULT_DIR_CHEATS])); + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG], + g_defaults.dirs[DEFAULT_DIR_CORE], + "autoconfig", sizeof(g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG])); } #ifndef IS_SALAMANDER diff --git a/frontend/drivers/platform_wii.c b/frontend/drivers/platform_wii.c index 51b0d9c148..d29b890163 100644 --- a/frontend/drivers/platform_wii.c +++ b/frontend/drivers/platform_wii.c @@ -124,8 +124,8 @@ static void dol_copy_argv_path(const char *dolpath, const char *argpath) * heap memory and are restricted to the stack only. */ void system_exec_wii(const char *_path, bool should_load_game) { - FILE *fp; size_t size, booter_size; + FILE *fp = NULL; void *dol = NULL; char path[PATH_MAX_LENGTH] = {0}; char game_path[PATH_MAX_LENGTH] = {0}; diff --git a/frontend/drivers/platform_wiiu.c b/frontend/drivers/platform_wiiu.c index 925f820652..c616caf268 100644 --- a/frontend/drivers/platform_wiiu.c +++ b/frontend/drivers/platform_wiiu.c @@ -188,8 +188,8 @@ static void frontend_wiiu_exec(const char *path, bool should_load_game) u32 argc; char * argv[3]; char args[]; - }*param = getApplicationEndAddr(); - int len = 0; + }*param = getApplicationEndAddr(); + int len = 0; param->argc = 0; if(!path || !*path) @@ -395,7 +395,7 @@ static devoptab_t dotab_stdout = }; #endif -void SaveCallback() +void SaveCallback(void) { OSSavesDone_ReadyToRelease(); } @@ -517,7 +517,7 @@ unsigned long _times_r(struct _reent *r, struct tms *tmsbuf) return 0; } -void __eabi() +void __eabi(void) { } @@ -556,7 +556,7 @@ void someFunc(void *arg) static int mcp_hook_fd = -1; -int MCPHookOpen() +int MCPHookOpen(void) { //take over mcp thread mcp_hook_fd = IOS_Open("/dev/mcp", 0); @@ -578,7 +578,7 @@ int MCPHookOpen() return 0; } -void MCPHookClose() +void MCPHookClose(void) { if (mcp_hook_fd < 0) return; @@ -630,12 +630,14 @@ static void fsdev_exit(void) /* HBL elf entry point */ int __entry_menu(int argc, char **argv) { + int ret; + InitFunctionPointers(); memoryInitialize(); __init(); fsdev_init(); - int ret = main(argc, argv); + ret = main(argc, argv); fsdev_exit(); __fini(); @@ -654,9 +656,11 @@ void _start(int argc, char **argv) fsdev_exit(); -/* TODO: fix elf2rpl so it doesn't error with "Could not find matching symbol - for relocation" then uncomment this */ -// __fini(); + /* TODO: fix elf2rpl so it doesn't error with "Could not find matching symbol + for relocation" then uncomment this */ +#if 0 + __fini(); +#endif memoryRelease(); SYSRelaunchTitle(0, 0); exit(0); diff --git a/gfx/common/win32_common.c b/gfx/common/win32_common.c index 766838e671..b4d13a401b 100644 --- a/gfx/common/win32_common.c +++ b/gfx/common/win32_common.c @@ -86,8 +86,8 @@ bool g_restore_desktop = false; static bool doubleclick_on_titlebar = false; bool g_inited = false; static bool g_quit = false; -static unsigned g_pos_x = CW_USEDEFAULT; -static unsigned g_pos_y = CW_USEDEFAULT; +static int g_pos_x = CW_USEDEFAULT; +static int g_pos_y = CW_USEDEFAULT; static void *curD3D = NULL; ui_window_win32_t main_window; @@ -513,7 +513,11 @@ static LRESULT CALLBACK WndProcCommon(bool *quit, HWND hwnd, UINT message, case WM_QUIT: { WINDOWPLACEMENT placement; + memset(&placement, 0, sizeof(placement)); + placement.length = sizeof(placement); + GetWindowPlacement(main_window.hwnd, &placement); + g_pos_x = placement.rcNormalPosition.left; g_pos_y = placement.rcNormalPosition.top; g_quit = true; diff --git a/gfx/common/x11_common.c b/gfx/common/x11_common.c index 75095a5c2a..d3f4d72eb1 100644 --- a/gfx/common/x11_common.c +++ b/gfx/common/x11_common.c @@ -109,7 +109,7 @@ void x11_show_mouse(Display *dpy, Window win, bool state) void x11_windowed_fullscreen(Display *dpy, Window win) { - XEvent xev = {0}; + XEvent xev = {0}; XA_NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", False); XA_NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); @@ -132,7 +132,7 @@ void x11_windowed_fullscreen(Display *dpy, Window win) void x11_move_window(Display *dpy, Window win, int x, int y, unsigned width, unsigned height) { - XEvent xev = {0}; + XEvent xev = {0}; XA_NET_MOVERESIZE_WINDOW = XInternAtom(dpy, "_NET_MOVERESIZE_WINDOW", False); @@ -162,9 +162,9 @@ static void x11_set_window_class(Display *dpy, Window win) static void x11_set_window_pid(Display *dpy, Window win) { - long scret; - char *hostname; - pid_t pid = getpid(); + long scret = 0; + char *hostname = NULL; + pid_t pid = getpid(); XChangeProperty(dpy, win, XInternAtom(dpy, "_NET_WM_PID", False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1); @@ -238,9 +238,9 @@ static bool get_video_mode(video_frame_info_t *video_info, Display *dpy, unsigned width, unsigned height, XF86VidModeModeInfo *mode, XF86VidModeModeInfo *desktop_mode) { - float refresh_mod; int i, num_modes = 0; bool ret = false; + float refresh_mod = 0.0f; float minimum_fps_diff = 0.0f; XF86VidModeModeInfo **modes = NULL; @@ -386,15 +386,15 @@ bool x11_get_metrics(void *data, static void x11_handle_key_event(XEvent *event, XIC ic, bool filter) { int i; - unsigned key; uint32_t chars[32]; + unsigned key = 0; uint16_t mod = 0; unsigned state = event->xkey.state; - bool down = event->type == KeyPress; - int num = 0; - KeySym keysym = 0; + bool down = event->type == KeyPress; + int num = 0; + KeySym keysym = 0; - chars[0] = '\0'; + chars[0] = '\0'; if (!filter) { diff --git a/gfx/display_servers/dispserv_win32.c b/gfx/display_servers/dispserv_win32.c index 8165d9e3bf..82272a9e6a 100644 --- a/gfx/display_servers/dispserv_win32.c +++ b/gfx/display_servers/dispserv_win32.c @@ -28,6 +28,9 @@ static void* win32_display_server_init(void) { dispserv_win32_t *dispserv = (dispserv_win32_t*)calloc(1, sizeof(*dispserv)); + if (!dispserv) + return NULL; + return dispserv; } @@ -38,17 +41,17 @@ static void win32_display_server_destroy(void) static bool win32_set_window_opacity(void *data, unsigned opacity) { - HWND hwnd = win32_get_window(); + HWND hwnd = win32_get_window(); dispserv_win32_t *serv = (dispserv_win32_t*)data; - serv->opacity = opacity; + serv->opacity = opacity; #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* Set window transparency on Windows 2000 and above */ - return SetLayeredWindowAttributes(hwnd, 0, (255 * opacity) / 100, LWA_ALPHA); -#else - return false; + if (SetLayeredWindowAttributes(hwnd, 0, (255 * opacity) / 100, LWA_ALPHA)) + return true; #endif + return false; } const video_display_server_t dispserv_win32 = { diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index 1d53ca9052..8fa795537a 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -28,6 +28,9 @@ static void* x11_display_server_init(void) { dispserv_x11_t *dispserv = (dispserv_x11_t*)calloc(1, sizeof(*dispserv)); + if (!dispserv) + return NULL; + return dispserv; } @@ -39,13 +42,13 @@ static void x11_display_server_destroy(void) static bool x11_set_window_opacity(void *data, unsigned opacity) { dispserv_x11_t *serv = (dispserv_x11_t*)data; - Atom net_wm_opacity = XInternAtom(g_x11_dpy, "_NET_WM_WINDOW_OPACITY", False); - Atom cardinal = XInternAtom(g_x11_dpy, "CARDINAL", False); + Atom net_wm_opacity = XInternAtom(g_x11_dpy, "_NET_WM_WINDOW_OPACITY", False); + Atom cardinal = XInternAtom(g_x11_dpy, "CARDINAL", False); settings_t *settings = config_get_ptr(); - serv->opacity = opacity; + serv->opacity = opacity; - opacity = opacity * ((unsigned)-1 / 100.0); + opacity = opacity * ((unsigned)-1 / 100.0); if (opacity == (unsigned)-1) XDeleteProperty(g_x11_dpy, g_x11_win, net_wm_opacity); diff --git a/gfx/drivers/ctr_gfx.c b/gfx/drivers/ctr_gfx.c index 720fac0834..6f1931f6ac 100644 --- a/gfx/drivers/ctr_gfx.c +++ b/gfx/drivers/ctr_gfx.c @@ -238,7 +238,7 @@ static void ctr_lcd_aptHook(APT_HookType hook, void* param) CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 0 | CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 4, sizeof(ctr_vertex_t)); - GPUCMD_Finalize(); + GPU_Finalize(); ctrGuFlushAndRun(true); gspWaitForEvent(GSPGPU_EVENT_P3D, false); ctr->p3d_event_pending = false; @@ -407,7 +407,7 @@ static void* ctr_init(const video_info_t* video, CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 0 | CTRGU_ATTRIBFMT(GPU_SHORT, 4) << 4, sizeof(ctr_vertex_t)); - GPUCMD_Finalize(); + GPU_Finalize(); ctrGuFlushAndRun(true); ctr->p3d_event_pending = true; @@ -779,7 +779,7 @@ static bool ctr_frame(void* data, const void* frame, #endif GPU_FinishDrawing(); - GPUCMD_Finalize(); + GPU_Finalize(); ctrGuFlushAndRun(true); ctrGuDisplayTransfer(true, ctr->drawbuffers.top.left, diff --git a/gfx/font_driver.c b/gfx/font_driver.c index 61969afe56..85f1bf43c3 100644 --- a/gfx/font_driver.c +++ b/gfx/font_driver.c @@ -34,7 +34,7 @@ static const font_renderer_driver_t *font_backends[] = { &coretext_font_renderer, #endif #ifdef HAVE_STB_FONT -#if defined(VITA) || defined(WIIU) || defined(ANDROID) || defined(_WIN32) && !defined(_XBOX) && !defined(_MSC_VER) || defined(_WIN32) && !defined(_XBOX) && defined(_MSC_VER) && _MSC_VER > 1400 +#if defined(VITA) || defined(WIIU) || defined(ANDROID) || defined(_WIN32) && !defined(_XBOX) && !defined(_MSC_VER) || (defined(_WIN32) && !defined(_XBOX) && defined(_MSC_VER) && _MSC_VER > 1400) || defined(__CELLOS_LV2__) &stb_unicode_font_renderer, #else &stb_font_renderer, diff --git a/gfx/video_display_server.c b/gfx/video_display_server.c index 22f481ce45..c7e7dfd06d 100644 --- a/gfx/video_display_server.c +++ b/gfx/video_display_server.c @@ -29,16 +29,16 @@ void* video_display_server_init(void) switch (type) { -#if defined(_WIN32) && !defined(_XBOX) case RARCH_DISPLAY_WIN32: +#if defined(_WIN32) && !defined(_XBOX) current_display_server = &dispserv_win32; - break; #endif -#if defined(HAVE_X11) + break; case RARCH_DISPLAY_X11: +#if defined(HAVE_X11) current_display_server = &dispserv_x11; - break; #endif + break; default: current_display_server = &dispserv_null; break; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 0302d7008b..da87988eb9 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -955,7 +955,7 @@ static bool video_driver_init_internal(bool *video_is_threaded) video_driver_set_aspect_ratio_value( aspectratio_lut[settings->uints.video_aspect_ratio_idx].value); - if (settings->bools.video_fullscreen) + if (settings->bools.video_fullscreen|| retroarch_is_forced_fullscreen()) { width = settings->uints.video_fullscreen_x; height = settings->uints.video_fullscreen_y; @@ -999,7 +999,7 @@ static bool video_driver_init_internal(bool *video_is_threaded) video.width = width; video.height = height; - video.fullscreen = settings->bools.video_fullscreen; + video.fullscreen = settings->bools.video_fullscreen || retroarch_is_forced_fullscreen(); video.vsync = settings->bools.video_vsync && !rarch_ctl(RARCH_CTL_IS_NONBLOCK_FORCED, NULL); video.force_aspect = settings->bools.video_force_aspect; video.font_enable = settings->bools.video_font_enable; @@ -2515,7 +2515,7 @@ void video_driver_build_info(video_frame_info_t *video_info) video_info->post_filter_record = settings->bools.video_post_filter_record; video_info->max_swapchain_images = settings->uints.video_max_swapchain_images; video_info->windowed_fullscreen = settings->bools.video_windowed_fullscreen; - video_info->fullscreen = settings->bools.video_fullscreen; + video_info->fullscreen = settings->bools.video_fullscreen || retroarch_is_forced_fullscreen(); video_info->monitor_index = settings->uints.video_monitor_index; video_info->shared_context = settings->bools.video_shared_context; diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 991e2768a5..29462ea91e 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -587,7 +587,6 @@ bool video_shader_resolve_parameters(config_file_t *conf, free(line); intfstream_close(file); - free(file); } if (conf && !video_shader_resolve_current_parameters(conf, shader)) diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index 90cb9cf06b..e79fa9a82c 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -84,6 +84,7 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn, { "Wii U GC Controller Adapter", 1406, 823, &pad_connection_wiiugca }, { "PS2/PSX Controller Adapter", 2064, 1, &pad_connection_ps2adapter }, { "PSX to PS3 Controller Adapter", 2064, 3, &pad_connection_psxadapter }, + { "Mayflash DolphinBar", 1406, 774, &pad_connection_wii }, { 0, 0} }; joypad_connection_t *s = NULL; diff --git a/input/drivers/android_input.c b/input/drivers/android_input.c index 2eb4884bce..a4b12ec11f 100644 --- a/input/drivers/android_input.c +++ b/input/drivers/android_input.c @@ -1429,11 +1429,6 @@ static int16_t android_input_state(void *data, return 0; } -static bool android_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static void android_input_free_input(void *data) { android_input_t *android = (android_input_t*)data; @@ -1587,7 +1582,6 @@ input_driver_t input_android = { android_input_init, android_input_poll, android_input_state, - android_input_meta_key_pressed, android_input_free_input, android_input_set_sensor_state, android_input_get_sensor_input, diff --git a/input/drivers/cocoa_input.c b/input/drivers/cocoa_input.c index f14932ab23..da33ccef83 100644 --- a/input/drivers/cocoa_input.c +++ b/input/drivers/cocoa_input.c @@ -328,11 +328,6 @@ static int16_t cocoa_input_state(void *data, return 0; } -static bool cocoa_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static void cocoa_input_free(void *data) { unsigned i; @@ -426,7 +421,6 @@ input_driver_t input_cocoa = { cocoa_input_init, cocoa_input_poll, cocoa_input_state, - cocoa_input_meta_key_pressed, cocoa_input_free, NULL, NULL, diff --git a/input/drivers/ctr_input.c b/input/drivers/ctr_input.c index 359dc9f5eb..90702187d4 100644 --- a/input/drivers/ctr_input.c +++ b/input/drivers/ctr_input.c @@ -35,8 +35,6 @@ typedef struct ctr_input const input_device_driver_t *joypad; } ctr_input_t; -uint64_t lifecycle_state; - static void ctr_input_poll(void *data) { ctr_input_t *ctr = (ctr_input_t*)data; @@ -92,14 +90,6 @@ static void* ctr_input_init(const char *joypad_driver) return ctr; } -static bool ctr_input_meta_key_pressed(void *data, int key) -{ - if (BIT64_GET(lifecycle_state, key)) - return true; - - return false; -} - static uint64_t ctr_input_get_capabilities(void *data) { (void)data; @@ -152,7 +142,6 @@ input_driver_t input_ctr = { ctr_input_init, ctr_input_poll, ctr_input_state, - ctr_input_meta_key_pressed, ctr_input_free_input, NULL, NULL, diff --git a/input/drivers/dinput.c b/input/drivers/dinput.c index 6550bec50e..26757500f3 100644 --- a/input/drivers/dinput.c +++ b/input/drivers/dinput.c @@ -364,11 +364,6 @@ static int16_t dinput_pressed_analog(struct dinput_input *di, return pressed_plus + pressed_minus; } -static bool dinput_meta_key_pressed(void *data, int key) -{ - return false; -} - static int16_t dinput_lightgun_aiming_state( struct dinput_input *di, unsigned idx, unsigned id ) { const int edge_detect = 32700; @@ -925,7 +920,6 @@ input_driver_t input_dinput = { dinput_init, dinput_poll, dinput_input_state, - dinput_meta_key_pressed, dinput_free, NULL, NULL, diff --git a/input/drivers/dos_input.c b/input/drivers/dos_input.c index e985d5f5b5..4c168cd5a2 100644 --- a/input/drivers/dos_input.c +++ b/input/drivers/dos_input.c @@ -86,11 +86,6 @@ static void* dos_input_init(const char *joypad_driver) return dos; } -static bool dos_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static uint64_t dos_input_get_capabilities(void *data) { uint64_t caps = 0; @@ -129,7 +124,6 @@ input_driver_t input_dos = { dos_input_init, dos_input_poll, dos_input_state, - dos_input_meta_key_pressed, dos_input_free_input, NULL, NULL, diff --git a/input/drivers/gx_input.c b/input/drivers/gx_input.c index cecbc92643..8e4c2d42a8 100644 --- a/input/drivers/gx_input.c +++ b/input/drivers/gx_input.c @@ -31,8 +31,6 @@ #define MAX_PADS 4 #endif -uint64_t lifecycle_state; - typedef struct gx_input { bool blocked; @@ -97,14 +95,6 @@ static void gx_input_poll(void *data) gx->joypad->poll(); } -static bool gx_input_meta_key_pressed(void *data, int key) -{ - if (BIT64_GET(lifecycle_state, key)) - return true; - - return false; -} - static uint64_t gx_input_get_capabilities(void *data) { (void)data; @@ -157,7 +147,6 @@ input_driver_t input_gx = { gx_input_init, gx_input_poll, gx_input_state, - gx_input_meta_key_pressed, gx_input_free_input, NULL, NULL, diff --git a/input/drivers/linuxraw_input.c b/input/drivers/linuxraw_input.c index 5c2b780e9a..72928de443 100644 --- a/input/drivers/linuxraw_input.c +++ b/input/drivers/linuxraw_input.c @@ -93,11 +93,6 @@ static int16_t linuxraw_analog_pressed(linuxraw_input_t *linuxraw, return pressed_plus + pressed_minus; } -static bool linuxraw_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static int16_t linuxraw_input_state(void *data, rarch_joypad_info_t joypad_info, const struct retro_keybind **binds, unsigned port, @@ -223,7 +218,6 @@ input_driver_t input_linuxraw = { linuxraw_input_init, linuxraw_input_poll, linuxraw_input_state, - linuxraw_input_meta_key_pressed, linuxraw_input_free, NULL, NULL, diff --git a/input/drivers/nullinput.c b/input/drivers/nullinput.c index edb3c93e3e..e449e1d7fa 100644 --- a/input/drivers/nullinput.c +++ b/input/drivers/nullinput.c @@ -43,14 +43,6 @@ static int16_t nullinput_input_state(void *data, return 0; } -static bool nullinput_input_meta_key_pressed(void *data, int key) -{ - (void)data; - (void)key; - - return false; -} - static void nullinput_input_free_input(void *data) { (void)data; @@ -100,7 +92,6 @@ input_driver_t input_null = { nullinput_input_init, nullinput_input_poll, nullinput_input_state, - nullinput_input_meta_key_pressed, nullinput_input_free_input, nullinput_set_sensor_state, NULL, diff --git a/input/drivers/ps3_input.c b/input/drivers/ps3_input.c index 8edc841960..f18c9ea327 100644 --- a/input/drivers/ps3_input.c +++ b/input/drivers/ps3_input.c @@ -179,11 +179,6 @@ static void* ps3_input_init(const char *joypad_driver) return ps3; } -static bool ps3_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static uint64_t ps3_input_get_capabilities(void *data) { (void)data; @@ -266,7 +261,6 @@ input_driver_t input_ps3 = { ps3_input_init, ps3_input_poll, ps3_input_state, - ps3_input_meta_key_pressed, ps3_input_free_input, ps3_input_set_sensor_state, NULL, diff --git a/input/drivers/psp_input.c b/input/drivers/psp_input.c index b7e2b959ae..bc0cd827c0 100644 --- a/input/drivers/psp_input.c +++ b/input/drivers/psp_input.c @@ -49,8 +49,6 @@ typedef struct psp_input const input_device_driver_t *joypad; } psp_input_t; -uint64_t lifecycle_state; - static void psp_input_poll(void *data) { psp_input_t *psp = (psp_input_t*)data; @@ -106,11 +104,6 @@ static void* psp_input_initialize(const char *joypad_driver) return psp; } -static bool psp_input_meta_key_pressed(void *data, int key) -{ - return (BIT64_GET(lifecycle_state, key)); -} - static uint64_t psp_input_get_capabilities(void *data) { (void)data; @@ -163,7 +156,6 @@ input_driver_t input_psp = { psp_input_initialize, psp_input_poll, psp_input_state, - psp_input_meta_key_pressed, psp_input_free_input, NULL, NULL, diff --git a/input/drivers/qnx_input.c b/input/drivers/qnx_input.c index 5ae1e2740d..47b663a3ae 100644 --- a/input/drivers/qnx_input.c +++ b/input/drivers/qnx_input.c @@ -803,11 +803,6 @@ static int16_t qnx_input_state(void *data, return 0; } -static bool qnx_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static void qnx_input_free_input(void *data) { if (data) @@ -853,7 +848,6 @@ input_driver_t input_qnx = { qnx_input_init, qnx_input_poll, qnx_input_state, - qnx_input_meta_key_pressed, qnx_input_free_input, NULL, NULL, diff --git a/input/drivers/rwebinput_input.c b/input/drivers/rwebinput_input.c index 3506b7e029..a795a3ff2a 100644 --- a/input/drivers/rwebinput_input.c +++ b/input/drivers/rwebinput_input.c @@ -81,13 +81,6 @@ static bool rwebinput_key_pressed_internal(void *data, int key) return ret; } -static bool rwebinput_meta_key_pressed(void *data, int key) -{ - (void)data; - (void)key; - return false; -} - static bool rwebinput_is_pressed(rwebinput_input_t *rwebinput, const struct retro_keybind *binds, unsigned id) { @@ -254,7 +247,6 @@ input_driver_t input_rwebinput = { rwebinput_input_init, rwebinput_input_poll, rwebinput_input_state, - rwebinput_meta_key_pressed, rwebinput_input_free, NULL, NULL, diff --git a/input/drivers/sdl_input.c b/input/drivers/sdl_input.c index 5376f2b9ce..707e436c54 100644 --- a/input/drivers/sdl_input.c +++ b/input/drivers/sdl_input.c @@ -89,11 +89,6 @@ static int16_t sdl_analog_pressed(sdl_input_t *sdl, const struct retro_keybind * return pressed_plus + pressed_minus; } -static bool sdl_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static int16_t sdl_joypad_device_state(sdl_input_t *sdl, rarch_joypad_info_t joypad_info, const struct retro_keybind *binds, @@ -409,7 +404,6 @@ input_driver_t input_sdl = { sdl_input_init, sdl_input_poll, sdl_input_state, - sdl_input_meta_key_pressed, sdl_input_free, NULL, NULL, diff --git a/input/drivers/udev_input.c b/input/drivers/udev_input.c index a22ba8636d..9712193161 100644 --- a/input/drivers/udev_input.c +++ b/input/drivers/udev_input.c @@ -907,11 +907,6 @@ static int16_t udev_input_state(void *data, return 0; } -static bool udev_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static void udev_input_free(void *data) { unsigned i; @@ -1160,7 +1155,6 @@ input_driver_t input_udev = { udev_input_init, udev_input_poll, udev_input_state, - udev_input_meta_key_pressed, udev_input_free, NULL, NULL, diff --git a/input/drivers/wayland_input.c b/input/drivers/wayland_input.c index 6fab41d99f..0c23db52f4 100644 --- a/input/drivers/wayland_input.c +++ b/input/drivers/wayland_input.c @@ -320,19 +320,10 @@ static void input_wl_keyboard_mapping_set_block(void *data, bool value) wl->blocked = value; } -static bool input_wl_meta_key_pressed(void *data, int key) -{ - (void)data; - (void)key; - /* FIXME: What is this supposed to do? */ - return false; -} - input_driver_t input_wayland = { NULL, input_wl_poll, input_wl_state, - input_wl_meta_key_pressed, input_wl_free, NULL, NULL, diff --git a/input/drivers/wiiu_input.c b/input/drivers/wiiu_input.c index 7bf5a752e0..8580b80d65 100644 --- a/input/drivers/wiiu_input.c +++ b/input/drivers/wiiu_input.c @@ -46,9 +46,6 @@ typedef struct wiiu_input const input_device_driver_t *joypad; } wiiu_input_t; -uint64_t lifecycle_state; - - void kb_connection_callback(KBDKeyEvent *key) { keyboardChannel = keyboardChannel + (key->channel + 0x01); @@ -200,14 +197,6 @@ static void* wiiu_input_init(const char *joypad_driver) return wiiu; } -static bool wiiu_input_meta_key_pressed(void *data, int key) -{ - if (BIT64_GET(lifecycle_state, key)) - return true; - - return false; -} - static uint64_t wiiu_input_get_capabilities(void *data) { (void)data; @@ -263,7 +252,6 @@ input_driver_t input_wiiu = { wiiu_input_init, wiiu_input_poll, wiiu_input_state, - wiiu_input_meta_key_pressed, wiiu_input_free_input, NULL, NULL, diff --git a/input/drivers/winraw_input.c b/input/drivers/winraw_input.c index 2b15c53c1b..d56deb4c75 100644 --- a/input/drivers/winraw_input.c +++ b/input/drivers/winraw_input.c @@ -762,11 +762,6 @@ static int16_t winraw_input_state(void *d, return 0; } -static bool winraw_meta_key_pressed(void *u1, int u2) -{ - return false; -} - static void winraw_free(void *d) { winraw_input_t *wr = (winraw_input_t*)d; @@ -841,7 +836,6 @@ input_driver_t input_winraw = { winraw_init, winraw_poll, winraw_input_state, - winraw_meta_key_pressed, winraw_free, NULL, NULL, diff --git a/input/drivers/x11_input.c b/input/drivers/x11_input.c index 9e357870bf..d2b1bcd9f5 100644 --- a/input/drivers/x11_input.c +++ b/input/drivers/x11_input.c @@ -179,11 +179,6 @@ static int16_t x_pressed_analog(x11_input_t *x11, return pressed_plus + pressed_minus; } -static bool x_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static int16_t x_lightgun_aiming_state( x11_input_t *x11, unsigned idx, unsigned id ) { const int edge_detect = 32700; @@ -531,7 +526,6 @@ input_driver_t input_x = { x_input_init, x_input_poll, x_input_state, - x_input_meta_key_pressed, x_input_free, NULL, NULL, diff --git a/input/drivers/xdk_xinput_input.c b/input/drivers/xdk_xinput_input.c index a603d0ae62..3d4f1363df 100644 --- a/input/drivers/xdk_xinput_input.c +++ b/input/drivers/xdk_xinput_input.c @@ -94,11 +94,6 @@ static void *xdk_input_init(const char *joypad_driver) return xdk; } -static bool xdk_input_meta_key_pressed(void *data, int key) -{ - return false; -} - static uint64_t xdk_input_get_capabilities(void *data) { (void)data; @@ -178,7 +173,6 @@ input_driver_t input_xinput = { xdk_input_init, xdk_input_poll, xdk_input_state, - xdk_input_meta_key_pressed, xdk_input_free_input, NULL, NULL, diff --git a/input/drivers/xenon360_input.c b/input/drivers/xenon360_input.c index f1c933a68e..e87d413992 100644 --- a/input/drivers/xenon360_input.c +++ b/input/drivers/xenon360_input.c @@ -90,11 +90,6 @@ static void* xenon360_input_init(const char *joypad_driver) return (void*)-1; } -static bool xenon360_input_meta_key_pressed(void *data, int key) -{ - return (state & (UINT64_C(1) << key)); -} - static uint64_t xenon360_input_get_capabilities(void *data) { uint64_t caps = 0; @@ -125,7 +120,6 @@ input_driver_t input_xenon360 = { xenon360_input_init, xenon360_input_poll, xenon360_input_state, - xenon360_input_meta_key_pressed, xenon360_input_free_input, NULL, NULL, diff --git a/input/drivers_joypad/xinput_joypad.c b/input/drivers_joypad/xinput_joypad.c index 77a9680d52..b7514cf9ac 100644 --- a/input/drivers_joypad/xinput_joypad.c +++ b/input/drivers_joypad/xinput_joypad.c @@ -475,7 +475,7 @@ static void xinput_joypad_poll(void) { if (g_xinput_states[i].connected) { - if (g_XInputGetStateEx(i, + if (g_XInputGetStateEx && g_XInputGetStateEx(i, &(g_xinput_states[i].xstate)) == ERROR_DEVICE_NOT_CONNECTED) g_xinput_states[i].connected = false; @@ -507,6 +507,9 @@ static bool xinput_joypad_rumble(unsigned pad, else if (effect == RETRO_RUMBLE_WEAK) g_xinput_rumble_states[xuser].wRightMotorSpeed = strength; + if (!g_XInputSetState) + return false; + return (g_XInputSetState(xuser, &g_xinput_rumble_states[xuser]) == 0); } diff --git a/input/input_driver.c b/input/input_driver.c index 3765d39916..3d5ee6ca73 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -233,6 +233,7 @@ static const uint8_t buttons[] = { static uint16_t input_config_vid[MAX_USERS]; static uint16_t input_config_pid[MAX_USERS]; +uint64_t lifecycle_state; char input_device_names[MAX_INPUT_DEVICES][64]; struct retro_keybind input_config_binds[MAX_USERS][RARCH_BIND_LIST_END]; struct retro_keybind input_autoconf_binds[MAX_USERS][RARCH_BIND_LIST_END]; @@ -784,6 +785,42 @@ void state_tracker_update_input(uint16_t *input1, uint16_t *input2) } } +static INLINE bool input_keys_pressed_iterate(unsigned i, + retro_bits_t* p_new_state) +{ + if ((i >= RARCH_FIRST_META_KEY) && + BIT64_GET(lifecycle_state, i) + ) + return true; + +#ifdef HAVE_OVERLAY + if (overlay_ptr && + input_overlay_key_pressed(overlay_ptr, i)) + return true; +#endif + +#ifdef HAVE_COMMAND + if (input_driver_command) + { + command_handle_t handle; + + handle.handle = input_driver_command; + handle.id = i; + + if (command_get(&handle)) + return true; + } +#endif + +#ifdef HAVE_NETWORKGAMEPAD + if (input_driver_remote && + input_remote_key_pressed(i, 0)) + return true; +#endif + + return false; +} + #ifdef HAVE_MENU /** @@ -857,9 +894,11 @@ void input_menu_keys_pressed(void *data, retro_bits_t* p_new_state) for (i = 0; i < RARCH_BIND_LIST_END; i++) { + bool bit_pressed = false; + if ( - (((!input_driver_block_libretro_input && ((i < RARCH_FIRST_META_KEY))) - || !input_driver_block_hotkey)) + (!input_driver_block_libretro_input && ((i < RARCH_FIRST_META_KEY))) + || !input_driver_block_hotkey ) { const input_device_driver_t *first = current_input->get_joypad_driver @@ -869,21 +908,20 @@ void input_menu_keys_pressed(void *data, retro_bits_t* p_new_state) for (port = 0; port < port_max; port++) { - uint64_t joykey = 0; - uint32_t joyaxis = 0; - bool pressed = false; + uint64_t joykey = 0; + uint32_t joyaxis = 0; const struct retro_keybind *mtkey = &input_config_binds[port][i]; if (!mtkey->valid) continue; - joypad_info.joy_idx = settings->uints.input_joypad_map[port]; - joypad_info.auto_binds = input_autoconf_binds[joypad_info.joy_idx]; - joypad_info.axis_threshold = input_driver_axis_threshold; + joypad_info.joy_idx = settings->uints.input_joypad_map[port]; + joypad_info.auto_binds = input_autoconf_binds[joypad_info.joy_idx]; + joypad_info.axis_threshold = input_driver_axis_threshold; - joykey = (input_config_binds[port][i].joykey != NO_BTN) + joykey = (input_config_binds[port][i].joykey != NO_BTN) ? input_config_binds[port][i].joykey : joypad_info.auto_binds[i].joykey; - joyaxis = (input_config_binds[port][i].joyaxis != AXIS_NONE) + joyaxis = (input_config_binds[port][i].joyaxis != AXIS_NONE) ? input_config_binds[port][i].joyaxis : joypad_info.auto_binds[i].joyaxis; if (sec) @@ -892,72 +930,33 @@ void input_menu_keys_pressed(void *data, retro_bits_t* p_new_state) { int16_t axis = sec->axis(joypad_info.joy_idx, joyaxis); float scaled_axis = (float)abs(axis) / 0x8000; - pressed = scaled_axis > joypad_info.axis_threshold; + bit_pressed = scaled_axis > joypad_info.axis_threshold; } else - pressed = true; + bit_pressed = true; } - if (!pressed && first) + if (!bit_pressed && first) { if ((uint16_t)joykey == NO_BTN || !first->button(joypad_info.joy_idx, (uint16_t)joykey)) { int16_t axis = first->axis(joypad_info.joy_idx, joyaxis); float scaled_axis = (float)abs(axis) / 0x8000; - pressed = scaled_axis > joypad_info.axis_threshold; + bit_pressed = scaled_axis > joypad_info.axis_threshold; } else - pressed = true; + bit_pressed = true; } - if (pressed) - { - BIT256_SET_PTR(p_new_state, i); - continue; - } + if (bit_pressed) + break; } } - if (i >= RARCH_FIRST_META_KEY) - { - if (current_input->meta_key_pressed(current_input_data, i)) - { - BIT256_SET_PTR(p_new_state, i); - continue; - } - } - -#ifdef HAVE_OVERLAY - if (overlay_ptr && input_overlay_key_pressed(overlay_ptr, i)) + if (bit_pressed || input_keys_pressed_iterate(i, p_new_state)) { BIT256_SET_PTR(p_new_state, i); - continue; } -#endif - -#ifdef HAVE_COMMAND - if (input_driver_command) - { - command_handle_t handle; - - handle.handle = input_driver_command; - handle.id = i; - - if (command_get(&handle)) - { - BIT256_SET_PTR(p_new_state, i); - continue; - } - } -#endif - -#ifdef HAVE_NETWORKGAMEPAD - if (input_driver_remote && input_remote_key_pressed(i, 0)) - { - BIT256_SET_PTR(p_new_state, i); - continue; - } -#endif } for (i = 0; i < max_users; i++) @@ -1077,6 +1076,8 @@ void input_keys_pressed(void *data, retro_bits_t* p_new_state) for (i = 0; i < RARCH_BIND_LIST_END; i++) { + bool bit_pressed = false; + if ( ((!input_driver_block_libretro_input && ((i < RARCH_FIRST_META_KEY))) || !input_driver_block_hotkey) && @@ -1084,56 +1085,15 @@ void input_keys_pressed(void *data, retro_bits_t* p_new_state) joypad_info, &binds, 0, RETRO_DEVICE_JOYPAD, 0, i) ) + bit_pressed = true; + + if (bit_pressed || input_keys_pressed_iterate(i, p_new_state)) { BIT256_SET_PTR(p_new_state, i); - continue; } - - if ((i >= RARCH_FIRST_META_KEY) && - current_input->meta_key_pressed(current_input_data, i) - ) - { - BIT256_SET_PTR(p_new_state, i); - continue; - } - -#ifdef HAVE_OVERLAY - if (overlay_ptr && - input_overlay_key_pressed(overlay_ptr, i)) - { - BIT256_SET_PTR(p_new_state, i); - continue; - } -#endif - -#ifdef HAVE_COMMAND - if (input_driver_command) - { - command_handle_t handle; - - handle.handle = input_driver_command; - handle.id = i; - - if (command_get(&handle)) - { - BIT256_SET_PTR(p_new_state, i); - continue; - } - } -#endif - -#ifdef HAVE_NETWORKGAMEPAD - if (input_driver_remote && - input_remote_key_pressed(i, 0)) - { - BIT256_SET_PTR(p_new_state, i); - continue; - } -#endif } } - void *input_driver_get_data(void) { return current_input_data; diff --git a/input/input_driver.h b/input/input_driver.h index 1f7b711917..beed89459a 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -147,8 +147,6 @@ typedef struct input_driver const struct retro_keybind **retro_keybinds, unsigned port, unsigned device, unsigned index, unsigned id); - bool (*meta_key_pressed)(void *data, int key); - /* Frees the input struct. */ void (*free)(void *data); diff --git a/input/input_overlay.c b/input/input_overlay.c index 384d589015..168c393dc1 100644 --- a/input/input_overlay.c +++ b/input/input_overlay.c @@ -43,7 +43,7 @@ typedef struct input_overlay_state int16_t analog[4]; uint32_t keys[RETROK_LAST / 32 + 1]; /* This is a bitmask of (1 << key_bind_id). */ - uint64_t buttons; + retro_bits_t buttons; } input_overlay_state_t; struct input_overlay @@ -302,17 +302,15 @@ static void input_overlay_poll( { case OVERLAY_TYPE_BUTTONS: { - uint64_t mask = desc->key_mask; + bits_or_bits(out->buttons.data, desc->button_mask.data, ARRAY_SIZE(desc->button_mask.data)); - out->buttons |= mask; - - if (mask & (UINT64_C(1) << RARCH_OVERLAY_NEXT)) + if (BIT256_GET(desc->button_mask, RARCH_OVERLAY_NEXT)) ol->next_index = desc->next_index; } break; case OVERLAY_TYPE_KEYBOARD: - if (desc->key_mask < RETROK_LAST) - OVERLAY_SET_KEY(out, desc->key_mask); + if (desc->retro_key_idx < RETROK_LAST) + OVERLAY_SET_KEY(out, desc->retro_key_idx); break; default: { @@ -338,7 +336,7 @@ static void input_overlay_poll( } } - if (!out->buttons) + if (!bits_any_set(out->buttons.data, ARRAY_SIZE(out->buttons.data))) ol->blocked = false; else if (ol->blocked) memset(out, 0, sizeof(*out)); @@ -556,12 +554,12 @@ bool input_overlay_is_alive(input_overlay_t *ol) return false; } -bool input_overlay_key_pressed(input_overlay_t *ol, int key) +bool input_overlay_key_pressed(input_overlay_t *ol, unsigned key) { input_overlay_state_t *ol_state = ol ? &ol->overlay_state : NULL; if (!ol) return false; - return (ol_state->buttons & (UINT64_C(1) << key)); + return (BIT256_GET(ol_state->buttons, key)); } /* @@ -616,12 +614,12 @@ void input_poll_overlay(input_overlay_t *ol, float opacity, unsigned analog_dpad else ol->blocked = false; - ol_state->buttons |= polled_data.buttons; + bits_or_bits(ol_state->buttons.data, polled_data.buttons.data, ARRAY_SIZE(polled_data.buttons.data)); for (j = 0; j < ARRAY_SIZE(ol_state->keys); j++) ol_state->keys[j] |= polled_data.keys[j]; - /* Fingers pressed later take prio and matched up + /* Fingers pressed later take priority and matched up * with overlay poll priorities. */ for (j = 0; j < 4; j++) if (polled_data.analog[j]) @@ -693,13 +691,13 @@ void input_poll_overlay(input_overlay_t *ol, float opacity, unsigned analog_dpad analog_y = (float)ol_state->analog[analog_base + 1] / 0x7fff; if (analog_x <= -axis_threshold) - BIT32_SET(ol_state->buttons, RETRO_DEVICE_ID_JOYPAD_LEFT); + BIT256_SET(ol_state->buttons, RETRO_DEVICE_ID_JOYPAD_LEFT); if (analog_x >= axis_threshold) - BIT32_SET(ol_state->buttons, RETRO_DEVICE_ID_JOYPAD_RIGHT); + BIT256_SET(ol_state->buttons, RETRO_DEVICE_ID_JOYPAD_RIGHT); if (analog_y <= -axis_threshold) - BIT32_SET(ol_state->buttons, RETRO_DEVICE_ID_JOYPAD_UP); + BIT256_SET(ol_state->buttons, RETRO_DEVICE_ID_JOYPAD_UP); if (analog_y >= axis_threshold) - BIT32_SET(ol_state->buttons, RETRO_DEVICE_ID_JOYPAD_DOWN); + BIT256_SET(ol_state->buttons, RETRO_DEVICE_ID_JOYPAD_DOWN); break; } @@ -767,14 +765,100 @@ void input_state_overlay(input_overlay_t *ol, int16_t *ret, * Adds inputs from current_input to the overlay, so it's displayed * returns true if an input that is pressed will change the overlay */ +static bool input_overlay_add_inputs_inner(overlay_desc_t *desc, + unsigned port, unsigned analog_dpad_mode) +{ + switch(desc->type) + { + case OVERLAY_TYPE_BUTTONS: + { + unsigned i; + unsigned id; + uint32_t bank_mask; + bool all_buttons_pressed = false; + + /*Check each bank of the mask*/ + for (i=0; ibutton_mask.data); ++i) + { + /*Get bank*/ + bank_mask = BITS_GET_ELEM(desc->button_mask,i); + id = i*32; + + /*Worth pursuing? Have we got any bits left in here?*/ + while (bank_mask) + { + /*If this bit is set then we need to query the pad + *The button must be pressed.*/ + if (bank_mask & 1) + { + /* Light up the button if pressed */ + if(input_state(port, RETRO_DEVICE_JOYPAD, 0, id)) + { + all_buttons_pressed = true; + desc->updated = true; + } + else + { + /*we need ALL of the inputs to be active*/ + all_buttons_pressed = false; + desc->updated = false; + + /*abort*/ + return false; + } + } + + bank_mask >>= 1; + ++id; + } + } + + return all_buttons_pressed; + } + + case OVERLAY_TYPE_ANALOG_LEFT: + case OVERLAY_TYPE_ANALOG_RIGHT: + { + float analog_x, analog_y; + float dx, dy; + unsigned int index = (desc->type == OVERLAY_TYPE_ANALOG_RIGHT) ? + RETRO_DEVICE_INDEX_ANALOG_RIGHT : RETRO_DEVICE_INDEX_ANALOG_LEFT; + + analog_x = input_state(port, RETRO_DEVICE_ANALOG, index, RETRO_DEVICE_ID_ANALOG_X); + analog_y = input_state(port, RETRO_DEVICE_ANALOG, index, RETRO_DEVICE_ID_ANALOG_Y); + dx = (analog_x/0x8000)*(desc->range_x/2); + dy = (analog_y/0x8000)*(desc->range_y/2); + + desc->delta_x = dx; + desc->delta_y = dy; + /*Maybe use some option here instead of 0, only display + changes greater than some magnitude. + */ + if((dx*dx) > 0 || (dy*dy) > 0) + return true; + } + break; + + case OVERLAY_TYPE_KEYBOARD: + if(input_state(port, RETRO_DEVICE_KEYBOARD, 0, desc->retro_key_idx)) + { + desc->updated = true; + return true; + } + break; + + default: + break; + } + + return false; +} + static bool input_overlay_add_inputs(input_overlay_t *ol, unsigned port, unsigned analog_dpad_mode) { unsigned i; - uint64_t mask; - int id; bool button_pressed = false; - bool current_button_pressed = false; input_overlay_state_t *ol_state = &ol->overlay_state; if(!ol_state) @@ -783,73 +867,7 @@ static bool input_overlay_add_inputs(input_overlay_t *ol, for(i = 0; i < ol->active->size; i++) { overlay_desc_t *desc = &(ol->active->descs[i]); - switch(desc->type) - { - case OVERLAY_TYPE_BUTTONS: - mask = desc->key_mask; - id = RETRO_DEVICE_ID_JOYPAD_B; - /* Need to check all bits in the mask, - * multiple ones can be pressed */ - current_button_pressed = false; - while(mask) - { - /* Get the next button ID */ - while(mask && (mask & 1) == 0) - { - id+=1; - mask = mask >> 1; - } - /* Light up the button if pressed */ - if(input_state(port, RETRO_DEVICE_JOYPAD, 0, id)) - { - current_button_pressed = true; - desc->updated = true; - - id+=1; - mask = mask >> 1; - } - else - { - /* One of the buttons not pressed */ - current_button_pressed = false; - desc->updated = false; - break; - } - } - button_pressed = button_pressed || current_button_pressed; - break; - case OVERLAY_TYPE_ANALOG_LEFT: - case OVERLAY_TYPE_ANALOG_RIGHT: - { - float analog_x, analog_y; - float dx, dy; - unsigned int index = (desc->type == OVERLAY_TYPE_ANALOG_RIGHT) ? - RETRO_DEVICE_INDEX_ANALOG_RIGHT : RETRO_DEVICE_INDEX_ANALOG_LEFT; - - analog_x = input_state(port, RETRO_DEVICE_ANALOG, index, RETRO_DEVICE_ID_ANALOG_X); - analog_y = input_state(port, RETRO_DEVICE_ANALOG, index, RETRO_DEVICE_ID_ANALOG_Y); - dx = (analog_x/0x8000)*(desc->range_x/2); - dy = (analog_y/0x8000)*(desc->range_y/2); - - desc->delta_x = dx; - desc->delta_y = dy; - /*Maybe use some option here instead of 0, only display - changes greater than some magnitude. - */ - if((dx*dx) > 0 || (dy*dy) > 0) - button_pressed = true; - } - break; - case OVERLAY_TYPE_KEYBOARD: - if(input_state(port, RETRO_DEVICE_KEYBOARD, 0, (unsigned)desc->key_mask)) - { - desc->updated = true; - button_pressed = true; - } - break; - default: - break; - } + button_pressed |= input_overlay_add_inputs_inner(desc, port, analog_dpad_mode); } return button_pressed; diff --git a/input/input_overlay.h b/input/input_overlay.h index cac2269388..921a905548 100644 --- a/input/input_overlay.h +++ b/input/input_overlay.h @@ -172,7 +172,11 @@ struct overlay_desc float x; float y; - uint64_t key_mask; + /* This is a retro_key value for keyboards */ + unsigned retro_key_idx; + + /* This is a bit mask of all input binds to set with this overlay control */ + retro_bits_t button_mask; char next_index_name[64]; @@ -247,7 +251,7 @@ void input_state_overlay(input_overlay_t *ol, int16_t *ret, unsigned port, unsigned device, unsigned idx, unsigned id); -bool input_overlay_key_pressed(input_overlay_t *ol, int key); +bool input_overlay_key_pressed(input_overlay_t *ol, unsigned key); bool input_overlay_is_alive(input_overlay_t *ol); diff --git a/intl/msg_hash_pl.c b/intl/msg_hash_pl.c index 6aceda10d8..1ad5fa1a2b 100644 --- a/intl/msg_hash_pl.c +++ b/intl/msg_hash_pl.c @@ -42,976 +42,7 @@ const char *msg_hash_to_str_pl(enum msg_hash_enums msg) { switch (msg) { - case MENU_ENUM_LABEL_VALUE_ADD_CONTENT_LIST: - return "Dodaj treść"; - case MENU_ENUM_LABEL_VALUE_ASK_ARCHIVE: - return "Pytaj"; - case MENU_ENUM_LABEL_VALUE_ASSETS_DIRECTORY: - return "Katalog assetów"; - case MENU_ENUM_LABEL_VALUE_AUDIO_BLOCK_FRAMES: - return "Block Frames"; - case MENU_ENUM_LABEL_VALUE_AUDIO_DEVICE: - return "Urządzenie audio"; - case MENU_ENUM_LABEL_VALUE_AUDIO_DRIVER: - return "Kontroler dźwięku"; - case MENU_ENUM_LABEL_VALUE_AUDIO_DSP_PLUGIN: - return "Wtyczki audio DSP"; - case MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE: - return "Włącz dźwięk"; - case MENU_ENUM_LABEL_VALUE_AUDIO_FILTER_DIR: - return "Katalog filtrów audio"; - case MENU_ENUM_LABEL_VALUE_AUDIO_LATENCY: - return "Opóźnienie dźwięku (ms)"; - case MENU_ENUM_LABEL_VALUE_AUDIO_MAX_TIMING_SKEW: - return "Audio Maximum Timing Skew"; - case MENU_ENUM_LABEL_VALUE_AUDIO_MUTE: - return "Wycisz dźwięk"; - case MENU_ENUM_LABEL_VALUE_AUDIO_OUTPUT_RATE: - return "Częstotliwość próbkowania dźwięku (Hz)"; - case MENU_ENUM_LABEL_VALUE_AUDIO_RATE_CONTROL_DELTA: - return "Audio Rate Control Delta"; - case MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_DRIVER: - return "Kontroler resamplera dźwięku"; - case MENU_ENUM_LABEL_VALUE_AUDIO_SETTINGS: - return "Ustawienia dźwięku"; - case MENU_ENUM_LABEL_VALUE_AUDIO_SYNC: - return "Włącz synchronizację dźwięku"; - case MENU_ENUM_LABEL_VALUE_AUDIO_VOLUME: - return "Poziom głośności (dB)"; - case MENU_ENUM_LABEL_VALUE_AUTOSAVE_INTERVAL: - return "Częstotliwość automatycznego zapisu SaveRAM"; - case MENU_ENUM_LABEL_VALUE_AUTO_OVERRIDES_ENABLE: - return "Load Override Files Automatically"; /* this one's rather complicated */ - case MENU_ENUM_LABEL_VALUE_AUTO_REMAPS_ENABLE: - return "Automatycznie wczytuj pliki remapowania"; - case MENU_ENUM_LABEL_VALUE_BLOCK_SRAM_OVERWRITE: - return "Nie nadpisuj SaveRAM przy wczytywaniu stanu"; - case MENU_ENUM_LABEL_VALUE_BUILDBOT_ASSETS_URL: - return "URL assetów buildbota"; - case MENU_ENUM_LABEL_VALUE_CACHE_DIRECTORY: /* UPDATE/FIXME */ - return "Katalog do wypakowywania archiwów"; - case MENU_ENUM_LABEL_VALUE_CAMERA_ALLOW: - return "Zezwalaj na dostęp do kamerki"; - case MENU_ENUM_LABEL_VALUE_CAMERA_DRIVER: - return "Kontroler kamerki"; - case MENU_ENUM_LABEL_VALUE_CHEAT: - return "Cheat"; - case MENU_ENUM_LABEL_VALUE_CHEAT_APPLY_CHANGES: - return "Zastosuj zmiany cheatów"; - case MENU_ENUM_LABEL_VALUE_CHEAT_DATABASE_PATH: - return "Katalog z plikami cheatów"; - case MENU_ENUM_LABEL_VALUE_CHEAT_FILE_LOAD: - return "Wczytaj plik z cheatami"; - case MENU_ENUM_LABEL_VALUE_CHEAT_FILE_SAVE_AS: - return "Zapisz plik z cheatami jako"; - case MENU_ENUM_LABEL_VALUE_CHEAT_NUM_PASSES: - return "Liczba przebiegów cheatów"; - case MENU_ENUM_LABEL_VALUE_CLOSE_CONTENT: - return "Zamknij"; - case MENU_ENUM_LABEL_VALUE_CONFIGURATIONS: - return "Wczytaj konfigurację"; - case MENU_ENUM_LABEL_VALUE_CONFIGURATION_SETTINGS: - return "Ustawienia konfiguracji"; - case MENU_ENUM_LABEL_VALUE_CONFIG_SAVE_ON_EXIT: - return "Zapisz konfigurację przy wyjściu"; - case MENU_ENUM_LABEL_VALUE_CONTENT_COLLECTION_LIST: - return "Kolekcji"; - case MENU_ENUM_LABEL_VALUE_CONTENT_DATABASE_DIRECTORY: - return "Katalog bazy danych treści"; - case MENU_ENUM_LABEL_VALUE_CONTENT_HISTORY_SIZE: - return "Rozmiar historii treści"; - case MENU_ENUM_LABEL_VALUE_CONTENT_SETTINGS: - return "Szybkie menu"; - case MENU_ENUM_LABEL_VALUE_CORE_ASSETS_DIRECTORY: - return "Katalog pobranych"; - case MENU_ENUM_LABEL_VALUE_CORE_CHEAT_OPTIONS: - return "Opcje cheatów rdzenia"; - case MENU_ENUM_LABEL_VALUE_CORE_COUNTERS: - return "Liczniki rdzenia"; - case MENU_ENUM_LABEL_VALUE_CORE_ENABLE: - return "Wyświetlaj nazwę rdzenia"; - case MENU_ENUM_LABEL_VALUE_CORE_INFORMATION: - return "Informacje o rdzeniu"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_AUTHORS: - return "Autorzy"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_CATEGORIES: - return "Kategorie"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_LABEL: - return "Oznaczenie rdzenia"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_NAME: - return "Nazwa rdzenia"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_FIRMWARE: - return "Firmware(s)"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_LICENSES: - return "Licencja(-e)"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_PERMISSIONS: - return "Zezwolenia"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_SUPPORTED_EXTENSIONS: - return "Wspierane rozszerzenia"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_SYSTEM_MANUFACTURER: - return "Producent systemu"; - case MENU_ENUM_LABEL_VALUE_CORE_INFO_SYSTEM_NAME: - return "Nazwa systemu"; - case MENU_ENUM_LABEL_VALUE_CORE_INPUT_REMAPPING_OPTIONS: - return "Opcje remapowania kontrolera rdzenia"; /* this is quite bad */ - case MENU_ENUM_LABEL_VALUE_CORE_LIST: - return "Wczytaj rdzeń"; - case MENU_ENUM_LABEL_VALUE_CORE_OPTIONS: - return "Opcje"; - case MENU_ENUM_LABEL_VALUE_CORE_SETTINGS: - return "Ustawienia rdzenia"; - case MENU_ENUM_LABEL_VALUE_CORE_SET_SUPPORTS_NO_CONTENT_ENABLE: /* TODO/FIXME */ - return "Nie uruchamiaj rdzenia automatycznie"; - case MENU_ENUM_LABEL_VALUE_CORE_UPDATER_AUTO_EXTRACT_ARCHIVE: - return "Automatycznie wypakowuj pobierane archiwa"; - case MENU_ENUM_LABEL_VALUE_CORE_UPDATER_BUILDBOT_URL: - return "URL rdzeni buildbota"; - case MENU_ENUM_LABEL_VALUE_CORE_UPDATER_LIST: - return "Aktualizator rdzeni"; - case MENU_ENUM_LABEL_VALUE_CORE_UPDATER_SETTINGS: - return "Ustawienia aktualizatora"; - case MENU_ENUM_LABEL_VALUE_CURSOR_DIRECTORY: - return "Katalog z kursorami"; - case MENU_ENUM_LABEL_VALUE_CURSOR_MANAGER: - return "Menedżer kursorów"; - case MENU_ENUM_LABEL_VALUE_CUSTOM_RATIO: - return "Włąsny współczynnik"; - case MENU_ENUM_LABEL_VALUE_DATABASE_MANAGER: - return "Menedżer bazy danych"; - case MENU_ENUM_LABEL_VALUE_FAVORITES: /* TODO/FIXME - update */ - return "Wybierz plik i dopasuj rdzeń"; - case MENU_ENUM_LABEL_VALUE_DIRECTORY_CONTENT: - return ""; - case MENU_ENUM_LABEL_VALUE_DIRECTORY_DEFAULT: - return ""; - case MENU_ENUM_LABEL_VALUE_DIRECTORY_NONE: - return "<Żaden>"; - case MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND: - return "Nie znaleziono katalogu."; - case MENU_ENUM_LABEL_VALUE_DIRECTORY_SETTINGS: - return "Ustawienia katalogów"; - case MENU_ENUM_LABEL_VALUE_DISABLED: - return "Wyłączone"; - case MENU_ENUM_LABEL_VALUE_DISK_CYCLE_TRAY_STATUS: - return "Disk Cycle Tray Status"; - case MENU_ENUM_LABEL_VALUE_DISK_IMAGE_APPEND: - return "Dopisz do obrazu dysku"; - case MENU_ENUM_LABEL_VALUE_DISK_INDEX: - return "Indeks dysku"; - case MENU_ENUM_LABEL_VALUE_DISK_OPTIONS: - return "Opcje dysku rdzenia"; - case MENU_ENUM_LABEL_VALUE_DONT_CARE: - return "Bez znaczenia"; - case MENU_ENUM_LABEL_VALUE_DOWNLOADED_FILE_DETECT_CORE_LIST: - return "Wybierz pobrany plik i dopasuj rdzeń"; /* TODO/FIXME - rewrite */ - case MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_CONTENT: - return "Pobierz treści"; - case MENU_ENUM_LABEL_VALUE_DPI_OVERRIDE_ENABLE: - return "Pomiń wykryte DPI"; - case MENU_ENUM_LABEL_VALUE_DPI_OVERRIDE_VALUE: - return "Własne DPI"; - case MENU_ENUM_LABEL_VALUE_DRIVER_SETTINGS: - return "Ustawienia kontrolerów"; - case MENU_ENUM_LABEL_VALUE_DUMMY_ON_CORE_SHUTDOWN: - return "Atrapa rdzenia przy zatrzymaniu rdzenia"; - case MENU_ENUM_LABEL_VALUE_DYNAMIC_WALLPAPER: - return "Dynamiczna tapeta"; - case MENU_ENUM_LABEL_VALUE_DYNAMIC_WALLPAPERS_DIRECTORY: - return "Katalog dynamicznych tapet"; - case MENU_ENUM_LABEL_VALUE_ENTRY_HOVER_COLOR: - return "Kolor zaznaczonego elementu menu"; - case MENU_ENUM_LABEL_VALUE_ENTRY_NORMAL_COLOR: - return "Zwykły kolor elementu menu"; - case MENU_ENUM_LABEL_VALUE_FALSE: - return "Fałsz"; - case MENU_ENUM_LABEL_VALUE_FASTFORWARD_RATIO: - return "Maksymalna szybkość działania"; - case MENU_ENUM_LABEL_VALUE_FPS_SHOW: - return "Wyświetlaj FPS"; - case MENU_ENUM_LABEL_VALUE_FRAME_THROTTLE_ENABLE: - return "Limituj maksymalną szybkość działania"; - case MENU_ENUM_LABEL_VALUE_FRAME_THROTTLE_SETTINGS: - return "Frame Throttle Settings"; - case MENU_ENUM_LABEL_VALUE_FRONTEND_COUNTERS: - return "Liczniki frontendu"; - case MENU_ENUM_LABEL_VALUE_HELP: - return "Pooc"; - case MENU_ENUM_LABEL_VALUE_HISTORY_LIST_ENABLE: - return "Włącz historię treści"; - case MENU_ENUM_LABEL_VALUE_HORIZONTAL_MENU: /* Don't change. Breaks everything. (Would be: "Menu poziome") */ - return "Horizontal Menu"; - case MENU_ENUM_LABEL_VALUE_INFORMATION_LIST: - return "Informacje"; - case MENU_ENUM_LABEL_VALUE_INPUT_AUTODETECT_ENABLE: - return "Włącz autokonfigurację"; - case MENU_ENUM_LABEL_VALUE_INPUT_AXIS_THRESHOLD: - return "Próg osi"; - case MENU_ENUM_LABEL_VALUE_INPUT_DESCRIPTOR_HIDE_UNBOUND: - return "Ukryj nieprzypisane przyciski"; - case MENU_ENUM_LABEL_VALUE_INPUT_DESCRIPTOR_LABEL_SHOW: - return "Wyświetl opisy przycisków dla tego rdzenia"; /* UPDATE/FIXME */ - case MENU_ENUM_LABEL_VALUE_INPUT_DRIVER: - return "Kontroler wejścia"; - case MENU_ENUM_LABEL_VALUE_INPUT_DUTY_CYCLE: - return "Cykl zmian"; - case MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BINDS: - return "Input Hotkey Binds"; - case MENU_ENUM_LABEL_VALUE_INPUT_MAX_USERS: - return "Maksymalna liczba użytkowników"; - case MENU_ENUM_LABEL_VALUE_INPUT_OSK_OVERLAY_ENABLE: - return "Wyświetlaj klawiaturę ekranową"; - case MENU_ENUM_LABEL_VALUE_INPUT_OVERLAY_ENABLE: - return "Wyświetlaj nakładkę"; - case MENU_ENUM_LABEL_VALUE_INPUT_REMAPPING_DIRECTORY: - return "Katalog plików remapowania"; - case MENU_ENUM_LABEL_VALUE_INPUT_REMAP_BINDS_ENABLE: - return "Włącz remapowanie bindów"; - case MENU_ENUM_LABEL_VALUE_INPUT_SETTINGS: - return "Ustawienia wprowadzania"; - case MENU_ENUM_LABEL_VALUE_INPUT_TURBO_PERIOD: - return "Okres turbo"; - case MENU_ENUM_LABEL_VALUE_INPUT_USER_BINDS: - return "Wprowadź bindy dla użytkownika %u"; - case MENU_ENUM_LABEL_VALUE_JOYPAD_AUTOCONFIG_DIR: - return "Katalog autokonfiguracji kontrolerów gier"; - case MENU_ENUM_LABEL_VALUE_JOYPAD_DRIVER: - return "Kontroler gamepadów"; - case MENU_ENUM_LABEL_VALUE_LANG_CHINESE_SIMPLIFIED: - return "chińśki (Uproszczony)"; - case MENU_ENUM_LABEL_VALUE_LANG_CHINESE_TRADITIONAL: - return "chiński (Tradycyjny)"; - case MENU_ENUM_LABEL_VALUE_LANG_DUTCH: - return "duński"; - case MENU_ENUM_LABEL_VALUE_LANG_ENGLISH: - return "angielski"; - case MENU_ENUM_LABEL_VALUE_LANG_ESPERANTO: - return "esperanto"; - case MENU_ENUM_LABEL_VALUE_LANG_FRENCH: - return "francuski"; - case MENU_ENUM_LABEL_VALUE_LANG_GERMAN: - return "niemiecki"; - case MENU_ENUM_LABEL_VALUE_LANG_ITALIAN: - return "włoski"; - case MENU_ENUM_LABEL_VALUE_LANG_JAPANESE: - return "japoński"; - case MENU_ENUM_LABEL_VALUE_LANG_KOREAN: - return "koreański"; - case MENU_ENUM_LABEL_VALUE_LANG_PORTUGUESE_BRAZIL: - return "portugalski (brazil)"; - case MENU_ENUM_LABEL_VALUE_LANG_PORTUGUESE_PORTUGAL: - return "portugalski (portugal)"; - case MENU_ENUM_LABEL_VALUE_LANG_RUSSIAN: - return "rosyjski"; - case MENU_ENUM_LABEL_VALUE_LANG_SPANISH: - return "hiszpański"; - case MENU_ENUM_LABEL_VALUE_LEFT_ANALOG: - return "Lewy analog"; - case MENU_ENUM_LABEL_VALUE_LIBRETRO_DIR_PATH: - return "Katalog rdzeni"; - case MENU_ENUM_LABEL_VALUE_LIBRETRO_INFO_PATH: - return "Katalog informacji o rdzeniach"; - case MENU_ENUM_LABEL_VALUE_LIBRETRO_LOG_LEVEL: - return "Poziom logowania rdzenia"; - case MENU_ENUM_LABEL_VALUE_LINEAR: - return "Liniowe"; - case MENU_ENUM_LABEL_VALUE_LOAD_ARCHIVE: - return "Wczytaj archiwum"; - case MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_HISTORY: - return "Wczytaj z ostatnio używanych"; - case MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_LIST: - return "Wczytaj treść"; - case MENU_ENUM_LABEL_VALUE_LOAD_STATE: - return "Wczytaj stan"; - case MENU_ENUM_LABEL_VALUE_LOCATION_ALLOW: - return "Zezwalaj na dostęp do lokalizacji"; - case MENU_ENUM_LABEL_VALUE_LOCATION_DRIVER: - return "Kontroler lokalizacji"; - case MENU_ENUM_LABEL_VALUE_LOGGING_SETTINGS: - return "Ustawienia logowania"; - case MENU_ENUM_LABEL_VALUE_LOG_VERBOSITY: - return "Szczegółowość logowania"; - case MENU_ENUM_LABEL_VALUE_MAIN_MENU: - return "Menu główne"; - case MENU_ENUM_LABEL_VALUE_MANAGEMENT: - return "Ustawienia bazy danych"; - case MENU_ENUM_LABEL_VALUE_MENU_DRIVER: - return "Kontroler menu"; - case MENU_ENUM_LABEL_VALUE_MENU_FILE_BROWSER_SETTINGS: - return "Menu File Browser Settings"; - case MENU_ENUM_LABEL_VALUE_MENU_SETTINGS: - return "Ustawienia menu"; - case MENU_ENUM_LABEL_VALUE_MENU_WALLPAPER: - return "Tapeta menu"; - case MENU_ENUM_LABEL_VALUE_MISSING: - return "Brak"; - case MENU_ENUM_LABEL_VALUE_MOUSE_ENABLE: - return "Obsługa myszy"; - case MENU_ENUM_LABEL_VALUE_MULTIMEDIA_SETTINGS: - return "Ustawienia multimediów"; - case MENU_ENUM_LABEL_VALUE_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE: - return "Filtruj według wspieranych rozszerzeń"; /* TODO/FIXME - rewrite */ - case MENU_ENUM_LABEL_VALUE_NAVIGATION_WRAPAROUND: - return "Zawijanie nawigacji"; - case MENU_ENUM_LABEL_VALUE_NEAREST: - return "Najbliższe"; - case MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT: /* TODO: Original string changed */ - return "Zamień kontrolery w grze sieciowej"; - case MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES: - return "Opóxnione klatki w grze sieciowej"; - case MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE: - return "Włącz grę sieciową"; - case MENU_ENUM_LABEL_VALUE_NETPLAY_IP_ADDRESS: /* TODO: Original string changed */ - return "Adres IP"; - case MENU_ENUM_LABEL_VALUE_NETPLAY_MODE: - return "Tryb klienta gry sieciowej"; - case MENU_ENUM_LABEL_VALUE_NETPLAY_NICKNAME: - return "Nazwa użytkownika"; - case MENU_ENUM_LABEL_VALUE_NETPLAY_SPECTATOR_MODE_ENABLE: - return "Tryb obserwatora gry sieciowej"; - case MENU_ENUM_LABEL_VALUE_NETPLAY_TCP_UDP_PORT: - return "Port TCP/UDP gry sieciowej"; - case MENU_ENUM_LABEL_VALUE_NETWORK_CMD_ENABLE: - return "Komendy sieciowe"; - case MENU_ENUM_LABEL_VALUE_NETWORK_CMD_PORT: - return "Port dla komend sieciowych"; - case MENU_ENUM_LABEL_VALUE_NETWORK_SETTINGS: - return "Ustawienia sieci"; - case MENU_ENUM_LABEL_VALUE_NO: - return "Nie"; - case MENU_ENUM_LABEL_VALUE_NONE: - return "Żaden"; - case MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE: - return "B/D"; - case MENU_ENUM_LABEL_VALUE_NO_CORE: - return "Brak rdzenia"; - case MENU_ENUM_LABEL_VALUE_NO_CORES_AVAILABLE: - return "Brak dostępnych rdzeni."; - case MENU_ENUM_LABEL_VALUE_NO_CORE_INFORMATION_AVAILABLE: - return "Brak informacji o rdzeniu."; - case MENU_ENUM_LABEL_VALUE_NO_CORE_OPTIONS_AVAILABLE: - return "Brak dostępnych opcji rdzenia."; - case MENU_ENUM_LABEL_VALUE_NO_INFORMATION_AVAILABLE: - return "Brak dostępnych informacji."; - case MENU_ENUM_LABEL_VALUE_NO_ITEMS: - return "Brak elementów."; - case MENU_ENUM_LABEL_VALUE_NO_PERFORMANCE_COUNTERS: - return "Brak liczników wydajności."; - case MENU_ENUM_LABEL_VALUE_NO_PLAYLIST_ENTRIES_AVAILABLE: - return "Brak wpisów w playliście."; - case MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND: - return "Nie znaleziono ustawień."; - case MENU_ENUM_LABEL_VALUE_NO_SHADER_PARAMETERS: - return "Brak parametrów shadera."; - case MENU_ENUM_LABEL_VALUE_OFF: /* Don't change. Needed for XMB atm. (Would be: "WYŁĄCZONE") */ - return "OFF"; - case MENU_ENUM_LABEL_VALUE_ON: /* Don't change. Needed for XMB atm. (Would be: "WŁĄCZONE") */ - return "ON"; - case MENU_ENUM_LABEL_VALUE_ONLINE_UPDATER: - return "Aktualizator sieciowy"; - case MENU_ENUM_LABEL_VALUE_ONSCREEN_DISPLAY_SETTINGS: - return "Ustawienia OSD"; - case MENU_ENUM_LABEL_VALUE_OPEN_ARCHIVE: - return "Otwórz archiwum"; - case MENU_ENUM_LABEL_VALUE_OPTIONAL: - return "Opcjonalny"; - case MENU_ENUM_LABEL_VALUE_OSK_OVERLAY_DIRECTORY: - return "Katalog klawiatur ekranowych"; - case MENU_ENUM_LABEL_VALUE_OVERLAY_AUTOLOAD_PREFERRED: - return "Automatycznie wczytaj preferowaną nakładkę"; - case MENU_ENUM_LABEL_VALUE_OVERLAY_DIRECTORY: - return "Katalog nakładek"; - case MENU_ENUM_LABEL_VALUE_OVERLAY_OPACITY: - return "Nieprzeźroczystość nakładki"; - case MENU_ENUM_LABEL_VALUE_OVERLAY_PRESET: - return "Preset nakładki"; - case MENU_ENUM_LABEL_VALUE_OVERLAY_SCALE: - return "Skala nakładki"; - case MENU_ENUM_LABEL_VALUE_OVERLAY_SETTINGS: - return "Ustawienia przycisków ekranowych"; - case MENU_ENUM_LABEL_VALUE_PAL60_ENABLE: - return "Użyj trybu PAL60"; - case MENU_ENUM_LABEL_VALUE_PAUSE_LIBRETRO: - return "Pauzuj przy wejściu do menu"; - case MENU_ENUM_LABEL_VALUE_PAUSE_NONACTIVE: - return "Wstrzymaj gdy w tle"; - case MENU_ENUM_LABEL_VALUE_PERFCNT_ENABLE: - return "Liczniki wydajności"; - case MENU_ENUM_LABEL_VALUE_PLAYLIST_DIRECTORY: - return "Katalog historii"; - case MENU_ENUM_LABEL_VALUE_PLAYLIST_SETTINGS: - return "Ustawienia playlisty"; - case MENU_ENUM_LABEL_VALUE_POINTER_ENABLE: - return "Obsługa dotyku"; - case MENU_ENUM_LABEL_VALUE_PORT: - return "Port"; - case MENU_ENUM_LABEL_VALUE_PRESENT: - return "Obecny"; - case MENU_ENUM_LABEL_VALUE_PRIVACY_SETTINGS: - return "Ustawienia prywatności"; - case MENU_ENUM_LABEL_VALUE_QUIT_RETROARCH: - return "Opuść RetroArch"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_CRC32: - return "CRC32"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_DESCRIPTION: - return "Opis"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_DEVELOPER: - return "Deweloper"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_FRANCHISE: - return "Franczyza"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_MD5: - return "MD5"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_NAME: - return "Nazwa"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ORIGIN: - return "Pochodzenie"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_PUBLISHER: - return "Wydawca"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_RELEASE_MONTH: - return "Miesiąc wydania"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_RELEASE_YEAR: - return "Rok wydania"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_SHA1: - return "SHA1"; - case MENU_ENUM_LABEL_VALUE_RDB_ENTRY_START_CONTENT: - return "Uruchom treść"; - case MENU_ENUM_LABEL_VALUE_RECORDING_CONFIG_DIRECTORY: - return "Katalog konfiguracji nagrywania"; - case MENU_ENUM_LABEL_VALUE_RECORDING_OUTPUT_DIRECTORY: - return "Katalog wyjściowy nagrywania"; - case MENU_ENUM_LABEL_VALUE_RECORDING_SETTINGS: - return "Ustawienia nagrywania"; - case MENU_ENUM_LABEL_VALUE_RECORD_CONFIG: - return "Konfiguracja nagrywania"; - case MENU_ENUM_LABEL_VALUE_RECORD_DRIVER: - return "Kontroler nagrywania"; - case MENU_ENUM_LABEL_VALUE_RECORD_ENABLE: - return "Włącz nagrywanie"; - case MENU_ENUM_LABEL_VALUE_RECORD_PATH: /* FIXME/UPDATE */ - return "Ścieżka nagrywania"; - case MENU_ENUM_LABEL_VALUE_RECORD_USE_OUTPUT_DIRECTORY: - return "Używaj katalogu wyjściowego nagrywania"; - case MENU_ENUM_LABEL_VALUE_REMAP_FILE_LOAD: - return "Wczytaj plik remapowania"; - case MENU_ENUM_LABEL_VALUE_REMAP_FILE_SAVE_CORE: - return "Zapisz plik remapowania dla rdzenia"; - case MENU_ENUM_LABEL_VALUE_REMAP_FILE_SAVE_GAME: - return "Zapisz plik remapowania dla gry"; - case MENU_ENUM_LABEL_VALUE_REQUIRED: - return "Wymagany"; - case MENU_ENUM_LABEL_VALUE_RESTART_CONTENT: - return "Restartuj"; - case MENU_ENUM_LABEL_VALUE_RESTART_RETROARCH: - return "Uruchom ponownie RetroArch"; - case MENU_ENUM_LABEL_VALUE_RESUME: - return "Wznów"; - case MENU_ENUM_LABEL_VALUE_RESUME_CONTENT: - return "Wznów"; - case MENU_ENUM_LABEL_VALUE_RETROKEYBOARD: - return "RetroKeyboard"; - case MENU_ENUM_LABEL_VALUE_RETROPAD: - return "RetroPad"; - case MENU_ENUM_LABEL_VALUE_REWIND_ENABLE: - return "Włącz przewijanie"; - case MENU_ENUM_LABEL_VALUE_REWIND_GRANULARITY: - return "Płynność przewijania"; - case MENU_ENUM_LABEL_VALUE_REWIND_SETTINGS: - return "Ustawienia przewijania"; - case MENU_ENUM_LABEL_VALUE_RGUI_BROWSER_DIRECTORY: - return "Katalog przeglądarki"; - case MENU_ENUM_LABEL_VALUE_RGUI_CONFIG_DIRECTORY: - return "Katalog zapisanych konfiguracji"; - case MENU_ENUM_LABEL_VALUE_RGUI_SHOW_START_SCREEN: - return "Pokazuj ekran startowy"; - case MENU_ENUM_LABEL_VALUE_RIGHT_ANALOG: - return "Prawy analog"; - case MENU_ENUM_LABEL_VALUE_SAVEFILE_DIRECTORY: - return "Katalog zapisów treści"; - case MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_INDEX: - return "Indeks automatycznie zapisywanego stanu"; - case MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_LOAD: - return "Automatyczne wczytywanie stanu"; - case MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_SAVE: - return "Automatyczny zapis stanu"; - case MENU_ENUM_LABEL_VALUE_SAVESTATE_DIRECTORY: - return "Katalog zapisanych stanów"; - case MENU_ENUM_LABEL_VALUE_SAVE_NEW_CONFIG: - return "Zapisz nową konfigurację"; - case MENU_ENUM_LABEL_VALUE_SAVE_STATE: - return "Zapisz stan"; - case MENU_ENUM_LABEL_VALUE_SAVING_SETTINGS: - return "Ustawienia zapisywania"; - case MENU_ENUM_LABEL_VALUE_SCAN_DIRECTORY: - return "Przeszukaj katalog"; - case MENU_ENUM_LABEL_VALUE_SCAN_FILE: - return "Skanuj plik"; - case MENU_ENUM_LABEL_VALUE_SCAN_THIS_DIRECTORY: - return ""; - case MENU_ENUM_LABEL_VALUE_SCREENSHOT_DIRECTORY: - return "Katalog zrzutów"; - case MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION: - return "Rozdzielczość ekranu"; - case MENU_ENUM_LABEL_VALUE_SEARCH: - return "Szukaj:"; - case MENU_ENUM_LABEL_VALUE_SECONDS: - return "sekund"; - case MENU_ENUM_LABEL_VALUE_SETTINGS: - return "Ustawienia"; - case MENU_ENUM_LABEL_VALUE_SHADER: - return "Shader"; - case MENU_ENUM_LABEL_VALUE_SHADER_APPLY_CHANGES: - return "Zastosuj zmiany shaderów"; - case MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS: - return "Opcje shadera"; - case MENU_ENUM_LABEL_VALUE_SHOW_ADVANCED_SETTINGS: - return "Pokaż zaawansowane ustawienia"; - case MENU_ENUM_LABEL_VALUE_SLOWMOTION_RATIO: - return "Współczynnik spowolnienia"; - case MENU_ENUM_LABEL_VALUE_SORT_SAVEFILES_ENABLE: - return "Sortuj zapisy w folderach"; - case MENU_ENUM_LABEL_VALUE_SORT_SAVESTATES_ENABLE: - return "Sortuj zapisane stany w folderach"; - case MENU_ENUM_LABEL_VALUE_STATUS: - return "Status"; - case MENU_ENUM_LABEL_VALUE_STDIN_CMD_ENABLE: - return "Komendy stdin"; - case MENU_ENUM_LABEL_VALUE_SUSPEND_SCREENSAVER_ENABLE: - return "Wstrzymaj wygaszacz"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_BGM_ENABLE: - return "Włącz BGM systemu"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_DIRECTORY: - return "Katalog systemu"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFORMATION: - return "Informacje o systemie"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_7ZIP_SUPPORT: - return "Wsparcie 7zip"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ALSA_SUPPORT: - return "Wsparcie ALSA"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_BUILD_DATE: - return "Data kompilacji"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CG_SUPPORT: - return "Wsparcie Cg"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_COCOA_SUPPORT: - return "Wsparcie Cocoa"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_COMMAND_IFACE_SUPPORT: - return "Wsparcie interfejsu wiersza poleceń"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CORETEXT_SUPPORT: - return "Wsparcie CoreText"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CPU_FEATURES: - return "Właściwości CPU"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_DPI: - return "Metryczne DPI wyświetlacza"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_HEIGHT: - return "Metryczna wysokość wyświetlacza (mm)"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_WIDTH: - return "Metryczna szerokość wyświetlacza (mm)"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DSOUND_SUPPORT: - return "Wsparcie DirectSound"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_WASAPI_SUPPORT: - return "Wsparcie WASAPI"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DYLIB_SUPPORT: - return "Wsparcie bibliotek dynamicznych"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_EGL_SUPPORT: - return "Wsparcie EGL"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FBO_SUPPORT: - return "Wsparcie renderowania do tekstury w OpenGL/Direct3D (wielokrotne przebiegi shaderów)"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FFMPEG_SUPPORT: - return "Wsparcie FFmpeg"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FREETYPE_SUPPORT: - return "Wsparcie FreeType"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_IDENTIFIER: - return "Identyfikator frontendu"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_NAME: - return "Nazwa frontendu"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_OS: - return "System operacyjny hosta:"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_GIT_VERSION: - return "Wersja git"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_GLSL_SUPPORT: - return "Wsparcie GLSL"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_HLSL_SUPPORT: - return "Wsparcie HLSL"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_JACK_SUPPORT: - return "Wsparcie JACK"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_KMS_SUPPORT: - return "Wsparcie KMS/EGL"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBRETRODB_SUPPORT: - return "Wsparcie LibretroDB"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBUSB_SUPPORT: - return "Wsparcie libusb"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBXML2_SUPPORT: - return "Wsparcie parsowania XML libxml2"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETPLAY_SUPPORT: - return "Wsparcie Netplay (peer-to-peer)"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETWORK_COMMAND_IFACE_SUPPORT: - return "Wsparcie interfejsu komend sieciowych"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENAL_SUPPORT: - return "Wsparcie OpenAL"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENGLES_SUPPORT: - return "Wsparcie OpenGL ES"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENGL_SUPPORT: - return "Wsparcie OpenGL"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENSL_SUPPORT: - return "Wsparcie OpenSL"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENVG_SUPPORT: - return "Wsparcie OpenVG"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OSS_SUPPORT: - return "Wsparcie OSS"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OVERLAY_SUPPORT: - return "Wsparcie nakładek graficznych"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE: - return "Źródło zasilania"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_CHARGED: - return "Naładowano"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_CHARGING: - return "Ładowanie"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_DISCHARGING: - return "Na baterii"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_NO_SOURCE: - return "Brak źródła"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_PULSEAUDIO_SUPPORT: - return "Wsparcie PulseAudio"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_PYTHON_SUPPORT: - return "Wsparcie Pythona (skrypty w shaderach)"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RETRORATING_LEVEL: - return "Poziom RetroRating"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ROARAUDIO_SUPPORT: - return "Wsparcie RoarAudio"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RPNG_SUPPORT: - return "Wsparcie PNG (RPNG)"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RSOUND_SUPPORT: - return "Wsparcie RSound"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SDL2_SUPPORT: - return "Wsparcie SDL2"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SDL_IMAGE_SUPPORT: - return "Wsparcie SDL image"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SDL_SUPPORT: - return "Wsparcie SDL1.2"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_THREADING_SUPPORT: - return "Wsparcie wielu wątków"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_UDEV_SUPPORT: - return "Wsparcie Udev"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_V4L2_SUPPORT: - return "Wsparcie Video4Linux2"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_VIDEO_CONTEXT_DRIVER: - return "Kontroler wideo"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_WAYLAND_SUPPORT: - return "Wsparcie Wayland"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_X11_SUPPORT: - return "Wsparcie X11"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_XAUDIO2_SUPPORT: - return "Wsparcie XAudio2"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_XVIDEO_SUPPORT: - return "Wsparcie XVideo"; - case MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ZLIB_SUPPORT: - return "Wsparcie Zlib"; - case MENU_ENUM_LABEL_VALUE_TAKE_SCREENSHOT: - return "Zapisz zrzut"; - case MENU_ENUM_LABEL_VALUE_THREADED_DATA_RUNLOOP_ENABLE: /* TODO/FIXME - update */ - return "Osobny wątek odbierania danych"; - case MENU_ENUM_LABEL_VALUE_TIMEDATE_ENABLE: - return "Wyświetl czas/datę"; - case MENU_ENUM_LABEL_VALUE_TITLE_COLOR: - return "Kolor tytułu menu"; - case MENU_ENUM_LABEL_VALUE_TRUE: - return "Prawda"; - case MENU_ENUM_LABEL_VALUE_UI_COMPANION_START_ON_BOOT: - return "UI Companion Start On Boot"; - case MENU_ENUM_LABEL_VALUE_UI_MENUBAR_ENABLE: - return "Pasek menu"; - case MENU_ENUM_LABEL_VALUE_UNABLE_TO_READ_COMPRESSED_FILE: - return "Nie udało się odczytać skompresowanego pliku."; - case MENU_ENUM_LABEL_VALUE_UNKNOWN: - return "Nieznane"; - case MENU_ENUM_LABEL_VALUE_UPDATE_ASSETS: - return "Aktualizuj assety"; - case MENU_ENUM_LABEL_VALUE_UPDATE_AUTOCONFIG_PROFILES: - return "Aktualizuj profile autokonfiguracji"; - case MENU_ENUM_LABEL_VALUE_UPDATE_CG_SHADERS: - return "Aktualizuj shadery Cg"; - case MENU_ENUM_LABEL_VALUE_UPDATE_CHEATS: - return "Aktualizuj cheaty"; - case MENU_ENUM_LABEL_VALUE_UPDATE_CORE_INFO_FILES: - return "Aktualizuj pliki informacji o rdzeniach"; - case MENU_ENUM_LABEL_VALUE_UPDATE_DATABASES: - return "Aktualizuj bazy danych"; - case MENU_ENUM_LABEL_VALUE_UPDATE_GLSL_SHADERS: - return "Aktualizuj shadery GLSL"; - case MENU_ENUM_LABEL_VALUE_UPDATE_OVERLAYS: - return "Aktualizuj nakładki graficzne"; - case MENU_ENUM_LABEL_VALUE_USER: - return "Użytkownik"; - case MENU_ENUM_LABEL_VALUE_USER_INTERFACE_SETTINGS: - return "Ustawienia interfejsu użytkownika"; - case MENU_ENUM_LABEL_VALUE_USER_LANGUAGE: - return "Język"; - case MENU_ENUM_LABEL_VALUE_USER_SETTINGS: - return "Ustawienia użytkownika"; - case MENU_ENUM_LABEL_VALUE_USE_BUILTIN_IMAGE_VIEWER: - return "Użyj wbudowanej przeglądarki obrazów"; - case MENU_ENUM_LABEL_VALUE_USE_BUILTIN_PLAYER: - return "Użyj wbudowanego odtwarzacza mediów"; - case MENU_ENUM_LABEL_VALUE_USE_THIS_DIRECTORY: - return ""; - case MENU_ENUM_LABEL_VALUE_VIDEO_ALLOW_ROTATE: - return "Zezwól na obrót"; - case MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO_AUTO: - return "Auto współczynnik proporcji"; - case MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO_INDEX: - return "łczynnika proporcji"; - case MENU_ENUM_LABEL_VALUE_VIDEO_BLACK_FRAME_INSERTION: - return "Wstawiaj czarne klatki"; - case MENU_ENUM_LABEL_VALUE_VIDEO_CROP_OVERSCAN: - return "Wytnij overscan (restart)"; - case MENU_ENUM_LABEL_VALUE_VIDEO_DISABLE_COMPOSITION: - return "Wyłącz efekty kompozycji pulpitu"; - case MENU_ENUM_LABEL_VALUE_VIDEO_DRIVER: - return "Kontroler wideo"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FILTER: - return "Filtr obrazu"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FILTER_DIR: - return "Katalog filtrów wideo"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FILTER_FLICKER: - return "Filtr migotania"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FONT_ENABLE: - return "Wyświetlaj wiadomości OSD"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FONT_PATH: - return "Czcionka wiadomości OSD"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FONT_SIZE: - return "Rozmiar wiadomości OSD"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FORCE_ASPECT: - return "Wymuś współczynnik proporcji"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FORCE_SRGB_DISABLE: - return "Wymuś wyłączenie sRGB FBO"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY: - return "Opóźnienie klatek"; - case MENU_ENUM_LABEL_VALUE_VIDEO_FULLSCREEN: - return "Pełny ekran"; - case MENU_ENUM_LABEL_VALUE_VIDEO_GAMMA: - return "Gamma wideo"; - case MENU_ENUM_LABEL_VALUE_VIDEO_GPU_RECORD: - return "Włącz nagrywanie z użyciem GPU"; - case MENU_ENUM_LABEL_VALUE_VIDEO_GPU_SCREENSHOT: - return "Wykonuj zrzuty ekranu z wykorzystaniem GPU"; - case MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC: - return "Ścisła synchronizacja GPU"; - case MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC_FRAMES: - return "Hard GPU Sync Frames"; - case MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_POS_X: - return "Współrzędna X dla wiadomości OSD"; - case MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_POS_Y: - return "Współrzędna Y dla wiadomości OSD"; - case MENU_ENUM_LABEL_VALUE_VIDEO_MONITOR_INDEX: - return "Indeks monitora"; - case MENU_ENUM_LABEL_VALUE_VIDEO_POST_FILTER_RECORD: - return "Nagrywaj wraz z zaaplikowanymi filtrami"; - case MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE: - return "Częstotliwość odświeżania"; - case MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO: - return "Szacowana częstotliwość odświeżania monitora"; - case MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION: - return "Obrót"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SCALE: - return "Skala w oknie"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER: - return "Skaluj w liczbach całkowitych"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SETTINGS: - return "Ustawienia wideo"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_DIR: - return "Katalog shaderów"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_NUM_PASSES: - return "Liczba przebiegów shadera"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PARAMETERS: - return "Podgląd parametrów shadera"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET: - return "Wczytaj preset shaderów"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_PARAMETERS: - return "Parametry shadera menu"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_AS: - return "Zapisz preset shadera jako"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SHARED_CONTEXT: - return "Enable Hardware Shared Context"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SMOOTH: - return "Sprzętowe filtrowanie dwuliniowe"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SOFT_FILTER: - return "Włącz filtr programowy"; - case MENU_ENUM_LABEL_VALUE_VIDEO_SWAP_INTERVAL: - return "VSync Swap Interval"; - case MENU_ENUM_LABEL_VALUE_VIDEO_THREADED: - return "Osobny wątek wideo"; - case MENU_ENUM_LABEL_VALUE_VIDEO_VFILTER: - return "Redukcja migotania"; - case MENU_ENUM_LABEL_VALUE_VIDEO_VI_WIDTH: - return "Set VI Screen Width"; - case MENU_ENUM_LABEL_VALUE_VIDEO_VSYNC: - return "Synchronizacja pionowa"; - case MENU_ENUM_LABEL_VALUE_VIDEO_WINDOWED_FULLSCREEN: - return "Tryb pełnego ekranu w oknie"; - case MENU_ENUM_LABEL_VALUE_YES: - return "Tak"; - case MSG_APPENDED_DISK: - return "Dopisano do dysku"; - case MSG_APPLYING_CHEAT: - return "Applying cheat changes."; - case MSG_APPLYING_SHADER: - return "Aplikowanie shadera"; - case MSG_AUDIO_MUTED: - return "Wyciszono dźwięk."; - case MSG_AUDIO_UNMUTED: - return "Przywrócono dźwięk."; - case MSG_AUTOSAVE_FAILED: - return "Nie udało się zainicjalizować automatycznego zapisu."; - case MSG_BLOCKING_SRAM_OVERWRITE: - return "Blokowanie nadpisania SRAM"; - case MSG_BYTES: - return "bajtów"; - case MSG_CONFIG_DIRECTORY_NOT_SET: - return "Nie ustawiono katalogu konfiguracji. Nie można zapisać nowej konfiguracji."; - case MSG_CORE_DOES_NOT_SUPPORT_SAVESTATES: - return "Rdzeń nie wspiera zapisów stanu."; - case MSG_COULD_NOT_READ_CONTENT_FILE: - return "Nie udało się odczytać pliku treści"; - case MSG_CUSTOM_TIMING_GIVEN: - return "Wprowadzono niestandardowy timing"; - case MSG_DETECTED_VIEWPORT_OF: - return "Wykrywanie viewportu"; - case MSG_FAILED_TO: - return "Nie udało się"; - case MSG_FAILED_TO_APPLY_SHADER: - return "Nie udało się zaaplikować shadera."; - case MSG_FAILED_TO_LOAD_CONTENT: - return "Nie udało się wczytać treści"; - case MSG_FAILED_TO_LOAD_MOVIE_FILE: - return "Nie udało się wczytać pliku filmu"; - case MSG_FAILED_TO_LOAD_OVERLAY: - return "Nie udało się wczytać nakładki."; - case MSG_FAILED_TO_LOAD_STATE: - return "Nie udało się wczytać stanu z"; - case MSG_FAILED_TO_REMOVE_DISK_FROM_TRAY: - return "Nie udało się usunąć dysku z tacki."; - case MSG_FAILED_TO_REMOVE_TEMPORARY_FILE: - return "Nie udało się usunąć pliku tymczasowego"; - case MSG_FAILED_TO_SAVE_SRAM: - return "Nie udało się zapisać SRAM"; - case MSG_FAILED_TO_SAVE_STATE_TO: - return "Nie udało się zapisać stanu do"; - case MSG_FAILED_TO_START_MOVIE_RECORD: - return "Nie udało się rozpocząć nagrywania filmu."; - case MSG_FAILED_TO_START_RECORDING: - return "Nie udało się rozpocząć nagrywania."; - case MSG_FAILED_TO_TAKE_SCREENSHOT: - return "Nie udało się zapisać zrzutu."; - case MSG_FAILED_TO_UNMUTE_AUDIO: - return "Nie udało się przywrócić dźwięku."; - case MSG_FOUND_SHADER: - return "Znaleziono shader"; - case MSG_GOT_INVALID_DISK_INDEX: - return "Otrzymano nieprawidłowy indeks dysku."; - case MSG_GRAB_MOUSE_STATE: - return "Grab mouse state"; - case MSG_HW_RENDERED_MUST_USE_POSTSHADED_RECORDING: - return "Ten rdzeń libretro używa renderowania sprzętowego. Konieczne jest użycie nagrywania wraz z zaaplikowanymi shaderami."; - case MSG_LIBRETRO_ABI_BREAK: - return "został skompilowany dla innej wersji libretro, różnej od obecnie używanej."; - case MSG_LOADED_STATE_FROM_SLOT: - return "Wczytano stan ze slotu #%d."; - case MSG_LOADED_STATE_FROM_SLOT_AUTO: - return "Wczytano stan ze slotu #-1 (auto)."; - case MSG_LOADING_CONTENT_FILE: - return "Wczytywanie pliku treści"; - case MSG_LOADING_STATE: - return "Wczytywanie stanu"; - case MSG_MOVIE_PLAYBACK_ENDED: - return "Zakończono odtwarzanie filmu."; - case MSG_MOVIE_RECORD_STOPPED: - return "Zatrzymano nagrywanie filmu."; - case MSG_NETPLAY_FAILED: - return "Nie udało się zainicjalizować gry sieciowej."; - case MSG_PAUSED: - return "Wstrzymano."; - case MSG_PROGRAM: - return "RetroArch"; - case MSG_RECEIVED: - return "otrzymano"; - case MSG_RECORDING_TERMINATED_DUE_TO_RESIZE: - return "Przerwano nagrywanie z powodu zmiany rozmiaru."; - case MSG_RECORDING_TO: - return "Nagrywanie do"; - case MSG_REDIRECTING_CHEATFILE_TO: - return "Przekierowywanie pliku cheatów do"; - case MSG_REDIRECTING_SAVEFILE_TO: - return "Przekierowywanie pliku zapisu do"; - case MSG_REDIRECTING_SAVESTATE_TO: - return "Przekierowywanie zapisu stanu do"; /* TODO */ - case MSG_REMOVED_DISK_FROM_TRAY: - return "Usunięto dysk z tacki."; - case MSG_REMOVING_TEMPORARY_CONTENT_FILE: - return "Usuwanie tymczasowego pliku treści"; - case MSG_RESET: - return "Reset"; - case MSG_RESTARTING_RECORDING_DUE_TO_DRIVER_REINIT: - return "Ponowne rozpoczęcie nagrywania z powodu reinicjalizacji kontrolera."; - case MSG_REWINDING: - return "Przewijanie."; - case MSG_REWIND_INIT: - return "Inicjalizowanie bufora przewijania o rozmiarze"; - case MSG_REWIND_INIT_FAILED: - return "Nie udało się zainicjalizować bufora przewijania. Przewijanie zostanie wyłączone."; - case MSG_REWIND_INIT_FAILED_THREADED_AUDIO: - return "Implementacja używa osobnego wątku do przetwarzania dźwięku. Przewijanie nie jest możliwe."; - case MSG_REWIND_REACHED_END: - return "W buforze przewijania nie ma więcej danych."; - case MSG_SAVED_STATE_TO_SLOT: - return "Zapisano stan w slocie #%d."; - case MSG_SAVED_STATE_TO_SLOT_AUTO: - return "Zapisano stan w slocie #-1 (auto)."; - case MSG_SAVED_SUCCESSFULLY_TO: - return "Pomyślnie zapisano do"; - case MSG_SAVING_RAM_TYPE: - return "Zapisywanie typu RAM"; - case MSG_SAVING_STATE: - return "Zapisywanie stanu"; - case MSG_SCANNING: - return "Skanowanie"; - case MSG_SCANNING_OF_DIRECTORY_FINISHED: - return "Zakończono skanowanie katalogu"; - case MSG_SENDING_COMMAND: - return "Wysyłanie komendy"; - case MSG_SHADER: - return "Shader"; - case MSG_SKIPPING_SRAM_LOAD: - return "Pomijanie wczytywania SRAM."; - case MSG_SLOW_MOTION: - return "Spowolnione tempo."; - case MSG_FAST_FORWARD: - return "Szybko do przodu."; - case MSG_SLOW_MOTION_REWIND: - return "Przewijanie w spowolnionym tempie."; - case MSG_SRAM_WILL_NOT_BE_SAVED: - return "SRAM nie zostanie zapisany."; - case MSG_STARTING_MOVIE_PLAYBACK: - return "Rozpoczynanie odtwarzania filmu."; - case MSG_STARTING_MOVIE_RECORD_TO: - return "Rozpoczynanie zapisu filmu do"; - case MSG_STATE_SIZE: - return "Rozmiar stanu"; - case MSG_STATE_SLOT: - return "Slot zapisu"; - case MSG_TAKING_SCREENSHOT: - return "Zapisywanie zrzutu."; - case MSG_TO: - return "do"; - case MSG_UNKNOWN: - return "Nieznane"; - case MSG_UNPAUSED: - return "Wznowiono."; - case MSG_UNRECOGNIZED_COMMAND: - return "Nieznana komenda"; - case MSG_USING_LIBRETRO_DUMMY_CORE_RECORDING_SKIPPED: - return "Atrapa rdzenia w użyciu. Pomijanie nagrywania."; - case MSG_VIEWPORT_SIZE_CALCULATION_FAILED: - return "Obliczanie rozmiaru viewportu nie powiodło się! Kontynuowanie z użyciem surowych danych. Prawdopodobnie nie będzie to działało poprawnie..."; - case MSG_VIRTUAL_DISK_TRAY: - return "wirtualna tacka."; /* this is funny */ +#include "msg_hash_pl.h" default: break; } diff --git a/intl/msg_hash_pl.h b/intl/msg_hash_pl.h new file mode 100644 index 0000000000..929169f621 --- /dev/null +++ b/intl/msg_hash_pl.h @@ -0,0 +1,3345 @@ +MSG_HASH( + MSG_COMPILER, + "Kompilator" + ) +MSG_HASH( + MSG_UNKNOWN_COMPILER, + "Nieznany kompilator" + ) +MSG_HASH( + MSG_DEVICE_DISCONNECTED_FROM_PORT, + "Urządzenie zostało odłączone od portu" + ) +MSG_HASH( + MSG_UNKNOWN_NETPLAY_COMMAND_RECEIVED, + "Otrzymano nieznane polecenie netplay" + ) +MSG_HASH( + MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER, + "Plik już istnieje. Zapisywanie do bufora kopii zapasowej" + ) +MSG_HASH( + MSG_GOT_CONNECTION_FROM, + "Mam połączenie od: \"%s\"" + ) +MSG_HASH( + MSG_GOT_CONNECTION_FROM_NAME, + "Mam połączenie od: \"%s (%s)\"" + ) +MSG_HASH( + MSG_PUBLIC_ADDRESS, + "Adres publiczny" + ) +MSG_HASH( + MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN, + "Brak argumentów i brak wbudowanego menu, wyświetlanie pomocy..." + ) +MSG_HASH( + MSG_NETPLAY_USERS_HAS_FLIPPED, + "Użytkownicy Netplay odwrócili się" + ) +MSG_HASH( + MSG_SETTING_DISK_IN_TRAY, + "Ustawianie dysku w zasobniku" + ) +MSG_HASH( + MSG_WAITING_FOR_CLIENT, + "Czekam na klienta ..." + ) +MSG_HASH( + MSG_NETPLAY_YOU_HAVE_LEFT_THE_GAME, + "Opuściłeś grę" + ) +MSG_HASH( + MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N, + "Dołączyłeś jako gracz %d" + ) +MSG_HASH( + MSG_NETPLAY_IMPLEMENTATIONS_DIFFER, + "Implementacja różni się. Upewnij się, że używasz dokładnie tych samych wersji RetroArch i rdzenia." + ) +MSG_HASH( + MSG_NETPLAY_ENDIAN_DEPENDENT, + "Ten rdzeń nie obsługuje net-play między architekturami w tych systemach" + ) +MSG_HASH( + MSG_NETPLAY_PLATFORM_DEPENDENT, + "Ten rdzeń nie obsługuje netplay między architekturami" + ) +MSG_HASH( + MSG_NETPLAY_ENTER_PASSWORD, + "Wprowadź hasło do serwera netplay:" + ) +MSG_HASH( + MSG_NETPLAY_INCORRECT_PASSWORD, + "Niepoprawne hasło" + ) +MSG_HASH( + MSG_NETPLAY_SERVER_NAMED_HANGUP, + "\"%s\" Został rozłączony" + ) +MSG_HASH( + MSG_NETPLAY_SERVER_HANGUP, + "Klient netplay został odłączony" + ) +MSG_HASH( + MSG_NETPLAY_CLIENT_HANGUP, + "Netplay odłączony" + ) +MSG_HASH( + MSG_NETPLAY_CANNOT_PLAY_UNPRIVILEGED, + "Nie masz uprawnień do grania" + ) +MSG_HASH( + MSG_NETPLAY_CANNOT_PLAY_NO_SLOTS, + "Nie ma wolnych miejsc dla graczy" + ) +MSG_HASH( + MSG_NETPLAY_CANNOT_PLAY, + "Nie można przełączyć do trybu odtwarzania" + ) +MSG_HASH( + MSG_NETPLAY_PEER_PAUSED, + "Netplay \"%s\" wstrzymano" + ) +MSG_HASH( + MSG_NETPLAY_CHANGED_NICK, + "Twój pseudonim został zmieniony na \"%s\"" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_SHARED_CONTEXT, + "Nadaj rdzeniom sprzętowym własny prywatny kontekst. Unikaj konieczności przejmowania zmian stanu sprzętu pomiędzy klatkami." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_SETTINGS, + "Dostosuj ustawienia wyglądu ekranu menu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_HARD_SYNC, + "Hard-synchronize CPU i GPU. Zmniejsza opóźnienie kosztem wydajności." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_THREADED, + "Poprawia wydajność kosztem opóźnień i częstszego rwania wideo. Używaj tylko wtedy, gdy nie możesz uzyskać pełnej prędkości w przeciwnym razie." + ) +MSG_HASH( + MSG_AUDIO_VOLUME, + "Głośność dźwięku" + ) +MSG_HASH( + MSG_AUTODETECT, + "Automatyczne wykrywanie" + ) +MSG_HASH( + MSG_AUTOLOADING_SAVESTATE_FROM, + "Automatyczne ładowanie stanu zapisu" + ) +MSG_HASH( + MSG_CAPABILITIES, + "Możliwości" + ) +MSG_HASH( + MSG_CONNECTING_TO_NETPLAY_HOST, + "Łączenie z hostem gry" + ) +MSG_HASH( + MSG_CONNECTING_TO_PORT, + "Łączenie z portem" + ) +MSG_HASH( + MSG_CONNECTION_SLOT, + "Gniazdo połączenia" + ) +MSG_HASH( + MSG_SORRY_UNIMPLEMENTED_CORES_DONT_DEMAND_CONTENT_NETPLAY, + "Przepraszamy, niezaimplementowane: rdzenie, które nie wymagają treści, nie mogą uczestniczyć w grze sieciowej." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ACCOUNTS_CHEEVOS_PASSWORD, + "Hasło" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ACCOUNTS_CHEEVOS_SETTINGS, + "Konta Cheevos" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ACCOUNTS_CHEEVOS_USERNAME, + "Nazwa Użytkownika" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ACCOUNTS_LIST, + "Konta" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ACCOUNTS_LIST_END, + "Lista punktów klienta" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ACCOUNTS_RETRO_ACHIEVEMENTS, + "Retro Osiągniecia" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_LIST, + "Lista osiągnięć" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_LIST_HARDCORE, + "Lista osiągnięć (Hardcore)" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ADD_CONTENT_LIST, + "Skanuj zawartość" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONFIGURATIONS_LIST, + "Konfiguracje" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ADD_TAB, + "Importuj zawartość" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_NETPLAY_TAB, + "Pokoje Netplay" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ASK_ARCHIVE, + "Zapytać" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ASSETS_DIRECTORY, + "Assety" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_BLOCK_FRAMES, + "Zablokuj klatki" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_DEVICE, + "Urządzenie audio" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_DRIVER, + "Sterownik audio" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_DSP_PLUGIN, + "Plugin dzwięku DSP" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE, + "Włącz dźwięk" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_FILTER_DIR, + "Filtr audio" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_TURBO_DEADZONE_LIST, + "Turbo/Martwa strefa" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_LATENCY, + "Opóźnienie dźwięku (ms)" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_MAX_TIMING_SKEW, + "Maksymalne przesunięcie czasowe dźwięku" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_MUTE, + "Wycisz dźwięk" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_OUTPUT_RATE, + "Szybkość wyjścia audio (Hz)" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_RATE_CONTROL_DELTA, + "Dynamiczna kontrola szybkości audio" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_DRIVER, + "Sterownik Audio Resampler" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_SETTINGS, + "Dźwiek" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_SYNC, + "Synchronizacja dźwięku" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_VOLUME, + "Poziom głośności dźwięku (dB)" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_WASAPI_EXCLUSIVE_MODE, + "Tryb WASAPI" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_WASAPI_FLOAT_FORMAT, + "Format WASAPI Float" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_WASAPI_SH_BUFFER_LENGTH, + "Współdzielony bufor WASAPI" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUTOSAVE_INTERVAL, + "SaveRAM Autozapis Interwału" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUTO_OVERRIDES_ENABLE, + "Automatyczne zastępowanie plików" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUTO_REMAPS_ENABLE, + "Automatycznie ładuj pliki zmian" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUTO_SHADERS_ENABLE, + "Automatycznie załaduj Presety Shadera" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_BACK, + "Z powrotem" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_CONFIRM, + "Potwierdź" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_INFO, + "Info" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_QUIT, + "Wyjdź" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_SCROLL_DOWN, + "Przewiń w dół" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_SCROLL_UP, + "Przewiń do góry" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_START, + "Start" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_TOGGLE_KEYBOARD, + "Przełącz klawiaturę" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_TOGGLE_MENU, + "Przełącz menu" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS, + "Podstawowe ustawienia menu" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_CONFIRM, + "Potwierdz/OK" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_INFO, + "Info" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_QUIT, + "Wyjdź" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_SCROLL_UP, + "Przewiń do góry" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_START, + "Domyślne" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_TOGGLE_KEYBOARD, + "Przełącz klawiaturę" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BASIC_MENU_ENUM_CONTROLS_TOGGLE_MENU, + "Przełącz menu" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BLOCK_SRAM_OVERWRITE, + "Nie zastępuj SaveRAM przy ładowaniu stanu zapisu" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BLUETOOTH_ENABLE, + "Bluetooth Włącz" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BUILDBOT_ASSETS_URL, + "Adres URL zasobów Buildbot" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CACHE_DIRECTORY, + "Pamięć podręczna" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CAMERA_ALLOW, + "Zezwalaj na kamerę" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CAMERA_DRIVER, + "Sterownik kamery" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEAT, + "Oszukać" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEAT_APPLY_CHANGES, + "Zatwierdź zmiany" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEAT_DATABASE_PATH, + "Oszukane Pliki" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEAT_FILE, + "Oszukane Pliki" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEAT_FILE_LOAD, + "Załaduj oszukany plik" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEAT_FILE_SAVE_AS, + "Zapisz oszukany plik jako" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEAT_NUM_PASSES, + "Oszukane przepustki" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_DESCRIPTION, + "Opis" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_HARDCORE_MODE_ENABLE, + "Osiągnięcia Trybu Hardcore" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_LEADERBOARDS_ENABLE, + "Tabele wyników" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_BADGES_ENABLE, + "Odznaki osiągnięć" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ACHIEVEMENTS, + "Zablokowane osiągnięcia:" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY, + "Zablokowany" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_SETTINGS, + "Retro osiągnięcia" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_TEST_UNOFFICIAL, + "Sprawdź nieoficjalne osiągnięcia" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ACHIEVEMENTS, + "Odblokowane osiągnięcia:" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY, + "Odblokowany" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY_HARDCORE, + "Hardcore" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CHEEVOS_VERBOSE_ENABLE, + "Osiągnięcia trybu Pełnego" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CLOSE_CONTENT, + "Zamknij treść" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONFIG, + "Konfiguracja" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONFIGURATIONS, + "Załaduj konfigurację" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONFIGURATION_SETTINGS, + "Konfiguracja" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONFIG_SAVE_ON_EXIT, + "Zapisz konfigurację przy wyjściu" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONTENT_COLLECTION_LIST, + "Kolekcje" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONTENT_DATABASE_DIRECTORY, + "Baza danych" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONTENT_DIR, + "Zawartość" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONTENT_HISTORY_SIZE, + "Rozmiar listy historii") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_ENTRY_REMOVE, + "Zezwalaj na usuwanie wpisów") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SETTINGS, + "Szybkie menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_ASSETS_DIR, + "Pliki do pobrania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_ASSETS_DIRECTORY, + "Pliki do pobrania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_CHEAT_OPTIONS, + "Kody") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_COUNTERS, + "Liczniki rdzeniowe") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_ENABLE, + "Pokaż nazwę rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFORMATION, + "Informacje podstawowe") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_AUTHORS, + "Autorski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_CATEGORIES, + "Kategorie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_LABEL, + "Etykieta rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_NAME, + "Nazwa rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_FIRMWARE, + "Firmware(s)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_LICENSES, + "Licencje") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_PERMISSIONS, + "Uprawnienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_SUPPORTED_EXTENSIONS, + "Obsługiwane rozszerzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_SYSTEM_MANUFACTURER, + "Producent systemu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INFO_SYSTEM_NAME, + "Nawa systemu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_INPUT_REMAPPING_OPTIONS, + "Sterowanie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_LIST, + "Załaduj Rdzeń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_OPTIONS, + "Opcje") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_SETTINGS, + "Rdzeń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_SET_SUPPORTS_NO_CONTENT_ENABLE, + "Rozpocznij rdzeń automatycznie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_UPDATER_AUTO_EXTRACT_ARCHIVE, + "Automatycznie wyodrębnij pobrane archiwum") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_UPDATER_BUILDBOT_URL, + "Adres URL rdzeni Buildbot") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_UPDATER_LIST, + "Aktualizacja Rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_UPDATER_SETTINGS, + "Aktualizacja") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CPU_ARCHITECTURE, + "Architektura procesora:") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CPU_CORES, + "Rdzeń procesora") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CURSOR_DIRECTORY, + "Kursor") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CURSOR_MANAGER, + "Menedżer kursorów") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CUSTOM_RATIO, + "Niestandardowy współczynnik") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_MANAGER, + "Menedżer bazy danych") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_SELECTION, + "Wybór bazy danych") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DELETE_ENTRY, + "Usunąć") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FAVORITES, + "Katalog startowy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DIRECTORY_CONTENT, + "") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DIRECTORY_DEFAULT, + "") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DIRECTORY_NONE, + "<Żaden>") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND, + "Nie znaleziono katalogu.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DIRECTORY_SETTINGS, + "Informator") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DISK_CYCLE_TRAY_STATUS, + "Status tacy cyklowej dysku") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DISK_IMAGE_APPEND, + "Dołącz obraz dysku") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DISK_INDEX, + "Indeks dysku") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DISK_OPTIONS, + "Kontrola dysku") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DONT_CARE, + "Nie przejmuj się") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DOWNLOADED_FILE_DETECT_CORE_LIST, + "Pliki do pobrania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE, + "Pobierz rdzeń...") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_CONTENT, + "Program do pobierania treści") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DPI_OVERRIDE_ENABLE, + "Zastąp włączone DPI") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DPI_OVERRIDE_VALUE, + "Nadpisz DPI") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DRIVER_SETTINGS, + "Sterownik") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DUMMY_ON_CORE_SHUTDOWN, + "Atrapa rdzenia przy zatrzymaniu rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CHECK_FOR_MISSING_FIRMWARE, + "Sprawdź brakujące oprogramowanie sprzętowe przed ładowaniem") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DYNAMIC_WALLPAPER, + "Dynamiczne tło") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DYNAMIC_WALLPAPERS_DIRECTORY, + "Dynamiczne tła") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEEVOS_ENABLE, + "Włącz osiągnięcia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ENTRY_HOVER_COLOR, + "Zmodyfikowany kolor menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ENTRY_NORMAL_COLOR, + "Normalny kolor menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FALSE, + "Fałszywy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FASTFORWARD_RATIO, + "Maksymalna prędkość") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FAVORITES_TAB, + "Ulubione") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FPS_SHOW, + "Wyświetl ilość klatek na sekundę") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FRAME_THROTTLE_ENABLE, + "Ogranicz maksymalną prędkość działania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FRAME_THROTTLE_SETTINGS, + "Przepustnica klatek") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FRONTEND_COUNTERS, + "Liczniki frontendu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_GAME_SPECIFIC_OPTIONS, + "Automatycznie ładuj zależne od zawartości opcje rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_GAME_SPECIFIC_OPTIONS_CREATE, + "Utwórz plik opcji gry") +MSG_HASH(MENU_ENUM_LABEL_VALUE_GAME_SPECIFIC_OPTIONS_IN_USE, + "Plik opcji gry") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP, + "Pomoc") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_AUDIO_VIDEO_TROUBLESHOOTING, + "Rozwiązywanie problemów audio / wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_CHANGE_VIRTUAL_GAMEPAD, + "Zmiana nakładki wirtualnego gamepada") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_CONTROLS, + "Podstawowe kontrolki menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_LIST, + "Pomoc") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_LOADING_CONTENT, + "Ładowanie zawartości") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_SCANNING_CONTENT, + "Skanowanie w poszukiwaniu treści") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HELP_WHAT_IS_A_CORE, + "Co to jest rdzeń?") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HISTORY_LIST_ENABLE, + "Włącz liste historii") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HISTORY_TAB, + "Historia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_HORIZONTAL_MENU, + "Menu poziome") +MSG_HASH(MENU_ENUM_LABEL_VALUE_IMAGES_TAB, + "Obraz") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INFORMATION, + "Informacja") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INFORMATION_LIST, + "Informacja") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ADC_TYPE, + "Typ analogowo-cyfrowy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ALL_USERS_CONTROL_MENU, + "Menu sterowania wszystkich użytkowników") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X, + "Lewy Analog X") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X_MINUS, + "Lewy analog X - (lewy)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X_PLUS, + "Lewy analog X + (po prawej)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y, + "Left Analog Y") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y_MINUS, + "Lewy analogo Y- (w górę)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y_PLUS, + "Lewy analogo Y + (dół)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X, + "Prawo Analog X") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X_MINUS, + "Prawy analog X- (po lewej)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X_PLUS, + "Prawy analog X + (po prawej)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y, + "Prawo analog Y") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_MINUS, + "Prawy analog Y- (w górę)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_PLUS, + "Prawe analog Y + (w dół)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, + "Spust broni") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_RELOAD, + "Przeładowanie broni") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_A, + "Aux A broni") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_B, + "Aux B broni") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_C, + "Gun Aux C") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_START, + "Start broni") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_SELECT, + "Wybierz broń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_UP, + "D-pad góra broń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_DOWN, + "D-pad dół broń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_LEFT, + "D-pad lewo broń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_RIGHT, + "D-pad prawo broń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_AUTODETECT_ENABLE, + "Włącz Autoconfig") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_AXIS_THRESHOLD, + "Martwa strefa gałki analogowej") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_INPUT_SWAP_OK_CANCEL, + "Zamień Menu OK i Anuluj przyciski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_BIND_ALL, + "Zwiąż wszystko") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_BIND_DEFAULT_ALL, + "Wszystkie domyślne powiązania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_BIND_TIMEOUT, + "Limit czasu wiązania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_DESCRIPTOR_HIDE_UNBOUND, + "Ukryj niezwiązane podstawowe deskryptory wejściowe") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_DESCRIPTOR_LABEL_SHOW, + "Wyświetl etykiety deskryptorów wejściowych") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_INDEX, + "Indeks urządzeń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_TYPE, + "Rodzaj urządzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_INDEX, + "Indeks myszy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_DRIVER, + "Sterownik wejściowy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_DUTY_CYCLE, + "Cykl obciążenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BINDS, + "Wejściowe powiązania skrótów") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_ICADE_ENABLE, + "Włączanie mapowania gamepada klawiatury") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_A, + "Przycisk (po prawej)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_B, + "Przycisk B (w dół)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_DOWN, + "W dół D-pad") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_L2, + "Przycisk L2 (spust)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_L3, + "Przycisk L3") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_L, + "Przycisk L (ramię)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_LEFT, + "Lewy D-pad") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_R2, + "R2 przycisk (spust)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_R3, + "R3 przycisk") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_R, + "Przycisk R") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_RIGHT, + "Prawy D-pad") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_SELECT, + "Wybierz przycisk") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_START, + "Przycisk Start") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_UP, + "Do góry D-pad") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_X, + "Przycisk X (u góry)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_Y, + "Przycisk Y (po lewej)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_KEY, + "(Klucz: %s)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_LEFT, + "Mysz 1") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_RIGHT, + "Mysz 2") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_MIDDLE, + "Mysz 3") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_BUTTON4, + "Mysz 4") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_BUTTON5, + "Mysz 5") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_WHEEL_UP, + "Kółko do góry") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_WHEEL_DOWN, + "Kółko do dołu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_HORIZ_WHEEL_UP, + "Kółko w lewo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_HORIZ_WHEEL_DOWN, + "Kółko w prawo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_KEYBOARD_GAMEPAD_MAPPING_TYPE, + "Typ odwzorowania klawiatury gamepada") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MAX_USERS, + "Maksymalna liczba użytkowników") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO, + "Menu Przełączenia Gamepad Combo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_CHEAT_INDEX_MINUS, + "Indeks oszustw -") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_CHEAT_INDEX_PLUS, + "Indeks oszustw +") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_CHEAT_TOGGLE, + "Włącz oszustwa") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_EJECT_TOGGLE, + "Przełącznik wysuwania dysku") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_NEXT, + "Dysk następny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_PREV, + "Dysk poprzedni") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_ENABLE_HOTKEY, + "Włącz klawisze skrótów") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_FAST_FORWARD_HOLD_KEY, + "Szybkie zatrzymanie do przodu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_FAST_FORWARD_KEY, + "Szybkie przewijanie do przodu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_FRAMEADVANCE, + "Zawansowane klatki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_FULLSCREEN_TOGGLE_KEY, + "Przełączanie pełnoekranowe") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_GRAB_MOUSE_TOGGLE, + "Sprawdź przełącznik myszy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_GAME_FOCUS_TOGGLE, + "Przełącznik ostrości gry") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_LOAD_STATE_KEY, + "Stan obciążenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MENU_TOGGLE, + "Przełączanie menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE, + "Przełącznik nagrywania filmu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE, + "Przełącznik wyciszania dźwięku") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP, + "Netplay przerzuca użytkowników") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH, + "Netplay przełącza tryb play / spectate") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK, + "Przełączanie klawiatury ekranowej") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OVERLAY_NEXT, + "Nakładka next") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_PAUSE_TOGGLE, + "Wstrzymaj przełącznik") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY, + "Zamknij RetroArch") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_RESET, + "Zresetuj grę") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_REWIND, + "Przewijanie do tyłu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_STATE_KEY, + "Zapisz stan") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_SCREENSHOT, + "Zrob zrzut ekranu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_NEXT, + "Następny moduł cieniujący") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_PREV, + "Poprzedni moduł cieniujący") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION, + "Zwolnione tempo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_MINUS, + "Slot zapisu -") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_PLUS, + "Slot zapisu +") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_VOLUME_DOWN, + "Głośność -") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_VOLUME_UP, + "Głośność +") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_OVERLAY_ENABLE, + "Wyświetl nakładkę") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_OVERLAY_HIDE_IN_MENU, + "Ukryj nakładkę w menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS, + "Pokaż nakładki na nakładce") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS_PORT, + "Pokaż wejścia Posłuchaj portu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR, + "Zachowanie typu ankiety") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_EARLY, + "Wcześnie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_LATE, + "Późno") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR_NORMAL, + "Normalny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_PREFER_FRONT_TOUCH, + "Preferuj Front Touch") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_REMAPPING_DIRECTORY, + "Odwzorowanie wejścia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_REMAP_BINDS_ENABLE, + "Włącz Remap Binds") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_SAVE_AUTOCONFIG, + "Zapisz Autoconfig") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_SETTINGS, + "Wkład") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_SMALL_KEYBOARD_ENABLE, + "Włącz małą klawiaturę") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_TOUCH_ENABLE, + "Włącz dotyk") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_TURBO_ENABLE, + "Włącz turbo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_TURBO_PERIOD, + "Okres Turbo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_USER_BINDS, + "Wprowadź użytkownika %u Binds") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INTERNAL_STORAGE_STATUS, + "Status wewnętrznej pamięci") +MSG_HASH(MENU_ENUM_LABEL_VALUE_JOYPAD_AUTOCONFIG_DIR, + "Wprowadź Autoconfig") +MSG_HASH(MENU_ENUM_LABEL_VALUE_JOYPAD_DRIVER, + "Sterownik Joypada") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LAKKA_SERVICES, + "Usługi") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_CHINESE_SIMPLIFIED, + "chiński (Simplified)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_CHINESE_TRADITIONAL, + "chiński (Tradycyjny)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_DUTCH, + "holenderski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_ENGLISH, + "angielski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_ESPERANTO, + "esperanto") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_FRENCH, + "Francuski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_GERMAN, + "niemiecki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_ITALIAN, + "włoski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_JAPANESE, + "japoński") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_KOREAN, + "koreański") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_POLISH, + "polski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_PORTUGUESE_BRAZIL, + "portugalski (brazylia)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_PORTUGUESE_PORTUGAL, + "portugalski (portugalia)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_RUSSIAN, + "Russianrosyjski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_SPANISH, + "Spanish") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LANG_VIETNAMESE, + "wietnamski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LEFT_ANALOG, + "Lewy analogowy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LIBRETRO_DIR_PATH, + "Rdzeń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LIBRETRO_INFO_PATH, + "Informacje o rdzeniu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LIBRETRO_LOG_LEVEL, + "Poziom zalogowania rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LINEAR, + "Liniowy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LOAD_ARCHIVE, + "Załaduj archiwum") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_HISTORY, + "Załaduj ostatnie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_LIST, + "Załaduj zawartość") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LOAD_STATE, + "Stan obciążenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LOCATION_ALLOW, + "Zezwalaj na lokalizację") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LOCATION_DRIVER, + "Sterownik lokalizacji") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LOGGING_SETTINGS, + "Zalogowanie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_LOG_VERBOSITY, + "Zalogowanie rozmowy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MAIN_MENU, + "Menu główne") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MANAGEMENT, + "Ustawienia bazy danych") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_COLOR_THEME, + "Kolor menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_COLOR_THEME_BLUE, + "Niebieski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_COLOR_THEME_BLUE_GREY, + "Niebiesko szary") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_COLOR_THEME_DARK_BLUE, + "Ciemny niebieski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_COLOR_THEME_GREEN, + "Zielony") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_COLOR_THEME_NVIDIA_SHIELD, + "Tarcza") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_COLOR_THEME_RED, + "Czerwony") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_COLOR_THEME_YELLOW, + "Żółty") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_FOOTER_OPACITY, + "Nieprzezroczystość stopki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_HEADER_OPACITY, + "Nieprzezroczystość nagłówka") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_DRIVER, + "Sterownik menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_ENUM_THROTTLE_FRAMERATE, + "Menu obrotowe przepustnicy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FILE_BROWSER_SETTINGS, + "Ustawienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_LINEAR_FILTER, + "Menu filtra liniowego") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_HORIZONTAL_ANIMATION, + "Animacja pozioma") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SETTINGS, + "Wygląd") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_WALLPAPER, + "Tło") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_WALLPAPER_OPACITY, + "Nieprzezroczystość tła") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MISSING, + "Brakujący") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MORE, + "...") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MOUSE_ENABLE, + "Obsługa myszy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MULTIMEDIA_SETTINGS, + "Multimedia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MUSIC_TAB, + "Muzyka") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE, + "Filtruj nieznane rozszerzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NAVIGATION_WRAPAROUND, + "Nawigacja owinięciem") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NEAREST, + "Najbliższy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY, + "Netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ALLOW_SLAVES, + "Zezwalaj na klientów w trybie slave") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CHECK_FRAMES, + "Netplay sprawdź klatki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN, + "Wejściowe klatki opóźnień") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE, + "Zakres latencji wejściowych klatek") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT, + "Netplay P2 Używa C1") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES, + "Netplay opóźnij klatki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT, + "Odłącz od hosta netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE, + "Włącz Netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE_CLIENT, + "Połącz się z hostem netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE_HOST, + "Uruchom hosta netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISABLE_HOST, + "Zatrzymaj hosta gry") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_IP_ADDRESS, + "Adres serwera") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_LAN_SCAN_SETTINGS, + "Zeskanuj sieć lokalną") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_MODE, + "Włącz klienta Netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_NICKNAME, + "Nazwa Użytkownika") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_PASSWORD, + "Hasło serwera") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_PUBLIC_ANNOUNCE, + "Publicznie ogłosić grę na Netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_REQUIRE_SLAVES, + "Odmów klientów w trybie innym niż slave") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SETTINGS, + "Ustawienia Netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_START_AS_SPECTATOR, + "Tryb Netplay Spectator") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_STATELESS_MODE, + "Tryb bezstanowej Netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SPECTATE_PASSWORD, + "Hasło spontaniczne serwera") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SPECTATOR_MODE_ENABLE, + "Netplay Spectator Włączone") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_TCP_UDP_PORT, + "Port TCP Netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_NAT_TRAVERSAL, + "Netplay NAT Traversal") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETWORK_CMD_ENABLE, + "Polecenia sieciowe") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETWORK_CMD_PORT, + "Port poleceń sieciowych") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETWORK_INFORMATION, + "Informacje o sieci") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETWORK_REMOTE_ENABLE, + "Gamepad sieciowy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETWORK_REMOTE_PORT, + "Port zdalnej sieci") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETWORK_SETTINGS, + "Sieć") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO, + "Nie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NONE, + "Nic") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE, + "N/A") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_ACHIEVEMENTS_TO_DISPLAY, + "Brak osiągnięć do wyświetlenia.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_CORE, + "Bez rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_CORES_AVAILABLE, + "Brak dostępnych rdzeni.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_CORE_INFORMATION_AVAILABLE, + "Brak dostępnych podstawowych informacji.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_CORE_OPTIONS_AVAILABLE, + "Brak opcji podstawowych rdzenia.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY, + "Brak wpisów do wyświetlenia.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_HISTORY_AVAILABLE, + "Brak historii.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_INFORMATION_AVAILABLE, + "Brak informacji.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_ITEMS, + "Nie ma przedmiotów.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_NETPLAY_HOSTS_FOUND, + "Nie znaleziono hostów netplay.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_NETWORKS_FOUND, + "Nie znaleziono sieci.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_PERFORMANCE_COUNTERS, + "Brak liczników wydajności.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_PLAYLISTS, + "Brak playlist.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_PLAYLIST_ENTRIES_AVAILABLE, + "Brak dostępnych pozycji na liście odtwarzania.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND, + "Nie znaleziono ustawień.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NO_SHADER_PARAMETERS, + "Brak parametrów modułu cieniującego.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OFF, + "OFF") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ON, + "ON") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ONLINE, + "Online") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ONLINE_UPDATER, + "Online Updater") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ONSCREEN_DISPLAY_SETTINGS, + "Wyświetlacz na ekranie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ONSCREEN_OVERLAY_SETTINGS, + "Nakładka na ekranie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ONSCREEN_NOTIFICATIONS_SETTINGS, + "Powiadomienia na ekranie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OPEN_ARCHIVE, + "Przeglądaj archiwum") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OPTIONAL, + "Opcjonalny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OVERLAY, + "Nakładka") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OVERLAY_AUTOLOAD_PREFERRED, + "Automatyczna preferowana nakładka") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OVERLAY_DIRECTORY, + "Nakładka") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OVERLAY_OPACITY, + "Krycie nakładki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OVERLAY_PRESET, + "Ustawienia nakładki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OVERLAY_SCALE, + "Skala nakładki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_OVERLAY_SETTINGS, + "Nakładka na ekranie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PAL60_ENABLE, + "Użyj trybu PAL60") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PARENT_DIRECTORY, + "Nadrzędna Lokalizacja") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PAUSE_LIBRETRO, + "Wstrzymaj przy włączonym menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PAUSE_NONACTIVE, + "Nie uruchamiaj się w tle") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PERFCNT_ENABLE, + "Liczniki wydajności") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB, + "Listy odtwarzania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_DIRECTORY, + "Playlista") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_SETTINGS, + "Listy odtwarzania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_POINTER_ENABLE, + "Dotknij Wsparcie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PORT, + "Port") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PRESENT, + "Obecny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PRIVACY_SETTINGS, + "Prywatność") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUIT_RETROARCH, + "Zamknij RetroArch") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ANALOG, + "Obsługiwany analog") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_BBFC_RATING, + "Ocena BBFC") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_CERO_RATING, + "Ocena CERO") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_COOP, + "Kooperacja wspierana") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_CRC32, + "CRC32") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_DESCRIPTION, + "Opis") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_DEVELOPER, + "Deweloper") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_EDGE_MAGAZINE_ISSUE, + "Problem z Edge Magazine") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_EDGE_MAGAZINE_RATING, + "Ocena magazynu Edge") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_EDGE_MAGAZINE_REVIEW, + "Recenzja magazynu Edge") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ELSPA_RATING, + "Ocena ELSPA") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ENHANCEMENT_HW, + "Sprzęt ulepszający") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ESRB_RATING, + "Ocena ESRB") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_FAMITSU_MAGAZINE_RATING, + "Ocena magazynu Famitsu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_FRANCHISE, + "Franczyzowa") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_GENRE, + "Gatunek muzyczny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_MD5, + "MD5") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_NAME, + "Nazwa") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ORIGIN, + "Pochodzenie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_PEGI_RATING, + "Ocena PEGI") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_PUBLISHER, + "Wydawca") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_RELEASE_MONTH, + "Data wydania miesiąca") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_RELEASE_YEAR, + "Rok wydania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_RUMBLE, + "Rumble obsługiwane") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_SERIAL, + "Seryjny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_SHA1, + "SHA1") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_START_CONTENT, + "Rozpocznij zawartość") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_TGDB_RATING, + "Ocena TGDB") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REBOOT, + "Restart") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORDING_CONFIG_DIRECTORY, + "Konfig. Nagrywania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORDING_OUTPUT_DIRECTORY, + "Wyjście nagrywania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORDING_SETTINGS, + "Nagranie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORD_CONFIG, + "Załaduj konfigurację nagrywania...") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORD_DRIVER, + "Sterowniki nagrywania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORD_ENABLE, + "Włącz nagrywanie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORD_PATH, + "Zapisz zapisywanie wyjścia jako...") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RECORD_USE_OUTPUT_DIRECTORY, + "Zapisz nagrania w katalogu wyjściowym") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REMAP_FILE, + "Plik zmian") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REMAP_FILE_LOAD, + "Załaduj plik zmiany") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REMAP_FILE_SAVE_CORE, + "Zapisz plik zmiany rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REMAP_FILE_SAVE_GAME, + "Zapisz plik zmiany gry") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REMAP_FILE_REMOVE_CORE, + "Usuń plik zmiany rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REMAP_FILE_REMOVE_GAME, + "Usuń plik zmiany gry") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REQUIRED, + "Wymagany") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RESTART_CONTENT, + "Uruchom ponownie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RESTART_RETROARCH, + "Uruchom ponownie RetroArch") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RESUME, + "Wznaw") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RESUME_CONTENT, + "Wznaw") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RETROKEYBOARD, + "Retro klawiatura") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RETROPAD, + "Retro pad") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RETROPAD_WITH_ANALOG, + "Retro pad w/ Analog") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RETRO_ACHIEVEMENTS_SETTINGS, + "Osiągnięcia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REWIND_ENABLE, + "Włącz przewianie do tyłu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REWIND_GRANULARITY, + "Przewijanie granularności") +MSG_HASH(MENU_ENUM_LABEL_VALUE_REWIND_SETTINGS, + "Przewijanie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RGUI_BROWSER_DIRECTORY, + "Przeglądarka plików") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RGUI_CONFIG_DIRECTORY, + "Config") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RGUI_SHOW_START_SCREEN, + "Wyświetl ekran startowy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RIGHT_ANALOG, + "Prawy Analog") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_FAVORITES, + "Dodaj do ulubionych") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_FAVORITES_PLAYLIST, + "Dodaj do ulubionych") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RUN, + "Biec") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RUN_MUSIC, + "Biec") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAMBA_ENABLE, + "Włącz SAMBA") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVEFILE_DIRECTORY, + "Zapisz plik") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_INDEX, + "Zapisz indeks auto stanu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_LOAD, + "Automatyczne załadowanie stanu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATE_AUTO_SAVE, + "Automatyczne zapisanie stanu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATE_DIRECTORY, + "Zapisz stan") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATE_THUMBNAIL_ENABLE, + "Zapisz Miniatury") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG, + "Zapisz bieżącą konfigurację") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG_OVERRIDE_CORE, + "Zapisz przesłonięcia rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG_OVERRIDE_GAME, + "Zapisz nadpisania gry") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_NEW_CONFIG, + "Zapisz nową konfigurację") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVE_STATE, + "Zapisz stans") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVING_SETTINGS, + "Zapisywanie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SCAN_DIRECTORY, + "Skanuj katalog") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SCAN_FILE, + "Zeskanuj plik") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SCAN_THIS_DIRECTORY, + "") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SCREENSHOT_DIRECTORY, + "Zrzut ekranu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SCREEN_RESOLUTION, + "Rozdzielczość ekranu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SEARCH, + "Szukaj") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SECONDS, + "sekundy") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SETTINGS, + "Ustawienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SETTINGS_TAB, + "Ustawienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER, + "Shader") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_APPLY_CHANGES, + "Zatwierdź zmiany") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS, + "Shadery") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_RIBBON, + "Wstążka") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_RIBBON_SIMPLIFIED, + "Wstążka (uproszczona)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_SIMPLE_SNOW, + "Prosty śnieg") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_SNOW, + "Śnieg") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHOW_ADVANCED_SETTINGS, + "Pokaż ustawienia zaawansowane") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHOW_HIDDEN_FILES, + "Pokaż ukryte pliki i foldery") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHUTDOWN, + "Zamknąć") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SLOWMOTION_RATIO, + "Współczynnik powolnego ruchu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SORT_SAVEFILES_ENABLE, + "Sort Saves In Folders") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SORT_SAVESTATES_ENABLE, + "Sortuj zapisz stany w folderach") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVESTATES_IN_CONTENT_DIR_ENABLE, + "Napisz zapis stanów do treści dir") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SAVEFILES_IN_CONTENT_DIR_ENABLE, + "Napisz zapisuje do treści dir") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEMFILES_IN_CONTENT_DIR_ENABLE, + "Pliki systemowe znajdują się w katalogu treści") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SCREENSHOTS_IN_CONTENT_DIR_ENABLE, + "Zapisuj zrzuty ekranu w katalog treści") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SSH_ENABLE, + "Włącz SSH") +MSG_HASH(MENU_ENUM_LABEL_VALUE_START_CORE, + "Rozpocznij rdzeń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_START_NET_RETROPAD, + "Uruchom zdalny Retro pad") +MSG_HASH(MENU_ENUM_LABEL_VALUE_START_VIDEO_PROCESSOR, + "Uruchom procesor wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_STATE_SLOT, + "Slot stanu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_STATUS, + "Status") +MSG_HASH(MENU_ENUM_LABEL_VALUE_STDIN_CMD_ENABLE, + "Polecenia STDIN") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SUPPORTED_CORES, + "Sugerowane rdzenie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSPEND_SCREENSAVER_ENABLE, + "Wstrzymaj wygaszacz ekranu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_BGM_ENABLE, + "Włącz System BGM ") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_DIRECTORY, + "System/BIOS") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFORMATION, + "Informacje o systemie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_7ZIP_SUPPORT, + "Obsługa 7zip") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ALSA_SUPPORT, + "Obsługa ALSA") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_BUILD_DATE, + "Data Builda") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CG_SUPPORT, + "Wsparcie Cg") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_COCOA_SUPPORT, + "Wsparcie Cocoa") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_COMMAND_IFACE_SUPPORT, + "Obsługa interfejsu poleceń") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CORETEXT_SUPPORT, + "Obsługa CoreText") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CPU_FEATURES, + "Funkcje procesora") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_DPI, + "Wyświetl DPI metryczne") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_HEIGHT, + "Wyświetl wysokość metryczną (mm)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_WIDTH, + "Wyświetl szerokość metryczną (mm)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DSOUND_SUPPORT, + "Wsparcie DirectSound") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_WASAPI_SUPPORT, + "Obsługa WASAPI") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DYLIB_SUPPORT, + "Obsługa dynamicznej biblioteki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DYNAMIC_SUPPORT, + "Dynamiczne ładowanie biblioteki libretro") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_EGL_SUPPORT, + "Wsparcie EGL") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FBO_SUPPORT, + "Obsługuje renderowanie do tekstury (shadery wieloprzebiegowe) OpenGL / Direct3D") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FFMPEG_SUPPORT, + "Wsparcie FFmpeg") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FREETYPE_SUPPORT, + "Wsparcie FreeType") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_IDENTIFIER, + "Identyfikator Frontendu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_NAME, + "Nazwa frontendu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_OS, + "System operacyjny Frontend") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_GIT_VERSION, + "Wersja Git") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_GLSL_SUPPORT, + "Wsparcie GLSL") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_HLSL_SUPPORT, + "Wsparcie HLSL") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_JACK_SUPPORT, + "Obsługa JACK") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_KMS_SUPPORT, + "Obsługa KMS / EGL") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LAKKA_VERSION, + "Wersja Lakka") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBRETRODB_SUPPORT, + "Obsługa LibretroDB") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBUSB_SUPPORT, + "Wsparcie Libusb") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBXML2_SUPPORT, + "libxml2 Obsługa parsowania XML") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETPLAY_SUPPORT, + "Wsparcie Netplay (peer-to-peer)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETWORK_COMMAND_IFACE_SUPPORT, + "Obsługa interfejsu sieciowego Command") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETWORK_REMOTE_SUPPORT, + "Obsługa sieciowego gamepada") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENAL_SUPPORT, + "Obsługa OpenAL") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENGLES_SUPPORT, + "Obsługa OpenGL ES") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENGL_SUPPORT, + "Obsługa OpenGL") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENSL_SUPPORT, + "Obsługa OpenSL") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENVG_SUPPORT, + "Obsługa OpenVG") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OSS_SUPPORT, + "Obsługa OSS") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OVERLAY_SUPPORT, + "Obsługa nakładek") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE, + "Źródło prądu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_CHARGED, + "Naładowany") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_CHARGING, + "Ładowanie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_DISCHARGING, + "Rozładowywanie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_NO_SOURCE, + "Brak źródła") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_PULSEAUDIO_SUPPORT, + "Obsługa PulseAudio") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_PYTHON_SUPPORT, + "Obsługa Pythona (obsługa skryptów w modułach cieniujących)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RBMP_SUPPORT, + "Obsługa BMP (RBMP)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RETRORATING_LEVEL, + "Poziom RetroRating") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RJPEG_SUPPORT, + "Obsługa JPEG (RJPEG)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ROARAUDIO_SUPPORT, + "Obsługa RoarAudio") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RPNG_SUPPORT, + "Obsługa PNG (RPNG)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RSOUND_SUPPORT, + "Wsparcie RSound") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RTGA_SUPPORT, + "Obsługa TGA (RTGA)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SDL2_SUPPORT, + "Wsparcie SDL2") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SDL_IMAGE_SUPPORT, + "Obsługa obrazów SDL") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SDL_SUPPORT, + "Wsparcie SDL1.2") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SLANG_SUPPORT, + "Obsługa Slangu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_THREADING_SUPPORT, + "Gwintowanie wsparcia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_UDEV_SUPPORT, + "Wsparcie dla Udev") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_V4L2_SUPPORT, + "Obsługa Video4Linux2") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_VIDEO_CONTEXT_DRIVER, + "Sterownik kontekstowy wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_VULKAN_SUPPORT, + "Wsparcie Vulkan") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_WAYLAND_SUPPORT, + "Obsługa Wayland") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_X11_SUPPORT, + "Wsparcie X11") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_XAUDIO2_SUPPORT, + "Wsparcie XAudio2") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_XVIDEO_SUPPORT, + "Wsparcie XVideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ZLIB_SUPPORT, + "Obsługa Zlib") +MSG_HASH(MENU_ENUM_LABEL_VALUE_TAKE_SCREENSHOT, + "Zrobić zrzut ekranu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_THREADED_DATA_RUNLOOP_ENABLE, + "Zadania z wątkami") +MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS, + "Miniatury") +MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS_DIRECTORY, + "Miniatury") +MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAILS_UPDATER_LIST, + "Zaktualizuj Miniatury") +MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_BOXARTS, + "Boxarts") +MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_SCREENSHOTS, + "Zrzuty ekranu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_TITLE_SCREENS, + "Ekrany tytułowe") +MSG_HASH(MENU_ENUM_LABEL_VALUE_TIMEDATE_ENABLE, + "Pokaż datę / czas") +MSG_HASH(MENU_ENUM_LABEL_VALUE_TITLE_COLOR, + "Kolor tytułu menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_TRUE, + "Prawdziwe") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UI_COMPANION_ENABLE, + "Włącz Companion UI") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UI_COMPANION_START_ON_BOOT, + "Włącz przy starcie UI Companion") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UI_MENUBAR_ENABLE, + "Pasek menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UNABLE_TO_READ_COMPRESSED_FILE, + "Nie można odczytać skompresowanego pliku.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UNDO_LOAD_STATE, + "Cofnij ładowanie stanu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UNDO_SAVE_STATE, + "Cofnij zapisanie stanu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UNKNOWN, + "Nieznany") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATER_SETTINGS, + "Aktualizator") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_ASSETS, + "Zaktualizuj zasoby") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_AUTOCONFIG_PROFILES, + "Zaktualizuj profile Joypad") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_CG_SHADERS, + "Zaktualizuj shadery CG") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_CHEATS, + "Zaktualizuj kody") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_CORE_INFO_FILES, + "Zaktualizuj podstawowe pliki informacyjne") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_DATABASES, + "Zaktualizuj bazy danych") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_GLSL_SHADERS, + "Zaktualizuj shadery GLSL") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_LAKKA, + "Zaktualizuj Lakka") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_OVERLAYS, + "Zaktualizuj nakładki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_UPDATE_SLANG_SHADERS, + "Zaktualizuj Shadery Slang") +MSG_HASH(MENU_ENUM_LABEL_VALUE_USER, + "Użytkownik") +MSG_HASH(MENU_ENUM_LABEL_VALUE_KEYBOARD, + "Kbd") +MSG_HASH(MENU_ENUM_LABEL_VALUE_USER_INTERFACE_SETTINGS, + "Interfejs użytkownika") +MSG_HASH(MENU_ENUM_LABEL_VALUE_USER_LANGUAGE, + "Język") +MSG_HASH(MENU_ENUM_LABEL_VALUE_USER_SETTINGS, + "Użytkownik") +MSG_HASH(MENU_ENUM_LABEL_VALUE_USE_BUILTIN_IMAGE_VIEWER, + "Użyj wbudowanej przeglądarki zdjęć") +MSG_HASH(MENU_ENUM_LABEL_VALUE_USE_BUILTIN_PLAYER, + "Użyj wbudowanego odtwarzacza multimedialnego") +MSG_HASH(MENU_ENUM_LABEL_VALUE_USE_THIS_DIRECTORY, + "") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ALLOW_ROTATE, + "Pozwól rotacji") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO, + "Konfiguruj współczynnik kształtu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO_AUTO, + "Auto. Współczynnik proporcji") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ASPECT_RATIO_INDEX, + "Współczynnik proporcji") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_BLACK_FRAME_INSERTION, + "Wstawianie czarnej klatki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_CROP_OVERSCAN, + "Przytnij Overscan (Przeładuj)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_DISABLE_COMPOSITION, + "Wyłącz kompozycję pulpitu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_DRIVER, + "Sterownik wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FILTER, + "Filtr wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FILTER_DIR, + "Filtr wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FILTER_FLICKER, + "Filtr migotania") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FONT_ENABLE, + "Włącz powiadomienia na ekranie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FONT_PATH, + "Czcionka powiadomienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FONT_SIZE, + "Rozmiar powiadomienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FORCE_ASPECT, + "Wymuś współczynnik proporcji") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FORCE_SRGB_DISABLE, + "Wymuś wyłączenie sRGB FBO") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY, + "Opóźnienie ramki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FULLSCREEN, + "Użyj trybu pełnoekranowego") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GAMMA, + "Gamma wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GPU_RECORD, + "Użyj zapisu GPU") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GPU_SCREENSHOT, + "Włącz zrzut ekranu GPU ") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC, + "Trudna synchronizacja z GPU") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC_FRAMES, + "Twarde ramki do synchronizacji z GPU") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MAX_SWAPCHAIN_IMAGES, + "Maksymalne obrazy swapchain") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_POS_X, + "Pozycja X powiadomienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_POS_Y, + "Pozycja Y powiadomienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MONITOR_INDEX, + "Monitoruj indeks") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_POST_FILTER_RECORD, + "Użyj funkcji Nagrywania po filtrowaniu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE, + "Odświeżanie w pionie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_REFRESH_RATE_AUTO, + "Szacunkowa liczba klatek na sekundę na ekranie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_ROTATION, + "Obrót") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE, + "Skala okienkowa") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SCALE_INTEGER, + "Skala całkowita") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SETTINGS, + "Wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_DIR, + "Moduł cieniujący wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_NUM_PASSES, + "Shader Pass") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PARAMETERS, + "Podgląd parametrów modułu cieniującego") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET, + "Załaduj ustawienia Shader") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_PARAMETERS, + "Parametry menu Shadera") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_AS, + "Zapisz ustawienie Shadera jako") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_CORE, + "Zapis ustawienia podstawowe rdzenia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_GAME, + "Zapisz ustawienie gry") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SHARED_CONTEXT, + "Włącz udostępniony kontekst sprzętu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SMOOTH, + "Filtrowanie bilinearne") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SOFT_FILTER, + "Włącz filtr miękki") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_SWAP_INTERVAL, + "Interwał wymiany pionowej synchronizacji (Vsync)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_TAB, + "Wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_THREADED, + "Wątek wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_VFILTER, + "Deflicker") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_VIEWPORT_CUSTOM_HEIGHT, + "Niestandardowy współczynnik proporcji Wysokość") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_VIEWPORT_CUSTOM_WIDTH, + "Niestandardowy współczynnik proporcji Szerokość") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_VIEWPORT_CUSTOM_X, + "Niestandardowy współczynnik kształtu X Poz.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_VIEWPORT_CUSTOM_Y, + "Niestandardowy współczynnik kształtu Y Poz.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_VI_WIDTH, + "Ustaw VI szerokość ekranu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_VSYNC, + "Synchronizacja pionowa (Vsync)") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOWED_FULLSCREEN, + "Tryb pełnoekranowy z pełnym ekranem") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_WIDTH, + "Szerokość okna") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_HEIGHT, + "Wysokość okna") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FULLSCREEN_X, + "Pełna szerokość ekranu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FULLSCREEN_Y, + "Pełnoekranowa wysokość") +MSG_HASH(MENU_ENUM_LABEL_VALUE_WIFI_DRIVER, + "Sterownik Wi-Fi") +MSG_HASH(MENU_ENUM_LABEL_VALUE_WIFI_SETTINGS, + "Wi-Fi") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ALPHA_FACTOR, + "Menu Czynnik alfa") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_FONT, + "Czcionka menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_CUSTOM, + "Niestandardowy ") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_FLATUI, + "FlatUI") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_MONOCHROME, + "Monochromia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_SYSTEMATIC, + "Systematyczny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_NEOACTIVE, + "NeoActive") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_PIXEL, + "Pixel") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_RETROACTIVE, + "RetroActive") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_RETROSYSTEM, + "RetroSystem") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_ICON_THEME_DOTART, + "Dot-Art") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME, + "Kolor menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_APPLE_GREEN, + "Zielone jabłko") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_DARK, + "Ciemny") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_DARK_PURPLE, + "Ciemny fiolet") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_ELECTRIC_BLUE, + "Elektryczny błękit") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_GOLDEN, + "Złoty") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_LEGACY_RED, + "Czerwone dziedzictwo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_MIDNIGHT_BLUE, + "Niebieska północ") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_PLAIN, + "Zwykły") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_UNDERSEA, + "Podmorski") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_VOLCANIC_RED, + "Czerwień wulkaniczna") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_RIBBON_ENABLE, + "Menu Shader Pipeline") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SCALE_FACTOR, + "Współczynnik skali menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHADOWS_ENABLE, + "Włącz cienie ikony") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHOW_HISTORY, + "Pokaż kartę historii") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHOW_ADD, + "Pokaż kartę Importuj zawartość") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHOW_FAVORITES, + "Pokaż kartę Ulubione") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHOW_IMAGES, + "Pokaż kartę Obraz") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHOW_MUSIC, + "Pokaż kartę Muzyka") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHOW_SETTINGS, + "Pokaż kartę Ustawienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHOW_VIDEO, + "Pokaż kartę Wideo") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHOW_NETPLAY, + "Pokaż kartę Netplay") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_THEME, + "Motyw ikon menu") +MSG_HASH(MENU_ENUM_LABEL_VALUE_YES, + "Tak") +MSG_HASH(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_TWO, + "Ustawienia Shader") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_ENABLE, + "Włącz lub wyłącz osiągnięcia. Aby uzyskać więcej informacji, odwiedź http://retroachievements.org") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_TEST_UNOFFICIAL, + "Włącz lub wyłącz nieoficjalne osiągnięcia i / lub funkcje beta do celów testowych.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, + "Włączanie i wyłączanie stanów save, cheats, rewind, fast forward, pause i slow-motion dla wszystkich gier.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_LEADERBOARDS_ENABLE, + "Włącz lub wyłącz tabele wyników w grze. Nie działa, jeśli tryb Hardcore jest wyłączony.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_BADGES_ENABLE, + "Włącz lub wyłącz wyświetlanie znaczków na liście osiągnięć.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_VERBOSE_ENABLE, + "Włącz lub wyłącz powiadomienia OSD dla osiągnięć.") +MSG_HASH(MENU_ENUM_SUBLABEL_DRIVER_SETTINGS, + "Zmień sterowniki używane przez system.") +MSG_HASH(MENU_ENUM_SUBLABEL_RETRO_ACHIEVEMENTS_SETTINGS, + "Zmień ustawienia osiągnięć.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_SETTINGS, + "Zmień ustawienia rdzenia.") +MSG_HASH(MENU_ENUM_SUBLABEL_RECORDING_SETTINGS, + "Zmień ustawienia nagrywania.") +MSG_HASH(MENU_ENUM_SUBLABEL_ONSCREEN_DISPLAY_SETTINGS, + "Zmień nakładkę ekranu i nakładkę klawiatury oraz ustawienia powiadomień na ekranie.") +MSG_HASH(MENU_ENUM_SUBLABEL_FRAME_THROTTLE_SETTINGS, + "Zmień ustawienia przewijania, przewijania do przodu i spowolnienia.") +MSG_HASH(MENU_ENUM_SUBLABEL_SAVING_SETTINGS, + "Zmień ustawienia zapisu.") +MSG_HASH(MENU_ENUM_SUBLABEL_LOGGING_SETTINGS, + "Zmień ustawienia rejestrowania.") +MSG_HASH(MENU_ENUM_SUBLABEL_USER_INTERFACE_SETTINGS, + "Zmień ustawienia interfejsu użytkownika.") +MSG_HASH(MENU_ENUM_SUBLABEL_USER_SETTINGS, + "Zmień konto, nazwę użytkownika i ustawienia językowe.") +MSG_HASH(MENU_ENUM_SUBLABEL_PRIVACY_SETTINGS, + "Zmień ustawienia prywatności.") +MSG_HASH(MENU_ENUM_SUBLABEL_DIRECTORY_SETTINGS, + "Zmień domyślne katalogi, w których znajdują się pliki.") +MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_SETTINGS, + "Zmień ustawienia listy odtwarzania.") +MSG_HASH(MENU_ENUM_SUBLABEL_NETWORK_SETTINGS, + "Skonfiguruj ustawienia serwera i sieci.") +MSG_HASH(MENU_ENUM_SUBLABEL_ADD_CONTENT_LIST, + "Skanuj zawartość i dodaj do bazy danych.") +MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_SETTINGS, + "Zmień ustawienia wyjścia audio.") +MSG_HASH(MENU_ENUM_SUBLABEL_BLUETOOTH_ENABLE, + "Włącz lub wyłącz bluetooth.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONFIG_SAVE_ON_EXIT, + "Zapisuje zmiany w pliku konfiguracyjnym przy wyjściu.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONFIGURATION_SETTINGS, + "Zmień domyślne ustawienia plików konfiguracyjnych.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONFIGURATIONS_LIST, + "Zarządzaj i twórz pliki konfiguracyjne.") +MSG_HASH(MENU_ENUM_SUBLABEL_CPU_CORES, + "Ilość rdzeni procesora.") +MSG_HASH(MENU_ENUM_SUBLABEL_FPS_SHOW, + "Wyświetla bieżącą liczbę klatek na sekundę na ekranie.") +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_HOTKEY_BINDS, + "Skonfiguruj ustawienia skrótu.") +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO, + "Kombinacja przycisków gamepada do przełączania menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_SETTINGS, + "Zmień ustawienia joypada, klawiatury i myszy.") +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_USER_BINDS, + "Skonfiguruj elementy sterujące dla tego użytkownika.") +MSG_HASH(MENU_ENUM_SUBLABEL_LOG_VERBOSITY, + "Włącz lub wyłącz rejestrowanie w terminalu.") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY, + "Dołącz lub obsługuj sesję netplay.") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_LAN_SCAN_SETTINGS, + "Wyszukaj i połącz się z hostami netplay w sieci lokalnej.") +MSG_HASH(MENU_ENUM_SUBLABEL_INFORMATION_LIST_LIST, + "Wyświetl informacje o systemie.") +MSG_HASH(MENU_ENUM_SUBLABEL_ONLINE_UPDATER, + "Pobierz dodatki, komponenty i treści do RetroArch.") +MSG_HASH(MENU_ENUM_SUBLABEL_SAMBA_ENABLE, + "Włącz lub wyłącz udostępnianie sieciowe folderów.") +MSG_HASH(MENU_ENUM_SUBLABEL_SERVICES_SETTINGS, + "Zarządzaj usługami na poziomie systemu operacyjnego.") +MSG_HASH(MENU_ENUM_SUBLABEL_SHOW_HIDDEN_FILES, + "Pokaż ukryte pliki / katalogi w przeglądarce plików.") +MSG_HASH(MENU_ENUM_SUBLABEL_SSH_ENABLE, + "Włącz lub wyłącz zdalny dostęp do wiersza poleceń.") +MSG_HASH(MENU_ENUM_SUBLABEL_SUSPEND_SCREENSAVER_ENABLE, + "Zapobiega włączaniu wygaszacza ekranu systemu.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_WINDOW_SCALE, + "Ustawia rozmiar okna względem głównego rozmiaru wyświetlania. Alternatywnie możesz ustawić szerokość i wysokość okna poniżej dla ustalonego rozmiaru okna.") +MSG_HASH(MENU_ENUM_SUBLABEL_USER_LANGUAGE, + "Ustaw język interfejsu.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_BLACK_FRAME_INSERTION, + "Wstawia czarną klatke między klatkami. Przydatny dla użytkowników z ekranami 120Hz, którzy chcą odtwarzać zawartość 60 Hz, aby wyeliminować efekt duchów.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FRAME_DELAY, + "Zmniejsza opóźnienie kosztem większego ryzyka rwania wideo. Dodaje opóźnienie po V-Sync (w ms).") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_HARD_SYNC_FRAMES, + "Określa liczbę klatek, jaką procesor może uruchomić przed GPU, gdy używana jest 'Hard GPU Sync'.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, + "Informuje sterownik wideo, aby jawnie użył określonego trybu buforowania.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MONITOR_INDEX, + "Określa, który ekran wyświetlacza ma być używany.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE_AUTO, + "Dokładna szacowana częstotliwość odświeżania ekranu w Hz.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SETTINGS, + "Zmień ustawienia wyjścia wideo.") +MSG_HASH(MENU_ENUM_SUBLABEL_WIFI_SETTINGS, + "Skanuje sieci bezprzewodowe i nawiązuje połączenie.") +MSG_HASH(MENU_ENUM_SUBLABEL_HELP_LIST, + "Dowiedz się więcej o tym, jak działa program.") +MSG_HASH(MSG_ADDED_TO_FAVORITES, + "Dodano do ulubionych") +MSG_HASH(MSG_APPENDED_DISK, + "Dołączony dysk") +MSG_HASH(MSG_APPLICATION_DIR, + "Aplikacja Dir") +MSG_HASH(MSG_APPLYING_CHEAT, + "Stosowanie zmian w cheacie.") +MSG_HASH(MSG_APPLYING_SHADER, + "Zastosuj Shader") +MSG_HASH(MSG_AUDIO_MUTED, + "Wyciszenie Dźwięku.") +MSG_HASH(MSG_AUDIO_UNMUTED, + "Dźwięk nie jest wyciszony.") +MSG_HASH(MSG_AUTOCONFIG_FILE_ERROR_SAVING, + "Błąd podczas zapisywania pliku autoconf.") +MSG_HASH(MSG_AUTOCONFIG_FILE_SAVED_SUCCESSFULLY, + "Plik Autoconfig został pomyślnie zapisany.") +MSG_HASH(MSG_AUTOSAVE_FAILED, + "Nie można zainicjować autozapisu.") +MSG_HASH(MSG_AUTO_SAVE_STATE_TO, + "Automatycznie zapisz stan do") +MSG_HASH(MSG_BLOCKING_SRAM_OVERWRITE, + "Blokowanie nadpisywania SRAM") +MSG_HASH(MSG_BRINGING_UP_COMMAND_INTERFACE_ON_PORT, + "Wprowadzanie interfejsu poleceń na porcie") +MSG_HASH(MSG_BYTES, + "bajty") +MSG_HASH(MSG_CANNOT_INFER_NEW_CONFIG_PATH, + "Nie można określić nowej ścieżki konfiguracji. Użyj bieżącego czasu.") +MSG_HASH(MSG_CHEEVOS_HARDCORE_MODE_ENABLE, + "Tryb Hardcore włączony, savestate i rewind były wyłączone.") +MSG_HASH(MSG_COMPARING_WITH_KNOWN_MAGIC_NUMBERS, + "Porównując ze znanymi magicznymi liczbami...") +MSG_HASH(MSG_COMPILED_AGAINST_API, + "Skompilowany z API") +MSG_HASH(MSG_CONFIG_DIRECTORY_NOT_SET, + "Nie skonfigurowano katalogu konfiguracyjnego. Nie można zapisać nowej konfiguracji.") +MSG_HASH(MSG_CONNECTED_TO, + "Połączony z") +MSG_HASH(MSG_CONTENT_CRC32S_DIFFER, + "Zawartość CRC32 różni się. Nie można używać różnych gier.") +MSG_HASH(MSG_CONTENT_LOADING_SKIPPED_IMPLEMENTATION_WILL_DO_IT, + "Pominięto ładowanie treści. Implementacja załaduje ją samodzielnie.") +MSG_HASH(MSG_CORE_DOES_NOT_SUPPORT_SAVESTATES, + "Rdzeń nie obsługuje stanów zapisywania.") +MSG_HASH(MSG_CORE_OPTIONS_FILE_CREATED_SUCCESSFULLY, + "Plik opcji rdzenia został pomyślnie utworzony.") +MSG_HASH(MSG_COULD_NOT_FIND_ANY_NEXT_DRIVER, + "Nie można znaleźć następnego sterownika") +MSG_HASH(MSG_COULD_NOT_FIND_COMPATIBLE_SYSTEM, + "Nie można znaleźć zgodnego systemu.") +MSG_HASH(MSG_COULD_NOT_FIND_VALID_DATA_TRACK, + "Nie można znaleźć prawidłowej ścieżki danych") +MSG_HASH(MSG_COULD_NOT_OPEN_DATA_TRACK, + "Nie można otworzyć ścieżki danych") +MSG_HASH(MSG_COULD_NOT_READ_CONTENT_FILE, + "Nie można odczytać pliku zawartości") +MSG_HASH(MSG_COULD_NOT_READ_MOVIE_HEADER, + "Nie można odczytać nagłówka filmu.") +MSG_HASH(MSG_COULD_NOT_READ_STATE_FROM_MOVIE, + "Nie można odczytać stanu z filmu.") +MSG_HASH(MSG_CRC32_CHECKSUM_MISMATCH, + "Niezgodność sumy kontrolnej CRC32 między plikiem treści a zapisaną sumą kontrolną w nagłówku pliku odtwarzania. Powtórka najprawdopodobniej zsynchronizuje się podczas odtwarzania.") +MSG_HASH(MSG_CUSTOM_TIMING_GIVEN, + "Podano niestandardowy czas") +MSG_HASH(MSG_DECOMPRESSION_ALREADY_IN_PROGRESS, + "Dekompresja już trwa.") +MSG_HASH(MSG_DECOMPRESSION_FAILED, + "Dekompresja nie powiodła się.") +MSG_HASH(MSG_DETECTED_VIEWPORT_OF, + "Wykryty obszar widoku") +MSG_HASH(MSG_DID_NOT_FIND_A_VALID_CONTENT_PATCH, + "Nie znaleziono poprawki treści.") +MSG_HASH(MSG_DISCONNECT_DEVICE_FROM_A_VALID_PORT, + "Odłącz urządzenie od poprawnego portu.") +MSG_HASH(MSG_DISK_CLOSED, + "Zamknięte") +MSG_HASH(MSG_DISK_EJECTED, + "Wyrzucony") +MSG_HASH(MSG_DOWNLOADING, + "Ściąganie") +MSG_HASH(MSG_DOWNLOAD_FAILED, + "Pobieranie nie udane") +MSG_HASH(MSG_ERROR, + "Błąd") +MSG_HASH(MSG_ERROR_LIBRETRO_CORE_REQUIRES_CONTENT, + "Rdzeń Libretro wymaga treści, ale nic nie zostało dostarczone.") +MSG_HASH(MSG_ERROR_LIBRETRO_CORE_REQUIRES_SPECIAL_CONTENT, + "Rdzeń Libretro wymaga specjalnych treści, ale żadne nie zostały dostarczone.") +MSG_HASH(MSG_ERROR_PARSING_ARGUMENTS, + "Błąd podczas analizowania argumentów.") +MSG_HASH(MSG_ERROR_SAVING_CORE_OPTIONS_FILE, + "Błąd podczas zapisywania pliku opcji podstawowych.") +MSG_HASH(MSG_ERROR_SAVING_REMAP_FILE, + "Błąd podczas zapisywania pliku remap.") +MSG_HASH(MSG_ERROR_REMOVING_REMAP_FILE, + "Błąd podczas usuwania pliku remap.") +MSG_HASH(MSG_ERROR_SAVING_SHADER_PRESET, + "Błąd podczas zapisywania ustawienia modułu cieniującego.") +MSG_HASH(MSG_EXTERNAL_APPLICATION_DIR, + "Aplikacja zewnętrzna Dir") +MSG_HASH(MSG_EXTRACTING, + "Wyodrębnianie") +MSG_HASH(MSG_EXTRACTING_FILE, + "Wyodrębnianie pliku") +MSG_HASH(MSG_FAILED_SAVING_CONFIG_TO, + "Nie powiodło się zapisanie konfiguracji do") +MSG_HASH(MSG_FAILED_TO, + "Nie udało się") +MSG_HASH(MSG_FAILED_TO_ACCEPT_INCOMING_SPECTATOR, + "Nie udało się przyjąć przychodzącego widza.") +MSG_HASH(MSG_FAILED_TO_ALLOCATE_MEMORY_FOR_PATCHED_CONTENT, + "Nie można przydzielić pamięci na poprawioną zawartość...") +MSG_HASH(MSG_FAILED_TO_APPLY_SHADER, + "Nie można zastosować modułu cieniującego.") +MSG_HASH(MSG_FAILED_TO_BIND_SOCKET, + "Nie powiodło się wiązanie gniazda.") +MSG_HASH(MSG_FAILED_TO_CREATE_THE_DIRECTORY, + "Nie można utworzyć katalogu.") +MSG_HASH(MSG_FAILED_TO_EXTRACT_CONTENT_FROM_COMPRESSED_FILE, + "Nie można wyodrębnić treści ze skompresowanego pliku") +MSG_HASH(MSG_FAILED_TO_GET_NICKNAME_FROM_CLIENT, + "Nie udało się uzyskać pseudonimu od klienta.") +MSG_HASH(MSG_FAILED_TO_LOAD, + "Nie udało się załadować") +MSG_HASH(MSG_FAILED_TO_LOAD_CONTENT, + "Nie udało się wczytać treści") +MSG_HASH(MSG_FAILED_TO_LOAD_MOVIE_FILE, + "Nie udało się załadować pliku filmowego") +MSG_HASH(MSG_FAILED_TO_LOAD_OVERLAY, + "Nie udało się załadować nakładki.") +MSG_HASH(MSG_FAILED_TO_LOAD_STATE, + "Nie udało się załadować stanu z") +MSG_HASH(MSG_FAILED_TO_OPEN_LIBRETRO_CORE, + "Nie udało się otworzyć rdzenia libretro") +MSG_HASH(MSG_FAILED_TO_PATCH, + "Nie udało się załatać") +MSG_HASH(MSG_FAILED_TO_RECEIVE_HEADER_FROM_CLIENT, + "Nie można odebrać nagłówka od klienta.") +MSG_HASH(MSG_FAILED_TO_RECEIVE_NICKNAME, + "Nie udało się odebrać pseudonimu.") +MSG_HASH(MSG_FAILED_TO_RECEIVE_NICKNAME_FROM_HOST, + "Nie udało się odebrać pseudonimu z hosta.") +MSG_HASH(MSG_FAILED_TO_RECEIVE_NICKNAME_SIZE_FROM_HOST, + "Nie można odebrać rozmiaru pseudonimu z hosta.") +MSG_HASH(MSG_FAILED_TO_RECEIVE_SRAM_DATA_FROM_HOST, + "Nie można odebrać danych SRAM z hosta.") +MSG_HASH(MSG_FAILED_TO_REMOVE_DISK_FROM_TRAY, + "Nie udało się usunąć dysku z zasobnika.") +MSG_HASH(MSG_FAILED_TO_REMOVE_TEMPORARY_FILE, + "Nie udało się usunąć pliku tymczasowego") +MSG_HASH(MSG_FAILED_TO_SAVE_SRAM, + "Nie udało się zapisać SRAM") +MSG_HASH(MSG_FAILED_TO_SAVE_STATE_TO, + "Nie udało się zapisać stanu do") +MSG_HASH(MSG_FAILED_TO_SEND_NICKNAME, + "Nie udało się wysłać pseudonimu.") +MSG_HASH(MSG_FAILED_TO_SEND_NICKNAME_SIZE, + "Nie udało się wysłać rozmiaru pseudonimu.") +MSG_HASH(MSG_FAILED_TO_SEND_NICKNAME_TO_CLIENT, + "Nie udało się wysłać pseudonimu do klienta.") +MSG_HASH(MSG_FAILED_TO_SEND_NICKNAME_TO_HOST, + "Nie udało się wysłać pseudonimu do hosta.") +MSG_HASH(MSG_FAILED_TO_SEND_SRAM_DATA_TO_CLIENT, + "Nie udało się wysłać danych SRAM do klienta.") +MSG_HASH(MSG_FAILED_TO_START_AUDIO_DRIVER, + "Nie można uruchomić sterownika audio. Będzie kontynuowany bez dźwięku.") +MSG_HASH(MSG_FAILED_TO_START_MOVIE_RECORD, + "Nie można uruchomić nagrywania filmu.") +MSG_HASH(MSG_FAILED_TO_START_RECORDING, + "Nie można rozpocząć nagrywania.") +MSG_HASH(MSG_FAILED_TO_TAKE_SCREENSHOT, + "Nie udało się zrobić zrzutu ekranu.") +MSG_HASH(MSG_FAILED_TO_UNDO_LOAD_STATE, + "Nie udało się cofnąć stanu obciążenia.") +MSG_HASH(MSG_FAILED_TO_UNDO_SAVE_STATE, + "Nie udało się cofnąć stanu zapisania.") +MSG_HASH(MSG_FAILED_TO_UNMUTE_AUDIO, + "Nie udało się wyłączyć dźwięku.") +MSG_HASH(MSG_FATAL_ERROR_RECEIVED_IN, + "Błąd krytyczny odebrany w") +MSG_HASH(MSG_FILE_NOT_FOUND, + "Nie znaleziono pliku") +MSG_HASH(MSG_FOUND_AUTO_SAVESTATE_IN, + "Znajdź stan automatycznego zapisywania w") +MSG_HASH(MSG_FOUND_DISK_LABEL, + "Znaleziono etykietę dysku") +MSG_HASH(MSG_FOUND_FIRST_DATA_TRACK_ON_FILE, + "Znaleziono pierwszą ścieżkę danych w pliku") +MSG_HASH(MSG_FOUND_LAST_STATE_SLOT, + "Znaleziono ostatni stan automatu") +MSG_HASH(MSG_FOUND_SHADER, + "Znaleziony moduł cieniujący") +MSG_HASH(MSG_FRAMES, + "Klatki") +MSG_HASH(MSG_GAME_SPECIFIC_CORE_OPTIONS_FOUND_AT, + "Opcje gray: podstawowe opcje zależne od danej gry") +MSG_HASH(MSG_GOT_INVALID_DISK_INDEX, + "Otrzymałem nieprawidłowy indeks dysku.") +MSG_HASH(MSG_GRAB_MOUSE_STATE, + "Sprawdź stan myszy") +MSG_HASH(MSG_GAME_FOCUS_ON, + "Skup się na grze") +MSG_HASH(MSG_GAME_FOCUS_OFF, + "Nie skupiaj się na grze") +MSG_HASH(MSG_HW_RENDERED_MUST_USE_POSTSHADED_RECORDING, + "Rdzeń Libretro jest renderowany sprzętowo. Musi także korzystać z nagrywania po cieniowaniu.") +MSG_HASH(MSG_INFLATED_CHECKSUM_DID_NOT_MATCH_CRC32, + "Skomplikowana suma kontrolna nie pasuje do CRC32.") +MSG_HASH(MSG_INPUT_CHEAT, + "Wejdź w Cheat") +MSG_HASH(MSG_INPUT_CHEAT_FILENAME, + "Wprowadź nazwe Cheata") +MSG_HASH(MSG_INPUT_PRESET_FILENAME, + "Wprowadź wstępnie ustawioną nazwę pliku") +MSG_HASH(MSG_INPUT_RENAME_ENTRY, + "Zmień nazwę tytułu") +MSG_HASH(MSG_INTERFACE, + "Interfejs") +MSG_HASH(MSG_INTERNAL_STORAGE, + "Pamięć wewnętrzna") +MSG_HASH(MSG_REMOVABLE_STORAGE, + "Magazyn wymienny") +MSG_HASH(MSG_INVALID_NICKNAME_SIZE, + "Nieprawidłowy rozmiar pseudonimu.") +MSG_HASH(MSG_IN_BYTES, + "w bajtach") +MSG_HASH(MSG_IN_GIGABYTES, + "w gigabajtach") +MSG_HASH(MSG_IN_MEGABYTES, + "w megabajtach") +MSG_HASH(MSG_LIBRETRO_ABI_BREAK, + "jest skompilowany przeciwko innej wersji libretro niż ta implementacja libretro.") +MSG_HASH(MSG_LIBRETRO_FRONTEND, + "Frontend dla libretro") +MSG_HASH(MSG_LOADED_STATE_FROM_SLOT, + "Załadowany stan z gniazda #%d.") +MSG_HASH(MSG_LOADED_STATE_FROM_SLOT_AUTO, + "Załadowany stan z gniazda #-1 (automatyczny).") +MSG_HASH(MSG_LOADING, + "Ładuję") +MSG_HASH(MSG_FIRMWARE, + "Brak jednego lub więcej plików oprogramowania układowego") +MSG_HASH(MSG_LOADING_CONTENT_FILE, + "Ładowanie pliku zawartości") +MSG_HASH(MSG_LOADING_HISTORY_FILE, + "Ładowanie pliku historii") +MSG_HASH(MSG_LOADING_STATE, + "Ładowanie stanu") +MSG_HASH(MSG_MEMORY, + "Pamięć") +MSG_HASH(MSG_MOVIE_FILE_IS_NOT_A_VALID_BSV1_FILE, + "Plik filmu nie jest prawidłowym plikiem BSV1.") +MSG_HASH(MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION, + "Wygląda na to, że format filmu ma inną wersję serializera. Najprawdopodobniej zawiedzie.") +MSG_HASH(MSG_MOVIE_PLAYBACK_ENDED, + "Zakończono odtwarzanie filmu.") +MSG_HASH(MSG_MOVIE_RECORD_STOPPED, + "Zatrzymywanie nagrywania filmu.") +MSG_HASH(MSG_NETPLAY_FAILED, + "Nie udało się zainicjować gry sieciowej.") +MSG_HASH(MSG_NO_CONTENT_STARTING_DUMMY_CORE, + "Bez zawartości, zaczynając sztuczny rdzeń.") +MSG_HASH(MSG_NO_SAVE_STATE_HAS_BEEN_OVERWRITTEN_YET, + "Żaden stan zapisu nie został jeszcze nadpisany.") +MSG_HASH(MSG_NO_STATE_HAS_BEEN_LOADED_YET, + "Żaden stan nie został jeszcze załadowany.") +MSG_HASH(MSG_OVERRIDES_ERROR_SAVING, + "Błąd podczas zapisywania zastąpień.") +MSG_HASH(MSG_OVERRIDES_SAVED_SUCCESSFULLY, + "Przesłonięcia zostały pomyślnie zapisane.") +MSG_HASH(MSG_PAUSED, + "Wstrzymane.") +MSG_HASH(MSG_PROGRAM, + "RetroArch") +MSG_HASH(MSG_READING_FIRST_DATA_TRACK, + "Czytanie pierwszej ścieżki danych...") +MSG_HASH(MSG_RECEIVED, + "Odebrane") +MSG_HASH(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE, + "Nagrywanie zakończyło się z powodu zmiany rozmiaru.") +MSG_HASH(MSG_RECORDING_TO, + "Nagrywanie do") +MSG_HASH(MSG_REDIRECTING_CHEATFILE_TO, + "Przekierowuję plik oszustów do") +MSG_HASH(MSG_REDIRECTING_SAVEFILE_TO, + "Przekierowanie pliku zapisu do") +MSG_HASH(MSG_REDIRECTING_SAVESTATE_TO, + "Przekierowuję stan zapisywania do") +MSG_HASH(MSG_REMAP_FILE_SAVED_SUCCESSFULLY, + "Plik remap został pomyślnie zapisany.") +MSG_HASH(MSG_REMAP_FILE_REMOVED_SUCCESSFULLY, + "Plik remap został pomyślnie usunięty.") +MSG_HASH(MSG_REMOVED_DISK_FROM_TRAY, + "Usunięto dysk z zasobnika.") +MSG_HASH(MSG_REMOVING_TEMPORARY_CONTENT_FILE, + "Usuwanie tymczasowego pliku zawartości") +MSG_HASH(MSG_RESET, + "Reset") +MSG_HASH(MSG_RESTARTING_RECORDING_DUE_TO_DRIVER_REINIT, + "Ponowne uruchamianie nagrywania z powodu ponownego uruchomienia sterownika.") +MSG_HASH(MSG_RESTORED_OLD_SAVE_STATE, + "Przywrócono stary stan zapisywania.") +MSG_HASH(MSG_RESTORING_DEFAULT_SHADER_PRESET_TO, + "Shadery: przywracanie domyślnego ustawienia modułu cieniującego do") +MSG_HASH(MSG_REVERTING_SAVEFILE_DIRECTORY_TO, + "Przywracanie zapisywania katalogu plików do") +MSG_HASH(MSG_REVERTING_SAVESTATE_DIRECTORY_TO, + "Przywracanie katalogu stanu zapisu do") +MSG_HASH(MSG_REWINDING, + "Przewijanie.") +MSG_HASH(MSG_REWIND_INIT, + "Inicjowanie bufora przewijania z rozmiarem") +MSG_HASH(MSG_REWIND_INIT_FAILED, + "Nie można zainicjować buforu przewijania. Przewijanie zostanie wyłączone.") +MSG_HASH(MSG_REWIND_INIT_FAILED_THREADED_AUDIO, + "mplementacja wykorzystuje nagrany dźwięk. Nie można użyć do przewijania.") +MSG_HASH(MSG_REWIND_REACHED_END, + "Osiągnięty koniec bufora przewijania.") +MSG_HASH(MSG_SAVED_NEW_CONFIG_TO, + "Zapisano nową konfigurację do") +MSG_HASH(MSG_SAVED_STATE_TO_SLOT, + "Zapisany stan do gniazda #%d.") +MSG_HASH(MSG_SAVED_STATE_TO_SLOT_AUTO, + "Zapisany stan do gniazda #-1 (auto).") +MSG_HASH(MSG_SAVED_SUCCESSFULLY_TO, + "Zapisano pomyślnie do") +MSG_HASH(MSG_SAVING_RAM_TYPE, + "Zapisywanie typu pamięci RAM") +MSG_HASH(MSG_SAVING_STATE, + "Zapisywanie stanu") +MSG_HASH(MSG_SCANNING, + "Skanowwanie") +MSG_HASH(MSG_SCANNING_OF_DIRECTORY_FINISHED, + "Skanowanie katalogu zakończone") +MSG_HASH(MSG_SENDING_COMMAND, + "Wysyłam polecenie") +MSG_HASH(MSG_SEVERAL_PATCHES_ARE_EXPLICITLY_DEFINED, + "Kilka łatek jest jawnie zdefiniowanych, ignorując wszystko...") +MSG_HASH(MSG_SHADER, + "Shader") +MSG_HASH(MSG_SHADER_PRESET_SAVED_SUCCESSFULLY, + "Preset Shadera został pomyślnie zapisany.") +MSG_HASH(MSG_SKIPPING_SRAM_LOAD, + "Pomijanie obciążenia SRAM.") +MSG_HASH(MSG_SLOW_MOTION, + "Zwolnione tempo.") +MSG_HASH(MSG_FAST_FORWARD, + "Szybko do przodu.") +MSG_HASH(MSG_SLOW_MOTION_REWIND, + "Zwolnij w zwolnionym tempie.") +MSG_HASH(MSG_SRAM_WILL_NOT_BE_SAVED, + "SRAM nie zostanie zapisany.") +MSG_HASH(MSG_STARTING_MOVIE_PLAYBACK, + "Rozpoczynanie odtwarzania filmu.") +MSG_HASH(MSG_STARTING_MOVIE_RECORD_TO, + "Rozpoczęcie nagrywania filmu na") +MSG_HASH(MSG_STATE_SIZE, + "Wielkość państwa") +MSG_HASH(MSG_STATE_SLOT, + "Stan gniazda") +MSG_HASH(MSG_TAKING_SCREENSHOT, + "Zrzut ekranu.") +MSG_HASH(MSG_TO, + "do") +MSG_HASH(MSG_UNDID_LOAD_STATE, + "Anulować stan obciążenia.") +MSG_HASH(MSG_UNDOING_SAVE_STATE, + "Cofanie stanu zapisu") +MSG_HASH(MSG_UNKNOWN, + "Nieznany") +MSG_HASH(MSG_UNPAUSED, + "Anulowano.") +MSG_HASH(MSG_UNRECOGNIZED_COMMAND, + "Polecenie nierozpoznane") +MSG_HASH(MSG_USING_CORE_NAME_FOR_NEW_CONFIG, + "Używanie nazwy rdzenia dla nowej konfiguracji.") +MSG_HASH(MSG_USING_LIBRETRO_DUMMY_CORE_RECORDING_SKIPPED, + "Używanie rdzenia manekinowego libretro. Pomijanie nagrania.") +MSG_HASH(MSG_VALUE_CONNECT_DEVICE_FROM_A_VALID_PORT, + "Podłącz urządzenie z prawidłowego portu.") +MSG_HASH(MSG_VALUE_DISCONNECTING_DEVICE_FROM_PORT, + "Odłączanie urządzenia od portu") +MSG_HASH(MSG_VALUE_REBOOTING, + "Ponowne uruchamianie...") +MSG_HASH(MSG_VALUE_SHUTTING_DOWN, + "Wyłączanie...") +MSG_HASH(MSG_VERSION_OF_LIBRETRO_API, + "Wersja API libretro") +MSG_HASH(MSG_VIEWPORT_SIZE_CALCULATION_FAILED, + "Obliczenie wielkości wyświetlania nie powiodło się! Będzie nadal korzystać z nieprzetworzonych danych. Prawdopodobnie to nie zadziała ...") +MSG_HASH(MSG_VIRTUAL_DISK_TRAY, + "wirtualna taca dysku.") +MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_LATENCY, + "Pożądane opóźnienie dźwięku w milisekundach. Może nie być honorowane, jeśli sterownik audio nie może zapewnić określonego opóźnienia.") +MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_MUTE, + "Wycisz / włącz dźwięk.") +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_RATE_CONTROL_DELTA, + "Pomaga wygładzać niedoskonałości w synchronizacji czasu podczas synchronizowania dźwięku i obrazu. Pamiętaj, że jeśli jest wyłączona, właściwa synchronizacja jest prawie niemożliwa do uzyskania." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CAMERA_ALLOW, + "Zezwalaj lub nie zezwalaj na dostęp do kamery przez rdzenie." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_LOCATION_ALLOW, + "Zezwalaj lub nie zezwalaj na dostęp do usług lokalizacyjnych przez rdzenie." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_MAX_USERS, + "Maksymalna liczba użytkowników obsługiwanych przez RetroArch." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_POLL_TYPE_BEHAVIOR, + "Sprawdź, w jaki sposób odbywa się odpytywanie wejścia wewnątrz RetroArch. Ustawienie na 'Wcześnie' lub 'Późno' może spowodować mniejsze opóźnienie, w zależności od konfiguracji." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_ALL_USERS_CONTROL_MENU, + "Pozwala dowolnemu użytkownikowi kontrolować menu. Jeśli wyłączone, tylko użytkownik 1 może kontrolować menu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_VOLUME, + "Głośność dźwięku (w dB). 0 dB to normalna głośność i nie jest stosowane żadne wzmocnienie." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_WASAPI_EXCLUSIVE_MODE, + "Pozwól sterownikowi WASAPI na przejęcie wyłącznej kontroli nad urządzeniem audio. Jeśli jest wyłączona, zamiast tego użyje trybu wspólnego." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_WASAPI_FLOAT_FORMAT, + "Użyj formatu float dla sterownika WASAPI, jeśli jest on obsługiwany przez twoje urządzenie audio." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_WASAPI_SH_BUFFER_LENGTH, + "Pośrednia długość bufora (w klatkach), gdy używany jest sterownik WASAPI w trybie współdzielonym." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_SYNC, + "Synchronizuj dźwięk. Zalecana." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_AXIS_THRESHOLD, + "Jak daleko oś musi być przechylona, ​​aby spowodować naciśnięcie przycisku." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_BIND_TIMEOUT, + "Ilość sekund oczekiwania na przejście do następnej więzi." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_TURBO_PERIOD, + "Opisuje okres, w którym przełączane są przyciski z włączoną funkcją turbo. Liczby są opisane w klatkach." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_DUTY_CYCLE, + "Opisuje, jak długi powinien być okres przycisku z włączoną funkcją turbo. Liczby są opisane w klatkach." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_VSYNC, + "Synchronizuje wyjście wideo karty graficznej z częstotliwością odświeżania ekranu. Zalecana." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ALLOW_ROTATE, + "Pozwól rdzeniom ustawić rotację. Po wyłączeniu żądania obrotu są ignorowane. Przydatny w przypadku konfiguracji, w których ręcznie obraca się ekran." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_DUMMY_ON_CORE_SHUTDOWN, + "Niektóre rdzenie mogą mieć funkcję wyłączania. Jeśli jest włączona, uniemożliwi rdzeniu wyłączenie RetroArch. Zamiast tego ładuje fałszywy rdzeń." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CHECK_FOR_MISSING_FIRMWARE, + "Przed próbą załadowania zawartości sprawdź, czy wszystkie wymagane oprogramowanie układowe jest obecne." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_REFRESH_RATE, + "Pionowa częstotliwość odświeżania ekranu. Służy do obliczenia odpowiedniej wartości wejściowej audio. UWAGA: Zostanie to zignorowane, jeśli włączone jest 'Wideo wątkowe'." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_ENABLE, + "Włącz wyjście audio." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_MAX_TIMING_SKEW, + "Maksymalna zmiana częstotliwości wejściowej audio. Zwiększenie to umożliwia bardzo duże zmiany w taktowaniu kosztem niedokładnego nachylenia dźwięku (np. Uruchamianie rdzeni PAL na wyświetlaczach NTSC)." + ) +MSG_HASH( + MSG_FAILED, + "nie udało się" + ) +MSG_HASH( + MSG_SUCCEEDED, + "udało się" + ) +MSG_HASH( + MSG_DEVICE_NOT_CONFIGURED, + "nie skonfigurowane" + ) +MSG_HASH( + MSG_DEVICE_NOT_CONFIGURED_FALLBACK, + "nieskonfigurowane, korzystające z trybu awaryjnego" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST, + "Baza danych kursora" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_DEVELOPER, + "Baza danych - Filtr: Developer" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_PUBLISHER, + "Baza danych - Filtr: Wydawca" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_DISABLED, + "Wyłączony" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_ENABLED, + "Włączone" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CONTENT_HISTORY_PATH, + "Ścieżka historii treści" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_ORIGIN, + "Baza danych - Filtr: Pochodzenie") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_FRANCHISE, + "Baza danych - Filtr: Franczyza") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_ESRB_RATING, + "Baza danych - Filtr: Ocena ESRB") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_ELSPA_RATING, + "Baza danych - Filtr: Ocena ELSPA") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_PEGI_RATING, + "Baza danych - Filtr: Ocena PEGI") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_CERO_RATING, + "Baza danych - Filtr: Ocena CERO") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_BBFC_RATING, + "Baza danych - Filtr: Ocena BBFC") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_MAX_USERS, + "Baza danych - Filtr: Maks. Liczba użytkowników") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_RELEASEDATE_BY_MONTH, + "Baza danych - Filtr: Data wydania na miesiąc") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_RELEASEDATE_BY_YEAR, + "Baza danych - Filtr: Data wydania na rok") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_EDGE_MAGAZINE_ISSUE, + "Baza danych - Filter: Edge Magazine Issue") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_EDGE_MAGAZINE_RATING, + "Baza danych - Filtr: Ocena czasopisma Edge") +MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_DATABASE_INFO, + "Informacje o bazie danych") +MSG_HASH(MSG_WIFI_SCAN_COMPLETE, + "Skanowanie Wi-Fi zostało zakończone.") +MSG_HASH(MSG_SCANNING_WIRELESS_NETWORKS, + "Skanowanie sieci bezprzewodowych...") +MSG_HASH(MSG_NETPLAY_LAN_SCAN_COMPLETE, + "Zakończono skanowanie Netplay.") +MSG_HASH(MSG_NETPLAY_LAN_SCANNING, + "Skanowanie w poszukiwaniu hostów netplay...") +MSG_HASH(MENU_ENUM_SUBLABEL_PAUSE_NONACTIVE, + "Wstrzymaj grę, gdy RetroArch nie jest aktywnym oknem.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_DISABLE_COMPOSITION, + "Włącz lub wyłącz kompozycję (tylko system Windows).") +MSG_HASH(MENU_ENUM_SUBLABEL_HISTORY_LIST_ENABLE, + "Włącz lub wyłącz najnowszą listę odtwarzania gier, zdjęć, muzyki i filmów.") +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_HISTORY_SIZE, + "Ogranicz liczbę wpisów na liście odtwarzania w przypadku gier, zdjęć, muzyki i filmów.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_UNIFIED_MENU_CONTROLS, + "Zunifikowane sterowanie menu") +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_UNIFIED_MENU_CONTROLS, + "Użyj tych samych elementów sterujących zarówno do menu, jak i do gry. Dotyczy klawiatury.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FONT_ENABLE, + "Pokaż komunikaty na ekranie.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETWORK_USER_REMOTE_ENABLE, + "Użytkownik %d Zdalny Włącz") +MSG_HASH(MENU_ENUM_LABEL_VALUE_BATTERY_LEVEL_ENABLE, + "Pokaż poziom naładowania baterii") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SELECT_FILE, + "Wybierz plik") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SELECT_FROM_COLLECTION, + "Wybierz z kolekcji") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FILTER, + "Filtr") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SCALE, + "Skala") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_START_WHEN_LOADED, + "Netplay rozpocznie się po załadowaniu zawartości.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_LOAD_CONTENT_MANUALLY, + "Nie można znaleźć odpowiedniego pliku rdzenia lub treści, załaduj ręcznie.") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BROWSE_URL_LIST, + "Przeglądaj adres URL" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BROWSE_URL, + "Ścieżka adresu URL" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_BROWSE_START, + "Start" + ) +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_BOKEH, + "Bokeh") +MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_SNOWFLAKE, + "Snowflake") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_REFRESH_ROOMS, + "Odśwież listę pokoi") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ROOM_NICKNAME, + "Przezwisko: %s") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ROOM_NICKNAME_LAN, + "Przezwisko (lan): %s") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_COMPAT_CONTENT_FOUND, + "Znaleziono zgodną zawartość") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_CROP_OVERSCAN, + "Odcina kilka pikseli wokół krawędzi obrazu, zwykle pozostawionych pustych przez programistów, które czasami zawierają także piksele śmieci.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SMOOTH, + "Dodaje lekkie rozmycie obrazu, aby odciąć krawędzie twardych pikseli. Ta opcja ma bardzo mały wpływ na wydajność.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FILTER, + "Zastosuj filtr wideo zasilany przez procesor. UWAGA: Może przyjść na koszt wysokiej wydajności. Niektóre filtry wideo działają tylko w przypadku rdzeni, które używają kolorów 32-bitowych lub 16-bitowych.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_USERNAME, + "Wprowadź nazwę użytkownika swojego konta RetroAchievements.") +MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_PASSWORD, + "Wprowadź hasło do swojego konta RetroAchievements.") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_NICKNAME, + "Wprowadź tutaj swoją nazwę użytkownika. Będzie to wykorzystywane między innymi do sesji netplay.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_POST_FILTER_RECORD, + "Przechwyć obraz po zastosowaniu filtrów (ale nie shaderów). Twój film będzie wyglądał tak fantazyjnie jak to, co widzisz na ekranie.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_LIST, + "Wybierz, którego rdzenia użyć.") +MSG_HASH(MENU_ENUM_SUBLABEL_LOAD_CONTENT_LIST, + "Wybierz, które treści chcesz rozpocząć.") +MSG_HASH(MENU_ENUM_SUBLABEL_NETWORK_INFORMATION, + "Pokaż interfejsy sieciowe i powiązane adresy IP.") +MSG_HASH(MENU_ENUM_SUBLABEL_SYSTEM_INFORMATION, + "Pokaż informacje dotyczące konkretnego urządzenia.") +MSG_HASH(MENU_ENUM_SUBLABEL_QUIT_RETROARCH, + "Zamknij program.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_WINDOW_WIDTH, + "Ustaw niestandardowy rozmiar szerokości okna wyświetlacza. Pozostawienie go na 0 spowoduje przeskalowanie okna tak dużego, jak to możliwe.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_WINDOW_HEIGHT, + "Ustaw niestandardowy rozmiar wysokości okna wyświetlacza. Pozostawienie go na 0 spowoduje przeskalowanie okna tak dużego, jak to możliwe.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FULLSCREEN_X, + "Ustaw niestandardową szerokość w trybie pełnoekranowym bez okien. Pozostawienie go na 0 spowoduje użycie rozdzielczości pulpitu.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FULLSCREEN_Y, + "Ustaw niestandardowy rozmiar wysokości dla trybu pełnoekranowego bez okien. Pozostawienie go na 0 spowoduje użycie rozdzielczości pulpitu") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MESSAGE_POS_X, + "Określ niestandardową pozycję osi X dla tekstu na ekranie.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_MESSAGE_POS_Y, + "Określ niestandardową pozycję osi Y dla tekstu na ekranie.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FONT_SIZE, + "Określ rozmiar czcionki w punktach.") +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_OVERLAY_HIDE_IN_MENU, + "Ukryj nakładkę w menu i pokaż ją ponownie po wyjściu z menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS, + "Pokaż wejścia klawiatury / kontrolera na nakładce ekranowej.") +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS_PORT, + "Wybierz port dla nakładki, aby usłyszeć, czy opcja Pokaż nakładki na nakładkę jest włączona.") +MSG_HASH( + MENU_ENUM_SUBLABEL_CONTENT_COLLECTION_LIST, + "Tutaj pojawi się skanowana zawartość." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_SCALE_INTEGER, + "Skaluje wideo tylko w krokach całkowitych. Rozmiar bazy zależy od raportowanej przez system geometrii i współczynnika kształtu. Jeśli 'Force Aspect' nie jest ustawione, X / Y będzie liczbą całkowitą skalowaną niezależnie." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_GPU_SCREENSHOT, + "Zrzuty ekranu z zacienionych materiałów GPU, jeśli są dostępne." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ROTATION, + "Wymusza pewien obrót ekranu. Obrót jest dodawany do rotacji, które ustawia rdzeń." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_FORCE_SRGB_DISABLE, + "Przymusowe wyłączenie obsługi sRGB FBO. Niektóre sterowniki Intel OpenGL w systemie Windows mają problemy z wideo z obsługą sRGB FBO, jeśli jest włączona. Włączenie tego może obejść to." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_FULLSCREEN, + "Zacznij w trybie pełnoekranowym. Można zmienić w czasie wykonywania." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_WINDOWED_FULLSCREEN, + "Jeśli jest to tryb pełnoekranowy, korzystaj z trybu pełnoekranowego w oknie." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_GPU_RECORD, + "Rejestruje wyjście z zacienionego materiału GPU, jeśli jest dostępne." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_INDEX, + "WPodczas zapisywania stanu, wskaźnik stanu zapisu jest automatycznie zwiększany przed zapisaniem. Podczas ładowania zawartości indeks zostanie ustawiony na najwyższy istniejący indeks." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_BLOCK_SRAM_OVERWRITE, + "Blokuj Zapisz pamięć RAM przed nadpisaniem podczas ładowania stanów zapisu. Może potencjalnie prowadzić do zbugowanie gier." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_FASTFORWARD_RATIO, + "Maksymalna szybkość, z jaką zawartość będzie uruchamiana przy użyciu szybkiego przewijania do przodu (np. 5,0x przy zawartości 60 klatek na sekundę = 300 klatek na sekundę). Jeśli ustawione na 0.0x, współczynnik szybkiego przewijania jest nieograniczony (brak limitu FPS)." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_SLOWMOTION_RATIO, + "W zwolnionym tempie zawartość spowalnia o określony / ustawiony współczynnik." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_REWIND_ENABLE, + "Włącz przewijanie. To zajmie wydajność podczas gry." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_REWIND_GRANULARITY, + "Podczas przewijania określonej liczby klatek można przewijać kilka klatek na raz, zwiększając prędkość przewijania do tyłu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_LIBRETRO_LOG_LEVEL, + "Ustawia poziom logu dla rdzeni. Jeśli poziom dziennika wydany przez rdzeń jest poniżej tej wartości, jest on ignorowany." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_PERFCNT_ENABLE, + "Włącz liczniki wydajności dla RetroArch (i rdzeni)." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_SAVE, + "Automatycznie tworzy stan zapisywania na końcu środowiska wykonawczego RetroArch. RetroArch automatycznie załaduje ten stan zapisu Auto Load State jest włączony." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_LOAD, + "Automatycznie ładuj stan automatycznego zapisywania podczas uruchamiania." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_SAVESTATE_THUMBNAIL_ENABLE, + "Pokaż miniatury stanów zapisu w menu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUTOSAVE_INTERVAL, + "Automatyczne zapisywanie nieulotnej pamięci RAM w regularnych odstępach czasu. Jest to domyślnie wyłączone, chyba że ustawiono inaczej. Odstęp mierzony jest w sekundach. Wartość 0 wyłącza automatyczne zapisywanie." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_REMAP_BINDS_ENABLE, + "Jeśli włączone, przesłania powiązania wejściowe z remapped reminds zestaw dla bieżącego rdzenia." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_AUTODETECT_ENABLE, + "Włącz automatyczne wykrywanie wejścia. Spróbuje skonfigurować joypad, styl Plug-and-Play." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_INPUT_SWAP_OK_CANCEL, + "Zamień przyciski na OK / Cancel. Wyłączone to orientacja japońskiego przycisku, włączona jest orientacja zachodnia." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_PAUSE_LIBRETRO, + "Jeśli wyłączone, zawartość będzie nadal działać w tle, gdy menu RetroArch jest przełączane." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_DRIVER, + "Sterownik wideo do użycia." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_DRIVER, + "Sterownik audio do nase." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_DRIVER, + "Wprowadź sterownik, którego chcesz użyć. W zależności od sterownika wideo może wymusić inny sterownik wejściowy." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_JOYPAD_DRIVER, + "Sterownik joypad do użycia." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_DRIVER, + "Sterownik reemplera audio do użycia." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CAMERA_DRIVER, + "Sterownik kamery do użycia." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_LOCATION_DRIVER, + "Sterownik lokalizacji do użycia." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_DRIVER, + "Sterownik menu do użycia." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_RECORD_DRIVER, + "Zapisz sterownik, którego chcesz użyć." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_WIFI_DRIVER, + "Sterownik WiFi do użycia." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE, + "Filtruj pliki wyświetlane w przeglądarce plików według obsługiwanych rozszerzeń." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_WALLPAPER, + "Wybierz zdjęcie, aby ustawić jako tapetę menu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_DYNAMIC_WALLPAPER, + "Dynamicznie ładuj nową tapetę w zależności od kontekstu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_DEVICE, + "Zastąp domyślne urządzenie audio używane przez sterownik audio. To zależy od kierowcy." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_DSP_PLUGIN, + "Wtyczka audio DSP przetwarzająca dźwięk przed wysłaniem go do sterownika." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_OUTPUT_RATE, + "Prędkość próbkowania wyjścia audio." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_OVERLAY_OPACITY, + "Krycie wszystkich elementów interfejsu użytkownika nakładki." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_OVERLAY_SCALE, + "Skala wszystkich elementów interfejsu nakładki." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_OVERLAY_ENABLE, + "Włącz nakładkę." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_OVERLAY_PRESET, + "Wybierz nakładkę z przeglądarki plików." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_IP_ADDRESS, + "Adres hosta, z którym chcesz się połączyć." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_TCP_UDP_PORT, + "Port adresu IP hosta. Może to być port TCP lub UDP." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_PASSWORD, + "Hasło do połączenia z hostem netplay. Używane tylko w trybie hosta." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_PUBLIC_ANNOUNCE, + "Czy publicznie ogłaszać gry internetowe. W przypadku braku ustawienia klienci muszą ręcznie łączyć się, zamiast korzystać z publicznego lobby." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_SPECTATE_PASSWORD, + "Hasło do połączenia z hostem netplay z tylko uprawnieniami obserwatora. Używane tylko w trybie hosta." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_START_AS_SPECTATOR, + "Czy rozpocząć netplay w trybie obserwatora." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_ALLOW_SLAVES, + "Określa, czy zezwalać na połączenia w trybie slave. Klienty w trybie slave wymagają bardzo małej mocy obliczeniowej po każdej ze stron, ale znacznie ucierpią z powodu opóźnień sieci." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_REQUIRE_SLAVES, + "Określa, czy nie zezwalać na połączenia nie w trybie slave. Niezalecane, z wyjątkiem bardzo szybkich sieci z bardzo słabymi maszynami." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_STATELESS_MODE, + "Czy uruchomić netplay w trybie niewymagającym stanów zapisu. Jeśli jest ustawiona na wartość true, wymagana jest bardzo szybka sieć, ale nie jest wykonywane przewijanie, więc nie będzie jittera." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_CHECK_FRAMES, + "Częstotliwość w klatkach, w których netplay będzie weryfikować, czy host i klient są zsynchronizowane." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_NAT_TRAVERSAL, + "Podczas hostowania, próbuj słuchać połączeń z publicznego Internetu, używając UPnP lub podobnych technologii, aby uciec z sieci LAN." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_STDIN_CMD_ENABLE, + "Włącz interfejs poleceń Stdin." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MOUSE_ENABLE, + "Włącz kontrolki myszy w menu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_POINTER_ENABLE, + "Włącz sterowanie dotykowe w menu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_THUMBNAILS, + "Typ wyświetlanej miniatury." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_TIMEDATE_ENABLE, + "Pokazuje aktualną datę i / lub czas w menu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_BATTERY_LEVEL_ENABLE, + "Pokazuje aktualny poziom naładowania baterii w menu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NAVIGATION_WRAPAROUND, + "Oblewanie do początku i / lub końca, jeśli granica listy jest osiągnięta poziomo lub pionowo." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_NETPLAY_ENABLE_HOST, + "Włącza funkcję netplay w trybie hosta (serwer)." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_ENABLE_CLIENT, + "Włącza grę sieciową w trybie klienta.") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_DISCONNECT, + "Odłącz aktywne połączenie Netplay.") +MSG_HASH(MENU_ENUM_SUBLABEL_SCAN_DIRECTORY, + "Skanuje katalog w poszukiwaniu kompatybilnych plików i dodaje je do kolekcji.") +MSG_HASH(MENU_ENUM_SUBLABEL_SCAN_FILE, + "Skanuje zgodny plik i dodaje go do kolekcji.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SWAP_INTERVAL, + "Używa niestandardowego interwału wymiany dla Vsync. Ustaw, aby efektywnie zmniejszyć o połowę częstotliwość odświeżania monitora." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE, + "Sortuj pliki zapisu w folderach nazwanych po używanym rdzeniu." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE, + "Sortuj stany zachowywania w folderach nazwanych po używanym rdzeniu." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT, + "When being client over netplay, use keybinds for Player 1.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL, + "Adres URL do głównego katalogu Updater na kompilatorze Libretro.") +MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL, + "Adres URL do katalogu aktualizującego zasoby na kompilatorze Libretro.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_AUTO_EXTRACT_ARCHIVE, + "Po pobraniu automatycznie wyodrębnia pliki zawarte w pobranych archiwach." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_REFRESH_ROOMS, + "Zeskanuj nowe pokoje.") +MSG_HASH(MENU_ENUM_SUBLABEL_DELETE_ENTRY, + "Usuń ten wpis z kolekcji.") +MSG_HASH(MENU_ENUM_SUBLABEL_INFORMATION, + "Zobacz więcej informacji o zawartości.") +MSG_HASH(MENU_ENUM_SUBLABEL_ADD_TO_FAVORITES, + "Dodaj wpis do ulubionych.") +MSG_HASH(MENU_ENUM_SUBLABEL_ADD_TO_FAVORITES_PLAYLIST, + "Dodaj wpis do ulubionych.") +MSG_HASH(MENU_ENUM_SUBLABEL_RUN, + "Uruchom zawartość.") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_FILE_BROWSER_SETTINGS, + "Dostosowuje ustawienia przeglądarki plików.") +MSG_HASH( + MENU_ENUM_SUBLABEL_AUTO_REMAPS_ENABLE, + "Domyślnie włącz niestandardowe elementy sterujące podczas uruchamiania." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUTO_OVERRIDES_ENABLE, + "Domyślnie włącz niestandardową konfigurację podczas uruchamiania." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_GAME_SPECIFIC_OPTIONS, + "Domyślnie włącz spersonalizowane opcje rdzenia podczas uruchamiania.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_ENABLE, + "Wyświetla bieżącą nazwę rdzenia w menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_DATABASE_MANAGER, + "Zobacz bazy danych.") +MSG_HASH(MENU_ENUM_SUBLABEL_CURSOR_MANAGER, + "Wyświetl poprzednie wyszukiwania.") +MSG_HASH(MENU_ENUM_SUBLABEL_TAKE_SCREENSHOT, + "Przechwytuje obraz ekranu.") +MSG_HASH( + MENU_ENUM_SUBLABEL_CLOSE_CONTENT, + "Zamyka aktualną zawartość. Wszelkie niezapisane zmiany mogą zostać utracone." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_LOAD_STATE, + "Załaduj zapisany stan z aktualnie wybranego gniazda.") +MSG_HASH(MENU_ENUM_SUBLABEL_SAVE_STATE, + "Zapisz stan w aktualnie wybranym gnieździe.") +MSG_HASH(MENU_ENUM_SUBLABEL_RESUME, + "Wznów aktualnie uruchomioną zawartość i opuść Szybkie menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_RESUME_CONTENT, + "Wznów aktualnie uruchomioną zawartość i opuść Szybkie men.") +MSG_HASH(MENU_ENUM_SUBLABEL_STATE_SLOT, + "Zmienia aktualnie wybrany przedział stanu.") +MSG_HASH(MENU_ENUM_SUBLABEL_UNDO_LOAD_STATE, + "Jeśli stan został załadowany, zawartość wróci do stanu sprzed załadowania.") +MSG_HASH(MENU_ENUM_SUBLABEL_UNDO_SAVE_STATE, + "Jeśli stan został nadpisany, zostanie przywrócony do poprzedniego stanu zapisu.") +MSG_HASH( + MENU_ENUM_SUBLABEL_ACCOUNTS_RETRO_ACHIEVEMENTS, + "Usługa RetroAchievements. Aby uzyskać więcej informacji, odwiedź http://retroachievements.org" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_ACCOUNTS_LIST, + "Menedżerowie aktualnie skonfigurowali konta." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_META_REWIND, + "Zarządza ustawieniami przewijania.") +MSG_HASH(MENU_ENUM_SUBLABEL_RESTART_CONTENT, + "Ponownie uruchamia zawartość od początku.") +MSG_HASH(MENU_ENUM_SUBLABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CORE, + "Zapisuje plik konfiguracji zastąpienia, który będzie obowiązywał dla wszystkich treści załadowanych tym rdzeniem. Ma pierwszeństwo przed główną konfiguracją.") +MSG_HASH(MENU_ENUM_SUBLABEL_SAVE_CURRENT_CONFIG_OVERRIDE_GAME, + "Zapisuje plik konfiguracji zastąpienia, który będzie dotyczył tylko bieżącej treści. Ma pierwszeństwo przed główną konfiguracją.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_CHEAT_OPTIONS, + "Skonfiguruj kody oszustw.") +MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_OPTIONS, + "Skonfiguruj shadery, aby wizualnie powiększyć obraz.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_INPUT_REMAPPING_OPTIONS, + "Zmień ustawienia dla aktualnie wyświetlanej treści.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_OPTIONS, + "Zmień opcje aktualnie wyświetlanej treści.") +MSG_HASH(MENU_ENUM_SUBLABEL_SHOW_ADVANCED_SETTINGS, + "Pokaż zaawansowane ustawienia dla zaawansowanych użytkowników (domyślnie ukryty).") +MSG_HASH(MENU_ENUM_SUBLABEL_THREADED_DATA_RUNLOOP_ENABLE, + "Wykonuj zadania w oddzielnym wątku.") +MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_ENTRY_REMOVE, + "Pozwól użytkownikowi usuwać wpisy ze zbiorów.") +MSG_HASH(MENU_ENUM_SUBLABEL_SYSTEM_DIRECTORY, + "Ustawia katalog systemowy. Rdzenie mogą wysyłać zapytania do tego katalogu, aby załadować BIOS, konfiguracje specyficzne dla systemu itp.") +MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_BROWSER_DIRECTORY, + "Ustawia katalog startowy dla przeglądarki plików.") +MSG_HASH( + MENU_ENUM_SUBLABEL_CONTENT_DIR, + "Zwykle ustawiane przez programistów, którzy pakują aplikacje libretro / RetroArch, aby wskazywały na zasoby." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_DYNAMIC_WALLPAPERS_DIRECTORY, + "Katalog do przechowywania tapet dynamicznie ładowanych przez menu w zależności od kontekstu.") +MSG_HASH(MENU_ENUM_SUBLABEL_THUMBNAILS_DIRECTORY, + "Dodatkowe miniaturki (boxarty / miscale itp.) Są tutaj przechowywane." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_CONFIG_DIRECTORY, + "Ustawia katalog początkowy dla przeglądarki konfiguracji menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_INPUT_LATENCY_FRAMES_MIN, + "Liczba klatek opóźnienia wejściowego dla netplay do wykorzystania do ukrycia opóźnień sieci. Zmniejsza drgania i sprawia, że ​​gra jest mniej intensywna, kosztem zauważalnego opóźnienia wejścia.") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_INPUT_LATENCY_FRAMES_RANGE, + "Zakres klatek opóźnień wejściowych, które można wykorzystać do ukrycia opóźnień sieci. Zmniejsza fluktuacje i sprawia, że ​​netplay jest mniej obciążający procesor, kosztem nieprzewidywalnego opóźnienia wejściowego.") +MSG_HASH(MENU_ENUM_SUBLABEL_DISK_CYCLE_TRAY_STATUS, + "Cykluj bieżący dysk. Jeśli dysk zostanie włożony, wyskoczy. Jeśli dysk nie został włożony, zostanie włożony. ") +MSG_HASH(MENU_ENUM_SUBLABEL_DISK_INDEX, + "Zmień indeks dysku.") +MSG_HASH(MENU_ENUM_SUBLABEL_DISK_OPTIONS, + "Zarządzanie obrazem dysku.") +MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, + "Wybierz obraz dysku, który chcesz wstawić.") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, + "Upewnia się, że liczba klatek na sekundę jest ograniczona w menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, + "Wybierz inny motyw dla ikony. Zmiany zaczną obowiązywać po ponownym uruchomieniu programu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, + "Włącz cienie dla wszystkich ikon. Będzie to miało niewielki wpływ na wydajność.") +MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_COLOR_THEME, + "Wybierz inny motyw gradientu tła.") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_WALLPAPER_OPACITY, + "Zmodyfikuj krycie tapety w tle.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_MENU_COLOR_THEME, + "Wybierz inny motyw gradientu tła.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_RIBBON_ENABLE, + "Wybierz animowany efekt tła. Może być intensywnie wykorzystujący GPU w zależności od efektu. Jeśli wydajność jest niezadowalająca, wyłącz to lub powróć do prostszego efektu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_FONT, + "Wybierz inną główną czcionkę, która ma być używana w menu.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHOW_FAVORITES, + "Pokaż zakładkę Ulubione w menu głównym.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHOW_IMAGES, + "Pokaż kartę Obrazu w menu głównym.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHOW_MUSIC, + "Pokaż zakładkę Muzyka w menu głównym.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHOW_VIDEO, + "Pokaż kartę Video w menu głównym.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHOW_NETPLAY, + "Pokaż zakładkę Netplay w menu głównym.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHOW_SETTINGS, + "Pokaż kartę Ustawień w menu głównym.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHOW_HISTORY, + "Pokaż kartę ostatnich historii w menu głównym.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHOW_ADD, + "Pokaż kartę treści importu w menu głównym.") +MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, + "Pokaż ekran startowy w menu. Po pierwszym uruchomieniu program jest automatycznie ustawiany na false.") +MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, + "Zmodyfikuj krycie grafiki nagłówka.") +MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_FOOTER_OPACITY, + "Zmodyfikuj krycie grafiki stopki.") +MSG_HASH(MENU_ENUM_SUBLABEL_DPI_OVERRIDE_ENABLE, + "Menu zazwyczaj dynamicznie się skaluje. Jeśli chcesz zamiast tego ustawić określony rozmiar skalowania, włącz to.") +MSG_HASH(MENU_ENUM_SUBLABEL_DPI_OVERRIDE_VALUE, + "Ustaw tutaj niestandardowy rozmiar skalowania. UWAGA: Musisz włączyć 'DPI Override', aby ten rozmiar skali zaczął obowiązywać.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_ASSETS_DIRECTORY, + "Zapisz wszystkie pobrane pliki w tym katalogu.") +MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_REMAPPING_DIRECTORY, + "Zapisz wszystkie zmienione kontrolki do tego katalogu.") +MSG_HASH(MENU_ENUM_SUBLABEL_LIBRETRO_DIR_PATH, + "Katalog, w którym program szuka treści / rdzeni.") +MSG_HASH(MENU_ENUM_SUBLABEL_LIBRETRO_INFO_PATH, + "Pliki informacji o aplikacji / rdzeniu są tutaj przechowywane.") +MSG_HASH(MENU_ENUM_SUBLABEL_JOYPAD_AUTOCONFIG_DIR, + "Jeśli joypad jest podłączony, to joypad zostanie automatycznie skonfigurowany, jeśli plik konfiguracyjny odpowiadający mu jest obecny w tym katalogu.") +MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_DIRECTORY, + "Zapisz wszystkie kolekcje w tym katalogu.") +MSG_HASH( + MENU_ENUM_SUBLABEL_CACHE_DIRECTORY, + "Jeśli ustawione na katalog, zawartość, która jest czasowo wyodrębniana (np. Z archiwów), zostanie wyodrębniona do tego katalogu." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_CURSOR_DIRECTORY, + "Zapisane zapytania są przechowywane w tym katalogu.") +MSG_HASH( + MENU_ENUM_SUBLABEL_CONTENT_DATABASE_DIRECTORY, + "Bazy danych są przechowywane w tym katalogu." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_ASSETS_DIRECTORY, + "Ta lokalizacja jest domyślnie sprawdzana, gdy interfejsy menu próbują znaleźć ładowalne zasoby itp." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_SAVEFILE_DIRECTORY, + "Zapisz wszystkie pliki zapisu w tym katalogu. Jeśli nie jest ustawione, spróbuje zapisać w katalogu roboczym pliku zawartości.") +MSG_HASH(MENU_ENUM_SUBLABEL_SAVESTATE_DIRECTORY, + "Zapisz wszystkie stany zachowania w tym katalogu. Jeśli nie jest ustawione, spróbuje zapisać w katalogu roboczym plików zawartości.") +MSG_HASH(MENU_ENUM_SUBLABEL_SCREENSHOT_DIRECTORY, + "Katalog do zrzutu zrzutów ekranu do.") +MSG_HASH(MENU_ENUM_SUBLABEL_OVERLAY_DIRECTORY, + "Definiuje katalog, w którym nakładki są przechowywane dla łatwego dostępu.") +MSG_HASH( + MENU_ENUM_SUBLABEL_CHEAT_DATABASE_PATH, + "Pliki do pobrania są tutaj przechowywane." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_FILTER_DIR, + "Katalog, w którym przechowywane są pliki filtrów DSP audio." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_FILTER_DIR, + "Katalog, w którym przechowywane są pliki filtrów wideo oparte na procesorze." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_DIR, + "Definiuje katalog, w którym pliki shaderów wideo oparte na GPU są przechowywane dla łatwego dostępu.") +MSG_HASH(MENU_ENUM_SUBLABEL_RECORDING_OUTPUT_DIRECTORY, + "Nagrania zostaną zrzucone do tego katalogu.") +MSG_HASH(MENU_ENUM_SUBLABEL_RECORDING_CONFIG_DIRECTORY, + "Tutaj będą przechowywane konfiguracje nagrywania.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FONT_PATH, + "Wybierz inną czcionkę dla powiadomień na ekranie.") +MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_APPLY_CHANGES, + "Zmiany w konfiguracji modułu cieniującego zostaną natychmiast zastosowane. Użyj tej opcji, jeśli zmienisz liczbę przejść dla modułów cieniujących, filtrowanie, skalę FBO itp.") +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_SHADER_NUM_PASSES, + "Zwiększ lub zmniejsz ilość przejść potoku cieniującego. Możesz powiązać osobny moduł cieniujący z każdym przebiegiem potoku i skonfigurować jego skalę i filtrowanie." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET, + "Załaduj preset modułu cieniującego. Rurociąg cieniowany zostanie automatycznie skonfigurowany.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_AS, + "Zapisz bieżące ustawienia modułu cieniującego jako nowe ustawienie domyślne modułu cieniującego.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_CORE, + "Zapisz bieżące ustawienia modułu cieniującego jako ustawienia domyślne dla tej aplikacji / rdzenia.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_GAME, + "Zapisz bieżące ustawienia modułu cieniującego jako ustawienia domyślne dla zawartości.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PARAMETERS, + "Modyfikuje bezpośrednio bieżący moduł cieniujący. Zmiany nie zostaną zapisane w ustawionym pliku.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_PARAMETERS, + "Modyfikuje sam domyślne ustawienie modułu cieniującego w menu.") +MSG_HASH( + MENU_ENUM_SUBLABEL_CHEAT_NUM_PASSES, + "Zwiększ lub zmniejsz ilość cheatów." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_APPLY_CHANGES, + "Zmiany Cheat odniosą skutek natychmiast.") +MSG_HASH( + MENU_ENUM_SUBLABEL_CHEAT_FILE_LOAD, + "Załaduj plik oszukiwać." + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CHEAT_FILE_SAVE_AS, + "Zapisz bieżące kody jako plik składowania." + ) +MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SETTINGS, + "Szybki dostęp do wszystkich istotnych ustawień w grze.") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_INFORMATION, + "Wyświetl informacje dotyczące aplikacji / rdzenia.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_ASPECT_RATIO, + "Wartość zmiennoprzecinkowa dla współczynnika proporcji wideo (szerokość / wysokość), jeśli współczynnik proporcji jest ustawiony na 'Config'.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_HEIGHT, + "Niestandardowa wysokość rzutni, która jest używana, jeśli współczynnik proporcji jest ustawiony na 'Niestandardowy'.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_WIDTH, + "Niestandardowa szerokość rzutni, która jest używana, jeśli współczynnik proporcji jest ustawiony na 'Niestandardowy'.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_X, + "Niestandardowe przesunięcie wyświetlania używane do definiowania położenia osi X w rzutni. Są one ignorowane, jeśli włączona jest opcja 'Integer Scale'. Zostanie wtedy automatycznie wyśrodkowany.") +MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_Y, + "Niestandardowe przesunięcie wyświetlania używane do definiowania położenia osi Y w rzutni. Są one ignorowane, jeśli włączona jest opcja 'Integer Scale'. Zostanie wtedy automatycznie wyśrodkowany.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_USE_MITM_SERVER, + "Użyj serwera przekazywania") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_USE_MITM_SERVER, + "Przekaż połączenia sieciowe przez serwer pośredniczący. Przydatne, jeśli host znajduje się za zaporą lub ma problemy z NAT / UPnP.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER, + "Dodaj do mikser") +MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_COLLECTION, + "Dodaj do mikser") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FILTER_BY_CURRENT_CORE, + "Filtruj według bieżącego rdzenia") +MSG_HASH( + MSG_AUDIO_MIXER_VOLUME, + "Globalna objętość miksera audio" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_AUDIO_MIXER_VOLUME, + "Globalna objętość miksera audio (w dB). 0 dB to normalna głośność i nie jest stosowane żadne wzmocnienie." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_VOLUME, + "Poziom głośności miksera audio (dB)" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_MUTE, + "Mikser dźwięku Wycisz" + ) +MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_MIXER_MUTE, + "Wycisz / włącz dźwięk miksera.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_ONLINE_UPDATER, + "Pokaż Online Updater") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_ONLINE_UPDATER, + "Pokaż / ukryj opcję 'Online Update'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_VIEWS_SETTINGS, + "Widok") +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_VIEWS_SETTINGS, + "Pokaż lub ukryj elementy na ekranie menu." + ) +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_CORE_UPDATER, + "Pokaż program Updater rdzenia") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_CORE_UPDATER, + "Pokaż / ukryj możliwość aktualizacji rdzeni (i podstawowych plików informacyjnych).") +MSG_HASH(MSG_PREPARING_FOR_CONTENT_SCAN, + "Przygotowanie do skanowania zawartości...") +MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_DELETE, + "Usuń rdzeń") +MSG_HASH(MENU_ENUM_SUBLABEL_CORE_DELETE, + "Usuń ten rdzeń z dysku.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FRAMEBUFFER_OPACITY, + "Framebuffer Opacity") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_FRAMEBUFFER_OPACITY, + "Zmodyfikuj krycie bufora klatki.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES, + "Ulubione") +MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_FAVORITES, + "Treści, które dodałeś do \"Ulubionych\" pojawią się tutaj.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_MUSIC, + "Muzyka") +MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_MUSIC, + "Tutaj pojawi się muzyka, która została wcześniej odtworzona.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_IMAGES, + "Obraz") +MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_IMAGES, + "Tutaj pojawią się obrazy, które wcześniej były oglądane.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_VIDEO, + "Wideo") +MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_VIDEO, + "Tutaj będą wyświetlane filmy, które zostały wcześniej odtworzone.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_ICONS_ENABLE, + "Ikony menu") +MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_ICONS_ENABLE, + "Włącz / wyłącz ikony menu pokazane po lewej stronie wpisów menu.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MAIN_MENU_ENABLE_SETTINGS, + "Włącz kartę Ustawienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_SHOW_SETTINGS_PASSWORD, + "Ustaw hasło dla włączania karty Ustawienia") +MSG_HASH(MSG_INPUT_ENABLE_SETTINGS_PASSWORD, + "Wprowadź hasło") +MSG_HASH(MSG_INPUT_ENABLE_SETTINGS_PASSWORD_OK, + "Hasło poprawne.") +MSG_HASH(MSG_INPUT_ENABLE_SETTINGS_PASSWORD_NOK, + "Hasło niepoprawne.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_MAIN_MENU_ENABLE_SETTINGS, + "Włącza kartę Ustawienia. Wymagane jest ponowne uruchomienie karty.") +MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHOW_SETTINGS_PASSWORD, + "Podanie hasła podczas ukrywania karty ustawień pozwala później przywrócić ją z menu, przechodząc do karty Menu główne, wybierając opcję Włącz kartę Ustawienia i wprowadzając hasło.") +MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_ENTRY_RENAME, + "Zezwalaj użytkownikowi na zmianę nazw wpisów w kolekcjach.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_ENTRY_RENAME, + "Zezwalaj na zmianę nazw wpisów") +MSG_HASH(MENU_ENUM_SUBLABEL_RENAME_ENTRY, + "Zmień nazwę tytułu.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_RENAME_ENTRY, + "Przemianować") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CORE, + "Pokaż ładowanie rdzenia") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CORE, + "Pokaż / ukryj opcję 'Załaduj rdzeń'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CONTENT, + "Pokaż ładunek zawartości") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CONTENT, + "Pokaż / ukryj opcję \"Wczytaj zawartość\".") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_INFORMATION, + "Pokaż informacje") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_INFORMATION, + "Show/hide the 'Information' option.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_CONFIGURATIONS, + "Pokaż konfiguracje") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_CONFIGURATIONS, + "Pokaż / ukryj opcję 'Konfiguracje'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_HELP, + "Pokaż pomoc") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_HELP, + "Pokaż / ukryj opcję \"Pomoc\".") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_QUIT_RETROARCH, + "Pokaż Zamknij RetroArch") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_QUIT_RETROARCH, + "Pokaż / ukryj opcję 'Zamknij RetroArch'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_REBOOT, + "Pokaż restart") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_REBOOT, + "Pokaż / ukryj opcję 'Reboot'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_VIEWS_SETTINGS, + "Szybkie menu") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_VIEWS_SETTINGS, + "Pokaż lub ukryj elementy na ekranie szybkiego menu.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_TAKE_SCREENSHOT, + "Pokaż zrzut ekranu") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_TAKE_SCREENSHOT, + "Pokaż / ukryj opcję \"Zrób zrzut ekranu\".") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_LOAD_STATE, + "Pokaż stan zapisywania / ładowania") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_LOAD_STATE, + "Pokaż / ukryj opcje zapisywania / ładowania stanu.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE, + "Pokaż Cofnij zapisanie / załadowanie stanu") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE, + "Pokaż / ukryj opcje cofania stanu zapisywania / ładowania.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_ADD_TO_FAVORITES, + "Pokaż Dodaj do ulubionych") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_ADD_TO_FAVORITES, + "Pokaż / ukryj opcję 'Dodaj do ulubionych'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_OPTIONS, + "Pokaż opcje") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_OPTIONS, + "Pokaż / ukryj opcję 'Opcje'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_CONTROLS, + "Pokaż elementy sterujące") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CONTROLS, + "Pokaż / ukryj opcję 'Sterowanie'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_CHEATS, + "Pokaż kody") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CHEATS, + "Pokaż / ukryj opcję 'Cheaty'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SHADERS, + "Pokaż shadery") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SHADERS, + "Pokaż / ukryj opcję 'Shader'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, + "Pokaż zapis nadpisu rdzenia") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, + "Pokaż / ukryj opcję 'Zapisz przesłonięcia podstawowe'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES, + "Pokaż zapisywanie zmian gry") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES, + "Pokaż / ukryj opcję 'Zachowaj pominięcia gry'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_INFORMATION, + "Pokaż informacje") +MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_INFORMATION, + "Pokaż / ukryj opcję 'Informacje'.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_ENABLE, + "Tło powiadomień Włącz") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_RED, + "Czerwony kolor powiadomienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_GREEN, + "Zielony kolor powiadomienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_BLUE, + "Niebieski kolor powiadomienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_OPACITY, + "Krycie tła powiadomienia") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_DISABLE_KIOSK_MODE, + "Wyłącz tryb kiosku") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_DISABLE_KIOSK_MODE, + "Wyłącz tryb kiosku. Ponowne uruchomienie jest wymagane, aby zmiana mogła w pełni działać.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_ENABLE_KIOSK_MODE, + "Włącz tryb kiosku") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENABLE_KIOSK_MODE, + "Chroni konfigurację, ukrywając wszystkie ustawienia związane z konfiguracją.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_KIOSK_MODE_PASSWORD, + "Ustaw hasło do wyłączania trybu kiosku") +MSG_HASH(MENU_ENUM_SUBLABEL_MENU_KIOSK_MODE_PASSWORD, + "Podanie hasła podczas włączania trybu kiosku umożliwia późniejsze wyłączenie go z menu, przechodząc do Menu głównego, wybierając Wyłącz tryb kiosku i wprowadzając hasło.") +MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD, + "Wprowadź hasło") +MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD_OK, + "Hasło poprawne.") +MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD_NOK, + "Hasło niepoprawne.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_COLOR_RED, + "Powiadomienie czerwony kolor") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_COLOR_GREEN, + "Powiadomienie zielony kolor") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_COLOR_BLUE, + "Powiadomienie niebieski kolor") +MSG_HASH(MENU_ENUM_LABEL_VALUE_FRAMECOUNT_SHOW, + "Pokaż liczbę klatek na wyświetlaczu FPS") +MSG_HASH(MSG_CONFIG_OVERRIDE_LOADED, + "Przeładowanie konfiguracji zostało załadowane.") +MSG_HASH(MSG_GAME_REMAP_FILE_LOADED, + "Załadowano plik remap gry.") +MSG_HASH(MSG_CORE_REMAP_FILE_LOADED, + "Załadowano plik wymiany rdzenia.") +MSG_HASH(MENU_ENUM_LABEL_VALUE_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, + "Automatycznie dodawaj zawartość do listy odtwarzania") +MSG_HASH(MENU_ENUM_SUBLABEL_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, + "Automatycznie skanuje załadowaną zawartość, aby pojawiły się w listach odtwarzania.") +MSG_HASH(MSG_SCANNING_OF_FILE_FINISHED, + "Skanowanie pliku zakończone") +MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_OPACITY, + "Przezroczystość okna") diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index e7ad35b7cc..72f5c9c5bc 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -1670,7 +1670,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FORCE_SRGB_DISABLE, MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY, "Frame Delay") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_FULLSCREEN, - "Use Fullscreen Mode") + "Start in Fullscreen Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GAMMA, "Video Gamma") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_GPU_RECORD, @@ -2618,7 +2618,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_FULLSCREEN, - "Start in fullscreen. Can be changed at runtime." + "Start in fullscreen. Can be changed at runtime. Can be overriden by a command line switch" ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_WINDOWED_FULLSCREEN, diff --git a/libretro-common/audio/audio_mix.c b/libretro-common/audio/audio_mix.c index bd40ccb63c..795898c019 100644 --- a/libretro-common/audio/audio_mix.c +++ b/libretro-common/audio/audio_mix.c @@ -111,20 +111,23 @@ void audio_mix_free_chunk(audio_chunk_t *chunk) audio_chunk_t* audio_mix_load_wav_file(const char *path, int sample_rate) { int sample_size; + ssize_t len = 0; + void *buf = NULL; audio_chunk_t *chunk = (audio_chunk_t*)calloc(1, sizeof(*chunk)); if (!chunk) return NULL; - chunk->sample_rate = sample_rate; - - if (!filestream_read_file(path, &chunk->buf, &chunk->len)) + if (!filestream_read_file(path, &buf, &len)) { printf("Could not open WAV file for reading.\n"); goto error; } - chunk->rwav = (rwav_t*)malloc(sizeof(rwav_t)); + chunk->sample_rate = sample_rate; + chunk->buf = buf; + chunk->len = len; + chunk->rwav = (rwav_t*)malloc(sizeof(rwav_t)); if (rwav_load(chunk->rwav, chunk->buf, chunk->len) == RWAV_ITERATE_ERROR) { diff --git a/libretro-common/file/config_file.c b/libretro-common/file/config_file.c index 306aa7d717..fac7cca8be 100644 --- a/libretro-common/file/config_file.c +++ b/libretro-common/file/config_file.c @@ -44,7 +44,6 @@ #include #include #include -#include #define MAX_INCLUDE_DEPTH 16 @@ -78,6 +77,40 @@ struct config_file static config_file_t *config_file_new_internal( const char *path, unsigned depth); +static char *getaline(FILE *file) +{ + char* newline = (char*)malloc(9); + char* newline_tmp = NULL; + size_t cur_size = 8; + size_t idx = 0; + int in = fgetc(file); + + if (!newline) + return NULL; + + while (in != EOF && in != '\n') + { + if (idx == cur_size) + { + cur_size *= 2; + newline_tmp = (char*)realloc(newline, cur_size + 1); + + if (!newline_tmp) + { + free(newline); + return NULL; + } + + newline = newline_tmp; + } + + newline[idx++] = in; + in = fgetc(file); + } + newline[idx] = '\0'; + return newline; +} + static char *strip_comment(char *str) { /* Remove everything after comment. @@ -190,7 +223,7 @@ static void add_child_list(config_file_t *parent, config_file_t *child) /* Rebase tail. */ if (parent->entries) { - struct config_entry_list *head = + struct config_entry_list *head = (struct config_entry_list*)parent->entries; while (head->next) @@ -311,11 +344,10 @@ static bool parse_line(config_file_t *conf, key[idx++] = *line++; } - key[idx] = '\0'; - list->key = key; - - list->value = extract_value(line, true); + key[idx] = '\0'; + list->key = key; + list->value = extract_value(line, true); if (!list->value) { list->key = NULL; @@ -332,7 +364,7 @@ error: static config_file_t *config_file_new_internal( const char *path, unsigned depth) { - RFILE *file = NULL; + FILE *file = NULL; struct config_file *conf = (struct config_file*)malloc(sizeof(*conf)); if (!conf) return NULL; @@ -354,9 +386,7 @@ static config_file_t *config_file_new_internal( goto error; conf->include_depth = depth; - file = filestream_open(path, - RETRO_VFS_FILE_ACCESS_READ, - RETRO_VFS_FILE_ACCESS_HINT_NONE); + file = fopen_utf8(path, "r"); if (!file) { @@ -364,7 +394,7 @@ static config_file_t *config_file_new_internal( goto error; } - while (!filestream_eof(file)) + while (!feof(file)) { char *line = NULL; struct config_entry_list *list = (struct config_entry_list*)malloc(sizeof(*list)); @@ -372,7 +402,7 @@ static config_file_t *config_file_new_internal( if (!list) { config_file_free(conf); - filestream_close(file); + fclose(file); return NULL; } @@ -381,7 +411,7 @@ static config_file_t *config_file_new_internal( list->value = NULL; list->next = NULL; - line = filestream_getline(file); + line = getaline(file); if (!line) { @@ -405,7 +435,7 @@ static config_file_t *config_file_new_internal( free(list); } - filestream_close(file); + fclose(file); return conf; @@ -490,7 +520,7 @@ config_file_t *config_file_new_from_string(const char *from_string) conf->tail = NULL; conf->includes = NULL; conf->include_depth = 0; - + lines = string_split(from_string, "\n"); if (!lines) return conf; @@ -542,8 +572,11 @@ config_file_t *config_file_new(const char *path) static struct config_entry_list *config_get_entry(const config_file_t *conf, const char *key, struct config_entry_list **prev) { - struct config_entry_list *entry = NULL; - struct config_entry_list *previous = prev ? *prev : NULL; + struct config_entry_list *entry; + struct config_entry_list *previous = NULL; + + if (prev) + previous = *prev; for (entry = conf->entries; entry; entry = entry->next) { @@ -869,32 +902,9 @@ void config_set_bool(config_file_t *conf, const char *key, bool val) config_set_string(conf, key, val ? "true" : "false"); } -bool config_file_write(config_file_t *conf, const char *path) -{ - if (!string_is_empty(path)) - { - void* buf = NULL; - FILE *file = fopen_utf8(path, "wb"); - if (!file) - return false; - - /* TODO: this is only useful for a few platforms, find which and add ifdef */ - buf = calloc(1, 0x4000); - setvbuf(file, (char*)buf, _IOFBF, 0x4000); - - config_file_dump(conf, file); - - if (file != stdout) - fclose(file); - free(buf); - } - else - config_file_dump(conf, stdout); - - return true; -} - -void config_file_dump(config_file_t *conf, FILE *file) +/* Dump the current config to an already opened file. + * Does not close the file. */ +static void config_file_dump(config_file_t *conf, FILE *file) { struct config_entry_list *list = NULL; struct config_include_list *includes = conf->includes; @@ -915,6 +925,33 @@ void config_file_dump(config_file_t *conf, FILE *file) } } +bool config_file_write(config_file_t *conf, const char *path) +{ + void* buf = NULL; + FILE *file = !string_is_empty(path) ? fopen_utf8(path, "wb") : stdout; + + if (!file) + return false; + + /* TODO: this is only useful for a few platforms, find which and add ifdef */ + if (file != stdout) + { + buf = calloc(1, 0x4000); + setvbuf(file, (char*)buf, _IOFBF, 0x4000); + } + + config_file_dump(conf, file); + + if (file != stdout) + { + fclose(file); + free(buf); + } + + return true; +} + + bool config_entry_exists(config_file_t *conf, const char *entry) { struct config_entry_list *list = conf->entries; diff --git a/libretro-common/include/file/config_file.h b/libretro-common/include/file/config_file.h index 9a19beda4e..2cbe46b41d 100644 --- a/libretro-common/include/file/config_file.h +++ b/libretro-common/include/file/config_file.h @@ -154,10 +154,6 @@ void config_set_bool(config_file_t *conf, const char *entry, bool val); /* Write the current config to a file. */ bool config_file_write(config_file_t *conf, const char *path); -/* Dump the current config to an already opened file. - * Does not close the file. */ -void config_file_dump(config_file_t *conf, FILE *file); - bool config_file_exists(const char *path); RETRO_END_DECLS diff --git a/libretro-common/include/net/net_compat.h b/libretro-common/include/net/net_compat.h index dc8cdc1aad..7a182af2af 100644 --- a/libretro-common/include/net/net_compat.h +++ b/libretro-common/include/net/net_compat.h @@ -156,8 +156,10 @@ static INLINE bool isagain(int bytes) if (WSAGetLastError() != WSAEWOULDBLOCK) return false; return true; +#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) + return (sys_net_errno == SYS_NET_EWOULDBLOCK) || (sys_net_errno == SYS_NET_EAGAIN);//35 #elif defined(VITA) - return (bytes<0 && (bytes == SCE_NET_ERROR_EAGAIN || bytes == SCE_NET_ERROR_EWOULDBLOCK)); + return (bytes<0 && (bytes == SCE_NET_ERROR_EAGAIN || bytes == SCE_NET_ERROR_EWOULDBLOCK)); #elif defined(WIIU) return (bytes == -1) && ((socketlasterr() == SO_SUCCESS) || (socketlasterr() == SO_EWOULDBLOCK)); #else diff --git a/libretro-common/include/retro_miscellaneous.h b/libretro-common/include/retro_miscellaneous.h index 4768b90975..e526d6ebc2 100644 --- a/libretro-common/include/retro_miscellaneous.h +++ b/libretro-common/include/retro_miscellaneous.h @@ -36,12 +36,23 @@ #include #endif +#if defined(__CELLOS_LV2__) +#include +#endif + #include #ifdef _MSC_VER #include #endif +static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count) +{ + uint32_t i; + for (i = 0; i < count;i++) + a[i] |= b[i]; +} + static INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count) { uint32_t i; @@ -61,7 +72,9 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count) } #ifndef PATH_MAX_LENGTH -#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)|| defined(WIIU) +#if defined(__CELLOS_LV2__) +#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH +#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)|| defined(WIIU) #define PATH_MAX_LENGTH 512 #else #define PATH_MAX_LENGTH 4096 diff --git a/libretro-common/include/streams/file_stream_transforms.h b/libretro-common/include/streams/file_stream_transforms.h index a1f8da7830..0cd565b61c 100644 --- a/libretro-common/include/streams/file_stream_transforms.h +++ b/libretro-common/include/streams/file_stream_transforms.h @@ -24,12 +24,11 @@ #define __LIBRETRO_SDK_FILE_STREAM_TRANSFORMS_H #include +#include #include RETRO_BEGIN_DECLS -typedef struct RFILE RFILE; - #define FILE RFILE #undef fopen diff --git a/libretro-common/net/net_compat.c b/libretro-common/net/net_compat.c index 9238ebc9e6..1d3ae1c5a9 100644 --- a/libretro-common/net/net_compat.c +++ b/libretro-common/net/net_compat.c @@ -193,12 +193,6 @@ int getaddrinfo_retro(const char *node, const char *service, in_addr->sin_family = AF_INET; in_addr->sin_port = inet_htons(strtoul(service, NULL, 0)); - //sin_port seems to be the wrong endian for ps3 - #if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) - in_addr->sin_port = (in_addr->sin_port>>8) | (in_addr->sin_port<<8); - #endif - - if (!node && (hints->ai_flags & AI_PASSIVE)) in_addr->sin_addr.s_addr = INADDR_ANY; else if (node && isdigit(*node)) @@ -212,7 +206,7 @@ int getaddrinfo_retro(const char *node, const char *service, in_addr->sin_family = host->h_addrtype; -#ifdef AF_INET6 +#if defined(AF_INET6) && !defined(__CELLOS_LV2__) /* TODO/FIXME - In case we ever want to support IPv6 */ in_addr->sin_addr.s_addr = inet_addr(host->h_addr_list[0]); #else diff --git a/libretro-common/streams/interface_stream.c b/libretro-common/streams/interface_stream.c index 44177aa7d7..5edb5fdd9c 100644 --- a/libretro-common/streams/interface_stream.c +++ b/libretro-common/streams/interface_stream.c @@ -161,6 +161,7 @@ int intfstream_close(intfstream_internal_t *intf) case INTFSTREAM_FILE: if (intf->file.fp) return filestream_close(intf->file.fp); + return 0; case INTFSTREAM_MEMORY: if (intf->memory.fp) memstream_close(intf->memory.fp); diff --git a/libretro-db/Makefile b/libretro-db/Makefile index 49023b398f..1a8824662c 100644 --- a/libretro-db/Makefile +++ b/libretro-db/Makefile @@ -12,7 +12,8 @@ CFLAGS = -g -O2 -Wall -DNDEBUG endif LIBRETRO_COMMON_C = \ - $(LIBRETRO_COMM_DIR)/streams/file_stream.c + $(LIBRETRO_COMM_DIR)/streams/file_stream.c \ + $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c C_CONVERTER_C = \ $(LIBRETRODB_DIR)/rmsgpack.c \ @@ -71,4 +72,4 @@ rmsgpack_test: $(RMSGPACK_OBJS) $(CC) $(INCFLAGS) $(RMSGPACK_OBJS) -g -o $@ clean: - rm -rf $(TARGETS) $(C_CONVERTER_OBJS) $(RARCHDB_TOOL_OBJS) $(RMSGPACK_OBJS) $(TESTLIB_OBJS) + rm -rf $(TARGETS) $(C_CONVERTER_OBJS) $(RARCHDB_TOOL_OBJS) $(RMSGPACK_OBJS) $(TESTLIB_OBJS) diff --git a/libretro-db/c_converter.c b/libretro-db/c_converter.c index d114188553..f08171ca17 100644 --- a/libretro-db/c_converter.c +++ b/libretro-db/c_converter.c @@ -32,6 +32,7 @@ #include #include +#include #include "libretrodb.h" diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 3fb2a7a3e7..8969a05d7f 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -3431,6 +3431,9 @@ static void netplay_refresh_rooms_cb(void *task_data, void *user_data, const cha strlcpy(netplay_room_list[i].gamename, host->content, sizeof(netplay_room_list[i].gamename)); + strlcpy(netplay_room_list[i].frontend, + host->frontend, + sizeof(netplay_room_list[i].frontend)); netplay_room_list[i].port = host->port; netplay_room_list[i].gamecrc = host->content_crc; @@ -3745,12 +3748,15 @@ static int action_ok_netplay_enable_host(const char *path, bool contentless = false; bool is_inited = false; + file_list_t *list = menu_entries_get_selection_buf_ptr(0); + content_get_status(&contentless, &is_inited); if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) generic_action_ok_command(CMD_EVENT_NETPLAY_DEINIT); netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_SERVER, NULL); + netplay_refresh_rooms_menu(list); /* If we haven't yet started, this will load on its own */ if (!is_inited) { diff --git a/menu/cbs/menu_cbs_select.c b/menu/cbs/menu_cbs_select.c index 86dcb8e654..c0e9141caf 100644 --- a/menu/cbs/menu_cbs_select.c +++ b/menu/cbs/menu_cbs_select.c @@ -148,11 +148,13 @@ static int action_select_input_desc(const char *path, const char *label, unsigne return action_right_input_desc(type, label, true); } +#ifdef HAVE_KEYMAPPER static int action_select_input_desc_kbd(const char *path, const char *label, unsigned type, size_t idx) { return action_right_input_desc_kbd(type, label, true); } +#endif static int action_select_netplay_connect_room(const char *path, const char *label, unsigned type, size_t idx) diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 2dd471d3cc..3dd870bd06 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -405,6 +405,8 @@ static int action_bind_sublabel_netplay_room( const char *corename = NULL; const char *gamename = NULL; const char *core_ver = NULL; + const char *frontend = NULL; + /* This offset may cause issues if any entries are added to this menu */ unsigned offset = i - 3; @@ -415,11 +417,13 @@ static int action_bind_sublabel_netplay_room( corename = netplay_room_list[offset].corename; gamename = netplay_room_list[offset].gamename; core_ver = netplay_room_list[offset].coreversion; - gamecrc = netplay_room_list[offset].gamecrc; + gamecrc = netplay_room_list[offset].gamecrc; + frontend = netplay_room_list[offset].frontend; snprintf(s, len, - "RetroArch: %s\nCore: %s (%s)\nGame: %s (%08x)", + "RetroArch: %s (%s)\nCore: %s (%s)\nGame: %s (%08x)", string_is_empty(ra_version) ? "n/a" : ra_version, + string_is_empty(frontend) ? "n/a" : frontend, corename, core_ver, !string_is_equal(gamename, "N/A") ? gamename : "n/a", gamecrc); diff --git a/menu/cbs/menu_cbs_title.c b/menu/cbs/menu_cbs_title.c index 230b5b08d2..8f87b92ae6 100644 --- a/menu/cbs/menu_cbs_title.c +++ b/menu/cbs/menu_cbs_title.c @@ -1119,5 +1119,11 @@ int menu_cbs_init_bind_title(menu_file_list_cbs_t *cbs, if (menu_cbs_init_bind_title_compare_type(cbs, type) == 0) return 0; + if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS))) + { + BIND_ACTION_GET_TITLE(cbs, action_get_quick_menu_views_settings_list); + return 0; + } + return -1; } diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 265b6004fb..6929da58f8 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -3354,7 +3354,7 @@ static bool setting_append_list( general_write_handler, general_read_handler, SD_FLAG_CMD_APPLY_AUTO); - menu_settings_list_current_add_cmd(list, list_info, CMD_EVENT_REINIT); + menu_settings_list_current_add_cmd(list, list_info, CMD_EVENT_REINIT_FROM_TOGGLE); settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED); } if (video_driver_has_windowed()) diff --git a/network/netplay/netplay.h b/network/netplay/netplay.h index 2d9d1d0e38..b680298584 100644 --- a/network/netplay/netplay.h +++ b/network/netplay/netplay.h @@ -91,4 +91,6 @@ int netplay_rooms_get_count(); void netplay_rooms_free(); +void netplay_get_architecture(char *frontend_architecture, size_t size); + #endif diff --git a/network/netplay/netplay_discovery.c b/network/netplay/netplay_discovery.c index 7aceac4df5..7a919b7e2e 100644 --- a/network/netplay/netplay_discovery.c +++ b/network/netplay/netplay_discovery.c @@ -63,6 +63,7 @@ struct ad_packet char address[NETPLAY_HOST_STR_LEN]; char retroarch_version[NETPLAY_HOST_STR_LEN]; char nick[NETPLAY_HOST_STR_LEN]; + char frontend[NETPLAY_HOST_STR_LEN]; char core[NETPLAY_HOST_STR_LEN]; char core_version[NETPLAY_HOST_STR_LEN]; char content[NETPLAY_HOST_LONGSTR_LEN]; @@ -290,6 +291,8 @@ bool netplay_lan_ad_server(netplay_t *netplay) { char *p; char sub[NETPLAY_HOST_STR_LEN]; + char frontend[NETPLAY_HOST_STR_LEN]; + netplay_get_architecture(frontend, sizeof(frontend)); p=strrchr(reply_addr,'.'); if (p) @@ -321,6 +324,7 @@ bool netplay_lan_ad_server(netplay_t *netplay) ? path_basename(path_get(RARCH_PATH_BASENAME)) : "N/A", NETPLAY_HOST_LONGSTR_LEN); strlcpy(ad_packet_buffer.nick, netplay->nick, NETPLAY_HOST_STR_LEN); + strlcpy(ad_packet_buffer.frontend, frontend, NETPLAY_HOST_STR_LEN); if (info) { @@ -482,6 +486,8 @@ static bool netplay_lan_ad_client(void) NETPLAY_HOST_STR_LEN); strlcpy(host->content, ad_packet_buffer.content, NETPLAY_HOST_LONGSTR_LEN); + strlcpy(host->frontend, ad_packet_buffer.frontend, + NETPLAY_HOST_LONGSTR_LEN); host->content_crc = atoi(ad_packet_buffer.content_crc); diff --git a/network/netplay/netplay_discovery.h b/network/netplay/netplay_discovery.h index 8af63ddbc0..91153d3f46 100644 --- a/network/netplay/netplay_discovery.h +++ b/network/netplay/netplay_discovery.h @@ -39,6 +39,7 @@ struct netplay_host char address[NETPLAY_HOST_STR_LEN]; char nick[NETPLAY_HOST_STR_LEN]; + char frontend[NETPLAY_HOST_STR_LEN]; char core[NETPLAY_HOST_STR_LEN]; char core_version[NETPLAY_HOST_STR_LEN]; char retroarch_version[NETPLAY_HOST_STR_LEN]; @@ -69,6 +70,7 @@ struct netplay_room int port; int mitm_port; char corename [PATH_MAX_LENGTH]; + char frontend [PATH_MAX_LENGTH]; char coreversion [PATH_MAX_LENGTH]; char gamename [PATH_MAX_LENGTH]; int gamecrc; diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 8fbdeda591..c5d404dcba 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -605,6 +605,49 @@ static void netplay_announce_cb(void *task_data, void *user_data, const char *er return; } +void netplay_get_architecture(char *frontend_architecture, size_t size) +{ + const frontend_ctx_driver_t + *frontend = frontend_get_ptr(); + enum frontend_architecture arch = frontend_driver_get_cpu_architecture(); + char architecture[PATH_MAX_LENGTH]; + + switch (arch) + { + case FRONTEND_ARCH_X86: + strlcpy(architecture, "x86", sizeof(architecture)); + break; + case FRONTEND_ARCH_X86_64: + strlcpy(architecture, "x64", sizeof(architecture)); + break; + case FRONTEND_ARCH_PPC: + strlcpy(architecture, "PPC", sizeof(architecture)); + break; + case FRONTEND_ARCH_ARM: + strlcpy(architecture, "ARM", sizeof(architecture)); + break; + case FRONTEND_ARCH_ARMV7: + strlcpy(architecture, "ARMv7", sizeof(architecture)); + break; + case FRONTEND_ARCH_ARMV8: + strlcpy(architecture, "ARMv8", sizeof(architecture)); + break; + case FRONTEND_ARCH_MIPS: + strlcpy(architecture, "MIPS", sizeof(architecture)); + break; + case FRONTEND_ARCH_TILE: + strlcpy(architecture, "Tilera", sizeof(architecture)); + break; + case FRONTEND_ARCH_NONE: + default: + strlcpy(architecture, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), + sizeof(architecture)); + break; + } + snprintf(frontend_architecture, size, "%s %s", frontend->ident, architecture); +} + static void netplay_announce(void) { char buf [2048]; @@ -617,8 +660,9 @@ static void netplay_announce(void) settings_t *settings = config_get_ptr(); rarch_system_info_t *system = runloop_get_system_info(); uint32_t content_crc = content_get_crc(); - const frontend_ctx_driver_t - *frontend = frontend_get_ptr(); + char frontend_architecture[PATH_MAX_LENGTH]; + + netplay_get_architecture(frontend_architecture, sizeof(frontend_architecture)); net_http_urlencode_full(&username, settings->paths.username); net_http_urlencode_full(&corename, system->info.library_name); @@ -626,7 +670,7 @@ static void netplay_announce(void) !string_is_empty(path_basename(path_get(RARCH_PATH_BASENAME))) ? path_basename(path_get(RARCH_PATH_BASENAME)) : "N/A"); net_http_urlencode_full(&coreversion, system->info.library_version); - net_http_urlencode_full(&frontend_ident, frontend->ident); + net_http_urlencode_full(&frontend_ident, frontend_architecture); buf[0] = '\0'; @@ -638,7 +682,7 @@ static void netplay_announce(void) *settings->paths.netplay_password ? 1 : 0, *settings->paths.netplay_spectate_password ? 1 : 0, settings->bools.netplay_use_mitm_server, - PACKAGE_VERSION, frontend_ident); + PACKAGE_VERSION, frontend_architecture); #if 0 RARCH_LOG("[netplay] announcement URL: %s\n", buf); #endif diff --git a/network/netplay/netplay_room_parse.c b/network/netplay/netplay_room_parse.c index df8877f78c..aebb3b2dde 100644 --- a/network/netplay/netplay_room_parse.c +++ b/network/netplay/netplay_room_parse.c @@ -283,6 +283,11 @@ static JSON_Parser_HandlerResult JSON_CALL ObjectMemberHandler(JSON_Parser parse pCtx->cur_field = strdup(pValue); pCtx->cur_member = &rooms->cur->country; } + else if (string_is_equal_fast(pValue, "frontend", 7)) + { + pCtx->cur_field = strdup(pValue); + pCtx->cur_member = &rooms->cur->frontend; + } } } diff --git a/pkg/android/phoenix/AndroidManifest.xml b/pkg/android/phoenix/AndroidManifest.xml index b2896d6872..b8621b4d87 100644 --- a/pkg/android/phoenix/AndroidManifest.xml +++ b/pkg/android/phoenix/AndroidManifest.xml @@ -1,8 +1,8 @@ diff --git a/retroarch.c b/retroarch.c index 79b3f64dd1..1f1c801b06 100644 --- a/retroarch.c +++ b/retroarch.c @@ -1106,8 +1106,6 @@ static bool retroarch_init_state(void) video_driver_set_active(); audio_driver_set_active(); - rarch_force_fullscreen = false; - return true; } @@ -1182,10 +1180,6 @@ static void retroarch_main_init_media(void) if (!settings) return; - /* -L overrides internal cores */ - if (!string_is_empty(path_get(RARCH_PATH_CORE))) - return; - builtin_imageviewer = settings->bools.multimedia_builtin_imageviewer_enable; builtin_mediaplayer = settings->bools.multimedia_builtin_mediaplayer_enable; @@ -1447,7 +1441,6 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data) rarch_is_inited = false; rarch_error_on_init = false; rarch_block_config_read = false; - rarch_force_fullscreen = false; retroarch_msg_queue_deinit(); driver_uninit(DRIVERS_CMD_ALL); @@ -1926,6 +1919,11 @@ bool retroarch_is_forced_fullscreen(void) return rarch_force_fullscreen; } +void retroarch_unset_forced_fullscreen(void) +{ + rarch_force_fullscreen = false; +} + bool retroarch_override_setting_is_set(enum rarch_override_setting enum_idx, void *data) { switch (enum_idx) @@ -2365,6 +2363,7 @@ static enum runloop_state runloop_check_state( bool input_nonblock_state, unsigned *sleep_ms) { + retro_bits_t current_input; static retro_bits_t last_input = {{0}}; static bool old_fs_toggle_pressed= false; static bool old_focus = true; @@ -2378,17 +2377,12 @@ static enum runloop_state runloop_check_state( bool menu_driver_binding_state = menu_driver_is_binding_state(); bool menu_is_alive = menu_driver_is_alive(); - retro_bits_t current_input; - if (menu_is_alive && !(settings->bools.menu_unified_controls && !menu_input_dialog_get_display_kb())) input_menu_keys_pressed(settings, ¤t_input); else +#endif input_keys_pressed(settings, ¤t_input); -#else - retro_bits_t current_input; - input_keys_pressed(settings, ¤t_input); -#endif last_input = current_input; #ifdef HAVE_MENU diff --git a/retroarch.h b/retroarch.h index 123f3c6bcb..05614aba92 100644 --- a/retroarch.h +++ b/retroarch.h @@ -289,6 +289,8 @@ bool retroarch_validate_game_options(char *s, size_t len, bool mkdir); bool retroarch_is_forced_fullscreen(void); +void retroarch_unset_forced_fullscreen(void); + void retroarch_set_current_core_type(enum rarch_core_type type, bool explicitly_set); /** diff --git a/tasks/task_overlay.c b/tasks/task_overlay.c index a541448724..d0f4895a21 100644 --- a/tasks/task_overlay.c +++ b/tasks/task_overlay.c @@ -177,7 +177,8 @@ static bool task_overlay_load_desc( box_hash = djb2_calculate(box); key_hash = djb2_calculate(key); - desc->key_mask = 0; + desc->retro_key_idx = 0; + BIT256_CLEAR_ALL(desc->button_mask); switch (key_hash) { @@ -190,8 +191,8 @@ static bool task_overlay_load_desc( default: if (strstr(key, "retrok_") == key) { - desc->type = OVERLAY_TYPE_KEYBOARD; - desc->key_mask = input_config_translate_str_to_rk(key + 7); + desc->type = OVERLAY_TYPE_KEYBOARD; + desc->retro_key_idx = input_config_translate_str_to_rk(key + 7); } else { @@ -203,11 +204,10 @@ static bool task_overlay_load_desc( for (; tmp; tmp = strtok_r(NULL, "|", &save)) { if (!string_is_equal(tmp, file_path_str(FILE_PATH_NUL))) - desc->key_mask |= UINT64_C(1) - << input_config_translate_str_to_bind_id(tmp); + BIT256_SET(desc->button_mask, input_config_translate_str_to_bind_id(tmp)); } - if (desc->key_mask & (UINT64_C(1) << RARCH_OVERLAY_NEXT)) + if (BIT256_GET(desc->button_mask, RARCH_OVERLAY_NEXT)) { char overlay_target_key[64]; diff --git a/version.all b/version.all index ce3e230e61..e821c93a1a 100644 --- a/version.all +++ b/version.all @@ -6,8 +6,8 @@ # /* - pkg/snap/snapcraft.yaml (including the github url) */ #if 0 -RARCH_VERSION="1.6.9" +RARCH_VERSION="1.7.0" #endif #ifndef PACKAGE_VERSION -#define PACKAGE_VERSION "1.6.9" +#define PACKAGE_VERSION "1.7.0" #endif diff --git a/version.dtd b/version.dtd index d1fb503a4e..094dbc1191 100644 --- a/version.dtd +++ b/version.dtd @@ -1 +1 @@ - +