Merge pull request #2 from libretro/master

Rebase
This commit is contained in:
Ryan 'Swingflip' Hamlin 2018-11-05 20:49:43 +00:00 committed by GitHub
commit dd5c352a7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 215 additions and 144 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ node_modules
/package.json
/.bsv
/*.mkv
*.d

5
.gitmodules vendored
View File

@ -13,11 +13,6 @@
url = https://github.com/ChaiScript/ChaiScript.git
ignore = dirty
branch = develop
[submodule "vendor/filesystem"]
path = vendor/filesystem
url = https://github.com/wjakob/filesystem.git
ignore = dirty
branch = master
[submodule "vendor/SDL_tty"]
path = vendor/SDL_tty
url = https://github.com/Grumbel/SDL_tty.git

View File

@ -4,6 +4,23 @@ All notable changes to [ChaiLove](https://github.com/RobLoach/ChaiLove) will be
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## 0.29.1 - 2018-11-05
### Chores
- Moved String Methods to [ChaiScript_Extras](https://github.com/ChaiScript/ChaiScript_Extras)
- Replaced use of `filesystem/path.h` with internal functions
- Updated ChaiScript/ChaiScript_Extras
- Updated libretro/libretro-common
- Updated effolkronium/random
## 0.29.0 - 2018-10-13
### Fixes
- Fixed `/libretro/saves` mounting
### Features
- Added `string::trim()`
- Added `string::split()`
- Adds loading of `conf.chai` for the `conf()` callback
## 0.28.0 - 2018-10-07
### Features
- `love.timer.step()` now returns `dt`

View File

@ -8,6 +8,7 @@ SOURCES_CXX := $(wildcard \
$(CORE_DIR)/src/love/Types/Graphics/*.cpp \
$(CORE_DIR)/src/love/Types/Input/*.cpp \
)
FLAGS += -Wfatal-errors
# semver
FLAGS += -I$(CORE_DIR)/vendor/semver
@ -16,9 +17,6 @@ SOURCES_C := $(CORE_DIR)/vendor/semver/semver.c
# random
FLAGS += -I$(CORE_DIR)/vendor/random/include
# filesystem
FLAGS += -I$(CORE_DIR)/vendor/filesystem
# libretro-common
FLAGS += -I$(CORE_DIR)/vendor/libretro-common/include
# Only compile libretro-common when not STATIC_LINKING
@ -48,7 +46,7 @@ ifneq ($(STATIC_LINKING), 1)
)
# Ensure the sinc_resampler_neon is available for ARM NEON devices.
OBJECTS += $(CORE_DIR)/vendor/libretro-common/audio/resampler/drivers/sinc_resampler_neon.o
# MD5
FLAGS += -I$(CORE_DIR)/vendor/libretro-common/include
SOURCES_C += $(CORE_DIR)/vendor/libretro-common/utils/md5.c
@ -189,6 +187,7 @@ ifeq ($(HAVE_CHAISCRIPT),)
FLAGS += -I$(CORE_DIR)/vendor/ChaiScript_Extras/include
FLAGS += -D__HAVE_CHAISCRIPT__
FLAGS += -DCHAISCRIPT_NO_THREADS -DCHAISCRIPT_NO_THREADS_WARNING -DCHAISCRIPT_NO_DYNLOAD
FLAGS += -DCHAISCRIPT_EXTRAS_MATH_SKIP_ADVANCED
endif
# SDL

View File

@ -277,19 +277,23 @@ else ifeq ($(platform), switch)
# Nintendo Switch (libnx)
else ifeq ($(platform), libnx)
include $(DEVKITPRO)/libnx/switch_rules
EXT=a
TARGET := $(TARGET_NAME)_libretro_$(platform).$(EXT)
DEFINES := -DSWITCH=1 -U__linux__ -U__linux -DRARCH_INTERNAL
CFLAGS := $(DEFINES) -g \
-O2 \
export DEPSDIR := $(CURDIR)/
include $(DEVKITPRO)/libnx/switch_rules
EXT=a
TARGET := $(TARGET_NAME)_libretro_$(platform).$(EXT)
DEFINES := -DSWITCH=1 -U__linux__ -U__linux -DRARCH_INTERNAL
CFLAGS := $(DEFINES) -g \
-O2 \
-fPIE -I$(LIBNX)/include/ -ffunction-sections -fdata-sections -ftls-model=local-exec -Wl,--allow-multiple-definition -specs=$(LIBNX)/switch.specs
CFLAGS += $(INCDIRS)
CFLAGS += $(INCLUDE) -D__SWITCH__ -DHAVE_LIBNX
CXXFLAGS := $(ASFLAGS) $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
CFLAGS += -std=gnu11
PLATFORM_DEFINES += -DARM -march=armv8-a -mtune=cortex-a57 -mtp=soft
STATIC_LINKING = 1
CFLAGS += $(INCDIRS)
CFLAGS += $(INCLUDE) -D__SWITCH__ -DHAVE_LIBNX
# Replaced -fno-rtti -fno-exceptions with -fexceptions, using C++14
CXXFLAGS := $(ASFLAGS) $(CFLAGS) -fexceptions -std=c++14
CFLAGS += -std=gnu11
PLATFORM_DEFINES += -DARM -march=armv8-a -mtune=cortex-a57 -mtp=soft
STATIC_LINKING = 1
#PLATFORM_DEFINES += -D_INCL_PHYSFS_PLATFORMS -DPHYSFS_PLATFORM_UNIX=1 -DPHYSFS_PLATFORM_POSIX=1
#PLATFORM_DEFINES += -Dpthread_t=Thread -Dpthread_mutex_t=Mutex -Dpthread_mutexattr_t='void*' -Dpthread_attr_t=int -Dpthread_cond_t=CondVar -Dpthread_condattr_t='int' -D_SYS__PTHREADTYPES_H_
# Classic Platforms ####################
# Platform affix = classic_<ISA>_<µARCH>

View File

@ -16,14 +16,20 @@ ChaiLove is an awesome framework you can use to make 2D games in [ChaiScript](ht
- [Game of Life](https://github.com/RobLoach/ChaiLove-GameOfLife)
- [... and more](https://github.com/topics/chailove)
## Usage
## Installation
ChaiLove is a [libretro](https://www.libretro.com/) core, which can be run through [RetroArch](http://retroarch.com/). [Floppy Bird](https://github.com/RobLoach/ChaiLove-FloppyBird) is a [free game you can download and play](https://www.youtube.com/watch?v=RLVwTh6qDFI)...
ChaiLove is a [libretro](https://www.libretro.com/) core, which can be installed through [RetroArch](http://retroarch.com/).
1. Run [RetroArch](http://retroarch.com/)
2. *Online Updater**Core Updator* → *ChaiLove*
3. *Online Updater**Content Downloader**ChaiLove* → *Floppy Bird*
4. *Load Content**Downloads* → *Floppy Bird.chailove*
## Usage
[Floppy Bird](https://github.com/RobLoach/ChaiLove-FloppyBird) is a [free game you can download and play](https://www.youtube.com/watch?v=RLVwTh6qDFI)...
1. Run [RetroArch](http://retroarch.com/)
2. *Online Updater**Content Downloader**ChaiLove* → *FloppyBird.chailove*
3. *Load Content**Downloads* → *FloppyBird.chailove*
Alternatively, you can run the ChaiLove core through RetroArch via the command line:

View File

@ -23,7 +23,7 @@ PROJECT_NAME = "ChaiLove API"
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = "0.28.0"
PROJECT_NUMBER = "0.29.1"
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.

View File

@ -0,0 +1,8 @@
/**
* ChaiLove callback; Configure the application.
*/
def conf(t) {
t.window.width = 720
t.window.height = 680
t.console = true
}

View File

@ -7,15 +7,6 @@ global sprites = List()
global img
global music
/**
* ChaiLove callback; Configure the application.
*/
def conf(t) {
t.window.width = 720
t.window.height = 680
t.console = true
}
/**
* ChaiLove callback; Load the application.
*/
@ -94,8 +85,8 @@ class Sprite {
def Sprite() {
this.x = love.math.random(love.graphics.getWidth()) * 1.0f
this.y = love.math.random(love.graphics.getHeight()) * 1.0f
this.xspeed = love.math.random(10) * 50.0f
this.yspeed = love.math.random(10) * 50.0f
this.xspeed = love.math.random(-10, 10) * 50
this.yspeed = love.math.random(-10, 10) * 50
}
def draw() {
@ -124,32 +115,3 @@ class Sprite {
}
}
};
def loadstate(data) {
print("Load State")
print(data)
var info = from_json(data)
var num = info["number"]
// Do something with the loaded number.
sprites.clear()
for (var i = 0; i < num; ++i) {
sprites.push_back(Sprite())
}
// The state loaded correctly, so return true.
return true
}
def savestate() {
// Retrieve the number to save.
var num = sprites.size()
// Construct the JSON data.
var data = ["number": num]
print("Save State")
print(to_json(data))
// Tell the system to save the JSON data.
return to_json(data)
}

9
examples/pong/conf.chai Normal file
View File

@ -0,0 +1,9 @@
/**
* ChaiLove callback; Configure the application.
*/
def conf(t) {
t.window.width = 640
t.window.height = 480
//t.modules.sound = false
t.console = true
}

View File

@ -5,16 +5,6 @@ global players = []
global pongSound
global ball
/**
* ChaiLove callback; Configure the application.
*/
def conf(t) {
t.window.width = 640
t.window.height = 480
//t.modules.sound = false
t.console = true
}
/**
* ChaiLove callback; Load the application.
*/
@ -29,7 +19,6 @@ def load() {
Player(false, 80.0f, love.graphics.getHeight() / 2.0f),
Player(true, love.graphics.getWidth() - 80.0f, love.graphics.getHeight() / 2.0f)
]
}
/**

View File

@ -47,7 +47,7 @@ global T
def conf(t) {
t.window.width = WIDTH * gridScale
t.window.height = HEIGHT * gridScale
t.version = "0.28.0"
t.version = "0.29.0"
}
/**

View File

@ -47,9 +47,9 @@
#define SRC_CHAILOVE_H_
#define CHAILOVE_VERSION_MAJOR 0
#define CHAILOVE_VERSION_MINOR 28
#define CHAILOVE_VERSION_PATCH 0
#define CHAILOVE_VERSION_STRING "0.28.0"
#define CHAILOVE_VERSION_MINOR 29
#define CHAILOVE_VERSION_PATCH 1
#define CHAILOVE_VERSION_STRING "0.29.1"
#include "SDL.h"
#include "libretro.h"

View File

@ -100,6 +100,24 @@ class String {
* @endcode
*/
std::string replace(const std::string& search, const std::string& replace);
/**
* Returns a trimmed version of the given string.
*
* @return A new string with trimmed left and right.
*
* @code
* var hello = " Hello World! "
* var result = hello.trim()
* // => "Hello World!"
* @endcode
*/
std::string trim();
/**
* Splits a string by the given token.
*/
std::string split(const std::string& token);
};
#endif // SRC_CHAILOVEDOCS_H_

View File

@ -78,7 +78,6 @@ void retro_set_environment(retro_environment_t cb) {
* libretro callback; Updates the core option variables.
*/
static void update_variables(void) {
std::cout << "[ChaiLove] [libretro] update_variables()" << std::endl;
ChaiLove* app = ChaiLove::getInstance();
app->system.updateVariables(app->config);
}
@ -226,8 +225,8 @@ void retro_set_controller_port_device(unsigned port, unsigned device) {
* libretro callback; Return the amount of bytes required to save a state.
*/
size_t retro_serialize_size(void) {
// Save states will be 5 kilobytes.
return 5000;
// Save states will be 8 KB.
return 8192;
}
/**
@ -314,7 +313,6 @@ void frame_time_cb(retro_usec_t usec) {
* libretro callback; Load the given game.
*/
bool retro_load_game(const struct retro_game_info *info) {
std::cout << "[ChaiLove] retro_load_game" << std::endl;
// Update the core options.
update_variables();

View File

@ -4,7 +4,6 @@
#include <stdio.h>
#include <stdlib.h>
#include "filesystem/path.h"
#include "../../../ChaiLove.h"
@ -38,9 +37,8 @@ std::string FileData::getString() {
}
std::string FileData::getExtension() {
::filesystem::path p(m_filepath.c_str());
std::string extension(p.extension());
return extension;
ChaiLove* app = ChaiLove::getInstance();
return app->filesystem.getFileExtension(m_filepath);
}
} // namespace FileSystem

View File

@ -3,7 +3,6 @@
#include "Types/Audio/SoundData.h"
#include "../ChaiLove.h"
#include "sound.h"
#include "physfs.h"
#include "audio/conversion/float_to_s16.h"
using love::Types::Audio::SoundData;

View File

@ -5,7 +5,6 @@
#include "physfs.h"
#include "filesystem.h"
#include "physfsrwops.h"
#include "filesystem/path.h"
#include "../ChaiLove.h"
#include "Types/FileSystem/FileInfo.h"
@ -32,8 +31,7 @@ bool filesystem::init(const std::string& file, const void* data) {
}
// Find the parent and extension of the given file.
::filesystem::path p(file.c_str());
std::string extension(p.extension());
std::string extension(getFileExtension(file));
// Allow loading from an Archive.
if (extension == "chaigame" || extension == "chailove" || extension == "zip") {
@ -41,8 +39,7 @@ bool filesystem::init(const std::string& file, const void* data) {
}
// If we are just running the core, load the base path.
::filesystem::path parent(p.parent_path());
std::string parentPath(parent.str());
std::string parentPath(getParentDirectory(file));
if (parentPath.empty()) {
return mount(".", "/", false);
}
@ -51,6 +48,36 @@ bool filesystem::init(const std::string& file, const void* data) {
return mount(parentPath.c_str(), "/", false);
}
std::string filesystem::getParentDirectory(const std::string& filepath) {
size_t last = filepath.find_last_of("/\\");
if (last != std::string::npos) {
return filepath.substr(0, last);
}
return "";
}
std::string filesystem::getFileExtension(const std::string& filepath) {
size_t i = filepath.rfind('.', filepath.length());
if (i != std::string::npos) {
return filepath.substr(i + 1, filepath.length() - i);
}
return "";
}
std::string filesystem::getBasename(const std::string& filepath) {
char sep = '/';
if (filepath.find('\\') != std::string::npos) {
sep = '\\';
}
size_t i = filepath.rfind(sep, filepath.length());
if (i != std::string::npos) {
return filepath.substr(i + 1, filepath.length() - i);
}
return filepath;
}
void filesystem::mountlibretro() {
// Mount some of the libretro directories.
const char *system_dir = NULL;
@ -60,8 +87,8 @@ void filesystem::mountlibretro() {
if (ChaiLove::environ_cb(RETRO_ENVIRONMENT_GET_LIBRETRO_PATH, &core_dir) && core_dir) {
// Make sure to get the directory of the core.
::filesystem::path p(core_dir);
mount(p.parent_path().str(), "/libretro/core", false);
std::string parentPath(getParentDirectory(core_dir));
mount(parentPath, "/libretro/core", false);
}
if (ChaiLove::environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_dir) && system_dir) {
mount(system_dir, "/libretro/system", false);
@ -72,8 +99,12 @@ void filesystem::mountlibretro() {
if (ChaiLove::environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &save_dir) && save_dir) {
save_dir = *save_dir ? save_dir : system_dir;
mount(save_dir, "/libretro/saves", false);
} else {
} else if (system_dir) {
// Have the system directory be the save directory if available.
mount(save_dir = system_dir, "/libretro/saves", false);
} else {
// Save directory becomes the current working directory.
mount(save_dir = ".", "/libretro/saves", false);
}
// Ensure the write directory is set to the Save Directory.
@ -171,10 +202,11 @@ char* filesystem::readChar(const std::string& filename) {
std::string filesystem::read(const std::string& filename) {
// Retrieve a character buffer.
char* myBuf = readChar(filename);
if (myBuf == NULL) {
return std::string("");
std::string output;
if (myBuf != NULL) {
output = std::string(myBuf);
}
return std::string(myBuf);
return output;
}
void* filesystem::readBuffer(const std::string& filename, int& size) {
@ -222,6 +254,9 @@ bool filesystem::unmount(const std::string& archive) {
}
bool filesystem::mount(const char *archive, const std::string& mountpoint) {
if (strlen(archive) == 0) {
return false;
}
return mount(std::string(archive), mountpoint);
}

View File

@ -78,6 +78,10 @@ class filesystem {
*/
int getSize(const std::string& file);
std::string getFileExtension(const std::string& filepath);
std::string getBasename(const std::string& filepath);
std::string getParentDirectory(const std::string& filepath);
/**
* Removes a file or empty directory.
*

View File

@ -1,10 +1,10 @@
#include "script.h"
#include "../ChaiLove.h"
#include <filesystem/path.h>
#include <algorithm>
#ifdef __HAVE_CHAISCRIPT__
#include "chaiscript/extras/math.hpp"
#include "chaiscript/extras/string_methods.hpp"
using namespace chaiscript;
#endif
@ -35,7 +35,7 @@ bool script::loadModule(const std::string& moduleName) {
// See if we are to append .chai.
filename = filename + ".chai";
if (!app->filesystem.exists(filename)) {
std::cout << "[ChaiLove] [script] Module " << moduleName << " not found." << std::endl;
std::cout << "[ChaiLove] [script] Module " << filename << " not found." << std::endl;
return false;
}
}
@ -45,7 +45,7 @@ bool script::loadModule(const std::string& moduleName) {
// Make sure it was not empty.
if (contents.empty()) {
std::cout << "[ChaiLove] [script] Module " << moduleName << " was loaded, but empty." << std::endl;
std::cout << "[ChaiLove] [script] Module " << filename << " was loaded, but empty." << std::endl;
return false;
}
@ -58,7 +58,7 @@ bool script::loadModule(const std::string& moduleName) {
bool script::loadModuleRequire(const std::string& moduleName) {
// Check if the module has already been loaded.
std::string filename = replaceString(moduleName, ".", "/");
std::string filename = replaceString(replaceString(moduleName, ".chai", ""), ".", "/");
if (std::find(m_requiremodules.begin(), m_requiremodules.end(), filename) != m_requiremodules.end()) {
return true;
}
@ -76,6 +76,7 @@ chaiscript::Boxed_Value script::eval(const std::string& code, const std::string&
std::string contents = replaceString(code, "\t", " ");
return chai.eval(contents, Exception_Handler(), filename);
}
std::string script::evalString(const std::string& code, const std::string& filename) {
// Replace possible problematic tabs, and evaluate the script.
std::string contents = replaceString(code, "\t", " ");
@ -84,6 +85,7 @@ std::string script::evalString(const std::string& code, const std::string& filen
script::script(const std::string& file) {
#ifdef __HAVE_CHAISCRIPT__
ChaiLove* app = ChaiLove::getInstance();
// ChaiScript Standard Library Additions
// This adds some basic type definitions to ChaiScript.
@ -91,23 +93,8 @@ script::script(const std::string& file) {
chai.add(bootstrap::standard_library::vector_type<std::vector<std::string>>("StringVector"));
chai.add(bootstrap::standard_library::map_type<std::map<std::string, bool>>("StringBoolMap"));
// Global Helpers
// string::replace(std::string search, std::string replace)
chai.add(fun([](const std::string& subject, const std::string& search, const std::string& replace) {
std::string newSubject(subject);
size_t pos = 0;
while ((pos = newSubject.find(search, pos)) != std::string::npos) {
newSubject.replace(pos, search.length(), replace);
pos += replace.length();
}
return newSubject;
}), "replace");
// string::replace(char search, char replace)
chai.add(fun([](const std::string& subject, char search, char replace) {
std::string newSubject(subject);
std::replace(newSubject.begin(), newSubject.end(), search, replace);
return newSubject;
}), "replace");
auto stringmethods = chaiscript::extras::string_methods::bootstrap();
chai.add(stringmethods);
// List
auto listModule = std::make_shared<chaiscript::Module>();
@ -324,15 +311,18 @@ script::script(const std::string& file) {
chai.add(fun<std::vector<std::string>, filesystem, const std::string&, const std::string&>(&filesystem::lines), "lines");
chai.add(fun(&filesystem::load), "load");
chai.add(fun(&script::loadModuleRequire, this), "require");
chai.add(fun(&filesystem::getFileExtension), "getFileExtension");
chai.add(fun(&filesystem::getBasename), "getBasename");
chai.add(fun(&filesystem::getParentDirectory), "getParentDirectory");
// System
chai.add(fun(&system::getOS), "getOS");
chai.add(fun(&system::getVersion), "getVersion");
chai.add(fun(&system::getVersionString), "getVersionString");
chai.add(fun(&system::getUsername), "getUsername");
chai.add(fun(&system::execute), "execute");
chai.add(fun(&system::getClipboardText), "getClipboardText");
chai.add(fun(&system::setClipboardText), "setClipboardText");
chai.add(fun(&system::execute), "execute");
// Mouse
chai.add(fun(&mouse::getX), "getX");
@ -401,18 +391,19 @@ script::script(const std::string& file) {
// Load the desired main.chai file.
if (file.empty()) {
// When no content is provided, display a No Game demo.
eval(ChaiLove::getInstance()->demo(), "demo.chai");
eval(app->demo(), "demo.chai");
mainLoaded = true;
} else {
// Load the main.chai file.
::filesystem::path p(file.c_str());
std::string extension(p.extension());
loadModuleRequire("conf");
std::string extension(app->filesystem.getFileExtension(file));
if (extension == "chailove" || extension == "chaigame") {
mainLoaded = loadModule("main.chai");
mainLoaded = loadModuleRequire("main");
} else {
// Otherwise, load the actual file.
std::string filename(p.filename());
mainLoaded = loadModule(filename);
std::string filename(app->filesystem.getBasename(file));
mainLoaded = loadModuleRequire(filename);
}
}

View File

@ -45,6 +45,8 @@ class script {
*
* @param t The config object to modify.
*
* This callback can live in the `conf.chai` file.
*
* ### Example
*
* @code
@ -53,7 +55,7 @@ class script {
* t.console = false
*
* // The ChaiLove version this game was made for.
* t.version = "0.27.0"
* t.version = "0.29.0"
*
* // The width and height of the game.
* t.window.width = 1024

View File

@ -96,7 +96,9 @@ class system {
/**
* Execute an operating system shell command. This is like the C system() function.
*
* @return True or False depending on whether or not the command started properly.
* @param command The command to run.
*
* @return Returns true or false depending on the process succeeded to execute.
*/
bool execute(const std::string& command);

8
test/unittests/conf.chai Normal file
View File

@ -0,0 +1,8 @@
global confTestLoaded = false
def conf(t) {
t.console = true
t.window.width = 640
t.window.height = 500
confTestLoaded = true
}

View File

@ -102,3 +102,15 @@ requiretestFileLoaded = false
requireReturn = require("assets.requiretest")
assert(requireReturn, " double call")
assert_not(requiretestFileLoaded, " not loaded twice")
// getFileExtension()
assert_equal(love.filesystem.getFileExtension("/opt/var/something.txt"), "txt", "love.filesystem.getFileExtension()")
assert_equal(love.filesystem.getFileExtension("/opt/var/something.tar.gz"), "gz", "love.filesystem.getFileExtension()")
// getBasename
assert_equal(love.filesystem.getBasename("/opt/var/something.txt"), "something.txt", "love.filesystem.getBasename()")
assert_equal(love.filesystem.getBasename("something.txt"), "something.txt", "love.filesystem.getBasename()")
// getParentDirectory
assert_equal(love.filesystem.getParentDirectory("/opt/var/something.txt"), "/opt/var", "love.filesystem.getParentDirectory()")
assert_equal(love.filesystem.getParentDirectory("something.txt"), "", "love.filesystem.getParentDirectory()")

View File

@ -1,11 +1,5 @@
global failure = ""
def conf(t) {
t.console = true
t.window.width = 640
t.window.height = 500
}
def load() {
print("\n================================\n")
print("ChaiLove: Unit Testing Framework\n")

View File

@ -16,6 +16,7 @@ assert(true, "love.system.getUsername() == '" + username + "'")
// getOS()
if (love.system.getOS() == "Linux") {
// Run in foreground.
var result = love.system.execute("uname")
assert(result, "love.system.execute('uname')")
}
@ -32,3 +33,23 @@ var newReplaceString = replaceSubject.replace("World", "Space")
assert_equal(newReplaceString, "Hello Space! Hello Space!", "string::replace(string, string)")
newReplaceString = replaceSubject.replace('!', '.')
assert_equal(newReplaceString, "Hello World. Hello World.", "string::replace(char, char)")
// string::trim()
var trimSubject = " Hello World! "
assert_equal(trimSubject.trim(), "Hello World!", "string::trim()")
// string::split()
var splitTest = "Hello|How|Are|You"
var splitResult = splitTest.split("|")
assert_equal(splitResult[1], "How", "string::split()")
splitTest = "Hello, World, Time"
splitResult = splitTest.split(", ")
assert_equal(splitResult[1], "World", " - commas")
// conf.chai
var objs = get_objects()
var confTestLoadedExists = objs["confTestLoaded"].get_type_info().bare_equal(bool_type)
assert(confTestLoadedExists, "conf.chai is loaded")
if (confTestLoadedExists) {
assert(confTestLoaded, "conf() called")
}

View File

@ -4,4 +4,4 @@ assert(delta >= 0, "love.timer.getDelta()")
// getFPS()
var fps = love.timer.getFPS()
assert(fps >= 0, "love.love.timer.getFPS()")
assert(fps >= 0, "love.timer.getFPS()")

@ -1 +1 @@
Subproject commit 7043c12105f20baec7655e62563796ca43535557
Subproject commit 4f3ee02194411edc5b7aa80d109e400d3b94c15d

2
vendor/cppcodec vendored

@ -1 +1 @@
Subproject commit 302dc28f8fd5c8bf2ea8d7212aed3be884d5d166
Subproject commit 82d011756adfece7506728b4fa9e7354cbe58641

@ -1 +1 @@
Subproject commit fe12df08508044287aba2317e13cd91596af5af1
Subproject commit 3ae84ee5d0a0af72a6a808a32b63e1ea0076f2be

1
vendor/filesystem vendored

@ -1 +0,0 @@
Subproject commit 0a539a6c988dc8691af317e077893e831dee2908

@ -1 +1 @@
Subproject commit 29905d94e39090dbde5f9e6d726eb2510618704a
Subproject commit 4f99997d94bbfed63d957153976dd9a43c73aced

2
vendor/random vendored

@ -1 +1 @@
Subproject commit 2cdf5dc1b22a390f1a09008a98c56a7604d27597
Subproject commit 985de84de4ec891ce060c4c6579cf70d3c1c86e2