mirror of
https://github.com/love2d/love-android.git
synced 2026-08-13 17:11:01 +02:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0fd9a6e1b | |||
| 539ca8d4f2 | |||
| fab725ad8b | |||
| 5f6fa8c2b5 | |||
| 4c2846f4bb | |||
| cb2c852f58 | |||
| 60a58f9240 | |||
| 5849e8d369 | |||
| 1703660617 | |||
| 0db55463c9 | |||
| 288b25c585 | |||
| a5284dccf6 | |||
| 8069dc02c6 | |||
| 0bde453b2e | |||
| 667c4750ea | |||
| 38727b5c25 | |||
| 288a851a65 | |||
| 5e3579f680 | |||
| 1dd859c9d1 | |||
| 53d45533e0 | |||
| 3f13dc653f | |||
| 9e7e31ba05 | |||
| 3f268ebedf | |||
| 8fb02e11ab | |||
| 89c54f9712 | |||
| 606da6d0ae | |||
| 52d505624d | |||
| 89c9baf274 | |||
| e4e1a0f59b | |||
| 00052d8067 | |||
| de93ded9bf | |||
| 2da2da2652 | |||
| bfae01300e | |||
| 0b8dd90114 | |||
| 3cabe641d6 | |||
| 351e224815 | |||
| 89c2c014b2 | |||
| c3a21270ab | |||
| 597fad8034 | |||
| bf07caef09 | |||
| c9bb6ec3d6 | |||
| 007b0fc3f0 | |||
| b86319c0f4 | |||
| 9a688b9b37 | |||
| 405c79a8fe | |||
| cf30c31234 |
+57
-17
@@ -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 -->
|
||||
|
||||
@@ -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
@@ -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.
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
repo: 7672c9962ce627edaaa67ff54fe4ad8f9a46dc2b
|
||||
node: f94eec5e90540889a42c34a27931b8266f4af52c
|
||||
branch: stable-2.0
|
||||
latesttag: release-2.0.3
|
||||
latesttagdistance: 1
|
||||
@@ -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 ...
|
||||
@@ -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 ...
|
||||
|
||||
@@ -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 ... */
|
||||
|
||||
@@ -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 ... */
|
||||
|
||||
@@ -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 ... */
|
||||
|
||||
@@ -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 ... */
|
||||
|
||||
@@ -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 ... */
|
||||
|
||||
@@ -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
@@ -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 ... */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user