mirror of
https://github.com/love2d/love-android.git
synced 2026-08-15 15:51:20 +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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest package="org.love2d.android"
|
<manifest package="org.love2d.android"
|
||||||
android:versionCode="8"
|
android:versionCode="10"
|
||||||
android:versionName="0.9.0-alpha8"
|
android:versionName="0.9.0-beta2"
|
||||||
android:installLocation="auto" xmlns:android="http://schemas.android.com/apk/res/android">
|
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.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
@@ -9,21 +9,61 @@
|
|||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:label="Löve for Android"
|
android:label="LÖVE for Android"
|
||||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
|
||||||
<activity
|
<service android:name=".DownloadService" />
|
||||||
android:name="GameActivity"
|
<activity
|
||||||
android:configChanges="orientation|screenSize"
|
android:name="GameActivity"
|
||||||
android:label="Löve for Android"
|
android:configChanges="orientation|screenSize"
|
||||||
android:screenOrientation="landscape" >
|
android:label="LÖVE for Android"
|
||||||
<intent-filter>
|
android:screenOrientation="landscape" >
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="tv.ouya.intent.category.GAME"/>
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
<category android:name="tv.ouya.intent.category.GAME"/>
|
||||||
</activity>
|
</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>
|
</application>
|
||||||
|
|
||||||
<!-- Android 2.3.3 -->
|
<!-- Android 2.3.3 -->
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
Android Port of LÖVE, the awesome 2D game engine LÖVE (http://love2d.org)
|
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:
|
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
|
Install the Android NDK and the Android SDK with SDK API 12 and run
|
||||||
|
|
||||||
ndk-build
|
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
|
This should give you a .apk file in the bin/ subdirectory that you can then
|
||||||
install on your phone.
|
install on your phone.
|
||||||
|
|
||||||
|
Bugs:
|
||||||
|
-----
|
||||||
|
|
||||||
|
Bugs and feature requests should be reported to the [issue
|
||||||
|
tracker](issues).
|
||||||
|
|
||||||
Changelog:
|
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:
|
alpha8:
|
||||||
|
|
||||||
* Exposing DisplayMetrics in love.android.getDisplayMetrics())
|
* Exposing DisplayMetrics in love.android.getDisplayMetrics())
|
||||||
* Accelerometer is now available as a joystick
|
* Accelerometer is now available as a joystick
|
||||||
* enabled armv6 compilation (larger files, better compatibility with Tegra2 devices)
|
* 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 OpenAL from 1.13 to 1.15.1
|
||||||
* updated jpeg library from 8c to 9a
|
* updated jpeg library from 8c to 9a
|
||||||
* updated lcms from 2.2 to 2.5
|
* updated lcms from 2.2 to 2.5
|
||||||
@@ -34,16 +65,17 @@ alpha8:
|
|||||||
* updated mpg123 from 1.13.4 to 1.17.0
|
* updated mpg123 from 1.13.4 to 1.17.0
|
||||||
|
|
||||||
alpha7:
|
alpha7:
|
||||||
* love.system.getOS() now returns "Android"
|
|
||||||
* hardware search key is reported as "search"
|
* love.system.getOS() now returns "Android"
|
||||||
* switched to mobile-common branch
|
* hardware search key is reported as "search"
|
||||||
* using new love.touch module (love.touchpressed(id,x,y,p), love.touchmoved(id,x,y,p), love.touchmoved(id,x,y,p))
|
* switched to mobile-common branch
|
||||||
* added LOVE_ANDROID define
|
* 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:
|
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
|
Please look into the folders of jni/<projectname>/ for the respective
|
||||||
licenses.
|
licenses.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,6 +4,6 @@
|
|||||||
APP_STL := gnustl_shared
|
APP_STL := gnustl_shared
|
||||||
APP_ABI := armeabi armeabi-v7a
|
APP_ABI := armeabi armeabi-v7a
|
||||||
APP_CPPFLAGS := -frtti
|
APP_CPPFLAGS := -frtti
|
||||||
APP_LDFLAGS := -llog -landroid -lz -lOpenSLES
|
APP_LDFLAGS := -llog -landroid -lz
|
||||||
|
|
||||||
# APP_OPTIM := debug
|
# APP_OPTIM := debug
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -53,6 +53,6 @@ cd src
|
|||||||
buildLuaJIT armeabi
|
buildLuaJIT armeabi
|
||||||
|
|
||||||
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.0+ (ICS)
|
# 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
|
make clean
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ LOCAL_SRC_FILES := \
|
|||||||
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
|
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
|
||||||
LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
|
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_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_LDLIBS :=
|
||||||
LOCAL_EXPORT_LDLIBS := -Wl,--undefined=Java_org_libsdl_app_SDLActivity_nativeInit -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
|
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/*.cpp) \
|
||||||
$(wildcard ${LOCAL_PATH}/src-IL/src/*.c) ))
|
$(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: include dirs $(LOCAL_C_INCLUDES))
|
||||||
# $(info libdevil: src files $(LOCAL_SRC_FILES))
|
# $(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/ \
|
||||||
${LOCAL_PATH}/src/libraries/enet/libenet/include \
|
${LOCAL_PATH}/src/libraries/enet/libenet/include \
|
||||||
${LOCAL_PATH}/../SDL2-2.0.1/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/include \
|
||||||
${LOCAL_PATH}/../devil-1.7.8/src-IL/include \
|
${LOCAL_PATH}/../devil-1.7.8/src-IL/include \
|
||||||
${LOCAL_PATH}/../jasper-1.900.1/src/libjasper/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}/../openal-soft-android/OpenAL32/Include \
|
||||||
${LOCAL_PATH}/../freetype2-android/include \
|
${LOCAL_PATH}/../freetype2-android/include \
|
||||||
${LOCAL_PATH}/../freetype2-android/src \
|
${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}/../mpg123-1.17.0/src/libmpg123 \
|
||||||
${LOCAL_PATH}/../libmodplug-0.8.8.4/src \
|
${LOCAL_PATH}/../libmodplug-0.8.8.4/src \
|
||||||
${LOCAL_PATH}/../libvorbis-1.3.4/include \
|
${LOCAL_PATH}/../libvorbis-1.3.4/include \
|
||||||
@@ -43,8 +42,7 @@ LOCAL_SRC_FILES := \
|
|||||||
,$(subst $(LOCAL_PATH)/,,\
|
,$(subst $(LOCAL_PATH)/,,\
|
||||||
$(wildcard ${LOCAL_PATH}/src/love.cpp) \
|
$(wildcard ${LOCAL_PATH}/src/love.cpp) \
|
||||||
$(wildcard ${LOCAL_PATH}/src/common/*.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/null/*.cpp) \
|
||||||
$(wildcard ${LOCAL_PATH}/src/modules/audio/openal/*.cpp) \
|
$(wildcard ${LOCAL_PATH}/src/modules/audio/openal/*.cpp) \
|
||||||
$(wildcard ${LOCAL_PATH}/src/modules/event/*.cpp) \
|
$(wildcard ${LOCAL_PATH}/src/modules/event/*.cpp) \
|
||||||
@@ -99,9 +97,9 @@ LOCAL_SRC_FILES := \
|
|||||||
|
|
||||||
LOCAL_CXXFLAGS := -std=c++0x
|
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: include dirs $(LOCAL_C_INCLUDES))
|
||||||
# $(info liblove: src files $(LOCAL_SRC_FILES))
|
# $(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.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#ifndef LOVE_ANDROID_WRAP_ANDROID_H
|
#ifndef LOVE_ANDROID_H
|
||||||
#define LOVE_ANDROID_WRAP_ANDROID_H
|
#define LOVE_ANDROID_H
|
||||||
|
|
||||||
// LOVE
|
#include "config.h"
|
||||||
#include "common/config.h"
|
|
||||||
#include "common/runtime.h"
|
#ifdef LOVE_ANDROID
|
||||||
#include "Android.h"
|
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
namespace android
|
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
|
} // android
|
||||||
} // love
|
} // love
|
||||||
|
|
||||||
#endif // LOVE_ANDROID_WRAP_ANDROID_H
|
#endif // LOVE_ANDROID
|
||||||
|
#endif // LOVE_ANDROID_H
|
||||||
@@ -90,7 +90,6 @@
|
|||||||
# define LOVE_LITTLE_ENDIAN 1
|
# define LOVE_LITTLE_ENDIAN 1
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# define LOVE_ENABLE_ANDROID
|
|
||||||
# define LOVE_ENABLE_AUDIO
|
# define LOVE_ENABLE_AUDIO
|
||||||
# define LOVE_ENABLE_AUDIO_NULL
|
# define LOVE_ENABLE_AUDIO_NULL
|
||||||
# define LOVE_ENABLE_AUDIO_OPENAL
|
# define LOVE_ENABLE_AUDIO_OPENAL
|
||||||
|
|||||||
@@ -35,9 +35,6 @@ enum Type
|
|||||||
DATA_ID,
|
DATA_ID,
|
||||||
MODULE_ID,
|
MODULE_ID,
|
||||||
|
|
||||||
// Android
|
|
||||||
ANDROID_DISPLAY_METRICS_ID,
|
|
||||||
|
|
||||||
// Filesystem.
|
// Filesystem.
|
||||||
FILESYSTEM_FILE_ID,
|
FILESYSTEM_FILE_ID,
|
||||||
FILESYSTEM_FILE_DATA_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 DATA_T = (bits(1) << DATA_ID) | OBJECT_T;
|
||||||
const bits MODULE_T = (bits(1) << MODULE_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.
|
// Filesystem.
|
||||||
const bits FILESYSTEM_FILE_T = (bits(1) << FILESYSTEM_FILE_ID) | OBJECT_T;
|
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;
|
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
|
#define LUA_COMPAT_ALL
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lualib.h>
|
#include <lualib.h>
|
||||||
@@ -10,3 +13,5 @@
|
|||||||
|
|
||||||
extern int luax_typerror(lua_State *L, int narg, const char *type);
|
extern int luax_typerror(lua_State *L, int narg, const char *type);
|
||||||
#endif
|
#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.
|
// Make all sources available initially.
|
||||||
for (int i = 0; i < totalSources; i++)
|
for (int i = 0; i < totalSources; i++)
|
||||||
{
|
{
|
||||||
|
#ifdef AL_SOFT_direct_channels
|
||||||
if (hasext)
|
if (hasext)
|
||||||
{
|
{
|
||||||
// Bypass virtualization of speakers for multi-channel sources in OpenAL Soft.
|
// Bypass virtualization of speakers for multi-channel sources in OpenAL Soft.
|
||||||
alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
|
alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
available.push(sources[i]);
|
available.push(sources[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ namespace sdl
|
|||||||
// we want them in pixel coordinates (may be different with high-DPI enabled.)
|
// we want them in pixel coordinates (may be different with high-DPI enabled.)
|
||||||
static void windowToPixelCoords(int *x, int *y)
|
static void windowToPixelCoords(int *x, int *y)
|
||||||
{
|
{
|
||||||
|
#ifndef LOVE_ANDROID
|
||||||
double scale = 1.0;
|
double scale = 1.0;
|
||||||
|
|
||||||
window::Window *window = (window::Window *) Module::findInstance("love.window.");
|
window::Window *window = (window::Window *) Module::findInstance("love.window.");
|
||||||
@@ -53,6 +54,7 @@ static void windowToPixelCoords(int *x, int *y)
|
|||||||
|
|
||||||
if (y != nullptr)
|
if (y != nullptr)
|
||||||
*y = int(double(*y) * scale);
|
*y = int(double(*y) * scale);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -129,7 +131,6 @@ Message *Event::convert(const SDL_Event &e) const
|
|||||||
switch (e.type)
|
switch (e.type)
|
||||||
{
|
{
|
||||||
case SDL_KEYDOWN:
|
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)
|
if (e.key.repeat)
|
||||||
{
|
{
|
||||||
kb = (love::keyboard::Keyboard *) Module::findInstance("love.keyboard.");
|
kb = (love::keyboard::Keyboard *) Module::findInstance("love.keyboard.");
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include "common/android.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -59,6 +60,63 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOVE_ANDROID
|
#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) {
|
bool androidDirectoryExists(const char* path) {
|
||||||
SDL_Log ("Checking directory exists for %s", path);
|
SDL_Log ("Checking directory exists for %s", path);
|
||||||
struct stat s;
|
struct stat s;
|
||||||
@@ -106,69 +164,6 @@ namespace
|
|||||||
|
|
||||||
return true;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +196,11 @@ void Filesystem::init(const char *arg0)
|
|||||||
{
|
{
|
||||||
if (!PHYSFS_init(arg0))
|
if (!PHYSFS_init(arg0))
|
||||||
throw Exception(PHYSFS_getLastError());
|
throw Exception(PHYSFS_getLastError());
|
||||||
|
|
||||||
|
#ifdef LOVE_ANDROID
|
||||||
|
PHYSFS_permitSymbolicLinks (1);
|
||||||
|
#endif
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,19 +240,20 @@ bool Filesystem::setIdentity(const char *ident, bool appendToPath)
|
|||||||
save_path_full += save_path_relative;
|
save_path_full += save_path_relative;
|
||||||
|
|
||||||
#ifdef LOVE_ANDROID
|
#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;
|
save_path_full = std::string(SDL_AndroidGetInternalStoragePath()) + std::string("/save/") + save_identity;
|
||||||
|
|
||||||
|
if (androidDirectoryExists (save_path_full.c_str())) {
|
||||||
if (androidDirectoryExists (save_path_full.c_str())) {
|
SDL_Log ("dir exists");
|
||||||
SDL_Log ("dir exists");
|
} else {
|
||||||
} else {
|
SDL_Log ("does not exist");
|
||||||
SDL_Log ("does not exist");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!androidDirectoryExists (save_path_full.c_str())) {
|
if (!androidDirectoryExists (save_path_full.c_str())) {
|
||||||
if (!androidMkdir (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!");
|
SDL_Log ("Error creating storage directories!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (androidCopyGameFromAssets())
|
if (!androidMountSelectedGame() && !androidMountAssetGame()) {
|
||||||
new_search_path = std::string(SDL_AndroidGetInternalStoragePath()) + std::string("/game/game.love");
|
SDL_RWops *sdcard_main = SDL_RWFromFile("/sdcard/lovegame/main.lua", "rb");
|
||||||
else {
|
|
||||||
SDL_RWops *sdcard_main = SDL_RWFromFile("/sdcard/lovegame/main.lua", "rb");
|
|
||||||
|
|
||||||
if (sdcard_main) {
|
if (sdcard_main) {
|
||||||
SDL_Log ("using game from /sdcard/lovegame");
|
SDL_Log ("using game from /sdcard/lovegame");
|
||||||
new_search_path = "/sdcard/lovegame";
|
new_search_path = "/sdcard/lovegame";
|
||||||
sdcard_main->close(sdcard_main);
|
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.
|
// Add the directory.
|
||||||
if (!PHYSFS_addToSearchPath(new_search_path.c_str(), 1)) {
|
if (!PHYSFS_addToSearchPath(new_search_path.c_str(), 1)) {
|
||||||
SDL_Log ("mounting of %s failed", new_search_path.c_str());
|
SDL_Log ("mounting of %s failed", new_search_path.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Save the game source.
|
// Save the game source.
|
||||||
game_source = new_search_path;
|
game_source = new_search_path;
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM>::Entry Graphics::suppor
|
|||||||
{ "dxt", Graphics::SUPPORT_DXT },
|
{ "dxt", Graphics::SUPPORT_DXT },
|
||||||
{ "bc5", Graphics::SUPPORT_BC5 },
|
{ "bc5", Graphics::SUPPORT_BC5 },
|
||||||
{ "instancing", Graphics::SUPPORT_INSTANCING },
|
{ "instancing", Graphics::SUPPORT_INSTANCING },
|
||||||
|
{ "srgb", Graphics::SUPPORT_SRGB },
|
||||||
};
|
};
|
||||||
|
|
||||||
StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM> Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries));
|
StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM> Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries));
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ public:
|
|||||||
SUPPORT_DXT,
|
SUPPORT_DXT,
|
||||||
SUPPORT_BC5,
|
SUPPORT_BC5,
|
||||||
SUPPORT_INSTANCING,
|
SUPPORT_INSTANCING,
|
||||||
|
SUPPORT_SRGB,
|
||||||
SUPPORT_MAX_ENUM
|
SUPPORT_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,7 +136,7 @@ public:
|
|||||||
* @param width The viewport width.
|
* @param width The viewport width.
|
||||||
* @param height The viewport height.
|
* @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
|
* 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);
|
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[] =
|
StringMap<Texture::FilterMode, Texture::FILTER_MAX_ENUM>::Entry Texture::filterModeEntries[] =
|
||||||
{
|
{
|
||||||
{ "linear", Texture::FILTER_LINEAR },
|
{ "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::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
|
} // graphics
|
||||||
} // love
|
} // love
|
||||||
|
|||||||
@@ -55,6 +55,14 @@ public:
|
|||||||
FILTER_MAX_ENUM
|
FILTER_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Format
|
||||||
|
{
|
||||||
|
FORMAT_NORMAL,
|
||||||
|
FORMAT_HDR,
|
||||||
|
FORMAT_SRGB,
|
||||||
|
FORMAT_MAX_ENUM
|
||||||
|
};
|
||||||
|
|
||||||
struct Filter
|
struct Filter
|
||||||
{
|
{
|
||||||
Filter();
|
Filter();
|
||||||
@@ -111,6 +119,9 @@ public:
|
|||||||
static bool getConstant(const char *in, WrapMode &out);
|
static bool getConstant(const char *in, WrapMode &out);
|
||||||
static bool getConstant(WrapMode in, const char *&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:
|
protected:
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
@@ -132,6 +143,9 @@ private:
|
|||||||
static StringMap<WrapMode, WRAP_MAX_ENUM>::Entry wrapModeEntries[];
|
static StringMap<WrapMode, WRAP_MAX_ENUM>::Entry wrapModeEntries[];
|
||||||
static StringMap<WrapMode, WRAP_MAX_ENUM> wrapModes;
|
static StringMap<WrapMode, WRAP_MAX_ENUM> wrapModes;
|
||||||
|
|
||||||
|
static StringMap<Format, FORMAT_MAX_ENUM>::Entry formatEntries[];
|
||||||
|
static StringMap<Format, FORMAT_MAX_ENUM> formats;
|
||||||
|
|
||||||
}; // Texture
|
}; // Texture
|
||||||
|
|
||||||
} // graphics
|
} // graphics
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
FramebufferStrategy *strategy = NULL;
|
FramebufferStrategy *strategy = nullptr;
|
||||||
|
|
||||||
FramebufferStrategy strategyNone;
|
FramebufferStrategy strategyNone;
|
||||||
|
|
||||||
@@ -401,8 +401,9 @@ FramebufferStrategyPackedEXT strategyPackedEXT;
|
|||||||
|
|
||||||
FramebufferStrategyEXT strategyEXT;
|
FramebufferStrategyEXT strategyEXT;
|
||||||
|
|
||||||
Canvas *Canvas::current = NULL;
|
Canvas *Canvas::current = nullptr;
|
||||||
OpenGL::Viewport Canvas::systemViewport = OpenGL::Viewport();
|
OpenGL::Viewport Canvas::systemViewport = OpenGL::Viewport();
|
||||||
|
bool Canvas::screenHasSRGB = false;
|
||||||
|
|
||||||
static void getStrategy()
|
static void getStrategy()
|
||||||
{
|
{
|
||||||
@@ -421,16 +422,13 @@ static void getStrategy()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int maxFBOColorAttachments = 0;
|
Canvas::Canvas(int width, int height, Texture::Format format, int fsaa)
|
||||||
static int maxDrawBuffers = 0;
|
|
||||||
|
|
||||||
Canvas::Canvas(int width, int height, TextureType texture_type, int fsaa)
|
|
||||||
: fbo(0)
|
: fbo(0)
|
||||||
, resolve_fbo(0)
|
, resolve_fbo(0)
|
||||||
, texture(0)
|
, texture(0)
|
||||||
, fsaa_buffer(0)
|
, fsaa_buffer(0)
|
||||||
, depth_stencil(0)
|
, depth_stencil(0)
|
||||||
, texture_type(texture_type)
|
, format(format)
|
||||||
, fsaa_samples(fsaa)
|
, fsaa_samples(fsaa)
|
||||||
, fsaa_dirty(false)
|
, fsaa_dirty(false)
|
||||||
{
|
{
|
||||||
@@ -534,15 +532,19 @@ bool Canvas::loadVolatile()
|
|||||||
|
|
||||||
GLint internalformat;
|
GLint internalformat;
|
||||||
GLenum textype;
|
GLenum textype;
|
||||||
switch (texture_type)
|
switch (format)
|
||||||
{
|
{
|
||||||
case TYPE_HDR:
|
case Texture::FORMAT_HDR:
|
||||||
internalformat = GL_RGBA16F;
|
internalformat = GL_RGBA16F;
|
||||||
textype = GL_FLOAT;
|
textype = GL_FLOAT;
|
||||||
break;
|
break;
|
||||||
case TYPE_NORMAL:
|
case Texture::FORMAT_SRGB:
|
||||||
|
internalformat = GL_SRGB_ALPHA;
|
||||||
|
textype = GL_UNSIGNED_BYTE;
|
||||||
|
break;
|
||||||
|
case Texture::FORMAT_NORMAL:
|
||||||
default:
|
default:
|
||||||
internalformat = GL_RGBA8;
|
internalformat = GL_RGBA;
|
||||||
textype = GL_UNSIGNED_BYTE;
|
textype = GL_UNSIGNED_BYTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,20 +684,30 @@ void Canvas::setupGrab()
|
|||||||
if (current == this)
|
if (current == this)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// cleanup after previous fbo
|
// cleanup after previous Canvas
|
||||||
if (current != NULL)
|
if (current != nullptr)
|
||||||
current->stopGrab();
|
{
|
||||||
|
systemViewport = current->systemViewport;
|
||||||
|
current->stopGrab(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
systemViewport = gl.getViewport();
|
||||||
|
|
||||||
|
// indicate we are using this Canvas.
|
||||||
|
current = this;
|
||||||
|
|
||||||
// bind the framebuffer object.
|
// bind the framebuffer object.
|
||||||
systemViewport = gl.getViewport();
|
|
||||||
strategy->bindFBO(fbo);
|
strategy->bindFBO(fbo);
|
||||||
gl.setViewport(OpenGL::Viewport(0, 0, width, height));
|
gl.setViewport(OpenGL::Viewport(0, 0, width, height));
|
||||||
|
|
||||||
// Set up orthographic view (no depth)
|
// Set up orthographic view (no depth)
|
||||||
gl.matrices.projection.push(Matrix::ortho(0.0, width, 0.0, height));
|
gl.matrices.projection.push(Matrix::ortho(0.0, width, 0.0, height));
|
||||||
|
|
||||||
// indicate we are using this fbo
|
// Make sure the correct sRGB setting is used when drawing to the canvas.
|
||||||
current = this;
|
if (format == FORMAT_SRGB)
|
||||||
|
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||||
|
else if (screenHasSRGB)
|
||||||
|
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||||
|
|
||||||
if (fsaa_buffer != 0)
|
if (fsaa_buffer != 0)
|
||||||
fsaa_dirty = true;
|
fsaa_dirty = true;
|
||||||
@@ -712,7 +724,7 @@ void Canvas::startGrab(const std::vector<Canvas *> &canvases)
|
|||||||
if (!isMultiCanvasSupported())
|
if (!isMultiCanvasSupported())
|
||||||
throw love::Exception("Multi-canvas rendering is not supported on this system.");
|
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);
|
throw love::Exception("This system can't simultaniously render to %d canvases.", canvases.size()+1);
|
||||||
|
|
||||||
if (fsaa_samples != 0)
|
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)
|
if (canvases[i]->getWidth() != width || canvases[i]->getHeight() != height)
|
||||||
throw love::Exception("All canvas arguments must have the same dimensions.");
|
throw love::Exception("All canvas arguments must have the same dimensions.");
|
||||||
|
|
||||||
if (canvases[i]->getTextureType() != texture_type)
|
if (canvases[i]->getTextureFormat() != format)
|
||||||
throw love::Exception("All canvas arguments must have the same texture type.");
|
throw love::Exception("All canvas arguments must have the same texture format.");
|
||||||
|
|
||||||
if (canvases[i]->getFSAA() != 0)
|
if (canvases[i]->getFSAA() != 0)
|
||||||
throw love::Exception("Multi-canvas rendering is not supported with FSAA.");
|
throw love::Exception("Multi-canvas rendering is not supported with FSAA.");
|
||||||
@@ -769,7 +781,7 @@ void Canvas::startGrab()
|
|||||||
attachedCanvases.clear();
|
attachedCanvases.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::stopGrab()
|
void Canvas::stopGrab(bool switchingToOtherCanvas)
|
||||||
{
|
{
|
||||||
// i am not grabbing. leave me alone
|
// i am not grabbing. leave me alone
|
||||||
if (current != this)
|
if (current != this)
|
||||||
@@ -782,13 +794,25 @@ void Canvas::stopGrab()
|
|||||||
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 2, attachments);
|
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 2, attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind default
|
if (switchingToOtherCanvas)
|
||||||
strategy->bindFBO(gl.getDefaultFBO());
|
{
|
||||||
|
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();
|
gl.matrices.projection.pop();
|
||||||
|
|
||||||
current = nullptr;
|
|
||||||
|
|
||||||
gl.setViewport(systemViewport);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::clear(Color c)
|
void Canvas::clear(Color c)
|
||||||
@@ -959,6 +983,18 @@ bool Canvas::isHDRSupported()
|
|||||||
return GLAD_VERSION_3_0 || (isSupported() && GLAD_ARB_texture_float);
|
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()
|
bool Canvas::isMultiCanvasSupported()
|
||||||
{
|
{
|
||||||
// system must support at least 4 simultanious active canvases.
|
// system must support at least 4 simultanious active canvases.
|
||||||
@@ -971,23 +1007,6 @@ void Canvas::bindDefaultCanvas()
|
|||||||
current->stopGrab();
|
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
|
} // opengl
|
||||||
} // graphics
|
} // graphics
|
||||||
} // love
|
} // love
|
||||||
|
|||||||
@@ -39,14 +39,7 @@ class Canvas : public Texture
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum TextureType
|
Canvas(int width, int height, Texture::Format format = Texture::FORMAT_NORMAL, int fsaa = 0);
|
||||||
{
|
|
||||||
TYPE_NORMAL,
|
|
||||||
TYPE_HDR,
|
|
||||||
TYPE_MAX_ENUM
|
|
||||||
};
|
|
||||||
|
|
||||||
Canvas(int width, int height, TextureType texture_type = TYPE_NORMAL, int fsaa = 0);
|
|
||||||
virtual ~Canvas();
|
virtual ~Canvas();
|
||||||
|
|
||||||
// Implements Volatile.
|
// Implements Volatile.
|
||||||
@@ -69,7 +62,7 @@ public:
|
|||||||
**/
|
**/
|
||||||
void startGrab(const std::vector<Canvas *> &canvases);
|
void startGrab(const std::vector<Canvas *> &canvases);
|
||||||
void startGrab();
|
void startGrab();
|
||||||
void stopGrab();
|
void stopGrab(bool switchingToOtherCanvas = false);
|
||||||
|
|
||||||
void clear(Color c);
|
void clear(Color c);
|
||||||
|
|
||||||
@@ -92,9 +85,9 @@ public:
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline TextureType getTextureType() const
|
inline Texture::Format getTextureFormat() const
|
||||||
{
|
{
|
||||||
return texture_type;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int getFSAA() const
|
inline int getFSAA() const
|
||||||
@@ -106,17 +99,18 @@ public:
|
|||||||
|
|
||||||
static bool isSupported();
|
static bool isSupported();
|
||||||
static bool isHDRSupported();
|
static bool isHDRSupported();
|
||||||
|
static bool isSRGBSupported();
|
||||||
static bool isMultiCanvasSupported();
|
static bool isMultiCanvasSupported();
|
||||||
|
|
||||||
static bool getConstant(const char *in, TextureType &out);
|
|
||||||
static bool getConstant(TextureType in, const char *&out);
|
|
||||||
|
|
||||||
static Canvas *current;
|
static Canvas *current;
|
||||||
static void bindDefaultCanvas();
|
static void bindDefaultCanvas();
|
||||||
|
|
||||||
// The viewport dimensions of the system (default) framebuffer.
|
// The viewport dimensions of the system (default) framebuffer.
|
||||||
static OpenGL::Viewport systemViewport;
|
static OpenGL::Viewport systemViewport;
|
||||||
|
|
||||||
|
// Whether the main screen should have linear -> sRGB conversions enabled.
|
||||||
|
static bool screenHasSRGB;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool createFSAAFBO(GLenum internalformat);
|
bool createFSAAFBO(GLenum internalformat);
|
||||||
@@ -128,7 +122,7 @@ private:
|
|||||||
GLuint fsaa_buffer;
|
GLuint fsaa_buffer;
|
||||||
GLuint depth_stencil;
|
GLuint depth_stencil;
|
||||||
|
|
||||||
TextureType texture_type;
|
Format format;
|
||||||
|
|
||||||
GLenum status;
|
GLenum status;
|
||||||
|
|
||||||
@@ -140,9 +134,7 @@ private:
|
|||||||
void setupGrab();
|
void setupGrab();
|
||||||
void drawv(const Matrix &t, const Vertex *v);
|
void drawv(const Matrix &t, const Vertex *v);
|
||||||
|
|
||||||
static StringMap<TextureType, TYPE_MAX_ENUM>::Entry textureTypeEntries[];
|
}; // Canvas
|
||||||
static StringMap<TextureType, TYPE_MAX_ENUM> textureTypes;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // opengl
|
} // opengl
|
||||||
} // graphics
|
} // graphics
|
||||||
|
|||||||
@@ -56,8 +56,13 @@ Graphics::Graphics()
|
|||||||
{
|
{
|
||||||
currentWindow = love::window::sdl::Window::createSingleton();
|
currentWindow = love::window::sdl::Window::createSingleton();
|
||||||
|
|
||||||
|
int w, h;
|
||||||
|
love::window::WindowSettings wsettings;
|
||||||
|
|
||||||
|
currentWindow->getWindow(w, h, wsettings);
|
||||||
|
|
||||||
if (currentWindow->isCreated())
|
if (currentWindow->isCreated())
|
||||||
setMode(currentWindow->getWidth(), currentWindow->getHeight());
|
setMode(w, h, wsettings.sRGB);
|
||||||
}
|
}
|
||||||
|
|
||||||
Graphics::~Graphics()
|
Graphics::~Graphics()
|
||||||
@@ -104,6 +109,8 @@ DisplayState Graphics::saveState()
|
|||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
s.colorMask[i] = colorMask[i];
|
s.colorMask[i] = colorMask[i];
|
||||||
|
|
||||||
|
wireframe = isWireframe();
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +128,7 @@ void Graphics::restoreState(const DisplayState &s)
|
|||||||
else
|
else
|
||||||
setScissor();
|
setScissor();
|
||||||
setColorMask(s.colorMask[0], s.colorMask[1], s.colorMask[2], s.colorMask[3]);
|
setColorMask(s.colorMask[0], s.colorMask[1], s.colorMask[2], s.colorMask[3]);
|
||||||
|
setWireframe(s.wireframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::setViewportSize(int width, int height)
|
void Graphics::setViewportSize(int width, int height)
|
||||||
@@ -151,7 +159,7 @@ void Graphics::setViewportSize(int width, int height)
|
|||||||
c->startGrab(c->getAttachedCanvases());
|
c->startGrab(c->getAttachedCanvases());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Graphics::setMode(int width, int height)
|
bool Graphics::setMode(int width, int height, bool &sRGB)
|
||||||
{
|
{
|
||||||
this->width = width;
|
this->width = width;
|
||||||
this->height = height;
|
this->height = height;
|
||||||
@@ -181,9 +189,6 @@ bool Graphics::setMode(int width, int height)
|
|||||||
// Enable blending
|
// Enable blending
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
// "Normal" blending
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
// Enable all color component writes.
|
// Enable all color component writes.
|
||||||
setColorMask(true, true, true, true);
|
setColorMask(true, true, true, true);
|
||||||
|
|
||||||
@@ -228,6 +233,19 @@ bool Graphics::setMode(int width, int height)
|
|||||||
Shader::defaultShader->attach();
|
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;
|
bool enabledebug = false;
|
||||||
|
|
||||||
if (GLAD_VERSION_3_0)
|
if (GLAD_VERSION_3_0)
|
||||||
@@ -238,7 +256,10 @@ bool Graphics::setMode(int width, int height)
|
|||||||
enabledebug = (flags & GL_CONTEXT_FLAG_DEBUG_BIT) != 0;
|
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;
|
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_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);
|
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");
|
::printf("OpenGL debug output enabled (LOVE_GRAPHICS_DEBUG=1)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,10 +454,10 @@ void Graphics::discardStencil()
|
|||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *Graphics::newImage(love::image::ImageData *data)
|
Image *Graphics::newImage(love::image::ImageData *data, Texture::Format format)
|
||||||
{
|
{
|
||||||
// Create the image.
|
// Create the image.
|
||||||
Image *image = new Image(data);
|
Image *image = new Image(data, format);
|
||||||
|
|
||||||
if (!isCreated())
|
if (!isCreated())
|
||||||
return image;
|
return image;
|
||||||
@@ -457,10 +481,10 @@ Image *Graphics::newImage(love::image::ImageData *data)
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *Graphics::newImage(love::image::CompressedData *cdata)
|
Image *Graphics::newImage(love::image::CompressedData *cdata, Texture::Format format)
|
||||||
{
|
{
|
||||||
// Create the image.
|
// Create the image.
|
||||||
Image *image = new Image(cdata);
|
Image *image = new Image(cdata, format);
|
||||||
|
|
||||||
if (!isCreated())
|
if (!isCreated())
|
||||||
return image;
|
return image;
|
||||||
@@ -504,11 +528,14 @@ ParticleSystem *Graphics::newParticleSystem(Texture *texture, int size)
|
|||||||
return new ParticleSystem(texture, 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");
|
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())
|
if (width > gl.getMaxTextureSize())
|
||||||
throw Exception("Cannot create canvas: width of %d pixels is too large for this system.", width);
|
throw Exception("Cannot create canvas: width of %d pixels is too large for this system.", width);
|
||||||
else if (height > gl.getMaxTextureSize())
|
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())
|
while (GL_NO_ERROR != glGetError())
|
||||||
/* clear opengl error flag */;
|
/* 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();
|
GLenum err = canvas->getStatus();
|
||||||
|
|
||||||
// everything ok, return canvas (early out)
|
// everything ok, return canvas (early out)
|
||||||
@@ -629,22 +656,16 @@ const bool *Graphics::getColorMask() const
|
|||||||
|
|
||||||
void Graphics::setBlendMode(Graphics::BlendMode mode)
|
void Graphics::setBlendMode(Graphics::BlendMode mode)
|
||||||
{
|
{
|
||||||
const int gl_1_4 = GLAD_VERSION_1_4;
|
OpenGL::BlendState state = {GL_ONE, GL_ONE, GL_ZERO, GL_ZERO, GL_FUNC_ADD};
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case BLEND_ALPHA:
|
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;
|
state.srcRGB = GL_SRC_ALPHA;
|
||||||
src_a = GL_ONE;
|
state.srcA = GL_ONE;
|
||||||
dst_rgb = dst_a = GL_ONE_MINUS_SRC_ALPHA;
|
state.dstRGB = state.dstA = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -652,100 +673,56 @@ void Graphics::setBlendMode(Graphics::BlendMode mode)
|
|||||||
// This will most likely only be used for the Microsoft software renderer and
|
// 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
|
// 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).
|
// different alpha value when reading back the default framebuffer (newScreenshot).
|
||||||
src_rgb = src_a = GL_SRC_ALPHA;
|
state.srcRGB = state.srcA = GL_SRC_ALPHA;
|
||||||
dst_rgb = dst_a = GL_ONE_MINUS_SRC_ALPHA;
|
state.dstRGB = state.dstA = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BLEND_MULTIPLICATIVE:
|
case BLEND_MULTIPLICATIVE:
|
||||||
src_rgb = src_a = GL_DST_COLOR;
|
state.srcRGB = state.srcA = GL_DST_COLOR;
|
||||||
dst_rgb = dst_a = GL_ZERO;
|
state.dstRGB = state.dstA = GL_ZERO;
|
||||||
break;
|
break;
|
||||||
case BLEND_PREMULTIPLIED:
|
case BLEND_PREMULTIPLIED:
|
||||||
src_rgb = src_a = GL_ONE;
|
state.srcRGB = state.srcA = GL_ONE;
|
||||||
dst_rgb = dst_a = GL_ONE_MINUS_SRC_ALPHA;
|
state.dstRGB = state.dstA = GL_ONE_MINUS_SRC_ALPHA;
|
||||||
break;
|
break;
|
||||||
case BLEND_SUBTRACTIVE:
|
case BLEND_SUBTRACTIVE:
|
||||||
func = GL_FUNC_REVERSE_SUBTRACT;
|
state.func = GL_FUNC_REVERSE_SUBTRACT;
|
||||||
case BLEND_ADDITIVE:
|
case BLEND_ADDITIVE:
|
||||||
src_rgb = src_a = GL_SRC_ALPHA;
|
state.srcRGB = state.srcA = GL_SRC_ALPHA;
|
||||||
dst_rgb = dst_a = GL_ONE;
|
state.dstRGB = state.dstA = GL_ONE;
|
||||||
break;
|
break;
|
||||||
case BLEND_REPLACE:
|
case BLEND_REPLACE:
|
||||||
default:
|
default:
|
||||||
src_rgb = src_a = GL_ONE;
|
state.srcRGB = state.srcA = GL_ONE;
|
||||||
dst_rgb = dst_a = GL_ZERO;
|
state.dstRGB = state.dstA = GL_ZERO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gl_1_4 || GLAD_ES_VERSION_2_0)
|
gl.setBlendState(state);
|
||||||
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!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Graphics::BlendMode Graphics::getBlendMode() const
|
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;
|
if (state.func == GL_FUNC_REVERSE_SUBTRACT) // && src == GL_SRC_ALPHA && dst == GL_ONE
|
||||||
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
|
|
||||||
return BLEND_SUBTRACTIVE;
|
return BLEND_SUBTRACTIVE;
|
||||||
// Everything else has equation == GL_FUNC_ADD.
|
// 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;
|
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.
|
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;
|
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;
|
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;
|
return BLEND_REPLACE;
|
||||||
}
|
}
|
||||||
else if (src_rgb == GL_SRC_ALPHA && src_a == GL_ONE &&
|
else if (state.srcRGB == GL_SRC_ALPHA && state.srcA == GL_ONE &&
|
||||||
dst_rgb == GL_ONE_MINUS_SRC_ALPHA && dst_a == GL_ONE_MINUS_SRC_ALPHA)
|
state.dstRGB == GL_ONE_MINUS_SRC_ALPHA && state.dstA == GL_ONE_MINUS_SRC_ALPHA)
|
||||||
return BLEND_ALPHA;
|
return BLEND_ALPHA;
|
||||||
|
|
||||||
throw Exception("Unknown blend mode");
|
throw Exception("Unknown blend mode");
|
||||||
@@ -835,6 +812,21 @@ Graphics::PointStyle Graphics::getPointStyle() const
|
|||||||
return POINT_ROUGH;
|
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)
|
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)
|
if (currentFont != nullptr)
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ struct DisplayState
|
|||||||
// Color mask.
|
// Color mask.
|
||||||
bool colorMask[4];
|
bool colorMask[4];
|
||||||
|
|
||||||
|
bool wireframe;
|
||||||
|
|
||||||
// Default values.
|
// Default values.
|
||||||
DisplayState()
|
DisplayState()
|
||||||
{
|
{
|
||||||
@@ -93,6 +95,7 @@ struct DisplayState
|
|||||||
pointStyle = Graphics::POINT_SMOOTH;
|
pointStyle = Graphics::POINT_SMOOTH;
|
||||||
scissor = false;
|
scissor = false;
|
||||||
colorMask[0] = colorMask[1] = colorMask[2] = colorMask[3] = true;
|
colorMask[0] = colorMask[1] = colorMask[2] = colorMask[3] = true;
|
||||||
|
wireframe = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -112,7 +115,7 @@ public:
|
|||||||
void restoreState(const DisplayState &s);
|
void restoreState(const DisplayState &s);
|
||||||
|
|
||||||
virtual void setViewportSize(int width, int height);
|
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();
|
virtual void unSetMode();
|
||||||
|
|
||||||
void setDebug(bool enable);
|
void setDebug(bool enable);
|
||||||
@@ -191,8 +194,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Creates an Image object with padding and/or optimization.
|
* Creates an Image object with padding and/or optimization.
|
||||||
**/
|
**/
|
||||||
Image *newImage(love::image::ImageData *data);
|
Image *newImage(love::image::ImageData *data, Texture::Format format = Texture::FORMAT_NORMAL);
|
||||||
Image *newImage(love::image::CompressedData *cdata);
|
Image *newImage(love::image::CompressedData *cdata, Texture::Format format = Texture::FORMAT_NORMAL);
|
||||||
|
|
||||||
Quad *newQuad(Quad::Viewport v, float sw, float sh);
|
Quad *newQuad(Quad::Viewport v, float sw, float sh);
|
||||||
|
|
||||||
@@ -205,7 +208,7 @@ public:
|
|||||||
|
|
||||||
ParticleSystem *newParticleSystem(Texture *texture, int size);
|
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);
|
Shader *newShader(const Shader::ShaderSources &sources);
|
||||||
|
|
||||||
@@ -334,6 +337,19 @@ public:
|
|||||||
**/
|
**/
|
||||||
PointStyle getPointStyle() const;
|
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
|
* Draws text at the specified coordinates, with rotation and
|
||||||
* scaling along both axes.
|
* scaling along both axes.
|
||||||
@@ -459,6 +475,7 @@ private:
|
|||||||
float lineWidth;
|
float lineWidth;
|
||||||
size_t matrixLimit;
|
size_t matrixLimit;
|
||||||
bool colorMask[4];
|
bool colorMask[4];
|
||||||
|
bool wireframe;
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ float Image::maxMipmapSharpness = 0.0f;
|
|||||||
Texture::FilterMode Image::defaultMipmapFilter = Texture::FILTER_NONE;
|
Texture::FilterMode Image::defaultMipmapFilter = Texture::FILTER_NONE;
|
||||||
float Image::defaultMipmapSharpness = 0.0f;
|
float Image::defaultMipmapSharpness = 0.0f;
|
||||||
|
|
||||||
Image::Image(love::image::ImageData *data)
|
Image::Image(love::image::ImageData *data, Texture::Format format)
|
||||||
: data(data)
|
: data(data)
|
||||||
, cdata(nullptr)
|
, cdata(nullptr)
|
||||||
, paddedWidth(width)
|
, paddedWidth(width)
|
||||||
@@ -45,6 +45,7 @@ Image::Image(love::image::ImageData *data)
|
|||||||
, mipmapSharpness(defaultMipmapSharpness)
|
, mipmapSharpness(defaultMipmapSharpness)
|
||||||
, mipmapsCreated(false)
|
, mipmapsCreated(false)
|
||||||
, compressed(false)
|
, compressed(false)
|
||||||
|
, format(format)
|
||||||
, usingDefaultTexture(false)
|
, usingDefaultTexture(false)
|
||||||
{
|
{
|
||||||
width = data->getWidth();
|
width = data->getWidth();
|
||||||
@@ -54,7 +55,7 @@ Image::Image(love::image::ImageData *data)
|
|||||||
preload();
|
preload();
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::Image(love::image::CompressedData *cdata)
|
Image::Image(love::image::CompressedData *cdata, Texture::Format format)
|
||||||
: data(nullptr)
|
: data(nullptr)
|
||||||
, cdata(cdata)
|
, cdata(cdata)
|
||||||
, paddedWidth(width)
|
, paddedWidth(width)
|
||||||
@@ -63,6 +64,7 @@ Image::Image(love::image::CompressedData *cdata)
|
|||||||
, mipmapSharpness(defaultMipmapSharpness)
|
, mipmapSharpness(defaultMipmapSharpness)
|
||||||
, mipmapsCreated(false)
|
, mipmapsCreated(false)
|
||||||
, compressed(true)
|
, compressed(true)
|
||||||
|
, format(format)
|
||||||
, usingDefaultTexture(false)
|
, usingDefaultTexture(false)
|
||||||
{
|
{
|
||||||
width = cdata->getWidth(0);
|
width = cdata->getWidth(0);
|
||||||
@@ -328,6 +330,9 @@ void Image::unload()
|
|||||||
|
|
||||||
bool Image::loadVolatile()
|
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()))
|
if (isCompressed() && cdata && !hasCompressedTextureSupport(cdata->getFormat()))
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
@@ -400,9 +405,10 @@ void Image::uploadTexturePadded()
|
|||||||
}
|
}
|
||||||
else if (data)
|
else if (data)
|
||||||
{
|
{
|
||||||
|
GLenum iformat = (format == FORMAT_SRGB) ? GL_SRGB_ALPHA : GL_RGBA;
|
||||||
glTexImage2D(GL_TEXTURE_2D,
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
GL_RGBA,
|
iformat,
|
||||||
(GLsizei)paddedWidth,
|
(GLsizei)paddedWidth,
|
||||||
(GLsizei)paddedHeight,
|
(GLsizei)paddedHeight,
|
||||||
0,
|
0,
|
||||||
@@ -437,9 +443,10 @@ void Image::uploadTexture()
|
|||||||
}
|
}
|
||||||
else if (data)
|
else if (data)
|
||||||
{
|
{
|
||||||
|
GLenum iformat = (format == FORMAT_SRGB) ? GL_SRGB_ALPHA : GL_RGBA;
|
||||||
glTexImage2D(GL_TEXTURE_2D,
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
GL_RGBA,
|
iformat,
|
||||||
(GLsizei)width,
|
(GLsizei)width,
|
||||||
(GLsizei)height,
|
(GLsizei)height,
|
||||||
0,
|
0,
|
||||||
@@ -497,6 +504,11 @@ bool Image::refresh()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture::Format Image::getFormat() const
|
||||||
|
{
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
void Image::uploadDefaultTexture()
|
void Image::uploadDefaultTexture()
|
||||||
{
|
{
|
||||||
usingDefaultTexture = true;
|
usingDefaultTexture = true;
|
||||||
@@ -561,16 +573,27 @@ bool Image::isCompressed() const
|
|||||||
return compressed;
|
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:
|
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:
|
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:
|
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:
|
case image::CompressedData::FORMAT_BC4:
|
||||||
return GL_COMPRESSED_RED_RGTC1;
|
return GL_COMPRESSED_RED_RGTC1;
|
||||||
case image::CompressedData::FORMAT_BC4s:
|
case image::CompressedData::FORMAT_BC4s:
|
||||||
@@ -580,7 +603,10 @@ GLenum Image::getCompressedFormat(image::CompressedData::Format format) const
|
|||||||
case image::CompressedData::FORMAT_BC5s:
|
case image::CompressedData::FORMAT_BC5s:
|
||||||
return GL_COMPRESSED_SIGNED_RG_RGTC2;
|
return GL_COMPRESSED_SIGNED_RG_RGTC2;
|
||||||
default:
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Image::hasSRGBSupport()
|
||||||
|
{
|
||||||
|
return GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB || GLAD_EXT_sRGB;
|
||||||
|
}
|
||||||
|
|
||||||
} // opengl
|
} // opengl
|
||||||
} // graphics
|
} // graphics
|
||||||
} // love
|
} // love
|
||||||
|
|||||||
@@ -56,14 +56,14 @@ public:
|
|||||||
*
|
*
|
||||||
* @param data The data from which to load the image.
|
* @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.
|
* Creates a new Image with compressed image data.
|
||||||
*
|
*
|
||||||
* @param cdata The compressed data from which to load the image.
|
* @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.
|
* Destructor. Deletes the hardware texture and other resources.
|
||||||
@@ -120,6 +120,8 @@ public:
|
|||||||
**/
|
**/
|
||||||
bool refresh();
|
bool refresh();
|
||||||
|
|
||||||
|
Texture::Format getFormat() const;
|
||||||
|
|
||||||
static void setDefaultMipmapSharpness(float sharpness);
|
static void setDefaultMipmapSharpness(float sharpness);
|
||||||
static float getDefaultMipmapSharpness();
|
static float getDefaultMipmapSharpness();
|
||||||
static void setDefaultMipmapFilter(FilterMode f);
|
static void setDefaultMipmapFilter(FilterMode f);
|
||||||
@@ -132,6 +134,8 @@ public:
|
|||||||
|
|
||||||
static bool hasCompressedTextureSupport(image::CompressedData::Format format);
|
static bool hasCompressedTextureSupport(image::CompressedData::Format format);
|
||||||
|
|
||||||
|
static bool hasSRGBSupport();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void uploadDefaultTexture();
|
void uploadDefaultTexture();
|
||||||
@@ -161,6 +165,9 @@ private:
|
|||||||
// Whether this Image is using a compressed texture.
|
// Whether this Image is using a compressed texture.
|
||||||
bool compressed;
|
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
|
// True if the image wasn't able to be properly created and it had to fall
|
||||||
// back to a default texture.
|
// back to a default texture.
|
||||||
bool usingDefaultTexture;
|
bool usingDefaultTexture;
|
||||||
@@ -179,7 +186,7 @@ private:
|
|||||||
static FilterMode defaultMipmapFilter;
|
static FilterMode defaultMipmapFilter;
|
||||||
static float defaultMipmapSharpness;
|
static float defaultMipmapSharpness;
|
||||||
|
|
||||||
GLenum getCompressedFormat(image::CompressedData::Format format) const;
|
GLenum getCompressedFormat(image::CompressedData::Format cformat) const;
|
||||||
|
|
||||||
}; // Image
|
}; // Image
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ Mesh::Mesh(const std::vector<Vertex> &verts, Mesh::DrawMode mode)
|
|||||||
, range_max(-1)
|
, range_max(-1)
|
||||||
, texture(nullptr)
|
, texture(nullptr)
|
||||||
, colors_enabled(false)
|
, colors_enabled(false)
|
||||||
, wireframe(false)
|
|
||||||
{
|
{
|
||||||
setVertices(verts);
|
setVertices(verts);
|
||||||
}
|
}
|
||||||
@@ -59,7 +58,6 @@ Mesh::Mesh(int vertexcount, Mesh::DrawMode mode)
|
|||||||
, range_max(-1)
|
, range_max(-1)
|
||||||
, texture(nullptr)
|
, texture(nullptr)
|
||||||
, colors_enabled(false)
|
, colors_enabled(false)
|
||||||
, wireframe(false)
|
|
||||||
{
|
{
|
||||||
if (vertexcount < 1)
|
if (vertexcount < 1)
|
||||||
throw love::Exception("Invalid number of vertices.");
|
throw love::Exception("Invalid number of vertices.");
|
||||||
@@ -278,16 +276,6 @@ bool Mesh::hasVertexColors() const
|
|||||||
return colors_enabled;
|
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)
|
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);
|
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));
|
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);
|
GLenum mode = getGLDrawMode(draw_mode);
|
||||||
|
|
||||||
gl.prepareDraw();
|
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_POS);
|
||||||
gl.disableVertexAttribArray(OpenGL::ATTRIB_TEXCOORD);
|
gl.disableVertexAttribArray(OpenGL::ATTRIB_TEXCOORD);
|
||||||
|
|
||||||
if (wireframe && GLAD_VERSION_1_0)
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
|
|
||||||
if (hasVertexColors())
|
if (hasVertexColors())
|
||||||
{
|
{
|
||||||
gl.disableVertexAttribArray(OpenGL::ATTRIB_COLOR);
|
gl.disableVertexAttribArray(OpenGL::ATTRIB_COLOR);
|
||||||
|
|||||||
@@ -162,15 +162,6 @@ public:
|
|||||||
void setVertexColors(bool enable);
|
void setVertexColors(bool enable);
|
||||||
bool hasVertexColors() const;
|
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.
|
// Implements Drawable.
|
||||||
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
|
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.
|
// Whether the per-vertex colors are used when drawing.
|
||||||
bool colors_enabled;
|
bool colors_enabled;
|
||||||
|
|
||||||
bool wireframe;
|
|
||||||
|
|
||||||
static StringMap<DrawMode, DRAW_MODE_MAX_ENUM>::Entry drawModeEntries[];
|
static StringMap<DrawMode, DRAW_MODE_MAX_ENUM>::Entry drawModeEntries[];
|
||||||
static StringMap<DrawMode, DRAW_MODE_MAX_ENUM> drawModes;
|
static StringMap<DrawMode, DRAW_MODE_MAX_ENUM> drawModes;
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,9 @@ bool OpenGL::initContext()
|
|||||||
if (Canvas::isSupported())
|
if (Canvas::isSupported())
|
||||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint *) &state.defaultFBO);
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint *) &state.defaultFBO);
|
||||||
|
|
||||||
|
BlendState blend = {GL_ONE, GL_ONE, GL_ZERO, GL_ZERO, GL_FUNC_ADD};
|
||||||
|
setBlendState(blend);
|
||||||
|
|
||||||
initMaxValues();
|
initMaxValues();
|
||||||
createDefaultTexture();
|
createDefaultTexture();
|
||||||
|
|
||||||
@@ -492,6 +495,40 @@ OpenGL::Viewport OpenGL::getScissor() const
|
|||||||
return state.scissor;
|
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)
|
void OpenGL::setPointSize(float size)
|
||||||
{
|
{
|
||||||
if (GLAD_VERSION_1_0)
|
if (GLAD_VERSION_1_0)
|
||||||
|
|||||||
@@ -103,6 +103,13 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BlendState
|
||||||
|
{
|
||||||
|
GLenum srcRGB, srcA;
|
||||||
|
GLenum dstRGB, dstA;
|
||||||
|
GLenum func;
|
||||||
|
};
|
||||||
|
|
||||||
// Transformation matrix stacks.
|
// Transformation matrix stacks.
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@@ -202,6 +209,17 @@ public:
|
|||||||
**/
|
**/
|
||||||
Viewport getScissor() const;
|
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.
|
* Sets the global point size.
|
||||||
**/
|
**/
|
||||||
@@ -332,6 +350,8 @@ private:
|
|||||||
|
|
||||||
GLuint defaultFBO;
|
GLuint defaultFBO;
|
||||||
|
|
||||||
|
BlendState blend;
|
||||||
|
|
||||||
// The last ID value used for pseudo-instancing.
|
// The last ID value used for pseudo-instancing.
|
||||||
int lastPseudoInstanceID;
|
int lastPseudoInstanceID;
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ ParticleSystem::ParticleSystem(Texture *texture, uint32 size)
|
|||||||
, spinVariation(0)
|
, spinVariation(0)
|
||||||
, offsetX(float(texture->getWidth())*0.5f)
|
, offsetX(float(texture->getWidth())*0.5f)
|
||||||
, offsetY(float(texture->getHeight())*0.5f)
|
, offsetY(float(texture->getHeight())*0.5f)
|
||||||
|
, relativeRotation(false)
|
||||||
{
|
{
|
||||||
if (size == 0 || size > MAX_PARTICLES)
|
if (size == 0 || size > MAX_PARTICLES)
|
||||||
throw love::Exception("Invalid ParticleSystem size.");
|
throw love::Exception("Invalid ParticleSystem size.");
|
||||||
@@ -146,6 +147,7 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p)
|
|||||||
, offsetX(p.offsetX)
|
, offsetX(p.offsetX)
|
||||||
, offsetY(p.offsetY)
|
, offsetY(p.offsetY)
|
||||||
, colors(p.colors)
|
, colors(p.colors)
|
||||||
|
, relativeRotation(p.relativeRotation)
|
||||||
{
|
{
|
||||||
setBufferSize(maxParticles);
|
setBufferSize(maxParticles);
|
||||||
|
|
||||||
@@ -170,7 +172,7 @@ void ParticleSystem::createBuffers(size_t size)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pFree = pMem = new particle[size];
|
pFree = pMem = new Particle[size];
|
||||||
particleVerts = new love::Vertex[size * 4];
|
particleVerts = new love::Vertex[size * 4];
|
||||||
ibo = new VertexIndex(size);
|
ibo = new VertexIndex(size);
|
||||||
maxParticles = (uint32) size;
|
maxParticles = (uint32) size;
|
||||||
@@ -222,7 +224,7 @@ void ParticleSystem::addParticle(float t)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Gets a free particle and updates the allocation pointer.
|
// Gets a free particle and updates the allocation pointer.
|
||||||
particle *p = pFree++;
|
Particle *p = pFree++;
|
||||||
initParticle(p, t);
|
initParticle(p, t);
|
||||||
|
|
||||||
switch (insertMode)
|
switch (insertMode)
|
||||||
@@ -242,7 +244,7 @@ void ParticleSystem::addParticle(float t)
|
|||||||
activeParticles++;
|
activeParticles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleSystem::initParticle(particle *p, float t)
|
void ParticleSystem::initParticle(Particle *p, float t)
|
||||||
{
|
{
|
||||||
float min,max;
|
float min,max;
|
||||||
|
|
||||||
@@ -308,10 +310,14 @@ void ParticleSystem::initParticle(particle *p, float t)
|
|||||||
p->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation);
|
p->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation);
|
||||||
p->rotation = (float) rng.random(min, max);
|
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];
|
p->color = colors[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleSystem::insertTop(particle *p)
|
void ParticleSystem::insertTop(Particle *p)
|
||||||
{
|
{
|
||||||
if (pHead == nullptr)
|
if (pHead == nullptr)
|
||||||
{
|
{
|
||||||
@@ -327,7 +333,7 @@ void ParticleSystem::insertTop(particle *p)
|
|||||||
pTail = p;
|
pTail = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleSystem::insertBottom(particle *p)
|
void ParticleSystem::insertBottom(Particle *p)
|
||||||
{
|
{
|
||||||
if (pTail == nullptr)
|
if (pTail == nullptr)
|
||||||
{
|
{
|
||||||
@@ -343,7 +349,7 @@ void ParticleSystem::insertBottom(particle *p)
|
|||||||
pHead = p;
|
pHead = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleSystem::insertRandom(particle *p)
|
void ParticleSystem::insertRandom(Particle *p)
|
||||||
{
|
{
|
||||||
// Nonuniform, but 64-bit is so large nobody will notice. Hopefully.
|
// Nonuniform, but 64-bit is so large nobody will notice. Hopefully.
|
||||||
uint64 pos = rng.rand() % ((int64) activeParticles + 1);
|
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.
|
// Special case where the particle gets inserted before the head.
|
||||||
if (pos == activeParticles)
|
if (pos == activeParticles)
|
||||||
{
|
{
|
||||||
particle *pA = pHead;
|
Particle *pA = pHead;
|
||||||
if (pA)
|
if (pA)
|
||||||
pA->prev = p;
|
pA->prev = p;
|
||||||
p->prev = nullptr;
|
p->prev = nullptr;
|
||||||
@@ -361,8 +367,8 @@ void ParticleSystem::insertRandom(particle *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inserts the particle after the randomly selected particle.
|
// Inserts the particle after the randomly selected particle.
|
||||||
particle *pA = pMem + pos;
|
Particle *pA = pMem + pos;
|
||||||
particle *pB = pA->next;
|
Particle *pB = pA->next;
|
||||||
pA->next = p;
|
pA->next = p;
|
||||||
if (pB)
|
if (pB)
|
||||||
pB->prev = p;
|
pB->prev = p;
|
||||||
@@ -372,12 +378,12 @@ void ParticleSystem::insertRandom(particle *p)
|
|||||||
p->next = pB;
|
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
|
// The linked list is updated in this function and old pointers may be
|
||||||
// invalidated. The returned pointer will inform the caller of the new
|
// invalidated. The returned pointer will inform the caller of the new
|
||||||
// pointer to the next particle.
|
// pointer to the next particle.
|
||||||
particle *pNext = nullptr;
|
Particle *pNext = nullptr;
|
||||||
|
|
||||||
// Removes the particle from the linked list.
|
// Removes the particle from the linked list.
|
||||||
if (p->prev)
|
if (p->prev)
|
||||||
@@ -725,6 +731,16 @@ std::vector<Color> ParticleSystem::getColor() const
|
|||||||
return ncolors;
|
return ncolors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParticleSystem::setRelativeRotation(bool enable)
|
||||||
|
{
|
||||||
|
relativeRotation = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParticleSystem::hasRelativeRotation() const
|
||||||
|
{
|
||||||
|
return relativeRotation;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 ParticleSystem::getCount() const
|
uint32 ParticleSystem::getCount() const
|
||||||
{
|
{
|
||||||
return activeParticles;
|
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();
|
const Vertex *textureVerts = texture->getVertices();
|
||||||
Vertex *pVerts = particleVerts;
|
Vertex *pVerts = particleVerts;
|
||||||
particle *p = pHead;
|
Particle *p = pHead;
|
||||||
|
|
||||||
// set the vertex data for each particle (transformation, texcoords, color)
|
// set the vertex data for each particle (transformation, texcoords, color)
|
||||||
while (p)
|
while (p)
|
||||||
{
|
{
|
||||||
// particle vertices are image vertices transformed by particle information
|
// 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);
|
t.transform(pVerts, textureVerts, 4);
|
||||||
|
|
||||||
// set the texture coordinate and color data for particle vertices
|
// set the texture coordinate and color data for particle vertices
|
||||||
@@ -871,7 +887,7 @@ void ParticleSystem::update(float dt)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Traverse all particles and update.
|
// Traverse all particles and update.
|
||||||
particle *p = pHead;
|
Particle *p = pHead;
|
||||||
|
|
||||||
while (p)
|
while (p)
|
||||||
{
|
{
|
||||||
@@ -916,7 +932,12 @@ void ParticleSystem::update(float dt)
|
|||||||
const float t = 1.0f - p->life / p->lifetime;
|
const float t = 1.0f - p->life / p->lifetime;
|
||||||
|
|
||||||
// Rotate.
|
// 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:
|
// Change size according to given intervals:
|
||||||
// i = 0 1 2 3 n-1
|
// i = 0 1 2 3 n-1
|
||||||
|
|||||||
@@ -422,6 +422,12 @@ public:
|
|||||||
**/
|
**/
|
||||||
std::vector<Color> getColor() const;
|
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.
|
* 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);
|
static bool getConstant(InsertMode in, const char *&out);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Represents a single particle.
|
// Represents a single particle.
|
||||||
struct particle
|
struct Particle
|
||||||
{
|
{
|
||||||
particle *prev;
|
Particle *prev;
|
||||||
particle *next;
|
Particle *next;
|
||||||
|
|
||||||
float lifetime;
|
float lifetime;
|
||||||
float life;
|
float life;
|
||||||
@@ -519,7 +526,8 @@ protected:
|
|||||||
float sizeOffset;
|
float sizeOffset;
|
||||||
float sizeIntervalSize;
|
float sizeIntervalSize;
|
||||||
|
|
||||||
float rotation;
|
float rotation; // Amount of rotation applied to the final angle.
|
||||||
|
float angle;
|
||||||
float spinStart;
|
float spinStart;
|
||||||
float spinEnd;
|
float spinEnd;
|
||||||
|
|
||||||
@@ -527,16 +535,16 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Pointer to the beginning of the allocated memory.
|
// Pointer to the beginning of the allocated memory.
|
||||||
particle *pMem;
|
Particle *pMem;
|
||||||
|
|
||||||
// Pointer to a free particle.
|
// Pointer to a free particle.
|
||||||
particle *pFree;
|
Particle *pFree;
|
||||||
|
|
||||||
// Pointer to the start of the linked list.
|
// Pointer to the start of the linked list.
|
||||||
particle *pHead;
|
Particle *pHead;
|
||||||
|
|
||||||
// Pointer to the end of the linked list.
|
// Pointer to the end of the linked list.
|
||||||
particle *pTail;
|
Particle *pTail;
|
||||||
|
|
||||||
// array of transformed vertex data for all particles, for drawing
|
// array of transformed vertex data for all particles, for drawing
|
||||||
Vertex *particleVerts;
|
Vertex *particleVerts;
|
||||||
@@ -621,17 +629,19 @@ protected:
|
|||||||
// Color.
|
// Color.
|
||||||
std::vector<Colorf> colors;
|
std::vector<Colorf> colors;
|
||||||
|
|
||||||
|
bool relativeRotation;
|
||||||
|
|
||||||
void createBuffers(size_t size);
|
void createBuffers(size_t size);
|
||||||
void deleteBuffers();
|
void deleteBuffers();
|
||||||
|
|
||||||
void addParticle(float t);
|
void addParticle(float t);
|
||||||
particle *removeParticle(particle *p);
|
Particle *removeParticle(Particle *p);
|
||||||
|
|
||||||
// Called by addParticle.
|
// Called by addParticle.
|
||||||
void initParticle(particle *p, float t);
|
void initParticle(Particle *p, float t);
|
||||||
void insertTop(particle *p);
|
void insertTop(Particle *p);
|
||||||
void insertBottom(particle *p);
|
void insertBottom(Particle *p);
|
||||||
void insertRandom(particle *p);
|
void insertRandom(Particle *p);
|
||||||
|
|
||||||
static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM>::Entry distributionsEntries[];
|
static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM>::Entry distributionsEntries[];
|
||||||
static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM> distributions;
|
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)
|
if ((index == -1 && next >= size) || index < -1 || index >= size)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
Vertex sprite[4];
|
||||||
|
|
||||||
// Needed for colors.
|
// Needed for colors.
|
||||||
memcpy(sprite, texture->getVertices(), sizeof(Vertex) * 4);
|
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)
|
if ((index == -1 && next >= size) || index < -1 || index >= next)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
Vertex sprite[4];
|
||||||
|
|
||||||
// Needed for colors.
|
// Needed for colors.
|
||||||
memcpy(sprite, quad->getVertices(), sizeof(Vertex) * 4);
|
memcpy(sprite, quad->getVertices(), sizeof(Vertex) * 4);
|
||||||
|
|
||||||
|
|||||||
@@ -135,8 +135,6 @@ private:
|
|||||||
// The next free element.
|
// The next free element.
|
||||||
int next;
|
int next;
|
||||||
|
|
||||||
Vertex sprite[4];
|
|
||||||
|
|
||||||
// Current color. This color, if present, will be applied to the next
|
// Current color. This color, if present, will be applied to the next
|
||||||
// added sprite.
|
// added sprite.
|
||||||
Color *color;
|
Color *color;
|
||||||
|
|||||||
@@ -110,12 +110,14 @@ int w_Canvas_clear(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_Canvas_getType(lua_State *L)
|
int w_Canvas_getFormat(lua_State *L)
|
||||||
{
|
{
|
||||||
Canvas *canvas = luax_checkcanvas(L, 1);
|
Canvas *canvas = luax_checkcanvas(L, 1);
|
||||||
Canvas::TextureType type = canvas->getTextureType();
|
Texture::Format format = canvas->getTextureFormat();
|
||||||
const char *str;
|
const char *str;
|
||||||
Canvas::getConstant(type, str);
|
if (!Texture::getConstant(format, str))
|
||||||
|
return luaL_error(L, "Unknown texture format.");
|
||||||
|
|
||||||
lua_pushstring(L, str);
|
lua_pushstring(L, str);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -142,8 +144,11 @@ static const luaL_Reg functions[] =
|
|||||||
{ "getImageData", w_Canvas_getImageData },
|
{ "getImageData", w_Canvas_getImageData },
|
||||||
{ "getPixel", w_Canvas_getPixel },
|
{ "getPixel", w_Canvas_getPixel },
|
||||||
{ "clear", w_Canvas_clear },
|
{ "clear", w_Canvas_clear },
|
||||||
{ "getType", w_Canvas_getType },
|
{ "getFormat", w_Canvas_getFormat },
|
||||||
{ "getFSAA", w_Canvas_getFSAA },
|
{ "getFSAA", w_Canvas_getFSAA },
|
||||||
|
|
||||||
|
// Deprecated since 0.9.1.
|
||||||
|
{ "getType", w_Canvas_getFormat },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ int w_Canvas_renderTo(lua_State *L);
|
|||||||
int w_Canvas_getImageData(lua_State *L);
|
int w_Canvas_getImageData(lua_State *L);
|
||||||
int w_Canvas_getPixel(lua_State * L);
|
int w_Canvas_getPixel(lua_State * L);
|
||||||
int w_Canvas_clear(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);
|
int w_Canvas_getFSAA(lua_State *L);
|
||||||
extern "C" int luaopen_canvas(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)
|
int w_newImage(lua_State *L)
|
||||||
{
|
{
|
||||||
love::image::ImageData *data = 0;
|
love::image::ImageData *data = nullptr;
|
||||||
love::image::CompressedData *cdata = 0;
|
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.
|
// Convert to FileData, if necessary.
|
||||||
if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T))
|
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.");
|
return luaL_error(L, "Error creating image.");
|
||||||
|
|
||||||
// Create the image.
|
// Create the image.
|
||||||
Image *image = 0;
|
Image *image = nullptr;
|
||||||
EXCEPT_GUARD(
|
EXCEPT_GUARD(
|
||||||
if (cdata)
|
if (cdata)
|
||||||
image = instance->newImage(cdata);
|
image = instance->newImage(cdata, format);
|
||||||
else if (data)
|
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.");
|
return luaL_error(L, "Could not load image.");
|
||||||
|
|
||||||
// Push the type.
|
// Push the type.
|
||||||
@@ -325,12 +334,12 @@ int w_newCanvas(lua_State *L)
|
|||||||
const char *str = luaL_optstring(L, 3, "normal");
|
const char *str = luaL_optstring(L, 3, "normal");
|
||||||
int fsaa = luaL_optint(L, 4, 0);
|
int fsaa = luaL_optint(L, 4, 0);
|
||||||
|
|
||||||
Canvas::TextureType texture_type;
|
Texture::Format format;
|
||||||
if (!Canvas::getConstant(str, texture_type))
|
if (!Texture::getConstant(str, format))
|
||||||
return luaL_error(L, "Invalid canvas type: %s", str);
|
return luaL_error(L, "Invalid texture format: %s", str);
|
||||||
|
|
||||||
Canvas *canvas = nullptr;
|
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)
|
if (canvas == nullptr)
|
||||||
return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
|
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;
|
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)
|
int w_newScreenshot(lua_State *L)
|
||||||
{
|
{
|
||||||
love::image::Image *image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
|
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)))
|
if (!(GLAD_ARB_draw_instanced || (GLAD_ES_VERSION_2_0 && GLAD_EXT_draw_instanced)))
|
||||||
supported = false;
|
supported = false;
|
||||||
break;
|
break;
|
||||||
|
case Graphics::SUPPORT_SRGB:
|
||||||
|
if (!Canvas::isSRGBSupported())
|
||||||
|
supported = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
supported = false;
|
supported = false;
|
||||||
}
|
}
|
||||||
@@ -1405,6 +1430,8 @@ static const luaL_Reg functions[] =
|
|||||||
{ "setPointStyle", w_setPointStyle },
|
{ "setPointStyle", w_setPointStyle },
|
||||||
{ "getPointSize", w_getPointSize },
|
{ "getPointSize", w_getPointSize },
|
||||||
{ "getPointStyle", w_getPointStyle },
|
{ "getPointStyle", w_getPointStyle },
|
||||||
|
{ "setWireframe", w_setWireframe },
|
||||||
|
{ "isWireframe", w_isWireframe },
|
||||||
{ "newScreenshot", w_newScreenshot },
|
{ "newScreenshot", w_newScreenshot },
|
||||||
{ "setCanvas", w_setCanvas },
|
{ "setCanvas", w_setCanvas },
|
||||||
{ "getCanvas", w_getCanvas },
|
{ "getCanvas", w_getCanvas },
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ int w_setPointStyle(lua_State *L);
|
|||||||
int w_getPointSize(lua_State *L);
|
int w_getPointSize(lua_State *L);
|
||||||
int w_getPointStyle(lua_State *L);
|
int w_getPointStyle(lua_State *L);
|
||||||
int w_getMaxPointSize(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_newScreenshot(lua_State *L);
|
||||||
int w_setCanvas(lua_State *L);
|
int w_setCanvas(lua_State *L);
|
||||||
int w_getCanvas(lua_State *L);
|
int w_getCanvas(lua_State *L);
|
||||||
|
|||||||
@@ -361,20 +361,6 @@ int w_Mesh_hasVertexColors(lua_State *L)
|
|||||||
return 1;
|
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[] =
|
static const luaL_Reg functions[] =
|
||||||
{
|
{
|
||||||
{ "setVertex", w_Mesh_setVertex },
|
{ "setVertex", w_Mesh_setVertex },
|
||||||
@@ -394,8 +380,6 @@ static const luaL_Reg functions[] =
|
|||||||
{ "getDrawRange", w_Mesh_getDrawRange },
|
{ "getDrawRange", w_Mesh_getDrawRange },
|
||||||
{ "setVertexColors", w_Mesh_setVertexColors },
|
{ "setVertexColors", w_Mesh_setVertexColors },
|
||||||
{ "hasVertexColors", w_Mesh_hasVertexColors },
|
{ "hasVertexColors", w_Mesh_hasVertexColors },
|
||||||
{ "setWireframe", w_Mesh_setWireframe },
|
|
||||||
{ "isWireframe", w_Mesh_isWireframe },
|
|
||||||
|
|
||||||
// Deprecated since 0.9.1.
|
// Deprecated since 0.9.1.
|
||||||
{ "setImage", w_Mesh_setTexture },
|
{ "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_getDrawRange(lua_State *L);
|
||||||
int w_Mesh_setVertexColors(lua_State *L);
|
int w_Mesh_setVertexColors(lua_State *L);
|
||||||
int w_Mesh_hasVertexColors(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);
|
extern "C" int luaopen_mesh(lua_State *L);
|
||||||
|
|
||||||
|
|||||||
@@ -569,6 +569,20 @@ int w_ParticleSystem_getColors(lua_State *L)
|
|||||||
return colors.size();
|
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)
|
int w_ParticleSystem_getCount(lua_State *L)
|
||||||
{
|
{
|
||||||
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
||||||
@@ -687,6 +701,8 @@ static const luaL_Reg functions[] =
|
|||||||
{ "getColors", w_ParticleSystem_getColors },
|
{ "getColors", w_ParticleSystem_getColors },
|
||||||
{ "setOffset", w_ParticleSystem_setOffset },
|
{ "setOffset", w_ParticleSystem_setOffset },
|
||||||
{ "getOffset", w_ParticleSystem_getOffset },
|
{ "getOffset", w_ParticleSystem_getOffset },
|
||||||
|
{ "setRelativeRotation", w_ParticleSystem_setRelativeRotation },
|
||||||
|
{ "hasRelativeRotation", w_ParticleSystem_hasRelativeRotation },
|
||||||
{ "getCount", w_ParticleSystem_getCount },
|
{ "getCount", w_ParticleSystem_getCount },
|
||||||
{ "start", w_ParticleSystem_start },
|
{ "start", w_ParticleSystem_start },
|
||||||
{ "stop", w_ParticleSystem_stop },
|
{ "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_getColors(lua_State *L);
|
||||||
int w_ParticleSystem_setOffset(lua_State *L);
|
int w_ParticleSystem_setOffset(lua_State *L);
|
||||||
int w_ParticleSystem_getOffset(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_getCount(lua_State *L);
|
||||||
int w_ParticleSystem_start(lua_State *L);
|
int w_ParticleSystem_start(lua_State *L);
|
||||||
int w_ParticleSystem_stop(lua_State *L);
|
int w_ParticleSystem_stop(lua_State *L);
|
||||||
|
|||||||
@@ -52,9 +52,6 @@
|
|||||||
// of addressing implementations directly.
|
// of addressing implementations directly.
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#if defined(LOVE_ENABLE_ANDROID)
|
|
||||||
extern int luaopen_love_android(lua_State*);
|
|
||||||
#endif
|
|
||||||
#if defined(LOVE_ENABLE_AUDIO)
|
#if defined(LOVE_ENABLE_AUDIO)
|
||||||
extern int luaopen_love_audio(lua_State*);
|
extern int luaopen_love_audio(lua_State*);
|
||||||
#endif
|
#endif
|
||||||
@@ -110,9 +107,6 @@ extern "C"
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const luaL_Reg modules[] = {
|
static const luaL_Reg modules[] = {
|
||||||
#if defined(LOVE_ENABLE_ANDROID)
|
|
||||||
{ "love.android", luaopen_love_android },
|
|
||||||
#endif
|
|
||||||
#if defined(LOVE_ENABLE_AUDIO)
|
#if defined(LOVE_ENABLE_AUDIO)
|
||||||
{ "love.audio", luaopen_love_audio },
|
{ "love.audio", luaopen_love_audio },
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -193,5 +193,35 @@ bool Math::isConvex(const std::vector<Vertex> &polygon)
|
|||||||
return true;
|
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
|
} // math
|
||||||
} // love
|
} // love
|
||||||
|
|||||||
@@ -53,26 +53,6 @@ public:
|
|||||||
virtual ~Math()
|
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()
|
* @copydoc RandomGenerator::random()
|
||||||
**/
|
**/
|
||||||
@@ -105,6 +85,26 @@ public:
|
|||||||
return rng.randomNormal(stddev);
|
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.
|
* Create a new random number generator.
|
||||||
**/
|
**/
|
||||||
@@ -136,6 +136,16 @@ public:
|
|||||||
**/
|
**/
|
||||||
bool isConvex(const std::vector<Vertex> &polygon);
|
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).
|
* Calculate Simplex noise for the specified coordinate(s).
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -20,8 +20,13 @@
|
|||||||
|
|
||||||
#include "RandomGenerator.h"
|
#include "RandomGenerator.h"
|
||||||
|
|
||||||
// STL
|
// C++
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
// C
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
@@ -36,25 +41,10 @@ RandomGenerator::RandomGenerator()
|
|||||||
{
|
{
|
||||||
// because it is too big for some compilers to handle ... if you know what
|
// because it is too big for some compilers to handle ... if you know what
|
||||||
// i mean
|
// i mean
|
||||||
#ifdef LOVE_BIG_ENDIAN
|
Seed newseed;
|
||||||
seed.b32.a = 0x0139408D;
|
newseed.b32.low = 0xCBBF7A44;
|
||||||
seed.b32.b = 0xCBBF7A44;
|
newseed.b32.high = 0x0139408D;
|
||||||
#else
|
setSeed(newseed);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 RandomGenerator::rand()
|
uint64 RandomGenerator::rand()
|
||||||
@@ -83,5 +73,71 @@ double RandomGenerator::randomNormal(double stddev)
|
|||||||
return r * sin(phi) * 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
|
} // math
|
||||||
} // love
|
} // love
|
||||||
|
|||||||
@@ -28,8 +28,9 @@
|
|||||||
#include "common/int.h"
|
#include "common/int.h"
|
||||||
#include "common/Object.h"
|
#include "common/Object.h"
|
||||||
|
|
||||||
// STL
|
// C++
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
@@ -45,54 +46,19 @@ public:
|
|||||||
uint64 b64;
|
uint64 b64;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint32 a;
|
#ifdef LOVE_BIG_ENDIAN
|
||||||
uint32 b;
|
uint32 high;
|
||||||
|
uint32 low;
|
||||||
|
#else
|
||||||
|
uint32 low;
|
||||||
|
uint32 high;
|
||||||
|
#endif
|
||||||
} b32;
|
} b32;
|
||||||
};
|
};
|
||||||
|
|
||||||
RandomGenerator();
|
RandomGenerator();
|
||||||
virtual ~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.
|
* Return uniformly distributed pseudo random integer.
|
||||||
*
|
*
|
||||||
@@ -138,6 +104,28 @@ public:
|
|||||||
**/
|
**/
|
||||||
double randomNormal(double stddev);
|
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:
|
private:
|
||||||
|
|
||||||
Seed seed;
|
Seed seed;
|
||||||
|
|||||||
@@ -32,21 +32,6 @@ namespace love
|
|||||||
namespace math
|
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)
|
int w_random(lua_State *L)
|
||||||
{
|
{
|
||||||
return luax_getrandom(L, 1, Math::instance.random());
|
return luax_getrandom(L, 1, Math::instance.random());
|
||||||
@@ -62,6 +47,32 @@ int w_randomNormal(lua_State *L)
|
|||||||
return 1;
|
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)
|
int w_newRandomGenerator(lua_State *L)
|
||||||
{
|
{
|
||||||
RandomGenerator::Seed s;
|
RandomGenerator::Seed s;
|
||||||
@@ -238,6 +249,70 @@ int w_isConvex(lua_State *L)
|
|||||||
return 1;
|
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)
|
int w_noise(lua_State *L)
|
||||||
{
|
{
|
||||||
float w, x, y, z;
|
float w, x, y, z;
|
||||||
@@ -277,14 +352,18 @@ int w_noise(lua_State *L)
|
|||||||
// List of functions to wrap.
|
// List of functions to wrap.
|
||||||
static const luaL_Reg functions[] =
|
static const luaL_Reg functions[] =
|
||||||
{
|
{
|
||||||
{ "setRandomSeed", w_setRandomSeed },
|
|
||||||
{ "getRandomSeed", w_getRandomSeed },
|
|
||||||
{ "random", w_random },
|
{ "random", w_random },
|
||||||
{ "randomNormal", w_randomNormal },
|
{ "randomNormal", w_randomNormal },
|
||||||
|
{ "setRandomSeed", w_setRandomSeed },
|
||||||
|
{ "getRandomSeed", w_getRandomSeed },
|
||||||
|
{ "setRandomState", w_setRandomState },
|
||||||
|
{ "getRandomState", w_getRandomState },
|
||||||
{ "newRandomGenerator", w_newRandomGenerator },
|
{ "newRandomGenerator", w_newRandomGenerator },
|
||||||
{ "newBezierCurve", w_newBezierCurve },
|
{ "newBezierCurve", w_newBezierCurve },
|
||||||
{ "triangulate", w_triangulate },
|
{ "triangulate", w_triangulate },
|
||||||
{ "isConvex", w_isConvex },
|
{ "isConvex", w_isConvex },
|
||||||
|
{ "gammaToLinear", w_gammaToLinear },
|
||||||
|
{ "linearToGamma", w_linearToGamma },
|
||||||
{ "noise", w_noise },
|
{ "noise", w_noise },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,14 +30,18 @@ namespace love
|
|||||||
namespace math
|
namespace math
|
||||||
{
|
{
|
||||||
|
|
||||||
int w_setRandomSeed(lua_State *L);
|
|
||||||
int w_getRandomSeed(lua_State *L);
|
|
||||||
int w_random(lua_State *L);
|
int w_random(lua_State *L);
|
||||||
int w_randomNormal(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_newRandomGenerator(lua_State *L);
|
||||||
int w_newBezierCurve(lua_State *L);
|
int w_newBezierCurve(lua_State *L);
|
||||||
int w_triangulate(lua_State *L);
|
int w_triangulate(lua_State *L);
|
||||||
int w_isConvex(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);
|
int w_noise(lua_State *L);
|
||||||
extern "C" LOVE_EXPORT int luaopen_love_math(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))
|
if (!lua_isnoneornil(L, idx + 1))
|
||||||
{
|
{
|
||||||
uint32 low = checkrandomseed_part<uint32>(L, idx);
|
s.b32.low = checkrandomseed_part<uint32>(L, idx);
|
||||||
uint32 high = checkrandomseed_part<uint32>(L, idx + 1);
|
s.b32.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
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
s.b64 = checkrandomseed_part<uint64>(L, idx);
|
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);
|
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)
|
int w_RandomGenerator_random(lua_State *L)
|
||||||
{
|
{
|
||||||
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
|
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
|
||||||
@@ -132,12 +105,44 @@ int w_RandomGenerator_randomNormal(lua_State *L)
|
|||||||
return 1;
|
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[] =
|
static const luaL_Reg functions[] =
|
||||||
{
|
{
|
||||||
{ "setSeed", w_RandomGenerator_setSeed },
|
|
||||||
{ "getSeed", w_RandomGenerator_getSeed },
|
|
||||||
{ "random", w_RandomGenerator_random },
|
{ "random", w_RandomGenerator_random },
|
||||||
{ "randomNormal", w_RandomGenerator_randomNormal },
|
{ "randomNormal", w_RandomGenerator_randomNormal },
|
||||||
|
{ "setSeed", w_RandomGenerator_setSeed },
|
||||||
|
{ "getSeed", w_RandomGenerator_getSeed },
|
||||||
|
{ "setState", w_RandomGenerator_setState },
|
||||||
|
{ "getState", w_RandomGenerator_getState },
|
||||||
{ 0, 0 }
|
{ 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);
|
int luax_getrandom(lua_State *L, int startidx, double r);
|
||||||
|
|
||||||
RandomGenerator *luax_checkrandomgenerator(lua_State *L, int idx);
|
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_random(lua_State *L);
|
||||||
int w_RandomGenerator_randomNormal(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);
|
extern "C" int luaopen_randomgenerator(lua_State *L);
|
||||||
|
|
||||||
} // math
|
} // math
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ namespace sdl
|
|||||||
// we want them in pixel coordinates (may be different with high-DPI enabled.)
|
// we want them in pixel coordinates (may be different with high-DPI enabled.)
|
||||||
static void windowToPixelCoords(int *x, int *y)
|
static void windowToPixelCoords(int *x, int *y)
|
||||||
{
|
{
|
||||||
|
#ifndef LOVE_ANDROID
|
||||||
double scale = 1.0;
|
double scale = 1.0;
|
||||||
|
|
||||||
love::window::Window *window = love::window::sdl::Window::getSingleton();
|
love::window::Window *window = love::window::sdl::Window::getSingleton();
|
||||||
@@ -47,11 +48,13 @@ static void windowToPixelCoords(int *x, int *y)
|
|||||||
|
|
||||||
if (y != nullptr)
|
if (y != nullptr)
|
||||||
*y = int(double(*y) * scale);
|
*y = int(double(*y) * scale);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// And vice versa for setting mouse coordinates.
|
// And vice versa for setting mouse coordinates.
|
||||||
static void pixelToWindowCoords(int *x, int *y)
|
static void pixelToWindowCoords(int *x, int *y)
|
||||||
{
|
{
|
||||||
|
#ifndef LOVE_ANDROID
|
||||||
double scale = 1.0;
|
double scale = 1.0;
|
||||||
|
|
||||||
love::window::Window *window = love::window::sdl::Window::getSingleton();
|
love::window::Window *window = love::window::sdl::Window::getSingleton();
|
||||||
@@ -63,6 +66,7 @@ static void pixelToWindowCoords(int *x, int *y)
|
|||||||
|
|
||||||
if (y != nullptr)
|
if (y != nullptr)
|
||||||
*y = int(double(*y) / scale);
|
*y = int(double(*y) / scale);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Mouse::getName() const
|
const char *Mouse::getName() const
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ WindowSettings::WindowSettings()
|
|||||||
, centered(true)
|
, centered(true)
|
||||||
, display(0)
|
, display(0)
|
||||||
, highdpi(false)
|
, highdpi(false)
|
||||||
|
, sRGB(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +87,7 @@ StringMap<Window::Setting, Window::SETTING_MAX_ENUM>::Entry Window::settingEntri
|
|||||||
{"centered", SETTING_CENTERED},
|
{"centered", SETTING_CENTERED},
|
||||||
{"display", SETTING_DISPLAY},
|
{"display", SETTING_DISPLAY},
|
||||||
{"highdpi", SETTING_HIGHDPI},
|
{"highdpi", SETTING_HIGHDPI},
|
||||||
|
{"srgb", SETTING_SRGB},
|
||||||
};
|
};
|
||||||
|
|
||||||
StringMap<Window::Setting, Window::SETTING_MAX_ENUM> Window::settings(Window::settingEntries, sizeof(Window::settingEntries));
|
StringMap<Window::Setting, Window::SETTING_MAX_ENUM> Window::settings(Window::settingEntries, sizeof(Window::settingEntries));
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
SETTING_CENTERED,
|
SETTING_CENTERED,
|
||||||
SETTING_DISPLAY,
|
SETTING_DISPLAY,
|
||||||
SETTING_HIGHDPI,
|
SETTING_HIGHDPI,
|
||||||
|
SETTING_SRGB,
|
||||||
SETTING_MAX_ENUM
|
SETTING_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -157,6 +158,7 @@ struct WindowSettings
|
|||||||
bool centered; // = true
|
bool centered; // = true
|
||||||
int display; // = 0
|
int display; // = 0
|
||||||
bool highdpi; // false
|
bool highdpi; // false
|
||||||
|
bool sRGB; // false
|
||||||
|
|
||||||
}; // WindowSettings
|
}; // WindowSettings
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,10 @@
|
|||||||
#include "graphics/Graphics.h"
|
#include "graphics/Graphics.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
|
||||||
|
#ifdef LOVE_ANDROID
|
||||||
|
#include "common/android.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// C++
|
// C++
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -85,7 +89,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
|||||||
f.minwidth = std::max(f.minwidth, 1);
|
f.minwidth = std::max(f.minwidth, 1);
|
||||||
f.minheight = std::max(f.minheight, 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.
|
// Use the desktop resolution if a width or height of 0 is specified.
|
||||||
if (width == 0 || height == 0)
|
if (width == 0 || height == 0)
|
||||||
@@ -157,7 +161,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
|||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
// In Windows and Linux, some GL attributes are set on window creation.
|
// 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();
|
const char *title = windowTitle.c_str();
|
||||||
int pos = f.centered ? centeredpos : uncenteredpos;
|
int pos = f.centered ? centeredpos : uncenteredpos;
|
||||||
@@ -193,7 +197,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
|||||||
|
|
||||||
SDL_RaiseWindow(window);
|
SDL_RaiseWindow(window);
|
||||||
|
|
||||||
if (!setContext(f.fsaa, f.vsync))
|
if (!setContext(f.fsaa, f.vsync, f.sRGB))
|
||||||
{
|
{
|
||||||
created = false;
|
created = false;
|
||||||
return false;
|
return false;
|
||||||
@@ -212,7 +216,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
|||||||
SDL_GL_GetDrawableSize(window, &width, &height);
|
SDL_GL_GetDrawableSize(window, &width, &height);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!gfx->setMode(width, height))
|
if (!gfx->setMode(width, height, curMode.settings.sRGB))
|
||||||
displayError("Could not set graphics mode", "Unsupported OpenGL version?");
|
displayError("Could not set graphics mode", "Unsupported OpenGL version?");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +237,7 @@ bool Window::onWindowResize(int width, int height)
|
|||||||
return true;
|
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
|
// We would normally only need to recreate the context if FSAA changes or
|
||||||
// SDL_GL_MakeCurrent is unsuccessful, but in Windows MakeCurrent can
|
// 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.
|
// Make sure the proper attributes are set.
|
||||||
setWindowGLAttributes(fsaa);
|
setWindowGLAttributes(fsaa, sRGB);
|
||||||
|
|
||||||
context = SDL_GL_CreateContext(window);
|
context = SDL_GL_CreateContext(window);
|
||||||
|
|
||||||
@@ -297,7 +301,7 @@ bool Window::setContext(int fsaa, bool vsync)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setWindowGLAttributes(int fsaa) const
|
void Window::setWindowGLAttributes(int fsaa, bool /* sRGB */) const
|
||||||
{
|
{
|
||||||
// Set GL window attributes.
|
// Set GL window attributes.
|
||||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
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_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 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;
|
int contextprofile = 0;
|
||||||
|
|
||||||
bool tryES2 = false;
|
bool tryES2 = false;
|
||||||
@@ -406,6 +419,8 @@ void Window::updateSettings(const WindowSettings &newsettings)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
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
|
void Window::displayError(const std::string &title, const std::string &text) const
|
||||||
@@ -671,7 +686,9 @@ double Window::getPixelScale() const
|
|||||||
{
|
{
|
||||||
double scale = 1.0;
|
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)
|
if (window)
|
||||||
{
|
{
|
||||||
int wheight;
|
int wheight;
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool setContext(int fsaa, bool vsync);
|
bool setContext(int fsaa, bool vsync, bool sRGB);
|
||||||
void setWindowGLAttributes(int fsaa) const;
|
void setWindowGLAttributes(int fsaa, bool sRGB) const;
|
||||||
|
|
||||||
// Update the saved window settings based on the window's actual state.
|
// Update the saved window settings based on the window's actual state.
|
||||||
void updateSettings(const WindowSettings &newsettings);
|
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.centered = luax_boolflag(L, 3, settingName(Window::SETTING_CENTERED), true);
|
||||||
settings.display = luax_intflag(L, 3, settingName(Window::SETTING_DISPLAY), 1);
|
settings.display = luax_intflag(L, 3, settingName(Window::SETTING_DISPLAY), 1);
|
||||||
settings.highdpi = luax_boolflag(L, 3, settingName(Window::SETTING_HIGHDPI), false);
|
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.
|
// Display index is 1-based in Lua and 0-based internally.
|
||||||
settings.display--;
|
settings.display--;
|
||||||
@@ -151,6 +152,9 @@ int w_getMode(lua_State *L)
|
|||||||
luax_pushboolean(L, settings.highdpi);
|
luax_pushboolean(L, settings.highdpi);
|
||||||
lua_setfield(L, -2, settingName(Window::SETTING_HIGHDPI));
|
lua_setfield(L, -2, settingName(Window::SETTING_HIGHDPI));
|
||||||
|
|
||||||
|
luax_pushboolean(L, settings.sRGB);
|
||||||
|
lua_setfield(L, -2, settingName(Window::SETTING_SRGB));
|
||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -313,9 +313,9 @@ function love.init()
|
|||||||
resizable = false,
|
resizable = false,
|
||||||
centered = true,
|
centered = true,
|
||||||
highdpi = false,
|
highdpi = false,
|
||||||
|
srgb = false,
|
||||||
},
|
},
|
||||||
modules = {
|
modules = {
|
||||||
android = true,
|
|
||||||
event = true,
|
event = true,
|
||||||
keyboard = true,
|
keyboard = true,
|
||||||
mouse = true,
|
mouse = true,
|
||||||
@@ -364,7 +364,6 @@ function love.init()
|
|||||||
|
|
||||||
-- Gets desired modules.
|
-- Gets desired modules.
|
||||||
for k,v in ipairs{
|
for k,v in ipairs{
|
||||||
"android",
|
|
||||||
"thread",
|
"thread",
|
||||||
"timer",
|
"timer",
|
||||||
"event",
|
"event",
|
||||||
@@ -406,6 +405,7 @@ function love.init()
|
|||||||
centered = c.window.centered,
|
centered = c.window.centered,
|
||||||
display = c.window.display,
|
display = c.window.display,
|
||||||
highdpi = c.window.highdpi,
|
highdpi = c.window.highdpi,
|
||||||
|
srgb = c.window.srgb,
|
||||||
}), "Could not set window mode")
|
}), "Could not set window mode")
|
||||||
love.window.setTitle(c.window.title or c.title)
|
love.window.setTitle(c.window.title or c.title)
|
||||||
if c.window.icon then
|
if c.window.icon then
|
||||||
|
|||||||
@@ -570,9 +570,9 @@ const unsigned char boot_lua[] =
|
|||||||
0x2c, 0x0a,
|
0x2c, 0x0a,
|
||||||
0x09, 0x09, 0x09, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65,
|
0x09, 0x09, 0x09, 0x68, 0x69, 0x67, 0x68, 0x64, 0x70, 0x69, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65,
|
||||||
0x2c, 0x0a,
|
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, 0x7d, 0x2c, 0x0a,
|
||||||
0x09, 0x09, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 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, 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,
|
0x09, 0x09, 0x09, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65,
|
||||||
0x2c, 0x0a,
|
0x2c, 0x0a,
|
||||||
@@ -645,7 +645,6 @@ const unsigned char boot_lua[] =
|
|||||||
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x0a,
|
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,
|
0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73,
|
||||||
0x7b, 0x0a,
|
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, 0x68, 0x72, 0x65, 0x61, 0x64, 0x22, 0x2c, 0x0a,
|
||||||
0x09, 0x09, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x72, 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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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: include dirs $(LOCAL_C_INCLUDES))
|
||||||
# $(info libmpg123: src files $(LOCAL_SRC_FILES))
|
# $(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 := \
|
LOCAL_SRC_FILES := \
|
||||||
$(filter-out \
|
$(filter-out \
|
||||||
Alc/mixer_neon.c \
|
Alc/mixer_neon.c \
|
||||||
|
Alc/mixer_inc.c \
|
||||||
Alc/mixer_sse.c \
|
Alc/mixer_sse.c \
|
||||||
, $(subst $(LOCAL_PATH)/,,\
|
, $(subst $(LOCAL_PATH)/,,\
|
||||||
${LOCAL_PATH}/Alc/backends/base.c \
|
${LOCAL_PATH}/Alc/backends/base.c \
|
||||||
@@ -29,9 +30,6 @@ LOCAL_SRC_FILES := \
|
|||||||
$(wildcard ${LOCAL_PATH}/OpenAL32/*.c) \
|
$(wildcard ${LOCAL_PATH}/OpenAL32/*.c) \
|
||||||
))
|
))
|
||||||
|
|
||||||
# $(info libopenal: include dirs $(LOCAL_C_INCLUDES))
|
LOCAL_LDLIBS := -lOpenSLES
|
||||||
# $(info libopenal: src files $(LOCAL_SRC_FILES))
|
|
||||||
|
|
||||||
LOCAL_LDLIBS := -llog -lOpenSLES
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
include $(BUILD_STATIC_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