Compare commits

..

46 Commits

Author SHA1 Message Date
fysx c0fd9a6e1b beta2 2014-02-23 15:21:29 +01:00
fysx 539ca8d4f2 fixed opening of .love files when URL is entered in Chrome 2014-02-23 14:51:33 +01:00
fysx fab725ad8b using identity 'unnamed' if none is specified in conf.lua(fixes issue #46) 2014-02-20 22:31:59 +01:00
fysx 5f6fa8c2b5 Proper downloading of games and starting works when downloaded using the LÖVE app 2014-02-20 21:27:34 +01:00
fysx 4c2846f4bb download and progress bar somewhat work 2014-02-19 20:57:09 +01:00
fysx cb2c852f58 trying to add running of games via http link 2014-02-14 01:41:47 +01:00
fysx 60a58f9240 Merged GameLauncher and GameActivity together
The GameActivity would not run otherwise as the App started via
GameActivity would call in love::android::getSelectedGameFile() the wrong
activity (namely GameLauncher) that was not initialized properly. Hence it
would result in a segfault.
2014-02-14 00:56:47 +01:00
fysx 5849e8d369 fixed indentations 2014-02-13 14:24:17 +01:00
fysx 1703660617 fixed loading of files from file managers 2014-02-13 14:08:06 +01:00
fysx 0db55463c9 Allow .love files to be opened from email attachements 2014-02-13 13:56:23 +01:00
fysx 288b25c585 ensure that static variable is properly initialized 2014-02-13 01:31:20 +01:00
fysx a5284dccf6 Merge branch 'filetype_association' 2014-02-13 01:30:36 +01:00
Jairo Luiz 8069dc02c6 Now, we have a filetype association!!!! :) 2014-02-12 20:56:11 -03:00
fysx 0bde453b2e updated to changeset 80f0adedfaa5 of love-android (including newest mobile-common changes) 2014-02-13 00:44:51 +01:00
fysx 667c4750ea properly load shared libraries 2014-02-11 02:00:33 +01:00
fysx 38727b5c25 beta1 - here we go 2014-02-11 01:03:39 +01:00
fysx 288a851a65 fix for the fix for the non-improvement 2014-02-11 00:42:05 +01:00
fysx 5e3579f680 should fix the crash on startup 2014-02-11 00:26:03 +01:00
fysx 1dd859c9d1 fixed indentations 2014-02-10 08:31:40 +01:00
fysx 53d45533e0 properly using workaround for love.filesystem.getDirectoryItems 2014-02-10 08:30:43 +01:00
fysx 3f13dc653f fixed issue tracker link 2014-02-09 23:57:03 +01:00
fysx 9e7e31ba05 preparing alpha9 release 2014-02-09 23:15:15 +01:00
fysx 3f268ebedf Added workaround for love.filesystem.getDirectoryItems 2014-02-09 23:02:04 +01:00
fysx 8fb02e11ab static linking of SDL2: do not load libSDL2.so from Java 2014-02-09 22:58:45 +01:00
fysx 89c54f9712 Using static linking for SDL2 2014-02-09 15:01:12 +01:00
fysx 606da6d0ae removed debug output 2014-02-08 00:41:45 +01:00
fysx 52d505624d further readme tweaks 2014-02-07 23:46:12 +01:00
fysx 89c9baf274 trying to link to the wiki from the readme file 2014-02-07 23:43:14 +01:00
fysx e4e1a0f59b properly use dynamic linking for LGPL libraries 2014-02-07 23:40:02 +01:00
fysx 00052d8067 Use SDL_AndroidGetActivity() instead of the full activity name (better for custom packages) 2014-02-06 01:29:36 +01:00
fysx de93ded9bf removed include dir for the SDL private headers 2014-02-06 01:18:17 +01:00
fysx 2da2da2652 Replaced use of SDL internal header file with the public interface 2014-02-06 01:13:38 +01:00
fysx bfae01300e fixed mouse coordinates due to the love.window.getScale() change 2014-02-06 01:02:47 +01:00
fysx 0b8dd90114 properly free JNI objects 2014-02-06 00:52:52 +01:00
fysx 3cabe641d6 Disable OpenGL debug on OpenGL ES2 (should fix Ouya compatibility) 2014-02-06 00:14:33 +01:00
fysx 351e224815 LuaJIT: use proper -mfpu flags and added new binaries 2014-02-06 00:07:56 +01:00
Martin Felis 89c2c014b2 Merged in josefnpat's fantastic icon. THANKS!!!
Updating `res/drawable-*/ic_launcher.png` to proposed icon (icon2)
2014-02-05 23:59:52 +01:00
Josef Patoprsty c3a21270ab Updating res/drawable-*/ic_launcher.png to proposed icon (icon2) 2014-02-05 13:12:04 -05:00
Martin Felis 597fad8034 Merged tangerinagames/love-android-sdl2/pixel_scale into master 2014-02-02 21:28:09 +01:00
fysx bf07caef09 Circumventing duplication of assets/game.love by mounting it from memory 2014-02-02 02:19:29 +01:00
fysx c9bb6ec3d6 updated physfs to inofficial 2.1 version 2014-02-02 01:28:41 +01:00
Jairo Luiz 007b0fc3f0 love.window.getPixelScale now works properly on Android. 2014-01-30 15:08:15 -03:00
Jairo Luiz b86319c0f4 remove OpenAL LOCAL_LDLIBS warning 2014-01-30 14:51:03 -03:00
Jairo Luiz 9a688b9b37 remove unnecessary “love.android” module 2014-01-30 14:43:12 -03:00
fysx 405c79a8fe adjusted changelog 2014-01-30 10:32:38 +01:00
fysx cf30c31234 fixed markdown 2014-01-30 10:30:25 +01:00
629 changed files with 14658 additions and 27796 deletions
+57 -17
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="org.love2d.android"
android:versionCode="8"
android:versionName="0.9.0-alpha8"
android:versionCode="10"
android:versionName="0.9.0-beta2"
android:installLocation="auto" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
@@ -9,21 +9,61 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="Löve for Android"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<activity
android:name="GameActivity"
android:configChanges="orientation|screenSize"
android:label="Löve for Android"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="tv.ouya.intent.category.GAME"/>
</intent-filter>
</activity>
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="LÖVE for Android"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<service android:name=".DownloadService" />
<activity
android:name="GameActivity"
android:configChanges="orientation|screenSize"
android:label="LÖVE for Android"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="tv.ouya.intent.category.GAME"/>
</intent-filter>
</activity>
<activity
android:name="GameActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="application/x-love-game" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.love" />
<data android:host="*" />
</intent-filter>
</activity>
<activity
android:name="DownloadActivity"
android:noHistory="true" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="*"
android:pathPrefix="*"
android:mimeType="*/*"
android:pathPattern=".*\\.love" />
<data android:scheme="https"
android:host="*"
android:pathPrefix="*"
android:mimeType="*/*"
android:pathPattern=".*\\.love" />
</intent-filter>
</activity>
</application>
<!-- Android 2.3.3 -->
+40 -8
View File
@@ -1,9 +1,14 @@
Android Port of LÖVE, the awesome 2D game engine LÖVE (http://love2d.org)
Copyright (c) 2013 Martin Felis <martin@fysx.org>
Copyright (c) 2013-2014 Martin Felis <martin@fysx.org>
Instructions:
-------------
For detailed instructions please refer to the [wiki](wiki).
Quick Start:
------------
Install the Android NDK and the Android SDK with SDK API 12 and run
ndk-build
@@ -18,14 +23,40 @@ compile/run it using Eclipse.
This should give you a .apk file in the bin/ subdirectory that you can then
install on your phone.
Bugs:
-----
Bugs and feature requests should be reported to the [issue
tracker](issues).
Changelog:
----------
beta2:
* fixed bug with canvases
* fixed writing of files when no identity in conf.lua was set
* added file association (somewhat experimental)
beta1:
* fixed nasty crash on startup bug
* fixed love.filesystem.getDirectoryItems()
alpha9:
* Packaged games do not get duplicated for loading, instead are loaded from memory (!!!)
* Using inofficial physfs 2.1
* Removed love.android.getDisplayMetrics(), instead use love.window.getPixelScale()
* Properly link LGPL libraries dynamically. Everything else is linked statically
* Added an icon (design by @josefnpat)
* Fixed crash on startup on OUYA (and possibly other devices)
alpha8:
* Exposing DisplayMetrics in love.android.getDisplayMetrics())
* Accelerometer is now available as a joystick
* enabled armv6 compilation (larger files, better compatibility with Tegra2 devices)
* updated to latest mobile-common branch
* updated to latest mobile-common branch (including (very) basic multi-touch gesture tracking)
* updated OpenAL from 1.13 to 1.15.1
* updated jpeg library from 8c to 9a
* updated lcms from 2.2 to 2.5
@@ -34,16 +65,17 @@ alpha8:
* updated mpg123 from 1.13.4 to 1.17.0
alpha7:
* love.system.getOS() now returns "Android"
* hardware search key is reported as "search"
* switched to mobile-common branch
* using new love.touch module (love.touchpressed(id,x,y,p), love.touchmoved(id,x,y,p), love.touchmoved(id,x,y,p))
* added LOVE_ANDROID define
* love.system.getOS() now returns "Android"
* hardware search key is reported as "search"
* switched to mobile-common branch
* using new love.touch module (love.touchpressed(id,x,y,p), love.touchmoved(id,x,y,p), love.touchmoved(id,x,y,p))
* added LOVE_ANDROID define
License:
--------
This project contains code from various projects using various licenses.
This project contains code from multiple projects using various licenses.
Please look into the folders of jni/<projectname>/ for the respective
licenses.
+1 -1
View File
@@ -4,6 +4,6 @@
APP_STL := gnustl_shared
APP_ABI := armeabi armeabi-v7a
APP_CPPFLAGS := -frtti
APP_LDFLAGS := -llog -landroid -lz -lOpenSLES
APP_LDFLAGS := -llog -landroid -lz
# APP_OPTIM := debug
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -53,6 +53,6 @@ cd src
buildLuaJIT armeabi
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.0+ (ICS)
buildLuaJIT armeabi-v7a "-march=armv7-a -mfloat-abi=softfp -Wl,--fix-cortex-a8"
buildLuaJIT armeabi-v7a "-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -Wl,--fix-cortex-a8"
make clean
+2 -2
View File
@@ -48,7 +48,7 @@ LOCAL_SRC_FILES := \
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
include $(BUILD_SHARED_LIBRARY)
# include $(BUILD_SHARED_LIBRARY)
###########################
#
@@ -60,7 +60,7 @@ LOCAL_MODULE := SDL2_static
LOCAL_MODULE_FILENAME := libSDL2
LOCAL_SRC_FILES += $(LOCAL_PATH)/src/main/android/SDL_android_main.c
LOCAL_SRC_FILES += src/main/android/SDL_android_main.c
LOCAL_LDLIBS :=
LOCAL_EXPORT_LDLIBS := -Wl,--undefined=Java_org_libsdl_app_SDLActivity_nativeInit -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
+3 -1
View File
@@ -25,7 +25,9 @@ LOCAL_SRC_FILES := \
$(wildcard ${LOCAL_PATH}/src-IL/src/*.cpp) \
$(wildcard ${LOCAL_PATH}/src-IL/src/*.c) ))
LOCAL_SHARED_LIBRARIES := libtiff libpng libjasper libjpeg libmng liblcms
# $(info libdevil: include dirs $(LOCAL_C_INCLUDES))
# $(info libdevil: src files $(LOCAL_SRC_FILES))
include $(BUILD_STATIC_LIBRARY)
include $(BUILD_SHARED_LIBRARY)
+4 -6
View File
@@ -16,7 +16,6 @@ LOCAL_C_INCLUDES := \
${LOCAL_PATH}/src/libraries/ \
${LOCAL_PATH}/src/libraries/enet/libenet/include \
${LOCAL_PATH}/../SDL2-2.0.1/include \
${LOCAL_PATH}/../SDL2-2.0.1/src \
${LOCAL_PATH}/../devil-1.7.8/include \
${LOCAL_PATH}/../devil-1.7.8/src-IL/include \
${LOCAL_PATH}/../jasper-1.900.1/src/libjasper/include \
@@ -29,7 +28,7 @@ LOCAL_C_INCLUDES := \
${LOCAL_PATH}/../openal-soft-android/OpenAL32/Include \
${LOCAL_PATH}/../freetype2-android/include \
${LOCAL_PATH}/../freetype2-android/src \
${LOCAL_PATH}/../physfs-2.0.3 \
${LOCAL_PATH}/../physfs-2.1.0/src \
${LOCAL_PATH}/../mpg123-1.17.0/src/libmpg123 \
${LOCAL_PATH}/../libmodplug-0.8.8.4/src \
${LOCAL_PATH}/../libvorbis-1.3.4/include \
@@ -43,8 +42,7 @@ LOCAL_SRC_FILES := \
,$(subst $(LOCAL_PATH)/,,\
$(wildcard ${LOCAL_PATH}/src/love.cpp) \
$(wildcard ${LOCAL_PATH}/src/common/*.cpp) \
$(wildcard ${LOCAL_PATH}/src/modules/android/*.cpp) \
$(wildcard ${LOCAL_PATH}/src/modules/audio/*.cpp) \
$(wildcard ${LOCAL_PATH}/src/modules/audio/*.cpp) \
$(wildcard ${LOCAL_PATH}/src/modules/audio/null/*.cpp) \
$(wildcard ${LOCAL_PATH}/src/modules/audio/openal/*.cpp) \
$(wildcard ${LOCAL_PATH}/src/modules/event/*.cpp) \
@@ -99,9 +97,9 @@ LOCAL_SRC_FILES := \
LOCAL_CXXFLAGS := -std=c++0x
LOCAL_SHARED_LIBRARIES := SDL2 libphysfs libvorbis libogg libopenal libmpg123 libmodplug libdevil libtiff libmng libfreetype liblcms libjasper libpng libjpeg
LOCAL_SHARED_LIBRARIES := libphysfs libvorbis libogg libopenal libmpg123 libmodplug libdevil libtiff libmng libfreetype liblcms libjasper libpng libjpeg
LOCAL_STATIC_LIBRARIES := libluajit
LOCAL_STATIC_LIBRARIES := libluajit SDL2_static
# $(info liblove: include dirs $(LOCAL_C_INCLUDES))
# $(info liblove: src files $(LOCAL_SRC_FILES))
+82
View File
@@ -0,0 +1,82 @@
/**
* Copyright (c) 2006-2014 LOVE Development Team
*
* 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 "android.h"
#ifdef LOVE_ANDROID
#include "SDL.h"
#include "jni.h"
namespace love
{
namespace android
{
double getScreenScale()
{
static double result = -1.;
if (result == -1.) {
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
jclass activity = env->FindClass("org/love2d/android/GameActivity");
jmethodID getMetrics = env->GetStaticMethodID(activity, "getMetrics", "()Landroid/util/DisplayMetrics;");
jobject metrics = env->CallStaticObjectMethod(activity, getMetrics);
jclass metricsClass = env->GetObjectClass(metrics);
result = env->GetFloatField(metrics, env->GetFieldID(metricsClass, "density", "F"));
env->DeleteLocalRef (metricsClass);
env->DeleteLocalRef (metrics);
env->DeleteLocalRef (activity);
}
return result;
}
const char* getSelectedGameFile()
{
static const char *path = NULL;
if (!path) {
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
jclass activity = env->FindClass("org/love2d/android/GameActivity");
jmethodID getGamePath = env->GetStaticMethodID(activity, "getGamePath", "()Ljava/lang/String;");
jstring gamePath = (jstring) env->CallStaticObjectMethod(activity, getGamePath);
const char *utf = env->GetStringUTFChars(gamePath, 0);
if (utf)
{
path = SDL_strdup(utf);
env->ReleaseStringUTFChars(gamePath, utf);
}
env->DeleteLocalRef (gamePath);
env->DeleteLocalRef (activity);
}
return path;
}
} // android
} // love
#endif // LOVE_ANDROID
@@ -18,23 +18,31 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_ANDROID_WRAP_ANDROID_H
#define LOVE_ANDROID_WRAP_ANDROID_H
#ifndef LOVE_ANDROID_H
#define LOVE_ANDROID_H
// LOVE
#include "common/config.h"
#include "common/runtime.h"
#include "Android.h"
#include "config.h"
#ifdef LOVE_ANDROID
namespace love
{
namespace android
{
int w_getDisplayMetrics(lua_State *L);
extern "C" LOVE_EXPORT int luaopen_love_android(lua_State *L);
/**
* Gets the scale factor of the window's screen, e.g. on Retina displays this
* will return 2.0.
**/
double getScreenScale();
/**
* Gets the selected love file in the device filesystem.
**/
const char* getSelectedGameFile();
} // android
} // love
#endif // LOVE_ANDROID_WRAP_ANDROID_H
#endif // LOVE_ANDROID
#endif // LOVE_ANDROID_H
-1
View File
@@ -90,7 +90,6 @@
# define LOVE_LITTLE_ENDIAN 1
# endif
#else
# define LOVE_ENABLE_ANDROID
# define LOVE_ENABLE_AUDIO
# define LOVE_ENABLE_AUDIO_NULL
# define LOVE_ENABLE_AUDIO_OPENAL
-6
View File
@@ -35,9 +35,6 @@ enum Type
DATA_ID,
MODULE_ID,
// Android
ANDROID_DISPLAY_METRICS_ID,
// Filesystem.
FILESYSTEM_FILE_ID,
FILESYSTEM_FILE_DATA_ID,
@@ -124,9 +121,6 @@ const bits OBJECT_T = bits(1) << OBJECT_ID;
const bits DATA_T = (bits(1) << DATA_ID) | OBJECT_T;
const bits MODULE_T = (bits(1) << MODULE_ID) | OBJECT_T;
// Android
const bits ANDROID_DISPLAY_METRICS_T = (bits(1) << ANDROID_DISPLAY_METRICS_ID) | OBJECT_T;
// Filesystem.
const bits FILESYSTEM_FILE_T = (bits(1) << FILESYSTEM_FILE_ID) | OBJECT_T;
const bits FILESYSTEM_FILE_DATA_T = (bits(1) << FILESYSTEM_FILE_DATA_ID) | DATA_T;
@@ -1,3 +1,6 @@
#ifndef LUA_WRAP_H
#define LUA_WRAP_H
#define LUA_COMPAT_ALL
#include <lua.h>
#include <lualib.h>
@@ -10,3 +13,5 @@
extern int luax_typerror(lua_State *L, int narg, const char *type);
#endif
#endif // LUA_WRAP_H
-43
View File
@@ -1,43 +0,0 @@
/**
* Copyright (c) 2006-2014 LOVE Development Team
*
* 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 "Android.h"
namespace love
{
namespace android
{
DisplayMetrics* Android::getDisplayMetrics()
{
if (metrics == NULL)
{
metrics = new DisplayMetrics();
}
return metrics;
}
const char *Android::getName() const
{
return "love.android";
}
} // android
} // love
-63
View File
@@ -1,63 +0,0 @@
/**
* Copyright (c) 2006-2014 LOVE Development Team
*
* 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 LOVE_ANDROID_ANDROID_H
#define LOVE_ANDROID_ANDROID_H
// LOVE
#include "common/Module.h"
#include "DisplayMetrics.h"
namespace love
{
namespace android
{
/**
* The Android module provide access to some device features, like display metrics and camera.
**/
class Android : public Module
{
public:
/**
* Destructor.
**/
virtual ~Android() {}
/**
* Gets display metrics that describe the size and density of this display.
* @return A DisplayMetrics object containing the metrics.
**/
DisplayMetrics* getDisplayMetrics();
// Implements Module.
virtual const char *getName() const;
private:
DisplayMetrics *metrics;
}; // Android
} // android
} // love
#endif // LOVE_ANDROID_ANDROID_H
@@ -1,88 +0,0 @@
/**
* Copyright (c) 2006-2014 LOVE Development Team
*
* 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 "DisplayMetrics.h"
#include "core/android/SDL_android.h"
namespace love
{
namespace android
{
DisplayMetrics::DisplayMetrics()
{
JNIEnv *env = Android_JNI_GetEnv();
jclass activity = env->FindClass("org/love2d/android/GameActivity");
jmethodID getMetrics = env->GetStaticMethodID(activity, "getMetrics", "()Landroid/util/DisplayMetrics;");
jobject metrics = env->CallStaticObjectMethod(activity, getMetrics);
jclass metricsClass = env->GetObjectClass(metrics);
// Density
density = env->GetFloatField(metrics, env->GetFieldID(metricsClass, "density", "F"));
scaledDensity = env->GetFloatField(metrics, env->GetFieldID(metricsClass, "scaledDensity", "F"));
densityDpi = env->GetIntField(metrics, env->GetFieldID(metricsClass, "densityDpi", "I"));
// Size
widthPixels = env->GetIntField(metrics, env->GetFieldID(metricsClass, "widthPixels", "I"));
heightPixels = env->GetIntField(metrics, env->GetFieldID(metricsClass, "heightPixels", "I"));
// DPI
xdpi = env->GetFloatField(metrics, env->GetFieldID(metricsClass, "xdpi", "F"));
ydpi = env->GetFloatField(metrics, env->GetFieldID(metricsClass, "ydpi", "F"));
}
float DisplayMetrics::getDensity()
{
return density;
}
float DisplayMetrics::getScaledDensity()
{
return scaledDensity;
}
int DisplayMetrics::getDensityDpi()
{
return densityDpi;
}
int DisplayMetrics::getWidthPixels()
{
return widthPixels;
}
int DisplayMetrics::getHeightPixels()
{
return heightPixels;
}
float DisplayMetrics::getXdpi()
{
return xdpi;
}
float DisplayMetrics::getYdpi()
{
return ydpi;
}
} // android
} // love
@@ -1,98 +0,0 @@
/**
* Copyright (c) 2006-2014 LOVE Development Team
*
* 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 LOVE_ANDROID_DISPLAY_METRICS_H
#define LOVE_ANDROID_DISPLAY_METRICS_H
// LOVE
#include "common/Object.h"
namespace love
{
namespace android
{
/**
* A DisplayMetrics describe a general information about a display, such as its size, density, and font scaling.
**/
class DisplayMetrics : public Object
{
public:
/**
* Constructor.
**/
DisplayMetrics();
/**
* Destructor.
**/
virtual ~DisplayMetrics() {}
/**
* The logical density of the display.
**/
float getDensity();
/**
* A scaling factor for fonts displayed on the display.
**/
float getScaledDensity();
/**
* The screen density expressed as dots-per-inch.
**/
int getDensityDpi();
/**
* The absolute width of the display in pixels.
**/
int getWidthPixels();
/**
* The absolute height of the display in pixels.
**/
int getHeightPixels();
/**
* The exact physical pixels per inch of the screen in the X dimension.
**/
float getXdpi();
/**
* The exact physical pixels per inch of the screen in the X dimension.
**/
float getYdpi();
private:
float density;
float scaledDensity;
int densityDpi;
int widthPixels;
int heightPixels;
float xdpi;
float ydpi;
}; // DisplayMetrics
} // android
} // love
#endif // LOVE_ANDROID_DISPLAY_METRICS_H
@@ -1,75 +0,0 @@
/**
* Copyright (c) 2006-2014 LOVE Development Team
*
* 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 "wrap_Android.h"
#include "wrap_DisplayMetrics.h"
namespace love
{
namespace android
{
static Android *instance = nullptr;
int w_getDisplayMetrics(lua_State *L)
{
DisplayMetrics *metrics = 0;
EXCEPT_GUARD(metrics = instance->getDisplayMetrics();)
luax_pushtype(L, "DisplayMetrics", ANDROID_DISPLAY_METRICS_T, metrics);
return 1;
}
// List of functions to wrap.
static const luaL_Reg functions[] =
{
{ "getDisplayMetrics", w_getDisplayMetrics },
{ 0, 0 }
};
// Types for this module.
static const lua_CFunction types[] =
{
luaopen_displaymetrics,
0
};
extern "C" int luaopen_love_android(lua_State *L)
{
if (instance == 0)
{
EXCEPT_GUARD(instance = new Android();)
}
else
instance->retain();
WrappedModule w;
w.module = instance;
w.name = "android";
w.flags = MODULE_T;
w.functions = functions;
w.types = types;
int n = luax_register_module(L, w);
return n;
}
} // android
} // love
@@ -1,100 +0,0 @@
/**
* Copyright (c) 2006-2014 LOVE Development Team
*
* 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 "wrap_DisplayMetrics.h"
namespace love
{
namespace android
{
DisplayMetrics *luax_checkdisplaymetrics(lua_State *L, int idx)
{
return luax_checktype<DisplayMetrics>(L, idx, "DisplayMetrics", ANDROID_DISPLAY_METRICS_T);
}
int w_getDensity(lua_State *L)
{
DisplayMetrics *metrics = luax_checkdisplaymetrics(L, 1);
lua_pushnumber(L, metrics->getDensity());
return 1;
}
int w_getScaledDensity(lua_State *L)
{
DisplayMetrics *metrics = luax_checkdisplaymetrics(L, 1);
lua_pushnumber(L, metrics->getScaledDensity());
return 1;
}
int w_getDensityDpi(lua_State *L)
{
DisplayMetrics *metrics = luax_checkdisplaymetrics(L, 1);
lua_pushnumber(L, metrics->getDensityDpi());
return 1;
}
int w_getWidthPixels(lua_State *L)
{
DisplayMetrics *metrics = luax_checkdisplaymetrics(L, 1);
lua_pushnumber(L, metrics->getWidthPixels());
return 1;
}
int w_getHeightPixels(lua_State *L)
{
DisplayMetrics *metrics = luax_checkdisplaymetrics(L, 1);
lua_pushnumber(L, metrics->getHeightPixels());
return 1;
}
int w_getXdpi(lua_State *L)
{
DisplayMetrics *metrics = luax_checkdisplaymetrics(L, 1);
lua_pushnumber(L, metrics->getXdpi());
return 1;
}
int w_getYdpi(lua_State *L)
{
DisplayMetrics *metrics = luax_checkdisplaymetrics(L, 1);
lua_pushnumber(L, metrics->getYdpi());
return 1;
}
static const luaL_Reg functions[] =
{
{ "getDensity", w_getDensity },
{ "getScaledDensity", w_getScaledDensity },
{ "getDensityDpi", w_getDensityDpi },
{ "getWidthPixels", w_getWidthPixels },
{ "getHeightPixels", w_getHeightPixels },
{ "getXdpi", w_getXdpi },
{ "getYdpi", w_getYdpi },
{ 0, 0 },
};
extern "C" int luaopen_displaymetrics(lua_State *L)
{
return luax_register_type(L, "DisplayMetrics", functions);
}
} // android
} // love
@@ -1,45 +0,0 @@
/**
* Copyright (c) 2006-2014 LOVE Development Team
*
* 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 LOVE_ANDROID_WRAP_DISPLAY_METRICS_H
#define LOVE_ANDROID_WRAP_DISPLAY_METRICS_H
#include "common/runtime.h"
#include "DisplayMetrics.h"
namespace love
{
namespace android
{
DisplayMetrics *luax_checkdisplaymetrics(lua_State *L, int idx);
int w_getDensity(lua_State *L);
int w_getScaledDensity(lua_State *L);
int w_getDensityDpi(lua_State *L);
int w_getWidthPixels(lua_State *L);
int w_getHeightPixels(lua_State *L);
int w_getXdpi(lua_State *L);
int w_getYdpi(lua_State *L);
extern "C" int luaopen_displaymetrics(lua_State *L);
} // android
} // love
#endif // LOVE_ANDROID_WRAP_DISPLAY_METRICS_H
@@ -61,11 +61,13 @@ Pool::Pool()
// Make all sources available initially.
for (int i = 0; i < totalSources; i++)
{
#ifdef AL_SOFT_direct_channels
if (hasext)
{
// Bypass virtualization of speakers for multi-channel sources in OpenAL Soft.
alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
}
#endif
available.push(sources[i]);
}
+2 -1
View File
@@ -42,6 +42,7 @@ namespace sdl
// we want them in pixel coordinates (may be different with high-DPI enabled.)
static void windowToPixelCoords(int *x, int *y)
{
#ifndef LOVE_ANDROID
double scale = 1.0;
window::Window *window = (window::Window *) Module::findInstance("love.window.");
@@ -53,6 +54,7 @@ static void windowToPixelCoords(int *x, int *y)
if (y != nullptr)
*y = int(double(*y) * scale);
#endif
}
@@ -129,7 +131,6 @@ Message *Event::convert(const SDL_Event &e) const
switch (e.type)
{
case SDL_KEYDOWN:
SDL_Log ("got keydown for key %d search %d equal = %d", e.key.keysym.sym, SDLK_AC_SEARCH, e.key.keysym.sym == SDLK_AC_SEARCH);
if (e.key.repeat)
{
kb = (love::keyboard::Keyboard *) Module::findInstance("love.keyboard.");
@@ -35,6 +35,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include "common/android.h"
#endif
namespace
@@ -59,6 +60,63 @@ namespace
}
#ifdef LOVE_ANDROID
void androidDeleteAssetGameMemory (void *ptr) {
SDL_Log ("freeing memory for in-memory game.love");
char *game_love_data = static_cast<char*>(ptr);
delete[] game_love_data;
}
bool androidMountGame (const char *filename) {
SDL_Log ("Trying to mount %s", filename);
SDL_RWops *asset_game_file = SDL_RWFromFile(filename, "rb");
if (!asset_game_file) {
SDL_Log ("Could not find %s", filename);
return false;
}
Sint64 file_size = asset_game_file->size(asset_game_file);
if (file_size == 0) {
SDL_Log ("Could not find valid %s. File has zero size.", filename);
return false;
}
char *game_love_data = new char[file_size];
if (!game_love_data) {
SDL_Log ("Could not allocate memory for in-memory game archive");
return false;
}
size_t bytes_copied = asset_game_file->read(asset_game_file, game_love_data, sizeof(char), (size_t) file_size);
if (bytes_copied != file_size) {
SDL_Log ("Only copied %d of %d bytes into in-memory game archive!", bytes_copied, file_size);
delete[] game_love_data;
return false;
}
SDL_Log ("Copied %d of %d bytes into in-memory game archive", bytes_copied, file_size);
bool result = false;
if (PHYSFS_mountMemory (game_love_data, file_size, androidDeleteAssetGameMemory, "archive.zip", "/", 0)) {
result = true;
SDL_Log ("Mounting of in-memory game archive successful!");
} else {
SDL_Log ("Mounting of in-memory game archive failed!");
}
return result;
}
bool androidMountAssetGame () {
return androidMountGame ("game.love");
}
bool androidMountSelectedGame () {
return androidMountGame (love::android::getSelectedGameFile());
}
bool androidDirectoryExists(const char* path) {
SDL_Log ("Checking directory exists for %s", path);
struct stat s;
@@ -106,69 +164,6 @@ namespace
return true;
}
bool androidCopyGameFromAssets () {
SDL_RWops *asset_game_file = SDL_RWFromFile("game.love", "rb");
if (!asset_game_file) {
SDL_Log ("Could not find game.love in assets.");
return false;
}
Sint64 file_size = asset_game_file->size(asset_game_file);
if (file_size == 0) {
SDL_Log ("Could not find valid game.love in assets. File has zero size.", (int) file_size);
return false;
}
SDL_Log ("Found game.love in assets. Size: %d", (int) file_size);
std::string internal_storage_path = SDL_AndroidGetInternalStoragePath();
std::string internal_game_file = internal_storage_path + "/game/game.love";
SDL_RWops *storage_game_file = SDL_RWFromFile (internal_game_file.c_str(), "wb");
if (!storage_game_file) {
SDL_Log ("Error creating internal storage game file: %s", SDL_GetError());
asset_game_file->close(asset_game_file);
return false;
}
size_t buff_size = 128 * 1024;
char *data_buffer = new char[buff_size];
if (!data_buffer) {
SDL_Log ("Error allocating memory for file copy buffer!");
asset_game_file->close(asset_game_file);
storage_game_file->close(storage_game_file);
return false;
}
size_t bytes_copied = 0;
while (bytes_copied != (size_t) file_size) {
size_t bytes_read = asset_game_file->read(asset_game_file, data_buffer, sizeof(char), (size_t) buff_size);
size_t bytes_written = storage_game_file->write(storage_game_file, data_buffer, sizeof(char), bytes_read);
bytes_copied += bytes_written;
SDL_Log ("Copied %d of %d bytes", bytes_copied, file_size);
if (bytes_written != bytes_read) {
SDL_Log ("Error copying asset game to internal storage: %s", SDL_GetError());
asset_game_file->close(asset_game_file);
storage_game_file->close(storage_game_file);
return false;
}
}
delete[] data_buffer;
data_buffer = NULL;
asset_game_file->close(asset_game_file);
storage_game_file->close(storage_game_file);
SDL_Log ("Copying of asset game to internal storage %s successful!", internal_game_file.c_str());
return true;
}
#endif
}
@@ -201,6 +196,11 @@ void Filesystem::init(const char *arg0)
{
if (!PHYSFS_init(arg0))
throw Exception(PHYSFS_getLastError());
#ifdef LOVE_ANDROID
PHYSFS_permitSymbolicLinks (1);
#endif
initialized = true;
}
@@ -240,19 +240,20 @@ bool Filesystem::setIdentity(const char *ident, bool appendToPath)
save_path_full += save_path_relative;
#ifdef LOVE_ANDROID
std::string internal_storage_path = SDL_AndroidGetInternalStoragePath();
if (save_identity == "")
save_identity = "unnamed";
std::string internal_storage_path = SDL_AndroidGetInternalStoragePath();
std::string save_directory = internal_storage_path + "/save";
std::string save_directory = internal_storage_path + "/save";
save_path_full = std::string(SDL_AndroidGetInternalStoragePath()) + std::string("/save/") + save_identity;
if (androidDirectoryExists (save_path_full.c_str())) {
SDL_Log ("dir exists");
} else {
SDL_Log ("does not exist");
}
if (androidDirectoryExists (save_path_full.c_str())) {
SDL_Log ("dir exists");
} else {
SDL_Log ("does not exist");
}
if (!androidDirectoryExists (save_path_full.c_str())) {
if (!androidMkdir (save_path_full.c_str())) {
@@ -302,24 +303,31 @@ bool Filesystem::setSource(const char *source)
SDL_Log ("Error creating storage directories!");
}
if (androidCopyGameFromAssets())
new_search_path = std::string(SDL_AndroidGetInternalStoragePath()) + std::string("/game/game.love");
else {
SDL_RWops *sdcard_main = SDL_RWFromFile("/sdcard/lovegame/main.lua", "rb");
if (!androidMountSelectedGame() && !androidMountAssetGame()) {
SDL_RWops *sdcard_main = SDL_RWFromFile("/sdcard/lovegame/main.lua", "rb");
if (sdcard_main) {
SDL_Log ("using game from /sdcard/lovegame");
new_search_path = "/sdcard/lovegame";
sdcard_main->close(sdcard_main);
}
if (sdcard_main) {
SDL_Log ("using game from /sdcard/lovegame");
new_search_path = "/sdcard/lovegame";
sdcard_main->close(sdcard_main);
if (!PHYSFS_addToSearchPath(new_search_path.c_str(), 1)) {
SDL_Log ("mounting of %s failed", new_search_path.c_str());
return false;
}
} else {
// Neither assets/game.love or /sdcard/lovegame was mounted
// sucessfully, therefore simply fail.
return false;
}
}
#endif
#else
// Add the directory.
if (!PHYSFS_addToSearchPath(new_search_path.c_str(), 1)) {
SDL_Log ("mounting of %s failed", new_search_path.c_str());
return false;
}
#endif
// Save the game source.
game_source = new_search_path;
@@ -176,6 +176,7 @@ StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM>::Entry Graphics::suppor
{ "dxt", Graphics::SUPPORT_DXT },
{ "bc5", Graphics::SUPPORT_BC5 },
{ "instancing", Graphics::SUPPORT_INSTANCING },
{ "srgb", Graphics::SUPPORT_SRGB },
};
StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM> Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries));
+2 -1
View File
@@ -95,6 +95,7 @@ public:
SUPPORT_DXT,
SUPPORT_BC5,
SUPPORT_INSTANCING,
SUPPORT_SRGB,
SUPPORT_MAX_ENUM
};
@@ -135,7 +136,7 @@ public:
* @param width The viewport width.
* @param height The viewport height.
**/
virtual bool setMode(int width, int height) = 0;
virtual bool setMode(int width, int height, bool &sRGB) = 0;
/**
* Un-sets the current graphics display mode (uninitializing objects if
+19
View File
@@ -109,6 +109,16 @@ bool Texture::getConstant(WrapMode in, const char *&out)
return wrapModes.find(in, out);
}
bool Texture::getConstant(const char *in, Format &out)
{
return formats.find(in, out);
}
bool Texture::getConstant(Format in, const char *&out)
{
return formats.find(in, out);
}
StringMap<Texture::FilterMode, Texture::FILTER_MAX_ENUM>::Entry Texture::filterModeEntries[] =
{
{ "linear", Texture::FILTER_LINEAR },
@@ -125,6 +135,15 @@ StringMap<Texture::WrapMode, Texture::WRAP_MAX_ENUM>::Entry Texture::wrapModeEnt
StringMap<Texture::WrapMode, Texture::WRAP_MAX_ENUM> Texture::wrapModes(Texture::wrapModeEntries, sizeof(Texture::wrapModeEntries));
StringMap<Texture::Format, Texture::FORMAT_MAX_ENUM>::Entry Texture::formatEntries[] =
{
{"normal", Texture::FORMAT_NORMAL},
{"hdr", Texture::FORMAT_HDR},
{"srgb", Texture::FORMAT_SRGB},
};
StringMap<Texture::Format, Texture::FORMAT_MAX_ENUM> Texture::formats(Texture::formatEntries, sizeof(Texture::formatEntries));
} // graphics
} // love
+14
View File
@@ -55,6 +55,14 @@ public:
FILTER_MAX_ENUM
};
enum Format
{
FORMAT_NORMAL,
FORMAT_HDR,
FORMAT_SRGB,
FORMAT_MAX_ENUM
};
struct Filter
{
Filter();
@@ -111,6 +119,9 @@ public:
static bool getConstant(const char *in, WrapMode &out);
static bool getConstant(WrapMode in, const char *&out);
static bool getConstant(const char *in, Format &out);
static bool getConstant(Format in, const char *&out);
protected:
int width;
@@ -132,6 +143,9 @@ private:
static StringMap<WrapMode, WRAP_MAX_ENUM>::Entry wrapModeEntries[];
static StringMap<WrapMode, WRAP_MAX_ENUM> wrapModes;
static StringMap<Format, FORMAT_MAX_ENUM>::Entry formatEntries[];
static StringMap<Format, FORMAT_MAX_ENUM> formats;
}; // Texture
} // graphics
+63 -44
View File
@@ -389,7 +389,7 @@ struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
}
};
FramebufferStrategy *strategy = NULL;
FramebufferStrategy *strategy = nullptr;
FramebufferStrategy strategyNone;
@@ -401,8 +401,9 @@ FramebufferStrategyPackedEXT strategyPackedEXT;
FramebufferStrategyEXT strategyEXT;
Canvas *Canvas::current = NULL;
Canvas *Canvas::current = nullptr;
OpenGL::Viewport Canvas::systemViewport = OpenGL::Viewport();
bool Canvas::screenHasSRGB = false;
static void getStrategy()
{
@@ -421,16 +422,13 @@ static void getStrategy()
}
}
static int maxFBOColorAttachments = 0;
static int maxDrawBuffers = 0;
Canvas::Canvas(int width, int height, TextureType texture_type, int fsaa)
Canvas::Canvas(int width, int height, Texture::Format format, int fsaa)
: fbo(0)
, resolve_fbo(0)
, texture(0)
, fsaa_buffer(0)
, depth_stencil(0)
, texture_type(texture_type)
, format(format)
, fsaa_samples(fsaa)
, fsaa_dirty(false)
{
@@ -534,15 +532,19 @@ bool Canvas::loadVolatile()
GLint internalformat;
GLenum textype;
switch (texture_type)
switch (format)
{
case TYPE_HDR:
case Texture::FORMAT_HDR:
internalformat = GL_RGBA16F;
textype = GL_FLOAT;
break;
case TYPE_NORMAL:
case Texture::FORMAT_SRGB:
internalformat = GL_SRGB_ALPHA;
textype = GL_UNSIGNED_BYTE;
break;
case Texture::FORMAT_NORMAL:
default:
internalformat = GL_RGBA8;
internalformat = GL_RGBA;
textype = GL_UNSIGNED_BYTE;
}
@@ -682,20 +684,30 @@ void Canvas::setupGrab()
if (current == this)
return;
// cleanup after previous fbo
if (current != NULL)
current->stopGrab();
// cleanup after previous Canvas
if (current != nullptr)
{
systemViewport = current->systemViewport;
current->stopGrab(true);
}
else
systemViewport = gl.getViewport();
// indicate we are using this Canvas.
current = this;
// bind the framebuffer object.
systemViewport = gl.getViewport();
strategy->bindFBO(fbo);
gl.setViewport(OpenGL::Viewport(0, 0, width, height));
// Set up orthographic view (no depth)
gl.matrices.projection.push(Matrix::ortho(0.0, width, 0.0, height));
// indicate we are using this fbo
current = this;
// Make sure the correct sRGB setting is used when drawing to the canvas.
if (format == FORMAT_SRGB)
glEnable(GL_FRAMEBUFFER_SRGB);
else if (screenHasSRGB)
glDisable(GL_FRAMEBUFFER_SRGB);
if (fsaa_buffer != 0)
fsaa_dirty = true;
@@ -712,7 +724,7 @@ void Canvas::startGrab(const std::vector<Canvas *> &canvases)
if (!isMultiCanvasSupported())
throw love::Exception("Multi-canvas rendering is not supported on this system.");
if (canvases.size()+1 > size_t(maxDrawBuffers) || canvases.size()+1 > size_t(maxFBOColorAttachments))
if ((int) canvases.size() + 1 > gl.getMaxRenderTargets())
throw love::Exception("This system can't simultaniously render to %d canvases.", canvases.size()+1);
if (fsaa_samples != 0)
@@ -724,8 +736,8 @@ void Canvas::startGrab(const std::vector<Canvas *> &canvases)
if (canvases[i]->getWidth() != width || canvases[i]->getHeight() != height)
throw love::Exception("All canvas arguments must have the same dimensions.");
if (canvases[i]->getTextureType() != texture_type)
throw love::Exception("All canvas arguments must have the same texture type.");
if (canvases[i]->getTextureFormat() != format)
throw love::Exception("All canvas arguments must have the same texture format.");
if (canvases[i]->getFSAA() != 0)
throw love::Exception("Multi-canvas rendering is not supported with FSAA.");
@@ -769,7 +781,7 @@ void Canvas::startGrab()
attachedCanvases.clear();
}
void Canvas::stopGrab()
void Canvas::stopGrab(bool switchingToOtherCanvas)
{
// i am not grabbing. leave me alone
if (current != this)
@@ -782,13 +794,25 @@ void Canvas::stopGrab()
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 2, attachments);
}
// bind default
strategy->bindFBO(gl.getDefaultFBO());
if (switchingToOtherCanvas)
{
if (format == FORMAT_SRGB)
glDisable(GL_FRAMEBUFFER_SRGB);
}
else
{
// bind the default framebuffer.
strategy->bindFBO(gl.getDefaultFBO());
current = nullptr;
gl.setViewport(systemViewport);
if (format == FORMAT_SRGB && !screenHasSRGB)
glDisable(GL_FRAMEBUFFER_SRGB);
else if (format != FORMAT_SRGB && screenHasSRGB)
glEnable(GL_FRAMEBUFFER_SRGB);
}
gl.matrices.projection.pop();
current = nullptr;
gl.setViewport(systemViewport);
}
void Canvas::clear(Color c)
@@ -959,6 +983,18 @@ bool Canvas::isHDRSupported()
return GLAD_VERSION_3_0 || (isSupported() && GLAD_ARB_texture_float);
}
bool Canvas::isSRGBSupported()
{
if (GLAD_VERSION_3_0)
return true;
if (!isSupported())
return false;
return (GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB)
&& GLAD_EXT_texture_sRGB;
}
bool Canvas::isMultiCanvasSupported()
{
// system must support at least 4 simultanious active canvases.
@@ -971,23 +1007,6 @@ void Canvas::bindDefaultCanvas()
current->stopGrab();
}
bool Canvas::getConstant(const char *in, Canvas::TextureType &out)
{
return textureTypes.find(in, out);
}
bool Canvas::getConstant(Canvas::TextureType in, const char *&out)
{
return textureTypes.find(in, out);
}
StringMap<Canvas::TextureType, Canvas::TYPE_MAX_ENUM>::Entry Canvas::textureTypeEntries[] =
{
{"normal", Canvas::TYPE_NORMAL},
{"hdr", Canvas::TYPE_HDR},
};
StringMap<Canvas::TextureType, Canvas::TYPE_MAX_ENUM> Canvas::textureTypes(Canvas::textureTypeEntries, sizeof(Canvas::textureTypeEntries));
} // opengl
} // graphics
} // love
+10 -18
View File
@@ -39,14 +39,7 @@ class Canvas : public Texture
{
public:
enum TextureType
{
TYPE_NORMAL,
TYPE_HDR,
TYPE_MAX_ENUM
};
Canvas(int width, int height, TextureType texture_type = TYPE_NORMAL, int fsaa = 0);
Canvas(int width, int height, Texture::Format format = Texture::FORMAT_NORMAL, int fsaa = 0);
virtual ~Canvas();
// Implements Volatile.
@@ -69,7 +62,7 @@ public:
**/
void startGrab(const std::vector<Canvas *> &canvases);
void startGrab();
void stopGrab();
void stopGrab(bool switchingToOtherCanvas = false);
void clear(Color c);
@@ -92,9 +85,9 @@ public:
return status;
}
inline TextureType getTextureType() const
inline Texture::Format getTextureFormat() const
{
return texture_type;
return format;
}
inline int getFSAA() const
@@ -106,17 +99,18 @@ public:
static bool isSupported();
static bool isHDRSupported();
static bool isSRGBSupported();
static bool isMultiCanvasSupported();
static bool getConstant(const char *in, TextureType &out);
static bool getConstant(TextureType in, const char *&out);
static Canvas *current;
static void bindDefaultCanvas();
// The viewport dimensions of the system (default) framebuffer.
static OpenGL::Viewport systemViewport;
// Whether the main screen should have linear -> sRGB conversions enabled.
static bool screenHasSRGB;
private:
bool createFSAAFBO(GLenum internalformat);
@@ -128,7 +122,7 @@ private:
GLuint fsaa_buffer;
GLuint depth_stencil;
TextureType texture_type;
Format format;
GLenum status;
@@ -140,9 +134,7 @@ private:
void setupGrab();
void drawv(const Matrix &t, const Vertex *v);
static StringMap<TextureType, TYPE_MAX_ENUM>::Entry textureTypeEntries[];
static StringMap<TextureType, TYPE_MAX_ENUM> textureTypes;
};
}; // Canvas
} // opengl
} // graphics
@@ -56,8 +56,13 @@ Graphics::Graphics()
{
currentWindow = love::window::sdl::Window::createSingleton();
int w, h;
love::window::WindowSettings wsettings;
currentWindow->getWindow(w, h, wsettings);
if (currentWindow->isCreated())
setMode(currentWindow->getWidth(), currentWindow->getHeight());
setMode(w, h, wsettings.sRGB);
}
Graphics::~Graphics()
@@ -104,6 +109,8 @@ DisplayState Graphics::saveState()
for (int i = 0; i < 4; i++)
s.colorMask[i] = colorMask[i];
wireframe = isWireframe();
return s;
}
@@ -121,6 +128,7 @@ void Graphics::restoreState(const DisplayState &s)
else
setScissor();
setColorMask(s.colorMask[0], s.colorMask[1], s.colorMask[2], s.colorMask[3]);
setWireframe(s.wireframe);
}
void Graphics::setViewportSize(int width, int height)
@@ -151,7 +159,7 @@ void Graphics::setViewportSize(int width, int height)
c->startGrab(c->getAttachedCanvases());
}
bool Graphics::setMode(int width, int height)
bool Graphics::setMode(int width, int height, bool &sRGB)
{
this->width = width;
this->height = height;
@@ -181,9 +189,6 @@ bool Graphics::setMode(int width, int height)
// Enable blending
glEnable(GL_BLEND);
// "Normal" blending
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Enable all color component writes.
setColorMask(true, true, true, true);
@@ -228,6 +233,19 @@ bool Graphics::setMode(int width, int height)
Shader::defaultShader->attach();
}
// Set whether drawing converts input from linear -> sRGB colorspace.
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB)
{
if (sRGB)
glEnable(GL_FRAMEBUFFER_SRGB);
else
glDisable(GL_FRAMEBUFFER_SRGB);
}
else
sRGB = false;
Canvas::screenHasSRGB = sRGB;
bool enabledebug = false;
if (GLAD_VERSION_3_0)
@@ -238,7 +256,10 @@ bool Graphics::setMode(int width, int height)
enabledebug = (flags & GL_CONTEXT_FLAG_DEBUG_BIT) != 0;
}
setDebug(enabledebug);
// FIXME: workaround for KHR_debug being supported but function pointers
// resolving to null on Ouya.
if (!GLAD_ES_VERSION_2_0)
setDebug(enabledebug);
return true;
}
@@ -312,6 +333,9 @@ void Graphics::setDebug(bool enable)
glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, 0, GL_FALSE);
glDebugMessageControl(GL_DEBUG_SOURCE_SHADER_COMPILER, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, 0, GL_FALSE);
if (GLAD_VERSION_4_3 || GLAD_KHR_debug)
glEnable(GL_DEBUG_OUTPUT);
::printf("OpenGL debug output enabled (LOVE_GRAPHICS_DEBUG=1)\n");
}
@@ -430,10 +454,10 @@ void Graphics::discardStencil()
glDisable(GL_STENCIL_TEST);
}
Image *Graphics::newImage(love::image::ImageData *data)
Image *Graphics::newImage(love::image::ImageData *data, Texture::Format format)
{
// Create the image.
Image *image = new Image(data);
Image *image = new Image(data, format);
if (!isCreated())
return image;
@@ -457,10 +481,10 @@ Image *Graphics::newImage(love::image::ImageData *data)
return image;
}
Image *Graphics::newImage(love::image::CompressedData *cdata)
Image *Graphics::newImage(love::image::CompressedData *cdata, Texture::Format format)
{
// Create the image.
Image *image = new Image(cdata);
Image *image = new Image(cdata, format);
if (!isCreated())
return image;
@@ -504,11 +528,14 @@ ParticleSystem *Graphics::newParticleSystem(Texture *texture, int size)
return new ParticleSystem(texture, size);
}
Canvas *Graphics::newCanvas(int width, int height, Canvas::TextureType texture_type, int fsaa)
Canvas *Graphics::newCanvas(int width, int height, Texture::Format format, int fsaa)
{
if (texture_type == Canvas::TYPE_HDR && !Canvas::isHDRSupported())
if (format == Texture::FORMAT_HDR && !Canvas::isHDRSupported())
throw Exception("HDR Canvases are not supported by your OpenGL implementation");
if (format == Texture::FORMAT_SRGB && !Canvas::isSRGBSupported())
throw Exception("sRGB Canvases are not supported by your OpenGL implementation");
if (width > gl.getMaxTextureSize())
throw Exception("Cannot create canvas: width of %d pixels is too large for this system.", width);
else if (height > gl.getMaxTextureSize())
@@ -517,7 +544,7 @@ Canvas *Graphics::newCanvas(int width, int height, Canvas::TextureType texture_t
while (GL_NO_ERROR != glGetError())
/* clear opengl error flag */;
Canvas *canvas = new Canvas(width, height, texture_type, fsaa);
Canvas *canvas = new Canvas(width, height, format, fsaa);
GLenum err = canvas->getStatus();
// everything ok, return canvas (early out)
@@ -629,22 +656,16 @@ const bool *Graphics::getColorMask() const
void Graphics::setBlendMode(Graphics::BlendMode mode)
{
const int gl_1_4 = GLAD_VERSION_1_4;
GLenum func = GL_FUNC_ADD;
GLenum src_rgb = GL_ONE;
GLenum src_a = GL_ONE;
GLenum dst_rgb = GL_ZERO;
GLenum dst_a = GL_ZERO;
OpenGL::BlendState state = {GL_ONE, GL_ONE, GL_ZERO, GL_ZERO, GL_FUNC_ADD};
switch (mode)
{
case BLEND_ALPHA:
if (gl_1_4 || GLAD_ES_VERSION_2_0 || GLAD_EXT_blend_func_separate)
if (GLAD_ES_VERSION_2_0 || GLAD_VERSION_1_4 || GLAD_EXT_blend_func_separate)
{
src_rgb = GL_SRC_ALPHA;
src_a = GL_ONE;
dst_rgb = dst_a = GL_ONE_MINUS_SRC_ALPHA;
state.srcRGB = GL_SRC_ALPHA;
state.srcA = GL_ONE;
state.dstRGB = state.dstA = GL_ONE_MINUS_SRC_ALPHA;
}
else
{
@@ -652,100 +673,56 @@ void Graphics::setBlendMode(Graphics::BlendMode mode)
// This will most likely only be used for the Microsoft software renderer and
// since it's still stuck with OpenGL 1.1, the only expected difference is a
// different alpha value when reading back the default framebuffer (newScreenshot).
src_rgb = src_a = GL_SRC_ALPHA;
dst_rgb = dst_a = GL_ONE_MINUS_SRC_ALPHA;
state.srcRGB = state.srcA = GL_SRC_ALPHA;
state.dstRGB = state.dstA = GL_ONE_MINUS_SRC_ALPHA;
}
break;
case BLEND_MULTIPLICATIVE:
src_rgb = src_a = GL_DST_COLOR;
dst_rgb = dst_a = GL_ZERO;
state.srcRGB = state.srcA = GL_DST_COLOR;
state.dstRGB = state.dstA = GL_ZERO;
break;
case BLEND_PREMULTIPLIED:
src_rgb = src_a = GL_ONE;
dst_rgb = dst_a = GL_ONE_MINUS_SRC_ALPHA;
state.srcRGB = state.srcA = GL_ONE;
state.dstRGB = state.dstA = GL_ONE_MINUS_SRC_ALPHA;
break;
case BLEND_SUBTRACTIVE:
func = GL_FUNC_REVERSE_SUBTRACT;
state.func = GL_FUNC_REVERSE_SUBTRACT;
case BLEND_ADDITIVE:
src_rgb = src_a = GL_SRC_ALPHA;
dst_rgb = dst_a = GL_ONE;
state.srcRGB = state.srcA = GL_SRC_ALPHA;
state.dstRGB = state.dstA = GL_ONE;
break;
case BLEND_REPLACE:
default:
src_rgb = src_a = GL_ONE;
dst_rgb = dst_a = GL_ZERO;
state.srcRGB = state.srcA = GL_ONE;
state.dstRGB = state.dstA = GL_ZERO;
break;
}
if (gl_1_4 || GLAD_ES_VERSION_2_0)
glBlendEquation(func);
else if (GLAD_EXT_blend_minmax && GLAD_EXT_blend_subtract)
glBlendEquationEXT(func);
else
{
if (func == GL_FUNC_REVERSE_SUBTRACT)
throw Exception("This graphics card does not support the subtractive blend mode!");
// GL_FUNC_ADD is the default even without access to glBlendEquation, so that'll still work.
}
if (src_rgb == src_a && dst_rgb == dst_a)
glBlendFunc(src_rgb, dst_rgb);
else
{
if (gl_1_4 || GLAD_ES_VERSION_2_0)
glBlendFuncSeparate(src_rgb, dst_rgb, src_a, dst_a);
else if (GLAD_EXT_blend_func_separate)
glBlendFuncSeparateEXT(src_rgb, dst_rgb, src_a, dst_a);
else
throw Exception("This graphics card does not support separated rgb and alpha blend functions!");
}
gl.setBlendState(state);
}
Graphics::BlendMode Graphics::getBlendMode() const
{
const int gl_1_4 = GLAD_VERSION_1_4;
OpenGL::BlendState state = gl.getBlendState();
GLint src_rgb, src_a, dst_rgb, dst_a;
GLint equation = GL_FUNC_ADD;
if (gl_1_4 || GLAD_ES_VERSION_2_0 || GLAD_EXT_blend_func_separate)
{
glGetIntegerv(GL_BLEND_SRC_RGB, &src_rgb);
glGetIntegerv(GL_BLEND_SRC_ALPHA, &src_a);
glGetIntegerv(GL_BLEND_DST_RGB, &dst_rgb);
glGetIntegerv(GL_BLEND_DST_ALPHA, &dst_a);
}
else
{
glGetIntegerv(GL_BLEND_SRC, &src_rgb);
glGetIntegerv(GL_BLEND_DST, &dst_rgb);
src_a = src_rgb;
dst_a = dst_rgb;
}
if (GLAD_ES_VERSION_2_0)
glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation);
else if (gl_1_4 || (GLAD_EXT_blend_minmax && GLAD_EXT_blend_subtract))
glGetIntegerv(GL_BLEND_EQUATION, &equation);
if (equation == GL_FUNC_REVERSE_SUBTRACT) // && src == GL_SRC_ALPHA && dst == GL_ONE
if (state.func == GL_FUNC_REVERSE_SUBTRACT) // && src == GL_SRC_ALPHA && dst == GL_ONE
return BLEND_SUBTRACTIVE;
// Everything else has equation == GL_FUNC_ADD.
else if (src_rgb == src_a && dst_rgb == dst_a)
else if (state.srcRGB == state.srcA && state.dstRGB == state.dstA)
{
if (src_rgb == GL_SRC_ALPHA && dst_rgb == GL_ONE)
if (state.srcRGB == GL_SRC_ALPHA && state.dstRGB == GL_ONE)
return BLEND_ADDITIVE;
else if (src_rgb == GL_SRC_ALPHA && dst_rgb == GL_ONE_MINUS_SRC_ALPHA)
else if (state.srcRGB == GL_SRC_ALPHA && state.dstRGB == GL_ONE_MINUS_SRC_ALPHA)
return BLEND_ALPHA; // alpha blend mode fallback for very old OpenGL versions.
else if (src_rgb == GL_DST_COLOR && dst_rgb == GL_ZERO)
else if (state.srcRGB == GL_DST_COLOR && state.dstRGB == GL_ZERO)
return BLEND_MULTIPLICATIVE;
else if (src_rgb == GL_ONE && dst_rgb == GL_ONE_MINUS_SRC_ALPHA)
else if (state.srcRGB == GL_ONE && state.dstRGB == GL_ONE_MINUS_SRC_ALPHA)
return BLEND_PREMULTIPLIED;
else if (src_rgb == GL_ONE && dst_rgb == GL_ZERO)
else if (state.srcRGB == GL_ONE && state.dstRGB == GL_ZERO)
return BLEND_REPLACE;
}
else if (src_rgb == GL_SRC_ALPHA && src_a == GL_ONE &&
dst_rgb == GL_ONE_MINUS_SRC_ALPHA && dst_a == GL_ONE_MINUS_SRC_ALPHA)
else if (state.srcRGB == GL_SRC_ALPHA && state.srcA == GL_ONE &&
state.dstRGB == GL_ONE_MINUS_SRC_ALPHA && state.dstA == GL_ONE_MINUS_SRC_ALPHA)
return BLEND_ALPHA;
throw Exception("Unknown blend mode");
@@ -835,6 +812,21 @@ Graphics::PointStyle Graphics::getPointStyle() const
return POINT_ROUGH;
}
void Graphics::setWireframe(bool enable)
{
// Not supported in OpenGL ES.
if (GLAD_ES_VERSION_2_0)
return;
wireframe = enable;
glPolygonMode(GL_FRONT_AND_BACK, enable ? GL_LINE : GL_FILL);
}
bool Graphics::isWireframe() const
{
return wireframe;
}
void Graphics::print(const std::string &str, float x, float y , float angle, float sx, float sy, float ox, float oy, float kx, float ky)
{
if (currentFont != nullptr)
@@ -81,6 +81,8 @@ struct DisplayState
// Color mask.
bool colorMask[4];
bool wireframe;
// Default values.
DisplayState()
{
@@ -93,6 +95,7 @@ struct DisplayState
pointStyle = Graphics::POINT_SMOOTH;
scissor = false;
colorMask[0] = colorMask[1] = colorMask[2] = colorMask[3] = true;
wireframe = false;
}
};
@@ -112,7 +115,7 @@ public:
void restoreState(const DisplayState &s);
virtual void setViewportSize(int width, int height);
virtual bool setMode(int width, int height);
virtual bool setMode(int width, int height, bool &sRGB);
virtual void unSetMode();
void setDebug(bool enable);
@@ -191,8 +194,8 @@ public:
/**
* Creates an Image object with padding and/or optimization.
**/
Image *newImage(love::image::ImageData *data);
Image *newImage(love::image::CompressedData *cdata);
Image *newImage(love::image::ImageData *data, Texture::Format format = Texture::FORMAT_NORMAL);
Image *newImage(love::image::CompressedData *cdata, Texture::Format format = Texture::FORMAT_NORMAL);
Quad *newQuad(Quad::Viewport v, float sw, float sh);
@@ -205,7 +208,7 @@ public:
ParticleSystem *newParticleSystem(Texture *texture, int size);
Canvas *newCanvas(int width, int height, Canvas::TextureType texture_type = Canvas::TYPE_NORMAL, int fsaa = 0);
Canvas *newCanvas(int width, int height, Texture::Format format = Texture::FORMAT_NORMAL, int fsaa = 0);
Shader *newShader(const Shader::ShaderSources &sources);
@@ -334,6 +337,19 @@ public:
**/
PointStyle getPointStyle() const;
/**
* Sets whether graphics will be drawn as wireframe lines instead of filled
* triangles (has no effect for drawn points.)
* This should only be used as a debugging tool. The wireframe lines do not
* behave the same as regular love.graphics lines.
**/
void setWireframe(bool enable);
/**
* Gets whether wireframe drawing mode is enabled.
**/
bool isWireframe() const;
/**
* Draws text at the specified coordinates, with rotation and
* scaling along both axes.
@@ -459,6 +475,7 @@ private:
float lineWidth;
size_t matrixLimit;
bool colorMask[4];
bool wireframe;
int width;
int height;
+41 -10
View File
@@ -36,7 +36,7 @@ float Image::maxMipmapSharpness = 0.0f;
Texture::FilterMode Image::defaultMipmapFilter = Texture::FILTER_NONE;
float Image::defaultMipmapSharpness = 0.0f;
Image::Image(love::image::ImageData *data)
Image::Image(love::image::ImageData *data, Texture::Format format)
: data(data)
, cdata(nullptr)
, paddedWidth(width)
@@ -45,6 +45,7 @@ Image::Image(love::image::ImageData *data)
, mipmapSharpness(defaultMipmapSharpness)
, mipmapsCreated(false)
, compressed(false)
, format(format)
, usingDefaultTexture(false)
{
width = data->getWidth();
@@ -54,7 +55,7 @@ Image::Image(love::image::ImageData *data)
preload();
}
Image::Image(love::image::CompressedData *cdata)
Image::Image(love::image::CompressedData *cdata, Texture::Format format)
: data(nullptr)
, cdata(cdata)
, paddedWidth(width)
@@ -63,6 +64,7 @@ Image::Image(love::image::CompressedData *cdata)
, mipmapSharpness(defaultMipmapSharpness)
, mipmapsCreated(false)
, compressed(true)
, format(format)
, usingDefaultTexture(false)
{
width = cdata->getWidth(0);
@@ -328,6 +330,9 @@ void Image::unload()
bool Image::loadVolatile()
{
if (format == FORMAT_SRGB && !hasSRGBSupport())
throw love::Exception("sRGB images are not supported on this system.");
if (isCompressed() && cdata && !hasCompressedTextureSupport(cdata->getFormat()))
{
const char *str;
@@ -400,9 +405,10 @@ void Image::uploadTexturePadded()
}
else if (data)
{
GLenum iformat = (format == FORMAT_SRGB) ? GL_SRGB_ALPHA : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
iformat,
(GLsizei)paddedWidth,
(GLsizei)paddedHeight,
0,
@@ -437,9 +443,10 @@ void Image::uploadTexture()
}
else if (data)
{
GLenum iformat = (format == FORMAT_SRGB) ? GL_SRGB_ALPHA : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
iformat,
(GLsizei)width,
(GLsizei)height,
0,
@@ -497,6 +504,11 @@ bool Image::refresh()
return true;
}
Texture::Format Image::getFormat() const
{
return format;
}
void Image::uploadDefaultTexture()
{
usingDefaultTexture = true;
@@ -561,16 +573,27 @@ bool Image::isCompressed() const
return compressed;
}
GLenum Image::getCompressedFormat(image::CompressedData::Format format) const
GLenum Image::getCompressedFormat(image::CompressedData::Format cformat) const
{
switch (format)
bool srgb = format == FORMAT_SRGB;
switch (cformat)
{
case image::CompressedData::FORMAT_DXT1:
return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
if (srgb)
return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
else
return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
case image::CompressedData::FORMAT_DXT3:
return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
if (srgb)
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
else
return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
case image::CompressedData::FORMAT_DXT5:
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
if (srgb)
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
else
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
case image::CompressedData::FORMAT_BC4:
return GL_COMPRESSED_RED_RGTC1;
case image::CompressedData::FORMAT_BC4s:
@@ -580,7 +603,10 @@ GLenum Image::getCompressedFormat(image::CompressedData::Format format) const
case image::CompressedData::FORMAT_BC5s:
return GL_COMPRESSED_SIGNED_RG_RGTC2;
default:
return GL_RGBA;
if (srgb)
return GL_SRGB_ALPHA;
else
return GL_RGBA;
}
}
@@ -624,6 +650,11 @@ bool Image::hasCompressedTextureSupport(image::CompressedData::Format format)
return false;
}
bool Image::hasSRGBSupport()
{
return GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB || GLAD_EXT_sRGB;
}
} // opengl
} // graphics
} // love
+10 -3
View File
@@ -56,14 +56,14 @@ public:
*
* @param data The data from which to load the image.
**/
Image(love::image::ImageData *data);
Image(love::image::ImageData *data, Texture::Format format = Texture::FORMAT_NORMAL);
/**
* Creates a new Image with compressed image data.
*
* @param cdata The compressed data from which to load the image.
**/
Image(love::image::CompressedData *cdata);
Image(love::image::CompressedData *cdata, Texture::Format format = Texture::FORMAT_NORMAL);
/**
* Destructor. Deletes the hardware texture and other resources.
@@ -120,6 +120,8 @@ public:
**/
bool refresh();
Texture::Format getFormat() const;
static void setDefaultMipmapSharpness(float sharpness);
static float getDefaultMipmapSharpness();
static void setDefaultMipmapFilter(FilterMode f);
@@ -132,6 +134,8 @@ public:
static bool hasCompressedTextureSupport(image::CompressedData::Format format);
static bool hasSRGBSupport();
private:
void uploadDefaultTexture();
@@ -161,6 +165,9 @@ private:
// Whether this Image is using a compressed texture.
bool compressed;
// The format to interpret the texture's data as.
Texture::Format format;
// True if the image wasn't able to be properly created and it had to fall
// back to a default texture.
bool usingDefaultTexture;
@@ -179,7 +186,7 @@ private:
static FilterMode defaultMipmapFilter;
static float defaultMipmapSharpness;
GLenum getCompressedFormat(image::CompressedData::Format format) const;
GLenum getCompressedFormat(image::CompressedData::Format cformat) const;
}; // Image
@@ -44,7 +44,6 @@ Mesh::Mesh(const std::vector<Vertex> &verts, Mesh::DrawMode mode)
, range_max(-1)
, texture(nullptr)
, colors_enabled(false)
, wireframe(false)
{
setVertices(verts);
}
@@ -59,7 +58,6 @@ Mesh::Mesh(int vertexcount, Mesh::DrawMode mode)
, range_max(-1)
, texture(nullptr)
, colors_enabled(false)
, wireframe(false)
{
if (vertexcount < 1)
throw love::Exception("Invalid number of vertices.");
@@ -278,16 +276,6 @@ bool Mesh::hasVertexColors() const
return colors_enabled;
}
void Mesh::setWireframe(bool enable)
{
wireframe = enable;
}
bool Mesh::isWireframe() const
{
return wireframe;
}
void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
{
const size_t pos_offset = offsetof(Vertex, x);
@@ -326,9 +314,6 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
gl.setVertexAttribArray(OpenGL::ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, sizeof(Vertex), vbo->getPointer(color_offset));
}
if (wireframe && GLAD_VERSION_1_0)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GLenum mode = getGLDrawMode(draw_mode);
gl.prepareDraw();
@@ -377,9 +362,6 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
gl.disableVertexAttribArray(OpenGL::ATTRIB_POS);
gl.disableVertexAttribArray(OpenGL::ATTRIB_TEXCOORD);
if (wireframe && GLAD_VERSION_1_0)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (hasVertexColors())
{
gl.disableVertexAttribArray(OpenGL::ATTRIB_COLOR);
@@ -162,15 +162,6 @@ public:
void setVertexColors(bool enable);
bool hasVertexColors() const;
/**
* Sets whether the Mesh will be drawn as wireframe lines instead of filled
* triangles (has no effect for DRAW_MODE_POINTS.)
* This should only be used as a debugging tool. The wireframe lines do not
* behave the same as regular love.graphics lines.
**/
void setWireframe(bool enable);
bool isWireframe() const;
// Implements Drawable.
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
@@ -201,8 +192,6 @@ private:
// Whether the per-vertex colors are used when drawing.
bool colors_enabled;
bool wireframe;
static StringMap<DrawMode, DRAW_MODE_MAX_ENUM>::Entry drawModeEntries[];
static StringMap<DrawMode, DRAW_MODE_MAX_ENUM> drawModes;
@@ -127,6 +127,9 @@ bool OpenGL::initContext()
if (Canvas::isSupported())
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint *) &state.defaultFBO);
BlendState blend = {GL_ONE, GL_ONE, GL_ZERO, GL_ZERO, GL_FUNC_ADD};
setBlendState(blend);
initMaxValues();
createDefaultTexture();
@@ -492,6 +495,40 @@ OpenGL::Viewport OpenGL::getScissor() const
return state.scissor;
}
void OpenGL::setBlendState(const BlendState &blend)
{
if (GLAD_ES_VERSION_2_0 || GLAD_VERSION_1_4)
glBlendEquation(blend.func);
else if (GLAD_EXT_blend_minmax && GLAD_EXT_blend_subtract)
glBlendEquationEXT(blend.func);
else
{
if (blend.func == GL_FUNC_REVERSE_SUBTRACT)
throw love::Exception("This graphics card does not support the subtractive blend mode!");
// GL_FUNC_ADD is the default even without access to glBlendEquation, so that'll still work.
}
if (blend.srcRGB == blend.srcA && blend.dstRGB == blend.dstA)
glBlendFunc(blend.srcRGB, blend.dstRGB);
else
{
if (GLAD_ES_VERSION_2_0 || GLAD_VERSION_1_4)
glBlendFuncSeparate(blend.srcRGB, blend.dstRGB, blend.srcA, blend.dstA);
else if (GLAD_EXT_blend_func_separate)
glBlendFuncSeparateEXT(blend.srcRGB, blend.dstRGB, blend.srcA, blend.dstA);
else
throw love::Exception("This graphics card does not support separated rgb and alpha blend functions!");
}
state.blend = blend;
}
OpenGL::BlendState OpenGL::getBlendState() const
{
return state.blend;
}
void OpenGL::setPointSize(float size)
{
if (GLAD_VERSION_1_0)
@@ -103,6 +103,13 @@ public:
}
};
struct BlendState
{
GLenum srcRGB, srcA;
GLenum dstRGB, dstA;
GLenum func;
};
// Transformation matrix stacks.
struct
{
@@ -202,6 +209,17 @@ public:
**/
Viewport getScissor() const;
/**
* Sets blending functionality.
* Note: This does not globally enable or disable blending.
**/
void setBlendState(const BlendState &blend);
/**
* Gets the currently set blending functionality.
**/
BlendState getBlendState() const;
/**
* Sets the global point size.
**/
@@ -332,6 +350,8 @@ private:
GLuint defaultFBO;
BlendState blend;
// The last ID value used for pseudo-instancing.
int lastPseudoInstanceID;
@@ -95,6 +95,7 @@ ParticleSystem::ParticleSystem(Texture *texture, uint32 size)
, spinVariation(0)
, offsetX(float(texture->getWidth())*0.5f)
, offsetY(float(texture->getHeight())*0.5f)
, relativeRotation(false)
{
if (size == 0 || size > MAX_PARTICLES)
throw love::Exception("Invalid ParticleSystem size.");
@@ -146,6 +147,7 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p)
, offsetX(p.offsetX)
, offsetY(p.offsetY)
, colors(p.colors)
, relativeRotation(p.relativeRotation)
{
setBufferSize(maxParticles);
@@ -170,7 +172,7 @@ void ParticleSystem::createBuffers(size_t size)
{
try
{
pFree = pMem = new particle[size];
pFree = pMem = new Particle[size];
particleVerts = new love::Vertex[size * 4];
ibo = new VertexIndex(size);
maxParticles = (uint32) size;
@@ -222,7 +224,7 @@ void ParticleSystem::addParticle(float t)
return;
// Gets a free particle and updates the allocation pointer.
particle *p = pFree++;
Particle *p = pFree++;
initParticle(p, t);
switch (insertMode)
@@ -242,7 +244,7 @@ void ParticleSystem::addParticle(float t)
activeParticles++;
}
void ParticleSystem::initParticle(particle *p, float t)
void ParticleSystem::initParticle(Particle *p, float t)
{
float min,max;
@@ -308,10 +310,14 @@ void ParticleSystem::initParticle(particle *p, float t)
p->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation);
p->rotation = (float) rng.random(min, max);
p->angle = p->rotation;
if (relativeRotation)
p->angle += atan2f(p->speed.y, p->speed.x);
p->color = colors[0];
}
void ParticleSystem::insertTop(particle *p)
void ParticleSystem::insertTop(Particle *p)
{
if (pHead == nullptr)
{
@@ -327,7 +333,7 @@ void ParticleSystem::insertTop(particle *p)
pTail = p;
}
void ParticleSystem::insertBottom(particle *p)
void ParticleSystem::insertBottom(Particle *p)
{
if (pTail == nullptr)
{
@@ -343,7 +349,7 @@ void ParticleSystem::insertBottom(particle *p)
pHead = p;
}
void ParticleSystem::insertRandom(particle *p)
void ParticleSystem::insertRandom(Particle *p)
{
// Nonuniform, but 64-bit is so large nobody will notice. Hopefully.
uint64 pos = rng.rand() % ((int64) activeParticles + 1);
@@ -351,7 +357,7 @@ void ParticleSystem::insertRandom(particle *p)
// Special case where the particle gets inserted before the head.
if (pos == activeParticles)
{
particle *pA = pHead;
Particle *pA = pHead;
if (pA)
pA->prev = p;
p->prev = nullptr;
@@ -361,8 +367,8 @@ void ParticleSystem::insertRandom(particle *p)
}
// Inserts the particle after the randomly selected particle.
particle *pA = pMem + pos;
particle *pB = pA->next;
Particle *pA = pMem + pos;
Particle *pB = pA->next;
pA->next = p;
if (pB)
pB->prev = p;
@@ -372,12 +378,12 @@ void ParticleSystem::insertRandom(particle *p)
p->next = pB;
}
ParticleSystem::particle *ParticleSystem::removeParticle(particle *p)
ParticleSystem::Particle *ParticleSystem::removeParticle(Particle *p)
{
// The linked list is updated in this function and old pointers may be
// invalidated. The returned pointer will inform the caller of the new
// pointer to the next particle.
particle *pNext = nullptr;
Particle *pNext = nullptr;
// Removes the particle from the linked list.
if (p->prev)
@@ -725,6 +731,16 @@ std::vector<Color> ParticleSystem::getColor() const
return ncolors;
}
void ParticleSystem::setRelativeRotation(bool enable)
{
relativeRotation = enable;
}
bool ParticleSystem::hasRelativeRotation() const
{
return relativeRotation;
}
uint32 ParticleSystem::getCount() const
{
return activeParticles;
@@ -812,13 +828,13 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo
const Vertex *textureVerts = texture->getVertices();
Vertex *pVerts = particleVerts;
particle *p = pHead;
Particle *p = pHead;
// set the vertex data for each particle (transformation, texcoords, color)
while (p)
{
// particle vertices are image vertices transformed by particle information
t.setTransformation(p->position[0], p->position[1], p->rotation, p->size, p->size, offsetX, offsetY, 0.0f, 0.0f);
t.setTransformation(p->position[0], p->position[1], p->angle, p->size, p->size, offsetX, offsetY, 0.0f, 0.0f);
t.transform(pVerts, textureVerts, 4);
// set the texture coordinate and color data for particle vertices
@@ -871,7 +887,7 @@ void ParticleSystem::update(float dt)
return;
// Traverse all particles and update.
particle *p = pHead;
Particle *p = pHead;
while (p)
{
@@ -916,7 +932,12 @@ void ParticleSystem::update(float dt)
const float t = 1.0f - p->life / p->lifetime;
// Rotate.
p->rotation += (p->spinStart * (1.0f - t) + p->spinEnd * t)*dt;
p->rotation += (p->spinStart * (1.0f - t) + p->spinEnd * t) * dt;
p->angle = p->rotation;
if (relativeRotation)
p->angle += atan2f(p->speed.y, p->speed.x);
// Change size according to given intervals:
// i = 0 1 2 3 n-1
@@ -422,6 +422,12 @@ public:
**/
std::vector<Color> getColor() const;
/**
* sets whether particle angles & rotations are relative to their velocities.
**/
void setRelativeRotation(bool enable);
bool hasRelativeRotation() const;
/**
* Returns the amount of particles that are currently active in the system.
**/
@@ -495,11 +501,12 @@ public:
static bool getConstant(InsertMode in, const char *&out);
protected:
// Represents a single particle.
struct particle
struct Particle
{
particle *prev;
particle *next;
Particle *prev;
Particle *next;
float lifetime;
float life;
@@ -519,7 +526,8 @@ protected:
float sizeOffset;
float sizeIntervalSize;
float rotation;
float rotation; // Amount of rotation applied to the final angle.
float angle;
float spinStart;
float spinEnd;
@@ -527,16 +535,16 @@ protected:
};
// Pointer to the beginning of the allocated memory.
particle *pMem;
Particle *pMem;
// Pointer to a free particle.
particle *pFree;
Particle *pFree;
// Pointer to the start of the linked list.
particle *pHead;
Particle *pHead;
// Pointer to the end of the linked list.
particle *pTail;
Particle *pTail;
// array of transformed vertex data for all particles, for drawing
Vertex *particleVerts;
@@ -621,17 +629,19 @@ protected:
// Color.
std::vector<Colorf> colors;
bool relativeRotation;
void createBuffers(size_t size);
void deleteBuffers();
void addParticle(float t);
particle *removeParticle(particle *p);
Particle *removeParticle(Particle *p);
// Called by addParticle.
void initParticle(particle *p, float t);
void insertTop(particle *p);
void insertBottom(particle *p);
void insertRandom(particle *p);
void initParticle(Particle *p, float t);
void insertTop(Particle *p);
void insertBottom(Particle *p);
void insertRandom(Particle *p);
static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM>::Entry distributionsEntries[];
static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM> distributions;
@@ -105,6 +105,8 @@ int SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, fl
if ((index == -1 && next >= size) || index < -1 || index >= size)
return -1;
Vertex sprite[4];
// Needed for colors.
memcpy(sprite, texture->getVertices(), sizeof(Vertex) * 4);
@@ -131,6 +133,8 @@ int SpriteBatch::addq(Quad *quad, float x, float y, float a, float sx, float sy,
if ((index == -1 && next >= size) || index < -1 || index >= next)
return -1;
Vertex sprite[4];
// Needed for colors.
memcpy(sprite, quad->getVertices(), sizeof(Vertex) * 4);
@@ -135,8 +135,6 @@ private:
// The next free element.
int next;
Vertex sprite[4];
// Current color. This color, if present, will be applied to the next
// added sprite.
Color *color;
@@ -110,12 +110,14 @@ int w_Canvas_clear(lua_State *L)
return 0;
}
int w_Canvas_getType(lua_State *L)
int w_Canvas_getFormat(lua_State *L)
{
Canvas *canvas = luax_checkcanvas(L, 1);
Canvas::TextureType type = canvas->getTextureType();
Texture::Format format = canvas->getTextureFormat();
const char *str;
Canvas::getConstant(type, str);
if (!Texture::getConstant(format, str))
return luaL_error(L, "Unknown texture format.");
lua_pushstring(L, str);
return 1;
}
@@ -142,8 +144,11 @@ static const luaL_Reg functions[] =
{ "getImageData", w_Canvas_getImageData },
{ "getPixel", w_Canvas_getPixel },
{ "clear", w_Canvas_clear },
{ "getType", w_Canvas_getType },
{ "getFormat", w_Canvas_getFormat },
{ "getFSAA", w_Canvas_getFSAA },
// Deprecated since 0.9.1.
{ "getType", w_Canvas_getFormat },
{ 0, 0 }
};
@@ -39,7 +39,7 @@ int w_Canvas_renderTo(lua_State *L);
int w_Canvas_getImageData(lua_State *L);
int w_Canvas_getPixel(lua_State * L);
int w_Canvas_clear(lua_State *L);
int w_Canvas_getType(lua_State *L);
int w_Canvas_getFormat(lua_State *L);
int w_Canvas_getFSAA(lua_State *L);
extern "C" int luaopen_canvas(lua_State *L);
@@ -152,8 +152,17 @@ int w_getMaxTextureSize(lua_State *L)
int w_newImage(lua_State *L)
{
love::image::ImageData *data = 0;
love::image::CompressedData *cdata = 0;
love::image::ImageData *data = nullptr;
love::image::CompressedData *cdata = nullptr;
Texture::Format format = Texture::FORMAT_NORMAL;
const char *fstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2);
if (fstr != nullptr && !Texture::getConstant(fstr, format))
return luaL_error(L, "Invalid texture format: %s", fstr);
if (format == Texture::FORMAT_HDR) // For now...
return luaL_error(L, "HDR images are not supported.");
// Convert to FileData, if necessary.
if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T))
@@ -185,15 +194,15 @@ int w_newImage(lua_State *L)
return luaL_error(L, "Error creating image.");
// Create the image.
Image *image = 0;
Image *image = nullptr;
EXCEPT_GUARD(
if (cdata)
image = instance->newImage(cdata);
image = instance->newImage(cdata, format);
else if (data)
image = instance->newImage(data);
image = instance->newImage(data, format);
)
if (image == 0)
if (image == nullptr)
return luaL_error(L, "Could not load image.");
// Push the type.
@@ -325,12 +334,12 @@ int w_newCanvas(lua_State *L)
const char *str = luaL_optstring(L, 3, "normal");
int fsaa = luaL_optint(L, 4, 0);
Canvas::TextureType texture_type;
if (!Canvas::getConstant(str, texture_type))
return luaL_error(L, "Invalid canvas type: %s", str);
Texture::Format format;
if (!Texture::getConstant(str, format))
return luaL_error(L, "Invalid texture format: %s", str);
Canvas *canvas = nullptr;
EXCEPT_GUARD(canvas = instance->newCanvas(width, height, texture_type, fsaa);)
EXCEPT_GUARD(canvas = instance->newCanvas(width, height, format, fsaa);)
if (canvas == nullptr)
return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
@@ -835,6 +844,18 @@ int w_getMaxPointSize(lua_State *L)
return 1;
}
int w_setWireframe(lua_State *L)
{
instance->setWireframe(luax_toboolean(L, 1));
return 0;
}
int w_isWireframe(lua_State *L)
{
luax_pushboolean(L, instance->isWireframe());
return 1;
}
int w_newScreenshot(lua_State *L)
{
love::image::Image *image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
@@ -1029,6 +1050,10 @@ int w_isSupported(lua_State *L)
if (!(GLAD_ARB_draw_instanced || (GLAD_ES_VERSION_2_0 && GLAD_EXT_draw_instanced)))
supported = false;
break;
case Graphics::SUPPORT_SRGB:
if (!Canvas::isSRGBSupported())
supported = false;
break;
default:
supported = false;
}
@@ -1405,6 +1430,8 @@ static const luaL_Reg functions[] =
{ "setPointStyle", w_setPointStyle },
{ "getPointSize", w_getPointSize },
{ "getPointStyle", w_getPointStyle },
{ "setWireframe", w_setWireframe },
{ "isWireframe", w_isWireframe },
{ "newScreenshot", w_newScreenshot },
{ "setCanvas", w_setCanvas },
{ "getCanvas", w_getCanvas },
@@ -85,6 +85,8 @@ int w_setPointStyle(lua_State *L);
int w_getPointSize(lua_State *L);
int w_getPointStyle(lua_State *L);
int w_getMaxPointSize(lua_State *L);
int w_setWireframe(lua_State *L);
int w_isWireframe(lua_State *L);
int w_newScreenshot(lua_State *L);
int w_setCanvas(lua_State *L);
int w_getCanvas(lua_State *L);
@@ -361,20 +361,6 @@ int w_Mesh_hasVertexColors(lua_State *L)
return 1;
}
int w_Mesh_setWireframe(lua_State *L)
{
Mesh *t = luax_checkmesh(L, 1);
t->setWireframe(luax_toboolean(L, 2));
return 0;
}
int w_Mesh_isWireframe(lua_State *L)
{
Mesh *t = luax_checkmesh(L, 1);
luax_pushboolean(L, t->isWireframe());
return 1;
}
static const luaL_Reg functions[] =
{
{ "setVertex", w_Mesh_setVertex },
@@ -394,8 +380,6 @@ static const luaL_Reg functions[] =
{ "getDrawRange", w_Mesh_getDrawRange },
{ "setVertexColors", w_Mesh_setVertexColors },
{ "hasVertexColors", w_Mesh_hasVertexColors },
{ "setWireframe", w_Mesh_setWireframe },
{ "isWireframe", w_Mesh_isWireframe },
// Deprecated since 0.9.1.
{ "setImage", w_Mesh_setTexture },
@@ -51,8 +51,6 @@ int w_Mesh_setDrawRange(lua_State *L);
int w_Mesh_getDrawRange(lua_State *L);
int w_Mesh_setVertexColors(lua_State *L);
int w_Mesh_hasVertexColors(lua_State *L);
int w_Mesh_setWireframe(lua_State *L);
int w_Mesh_isWireframe(lua_State *L);
extern "C" int luaopen_mesh(lua_State *L);
@@ -569,6 +569,20 @@ int w_ParticleSystem_getColors(lua_State *L)
return colors.size();
}
int w_ParticleSystem_setRelativeRotation(lua_State *L)
{
ParticleSystem *t = luax_checkparticlesystem(L, 1);
t->setRelativeRotation(luax_toboolean(L, 2));
return 0;
}
int w_ParticleSystem_hasRelativeRotation(lua_State *L)
{
ParticleSystem *t = luax_checkparticlesystem(L, 1);
luax_pushboolean(L, t->hasRelativeRotation());
return 1;
}
int w_ParticleSystem_getCount(lua_State *L)
{
ParticleSystem *t = luax_checkparticlesystem(L, 1);
@@ -687,6 +701,8 @@ static const luaL_Reg functions[] =
{ "getColors", w_ParticleSystem_getColors },
{ "setOffset", w_ParticleSystem_setOffset },
{ "getOffset", w_ParticleSystem_getOffset },
{ "setRelativeRotation", w_ParticleSystem_setRelativeRotation },
{ "hasRelativeRotation", w_ParticleSystem_hasRelativeRotation },
{ "getCount", w_ParticleSystem_getCount },
{ "start", w_ParticleSystem_start },
{ "stop", w_ParticleSystem_stop },
@@ -77,6 +77,8 @@ int w_ParticleSystem_setColors(lua_State *L);
int w_ParticleSystem_getColors(lua_State *L);
int w_ParticleSystem_setOffset(lua_State *L);
int w_ParticleSystem_getOffset(lua_State *L);
int w_ParticleSystem_setRelativeRotation(lua_State *L);
int w_ParticleSystem_hasRelativeRotation(lua_State *L);
int w_ParticleSystem_getCount(lua_State *L);
int w_ParticleSystem_start(lua_State *L);
int w_ParticleSystem_stop(lua_State *L);
-6
View File
@@ -52,9 +52,6 @@
// of addressing implementations directly.
extern "C"
{
#if defined(LOVE_ENABLE_ANDROID)
extern int luaopen_love_android(lua_State*);
#endif
#if defined(LOVE_ENABLE_AUDIO)
extern int luaopen_love_audio(lua_State*);
#endif
@@ -110,9 +107,6 @@ extern "C"
}
static const luaL_Reg modules[] = {
#if defined(LOVE_ENABLE_ANDROID)
{ "love.android", luaopen_love_android },
#endif
#if defined(LOVE_ENABLE_AUDIO)
{ "love.audio", luaopen_love_audio },
#endif
+30
View File
@@ -193,5 +193,35 @@ bool Math::isConvex(const std::vector<Vertex> &polygon)
return true;
}
/**
* http://en.wikipedia.org/wiki/SRGB#The_reverse_transformation
**/
float Math::gammaToLinear(float c) const
{
if (c > 1.0)
return 1.0;
else if (c < 0.0)
return 0.0;
else if (c <= 0.04045)
return c / 12.92;
else
return powf((c + 0.055) / 1.055, 2.4);
}
/**
* http://en.wikipedia.org/wiki/SRGB#The_forward_transformation_.28CIE_xyY_or_CIE_XYZ_to_sRGB.29
**/
float Math::linearToGamma(float c) const
{
if (c > 1.0)
return 1.0;
else if (c < 0.0)
return 0.0;
else if (c < 0.0031308)
return c * 12.92;
else
return 1.055 * powf(c, 0.41666) - 0.055;
}
} // math
} // love
+30 -20
View File
@@ -53,26 +53,6 @@ public:
virtual ~Math()
{}
inline void setRandomSeed(RandomGenerator::Seed seed)
{
rng.setSeed(seed);
}
inline void setRandomSeed(uint32 low, uint32 high)
{
rng.setSeed(low, high);
}
inline RandomGenerator::Seed getRandomSeed() const
{
return rng.getSeed();
}
inline void getRandomSeed(uint32 &low, uint32 &high) const
{
rng.getSeed(low, high);
}
/**
* @copydoc RandomGenerator::random()
**/
@@ -105,6 +85,26 @@ public:
return rng.randomNormal(stddev);
}
inline void setRandomSeed(RandomGenerator::Seed seed)
{
rng.setSeed(seed);
}
inline RandomGenerator::Seed getRandomSeed() const
{
return rng.getSeed();
}
inline void setRandomState(const std::string &statestr)
{
rng.setState(statestr);
}
inline std::string getRandomState() const
{
return rng.getState();
}
/**
* Create a new random number generator.
**/
@@ -136,6 +136,16 @@ public:
**/
bool isConvex(const std::vector<Vertex> &polygon);
/**
* Converts a value from the sRGB (gamma) colorspace to linear RGB.
**/
float gammaToLinear(float c) const;
/**
* Converts a value from linear RGB to the sRGB (gamma) colorspace.
**/
float linearToGamma(float c) const;
/**
* Calculate Simplex noise for the specified coordinate(s).
*
+76 -20
View File
@@ -20,8 +20,13 @@
#include "RandomGenerator.h"
// STL
// C++
#include <cmath>
#include <sstream>
#include <iomanip>
// C
#include <cstdlib>
namespace love
{
@@ -36,25 +41,10 @@ RandomGenerator::RandomGenerator()
{
// because it is too big for some compilers to handle ... if you know what
// i mean
#ifdef LOVE_BIG_ENDIAN
seed.b32.a = 0x0139408D;
seed.b32.b = 0xCBBF7A44;
#else
seed.b32.b = 0x0139408D;
seed.b32.a = 0xCBBF7A44;
#endif
rng_state = seed;
}
void RandomGenerator::setSeed(RandomGenerator::Seed newseed)
{
// 0 xor 0 is still 0, so Xorshift can't generate new numbers.
if (newseed.b64 == 0)
throw love::Exception("Invalid random seed.");
seed = newseed;
rng_state = seed;
Seed newseed;
newseed.b32.low = 0xCBBF7A44;
newseed.b32.high = 0x0139408D;
setSeed(newseed);
}
uint64 RandomGenerator::rand()
@@ -83,5 +73,71 @@ double RandomGenerator::randomNormal(double stddev)
return r * sin(phi) * stddev;
}
void RandomGenerator::setSeed(RandomGenerator::Seed newseed)
{
// 0 xor 0 is still 0, so Xorshift can't generate new numbers.
if (newseed.b64 == 0)
throw love::Exception("Invalid random seed.");
seed = newseed;
rng_state = seed;
}
RandomGenerator::Seed RandomGenerator::getSeed() const
{
return seed;
}
void RandomGenerator::setState(const std::string &statestr)
{
// For this implementation we'll accept a hex string representing the
// 64-bit state integer xorshift uses.
Seed state = {};
// Hex string must start with 0x.
if (statestr.find("0x") != 0 || statestr.size() < 3)
throw love::Exception("Invalid random state.");
// standardized strtoull (or 64 bit integer support for stringstream)
// requires C++11's standard library, which we can't use yet.
// I use strtol like this not because it's the best solution, but because
// it's "good enough".
// Convert the hex string to the state integer character-by-character.
for (size_t i = 2; i < statestr.size(); i++)
{
char hex[2] = {statestr[i], 0};
char *end = nullptr;
// Convert the current hex character to a number.
int nibble = strtol(hex, &end, 16);
// Check if strtol failed to convert it.
if (end != nullptr && *end != 0)
throw love::Exception("Invalid random state.");
state.b64 = (state.b64 << 4) + nibble;
}
rng_state = state;
}
std::string RandomGenerator::getState() const
{
// For this implementation we'll return a hex string representing the 64-bit
// state integer xorshift uses.
std::stringstream ss;
ss << "0x";
// Again with the stringstream not dealing with 64 bit integers...
ss << std::setfill('0') << std::setw(8) << std::hex << rng_state.b32.high;
ss << std::setfill('0') << std::setw(8) << std::hex << rng_state.b32.low;
return ss.str();
}
} // math
} // love
+31 -43
View File
@@ -28,8 +28,9 @@
#include "common/int.h"
#include "common/Object.h"
// STL
// C++
#include <limits>
#include <string>
namespace love
{
@@ -45,54 +46,19 @@ public:
uint64 b64;
struct
{
uint32 a;
uint32 b;
#ifdef LOVE_BIG_ENDIAN
uint32 high;
uint32 low;
#else
uint32 low;
uint32 high;
#endif
} b32;
};
RandomGenerator();
virtual ~RandomGenerator() {}
/**
* Set pseudo-random seed.
* It's up to the implementation how to use this.
**/
void setSeed(Seed seed);
/**
* Separately set the low and high bits of the pseudo-random seed.
**/
inline void setSeed(uint32 low, uint32 high)
{
Seed newseed;
#ifdef LOVE_BIG_ENDIAN
newseed.b32.a = high;
newseed.b32.b = low;
#else
newseed.b32.b = high;
newseed.b32.a = low;
#endif
setSeed(newseed);
}
inline Seed getSeed() const
{
return seed;
}
inline void getSeed(uint32 &low, uint32 &high) const
{
#ifdef LOVE_BIG_ENDIAN
high = seed.b32.a;
low = seed.b32.b;
#else
high = seed.b32.b;
low = seed.b32.a;
#endif
}
/**
* Return uniformly distributed pseudo random integer.
*
@@ -138,6 +104,28 @@ public:
**/
double randomNormal(double stddev);
/**
* Set pseudo-random seed.
* It's up to the implementation how to use this.
**/
void setSeed(Seed seed);
/**
* Get the previously set pseudo-random seed.
**/
Seed getSeed() const;
/**
* Set the internal implementation-dependent state value based on a string.
**/
void setState(const std::string &statestr);
/**
* Get a string representation of the implementation-dependent internal
* state value.
**/
std::string getState() const;
private:
Seed seed;
+96 -17
View File
@@ -32,21 +32,6 @@ namespace love
namespace math
{
int w_setRandomSeed(lua_State *L)
{
EXCEPT_GUARD(Math::instance.setRandomSeed(luax_checkrandomseed(L, 1));)
return 0;
}
int w_getRandomSeed(lua_State *L)
{
uint32 low = 0, high = 0;
Math::instance.getRandomSeed(low, high);
lua_pushnumber(L, (lua_Number) low);
lua_pushnumber(L, (lua_Number) high);
return 2;
}
int w_random(lua_State *L)
{
return luax_getrandom(L, 1, Math::instance.random());
@@ -62,6 +47,32 @@ int w_randomNormal(lua_State *L)
return 1;
}
int w_setRandomSeed(lua_State *L)
{
EXCEPT_GUARD(Math::instance.setRandomSeed(luax_checkrandomseed(L, 1));)
return 0;
}
int w_getRandomSeed(lua_State *L)
{
RandomGenerator::Seed s = Math::instance.getRandomSeed();
lua_pushnumber(L, (lua_Number) s.b32.low);
lua_pushnumber(L, (lua_Number) s.b32.high);
return 2;
}
int w_setRandomState(lua_State *L)
{
EXCEPT_GUARD(Math::instance.setRandomState(luax_checkstring(L, 1));)
return 0;
}
int w_getRandomState(lua_State *L)
{
luax_pushstring(L, Math::instance.getRandomState());
return 1;
}
int w_newRandomGenerator(lua_State *L)
{
RandomGenerator::Seed s;
@@ -238,6 +249,70 @@ int w_isConvex(lua_State *L)
return 1;
}
static int getGammaArgs(lua_State *L, float color[4])
{
int numcomponents = 0;
if (lua_istable(L, 1))
{
int n = lua_objlen(L, 1);
for (int i = 1; i <= n && i <= 4; i++)
{
lua_rawgeti(L, 1, i);
color[i - 1] = (float) luaL_checknumber(L, -1) / 255.0;
numcomponents++;
}
lua_pop(L, numcomponents);
}
else
{
int n = lua_gettop(L);
for (int i = 1; i <= n && i <= 4; i++)
{
color[i - 1] = (float) luaL_checknumber(L, i) / 255.0;
numcomponents++;
}
}
if (numcomponents == 0)
luaL_checknumber(L, 1);
return numcomponents;
}
int w_gammaToLinear(lua_State *L)
{
float color[4];
int numcomponents = getGammaArgs(L, color);
for (int i = 0; i < numcomponents; i++)
{
// Alpha should always be linear.
if (i < 3)
color[i] = Math::instance.gammaToLinear(color[i]);
lua_pushnumber(L, color[i] * 255);
}
return numcomponents;
}
int w_linearToGamma(lua_State *L)
{
float color[4];
int numcomponents = getGammaArgs(L, color);
for (int i = 0; i < numcomponents; i++)
{
// Alpha should always be linear.
if (i < 3)
color[i] = Math::instance.linearToGamma(color[i]);
lua_pushnumber(L, color[i] * 255);
}
return numcomponents;
}
int w_noise(lua_State *L)
{
float w, x, y, z;
@@ -277,14 +352,18 @@ int w_noise(lua_State *L)
// List of functions to wrap.
static const luaL_Reg functions[] =
{
{ "setRandomSeed", w_setRandomSeed },
{ "getRandomSeed", w_getRandomSeed },
{ "random", w_random },
{ "randomNormal", w_randomNormal },
{ "setRandomSeed", w_setRandomSeed },
{ "getRandomSeed", w_getRandomSeed },
{ "setRandomState", w_setRandomState },
{ "getRandomState", w_getRandomState },
{ "newRandomGenerator", w_newRandomGenerator },
{ "newBezierCurve", w_newBezierCurve },
{ "triangulate", w_triangulate },
{ "isConvex", w_isConvex },
{ "gammaToLinear", w_gammaToLinear },
{ "linearToGamma", w_linearToGamma },
{ "noise", w_noise },
{ 0, 0 }
};
+6 -2
View File
@@ -30,14 +30,18 @@ namespace love
namespace math
{
int w_setRandomSeed(lua_State *L);
int w_getRandomSeed(lua_State *L);
int w_random(lua_State *L);
int w_randomNormal(lua_State *L);
int w_setRandomSeed(lua_State *L);
int w_getRandomSeed(lua_State *L);
int w_setRandomState(lua_State *L);
int w_getRandomState(lua_State *L);
int w_newRandomGenerator(lua_State *L);
int w_newBezierCurve(lua_State *L);
int w_triangulate(lua_State *L);
int w_isConvex(lua_State *L);
int w_gammaToLinear(lua_State *L);
int w_linearToGamma(lua_State *L);
int w_noise(lua_State *L);
extern "C" LOVE_EXPORT int luaopen_love_math(lua_State *L);
@@ -47,16 +47,8 @@ RandomGenerator::Seed luax_checkrandomseed(lua_State *L, int idx)
if (!lua_isnoneornil(L, idx + 1))
{
uint32 low = checkrandomseed_part<uint32>(L, idx);
uint32 high = checkrandomseed_part<uint32>(L, idx + 1);
#ifdef LOVE_BIG_ENDIAN
s.b32.a = high;
s.b32.b = low;
#else
s.b32.b = high;
s.b32.a = low;
#endif
s.b32.low = checkrandomseed_part<uint32>(L, idx);
s.b32.high = checkrandomseed_part<uint32>(L, idx + 1);
}
else
s.b64 = checkrandomseed_part<uint64>(L, idx);
@@ -95,25 +87,6 @@ RandomGenerator *luax_checkrandomgenerator(lua_State *L, int idx)
return luax_checktype<RandomGenerator>(L, idx, "RandomGenerator", MATH_RANDOM_GENERATOR_T);
}
int w_RandomGenerator_setSeed(lua_State *L)
{
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
EXCEPT_GUARD(rng->setSeed(luax_checkrandomseed(L, 2));)
return 0;
}
int w_RandomGenerator_getSeed(lua_State *L)
{
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
uint32 low = 0, high = 0;
rng->getSeed(low, high);
lua_pushnumber(L, (lua_Number) low);
lua_pushnumber(L, (lua_Number) high);
return 2;
}
int w_RandomGenerator_random(lua_State *L)
{
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
@@ -132,12 +105,44 @@ int w_RandomGenerator_randomNormal(lua_State *L)
return 1;
}
int w_RandomGenerator_setSeed(lua_State *L)
{
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
EXCEPT_GUARD(rng->setSeed(luax_checkrandomseed(L, 2));)
return 0;
}
int w_RandomGenerator_getSeed(lua_State *L)
{
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
RandomGenerator::Seed s = rng->getSeed();
lua_pushnumber(L, (lua_Number) s.b32.low);
lua_pushnumber(L, (lua_Number) s.b32.high);
return 2;
}
int w_RandomGenerator_setState(lua_State *L)
{
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
EXCEPT_GUARD(rng->setState(luax_checkstring(L, 2));)
return 0;
}
int w_RandomGenerator_getState(lua_State *L)
{
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
luax_pushstring(L, rng->getState());
return 1;
}
static const luaL_Reg functions[] =
{
{ "setSeed", w_RandomGenerator_setSeed },
{ "getSeed", w_RandomGenerator_getSeed },
{ "random", w_RandomGenerator_random },
{ "randomNormal", w_RandomGenerator_randomNormal },
{ "setSeed", w_RandomGenerator_setSeed },
{ "getSeed", w_RandomGenerator_getSeed },
{ "setState", w_RandomGenerator_setState },
{ "getState", w_RandomGenerator_getState },
{ 0, 0 }
};
@@ -36,10 +36,12 @@ RandomGenerator::Seed luax_checkrandomseed(lua_State *L, int idx);
int luax_getrandom(lua_State *L, int startidx, double r);
RandomGenerator *luax_checkrandomgenerator(lua_State *L, int idx);
int w_RandomGenerator_setSeed(lua_State *L);
int w_RandomGenerator_getSeed(lua_State *L);
int w_RandomGenerator_random(lua_State *L);
int w_RandomGenerator_randomNormal(lua_State *L);
int w_RandomGenerator_setSeed(lua_State *L);
int w_RandomGenerator_getSeed(lua_State *L);
int w_RandomGenerator_setState(lua_State *L);
int w_RandomGenerator_getState(lua_State *L);
extern "C" int luaopen_randomgenerator(lua_State *L);
} // math
+4
View File
@@ -36,6 +36,7 @@ namespace sdl
// we want them in pixel coordinates (may be different with high-DPI enabled.)
static void windowToPixelCoords(int *x, int *y)
{
#ifndef LOVE_ANDROID
double scale = 1.0;
love::window::Window *window = love::window::sdl::Window::getSingleton();
@@ -47,11 +48,13 @@ static void windowToPixelCoords(int *x, int *y)
if (y != nullptr)
*y = int(double(*y) * scale);
#endif
}
// And vice versa for setting mouse coordinates.
static void pixelToWindowCoords(int *x, int *y)
{
#ifndef LOVE_ANDROID
double scale = 1.0;
love::window::Window *window = love::window::sdl::Window::getSingleton();
@@ -63,6 +66,7 @@ static void pixelToWindowCoords(int *x, int *y)
if (y != nullptr)
*y = int(double(*y) / scale);
#endif
}
const char *Mouse::getName() const
+2
View File
@@ -50,6 +50,7 @@ WindowSettings::WindowSettings()
, centered(true)
, display(0)
, highdpi(false)
, sRGB(false)
{
}
@@ -86,6 +87,7 @@ StringMap<Window::Setting, Window::SETTING_MAX_ENUM>::Entry Window::settingEntri
{"centered", SETTING_CENTERED},
{"display", SETTING_DISPLAY},
{"highdpi", SETTING_HIGHDPI},
{"srgb", SETTING_SRGB},
};
StringMap<Window::Setting, Window::SETTING_MAX_ENUM> Window::settings(Window::settingEntries, sizeof(Window::settingEntries));
+2
View File
@@ -57,6 +57,7 @@ public:
SETTING_CENTERED,
SETTING_DISPLAY,
SETTING_HIGHDPI,
SETTING_SRGB,
SETTING_MAX_ENUM
};
@@ -157,6 +158,7 @@ struct WindowSettings
bool centered; // = true
int display; // = 0
bool highdpi; // false
bool sRGB; // false
}; // WindowSettings
+25 -8
View File
@@ -23,6 +23,10 @@
#include "graphics/Graphics.h"
#include "Window.h"
#ifdef LOVE_ANDROID
#include "common/android.h"
#endif
// C++
#include <iostream>
#include <vector>
@@ -85,7 +89,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
f.minwidth = std::max(f.minwidth, 1);
f.minheight = std::max(f.minheight, 1);
f.display = std::min(std::max(f.display, 0), getDisplayCount());
f.display = std::min(std::max(f.display, 0), getDisplayCount() - 1);
// Use the desktop resolution if a width or height of 0 is specified.
if (width == 0 || height == 0)
@@ -157,7 +161,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
if (!window)
{
// In Windows and Linux, some GL attributes are set on window creation.
setWindowGLAttributes(f.fsaa);
setWindowGLAttributes(f.fsaa, f.sRGB);
const char *title = windowTitle.c_str();
int pos = f.centered ? centeredpos : uncenteredpos;
@@ -193,7 +197,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
SDL_RaiseWindow(window);
if (!setContext(f.fsaa, f.vsync))
if (!setContext(f.fsaa, f.vsync, f.sRGB))
{
created = false;
return false;
@@ -212,7 +216,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
SDL_GL_GetDrawableSize(window, &width, &height);
#endif
if (!gfx->setMode(width, height))
if (!gfx->setMode(width, height, curMode.settings.sRGB))
displayError("Could not set graphics mode", "Unsupported OpenGL version?");
}
@@ -233,7 +237,7 @@ bool Window::onWindowResize(int width, int height)
return true;
}
bool Window::setContext(int fsaa, bool vsync)
bool Window::setContext(int fsaa, bool vsync, bool sRGB)
{
// We would normally only need to recreate the context if FSAA changes or
// SDL_GL_MakeCurrent is unsuccessful, but in Windows MakeCurrent can
@@ -245,7 +249,7 @@ bool Window::setContext(int fsaa, bool vsync)
}
// Make sure the proper attributes are set.
setWindowGLAttributes(fsaa);
setWindowGLAttributes(fsaa, sRGB);
context = SDL_GL_CreateContext(window);
@@ -297,7 +301,7 @@ bool Window::setContext(int fsaa, bool vsync)
return true;
}
void Window::setWindowGLAttributes(int fsaa) const
void Window::setWindowGLAttributes(int fsaa, bool /* sRGB */) const
{
// Set GL window attributes.
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
@@ -311,6 +315,15 @@ void Window::setWindowGLAttributes(int fsaa) const
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
/* FIXME: Enable this code but make sure to try to re-create the window and
* context with this disabled, if creation fails with it enabled.
* We can leave this out for now because in practice the framebuffer will
* already be sRGB-capable (on desktops at least.)
#if SDL_VERSION_ATLEAST(2,0,1)
SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, sRGB ? 1 : 0);
#endif
*/
int contextprofile = 0;
bool tryES2 = false;
@@ -406,6 +419,8 @@ void Window::updateSettings(const WindowSettings &newsettings)
else
#endif
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
curMode.settings.sRGB = newsettings.sRGB;
}
void Window::displayError(const std::string &title, const std::string &text) const
@@ -671,7 +686,9 @@ double Window::getPixelScale() const
{
double scale = 1.0;
#if SDL_VERSION_ATLEAST(2,0,1)
#ifdef LOVE_ANDROID
scale = love::android::getScreenScale();
#elif SDL_VERSION_ATLEAST(2,0,1)
if (window)
{
int wheight;
+2 -2
View File
@@ -90,8 +90,8 @@ public:
private:
bool setContext(int fsaa, bool vsync);
void setWindowGLAttributes(int fsaa) const;
bool setContext(int fsaa, bool vsync, bool sRGB);
void setWindowGLAttributes(int fsaa, bool sRGB) const;
// Update the saved window settings based on the window's actual state.
void updateSettings(const WindowSettings &newsettings);
@@ -96,6 +96,7 @@ int w_setMode(lua_State *L)
settings.centered = luax_boolflag(L, 3, settingName(Window::SETTING_CENTERED), true);
settings.display = luax_intflag(L, 3, settingName(Window::SETTING_DISPLAY), 1);
settings.highdpi = luax_boolflag(L, 3, settingName(Window::SETTING_HIGHDPI), false);
settings.sRGB = luax_boolflag(L, 3, settingName(Window::SETTING_SRGB), false);
// Display index is 1-based in Lua and 0-based internally.
settings.display--;
@@ -151,6 +152,9 @@ int w_getMode(lua_State *L)
luax_pushboolean(L, settings.highdpi);
lua_setfield(L, -2, settingName(Window::SETTING_HIGHDPI));
luax_pushboolean(L, settings.sRGB);
lua_setfield(L, -2, settingName(Window::SETTING_SRGB));
return 3;
}
+2 -2
View File
@@ -313,9 +313,9 @@ function love.init()
resizable = false,
centered = true,
highdpi = false,
srgb = false,
},
modules = {
android = true,
event = true,
keyboard = true,
mouse = true,
@@ -364,7 +364,6 @@ function love.init()
-- Gets desired modules.
for k,v in ipairs{
"android",
"thread",
"timer",
"event",
@@ -406,6 +405,7 @@ function love.init()
centered = c.window.centered,
display = c.window.display,
highdpi = c.window.highdpi,
srgb = c.window.srgb,
}), "Could not set window mode")
love.window.setTitle(c.window.title or c.title)
if c.window.icon then
+3 -2
View File
@@ -570,9 +570,9 @@ const unsigned char boot_lua[] =
0x2c, 0x0a,
0x09, 0x09, 0x09, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65,
0x2c, 0x0a,
0x09, 0x09, 0x09, 0x73, 0x72, 0x67, 0x62, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x7d, 0x2c, 0x0a,
0x09, 0x09, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
0x09, 0x09, 0x09, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65,
0x2c, 0x0a,
@@ -645,7 +645,6 @@ const unsigned char boot_lua[] =
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x0a,
0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73,
0x7b, 0x0a,
0x09, 0x09, 0x22, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x22, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x22, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x2c, 0x0a,
@@ -707,6 +706,8 @@ const unsigned char boot_lua[] =
0x64, 0x6f, 0x77, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e,
0x64, 0x6f, 0x77, 0x2e, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x73, 0x72, 0x67, 0x62, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77,
0x2e, 0x73, 0x72, 0x67, 0x62, 0x2c, 0x0a,
0x09, 0x09, 0x7d, 0x29, 0x2c, 0x20, 0x22, 0x43, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73,
0x65, 0x74, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x29, 0x0a,
0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x65, 0x74, 0x54,
+1 -1
View File
@@ -25,4 +25,4 @@ LOCAL_SRC_FILES := \
# $(info libmpg123: include dirs $(LOCAL_C_INCLUDES))
# $(info libmpg123: src files $(LOCAL_SRC_FILES))
include $(BUILD_STATIC_LIBRARY)
include $(BUILD_SHARED_LIBRARY)
+3 -5
View File
@@ -16,6 +16,7 @@ LOCAL_C_INCLUDES := \
LOCAL_SRC_FILES := \
$(filter-out \
Alc/mixer_neon.c \
Alc/mixer_inc.c \
Alc/mixer_sse.c \
, $(subst $(LOCAL_PATH)/,,\
${LOCAL_PATH}/Alc/backends/base.c \
@@ -29,9 +30,6 @@ LOCAL_SRC_FILES := \
$(wildcard ${LOCAL_PATH}/OpenAL32/*.c) \
))
# $(info libopenal: include dirs $(LOCAL_C_INCLUDES))
# $(info libopenal: src files $(LOCAL_SRC_FILES))
LOCAL_LDLIBS := -lOpenSLES
LOCAL_LDLIBS := -llog -lOpenSLES
include $(BUILD_STATIC_LIBRARY)
include $(BUILD_SHARED_LIBRARY)
-5
View File
@@ -1,5 +0,0 @@
repo: 7672c9962ce627edaaa67ff54fe4ad8f9a46dc2b
node: f94eec5e90540889a42c34a27931b8266f4af52c
branch: stable-2.0
latesttag: release-2.0.3
latesttagdistance: 1
-407
View File
@@ -1,407 +0,0 @@
# PhysicsFS; a portable, flexible file i/o abstraction.
# Copyright (C) 2007 Ryan C. Gordon.
#
# Please see the file LICENSE.txt in the source's root directory.
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
PROJECT(PhysicsFS)
SET(PHYSFS_VERSION 2.0.3)
# Increment this if/when we break backwards compatibility.
SET(PHYSFS_SOVERSION 1)
# I hate that they define "WIN32" ... we're about to move to Win64...I hope!
IF(WIN32 AND NOT WINDOWS)
SET(WINDOWS TRUE)
ENDIF(WIN32 AND NOT WINDOWS)
# Bleh, let's do it for "APPLE" too.
IF(APPLE AND NOT MACOSX)
SET(MACOSX TRUE)
ENDIF(APPLE AND NOT MACOSX)
# For now, Haiku and BeOS are the same, as far as the build system cares.
IF(HAIKU AND NOT BEOS)
SET(BEOS TRUE)
ENDIF(HAIKU AND NOT BEOS)
INCLUDE(CheckIncludeFile)
INCLUDE(CheckLibraryExists)
INCLUDE(CheckCSourceCompiles)
INCLUDE_DIRECTORIES(.)
#INCLUDE_DIRECTORIES(platform)
#INCLUDE_DIRECTORIES(archivers)
IF(MACOSX)
# Fallback to older OS X on PowerPC to support wider range of systems...
IF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
ADD_DEFINITIONS(-DMAC_OS_X_VERSION_MIN_REQUIRED=1020)
SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -mmacosx-version-min=10.2")
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
# Need these everywhere...
ADD_DEFINITIONS(-fno-common)
SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -framework Carbon -framework IOKit")
ENDIF(MACOSX)
# Add some gcc-specific command lines.
IF(CMAKE_COMPILER_IS_GNUCC)
# Always build with debug symbols...you can strip it later.
ADD_DEFINITIONS(-g -pipe -Werror -fsigned-char)
# Stupid BeOS generates warnings in the system headers.
IF(NOT BEOS)
ADD_DEFINITIONS(-Wall)
ENDIF(NOT BEOS)
CHECK_C_SOURCE_COMPILES("
#if ((defined(__GNUC__)) && (__GNUC__ >= 4))
int main(int argc, char **argv) { int is_gcc4 = 1; return 0; }
#else
#error This is not gcc4.
#endif
" PHYSFS_IS_GCC4)
IF(PHYSFS_IS_GCC4)
# Not supported on several operating systems at this time.
IF(NOT OS2 AND NOT SOLARIS AND NOT WINDOWS)
ADD_DEFINITIONS(-fvisibility=hidden)
ENDIF(NOT OS2 AND NOT SOLARIS AND NOT WINDOWS)
ENDIF(PHYSFS_IS_GCC4)
ENDIF(CMAKE_COMPILER_IS_GNUCC)
IF(MSVC)
# VS.NET 8.0 got really really anal about strcpy, etc, which even if we
# cleaned up our code, zlib, etc still use...so disable the warning.
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1)
ENDIF(MSVC)
# Basic chunks of source code ...
SET(ZLIB_SRCS
zlib123/adler32.c
zlib123/compress.c
zlib123/crc32.c
zlib123/deflate.c
zlib123/gzio.c
zlib123/infback.c
zlib123/inffast.c
zlib123/inflate.c
zlib123/inftrees.c
zlib123/trees.c
zlib123/uncompr.c
zlib123/zutil.c
)
SET(LZMA_SRCS
lzma/C/7zCrc.c
lzma/C/Archive/7z/7zBuffer.c
lzma/C/Archive/7z/7zDecode.c
lzma/C/Archive/7z/7zExtract.c
lzma/C/Archive/7z/7zHeader.c
lzma/C/Archive/7z/7zIn.c
lzma/C/Archive/7z/7zItem.c
lzma/C/Archive/7z/7zMethodID.c
lzma/C/Compress/Branch/BranchX86.c
lzma/C/Compress/Branch/BranchX86_2.c
lzma/C/Compress/Lzma/LzmaDecode.c
)
IF(BEOS)
# We add this explicitly, since we don't want CMake to think this
# is a C++ project unless we're on BeOS.
SET(PHYSFS_BEOS_SRCS platform/beos.cpp)
FIND_LIBRARY(BE_LIBRARY be)
FIND_LIBRARY(ROOT_LIBRARY root)
SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${BE_LIBRARY} ${ROOT_LIBRARY})
ENDIF(BEOS)
# Almost everything is "compiled" here, but things that don't apply to the
# build are #ifdef'd out. This is to make it easy to embed PhysicsFS into
# another project or bring up a new build system: just compile all the source
# code and #define the things you want.
SET(PHYSFS_SRCS
physfs.c
physfs_byteorder.c
physfs_unicode.c
platform/os2.c
platform/pocketpc.c
platform/posix.c
platform/unix.c
platform/macosx.c
platform/windows.c
archivers/dir.c
archivers/grp.c
archivers/hog.c
archivers/lzma.c
archivers/mvl.c
archivers/qpak.c
archivers/wad.c
archivers/zip.c
${PHYSFS_BEOS_SRCS}
)
# platform layers ...
IF(UNIX)
IF(BEOS)
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
SET(HAVE_PTHREAD_H TRUE)
ELSE(BEOS)
# !!! FIXME
# AC_DEFINE([PHYSFS_HAVE_LLSEEK], 1, [define if we have llseek])
CHECK_INCLUDE_FILE(sys/ucred.h HAVE_UCRED_H)
IF(HAVE_UCRED_H)
ADD_DEFINITIONS(-DPHYSFS_HAVE_SYS_UCRED_H=1)
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
ENDIF(HAVE_UCRED_H)
CHECK_INCLUDE_FILE(mntent.h HAVE_MNTENT_H)
IF(HAVE_MNTENT_H)
ADD_DEFINITIONS(-DPHYSFS_HAVE_MNTENT_H=1)
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
ENDIF(HAVE_MNTENT_H)
CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
IF(HAVE_PTHREAD_H)
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
ENDIF(HAVE_PTHREAD_H)
ENDIF(BEOS)
ENDIF(UNIX)
IF(WINDOWS)
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
ENDIF(WINDOWS)
IF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
ADD_DEFINITIONS(-DPHYSFS_NO_CDROM_SUPPORT=1)
MESSAGE(WARNING " ***")
MESSAGE(WARNING " *** There is no CD-ROM support in this build!")
MESSAGE(WARNING " *** PhysicsFS will just pretend there are no discs.")
MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
MESSAGE(WARNING " *** but is this what you REALLY wanted?")
MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
MESSAGE(WARNING " ***")
ENDIF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
IF(PHYSFS_HAVE_THREAD_SUPPORT)
ADD_DEFINITIONS(-D_REENTRANT -D_THREAD_SAFE)
ELSE(PHYSFS_HAVE_THREAD_SUPPORT)
ADD_DEFINITIONS(-DPHYSFS_NO_THREAD_SUPPORT=1)
MESSAGE(WARNING " ***")
MESSAGE(WARNING " *** There is no thread support in this build!")
MESSAGE(WARNING " *** PhysicsFS will NOT be reentrant!")
MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
MESSAGE(WARNING " *** but is this what you REALLY wanted?")
MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
MESSAGE(WARNING " ***")
ENDIF(PHYSFS_HAVE_THREAD_SUPPORT)
CHECK_INCLUDE_FILE(assert.h HAVE_ASSERT_H)
IF(HAVE_ASSERT_H)
ADD_DEFINITIONS(-DHAVE_ASSERT_H=1)
ENDIF(HAVE_ASSERT_H)
# Archivers ...
OPTION(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" TRUE)
IF(PHYSFS_ARCHIVE_ZIP)
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_ZIP=1)
SET(PHYSFS_NEED_ZLIB TRUE)
ENDIF(PHYSFS_ARCHIVE_ZIP)
OPTION(PHYSFS_ARCHIVE_7Z "Enable 7zip support" TRUE)
IF(PHYSFS_ARCHIVE_7Z)
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_7Z=1)
# !!! FIXME: rename to 7z.c?
SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${LZMA_SRCS})
ENDIF(PHYSFS_ARCHIVE_7Z)
OPTION(PHYSFS_ARCHIVE_GRP "Enable Build Engine GRP support" TRUE)
IF(PHYSFS_ARCHIVE_GRP)
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_GRP=1)
ENDIF(PHYSFS_ARCHIVE_GRP)
OPTION(PHYSFS_ARCHIVE_WAD "Enable Doom WAD support" TRUE)
IF(PHYSFS_ARCHIVE_WAD)
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_WAD=1)
ENDIF(PHYSFS_ARCHIVE_WAD)
OPTION(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE)
IF(PHYSFS_ARCHIVE_HOG)
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_HOG=1)
ENDIF(PHYSFS_ARCHIVE_HOG)
OPTION(PHYSFS_ARCHIVE_MVL "Enable Descent I/II MVL support" TRUE)
IF(PHYSFS_ARCHIVE_MVL)
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_MVL=1)
ENDIF(PHYSFS_ARCHIVE_MVL)
OPTION(PHYSFS_ARCHIVE_QPAK "Enable Quake I/II QPAK support" TRUE)
IF(PHYSFS_ARCHIVE_QPAK)
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_QPAK=1)
ENDIF(PHYSFS_ARCHIVE_QPAK)
# See if some archiver required zlib, and see about using system version.
IF(PHYSFS_NEED_ZLIB)
FIND_PACKAGE(ZLIB)
IF(ZLIB_FOUND)
OPTION(PHYSFS_INTERNAL_ZLIB "Link own zlib instead of system library" FALSE)
ELSE(HAVE_SYSTEM_ZLIB)
SET(PHYSFS_INTERNAL_ZLIB TRUE)
ENDIF(ZLIB_FOUND)
IF(PHYSFS_INTERNAL_ZLIB)
INCLUDE_DIRECTORIES(zlib123)
ADD_DEFINITIONS(-DZ_PREFIX=1)
SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${ZLIB_SRCS})
ELSE(PHYSFS_INTERNAL_ZLIB)
SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${ZLIB_LIBRARY})
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
ENDIF(PHYSFS_INTERNAL_ZLIB)
ENDIF(PHYSFS_NEED_ZLIB)
OPTION(PHYSFS_BUILD_STATIC "Build static library" TRUE)
IF(PHYSFS_BUILD_STATIC)
ADD_LIBRARY(physfs-static STATIC ${PHYSFS_SRCS})
SET_TARGET_PROPERTIES(physfs-static PROPERTIES OUTPUT_NAME "physfs")
SET(PHYSFS_LIB_TARGET physfs-static)
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs-static")
ENDIF(PHYSFS_BUILD_STATIC)
OPTION(PHYSFS_BUILD_SHARED "Build shared library" TRUE)
IF(PHYSFS_BUILD_SHARED)
ADD_LIBRARY(physfs SHARED ${PHYSFS_SRCS})
SET_TARGET_PROPERTIES(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
SET_TARGET_PROPERTIES(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
TARGET_LINK_LIBRARIES(physfs ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
SET(PHYSFS_LIB_TARGET physfs)
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
ENDIF(PHYSFS_BUILD_SHARED)
IF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
MESSAGE(FATAL "Both shared and static libraries are disabled!")
ENDIF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
# CMake FAQ says I need this...
IF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
SET_TARGET_PROPERTIES(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(physfs-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
ENDIF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
OPTION(PHYSFS_BUILD_TEST "Build stdio test program." TRUE)
MARK_AS_ADVANCED(PHYSFS_BUILD_TEST)
IF(PHYSFS_BUILD_TEST)
FIND_PATH(READLINE_H readline/readline.h)
FIND_PATH(HISTORY_H readline/history.h)
IF(READLINE_H AND HISTORY_H)
FIND_LIBRARY(CURSES_LIBRARY NAMES curses ncurses)
SET(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
FIND_LIBRARY(READLINE_LIBRARY readline)
IF(READLINE_LIBRARY)
SET(HAVE_SYSTEM_READLINE TRUE)
SET(TEST_PHYSFS_LIBS ${TEST_PHYSFS_LIBS} ${READLINE_LIBRARY} ${CURSES_LIBRARY})
INCLUDE_DIRECTORIES(${READLINE_H} ${HISTORY_H})
ADD_DEFINITIONS(-DPHYSFS_HAVE_READLINE=1)
ENDIF(READLINE_LIBRARY)
ENDIF(READLINE_H AND HISTORY_H)
ADD_EXECUTABLE(test_physfs test/test_physfs.c)
TARGET_LINK_LIBRARIES(test_physfs ${PHYSFS_LIB_TARGET} ${TEST_PHYSFS_LIBS} ${OTHER_LDFLAGS})
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";test_physfs")
ENDIF(PHYSFS_BUILD_TEST)
OPTION(PHYSFS_BUILD_WX_TEST "Build wxWidgets test program." FALSE)
MARK_AS_ADVANCED(PHYSFS_BUILD_WX_TEST)
IF(PHYSFS_BUILD_WX_TEST)
SET(wxWidgets_USE_LIBS base core adv)
SET(wxWidgets_INCLUDE_DIRS_NO_SYSTEM 1)
FIND_PACKAGE(wxWidgets)
IF(wxWidgets_FOUND)
INCLUDE(${wxWidgets_USE_FILE})
ADD_EXECUTABLE(wxtest_physfs test/wxtest_physfs.cpp)
SET_SOURCE_FILES_PROPERTIES(test/wxtest_physfs.cpp COMPILE_FLAGS ${wxWidgets_CXX_FLAGS})
TARGET_LINK_LIBRARIES(wxtest_physfs ${PHYSFS_LIB_TARGET} ${wxWidgets_LIBRARIES} ${OTHER_LDFLAGS})
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";wxtest_physfs")
ELSE(wxWidgets_FOUND)
MESSAGE(STATUS "wxWidgets not found. Disabling wx test app.")
SET(PHYSFS_BUILD_WX_TEST FALSE)
ENDIF(wxWidgets_FOUND)
ENDIF(PHYSFS_BUILD_WX_TEST)
INSTALL(TARGETS ${PHYSFS_INSTALL_TARGETS}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
INSTALL(FILES physfs.h DESTINATION include)
FIND_PACKAGE(Doxygen)
IF(DOXYGEN_FOUND)
SET(PHYSFS_OUTPUT_DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile"
"${PHYSFS_OUTPUT_DOXYFILE}"
COPYONLY
)
FILE(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n\n# Below auto-generated by cmake...\n\n")
FILE(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "PROJECT_NUMBER = ${PHYSFS_VERSION}\n")
FILE(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "OUTPUT_DIRECTORY = ${CMAKE_CURRENT_BINARY_DIR}/docs\n")
FILE(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n# End auto-generated section.\n\n")
ADD_CUSTOM_TARGET(
docs
${DOXYGEN_EXECUTABLE} "${PHYSFS_OUTPUT_DOXYFILE}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Building documentation in 'docs' directory..."
)
ELSE(DOXYGEN_FOUND)
MESSAGE(STATUS "Doxygen not found. You won't be able to build documentation.")
ENDIF(DOXYGEN_FOUND)
IF(UNIX)
SET(PHYSFS_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../physfs-${PHYSFS_VERSION}.tar.bz2")
ADD_CUSTOM_TARGET(
dist
hg archive -t tbz2 "${PHYSFS_TARBALL}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Building source tarball '${PHYSFS_TARBALL}'..."
)
ENDIF(UNIX)
MACRO(MESSAGE_BOOL_OPTION _NAME _VALUE)
IF(${_VALUE})
MESSAGE(STATUS " ${_NAME}: enabled")
ELSE(${_VALUE})
MESSAGE(STATUS " ${_NAME}: disabled")
ENDIF(${_VALUE})
ENDMACRO(MESSAGE_BOOL_OPTION)
MESSAGE(STATUS "PhysicsFS will build with the following options:")
MESSAGE_BOOL_OPTION("ZIP support" PHYSFS_ARCHIVE_ZIP)
MESSAGE_BOOL_OPTION("7zip support" PHYSFS_ARCHIVE_7Z)
MESSAGE_BOOL_OPTION("GRP support" PHYSFS_ARCHIVE_GRP)
MESSAGE_BOOL_OPTION("WAD support" PHYSFS_ARCHIVE_WAD)
MESSAGE_BOOL_OPTION("HOG support" PHYSFS_ARCHIVE_HOG)
MESSAGE_BOOL_OPTION("MVL support" PHYSFS_ARCHIVE_MVL)
MESSAGE_BOOL_OPTION("QPAK support" PHYSFS_ARCHIVE_QPAK)
MESSAGE_BOOL_OPTION("CD-ROM drive support" PHYSFS_HAVE_CDROM_SUPPORT)
MESSAGE_BOOL_OPTION("Thread safety" PHYSFS_HAVE_THREAD_SUPPORT)
MESSAGE_BOOL_OPTION("Build own zlib" PHYSFS_INTERNAL_ZLIB)
MESSAGE_BOOL_OPTION("Build static library" PHYSFS_BUILD_STATIC)
MESSAGE_BOOL_OPTION("Build shared library" PHYSFS_BUILD_SHARED)
MESSAGE_BOOL_OPTION("Build wxWidgets test program" PHYSFS_BUILD_WX_TEST)
MESSAGE_BOOL_OPTION("Build stdio test program" PHYSFS_BUILD_TEST)
IF(PHYSFS_BUILD_TEST)
MESSAGE_BOOL_OPTION(" Use readline in test program" HAVE_SYSTEM_READLINE)
ENDIF(PHYSFS_BUILD_TEST)
# end of CMakeLists.txt ...
-45
View File
@@ -1,45 +0,0 @@
Stuff that needs to be done and wishlist:
These are in no particular order.
Some might be dupes, some might be done already.
UNICODE:
- OS/2: Codepages. No full Unicode in the filesystem, but we can probably make
a conversion effort.
Stuff:
- Other archivers: perhaps tar(.gz|.bz2), RPM, ARJ, etc. These are less
important, since streaming archives aren't of much value to games (which
is why zipfiles are king: random access), but it could have uses for, say,
an installer/updater.
- Reduce malloc() pressure all over the place. We fragment memory like mad.
- profile string list interpolation.
- We have two different ways to find dir entries in zip.c.
- Do symlinks in zip archiver work when they point to dirs?
- Enable more warnings?
- Use __cdecl in physfs.h?
- Look for FIXMEs (many marked with "!!!" in comments).
- Find some way to relax or remove the security model for external tools.
- OSX shouldn't use ~/.app for userdir.
- fscanf and fprintf support in extras dir.
- Why do we call it openArchive and dirClose?
- Sanity check byte order at runtime.
- Memory locking?
- Find a better name than dvoid and fvoid.
- Can windows.c and pocketpc.c get merged?
- There's so much cut-and-paste between archivers...can this be reduced?
- General code audit.
- Multiple write dirs with mount points?
- Deprecate PHYSFS_setSaneConfig and move it to extras?
- Why is physfsrwops.c cut-and-pasted into the ruby bindings?
- Replace code from SDL...
- Should file enumeration return an error or set error state?
- Need "getmountpoint" command in test_physfs.c ...
- Look for calloc() calls that aren't going through the allocation hooks.
- Write up a simple HOWTO on embedding physicsfs in another project.
- Archivers need abstracted i/o to read from memory or files (archives in archives?)
- Probably other stuff. Requests and recommendations are welcome.
// end of TODO.txt ...
-283
View File
@@ -1,283 +0,0 @@
/*
* Standard directory I/O support routines for PhysicsFS.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "physfs.h"
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
static PHYSFS_sint64 DIR_read(fvoid *opaque, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
PHYSFS_sint64 retval;
retval = __PHYSFS_platformRead(opaque, buffer, objSize, objCount);
return(retval);
} /* DIR_read */
static PHYSFS_sint64 DIR_write(fvoid *opaque, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
PHYSFS_sint64 retval;
retval = __PHYSFS_platformWrite(opaque, buffer, objSize, objCount);
return(retval);
} /* DIR_write */
static int DIR_eof(fvoid *opaque)
{
return(__PHYSFS_platformEOF(opaque));
} /* DIR_eof */
static PHYSFS_sint64 DIR_tell(fvoid *opaque)
{
return(__PHYSFS_platformTell(opaque));
} /* DIR_tell */
static int DIR_seek(fvoid *opaque, PHYSFS_uint64 offset)
{
return(__PHYSFS_platformSeek(opaque, offset));
} /* DIR_seek */
static PHYSFS_sint64 DIR_fileLength(fvoid *opaque)
{
return(__PHYSFS_platformFileLength(opaque));
} /* DIR_fileLength */
static int DIR_fileClose(fvoid *opaque)
{
/*
* we manually flush the buffer, since that's the place a close will
* most likely fail, but that will leave the file handle in an undefined
* state if it fails. Flush failures we can recover from.
*/
BAIL_IF_MACRO(!__PHYSFS_platformFlush(opaque), NULL, 0);
BAIL_IF_MACRO(!__PHYSFS_platformClose(opaque), NULL, 0);
return(1);
} /* DIR_fileClose */
static int DIR_isArchive(const char *filename, int forWriting)
{
/* directories ARE archives in this driver... */
return(__PHYSFS_platformIsDirectory(filename));
} /* DIR_isArchive */
static void *DIR_openArchive(const char *name, int forWriting)
{
const char *dirsep = PHYSFS_getDirSeparator();
char *retval = NULL;
size_t namelen = strlen(name);
size_t seplen = strlen(dirsep);
/* !!! FIXME: when is this not called right before openArchive? */
BAIL_IF_MACRO(!DIR_isArchive(name, forWriting),
ERR_UNSUPPORTED_ARCHIVE, 0);
retval = allocator.Malloc(namelen + seplen + 1);
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
/* make sure there's a dir separator at the end of the string */
strcpy(retval, name);
if (strcmp((name + namelen) - seplen, dirsep) != 0)
strcat(retval, dirsep);
return(retval);
} /* DIR_openArchive */
static void DIR_enumerateFiles(dvoid *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
char *d = __PHYSFS_platformCvtToDependent((char *)opaque, dname, NULL);
if (d != NULL)
{
__PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
origdir, callbackdata);
allocator.Free(d);
} /* if */
} /* DIR_enumerateFiles */
static int DIR_exists(dvoid *opaque, const char *name)
{
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
retval = __PHYSFS_platformExists(f);
allocator.Free(f);
return(retval);
} /* DIR_exists */
static int DIR_isDirectory(dvoid *opaque, const char *name, int *fileExists)
{
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
int retval = 0;
BAIL_IF_MACRO(d == NULL, NULL, 0);
*fileExists = __PHYSFS_platformExists(d);
if (*fileExists)
retval = __PHYSFS_platformIsDirectory(d);
allocator.Free(d);
return(retval);
} /* DIR_isDirectory */
static int DIR_isSymLink(dvoid *opaque, const char *name, int *fileExists)
{
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
int retval = 0;
BAIL_IF_MACRO(f == NULL, NULL, 0);
*fileExists = __PHYSFS_platformExists(f);
if (*fileExists)
retval = __PHYSFS_platformIsSymLink(f);
allocator.Free(f);
return(retval);
} /* DIR_isSymLink */
static PHYSFS_sint64 DIR_getLastModTime(dvoid *opaque,
const char *name,
int *fileExists)
{
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
PHYSFS_sint64 retval = -1;
BAIL_IF_MACRO(d == NULL, NULL, 0);
*fileExists = __PHYSFS_platformExists(d);
if (*fileExists)
retval = __PHYSFS_platformGetLastModTime(d);
allocator.Free(d);
return(retval);
} /* DIR_getLastModTime */
static fvoid *doOpen(dvoid *opaque, const char *name,
void *(*openFunc)(const char *filename),
int *fileExists)
{
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
void *rc = NULL;
BAIL_IF_MACRO(f == NULL, NULL, NULL);
if (fileExists != NULL)
{
*fileExists = __PHYSFS_platformExists(f);
if (!(*fileExists))
{
allocator.Free(f);
return(NULL);
} /* if */
} /* if */
rc = openFunc(f);
allocator.Free(f);
return((fvoid *) rc);
} /* doOpen */
static fvoid *DIR_openRead(dvoid *opaque, const char *fnm, int *exist)
{
return(doOpen(opaque, fnm, __PHYSFS_platformOpenRead, exist));
} /* DIR_openRead */
static fvoid *DIR_openWrite(dvoid *opaque, const char *filename)
{
return(doOpen(opaque, filename, __PHYSFS_platformOpenWrite, NULL));
} /* DIR_openWrite */
static fvoid *DIR_openAppend(dvoid *opaque, const char *filename)
{
return(doOpen(opaque, filename, __PHYSFS_platformOpenAppend, NULL));
} /* DIR_openAppend */
static int DIR_remove(dvoid *opaque, const char *name)
{
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
retval = __PHYSFS_platformDelete(f);
allocator.Free(f);
return(retval);
} /* DIR_remove */
static int DIR_mkdir(dvoid *opaque, const char *name)
{
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
retval = __PHYSFS_platformMkDir(f);
allocator.Free(f);
return(retval);
} /* DIR_mkdir */
static void DIR_dirClose(dvoid *opaque)
{
allocator.Free(opaque);
} /* DIR_dirClose */
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_DIR =
{
"",
DIR_ARCHIVE_DESCRIPTION,
"Ryan C. Gordon <icculus@icculus.org>",
"http://icculus.org/physfs/",
};
const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
{
&__PHYSFS_ArchiveInfo_DIR,
DIR_isArchive, /* isArchive() method */
DIR_openArchive, /* openArchive() method */
DIR_enumerateFiles, /* enumerateFiles() method */
DIR_exists, /* exists() method */
DIR_isDirectory, /* isDirectory() method */
DIR_isSymLink, /* isSymLink() method */
DIR_getLastModTime, /* getLastModTime() method */
DIR_openRead, /* openRead() method */
DIR_openWrite, /* openWrite() method */
DIR_openAppend, /* openAppend() method */
DIR_remove, /* remove() method */
DIR_mkdir, /* mkdir() method */
DIR_dirClose, /* dirClose() method */
DIR_read, /* read() method */
DIR_write, /* write() method */
DIR_eof, /* eof() method */
DIR_tell, /* tell() method */
DIR_seek, /* seek() method */
DIR_fileLength, /* fileLength() method */
DIR_fileClose /* fileClose() method */
};
/* end of dir.c ... */
-475
View File
@@ -1,475 +0,0 @@
/*
* GRP support routines for PhysicsFS.
*
* This driver handles BUILD engine archives ("groupfiles"). This format
* (but not this driver) was put together by Ken Silverman.
*
* The format is simple enough. In Ken's words:
*
* What's the .GRP file format?
*
* The ".grp" file format is just a collection of a lot of files stored
* into 1 big one. I tried to make the format as simple as possible: The
* first 12 bytes contains my name, "KenSilverman". The next 4 bytes is
* the number of files that were compacted into the group file. Then for
* each file, there is a 16 byte structure, where the first 12 bytes are
* the filename, and the last 4 bytes are the file's size. The rest of
* the group file is just the raw data packed one after the other in the
* same order as the list of files.
*
* (That info is from http://www.advsys.net/ken/build.htm ...)
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
#if (defined PHYSFS_SUPPORTS_GRP)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "physfs.h"
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
typedef struct
{
char name[13];
PHYSFS_uint32 startPos;
PHYSFS_uint32 size;
} GRPentry;
typedef struct
{
char *filename;
PHYSFS_sint64 last_mod_time;
PHYSFS_uint32 entryCount;
GRPentry *entries;
} GRPinfo;
typedef struct
{
void *handle;
GRPentry *entry;
PHYSFS_uint32 curPos;
} GRPfileinfo;
static void GRP_dirClose(dvoid *opaque)
{
GRPinfo *info = ((GRPinfo *) opaque);
allocator.Free(info->filename);
allocator.Free(info->entries);
allocator.Free(info);
} /* GRP_dirClose */
static PHYSFS_sint64 GRP_read(fvoid *opaque, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
GRPentry *entry = finfo->entry;
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
PHYSFS_sint64 rc;
if (objsLeft < objCount)
objCount = objsLeft;
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
if (rc > 0)
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
return(rc);
} /* GRP_read */
static PHYSFS_sint64 GRP_write(fvoid *opaque, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* GRP_write */
static int GRP_eof(fvoid *opaque)
{
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
GRPentry *entry = finfo->entry;
return(finfo->curPos >= entry->size);
} /* GRP_eof */
static PHYSFS_sint64 GRP_tell(fvoid *opaque)
{
return(((GRPfileinfo *) opaque)->curPos);
} /* GRP_tell */
static int GRP_seek(fvoid *opaque, PHYSFS_uint64 offset)
{
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
GRPentry *entry = finfo->entry;
int rc;
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
if (rc)
finfo->curPos = (PHYSFS_uint32) offset;
return(rc);
} /* GRP_seek */
static PHYSFS_sint64 GRP_fileLength(fvoid *opaque)
{
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
return((PHYSFS_sint64) finfo->entry->size);
} /* GRP_fileLength */
static int GRP_fileClose(fvoid *opaque)
{
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
allocator.Free(finfo);
return(1);
} /* GRP_fileClose */
static int grp_open(const char *filename, int forWriting,
void **fh, PHYSFS_uint32 *count)
{
PHYSFS_uint8 buf[12];
*fh = NULL;
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
*fh = __PHYSFS_platformOpenRead(filename);
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
if (__PHYSFS_platformRead(*fh, buf, 12, 1) != 1)
goto openGrp_failed;
if (memcmp(buf, "KenSilverman", 12) != 0)
{
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
goto openGrp_failed;
} /* if */
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
goto openGrp_failed;
*count = PHYSFS_swapULE32(*count);
return(1);
openGrp_failed:
if (*fh != NULL)
__PHYSFS_platformClose(*fh);
*count = -1;
*fh = NULL;
return(0);
} /* grp_open */
static int GRP_isArchive(const char *filename, int forWriting)
{
void *fh;
PHYSFS_uint32 fileCount;
int retval = grp_open(filename, forWriting, &fh, &fileCount);
if (fh != NULL)
__PHYSFS_platformClose(fh);
return(retval);
} /* GRP_isArchive */
static int grp_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
const GRPentry *a = (const GRPentry *) _a;
return(strcmp(a[one].name, a[two].name));
} /* if */
return 0;
} /* grp_entry_cmp */
static void grp_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
GRPentry tmp;
GRPentry *first = &(((GRPentry *) _a)[one]);
GRPentry *second = &(((GRPentry *) _a)[two]);
memcpy(&tmp, first, sizeof (GRPentry));
memcpy(first, second, sizeof (GRPentry));
memcpy(second, &tmp, sizeof (GRPentry));
} /* if */
} /* grp_entry_swap */
static int grp_load_entries(const char *name, int forWriting, GRPinfo *info)
{
void *fh = NULL;
PHYSFS_uint32 fileCount;
PHYSFS_uint32 location = 16; /* sizeof sig. */
GRPentry *entry;
char *ptr;
BAIL_IF_MACRO(!grp_open(name, forWriting, &fh, &fileCount), NULL, 0);
info->entryCount = fileCount;
info->entries = (GRPentry *) allocator.Malloc(sizeof(GRPentry)*fileCount);
if (info->entries == NULL)
{
__PHYSFS_platformClose(fh);
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
} /* if */
location += (16 * fileCount);
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
{
if (__PHYSFS_platformRead(fh, &entry->name, 12, 1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
entry->name[12] = '\0'; /* name isn't null-terminated in file. */
if ((ptr = strchr(entry->name, ' ')) != NULL)
*ptr = '\0'; /* trim extra spaces. */
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
entry->size = PHYSFS_swapULE32(entry->size);
entry->startPos = location;
location += entry->size;
} /* for */
__PHYSFS_platformClose(fh);
__PHYSFS_sort(info->entries, info->entryCount,
grp_entry_cmp, grp_entry_swap);
return(1);
} /* grp_load_entries */
static void *GRP_openArchive(const char *name, int forWriting)
{
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
GRPinfo *info = (GRPinfo *) allocator.Malloc(sizeof (GRPinfo));
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, 0);
memset(info, '\0', sizeof (GRPinfo));
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, GRP_openArchive_failed);
if (!grp_load_entries(name, forWriting, info))
goto GRP_openArchive_failed;
strcpy(info->filename, name);
info->last_mod_time = modtime;
return(info);
GRP_openArchive_failed:
if (info != NULL)
{
if (info->filename != NULL)
allocator.Free(info->filename);
if (info->entries != NULL)
allocator.Free(info->entries);
allocator.Free(info);
} /* if */
return(NULL);
} /* GRP_openArchive */
static void GRP_enumerateFiles(dvoid *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
/* no directories in GRP files. */
if (*dname == '\0')
{
GRPinfo *info = (GRPinfo *) opaque;
GRPentry *entry = info->entries;
PHYSFS_uint32 max = info->entryCount;
PHYSFS_uint32 i;
for (i = 0; i < max; i++, entry++)
cb(callbackdata, origdir, entry->name);
} /* if */
} /* GRP_enumerateFiles */
static GRPentry *grp_find_entry(GRPinfo *info, const char *name)
{
char *ptr = strchr(name, '.');
GRPentry *a = info->entries;
PHYSFS_sint32 lo = 0;
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
PHYSFS_sint32 middle;
int rc;
/*
* Rule out filenames to avoid unneeded processing...no dirs,
* big filenames, or extensions > 3 chars.
*/
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
while (lo <= hi)
{
middle = lo + ((hi - lo) / 2);
rc = strcmp(name, a[middle].name);
if (rc == 0) /* found it! */
return(&a[middle]);
else if (rc > 0)
lo = middle + 1;
else
hi = middle - 1;
} /* while */
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
} /* grp_find_entry */
static int GRP_exists(dvoid *opaque, const char *name)
{
return(grp_find_entry((GRPinfo *) opaque, name) != NULL);
} /* GRP_exists */
static int GRP_isDirectory(dvoid *opaque, const char *name, int *fileExists)
{
*fileExists = GRP_exists(opaque, name);
return(0); /* never directories in a groupfile. */
} /* GRP_isDirectory */
static int GRP_isSymLink(dvoid *opaque, const char *name, int *fileExists)
{
*fileExists = GRP_exists(opaque, name);
return(0); /* never symlinks in a groupfile. */
} /* GRP_isSymLink */
static PHYSFS_sint64 GRP_getLastModTime(dvoid *opaque,
const char *name,
int *fileExists)
{
GRPinfo *info = (GRPinfo *) opaque;
PHYSFS_sint64 retval = -1;
*fileExists = (grp_find_entry(info, name) != NULL);
if (*fileExists) /* use time of GRP itself in the physical filesystem. */
retval = info->last_mod_time;
return(retval);
} /* GRP_getLastModTime */
static fvoid *GRP_openRead(dvoid *opaque, const char *fnm, int *fileExists)
{
GRPinfo *info = (GRPinfo *) opaque;
GRPfileinfo *finfo;
GRPentry *entry;
entry = grp_find_entry(info, fnm);
*fileExists = (entry != NULL);
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
finfo = (GRPfileinfo *) allocator.Malloc(sizeof (GRPfileinfo));
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
if ( (finfo->handle == NULL) ||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
{
allocator.Free(finfo);
return(NULL);
} /* if */
finfo->curPos = 0;
finfo->entry = entry;
return(finfo);
} /* GRP_openRead */
static fvoid *GRP_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* GRP_openWrite */
static fvoid *GRP_openAppend(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* GRP_openAppend */
static int GRP_remove(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* GRP_remove */
static int GRP_mkdir(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* GRP_mkdir */
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_GRP =
{
"GRP",
GRP_ARCHIVE_DESCRIPTION,
"Ryan C. Gordon <icculus@icculus.org>",
"http://icculus.org/physfs/",
};
const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
{
&__PHYSFS_ArchiveInfo_GRP,
GRP_isArchive, /* isArchive() method */
GRP_openArchive, /* openArchive() method */
GRP_enumerateFiles, /* enumerateFiles() method */
GRP_exists, /* exists() method */
GRP_isDirectory, /* isDirectory() method */
GRP_isSymLink, /* isSymLink() method */
GRP_getLastModTime, /* getLastModTime() method */
GRP_openRead, /* openRead() method */
GRP_openWrite, /* openWrite() method */
GRP_openAppend, /* openAppend() method */
GRP_remove, /* remove() method */
GRP_mkdir, /* mkdir() method */
GRP_dirClose, /* dirClose() method */
GRP_read, /* read() method */
GRP_write, /* write() method */
GRP_eof, /* eof() method */
GRP_tell, /* tell() method */
GRP_seek, /* seek() method */
GRP_fileLength, /* fileLength() method */
GRP_fileClose /* fileClose() method */
};
#endif /* defined PHYSFS_SUPPORTS_GRP */
/* end of grp.c ... */
-514
View File
@@ -1,514 +0,0 @@
/*
* HOG support routines for PhysicsFS.
*
* This driver handles Descent I/II HOG archives.
*
* The format is very simple:
*
* The file always starts with the 3-byte signature "DHF" (Descent
* HOG file). After that the files of a HOG are just attached after
* another, divided by a 17 bytes header, which specifies the name
* and length (in bytes) of the forthcoming file! So you just read
* the header with its information of how big the following file is,
* and then skip exact that number of bytes to get to the next file
* in that HOG.
*
* char sig[3] = {'D', 'H', 'F'}; // "DHF"=Descent HOG File
*
* struct {
* char file_name[13]; // Filename, padded to 13 bytes with 0s
* int file_size; // filesize in bytes
* char data[file_size]; // The file data
* } FILE_STRUCT; // Repeated until the end of the file.
*
* (That info is from http://www.descent2.com/ddn/specs/hog/)
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Bradley Bell.
* Based on grp.c by Ryan C. Gordon.
*/
#if (defined PHYSFS_SUPPORTS_HOG)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "physfs.h"
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
/*
* One HOGentry is kept for each file in an open HOG archive.
*/
typedef struct
{
char name[13];
PHYSFS_uint32 startPos;
PHYSFS_uint32 size;
} HOGentry;
/*
* One HOGinfo is kept for each open HOG archive.
*/
typedef struct
{
char *filename;
PHYSFS_sint64 last_mod_time;
PHYSFS_uint32 entryCount;
HOGentry *entries;
} HOGinfo;
/*
* One HOGfileinfo is kept for each open file in a HOG archive.
*/
typedef struct
{
void *handle;
HOGentry *entry;
PHYSFS_uint32 curPos;
} HOGfileinfo;
static void HOG_dirClose(dvoid *opaque)
{
HOGinfo *info = ((HOGinfo *) opaque);
allocator.Free(info->filename);
allocator.Free(info->entries);
allocator.Free(info);
} /* HOG_dirClose */
static PHYSFS_sint64 HOG_read(fvoid *opaque, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
HOGentry *entry = finfo->entry;
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
PHYSFS_sint64 rc;
if (objsLeft < objCount)
objCount = objsLeft;
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
if (rc > 0)
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
return(rc);
} /* HOG_read */
static PHYSFS_sint64 HOG_write(fvoid *opaque, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* HOG_write */
static int HOG_eof(fvoid *opaque)
{
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
HOGentry *entry = finfo->entry;
return(finfo->curPos >= entry->size);
} /* HOG_eof */
static PHYSFS_sint64 HOG_tell(fvoid *opaque)
{
return(((HOGfileinfo *) opaque)->curPos);
} /* HOG_tell */
static int HOG_seek(fvoid *opaque, PHYSFS_uint64 offset)
{
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
HOGentry *entry = finfo->entry;
int rc;
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
if (rc)
finfo->curPos = (PHYSFS_uint32) offset;
return(rc);
} /* HOG_seek */
static PHYSFS_sint64 HOG_fileLength(fvoid *opaque)
{
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
return((PHYSFS_sint64) finfo->entry->size);
} /* HOG_fileLength */
static int HOG_fileClose(fvoid *opaque)
{
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
allocator.Free(finfo);
return(1);
} /* HOG_fileClose */
static int hog_open(const char *filename, int forWriting,
void **fh, PHYSFS_uint32 *count)
{
PHYSFS_uint8 buf[13];
PHYSFS_uint32 size;
PHYSFS_sint64 pos;
*count = 0;
*fh = NULL;
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
*fh = __PHYSFS_platformOpenRead(filename);
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
if (__PHYSFS_platformRead(*fh, buf, 3, 1) != 1)
goto openHog_failed;
if (memcmp(buf, "DHF", 3) != 0)
{
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
goto openHog_failed;
} /* if */
while (1)
{
if (__PHYSFS_platformRead(*fh, buf, 13, 1) != 1)
break; /* eof here is ok */
if (__PHYSFS_platformRead(*fh, &size, 4, 1) != 1)
goto openHog_failed;
size = PHYSFS_swapULE32(size);
(*count)++;
/* Skip over entry... */
pos = __PHYSFS_platformTell(*fh);
if (pos == -1)
goto openHog_failed;
if (!__PHYSFS_platformSeek(*fh, pos + size))
goto openHog_failed;
} /* while */
/* Rewind to start of entries... */
if (!__PHYSFS_platformSeek(*fh, 3))
goto openHog_failed;
return(1);
openHog_failed:
if (*fh != NULL)
__PHYSFS_platformClose(*fh);
*count = -1;
*fh = NULL;
return(0);
} /* hog_open */
static int HOG_isArchive(const char *filename, int forWriting)
{
void *fh;
PHYSFS_uint32 fileCount;
int retval = hog_open(filename, forWriting, &fh, &fileCount);
if (fh != NULL)
__PHYSFS_platformClose(fh);
return(retval);
} /* HOG_isArchive */
static int hog_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
const HOGentry *a = (const HOGentry *) _a;
return(__PHYSFS_stricmpASCII(a[one].name, a[two].name));
} /* if */
return 0;
} /* hog_entry_cmp */
static void hog_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
HOGentry tmp;
HOGentry *first = &(((HOGentry *) _a)[one]);
HOGentry *second = &(((HOGentry *) _a)[two]);
memcpy(&tmp, first, sizeof (HOGentry));
memcpy(first, second, sizeof (HOGentry));
memcpy(second, &tmp, sizeof (HOGentry));
} /* if */
} /* hog_entry_swap */
static int hog_load_entries(const char *name, int forWriting, HOGinfo *info)
{
void *fh = NULL;
PHYSFS_uint32 fileCount;
HOGentry *entry;
BAIL_IF_MACRO(!hog_open(name, forWriting, &fh, &fileCount), NULL, 0);
info->entryCount = fileCount;
info->entries = (HOGentry *) allocator.Malloc(sizeof(HOGentry)*fileCount);
if (info->entries == NULL)
{
__PHYSFS_platformClose(fh);
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
} /* if */
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
{
if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
entry->size = PHYSFS_swapULE32(entry->size);
entry->startPos = (unsigned int) __PHYSFS_platformTell(fh);
if (entry->startPos == -1)
{
__PHYSFS_platformClose(fh);
return(0);
}
/* Skip over entry */
if (!__PHYSFS_platformSeek(fh, entry->startPos + entry->size))
{
__PHYSFS_platformClose(fh);
return(0);
}
} /* for */
__PHYSFS_platformClose(fh);
__PHYSFS_sort(info->entries, info->entryCount,
hog_entry_cmp, hog_entry_swap);
return(1);
} /* hog_load_entries */
static void *HOG_openArchive(const char *name, int forWriting)
{
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
HOGinfo *info = (HOGinfo *) allocator.Malloc(sizeof (HOGinfo));
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, 0);
memset(info, '\0', sizeof (HOGinfo));
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, HOG_openArchive_failed);
if (!hog_load_entries(name, forWriting, info))
goto HOG_openArchive_failed;
strcpy(info->filename, name);
info->last_mod_time = modtime;
return(info);
HOG_openArchive_failed:
if (info != NULL)
{
if (info->filename != NULL)
allocator.Free(info->filename);
if (info->entries != NULL)
allocator.Free(info->entries);
allocator.Free(info);
} /* if */
return(NULL);
} /* HOG_openArchive */
static void HOG_enumerateFiles(dvoid *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
/* no directories in HOG files. */
if (*dname == '\0')
{
HOGinfo *info = (HOGinfo *) opaque;
HOGentry *entry = info->entries;
PHYSFS_uint32 max = info->entryCount;
PHYSFS_uint32 i;
for (i = 0; i < max; i++, entry++)
cb(callbackdata, origdir, entry->name);
} /* if */
} /* HOG_enumerateFiles */
static HOGentry *hog_find_entry(HOGinfo *info, const char *name)
{
char *ptr = strchr(name, '.');
HOGentry *a = info->entries;
PHYSFS_sint32 lo = 0;
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
PHYSFS_sint32 middle;
int rc;
/*
* Rule out filenames to avoid unneeded processing...no dirs,
* big filenames, or extensions > 3 chars.
*/
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
while (lo <= hi)
{
middle = lo + ((hi - lo) / 2);
rc = __PHYSFS_stricmpASCII(name, a[middle].name);
if (rc == 0) /* found it! */
return(&a[middle]);
else if (rc > 0)
lo = middle + 1;
else
hi = middle - 1;
} /* while */
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
} /* hog_find_entry */
static int HOG_exists(dvoid *opaque, const char *name)
{
return(hog_find_entry(((HOGinfo *) opaque), name) != NULL);
} /* HOG_exists */
static int HOG_isDirectory(dvoid *opaque, const char *name, int *fileExists)
{
*fileExists = HOG_exists(opaque, name);
return(0); /* never directories in a groupfile. */
} /* HOG_isDirectory */
static int HOG_isSymLink(dvoid *opaque, const char *name, int *fileExists)
{
*fileExists = HOG_exists(opaque, name);
return(0); /* never symlinks in a groupfile. */
} /* HOG_isSymLink */
static PHYSFS_sint64 HOG_getLastModTime(dvoid *opaque,
const char *name,
int *fileExists)
{
HOGinfo *info = ((HOGinfo *) opaque);
PHYSFS_sint64 retval = -1;
*fileExists = (hog_find_entry(info, name) != NULL);
if (*fileExists) /* use time of HOG itself in the physical filesystem. */
retval = info->last_mod_time;
return(retval);
} /* HOG_getLastModTime */
static fvoid *HOG_openRead(dvoid *opaque, const char *fnm, int *fileExists)
{
HOGinfo *info = ((HOGinfo *) opaque);
HOGfileinfo *finfo;
HOGentry *entry;
entry = hog_find_entry(info, fnm);
*fileExists = (entry != NULL);
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
finfo = (HOGfileinfo *) allocator.Malloc(sizeof (HOGfileinfo));
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
if ( (finfo->handle == NULL) ||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
{
allocator.Free(finfo);
return(NULL);
} /* if */
finfo->curPos = 0;
finfo->entry = entry;
return(finfo);
} /* HOG_openRead */
static fvoid *HOG_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* HOG_openWrite */
static fvoid *HOG_openAppend(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* HOG_openAppend */
static int HOG_remove(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* HOG_remove */
static int HOG_mkdir(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* HOG_mkdir */
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_HOG =
{
"HOG",
HOG_ARCHIVE_DESCRIPTION,
"Bradley Bell <btb@icculus.org>",
"http://icculus.org/physfs/",
};
const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
{
&__PHYSFS_ArchiveInfo_HOG,
HOG_isArchive, /* isArchive() method */
HOG_openArchive, /* openArchive() method */
HOG_enumerateFiles, /* enumerateFiles() method */
HOG_exists, /* exists() method */
HOG_isDirectory, /* isDirectory() method */
HOG_isSymLink, /* isSymLink() method */
HOG_getLastModTime, /* getLastModTime() method */
HOG_openRead, /* openRead() method */
HOG_openWrite, /* openWrite() method */
HOG_openAppend, /* openAppend() method */
HOG_remove, /* remove() method */
HOG_mkdir, /* mkdir() method */
HOG_dirClose, /* dirClose() method */
HOG_read, /* read() method */
HOG_write, /* write() method */
HOG_eof, /* eof() method */
HOG_tell, /* tell() method */
HOG_seek, /* seek() method */
HOG_fileLength, /* fileLength() method */
HOG_fileClose /* fileClose() method */
};
#endif /* defined PHYSFS_SUPPORTS_HOG */
/* end of hog.c ... */
-471
View File
@@ -1,471 +0,0 @@
/*
* MVL support routines for PhysicsFS.
*
* This driver handles Descent II Movielib archives.
*
* The file format of MVL is quite easy...
*
* //MVL File format - Written by Heiko Herrmann
* char sig[4] = {'D','M', 'V', 'L'}; // "DMVL"=Descent MoVie Library
*
* int num_files; // the number of files in this MVL
*
* struct {
* char file_name[13]; // Filename, padded to 13 bytes with 0s
* int file_size; // filesize in bytes
* }DIR_STRUCT[num_files];
*
* struct {
* char data[file_size]; // The file data
* }FILE_STRUCT[num_files];
*
* (That info is from http://www.descent2.com/ddn/specs/mvl/)
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Bradley Bell.
* Based on grp.c by Ryan C. Gordon.
*/
#if (defined PHYSFS_SUPPORTS_MVL)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "physfs.h"
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
typedef struct
{
char name[13];
PHYSFS_uint32 startPos;
PHYSFS_uint32 size;
} MVLentry;
typedef struct
{
char *filename;
PHYSFS_sint64 last_mod_time;
PHYSFS_uint32 entryCount;
MVLentry *entries;
} MVLinfo;
typedef struct
{
void *handle;
MVLentry *entry;
PHYSFS_uint32 curPos;
} MVLfileinfo;
static void MVL_dirClose(dvoid *opaque)
{
MVLinfo *info = ((MVLinfo *) opaque);
allocator.Free(info->filename);
allocator.Free(info->entries);
allocator.Free(info);
} /* MVL_dirClose */
static PHYSFS_sint64 MVL_read(fvoid *opaque, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
MVLentry *entry = finfo->entry;
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
PHYSFS_sint64 rc;
if (objsLeft < objCount)
objCount = objsLeft;
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
if (rc > 0)
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
return(rc);
} /* MVL_read */
static PHYSFS_sint64 MVL_write(fvoid *opaque, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* MVL_write */
static int MVL_eof(fvoid *opaque)
{
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
MVLentry *entry = finfo->entry;
return(finfo->curPos >= entry->size);
} /* MVL_eof */
static PHYSFS_sint64 MVL_tell(fvoid *opaque)
{
return(((MVLfileinfo *) opaque)->curPos);
} /* MVL_tell */
static int MVL_seek(fvoid *opaque, PHYSFS_uint64 offset)
{
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
MVLentry *entry = finfo->entry;
int rc;
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
if (rc)
finfo->curPos = (PHYSFS_uint32) offset;
return(rc);
} /* MVL_seek */
static PHYSFS_sint64 MVL_fileLength(fvoid *opaque)
{
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
return((PHYSFS_sint64) finfo->entry->size);
} /* MVL_fileLength */
static int MVL_fileClose(fvoid *opaque)
{
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
allocator.Free(finfo);
return(1);
} /* MVL_fileClose */
static int mvl_open(const char *filename, int forWriting,
void **fh, PHYSFS_uint32 *count)
{
PHYSFS_uint8 buf[4];
*fh = NULL;
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
*fh = __PHYSFS_platformOpenRead(filename);
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
goto openMvl_failed;
if (memcmp(buf, "DMVL", 4) != 0)
{
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
goto openMvl_failed;
} /* if */
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
goto openMvl_failed;
*count = PHYSFS_swapULE32(*count);
return(1);
openMvl_failed:
if (*fh != NULL)
__PHYSFS_platformClose(*fh);
*count = -1;
*fh = NULL;
return(0);
} /* mvl_open */
static int MVL_isArchive(const char *filename, int forWriting)
{
void *fh;
PHYSFS_uint32 fileCount;
int retval = mvl_open(filename, forWriting, &fh, &fileCount);
if (fh != NULL)
__PHYSFS_platformClose(fh);
return(retval);
} /* MVL_isArchive */
static int mvl_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
const MVLentry *a = (const MVLentry *) _a;
return(strcmp(a[one].name, a[two].name));
} /* if */
return 0;
} /* mvl_entry_cmp */
static void mvl_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
MVLentry tmp;
MVLentry *first = &(((MVLentry *) _a)[one]);
MVLentry *second = &(((MVLentry *) _a)[two]);
memcpy(&tmp, first, sizeof (MVLentry));
memcpy(first, second, sizeof (MVLentry));
memcpy(second, &tmp, sizeof (MVLentry));
} /* if */
} /* mvl_entry_swap */
static int mvl_load_entries(const char *name, int forWriting, MVLinfo *info)
{
void *fh = NULL;
PHYSFS_uint32 fileCount;
PHYSFS_uint32 location = 8; /* sizeof sig. */
MVLentry *entry;
BAIL_IF_MACRO(!mvl_open(name, forWriting, &fh, &fileCount), NULL, 0);
info->entryCount = fileCount;
info->entries = (MVLentry *) allocator.Malloc(sizeof(MVLentry)*fileCount);
if (info->entries == NULL)
{
__PHYSFS_platformClose(fh);
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
} /* if */
location += (17 * fileCount);
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
{
if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
entry->size = PHYSFS_swapULE32(entry->size);
entry->startPos = location;
location += entry->size;
} /* for */
__PHYSFS_platformClose(fh);
__PHYSFS_sort(info->entries, info->entryCount,
mvl_entry_cmp, mvl_entry_swap);
return(1);
} /* mvl_load_entries */
static void *MVL_openArchive(const char *name, int forWriting)
{
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
MVLinfo *info = (MVLinfo *) allocator.Malloc(sizeof (MVLinfo));
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
memset(info, '\0', sizeof (MVLinfo));
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, MVL_openArchive_failed);
if (!mvl_load_entries(name, forWriting, info))
goto MVL_openArchive_failed;
strcpy(info->filename, name);
info->last_mod_time = modtime;
return(info);
MVL_openArchive_failed:
if (info != NULL)
{
if (info->filename != NULL)
allocator.Free(info->filename);
if (info->entries != NULL)
allocator.Free(info->entries);
allocator.Free(info);
} /* if */
return(NULL);
} /* MVL_openArchive */
static void MVL_enumerateFiles(dvoid *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
/* no directories in MVL files. */
if (*dname == '\0')
{
MVLinfo *info = ((MVLinfo *) opaque);
MVLentry *entry = info->entries;
PHYSFS_uint32 max = info->entryCount;
PHYSFS_uint32 i;
for (i = 0; i < max; i++, entry++)
cb(callbackdata, origdir, entry->name);
} /* if */
} /* MVL_enumerateFiles */
static MVLentry *mvl_find_entry(MVLinfo *info, const char *name)
{
char *ptr = strchr(name, '.');
MVLentry *a = info->entries;
PHYSFS_sint32 lo = 0;
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
PHYSFS_sint32 middle;
int rc;
/*
* Rule out filenames to avoid unneeded processing...no dirs,
* big filenames, or extensions > 3 chars.
*/
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
while (lo <= hi)
{
middle = lo + ((hi - lo) / 2);
rc = __PHYSFS_stricmpASCII(name, a[middle].name);
if (rc == 0) /* found it! */
return(&a[middle]);
else if (rc > 0)
lo = middle + 1;
else
hi = middle - 1;
} /* while */
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
} /* mvl_find_entry */
static int MVL_exists(dvoid *opaque, const char *name)
{
return(mvl_find_entry(((MVLinfo *) opaque), name) != NULL);
} /* MVL_exists */
static int MVL_isDirectory(dvoid *opaque, const char *name, int *fileExists)
{
*fileExists = MVL_exists(opaque, name);
return(0); /* never directories in a groupfile. */
} /* MVL_isDirectory */
static int MVL_isSymLink(dvoid *opaque, const char *name, int *fileExists)
{
*fileExists = MVL_exists(opaque, name);
return(0); /* never symlinks in a groupfile. */
} /* MVL_isSymLink */
static PHYSFS_sint64 MVL_getLastModTime(dvoid *opaque,
const char *name,
int *fileExists)
{
MVLinfo *info = ((MVLinfo *) opaque);
PHYSFS_sint64 retval = -1;
*fileExists = (mvl_find_entry(info, name) != NULL);
if (*fileExists) /* use time of MVL itself in the physical filesystem. */
retval = info->last_mod_time;
return(retval);
} /* MVL_getLastModTime */
static fvoid *MVL_openRead(dvoid *opaque, const char *fnm, int *fileExists)
{
MVLinfo *info = ((MVLinfo *) opaque);
MVLfileinfo *finfo;
MVLentry *entry;
entry = mvl_find_entry(info, fnm);
*fileExists = (entry != NULL);
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
finfo = (MVLfileinfo *) allocator.Malloc(sizeof (MVLfileinfo));
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
if ( (finfo->handle == NULL) ||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
{
allocator.Free(finfo);
return(NULL);
} /* if */
finfo->curPos = 0;
finfo->entry = entry;
return(finfo);
} /* MVL_openRead */
static fvoid *MVL_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* MVL_openWrite */
static fvoid *MVL_openAppend(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* MVL_openAppend */
static int MVL_remove(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* MVL_remove */
static int MVL_mkdir(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* MVL_mkdir */
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_MVL =
{
"MVL",
MVL_ARCHIVE_DESCRIPTION,
"Bradley Bell <btb@icculus.org>",
"http://icculus.org/physfs/",
};
const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
{
&__PHYSFS_ArchiveInfo_MVL,
MVL_isArchive, /* isArchive() method */
MVL_openArchive, /* openArchive() method */
MVL_enumerateFiles, /* enumerateFiles() method */
MVL_exists, /* exists() method */
MVL_isDirectory, /* isDirectory() method */
MVL_isSymLink, /* isSymLink() method */
MVL_getLastModTime, /* getLastModTime() method */
MVL_openRead, /* openRead() method */
MVL_openWrite, /* openWrite() method */
MVL_openAppend, /* openAppend() method */
MVL_remove, /* remove() method */
MVL_mkdir, /* mkdir() method */
MVL_dirClose, /* dirClose() method */
MVL_read, /* read() method */
MVL_write, /* write() method */
MVL_eof, /* eof() method */
MVL_tell, /* tell() method */
MVL_seek, /* seek() method */
MVL_fileLength, /* fileLength() method */
MVL_fileClose /* fileClose() method */
};
#endif /* defined PHYSFS_SUPPORTS_MVL */
/* end of mvl.c ... */
-633
View File
@@ -1,633 +0,0 @@
/*
* QPAK support routines for PhysicsFS.
*
* This archiver handles the archive format utilized by Quake 1 and 2.
* Quake3-based games use the PkZip/Info-Zip format (which our zip.c
* archiver handles).
*
* ========================================================================
*
* This format info (in more detail) comes from:
* http://debian.fmi.uni-sofia.bg/~sergei/cgsr/docs/pak.txt
*
* Quake PAK Format
*
* Header
* (4 bytes) signature = 'PACK'
* (4 bytes) directory offset
* (4 bytes) directory length
*
* Directory
* (56 bytes) file name
* (4 bytes) file position
* (4 bytes) file length
*
* ========================================================================
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
#if (defined PHYSFS_SUPPORTS_QPAK)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "physfs.h"
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
#if 1 /* Make this case insensitive? */
#define QPAK_strcmp(x, y) __PHYSFS_stricmpASCII(x, y)
#define QPAK_strncmp(x, y, z) __PHYSFS_strnicmpASCII(x, y, z)
#else
#define QPAK_strcmp(x, y) strcmp(x, y)
#define QPAK_strncmp(x, y, z) strncmp(x, y, z)
#endif
typedef struct
{
char name[56];
PHYSFS_uint32 startPos;
PHYSFS_uint32 size;
} QPAKentry;
typedef struct
{
char *filename;
PHYSFS_sint64 last_mod_time;
PHYSFS_uint32 entryCount;
QPAKentry *entries;
} QPAKinfo;
typedef struct
{
void *handle;
QPAKentry *entry;
PHYSFS_uint32 curPos;
} QPAKfileinfo;
/* Magic numbers... */
#define QPAK_SIG 0x4b434150 /* "PACK" in ASCII. */
static void QPAK_dirClose(dvoid *opaque)
{
QPAKinfo *info = ((QPAKinfo *) opaque);
allocator.Free(info->filename);
allocator.Free(info->entries);
allocator.Free(info);
} /* QPAK_dirClose */
static PHYSFS_sint64 QPAK_read(fvoid *opaque, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
QPAKentry *entry = finfo->entry;
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
PHYSFS_sint64 rc;
if (objsLeft < objCount)
objCount = objsLeft;
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
if (rc > 0)
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
return(rc);
} /* QPAK_read */
static PHYSFS_sint64 QPAK_write(fvoid *opaque, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* QPAK_write */
static int QPAK_eof(fvoid *opaque)
{
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
QPAKentry *entry = finfo->entry;
return(finfo->curPos >= entry->size);
} /* QPAK_eof */
static PHYSFS_sint64 QPAK_tell(fvoid *opaque)
{
return(((QPAKfileinfo *) opaque)->curPos);
} /* QPAK_tell */
static int QPAK_seek(fvoid *opaque, PHYSFS_uint64 offset)
{
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
QPAKentry *entry = finfo->entry;
int rc;
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
if (rc)
finfo->curPos = (PHYSFS_uint32) offset;
return(rc);
} /* QPAK_seek */
static PHYSFS_sint64 QPAK_fileLength(fvoid *opaque)
{
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
return((PHYSFS_sint64) finfo->entry->size);
} /* QPAK_fileLength */
static int QPAK_fileClose(fvoid *opaque)
{
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
allocator.Free(finfo);
return(1);
} /* QPAK_fileClose */
static int qpak_open(const char *filename, int forWriting,
void **fh, PHYSFS_uint32 *count)
{
PHYSFS_uint32 buf;
*fh = NULL;
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
*fh = __PHYSFS_platformOpenRead(filename);
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
goto openQpak_failed;
buf = PHYSFS_swapULE32(buf);
GOTO_IF_MACRO(buf != QPAK_SIG, ERR_UNSUPPORTED_ARCHIVE, openQpak_failed);
if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
goto openQpak_failed;
buf = PHYSFS_swapULE32(buf); /* directory table offset. */
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
goto openQpak_failed;
*count = PHYSFS_swapULE32(*count);
/* corrupted archive? */
GOTO_IF_MACRO((*count % 64) != 0, ERR_CORRUPTED, openQpak_failed);
if (!__PHYSFS_platformSeek(*fh, buf))
goto openQpak_failed;
*count /= 64;
return(1);
openQpak_failed:
if (*fh != NULL)
__PHYSFS_platformClose(*fh);
*count = -1;
*fh = NULL;
return(0);
} /* qpak_open */
static int QPAK_isArchive(const char *filename, int forWriting)
{
void *fh;
PHYSFS_uint32 fileCount;
int retval = qpak_open(filename, forWriting, &fh, &fileCount);
if (fh != NULL)
__PHYSFS_platformClose(fh);
return(retval);
} /* QPAK_isArchive */
static int qpak_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
const QPAKentry *a = (const QPAKentry *) _a;
return(QPAK_strcmp(a[one].name, a[two].name));
} /* if */
return 0;
} /* qpak_entry_cmp */
static void qpak_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
QPAKentry tmp;
QPAKentry *first = &(((QPAKentry *) _a)[one]);
QPAKentry *second = &(((QPAKentry *) _a)[two]);
memcpy(&tmp, first, sizeof (QPAKentry));
memcpy(first, second, sizeof (QPAKentry));
memcpy(second, &tmp, sizeof (QPAKentry));
} /* if */
} /* qpak_entry_swap */
static int qpak_load_entries(const char *name, int forWriting, QPAKinfo *info)
{
void *fh = NULL;
PHYSFS_uint32 fileCount;
QPAKentry *entry;
BAIL_IF_MACRO(!qpak_open(name, forWriting, &fh, &fileCount), NULL, 0);
info->entryCount = fileCount;
info->entries = (QPAKentry*) allocator.Malloc(sizeof(QPAKentry)*fileCount);
if (info->entries == NULL)
{
__PHYSFS_platformClose(fh);
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
} /* if */
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
{
PHYSFS_uint32 loc;
if (__PHYSFS_platformRead(fh,&entry->name,sizeof(entry->name),1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
if (__PHYSFS_platformRead(fh,&loc,sizeof(loc),1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
if (__PHYSFS_platformRead(fh,&entry->size,sizeof(entry->size),1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
entry->size = PHYSFS_swapULE32(entry->size);
entry->startPos = PHYSFS_swapULE32(loc);
} /* for */
__PHYSFS_platformClose(fh);
__PHYSFS_sort(info->entries, info->entryCount,
qpak_entry_cmp, qpak_entry_swap);
return(1);
} /* qpak_load_entries */
static void *QPAK_openArchive(const char *name, int forWriting)
{
QPAKinfo *info = (QPAKinfo *) allocator.Malloc(sizeof (QPAKinfo));
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
memset(info, '\0', sizeof (QPAKinfo));
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
if (info->filename == NULL)
{
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
goto QPAK_openArchive_failed;
} /* if */
if (!qpak_load_entries(name, forWriting, info))
goto QPAK_openArchive_failed;
strcpy(info->filename, name);
info->last_mod_time = modtime;
return(info);
QPAK_openArchive_failed:
if (info != NULL)
{
if (info->filename != NULL)
allocator.Free(info->filename);
if (info->entries != NULL)
allocator.Free(info->entries);
allocator.Free(info);
} /* if */
return(NULL);
} /* QPAK_openArchive */
static PHYSFS_sint32 qpak_find_start_of_dir(QPAKinfo *info, const char *path,
int stop_on_first_find)
{
PHYSFS_sint32 lo = 0;
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
PHYSFS_sint32 middle;
PHYSFS_uint32 dlen = strlen(path);
PHYSFS_sint32 retval = -1;
const char *name;
int rc;
if (*path == '\0') /* root dir? */
return(0);
if ((dlen > 0) && (path[dlen - 1] == '/')) /* ignore trailing slash. */
dlen--;
while (lo <= hi)
{
middle = lo + ((hi - lo) / 2);
name = info->entries[middle].name;
rc = QPAK_strncmp(path, name, dlen);
if (rc == 0)
{
char ch = name[dlen];
if (ch < '/') /* make sure this isn't just a substr match. */
rc = -1;
else if (ch > '/')
rc = 1;
else
{
if (stop_on_first_find) /* Just checking dir's existance? */
return(middle);
if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
return(middle + 1);
/* there might be more entries earlier in the list. */
retval = middle;
hi = middle - 1;
} /* else */
} /* if */
if (rc > 0)
lo = middle + 1;
else
hi = middle - 1;
} /* while */
return(retval);
} /* qpak_find_start_of_dir */
/*
* Moved to seperate function so we can use alloca then immediately throw
* away the allocated stack space...
*/
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
const char *odir, const char *str, PHYSFS_sint32 ln)
{
char *newstr = __PHYSFS_smallAlloc(ln + 1);
if (newstr == NULL)
return;
memcpy(newstr, str, ln);
newstr[ln] = '\0';
cb(callbackdata, odir, newstr);
__PHYSFS_smallFree(newstr);
} /* doEnumCallback */
static void QPAK_enumerateFiles(dvoid *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
QPAKinfo *info = ((QPAKinfo *) opaque);
PHYSFS_sint32 dlen, dlen_inc, max, i;
i = qpak_find_start_of_dir(info, dname, 0);
if (i == -1) /* no such directory. */
return;
dlen = strlen(dname);
if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
dlen--;
dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
max = (PHYSFS_sint32) info->entryCount;
while (i < max)
{
char *add;
char *ptr;
PHYSFS_sint32 ln;
char *e = info->entries[i].name;
if ((dlen) && ((QPAK_strncmp(e, dname, dlen)) || (e[dlen] != '/')))
break; /* past end of this dir; we're done. */
add = e + dlen_inc;
ptr = strchr(add, '/');
ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
doEnumCallback(cb, callbackdata, origdir, add, ln);
ln += dlen_inc; /* point past entry to children... */
/* increment counter and skip children of subdirs... */
while ((++i < max) && (ptr != NULL))
{
char *e_new = info->entries[i].name;
if ((QPAK_strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))
break;
} /* while */
} /* while */
} /* QPAK_enumerateFiles */
/*
* This will find the QPAKentry associated with a path in platform-independent
* notation. Directories don't have QPAKentries associated with them, but
* (*isDir) will be set to non-zero if a dir was hit.
*/
static QPAKentry *qpak_find_entry(QPAKinfo *info, const char *path, int *isDir)
{
QPAKentry *a = info->entries;
PHYSFS_sint32 pathlen = strlen(path);
PHYSFS_sint32 lo = 0;
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
PHYSFS_sint32 middle;
const char *thispath = NULL;
int rc;
while (lo <= hi)
{
middle = lo + ((hi - lo) / 2);
thispath = a[middle].name;
rc = QPAK_strncmp(path, thispath, pathlen);
if (rc > 0)
lo = middle + 1;
else if (rc < 0)
hi = middle - 1;
else /* substring match...might be dir or entry or nothing. */
{
if (isDir != NULL)
{
*isDir = (thispath[pathlen] == '/');
if (*isDir)
return(NULL);
} /* if */
if (thispath[pathlen] == '\0') /* found entry? */
return(&a[middle]);
/* adjust search params, try again. */
else if (thispath[pathlen] > '/')
hi = middle - 1;
else
lo = middle + 1;
} /* if */
} /* while */
if (isDir != NULL)
*isDir = 0;
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
} /* qpak_find_entry */
static int QPAK_exists(dvoid *opaque, const char *name)
{
int isDir;
QPAKinfo *info = (QPAKinfo *) opaque;
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
return((entry != NULL) || (isDir));
} /* QPAK_exists */
static int QPAK_isDirectory(dvoid *opaque, const char *name, int *fileExists)
{
QPAKinfo *info = (QPAKinfo *) opaque;
int isDir;
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
*fileExists = ((isDir) || (entry != NULL));
if (isDir)
return(1); /* definitely a dir. */
BAIL_MACRO(ERR_NO_SUCH_FILE, 0);
} /* QPAK_isDirectory */
static int QPAK_isSymLink(dvoid *opaque, const char *name, int *fileExists)
{
*fileExists = QPAK_exists(opaque, name);
return(0); /* never symlinks in a quake pak. */
} /* QPAK_isSymLink */
static PHYSFS_sint64 QPAK_getLastModTime(dvoid *opaque,
const char *name,
int *fileExists)
{
int isDir;
QPAKinfo *info = ((QPAKinfo *) opaque);
PHYSFS_sint64 retval = -1;
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
*fileExists = ((isDir) || (entry != NULL));
if (*fileExists) /* use time of QPAK itself in the physical filesystem. */
retval = info->last_mod_time;
return(retval);
} /* QPAK_getLastModTime */
static fvoid *QPAK_openRead(dvoid *opaque, const char *fnm, int *fileExists)
{
QPAKinfo *info = ((QPAKinfo *) opaque);
QPAKfileinfo *finfo;
QPAKentry *entry;
int isDir;
entry = qpak_find_entry(info, fnm, &isDir);
*fileExists = ((entry != NULL) || (isDir));
BAIL_IF_MACRO(isDir, ERR_NOT_A_FILE, NULL);
BAIL_IF_MACRO(entry == NULL, ERR_NO_SUCH_FILE, NULL);
finfo = (QPAKfileinfo *) allocator.Malloc(sizeof (QPAKfileinfo));
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
if ( (finfo->handle == NULL) ||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
{
allocator.Free(finfo);
return(NULL);
} /* if */
finfo->curPos = 0;
finfo->entry = entry;
return(finfo);
} /* QPAK_openRead */
static fvoid *QPAK_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* QPAK_openWrite */
static fvoid *QPAK_openAppend(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* QPAK_openAppend */
static int QPAK_remove(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* QPAK_remove */
static int QPAK_mkdir(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* QPAK_mkdir */
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_QPAK =
{
"PAK",
QPAK_ARCHIVE_DESCRIPTION,
"Ryan C. Gordon <icculus@icculus.org>",
"http://icculus.org/physfs/",
};
const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
{
&__PHYSFS_ArchiveInfo_QPAK,
QPAK_isArchive, /* isArchive() method */
QPAK_openArchive, /* openArchive() method */
QPAK_enumerateFiles, /* enumerateFiles() method */
QPAK_exists, /* exists() method */
QPAK_isDirectory, /* isDirectory() method */
QPAK_isSymLink, /* isSymLink() method */
QPAK_getLastModTime, /* getLastModTime() method */
QPAK_openRead, /* openRead() method */
QPAK_openWrite, /* openWrite() method */
QPAK_openAppend, /* openAppend() method */
QPAK_remove, /* remove() method */
QPAK_mkdir, /* mkdir() method */
QPAK_dirClose, /* dirClose() method */
QPAK_read, /* read() method */
QPAK_write, /* write() method */
QPAK_eof, /* eof() method */
QPAK_tell, /* tell() method */
QPAK_seek, /* seek() method */
QPAK_fileLength, /* fileLength() method */
QPAK_fileClose /* fileClose() method */
};
#endif /* defined PHYSFS_SUPPORTS_QPAK */
/* end of qpak.c ... */
-531
View File
@@ -1,531 +0,0 @@
/*
* WAD support routines for PhysicsFS.
*
* This driver handles DOOM engine archives ("wads").
* This format (but not this driver) was designed by id Software for use
* with the DOOM engine.
* The specs of the format are from the unofficial doom specs v1.666
* found here: http://www.gamers.org/dhs/helpdocs/dmsp1666.html
* The format of the archive: (from the specs)
*
* A WAD file has three parts:
* (1) a twelve-byte header
* (2) one or more "lumps"
* (3) a directory or "info table" that contains the names, offsets, and
* sizes of all the lumps in the WAD
*
* The header consists of three four-byte parts:
* (a) an ASCII string which must be either "IWAD" or "PWAD"
* (b) a 4-byte (long) integer which is the number of lumps in the wad
* (c) a long integer which is the file offset to the start of
* the directory
*
* The directory has one 16-byte entry for every lump. Each entry consists
* of three parts:
*
* (a) a long integer, the file offset to the start of the lump
* (b) a long integer, the size of the lump in bytes
* (c) an 8-byte ASCII string, the name of the lump, padded with zeros.
* For example, the "DEMO1" entry in hexadecimal would be
* (44 45 4D 4F 31 00 00 00)
*
* Note that there is no way to tell if an opened WAD archive is a
* IWAD or PWAD with this archiver.
* I couldn't think of a way to provide that information, without being too
* hacky.
* I don't think it's really that important though.
*
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Travis Wells, based on the GRP archiver by
* Ryan C. Gordon.
*/
#if (defined PHYSFS_SUPPORTS_WAD)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "physfs.h"
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
typedef struct
{
char name[18];
PHYSFS_uint32 startPos;
PHYSFS_uint32 size;
} WADentry;
typedef struct
{
char *filename;
PHYSFS_sint64 last_mod_time;
PHYSFS_uint32 entryCount;
PHYSFS_uint32 entryOffset;
WADentry *entries;
} WADinfo;
typedef struct
{
void *handle;
WADentry *entry;
PHYSFS_uint32 curPos;
} WADfileinfo;
static void WAD_dirClose(dvoid *opaque)
{
WADinfo *info = ((WADinfo *) opaque);
allocator.Free(info->filename);
allocator.Free(info->entries);
allocator.Free(info);
} /* WAD_dirClose */
static PHYSFS_sint64 WAD_read(fvoid *opaque, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
WADfileinfo *finfo = (WADfileinfo *) opaque;
WADentry *entry = finfo->entry;
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
PHYSFS_sint64 rc;
if (objsLeft < objCount)
objCount = objsLeft;
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
if (rc > 0)
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
return(rc);
} /* WAD_read */
static PHYSFS_sint64 WAD_write(fvoid *opaque, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* WAD_write */
static int WAD_eof(fvoid *opaque)
{
WADfileinfo *finfo = (WADfileinfo *) opaque;
WADentry *entry = finfo->entry;
return(finfo->curPos >= entry->size);
} /* WAD_eof */
static PHYSFS_sint64 WAD_tell(fvoid *opaque)
{
return(((WADfileinfo *) opaque)->curPos);
} /* WAD_tell */
static int WAD_seek(fvoid *opaque, PHYSFS_uint64 offset)
{
WADfileinfo *finfo = (WADfileinfo *) opaque;
WADentry *entry = finfo->entry;
int rc;
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
if (rc)
finfo->curPos = (PHYSFS_uint32) offset;
return(rc);
} /* WAD_seek */
static PHYSFS_sint64 WAD_fileLength(fvoid *opaque)
{
WADfileinfo *finfo = (WADfileinfo *) opaque;
return((PHYSFS_sint64) finfo->entry->size);
} /* WAD_fileLength */
static int WAD_fileClose(fvoid *opaque)
{
WADfileinfo *finfo = (WADfileinfo *) opaque;
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
allocator.Free(finfo);
return(1);
} /* WAD_fileClose */
static int wad_open(const char *filename, int forWriting,
void **fh, PHYSFS_uint32 *count,PHYSFS_uint32 *offset)
{
PHYSFS_uint8 buf[4];
*fh = NULL;
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
*fh = __PHYSFS_platformOpenRead(filename);
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
goto openWad_failed;
if (memcmp(buf, "IWAD", 4) != 0 && memcmp(buf, "PWAD", 4) != 0)
{
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
goto openWad_failed;
} /* if */
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
goto openWad_failed;
*count = PHYSFS_swapULE32(*count);
if (__PHYSFS_platformRead(*fh, offset, sizeof (PHYSFS_uint32), 1) != 1)
goto openWad_failed;
*offset = PHYSFS_swapULE32(*offset);
return(1);
openWad_failed:
if (*fh != NULL)
__PHYSFS_platformClose(*fh);
*count = -1;
*fh = NULL;
return(0);
} /* wad_open */
static int WAD_isArchive(const char *filename, int forWriting)
{
void *fh;
PHYSFS_uint32 fileCount,offset;
int retval = wad_open(filename, forWriting, &fh, &fileCount,&offset);
if (fh != NULL)
__PHYSFS_platformClose(fh);
return(retval);
} /* WAD_isArchive */
static int wad_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
const WADentry *a = (const WADentry *) _a;
return(strcmp(a[one].name, a[two].name));
} /* if */
return 0;
} /* wad_entry_cmp */
static void wad_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
if (one != two)
{
WADentry tmp;
WADentry *first = &(((WADentry *) _a)[one]);
WADentry *second = &(((WADentry *) _a)[two]);
memcpy(&tmp, first, sizeof (WADentry));
memcpy(first, second, sizeof (WADentry));
memcpy(second, &tmp, sizeof (WADentry));
} /* if */
} /* wad_entry_swap */
static int wad_load_entries(const char *name, int forWriting, WADinfo *info)
{
void *fh = NULL;
PHYSFS_uint32 fileCount;
PHYSFS_uint32 directoryOffset;
WADentry *entry;
BAIL_IF_MACRO(!wad_open(name, forWriting, &fh, &fileCount,&directoryOffset), NULL, 0);
info->entryCount = fileCount;
info->entries = (WADentry *) allocator.Malloc(sizeof(WADentry)*fileCount);
if (info->entries == NULL)
{
__PHYSFS_platformClose(fh);
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
} /* if */
__PHYSFS_platformSeek(fh,directoryOffset);
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
{
if (__PHYSFS_platformRead(fh, &entry->startPos, 4, 1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
if (__PHYSFS_platformRead(fh, &entry->name, 8, 1) != 1)
{
__PHYSFS_platformClose(fh);
return(0);
} /* if */
entry->name[8] = '\0'; /* name might not be null-terminated in file. */
entry->size = PHYSFS_swapULE32(entry->size);
entry->startPos = PHYSFS_swapULE32(entry->startPos);
} /* for */
__PHYSFS_platformClose(fh);
__PHYSFS_sort(info->entries, info->entryCount,
wad_entry_cmp, wad_entry_swap);
return(1);
} /* wad_load_entries */
static void *WAD_openArchive(const char *name, int forWriting)
{
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
WADinfo *info = (WADinfo *) allocator.Malloc(sizeof (WADinfo));
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
memset(info, '\0', sizeof (WADinfo));
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, WAD_openArchive_failed);
if (!wad_load_entries(name, forWriting, info))
goto WAD_openArchive_failed;
strcpy(info->filename, name);
info->last_mod_time = modtime;
return(info);
WAD_openArchive_failed:
if (info != NULL)
{
if (info->filename != NULL)
allocator.Free(info->filename);
if (info->entries != NULL)
allocator.Free(info->entries);
allocator.Free(info);
} /* if */
return(NULL);
} /* WAD_openArchive */
static void WAD_enumerateFiles(dvoid *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
WADinfo *info = ((WADinfo *) opaque);
WADentry *entry = info->entries;
PHYSFS_uint32 max = info->entryCount;
PHYSFS_uint32 i;
const char *name;
char *sep;
if (*dname == '\0') /* root directory enumeration? */
{
for (i = 0; i < max; i++, entry++)
{
name = entry->name;
if (strchr(name, '/') == NULL)
cb(callbackdata, origdir, name);
} /* for */
} /* if */
else
{
for (i = 0; i < max; i++, entry++)
{
name = entry->name;
sep = strchr(name, '/');
if (sep != NULL)
{
if (strncmp(dname, name, (sep - name)) == 0)
cb(callbackdata, origdir, sep + 1);
} /* if */
} /* for */
} /* else */
} /* WAD_enumerateFiles */
static WADentry *wad_find_entry(WADinfo *info, const char *name)
{
WADentry *a = info->entries;
PHYSFS_sint32 lo = 0;
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
PHYSFS_sint32 middle;
int rc;
while (lo <= hi)
{
middle = lo + ((hi - lo) / 2);
rc = strcmp(name, a[middle].name);
if (rc == 0) /* found it! */
return(&a[middle]);
else if (rc > 0)
lo = middle + 1;
else
hi = middle - 1;
} /* while */
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
} /* wad_find_entry */
static int WAD_exists(dvoid *opaque, const char *name)
{
return(wad_find_entry(((WADinfo *) opaque), name) != NULL);
} /* WAD_exists */
static int WAD_isDirectory(dvoid *opaque, const char *name, int *fileExists)
{
WADentry *entry = wad_find_entry(((WADinfo *) opaque), name);
if (entry != NULL)
{
char *n;
*fileExists = 1;
/* Can't be a directory if it's a subdirectory. */
if (strchr(entry->name, '/') != NULL)
return(0);
/* Check if it matches "MAP??" or "E?M?" ... */
n = entry->name;
if ((n[0] == 'E' && n[2] == 'M') ||
(n[0] == 'M' && n[1] == 'A' && n[2] == 'P' && n[6] == 0))
{
return(1);
} /* if */
return(0);
} /* if */
else
{
*fileExists = 0;
return(0);
} /* else */
} /* WAD_isDirectory */
static int WAD_isSymLink(dvoid *opaque, const char *name, int *fileExists)
{
*fileExists = WAD_exists(opaque, name);
return(0); /* never symlinks in a wad. */
} /* WAD_isSymLink */
static PHYSFS_sint64 WAD_getLastModTime(dvoid *opaque,
const char *name,
int *fileExists)
{
WADinfo *info = ((WADinfo *) opaque);
PHYSFS_sint64 retval = -1;
*fileExists = (wad_find_entry(info, name) != NULL);
if (*fileExists) /* use time of WAD itself in the physical filesystem. */
retval = info->last_mod_time;
return(retval);
} /* WAD_getLastModTime */
static fvoid *WAD_openRead(dvoid *opaque, const char *fnm, int *fileExists)
{
WADinfo *info = ((WADinfo *) opaque);
WADfileinfo *finfo;
WADentry *entry;
entry = wad_find_entry(info, fnm);
*fileExists = (entry != NULL);
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
finfo = (WADfileinfo *) allocator.Malloc(sizeof (WADfileinfo));
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
if ( (finfo->handle == NULL) ||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
{
allocator.Free(finfo);
return(NULL);
} /* if */
finfo->curPos = 0;
finfo->entry = entry;
return(finfo);
} /* WAD_openRead */
static fvoid *WAD_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* WAD_openWrite */
static fvoid *WAD_openAppend(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* WAD_openAppend */
static int WAD_remove(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* WAD_remove */
static int WAD_mkdir(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* WAD_mkdir */
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_WAD =
{
"WAD",
WAD_ARCHIVE_DESCRIPTION,
"Travis Wells <traviswells@mchsi.com>",
"http://www.3dmm2.com/doom/",
};
const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
{
&__PHYSFS_ArchiveInfo_WAD,
WAD_isArchive, /* isArchive() method */
WAD_openArchive, /* openArchive() method */
WAD_enumerateFiles, /* enumerateFiles() method */
WAD_exists, /* exists() method */
WAD_isDirectory, /* isDirectory() method */
WAD_isSymLink, /* isSymLink() method */
WAD_getLastModTime, /* getLastModTime() method */
WAD_openRead, /* openRead() method */
WAD_openWrite, /* openWrite() method */
WAD_openAppend, /* openAppend() method */
WAD_remove, /* remove() method */
WAD_mkdir, /* mkdir() method */
WAD_dirClose, /* dirClose() method */
WAD_read, /* read() method */
WAD_write, /* write() method */
WAD_eof, /* eof() method */
WAD_tell, /* tell() method */
WAD_seek, /* seek() method */
WAD_fileLength, /* fileLength() method */
WAD_fileClose /* fileClose() method */
};
#endif /* defined PHYSFS_SUPPORTS_WAD */
/* end of wad.c ... */
File diff suppressed because it is too large Load Diff
-159
View File
@@ -1,159 +0,0 @@
/** \file globbing.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "physfs.h"
#include "globbing.h"
/**
* Please see globbing.h for details.
*
* License: this code is public domain. I make no warranty that it is useful,
* correct, harmless, or environmentally safe.
*
* This particular file may be used however you like, including copying it
* verbatim into a closed-source project, exploiting it commercially, and
* removing any trace of my name from the source (although I hope you won't
* do that). I welcome enhancements and corrections to this file, but I do
* not require you to send me patches if you make changes. This code has
* NO WARRANTY.
*
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
* Please see LICENSE.txt in the root of the source tree.
*
* \author Ryan C. Gordon.
*/
static int matchesPattern(const char *fname, const char *wildcard,
int caseSensitive)
{
char x, y;
const char *fnameptr = fname;
const char *wildptr = wildcard;
while ((*wildptr) && (*fnameptr))
{
y = *wildptr;
if (y == '*')
{
do
{
wildptr++; /* skip multiple '*' in a row... */
} while (*wildptr == '*');
y = (caseSensitive) ? *wildptr : (char) tolower(*wildptr);
while (1)
{
x = (caseSensitive) ? *fnameptr : (char) tolower(*fnameptr);
if ((!x) || (x == y))
break;
else
fnameptr++;
} /* while */
} /* if */
else if (y == '?')
{
wildptr++;
fnameptr++;
} /* else if */
else
{
if (caseSensitive)
x = *fnameptr;
else
{
x = tolower(*fnameptr);
y = tolower(y);
} /* if */
wildptr++;
fnameptr++;
if (x != y)
return(0);
} /* else */
} /* while */
while (*wildptr == '*')
wildptr++;
return(*fnameptr == *wildptr);
} /* matchesPattern */
char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard,
int caseSensitive)
{
char **rc = PHYSFS_enumerateFiles(dir);
char **i = rc;
char **j;
while (*i != NULL)
{
if (matchesPattern(*i, wildcard, caseSensitive))
i++;
else
{
/* FIXME: This counts on physfs's allocation method not changing! */
free(*i);
for (j = i; *j != NULL; j++)
j[0] = j[1];
} /* else */
} /* for */
return(rc);
} /* PHYSFSEXT_enumerateFilesWildcard */
#ifdef TEST_PHYSFSEXT_ENUMERATEFILESWILDCARD
int main(int argc, char **argv)
{
int rc;
char **flist;
char **i;
if (argc != 3)
{
printf("USAGE: %s <pattern> <caseSen>\n"
" where <caseSen> is 1 or 0.\n", argv[0]);
return(1);
} /* if */
if (!PHYSFS_init(argv[0]))
{
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getLastError());
return(1);
} /* if */
if (!PHYSFS_addToSearchPath(".", 1))
{
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getLastError());
PHYSFS_deinit();
return(1);
} /* if */
flist = PHYSFSEXT_enumerateFilesWildcard("/", argv[1], atoi(argv[2]));
rc = 0;
for (i = flist; *i; i++)
{
printf("%s\n", *i);
rc++;
} /* for */
printf("\n total %d files.\n\n", rc);
PHYSFS_freeList(flist);
PHYSFS_deinit();
return(0);
} /* main */
#endif
/* end of globbing.c ... */
-89
View File
@@ -1,89 +0,0 @@
#ifndef INCL_PHYSFSEXT_GLOBBING_H
#define INCL_PHYSFSEXT_GLOBBING_H
/** \file globbing.h */
/**
* \mainpage PhysicsFS globbing
*
* This is an extension to PhysicsFS to let you search for files with basic
* wildcard matching, regardless of what sort of filesystem or archive they
* reside in. It does this by enumerating directories as needed and manually
* locating matching entries.
*
* Usage: Set up PhysicsFS as you normally would, then use
* PHYSFSEXT_enumerateFilesPattern() when enumerating files. This is just
* like PHYSFS_enumerateFiles(), but it returns a subset that matches your
* wildcard pattern. You must call PHYSFS_freeList() on the results, just
* like you would with PHYSFS_enumerateFiles().
*
* License: this code is public domain. I make no warranty that it is useful,
* correct, harmless, or environmentally safe.
*
* This particular file may be used however you like, including copying it
* verbatim into a closed-source project, exploiting it commercially, and
* removing any trace of my name from the source (although I hope you won't
* do that). I welcome enhancements and corrections to this file, but I do
* not require you to send me patches if you make changes. This code has
* NO WARRANTY.
*
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
* Please see LICENSE.txt in the root of the source tree.
*
* \author Ryan C. Gordon.
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \fn char **PHYSFS_enumerateFilesWildcard(const char *dir, const char *wildcard, int caseSensitive)
* \brief Get a file listing of a search path's directory.
*
* Matching directories are interpolated. That is, if "C:\mydir" is in the
* search path and contains a directory "savegames" that contains "x.sav",
* "y.Sav", and "z.txt", and there is also a "C:\userdir" in the search path
* that has a "savegames" subdirectory with "w.sav", then the following code:
*
* \code
* char **rc = PHYSFS_enumerateFilesWildcard("savegames", "*.sav", 0);
* char **i;
*
* for (i = rc; *i != NULL; i++)
* printf(" * We've got [%s].\n", *i);
*
* PHYSFS_freeList(rc);
* \endcode
*
* ...will print:
*
* \verbatim
* We've got [x.sav].
* We've got [y.Sav].
* We've got [w.sav].\endverbatim
*
* Feel free to sort the list however you like. We only promise there will
* be no duplicates, but not what order the final list will come back in.
*
* Wildcard strings can use the '*' and '?' characters, currently.
* Matches can be case-insensitive if you pass a zero for argument 3.
*
* Don't forget to call PHYSFS_freeList() with the return value from this
* function when you are done with it.
*
* \param dir directory in platform-independent notation to enumerate.
* \return Null-terminated array of null-terminated strings.
*/
__EXPORT__ char **PHYSFSEXT_enumerateFilesWildcard(const char *dir,
const char *wildcard,
int caseSensitive);
#ifdef __cplusplus
}
#endif
#endif /* include-once blocker. */
/* end of globbing.h ... */
@@ -1,103 +0,0 @@
# $Id: installer.rb,v 1.3 2003/07/21 03:46:50 icculus Exp $
require 'rbconfig'
require 'find'
require 'ftools'
include Config
module Slimb
class Installer
def initialize target_dir = "", &user_skip
@user_skip = user_skip or proc {|f| false}
@version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
@libdir = File.join(CONFIG["libdir"], "ruby", @version)
@sitedir = CONFIG["sitedir"] || File.join(@libdir, "site_ruby")
@dest = File.join @sitedir, target_dir
File::makedirs @dest
File::chmod 0755, @dest, true
end
def skip? file
@user_skip[file] or
file[0] == ?. or file[-1] == ?~ or file[-1] == ?#
end
def install_dir dir
File::makedirs(File.join(@dest, dir))
File::chmod(0755, File.join(@dest, dir), true)
Dir.foreach(dir) {|file|
next if skip? file
if File.ftype(File.join(dir, file)) == "directory"
install_dir File.join(dir, file)
else
install_file File.join(dir, file)
end
}
end
def install_file file
if file =~ /\.so$/
install_so file
else
File::install file, File.join(@dest, file), 0644, true
end
end
def install_so file
File::install file, File.join(CONFIG["sitearchdir"], file), 0644, true
end
def uninstall_so file
file = File.join(CONFIG["sitearchdir"], file)
File::safe_unlink file
end
def install something
case something
when Array
something.each {|x|
install x if x.is_a? String
}
when String
if File.ftype(something) == "directory"
install_dir something
else
install_file something
end
end
end
def uninstall what = "*"
case what
when Array
files = what.map {|x| File.join(@dest, x)}
when String
files = Dir[File.join(@dest, what)]
end
files.each {|x|
# FIXME: recursive uninstall is a must
next if FileTest.directory? x
File::safe_unlink x
}
end
def run files, argv
if !argv.grep(/--uninstall/).empty?
uninstall files
else
install files
end
end
end
end
# self-installation
if $0 == __FILE__
$stderr.puts "Installing slimb installer..."
Slimb::Installer.new("slimb").install File.basename(__FILE__)
end
@@ -1,9 +0,0 @@
require 'mkmf'
$CFLAGS += `sdl-config --cflags`.chomp
$LDFLAGS += `sdl-config --libs`.chomp
have_library "physfs", "PHYSFS_init"
have_library "SDL", "SDL_AllocRW"
create_makefile "physfs_so"
@@ -1,7 +0,0 @@
#!/usr/local/bin/ruby
if __FILE__ == $0
require 'slimb/installer'
files = ["physfs.rb", "physfs_so.so"]
installer = Slimb::Installer.new.run files, ARGV
end
@@ -1,9 +0,0 @@
#!/bin/sh
ruby extconf.rb
make
cd ..
ruby installer.rb
cd physfs
ruby install.rb
cd test
ruby test_physfs.rb
@@ -1,121 +0,0 @@
#
# PhysicsFS - ruby interface
#
# Author: Ed Sinjiashvili (slimb@vlinkmail.com)
# License: LGPL
#
require 'physfs_so'
module PhysicsFS
class Version
def initialize major, minor, patch
@major = major
@minor = minor
@patch = patch
end
attr_reader :major, :minor, :patch
def to_s
"#@major.#@minor.#@patch"
end
end
class ArchiveInfo
def initialize ext, desc, author, url
@extension = ext
@description = desc
@author = author
@url = url
end
attr_reader :extension, :description
attr_reader :author, :url
def to_s
" * #@extension: #@description\n Written by #@author.\n #@url\n"
end
end
#
# convenience methods
#
class << self
def init argv0 = $0
init_internal argv0
end
def append_search_path str
add_to_search_path str, 1
self
end
def prepend_search_path str
add_to_search_path str, 0
self
end
alias_method :<<, :append_search_path
alias_method :push, :append_search_path
alias_method :unshift, :prepend_search_path
def ls path = ""
enumerate path
end
end
#
# File - PhysicsFS abstract file - can be drawn from various sources
#
class File
def write_str str
write str, 1, str.length
end
def cat
prev_pos = tell
seek 0
r = read length, 1
seek prev_pos
r
end
alias_method :size, :length
end
#
# RWops - general stdio like operations on file-like creatures
#
class RWops
SEEK_SET = 0
SEEK_CUR = 1
SEEK_END = 2
# tell current position of RWopted entity
def tell
seek 0, SEEK_CUR
end
# length of RWops abstracted entity
def length
cur = tell
r = seek 0, SEEK_END
seek cur, SEEK_SET
r
end
alias_method :size, :length
#
# create rwops from PhysicsFS file object
#
def self.from_physfs file
file.to_rwops
end
end
end
# physfs.rb ends here #
@@ -1,192 +0,0 @@
/*
* This code provides a glue layer between PhysicsFS and Simple Directmedia
* Layer's (SDL) RWops i/o abstraction.
*
* License: this code is public domain. I make no warranty that it is useful,
* correct, harmless, or environmentally safe.
*
* This particular file may be used however you like, including copying it
* verbatim into a closed-source project, exploiting it commercially, and
* removing any trace of my name from the source (although I hope you won't
* do that). I welcome enhancements and corrections to this file, but I do
* not require you to send me patches if you make changes.
*
* Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser
* General Public License: http://www.gnu.org/licenses/lgpl.txt
*
* SDL falls under the LGPL, too. You can get SDL at http://www.libsdl.org/
*
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
*/
#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
#include "physfsrwops.h"
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
{
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
int pos = 0;
if (whence == SEEK_SET)
{
pos = offset;
} /* if */
else if (whence == SEEK_CUR)
{
PHYSFS_sint64 current = PHYSFS_tell(handle);
if (current == -1)
{
SDL_SetError("Can't find position in file: %s",
PHYSFS_getLastError());
return(-1);
} /* if */
pos = (int) current;
if ( ((PHYSFS_sint64) pos) != current )
{
SDL_SetError("Can't fit current file position in an int!");
return(-1);
} /* if */
if (offset == 0) /* this is a "tell" call. We're done. */
return(pos);
pos += offset;
} /* else if */
else if (whence == SEEK_END)
{
PHYSFS_sint64 len = PHYSFS_fileLength(handle);
if (len == -1)
{
SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
return(-1);
} /* if */
pos = (int) len;
if ( ((PHYSFS_sint64) pos) != len )
{
SDL_SetError("Can't fit end-of-file position in an int!");
return(-1);
} /* if */
pos += offset;
} /* else if */
else
{
SDL_SetError("Invalid 'whence' parameter.");
return(-1);
} /* else */
if ( pos < 0 )
{
SDL_SetError("Attempt to seek past start of file.");
return(-1);
} /* if */
if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
{
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
return(-1);
} /* if */
return(pos);
} /* physfsrwops_seek */
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
{
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
PHYSFS_sint64 rc = PHYSFS_read(handle, ptr, size, maxnum);
if (rc != maxnum)
{
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
} /* if */
return((int) rc);
} /* physfsrwops_read */
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
{
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
PHYSFS_sint64 rc = PHYSFS_write(handle, ptr, size, num);
if (rc != num)
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
return((int) rc);
} /* physfsrwops_write */
static int physfsrwops_close(SDL_RWops *rw)
{
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
if (!PHYSFS_close(handle))
{
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
return(-1);
} /* if */
SDL_FreeRW(rw);
return(0);
} /* physfsrwops_close */
static SDL_RWops *create_rwops(PHYSFS_File *handle)
{
SDL_RWops *retval = NULL;
if (handle == NULL)
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
else
{
retval = SDL_AllocRW();
if (retval != NULL)
{
retval->seek = physfsrwops_seek;
retval->read = physfsrwops_read;
retval->write = physfsrwops_write;
retval->close = physfsrwops_close;
retval->hidden.unknown.data1 = handle;
} /* if */
} /* else */
return(retval);
} /* create_rwops */
SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
{
SDL_RWops *retval = NULL;
if (handle == NULL)
SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops().");
else
retval = create_rwops(handle);
return(retval);
} /* PHYSFSRWOPS_makeRWops */
SDL_RWops *PHYSFSRWOPS_openRead(const char *fname)
{
return(create_rwops(PHYSFS_openRead(fname)));
} /* PHYSFSRWOPS_openRead */
SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname)
{
return(create_rwops(PHYSFS_openWrite(fname)));
} /* PHYSFSRWOPS_openWrite */
SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname)
{
return(create_rwops(PHYSFS_openAppend(fname)));
} /* PHYSFSRWOPS_openAppend */
/* end of physfsrwops.c ... */
@@ -1,87 +0,0 @@
/*
* This code provides a glue layer between PhysicsFS and Simple Directmedia
* Layer's (SDL) RWops i/o abstraction.
*
* License: this code is public domain. I make no warranty that it is useful,
* correct, harmless, or environmentally safe.
*
* This particular file may be used however you like, including copying it
* verbatim into a closed-source project, exploiting it commercially, and
* removing any trace of my name from the source (although I hope you won't
* do that). I welcome enhancements and corrections to this file, but I do
* not require you to send me patches if you make changes.
*
* Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser
* General Public License: http://www.gnu.org/licenses/lgpl.txt
*
* SDL falls under the LGPL, too. You can get SDL at http://www.libsdl.org/
*
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
*/
#ifndef _INCLUDE_PHYSFSRWOPS_H_
#define _INCLUDE_PHYSFSRWOPS_H_
#include "physfs.h"
#include "SDL.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Open a platform-independent filename for reading, and make it accessible
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
* RWops is closed. PhysicsFS should be configured to your liking before
* opening files through this method.
*
* @param filename File to open in platform-independent notation.
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
* of the error can be gleaned from PHYSFS_getLastError().
*/
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openRead(const char *fname);
/**
* Open a platform-independent filename for writing, and make it accessible
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
* RWops is closed. PhysicsFS should be configured to your liking before
* opening files through this method.
*
* @param filename File to open in platform-independent notation.
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
* of the error can be gleaned from PHYSFS_getLastError().
*/
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname);
/**
* Open a platform-independent filename for appending, and make it accessible
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
* RWops is closed. PhysicsFS should be configured to your liking before
* opening files through this method.
*
* @param filename File to open in platform-independent notation.
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
* of the error can be gleaned from PHYSFS_getLastError().
*/
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname);
/**
* Make a SDL_RWops from an existing PhysicsFS file handle. You should
* dispose of any references to the handle after successful creation of
* the RWops. The actual PhysicsFS handle will be destroyed when the
* RWops is closed.
*
* @param handle a valid PhysicsFS file handle.
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
* of the error can be gleaned from PHYSFS_getLastError().
*/
__EXPORT__ SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_file *handle);
#ifdef __cplusplus
}
#endif
#endif /* include-once blocker */
/* end of physfsrwops.h ... */
@@ -1,462 +0,0 @@
/*
* PhysicsFS - ruby interface
*
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
* License:: LGPL
*/
#include "physfs.h"
#include "ruby.h"
#include "rb_physfs.h"
#include "rb_physfs_file.h"
VALUE modulePhysfs;
/*
* PhysicsFS::init str
*
* initialize PhysicsFS
*/
VALUE physfs_init (VALUE self, VALUE str)
{
int result = PHYSFS_init (STR2CSTR(str));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::deinit
*/
VALUE physfs_deinit (VALUE self)
{
if (PHYSFS_deinit ())
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::version
*
* return PhysicsFS::Version object
*/
VALUE physfs_version (VALUE self)
{
char evalStr[200];
PHYSFS_Version ver;
PHYSFS_getLinkedVersion (&ver);
sprintf (evalStr, "PhysicsFS::Version.new %d, %d, %d",
ver.major, ver.minor, ver.patch);
return rb_eval_string (evalStr);
}
/*
* PhysicsFS::supported_archives
*
* return Array of PhysicsFS::ArchiveInfo objects
*/
VALUE physfs_supported_archives (VALUE self)
{
const PHYSFS_ArchiveInfo **info = PHYSFS_supportedArchiveTypes();
VALUE klass = rb_const_get (modulePhysfs, rb_intern ("ArchiveInfo"));
VALUE ary = rb_ary_new ();
VALUE params[4];
while ( *info != 0 )
{
params[0] = rb_str_new2 ((*info)->extension);
params[1] = rb_str_new2 ((*info)->description);
params[2] = rb_str_new2 ((*info)->author);
params[3] = rb_str_new2 ((*info)->url);
rb_ary_push (ary, rb_class_new_instance (4, params, klass));
info++;
}
return ary;
}
/*
* PhysicsFS::last_error
*
* return string representation of last PhysicsFS error
*/
VALUE physfs_last_error (VALUE self)
{
const char *last_error = PHYSFS_getLastError ();
if (last_error == 0)
last_error = "";
return rb_str_new2 (last_error);
}
/*
* PhysicsFS::dir_separator
*
* return platform directory separator
*/
VALUE physfs_dir_separator (VALUE self)
{
return rb_str_new2 (PHYSFS_getDirSeparator ());
}
/*
* PhysicsFS::permit_symlinks boolValue
*
* turn symlinks support on/off
*/
VALUE physfs_permit_symlinks (VALUE self, VALUE allow)
{
int p = 1;
if (allow == Qfalse || allow == Qnil)
p = 0;
PHYSFS_permitSymbolicLinks (p);
return Qtrue;
}
/*
* PhysicsFS::cdrom_dirs
*
* return Array of strings containing available CDs
*/
VALUE physfs_cdrom_dirs (VALUE self)
{
char **cds = PHYSFS_getCdRomDirs();
char **i;
VALUE ary = rb_ary_new ();
for (i = cds; *i != 0; i++)
rb_ary_push (ary, rb_str_new2 (*i));
PHYSFS_freeList (cds);
return ary;
}
/*
* PhysicsFS::base_dir
*
* return base directory
*/
VALUE physfs_base_dir (VALUE self)
{
const char *base_dir = PHYSFS_getBaseDir ();
if (base_dir == 0)
base_dir = "";
return rb_str_new2 (base_dir);
}
/*
* PhysicsFS::user_dir
*
* return user directory
*/
VALUE physfs_user_dir (VALUE self)
{
const char *user_dir = PHYSFS_getBaseDir ();
if (user_dir == 0)
user_dir = "";
return rb_str_new2 (user_dir);
}
/*
* PhysicsFS::write_dir
*
* return write directory
*/
VALUE physfs_write_dir (VALUE self)
{
const char *write_dir = PHYSFS_getWriteDir ();
if (write_dir == 0)
return Qnil;
return rb_str_new2 (write_dir);
}
/*
* PhysicsFS::write_dir= str
*
* set write directory to *str*
*/
VALUE physfs_set_write_dir (VALUE self, VALUE str)
{
int result = PHYSFS_setWriteDir (STR2CSTR(str));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::add_to_search_path str, append
*
* if append > 0 - append str to search path, otherwise prepend it
*/
VALUE physfs_add_search_path (VALUE self, VALUE str, VALUE append)
{
int result = PHYSFS_addToSearchPath (STR2CSTR(str), FIX2INT(append));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::remove_from_search_path str
*
* removes str from search path
*/
VALUE physfs_remove_search_path (VALUE self, VALUE str)
{
int result = PHYSFS_removeFromSearchPath (STR2CSTR(str));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::search_path
*
* return current search_path - as array of strings
*/
VALUE physfs_search_path (VALUE self)
{
char **path = PHYSFS_getSearchPath ();
char **i;
VALUE ary = rb_ary_new ();
for (i = path ; *i != 0; i++)
rb_ary_push (ary, rb_str_new2 (*i));
PHYSFS_freeList (path);
return ary;
}
//
VALUE physfs_setSaneConfig(VALUE self, VALUE org, VALUE app, VALUE ext,
VALUE includeCdroms, VALUE archivesFirst)
{
int res = PHYSFS_setSaneConfig (STR2CSTR(org), STR2CSTR(app), STR2CSTR(ext),
RTEST(includeCdroms), RTEST(archivesFirst));
if (res)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::mkdir newdir
*
* create new directory
*/
VALUE physfs_mkdir (VALUE self, VALUE newdir)
{
int result = PHYSFS_mkdir (STR2CSTR(newdir));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::delete name
*
* delete file with name
*/
VALUE physfs_delete (VALUE self, VALUE name)
{
int result = PHYSFS_delete (STR2CSTR(name));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::real_dir name
*
* return real directory (in search path) of a name
*/
VALUE physfs_real_dir (VALUE self, VALUE name)
{
const char *path = PHYSFS_getRealDir (STR2CSTR(name));
if (path == 0)
return Qnil;
return rb_str_new2 (path);
}
/*
* PhysicsFS::enumerate dir
*
* list a dir from a search path
*/
VALUE physfs_enumerate (VALUE self, VALUE dir)
{
char **files = PHYSFS_enumerateFiles (STR2CSTR(dir));
char **i;
VALUE ary = rb_ary_new ();
for (i = files; *i != 0; i++)
rb_ary_push (ary, rb_str_new2 (*i));
PHYSFS_freeList (files);
return ary;
}
/*
* PhysicsFS::exists? name
*
* does a file with name exist?
*/
VALUE physfs_exists (VALUE self, VALUE name)
{
int result = PHYSFS_exists (STR2CSTR(name));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::is_directory? name
*
* return true if name is directory
*/
VALUE physfs_is_directory (VALUE self, VALUE name)
{
int result = PHYSFS_isDirectory (STR2CSTR(name));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::is_symlink? name
*
* return true if name is symlink
*/
VALUE physfs_is_symlink (VALUE self, VALUE name)
{
int result = PHYSFS_isSymbolicLink (STR2CSTR(name));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::last_mod_time name
*
* return last modification time of a file
*/
VALUE physfs_last_mod_time (VALUE self, VALUE name)
{
int result = PHYSFS_getLastModTime (STR2CSTR(name));
return INT2FIX(result);
}
/*
* PhysicsFS::open_read name
*
* return +PhysicsFS::File+ ready for reading
*/
VALUE physfs_open_read (VALUE self, VALUE name)
{
PHYSFS_File *file = PHYSFS_openRead (STR2CSTR(name));
return physfs_file_new (file);
}
/*
* PhysicsFS::open_write name
*
* return PhysicsFS::File ready for writing
*/
VALUE physfs_open_write (VALUE self, VALUE name)
{
PHYSFS_File *file = PHYSFS_openWrite (STR2CSTR(name));
return physfs_file_new (file);
}
/*
* PhysicsFS::open_append name
*
* return PhysicsFS::File ready for appending
*/
VALUE physfs_open_append (VALUE self, VALUE name)
{
PHYSFS_File *file = PHYSFS_openAppend (STR2CSTR(name));
return physfs_file_new (file);
}
void Init_physfs_so (void)
{
modulePhysfs = rb_define_module ("PhysicsFS");
rb_define_singleton_method (modulePhysfs, "init_internal", physfs_init, 1);
rb_define_singleton_method (modulePhysfs, "deinit", physfs_deinit, 0);
rb_define_singleton_method (modulePhysfs, "version", physfs_version, 0);
rb_define_singleton_method (modulePhysfs, "supported_archives",
physfs_supported_archives, 0);
rb_define_singleton_method (modulePhysfs, "last_error",
physfs_last_error, 0);
rb_define_singleton_method (modulePhysfs, "dir_separator",
physfs_dir_separator, 0);
rb_define_singleton_method (modulePhysfs, "permit_symlinks",
physfs_permit_symlinks, 1);
rb_define_singleton_method (modulePhysfs, "cdrom_dirs",
physfs_cdrom_dirs, 0);
rb_define_singleton_method (modulePhysfs, "base_dir", physfs_base_dir, 0);
rb_define_singleton_method (modulePhysfs, "user_dir", physfs_user_dir, 0);
rb_define_singleton_method (modulePhysfs, "write_dir", physfs_write_dir, 0);
rb_define_singleton_method (modulePhysfs, "write_dir=",
physfs_set_write_dir, 1);
rb_define_singleton_method (modulePhysfs, "add_to_search_path",
physfs_add_search_path, 2);
rb_define_singleton_method (modulePhysfs, "remove_from_search_path",
physfs_remove_search_path, 1);
rb_define_singleton_method (modulePhysfs, "search_path",
physfs_search_path, 0);
rb_define_singleton_method (modulePhysfs, "set_sane_config",
physfs_setSaneConfig, 5);
rb_define_singleton_method (modulePhysfs, "mkdir", physfs_mkdir, 1);
rb_define_singleton_method (modulePhysfs, "delete", physfs_delete, 1);
rb_define_singleton_method (modulePhysfs, "real_dir",
physfs_real_dir, 1);
rb_define_singleton_method (modulePhysfs, "enumerate", physfs_enumerate, 1);
rb_define_singleton_method (modulePhysfs, "exists?", physfs_exists, 1);
rb_define_singleton_method (modulePhysfs, "is_directory?",
physfs_is_directory, 1);
rb_define_singleton_method (modulePhysfs, "is_symlink?",
physfs_is_symlink, 1);
rb_define_singleton_method (modulePhysfs, "last_mod_time",
physfs_last_mod_time, 1);
rb_define_singleton_method (modulePhysfs, "open_read",
physfs_open_read, 1);
rb_define_singleton_method (modulePhysfs, "open_write",
physfs_open_write, 1);
rb_define_singleton_method (modulePhysfs, "open_append",
physfs_open_append, 1);
init_physfs_file ();
init_sdl_rwops ();
}
/*
// Local Variables:
// mode: C
// c-indentation-style: "stroustrup"
// indent-tabs-mode: nil
// End:
*/
@@ -1,13 +0,0 @@
/*
* PhysicsFS - ruby interface
*
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
* License:: LGPL
*/
#ifndef __RB__PHYSFS__H__
#define __RB__PHYSFS__H__
extern VALUE modulePhysfs;
#endif
@@ -1,226 +0,0 @@
/*
* PhysicsFS File abstraction - ruby interface
*
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
* License:: LGPL
*/
#include "physfs.h"
#include "ruby.h"
#include "rb_physfs.h"
#include "rb_physfs_file.h"
#include "physfsrwops.h"
VALUE classPhysfsFile;
/*
* construct new PhysicsFS::File object
*/
VALUE physfs_file_new (PHYSFS_File *file)
{
if (file == 0)
return Qnil;
return Data_Wrap_Struct (classPhysfsFile, 0, 0, file);
}
/*
* PhysicsFS::File#close
*
* Close the file. It's illegal to use the object after its closure.
*/
VALUE physfs_file_close (VALUE self)
{
int result;
PHYSFS_File *file;
Data_Get_Struct (self, PHYSFS_File, file);
if (file == 0)
return Qfalse;
result = PHYSFS_close (file);
DATA_PTR(self) = 0;
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::File#read obj_size, num_objects
*
* Read *objCount* objects which are *objSize* each.
* return String instance containing raw data or nil if failure.
* #length of string will reflect real number of objects read.
*/
VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount)
{
int objRead;
void *buffer;
VALUE result;
PHYSFS_File *file;
Data_Get_Struct (self, PHYSFS_File, file);
if (file == 0)
return Qnil; //wasted file - no read possible
buffer = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
if (buffer == 0)
return Qnil;
objRead = PHYSFS_read (file, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
if (objRead == -1)
{
free (buffer);
return Qnil;
}
result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
free (buffer);
return result;
}
/*
* PhysicsFS::File#write buffer, obj_size, num_objects
*
* return nil on failure or number of objects written.
*/
VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount)
{
int result;
PHYSFS_File *file;
Data_Get_Struct (self, PHYSFS_File, file);
if (file == 0)
return Qnil;
result = PHYSFS_write (file, STR2CSTR(buf),
FIX2UINT(objSize), FIX2UINT(objCount));
if (result == -1)
return Qnil;
return INT2FIX(result);
}
/*
* PhysicsFS::File#eof?
*/
VALUE physfs_file_eof (VALUE self)
{
int result;
PHYSFS_File *file;
Data_Get_Struct (self, PHYSFS_File, file);
if (file == 0)
return Qnil;
result = PHYSFS_eof (file);
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::File#tell
*
* tells current position in file
*/
VALUE physfs_file_tell (VALUE self)
{
int result;
PHYSFS_File *file;
Data_Get_Struct (self, PHYSFS_File, file);
if (file == 0)
return Qnil;
result = PHYSFS_tell (file);
if (result == -1)
return Qnil;
return INT2FIX(result);
}
/*
* PhysicsFS::File#seek pos
*
* seek to pos in file
*/
VALUE physfs_file_seek (VALUE self, VALUE pos)
{
int result;
PHYSFS_File *file;
Data_Get_Struct (self, PHYSFS_File, file);
if (file == 0)
return Qnil;
result = PHYSFS_seek (file, FIX2LONG(pos));
if (result)
return Qtrue;
return Qfalse;
}
/*
* PhysicsFS::File#length
*/
VALUE physfs_file_length (VALUE self)
{
int result;
PHYSFS_File *file;
Data_Get_Struct (self, PHYSFS_File, file);
if (file == 0)
return Qnil;
result = PHYSFS_fileLength (file);
if (result == -1)
return Qnil;
return INT2FIX(result);
}
/*
* PhysicsFS::File#to_rwops
*
* File object is converted to RWops object.
* File object becomes unusable after that - every operation
* should be done through new-born RWops object.
*/
VALUE physfs_file_to_rwops (VALUE self)
{
PHYSFS_File *file;
SDL_RWops *rwops;
Data_Get_Struct (self, PHYSFS_File, file);
if (file == 0)
return Qnil;
rwops = PHYSFSRWOPS_makeRWops (file);
if (rwops == 0)
return Qnil;
DATA_PTR(self) = 0; // oh, gosh, we've sacrificed ourselves!
return sdl_rwops_new (rwops);
}
void init_physfs_file (void)
{
classPhysfsFile = rb_define_class_under (modulePhysfs, "File", rb_cObject);
rb_define_method (classPhysfsFile, "close", physfs_file_close, 0);
rb_define_method (classPhysfsFile, "eof?", physfs_file_eof, 0);
rb_define_method (classPhysfsFile, "tell", physfs_file_tell, 0);
rb_define_method (classPhysfsFile, "seek", physfs_file_seek, 1);
rb_define_method (classPhysfsFile, "length", physfs_file_length, 0);
rb_define_method (classPhysfsFile, "read", physfs_file_read, 2);
rb_define_method (classPhysfsFile, "write", physfs_file_write, 3);
rb_define_method (classPhysfsFile, "to_rwops", physfs_file_to_rwops, 0);
}
@@ -1,24 +0,0 @@
/*
* PhysicsFS File abstraction - ruby interface
*
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
* License:: LGPL
*/
#ifndef __RB__PHYSFS__FILE__H__
#define __RB__PHYSFS__FILE__H__
extern VALUE classPhysfsFile;
VALUE physfs_file_new (PHYSFS_file *file);
VALUE physfs_file_close (VALUE self);
VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount);
VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount);
VALUE physfs_file_eof (VALUE self);
VALUE physfs_file_tell (VALUE self);
VALUE physfs_file_seek (VALUE self, VALUE pos);
VALUE physfs_file_length (VALUE self);
void init_physfs_file (void);
#endif
@@ -1,162 +0,0 @@
/*
* SDL_RWops - ruby interface
*
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
* License:: LGPL
*/
#include "SDL_rwops.h"
#include "ruby.h"
#include "rb_physfs.h"
#include "rb_sdl_rwops.h"
VALUE classRWops;
/*
* RWops constructor
*/
VALUE sdl_rwops_new (SDL_RWops *ops)
{
VALUE result;
if (ops == 0)
return Qnil;
result = Data_Wrap_Struct (classRWops, 0, SDL_FreeRW, ops);
return result;
}
/*
* PhysicsFS::RWops::from_file name, mode
*
* create RWops object from file
*/
VALUE sdl_rwops_from_file (VALUE self, VALUE name, VALUE mode)
{
SDL_RWops *ops = SDL_RWFromFile(STR2CSTR(name), STR2CSTR(mode));
return sdl_rwops_new (ops);
}
/*
* PhysicsFS::RWops::from_memory string
*
* create RWops object from memory
*/
VALUE sdl_rwops_from_mem (VALUE self, VALUE str)
{
int len = RSTRING(str)->len;
void *mem = STR2CSTR(str);
SDL_RWops *ops = SDL_RWFromMem(mem, len);
return sdl_rwops_new (ops);
}
/*
* PhysicsFS::RWops#seek offset, whence
*
* position RWops object
*/
VALUE sdl_rwops_seek (VALUE self, VALUE offset, VALUE whence)
{
int result;
SDL_RWops *ops;
Data_Get_Struct (self, SDL_RWops, ops);
if (ops == 0)
return Qnil;
result = SDL_RWseek(ops, FIX2INT(offset), FIX2INT(whence));
return INT2FIX(result);
}
/*
* PhysicsFS::RWops#close
*
* close RWops. No use of the object is possible after that.
*/
VALUE sdl_rwops_close (VALUE self)
{
int result;
SDL_RWops *ops;
Data_Get_Struct (self, SDL_RWops, ops);
if (ops == 0)
return Qnil;
result = SDL_RWclose (ops);
DATA_PTR(self) = 0;
return INT2FIX(result);
}
/*
* PhysicsFS::RWops#read
*
* read from RWops object objCount objSize'd entities.
* return string containing raw data or nil
*/
VALUE sdl_rwops_read (VALUE self, VALUE objSize, VALUE objCount)
{
int objRead;
void *buffer;
VALUE result;
SDL_RWops *ops;
Data_Get_Struct (self, SDL_RWops, ops);
if (ops == 0)
return Qnil;
buffer = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
if (buffer == 0)
return Qnil;
objRead = SDL_RWread (ops, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
if (objRead == -1)
{
free (buffer);
return Qnil;
}
result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
free (buffer);
return result;
}
/*
* PhysicsFS::RWops#write buffer, size, n
*
* write raw string containing n objects size length each.
* return number of objects written or nil
*/
VALUE sdl_rwops_write (VALUE self, VALUE buffer, VALUE size, VALUE n)
{
int result;
SDL_RWops *ops;
Data_Get_Struct (self, SDL_RWops, ops);
if (ops == 0)
return Qnil;
result = SDL_RWwrite (ops, STR2CSTR(buffer), FIX2INT(size), FIX2INT(n));
if (result == -1)
return Qnil;
return INT2FIX(result);
}
void init_sdl_rwops (void)
{
classRWops = rb_define_class_under (modulePhysfs, "RWops", rb_cObject);
rb_define_method (classRWops, "seek", sdl_rwops_seek, 2);
rb_define_method (classRWops, "read", sdl_rwops_read, 2);
rb_define_method (classRWops, "write", sdl_rwops_write, 3);
rb_define_method (classRWops, "close", sdl_rwops_close, 0);
rb_define_singleton_method (classRWops, "from_file",
sdl_rwops_from_file, 2);
rb_define_singleton_method (classRWops, "from_memory",
sdl_rwops_from_mem, 1);
}
@@ -1,16 +0,0 @@
/*
* SDL_RWops - ruby interface
*
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
* License:: LGPL
*/
#ifndef __RB__SDL__RWOPS__H__
#define __RB__SDL__RWOPS__H__
extern VALUE classRWops;
VALUE sdl_rwops_new (SDL_RWops *ops);
void init_sdl_rwops (void);
#endif
@@ -1,358 +0,0 @@
#
# PhysicsFS test program - mimics real physfs_test
#
require 'readline'
require 'physfs'
def die msg
puts "#{msg} - reason: #{PhysicsFS.last_error}"
end
#
# parse line to command and args
#
def parse line
return false if line.nil?
if line.strip =~ /^(.*?) (?: (?:\s+(.*)) | $)/x
run $1, $2
else
false
end
end
#
# parse command args
#
def parse_args args
args.strip!
dquoted = /^ " (.*?) "/x
squoted = /^ ' (.*?) '/x
unquoted = /^([^\s\'\"]+)/
regexps = [dquoted, squoted, unquoted]
result = []
while args != ""
regexps.each do |r|
if args =~ r
result << $1
args.sub! r, ""
args.sub!(/\s+/, "")
break
end
end
end
result
end
def usage cmd, prefix = "usage: "
print prefix
args = Commands::HELP[cmd]
if args
print cmd
args.scan(/\w+/).each {|x|
print " <#{x}>"
}
puts
else
puts %|#{cmd} (no arguments)|
end
end
# commands go below
module Commands
HELP = {
"init" => "argv0",
"addarchive" => "archiveLocation append",
"removearchive" => "archiveLocation",
"enumerate" => "dirToEnumerate",
"ls" => "dirToEnumerate",
"setwritedir" => "newWriteDir",
"permitsymlinks" => "1or0",
"setsaneconfig" => "org appName arcExt includeCdRoms archivesFirst",
"mkdir" => "dirToMk",
"delete" => "dirToDelete",
"getrealdir" => "fileToFind",
"exists" => "fileToCheck",
"isdir" => "fileToCheck",
"issymlink" => "fileToCheck",
"cat" => "fileToCat",
"filelength" => "fileToCheck",
"append" => "fileToAppend",
"write" => "fileToCreateOrTrash",
"getlastmodtime" => "fileToExamine"
}
def quit_cmd
exit
end
alias q_cmd quit_cmd
def help_cmd
commands = ::Commands.instance_methods.grep(/_cmd$/).sort
puts "Commands:"
commands.each do |c|
usage c.sub("_cmd", ""), " - "
end
true
end
def e val
if val
puts "Successful."
else
puts "Failure. reason: #{PhysicsFS.last_error}"
end
true
end
def init_cmd arg
e PhysicsFS.init(arg)
end
def deinit_cmd
e PhysicsFS.deinit
end
def addarchive_cmd archive, append
e PhysicsFS.add_to_search_path(archive, append)
end
def removearchive_cmd archive
e PhysicsFS.remove_from_search_path archive
end
def enumerate_cmd path
entries = PhysicsFS.enumerate(path)
entries.each {|x|
puts x
}
true
end
alias ls_cmd enumerate_cmd
def getlasterror_cmd
puts "Last error is [#{PhysicsFS.last_error}]"
true
end
def getdirsep_cmd
puts "Directory separator is [#{PhysicsFS.dir_separator}]"
true
end
def getcdromdirs_cmd
dirs = PhysicsFS.cdrom_dirs
dirs.each {|x|
puts x
}
puts " total [#{dirs.length}] drives."
true
end
def getsearchpath_cmd
spath = PhysicsFS.search_path
spath.each {|x|
puts x
}
puts "total [#{spath.length}] directories."
true
end
def getbasedir_cmd
dir = PhysicsFS.base_dir
puts dir if dir
true
end
def getuserdir_cmd
puts PhysicsFS.user_dir
true
end
def getwritedir_cmd
dir = PhysicsFS.write_dir
if dir
puts "Write directory is [#{dir}]."
else
puts "No write directory defined."
end
true
end
def setwritedir_cmd dir
e(PhysicsFS.write_dir = dir)
end
def permitsymlinks_cmd val
if val.to_i == 1
PhysicsFS.permit_symlinks true
puts "Symlinks are now permitted"
else
PhysicsFS.permit_symlinks false
puts "Symlinks are now forbidden"
end
true
end
def setsaneconfig_cmd org, appname, ext, includeCdroms, archivesFirst
includeCdroms = includeCdroms.to_i == 1
archiveFirst = archivesFirst == 1
e PhysicsFS.set_sane_config(org, appname, ext, includeCdroms, archivesFirst)
end
def mkdir_cmd dir
e PhysicsFS.mkdir(dir)
end
def delete_cmd dir
e PhysicsFS.delete(dir)
end
def getrealdir_cmd file
dir = PhysicsFS.real_dir file
if dir
puts "Found at [#{dir}]"
else
puts "Not found."
end
true
end
def exists_cmd file
if PhysicsFS.exists? file
puts "File exists"
else
puts "File does not exist"
end
true
end
def isdir_cmd file
if PhysicsFS.is_directory? file
puts "File is a directory"
else
puts "File is NOT a directory"
end
true
end
def issymlink_cmd file
if PhysicsFS.is_symlink? file
puts "File is a symlink"
else
puts "File is NOT a symlink"
end
true
end
def cat_cmd filename
file = PhysicsFS.open_read filename
if file.nil?
puts "failed to open. reason: #{PhysicsFS.last_error}"
return true
end
puts file.cat
true
end
def filelength_cmd filename
file = PhysicsFS.open_read filename
if file.nil?
puts "failed to open. reason: #{PhysicsFS.last_error}"
return true
end
puts file.length
file.close
true
end
WRITE_STR = "Rubyfied PhysicsFS works just fine.\n\n"
def append_cmd filename
file = PhysicsFS.open_append filename
if file.nil?
puts "failed to open. reason: #{PhysicsFS.last_error}"
return true
end
file.write WRITE_STR, 1, WRITE_STR.length
file.close
true
end
def write_cmd filename
file = PhysicsFS.open_write filename
if file.nil?
puts "failed to open. reason: #{PhysicsFS.last_error}"
return true
end
file.write_str WRITE_STR
file.close
true
end
def getlastmodtime_cmd filename
t = PhysicsFS.last_mod_time filename
if t == -1
puts "failed to determin. reason: #{PhysicsFS.last_error}"
else
puts "Last modified: #{Time.at(t)}"
end
true
end
end
include Commands
def run command, args
if args
args = parse_args args
else
args = []
end
begin
cmd = method "#{command}_cmd"
if args.length == cmd.arity
return cmd.call *args
else
usage command
true
end
rescue NameError
puts 'Unknown command. Enter "help" for instructions.'
true
end
end
if __FILE__ == $0
PhysicsFS.init($0) or die "PhysicsFS init failed"
puts "PhysicsFS version: #{PhysicsFS.version}"
puts
puts "Supported archives: "
puts PhysicsFS.supported_archives
puts
puts 'Enter commands. Enter "help" for instructions.'
loop {
line = Readline::readline "physfs_rb> ", true
break unless parse line
}
end
-181
View File
@@ -1,181 +0,0 @@
@echo off
rem this is a simple batch file to build PhysicsFS on OS/2. You need to have
rem the Innotek libc and GCC (or "kLIBC") installed for this to work:
rem
rem http://svn.netlabs.org/libc
rem
rem This script (and, indeed, our OS/2 support) could use some tweaking.
rem Patches go to icculus@icculus.org ...
set PHYSFSLANG=PHYSFS_LANG_ENGLISH
set DEBUGFLAGS=-D_NDEBUG -O2 -s
rem set CFLAGS=%DEBUGFLAGS% -Wall -Werror -Zomf -Zmt -Zmtd -I. -Izlib123 -c -D__ST_MT_ERRNO__ -DOS2 -DZ_PREFIX -DPHYSFS_SUPPORTS_ZIP -DPHYSFS_SUPPORTS_7Z -DPHYSFS_SUPPORTS_GRP -DPHYSFS_SUPPORTS_WAD -DPHYSFS_SUPPORTS_QPAK -DPHYSFS_SUPPORTS_HOG -DPHYSFS_SUPPORTS_MVL -DPHYSFS_LANG=%PHYSFSLANG% -DHAVE_ASSERT_H
set CFLAGS=%DEBUGFLAGS% -Wall -Werror -Zomf -I. -Iz -c -D__ST_MT_ERRNO__ -DOS2 -DZ_PREFIX -DPHYSFS_SUPPORTS_ZIP -DPHYSFS_SUPPORTS_7Z -DPHYSFS_SUPPORTS_GRP -DPHYSFS_SUPPORTS_WAD -DPHYSFS_SUPPORTS_QPAK -DPHYSFS_SUPPORTS_HOG -DPHYSFS_SUPPORTS_MVL -DHAVE_ASSERT_H
rem goto :dolinking
@echo cleaning up any previous build...
@mkdir bin 2>NUL
@erase /N bin\*.* 2>NUL
@echo Building export definitions...
@echo ;don't edit this directly! It is rewritten by makeos2.cmd! > bin\test_physfs.def
@echo NAME TESTPHYSFS WINDOWCOMPAT >> bin\test_physfs.def
@echo DESCRIPTION 'PhysicsFS: http://icculus.org/physfs/' >> bin\test_physfs.def
@echo STACKSIZE 0x10000 >> bin\test_physfs.def
@echo BASE=0x10000 >> bin\test_physfs.def
@echo PROTMODE >> bin\test_physfs.def
@echo ;don't edit this directly! It is rewritten by makeos2.cmd! > bin\physfs.def
@echo LIBRARY 'physfs' INITINSTANCE TERMINSTANCE >> bin\physfs.def
@echo STACKSIZE 0x10000 >> bin\physfs.def
@echo CODE LOADONCALL >> bin\physfs.def
@echo DATA LOADONCALL NONSHARED MULTIPLE >> bin\physfs.def
@echo DESCRIPTION 'PhysicsFS: http://icculus.org/physfs/' >> bin\physfs.def
@echo EXPORTS >> bin\physfs.def
@echo "_PHYSFS_getLinkedVersion" >> bin\physfs.def
@echo "_PHYSFS_init" >> bin\physfs.def
@echo "_PHYSFS_deinit" >> bin\physfs.def
@echo "_PHYSFS_isInit" >> bin\physfs.def
@echo "_PHYSFS_supportedArchiveTypes" >> bin\physfs.def
@echo "_PHYSFS_freeList" >> bin\physfs.def
@echo "_PHYSFS_getLastError" >> bin\physfs.def
@echo "_PHYSFS_getDirSeparator" >> bin\physfs.def
@echo "_PHYSFS_permitSymbolicLinks" >> bin\physfs.def
@echo "_PHYSFS_symbolicLinksPermitted" >> bin\physfs.def
@echo "_PHYSFS_getCdRomDirs" >> bin\physfs.def
@echo "_PHYSFS_getBaseDir" >> bin\physfs.def
@echo "_PHYSFS_getUserDir" >> bin\physfs.def
@echo "_PHYSFS_getWriteDir" >> bin\physfs.def
@echo "_PHYSFS_setWriteDir" >> bin\physfs.def
@echo "_PHYSFS_addToSearchPath" >> bin\physfs.def
@echo "_PHYSFS_removeFromSearchPath" >> bin\physfs.def
@echo "_PHYSFS_getSearchPath" >> bin\physfs.def
@echo "_PHYSFS_setSaneConfig" >> bin\physfs.def
@echo "_PHYSFS_mkdir" >> bin\physfs.def
@echo "_PHYSFS_delete" >> bin\physfs.def
@echo "_PHYSFS_getRealDir" >> bin\physfs.def
@echo "_PHYSFS_enumerateFiles" >> bin\physfs.def
@echo "_PHYSFS_exists" >> bin\physfs.def
@echo "_PHYSFS_isDirectory" >> bin\physfs.def
@echo "_PHYSFS_isSymbolicLink" >> bin\physfs.def
@echo "_PHYSFS_openWrite" >> bin\physfs.def
@echo "_PHYSFS_openAppend" >> bin\physfs.def
@echo "_PHYSFS_openRead" >> bin\physfs.def
@echo "_PHYSFS_close" >> bin\physfs.def
@echo "_PHYSFS_read" >> bin\physfs.def
@echo "_PHYSFS_write" >> bin\physfs.def
@echo "_PHYSFS_eof" >> bin\physfs.def
@echo "_PHYSFS_tell" >> bin\physfs.def
@echo "_PHYSFS_seek" >> bin\physfs.def
@echo "_PHYSFS_fileLength" >> bin\physfs.def
@echo "_PHYSFS_swapSLE16" >> bin\physfs.def
@echo "_PHYSFS_swapULE16" >> bin\physfs.def
@echo "_PHYSFS_swapSLE32" >> bin\physfs.def
@echo "_PHYSFS_swapULE32" >> bin\physfs.def
@echo "_PHYSFS_swapSLE64" >> bin\physfs.def
@echo "_PHYSFS_swapULE64" >> bin\physfs.def
@echo "_PHYSFS_swapSBE16" >> bin\physfs.def
@echo "_PHYSFS_swapUBE16" >> bin\physfs.def
@echo "_PHYSFS_swapSBE32" >> bin\physfs.def
@echo "_PHYSFS_swapUBE32" >> bin\physfs.def
@echo "_PHYSFS_swapSBE64" >> bin\physfs.def
@echo "_PHYSFS_swapUBE64" >> bin\physfs.def
@echo "_PHYSFS_getLastModTime" >> bin\physfs.def
@echo "_PHYSFS_readSLE16" >> bin\physfs.def
@echo "_PHYSFS_readULE16" >> bin\physfs.def
@echo "_PHYSFS_readSLE32" >> bin\physfs.def
@echo "_PHYSFS_readULE32" >> bin\physfs.def
@echo "_PHYSFS_readSLE64" >> bin\physfs.def
@echo "_PHYSFS_readULE64" >> bin\physfs.def
@echo "_PHYSFS_readSBE16" >> bin\physfs.def
@echo "_PHYSFS_readUBE16" >> bin\physfs.def
@echo "_PHYSFS_readSBE32" >> bin\physfs.def
@echo "_PHYSFS_readUBE32" >> bin\physfs.def
@echo "_PHYSFS_readSBE64" >> bin\physfs.def
@echo "_PHYSFS_readUBE64" >> bin\physfs.def
@echo "_PHYSFS_writeSLE16" >> bin\physfs.def
@echo "_PHYSFS_writeULE16" >> bin\physfs.def
@echo "_PHYSFS_writeSLE32" >> bin\physfs.def
@echo "_PHYSFS_writeULE32" >> bin\physfs.def
@echo "_PHYSFS_writeSLE64" >> bin\physfs.def
@echo "_PHYSFS_writeULE64" >> bin\physfs.def
@echo "_PHYSFS_writeSBE16" >> bin\physfs.def
@echo "_PHYSFS_writeUBE16" >> bin\physfs.def
@echo "_PHYSFS_writeSBE32" >> bin\physfs.def
@echo "_PHYSFS_writeUBE32" >> bin\physfs.def
@echo "_PHYSFS_writeSBE64" >> bin\physfs.def
@echo "_PHYSFS_writeUBE64" >> bin\physfs.def
@echo "_PHYSFS_setBuffer" >> bin\physfs.def
@echo "_PHYSFS_flush" >> bin\physfs.def
@echo "_PHYSFS_mount" >> bin\physfs.def
@echo "_PHYSFS_getMountPoint" >> bin\physfs.def
@echo "_PHYSFS_setAllocator" >> bin\physfs.def
@echo "_PHYSFS_getCdRomDirsCallback" >> bin\physfs.def
@echo "_PHYSFS_getSearchPathCallback" >> bin\physfs.def
@echo "_PHYSFS_enumerateFilesCallback" >> bin\physfs.def
@echo "_PHYSFS_utf8ToUcs2" >> bin\physfs.def
@echo "_PHYSFS_utf8FromUcs2" >> bin\physfs.def
@echo "_PHYSFS_utf8ToUcs4" >> bin\physfs.def
@echo "_PHYSFS_utf8FromUcs4" >> bin\physfs.def
@echo "_PHYSFS_utf8FromLatin1" >> bin\physfs.def
@echo Building export library...
emximp -o bin/physfs.lib bin/physfs.def
emximp -o bin/physfs.a bin/physfs.def
@echo Compiling PhysicsFS library...
@echo on
gcc %CFLAGS% -o bin/physfs.obj physfs.c
gcc %CFLAGS% -o bin/physfs_byteorder.obj physfs_byteorder.c
gcc %CFLAGS% -o bin/physfs_unicode.obj physfs_unicode.c
gcc %CFLAGS% -o bin/os2.obj platform/os2.c
gcc %CFLAGS% -o bin/dir.obj archivers/dir.c
gcc %CFLAGS% -o bin/grp.obj archivers/grp.c
gcc %CFLAGS% -o bin/wad.obj archivers/wad.c
gcc %CFLAGS% -o bin/lzma.obj archivers/lzma.c
gcc %CFLAGS% -o bin/zip.obj archivers/zip.c
gcc %CFLAGS% -o bin/qpak.obj archivers/qpak.c
gcc %CFLAGS% -o bin/hog.obj archivers/hog.c
gcc %CFLAGS% -o bin/mvl.obj archivers/mvl.c
gcc %CFLAGS% -o bin/adler32.obj zlib123/adler32.c
gcc %CFLAGS% -o bin/compress.obj zlib123/compress.c
gcc %CFLAGS% -o bin/crc32.obj zlib123/crc32.c
gcc %CFLAGS% -o bin/deflate.obj zlib123/deflate.c
gcc %CFLAGS% -o bin/gzio.obj zlib123/gzio.c
gcc %CFLAGS% -o bin/infback.obj zlib123/infback.c
gcc %CFLAGS% -o bin/inffast.obj zlib123/inffast.c
gcc %CFLAGS% -o bin/inflate.obj zlib123/inflate.c
gcc %CFLAGS% -o bin/inftrees.obj zlib123/inftrees.c
gcc %CFLAGS% -o bin/trees.obj zlib123/trees.c
gcc %CFLAGS% -o bin/uncompr.obj zlib123/uncompr.c
gcc %CFLAGS% -o bin/zutil.obj zlib123/zutil.c
gcc %CFLAGS% -o bin/7zBuffer.obj lzma/7zBuffer.c
gcc %CFLAGS% -o bin/7zCrc.obj lzma/7zCrc.c
gcc %CFLAGS% -o bin/7zDecode.obj lzma/7zDecode.c
gcc %CFLAGS% -o bin/7zExtract.obj lzma/7zExtract.c
gcc %CFLAGS% -o bin/7zHeader.obj lzma/7zHeader.c
gcc %CFLAGS% -o bin/7zIn.obj lzma/7zIn.c
gcc %CFLAGS% -o bin/7zItem.obj lzma/7zItem.c
gcc %CFLAGS% -o bin/7zMethodID.obj lzma/7zMethodID.c
gcc %CFLAGS% -o bin/LzmaDecode.obj lzma/LzmaDecode.c
gcc %CFLAGS% -o bin/LzmaStateDecode.obj lzma/LzmaStateDecode.c
@echo off
:dolinking
@echo Linking PhysicsFS library...
gcc %DEBUGFLAGS% -Zdll -Zcrtdll -Zomf -o bin/physfs.dll bin/*.obj bin/physfs.def
rem goto :builddone
@echo Compiling test program...
gcc %CFLAGS% -o bin/test_physfs.obj test/test_physfs.c
@echo Linking test program...
gcc %DEBUGFLAGS% -Zomf -Zcrtdll -o bin/test_physfs.exe bin/test_physfs.obj bin/physfs.lib bin/test_physfs.def
:builddone
@echo "All done!"
rem end of makeos2.cmd ...
File diff suppressed because it is too large Load Diff
-312
View File
@@ -1,312 +0,0 @@
/**
* PhysicsFS; a portable, flexible file i/o abstraction.
*
* Documentation is in physfs.h. It's verbose, honest. :)
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
#include <stdio.h>
#include <stdlib.h>
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
#if (defined macintosh) && !(defined __MWERKS__)
#define __inline__
#endif
#if (defined _MSC_VER)
#define __inline__ __inline
#endif
#ifndef PHYSFS_Swap16
static __inline__ PHYSFS_uint16 PHYSFS_Swap16(PHYSFS_uint16 D)
{
return((D<<8)|(D>>8));
}
#endif
#ifndef PHYSFS_Swap32
static __inline__ PHYSFS_uint32 PHYSFS_Swap32(PHYSFS_uint32 D)
{
return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24));
}
#endif
#ifndef PHYSFS_NO_64BIT_SUPPORT
#ifndef PHYSFS_Swap64
static __inline__ PHYSFS_uint64 PHYSFS_Swap64(PHYSFS_uint64 val) {
PHYSFS_uint32 hi, lo;
/* Separate into high and low 32-bit values and swap them */
lo = (PHYSFS_uint32)(val&0xFFFFFFFF);
val >>= 32;
hi = (PHYSFS_uint32)(val&0xFFFFFFFF);
val = PHYSFS_Swap32(lo);
val <<= 32;
val |= PHYSFS_Swap32(hi);
return(val);
}
#endif
#else
#ifndef PHYSFS_Swap64
/* This is mainly to keep compilers from complaining in PHYSFS code.
If there is no real 64-bit datatype, then compilers will complain about
the fake 64-bit datatype that PHYSFS provides when it compiles user code.
*/
#define PHYSFS_Swap64(X) (X)
#endif
#endif /* PHYSFS_NO_64BIT_SUPPORT */
/* Byteswap item from the specified endianness to the native endianness */
#if PHYSFS_BYTEORDER == PHYSFS_LIL_ENDIAN
PHYSFS_uint16 PHYSFS_swapULE16(PHYSFS_uint16 x) { return(x); }
PHYSFS_sint16 PHYSFS_swapSLE16(PHYSFS_sint16 x) { return(x); }
PHYSFS_uint32 PHYSFS_swapULE32(PHYSFS_uint32 x) { return(x); }
PHYSFS_sint32 PHYSFS_swapSLE32(PHYSFS_sint32 x) { return(x); }
PHYSFS_uint64 PHYSFS_swapULE64(PHYSFS_uint64 x) { return(x); }
PHYSFS_sint64 PHYSFS_swapSLE64(PHYSFS_sint64 x) { return(x); }
PHYSFS_uint16 PHYSFS_swapUBE16(PHYSFS_uint16 x) { return(PHYSFS_Swap16(x)); }
PHYSFS_sint16 PHYSFS_swapSBE16(PHYSFS_sint16 x) { return(PHYSFS_Swap16(x)); }
PHYSFS_uint32 PHYSFS_swapUBE32(PHYSFS_uint32 x) { return(PHYSFS_Swap32(x)); }
PHYSFS_sint32 PHYSFS_swapSBE32(PHYSFS_sint32 x) { return(PHYSFS_Swap32(x)); }
PHYSFS_uint64 PHYSFS_swapUBE64(PHYSFS_uint64 x) { return(PHYSFS_Swap64(x)); }
PHYSFS_sint64 PHYSFS_swapSBE64(PHYSFS_sint64 x) { return(PHYSFS_Swap64(x)); }
#else
PHYSFS_uint16 PHYSFS_swapULE16(PHYSFS_uint16 x) { return(PHYSFS_Swap16(x)); }
PHYSFS_sint16 PHYSFS_swapSLE16(PHYSFS_sint16 x) { return(PHYSFS_Swap16(x)); }
PHYSFS_uint32 PHYSFS_swapULE32(PHYSFS_uint32 x) { return(PHYSFS_Swap32(x)); }
PHYSFS_sint32 PHYSFS_swapSLE32(PHYSFS_sint32 x) { return(PHYSFS_Swap32(x)); }
PHYSFS_uint64 PHYSFS_swapULE64(PHYSFS_uint64 x) { return(PHYSFS_Swap64(x)); }
PHYSFS_sint64 PHYSFS_swapSLE64(PHYSFS_sint64 x) { return(PHYSFS_Swap64(x)); }
PHYSFS_uint16 PHYSFS_swapUBE16(PHYSFS_uint16 x) { return(x); }
PHYSFS_sint16 PHYSFS_swapSBE16(PHYSFS_sint16 x) { return(x); }
PHYSFS_uint32 PHYSFS_swapUBE32(PHYSFS_uint32 x) { return(x); }
PHYSFS_sint32 PHYSFS_swapSBE32(PHYSFS_sint32 x) { return(x); }
PHYSFS_uint64 PHYSFS_swapUBE64(PHYSFS_uint64 x) { return(x); }
PHYSFS_sint64 PHYSFS_swapSBE64(PHYSFS_sint64 x) { return(x); }
#endif
int PHYSFS_readSLE16(PHYSFS_File *file, PHYSFS_sint16 *val)
{
PHYSFS_sint16 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapSLE16(in);
return(1);
} /* PHYSFS_readSLE16 */
int PHYSFS_readULE16(PHYSFS_File *file, PHYSFS_uint16 *val)
{
PHYSFS_uint16 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapULE16(in);
return(1);
} /* PHYSFS_readULE16 */
int PHYSFS_readSBE16(PHYSFS_File *file, PHYSFS_sint16 *val)
{
PHYSFS_sint16 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapSBE16(in);
return(1);
} /* PHYSFS_readSBE16 */
int PHYSFS_readUBE16(PHYSFS_File *file, PHYSFS_uint16 *val)
{
PHYSFS_uint16 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapUBE16(in);
return(1);
} /* PHYSFS_readUBE16 */
int PHYSFS_readSLE32(PHYSFS_File *file, PHYSFS_sint32 *val)
{
PHYSFS_sint32 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapSLE32(in);
return(1);
} /* PHYSFS_readSLE32 */
int PHYSFS_readULE32(PHYSFS_File *file, PHYSFS_uint32 *val)
{
PHYSFS_uint32 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapULE32(in);
return(1);
} /* PHYSFS_readULE32 */
int PHYSFS_readSBE32(PHYSFS_File *file, PHYSFS_sint32 *val)
{
PHYSFS_sint32 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapSBE32(in);
return(1);
} /* PHYSFS_readSBE32 */
int PHYSFS_readUBE32(PHYSFS_File *file, PHYSFS_uint32 *val)
{
PHYSFS_uint32 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapUBE32(in);
return(1);
} /* PHYSFS_readUBE32 */
int PHYSFS_readSLE64(PHYSFS_File *file, PHYSFS_sint64 *val)
{
PHYSFS_sint64 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapSLE64(in);
return(1);
} /* PHYSFS_readSLE64 */
int PHYSFS_readULE64(PHYSFS_File *file, PHYSFS_uint64 *val)
{
PHYSFS_uint64 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapULE64(in);
return(1);
} /* PHYSFS_readULE64 */
int PHYSFS_readSBE64(PHYSFS_File *file, PHYSFS_sint64 *val)
{
PHYSFS_sint64 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapSBE64(in);
return(1);
} /* PHYSFS_readSBE64 */
int PHYSFS_readUBE64(PHYSFS_File *file, PHYSFS_uint64 *val)
{
PHYSFS_uint64 in;
BAIL_IF_MACRO(val == NULL, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(PHYSFS_read(file, &in, sizeof (in), 1) != 1, NULL, 0);
*val = PHYSFS_swapUBE64(in);
return(1);
} /* PHYSFS_readUBE64 */
int PHYSFS_writeSLE16(PHYSFS_File *file, PHYSFS_sint16 val)
{
PHYSFS_sint16 out = PHYSFS_swapSLE16(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeSLE16 */
int PHYSFS_writeULE16(PHYSFS_File *file, PHYSFS_uint16 val)
{
PHYSFS_uint16 out = PHYSFS_swapULE16(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeULE16 */
int PHYSFS_writeSBE16(PHYSFS_File *file, PHYSFS_sint16 val)
{
PHYSFS_sint16 out = PHYSFS_swapSBE16(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeSBE16 */
int PHYSFS_writeUBE16(PHYSFS_File *file, PHYSFS_uint16 val)
{
PHYSFS_uint16 out = PHYSFS_swapUBE16(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeUBE16 */
int PHYSFS_writeSLE32(PHYSFS_File *file, PHYSFS_sint32 val)
{
PHYSFS_sint32 out = PHYSFS_swapSLE32(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeSLE32 */
int PHYSFS_writeULE32(PHYSFS_File *file, PHYSFS_uint32 val)
{
PHYSFS_uint32 out = PHYSFS_swapULE32(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeULE32 */
int PHYSFS_writeSBE32(PHYSFS_File *file, PHYSFS_sint32 val)
{
PHYSFS_sint32 out = PHYSFS_swapSBE32(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeSBE32 */
int PHYSFS_writeUBE32(PHYSFS_File *file, PHYSFS_uint32 val)
{
PHYSFS_uint32 out = PHYSFS_swapUBE32(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeUBE32 */
int PHYSFS_writeSLE64(PHYSFS_File *file, PHYSFS_sint64 val)
{
PHYSFS_sint64 out = PHYSFS_swapSLE64(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeSLE64 */
int PHYSFS_writeULE64(PHYSFS_File *file, PHYSFS_uint64 val)
{
PHYSFS_uint64 out = PHYSFS_swapULE64(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeULE64 */
int PHYSFS_writeSBE64(PHYSFS_File *file, PHYSFS_sint64 val)
{
PHYSFS_sint64 out = PHYSFS_swapSBE64(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeSBE64 */
int PHYSFS_writeUBE64(PHYSFS_File *file, PHYSFS_uint64 val)
{
PHYSFS_uint64 out = PHYSFS_swapUBE64(val);
BAIL_IF_MACRO(PHYSFS_write(file, &out, sizeof (out), 1) != 1, NULL, 0);
return(1);
} /* PHYSFS_writeUBE64 */
/* end of physfs_byteorder.c ... */
File diff suppressed because it is too large Load Diff
-49
View File
@@ -1,49 +0,0 @@
#ifndef _INCL_PHYSFS_PLATFORMS
#define _INCL_PHYSFS_PLATFORMS
#ifndef __PHYSICSFS_INTERNAL__
#error Do not include this header from your applications.
#endif
/*
* These only define the platforms to determine which files in the platforms
* directory should be compiled. For example, technically BeOS can be called
* a "unix" system, but since it doesn't use unix.c, we don't define
* PHYSFS_PLATFORM_UNIX on that system.
*/
#if (defined __HAIKU__)
# define PHYSFS_PLATFORM_HAIKU
# define PHYSFS_PLATFORM_BEOS
# define PHYSFS_PLATFORM_POSIX
#elif ((defined __BEOS__) || (defined __beos__))
# define PHYSFS_PLATFORM_BEOS
# define PHYSFS_PLATFORM_POSIX
#elif (defined _WIN32_WCE) || (defined _WIN64_WCE)
# define PHYSFS_PLATFORM_POCKETPC
#elif (((defined _WIN32) || (defined _WIN64)) && (!defined __CYGWIN__))
# define PHYSFS_PLATFORM_WINDOWS
#elif (defined OS2)
# define PHYSFS_PLATFORM_OS2
#elif ((defined __MACH__) && (defined __APPLE__))
/* To check if iphone or not, we need to include this file */
# include <TargetConditionals.h>
# if ((TARGET_IPHONE_SIMULATOR) || (TARGET_OS_IPHONE))
# define PHYSFS_PLATFORM_UNIX
# define PHYSFS_PLATFORM_POSIX
# define PHYSFS_NO_CDROM_SUPPORT
# else
# define PHYSFS_PLATFORM_MACOSX
# define PHYSFS_PLATFORM_POSIX
# endif
#elif defined(macintosh)
# error Classic Mac OS support was dropped from PhysicsFS 2.0. Move to OS X.
#elif defined(unix) || defined(__unix__)
# define PHYSFS_PLATFORM_UNIX
# define PHYSFS_PLATFORM_POSIX
#else
# error Unknown platform.
#endif
#endif /* include-once blocker. */

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