Unverified Commit 14e0a09d authored by Rob Loach's avatar Rob Loach Committed by GitHub
Browse files

Merge pull request #334 from libretro/dev

0.29.0
parents b0b514a0 16e3c947
......@@ -4,6 +4,15 @@ 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.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`
......
......@@ -16,16 +16,16 @@ all: $(TARGET)
$(MAKE) $(TARGET)
$(TARGET): $(OBJECTS) | vendor/libretro-common/include/libretro.h
-$(CXX) -o $@ $^ $(LDFLAGS)
$(CXX) -o $@ $^ $(LDFLAGS)
%.o: %.cpp | vendor/libretro-common/include/libretro.h
-$(CXX) -c -o $@ $< $(CXXFLAGS)
$(CXX) -c -o $@ $< $(CXXFLAGS)
%.o: %.c | vendor/libretro-common/include/libretro.h
-$(CC) -c -o $@ $< $(CFLAGS)
$(CC) -c -o $@ $< $(CFLAGS)
%.o: %.m | vendor/libretro-common/include/libretro.h
-$(CC) -c -o $@ $< $(CFLAGS)
$(CC) -c -o $@ $< $(CFLAGS)
clean:
rm -f $(TARGET) $(OBJECTS)
......
......@@ -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,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:
......
......@@ -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.0"
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
......
/**
* ChaiLove callback; Configure the application.
*/
def conf(t) {
t.window.width = 720
t.window.height = 680
t.console = true
}
......@@ -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)
}
/**
* ChaiLove callback; Configure the application.
*/
def conf(t) {
t.window.width = 640
t.window.height = 480
//t.modules.sound = false
t.console = true
}
......@@ -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)
]
}
/**
......
......@@ -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"
}
/**
......
......@@ -47,9 +47,9 @@
#define SRC_CHAILOVE_H_
#define CHAILOVE_VERSION_MAJOR 0
#define CHAILOVE_VERSION_MINOR 28
#define CHAILOVE_VERSION_MINOR 29
#define CHAILOVE_VERSION_PATCH 0
#define CHAILOVE_VERSION_STRING "0.28.0"
#define CHAILOVE_VERSION_STRING "0.29.0"
#include "SDL.h"
#include "libretro.h"
......
......@@ -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_
......@@ -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();
......
......@@ -72,8 +72,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 +175,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 +227,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);
}
......
......@@ -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", " ");
......@@ -102,13 +103,43 @@ script::script(const std::string& file) {
}
return newSubject;
}), "replace");
// string::replace(char search, char 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");
// string::trim()
chai.add(fun([](const std::string& subject) {
std::string result(subject);
std::string chars = "\t\n\v\f\r ";
result.erase(0, result.find_first_not_of(chars));
result.erase(0, result.find_last_not_of(chars));
return result;
}), "trim");
// string::split()
chai.add(fun([](const std::string& subject, const std::string& token) {
std::string str(subject);
std::vector<std::string> result;
while (str.size()) {
int index = str.find(token);
if (index != std::string::npos) {
result.push_back(str.substr(0, index));
str = str.substr(index + token.size());
if (str.size() == 0) {
result.push_back(str);
}
} else {
result.push_back(str);
str = "";
}
}
return result;
}), "split");
// List
auto listModule = std::make_shared<chaiscript::Module>();
chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List", *listModule);
......@@ -330,9 +361,9 @@ script::script(const std::string& file) {
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");
......@@ -407,12 +438,13 @@ script::script(const std::string& file) {
// Load the main.chai file.
::filesystem::path p(file.c_str());
std::string extension(p.extension());
loadModuleRequire("conf");
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);
mainLoaded = loadModuleRequire(filename);
}
}
......
......@@ -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
......
......@@ -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);
......
global confTestLoaded = false
def conf(t) {
t.console = true
t.window.width = 640
t.window.height = 500
confTestLoaded = true
}
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")
......
......@@ -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")
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment