Merge pull request #4 from libretro/master

Use better devkit arm fix
This commit is contained in:
meepingsnesroms 2017-12-25 17:53:08 -08:00 committed by GitHub
commit c978b53214
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
119 changed files with 12507 additions and 1516 deletions

View File

@ -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.

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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();

View File

@ -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,

View File

@ -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

View File

@ -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++)
{

View File

@ -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" },

View File

@ -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

View File

@ -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
}

View File

@ -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;

61
deps/libfat/bit_ops.h vendored Normal file
View File

@ -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 <stdint.h>
/*-----------------------------------------------------------------
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 */

336
deps/libfat/cache.c vendored Normal file
View File

@ -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 <string.h>
#include <limits.h>
#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<numberOfPages;i++)
{
if(sector>=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_access<oldAccess))
{
if(cacheEntries[i].sector==CACHE_FREE) foundFree = true;
oldUsed = i;
oldAccess = cacheEntries[i].last_access;
}
}
if(foundFree==false && cacheEntries[oldUsed].dirty==true)
{
if(!_FAT_disc_writeSectors(cache->disc,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;
}
}

128
deps/libfat/cache.h vendored Normal file
View File

@ -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

92
deps/libfat/common.h vendored Normal file
View File

@ -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 <fat.h>
#include <stddef.h>
#include <stdint.h>
/* 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 <iosuhax_disc_interface.h>
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 <gctypes.h>
#include <ogc/disc_io.h>
#include <gccore.h>
#elif defined(NDS)
#include <nds/ndstypes.h>
#include <nds/system.h>
#include <nds/disc_io.h>
#elif defined(GBA)
#include <gba_types.h>
#include <disc_io.h>
#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 */

1180
deps/libfat/directory.c vendored Normal file

File diff suppressed because it is too large Load Diff

181
deps/libfat/directory.h vendored Normal file
View File

@ -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 <sys/stat.h>
#include <sys/syslimits.h>
#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 */

139
deps/libfat/disc.c vendored Normal file
View File

@ -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 <iosuhax_disc_interface.h>
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 <sdcard/wiisd_io.h>
#include <ogc/usbstorage.h>
#include <sdcard/gcsd.h>
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 <sdcard/gcsd.h>
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 <nds/system.h>
#include <nds/arm9/dldi.h>
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 <disc.h>
const INTERFACE_ID _FAT_disc_interfaces[] = {
{"fat", discGetInterface},
{NULL, NULL}
};
#endif

119
deps/libfat/disc.h vendored Normal file
View File

@ -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 */

666
deps/libfat/fatdir.c vendored Normal file
View File

@ -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 <string.h>
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/iosupport.h>
#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;
}

73
deps/libfat/fatdir.h vendored Normal file
View File

@ -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 <sys/reent.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/iosupport.h>
#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

1235
deps/libfat/fatfile.c vendored Normal file

File diff suppressed because it is too large Load Diff

105
deps/libfat/fatfile.h vendored Normal file
View File

@ -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 <sys/reent.h>
#include <sys/stat.h>
#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 */

395
deps/libfat/file_allocation_table.c vendored Normal file
View File

@ -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 <string.h>
/*
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;
}

70
deps/libfat/file_allocation_table.h vendored Normal file
View File

@ -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 */

111
deps/libfat/filetime.c vendored Normal file
View File

@ -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 <time.h>
#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);
}

41
deps/libfat/filetime.h vendored Normal file
View File

@ -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 <sys/types.h>
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 */

124
deps/libfat/include/fat.h vendored Normal file
View File

@ -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 <libfatversion.h>
/* When compiling for NDS, make sure NDS is defined */
#ifndef NDS
#if defined ARM9 || defined ARM7
#define NDS
#endif
#endif
#include <stdint.h>
#if defined (__wiiu__)
# include <iosuhax_disc_interface.h>
#elif defined(__gamecube__) || defined (__wii__)
# include <ogc/disc_io.h>
#else
# ifdef NDS
# include <nds/disc_io.h>
# else
# include <disc_io.h>
# 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 */

10
deps/libfat/include/libfatversion.h vendored Normal file
View File

@ -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__ */

264
deps/libfat/libfat.c vendored Normal file
View File

@ -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 <sys/iosupport.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#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';
}

29
deps/libfat/lock.c vendored Normal file
View File

@ -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 */

72
deps/libfat/lock.h vendored Normal file
View File

@ -0,0 +1,72 @@
/*
lock.h
Copyright (c) 2008 Sven Peter <svpe@gmx.net>
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 */

55
deps/libfat/mem_allocate.h vendored Normal file
View File

@ -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 <malloc.h>
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 */

464
deps/libfat/partition.c vendored Normal file
View File

@ -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 <string.h>
#include <ctype.h>
#include <sys/iosupport.h>
/*
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;
}

107
deps/libfat/partition.h vendored Normal file
View File

@ -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 */

966
deps/libiosuhax/iosuhax.c vendored Normal file
View File

@ -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 <string.h>
#include <malloc.h>
#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;
}

109
deps/libiosuhax/iosuhax.h vendored Normal file
View File

@ -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 <stdint.h>
#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

974
deps/libiosuhax/iosuhax_devoptab.c vendored Normal file
View File

@ -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 <errno.h>
#include <sys/statvfs.h>
#include <sys/dirent.h>
#include <string.h>
#include <malloc.h>
#include <stdint.h>
#include <fcntl.h>
#include <stdio.h>
#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);
}

42
deps/libiosuhax/iosuhax_devoptab.h vendored Normal file
View File

@ -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_

262
deps/libiosuhax/iosuhax_disc_interface.c vendored Normal file
View File

@ -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 <string.h>
#include <malloc.h>
#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
};

View File

@ -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 <stdint.h>
#include <stdbool.h>
#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

44
deps/libiosuhax/os_functions.h vendored Normal file
View File

@ -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_

View File

@ -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)
{

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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};

View File

@ -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);

View File

@ -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;

View File

@ -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)
{

View File

@ -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 = {

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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))

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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; i<ARRAY_SIZE(desc->button_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;

View File

@ -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);

View File

@ -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 "<Katalog treści>";
case MENU_ENUM_LABEL_VALUE_DIRECTORY_DEFAULT:
return "<Domyślny>";
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 "<Przeszukaj ten katalog>";
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 "<Użyj tego katalogu>";
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;
}

3345
intl/msg_hash_pl.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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,

View File

@ -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)
{

View File

@ -44,7 +44,6 @@
#include <file/file_path.h>
#include <lists/string_list.h>
#include <string/stdstring.h>
#include <streams/file_stream.h>
#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;

View File

@ -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

View File

@ -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

View File

@ -36,12 +36,23 @@
#include <Xtl.h>
#endif
#if defined(__CELLOS_LV2__)
#include <sys/fs_external.h>
#endif
#include <limits.h>
#ifdef _MSC_VER
#include <compat/msvc.h>
#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

View File

@ -24,12 +24,11 @@
#define __LIBRETRO_SDK_FILE_STREAM_TRANSFORMS_H
#include <retro_common_api.h>
#include <streams/file_stream.h>
#include <string.h>
RETRO_BEGIN_DECLS
typedef struct RFILE RFILE;
#define FILE RFILE
#undef fopen

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More