Added the NativeClient port code.
Thanks to Evgeniy Stepanov for providing the patch.
This commit is contained in:
parent
828550e58d
commit
6c6bf6e3a2
26 changed files with 1123 additions and 6 deletions
28
NaCl-LICENSE
Normal file
28
NaCl-LICENSE
Normal file
|
@ -0,0 +1,28 @@
|
|||
Copyright 2008, Google Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -18,7 +18,8 @@ CHANGES
|
|||
Large portraits, especially high ones, should now work properly. For example TRoW scenario 5 (The Oldwood) now shows Elilmaldur-Rithrandil properly even when the screen resolution is 1920x480. If there are still issues with portraits not being shown, please let us know, either in this thread or by a bug report.
|
||||
[/section]
|
||||
|
||||
[section="Another Change"]
|
||||
[section="NativeClient"]
|
||||
Added the NativeClient port code, provided by Evgeniy Stepanov.
|
||||
[/section]
|
||||
|
||||
[section="Another Change"]
|
||||
|
|
28
SConstruct
28
SConstruct
|
@ -291,6 +291,27 @@ if env["prereqs"]:
|
|||
conf.CheckBoost("thread") and \
|
||||
conf.CheckBoost("asio", header_only = True)
|
||||
|
||||
if env['host'] in ['x86_64-nacl', 'i686-nacl']:
|
||||
# libppapi_cpp has a reverse dependency on the following function
|
||||
env.Append(LINKFLAGS = ['-Wl,--undefined=_ZN2pp12CreateModuleEv'])
|
||||
conf.CheckLib("ppapi")
|
||||
conf.CheckLib("ppapi_cpp")
|
||||
conf.CheckLib("nacl-mounts")
|
||||
# We are linking static libraries without libtool.
|
||||
# Enumerating all transitive dependencies.
|
||||
conf.CheckLib("pthread")
|
||||
conf.CheckLib("dl")
|
||||
conf.CheckLib("SDL")
|
||||
conf.CheckLib("jpeg")
|
||||
conf.CheckLib("png")
|
||||
conf.CheckLib("tiff")
|
||||
conf.CheckLib("ogg")
|
||||
conf.CheckLib("expat")
|
||||
conf.CheckLib("pixman-1")
|
||||
conf.CheckLib("vorbisfile")
|
||||
conf.CheckLib("vorbis")
|
||||
conf.CheckLib("mikmod")
|
||||
|
||||
have_server_prereqs = \
|
||||
conf.CheckCPlusPlus(gcc_version = "3.3") and \
|
||||
conf.CheckGettextLibintl() and \
|
||||
|
@ -354,6 +375,11 @@ else:
|
|||
test_env = env.Clone()
|
||||
client_env = env.Clone()
|
||||
|
||||
|
||||
if env['host'] in ['x86_64-nacl', 'i686-nacl']:
|
||||
env['_LIBFLAGS'] = '-Wl,--start-group ' + env['_LIBFLAGS'] + ' -Wl,--end-group'
|
||||
client_env['_LIBFLAGS'] = '-Wl,--start-group ' + client_env['_LIBFLAGS'] + ' -Wl,--end-group'
|
||||
|
||||
have_msgfmt = env["MSGFMT"]
|
||||
if not have_msgfmt:
|
||||
env["nls"] = False
|
||||
|
@ -367,7 +393,7 @@ if not env['nls']:
|
|||
#
|
||||
|
||||
for env in [test_env, client_env, env]:
|
||||
env.Append(CPPPATH = ["#/", "#/src"])
|
||||
env.Prepend(CPPPATH = ["#/", "#/src"])
|
||||
|
||||
env.Append(CPPDEFINES = ["HAVE_CONFIG_H"])
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ Version 1.9.12+svn:
|
|||
* Fixed: hex-cut of images in :layers debug tool.
|
||||
* Forward ported a new version of multiplayer chat log history dialog
|
||||
* Fixed bug #19188: Turn dialog always speaks of Konrad in tutorial
|
||||
* Added: NativeClient port.
|
||||
|
||||
Version 1.9.12:
|
||||
* Language and i18n:
|
||||
|
|
|
@ -19,6 +19,7 @@ Version 1.9.12+svn:
|
|||
* Miscellaneous and bug fixes:
|
||||
* Forward ported a new version of multiplayer chat log history dialog
|
||||
* Fixed bug #19188: Turn dialog always speaks of Konrad in tutorial
|
||||
* Added NativeClient port.
|
||||
|
||||
Version 1.9.12:
|
||||
* Language and i18n:
|
||||
|
|
|
@ -14,5 +14,5 @@ def restore_env(env, backup):
|
|||
|
||||
def find_include(prefixes, include_file, include_subdir, default_prefixes = True):
|
||||
if default_prefixes:
|
||||
prefixes = ["/usr", "/usr/local", "/sw", "/sw/local"] + prefixes
|
||||
prefixes = prefixes + ["/usr", "/usr/local", "/sw", "/sw/local"]
|
||||
return [(prefix, include) for prefix in prefixes for include in glob(join(prefix, "include", include_subdir, include_file))]
|
||||
|
|
|
@ -482,7 +482,11 @@ for env in [test_env, client_env, env]:
|
|||
|
||||
game_cpp = client_env.Object("game.cpp", EXTRA_DEFINE = not env["pool_alloc"] and "DISABLE_POOL_ALLOC" or None);
|
||||
|
||||
client_env.WesnothProgram("wesnoth", [game_cpp] + [libwesnoth_extras, libwesnoth_core, libwesnoth_sdl, libwesnoth, env["wesnoth_res"]], have_client_prereqs)
|
||||
wesnoth_objects = [game_cpp, libwesnoth_extras, libwesnoth_core, libwesnoth_sdl,
|
||||
libwesnoth, env["wesnoth_res"]]
|
||||
if env["host"] in ["x86_64-nacl", "i686-nacl"]:
|
||||
wesnoth_objects += [SConscript("nacl/SConscript")]
|
||||
client_env.WesnothProgram("wesnoth", wesnoth_objects, have_client_prereqs)
|
||||
|
||||
campaignd_sources = Split("""
|
||||
server/input_stream.cpp
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
#define BREAKPOINT() __debugbreak()
|
||||
#define WES_HALT() do { BREAKPOINT(); exit(1); } while (false)
|
||||
|
||||
#elif defined(__GNUG__) && (defined(__i386__) || defined(__x86_64__))
|
||||
#elif defined(__GNUG__) && (defined(__i386__) || defined(__x86_64__)) \
|
||||
&& !defined(__native_client__)
|
||||
#define BREAKPOINT() asm("int3")
|
||||
#define WES_HALT() do { BREAKPOINT(); abort(); } while (false)
|
||||
|
||||
|
|
|
@ -261,6 +261,26 @@ void get_files_in_dir(const std::string &directory,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __native_client__
|
||||
// For performance reasons, on NaCl we only keep preferences and saves in persistent storage.
|
||||
std::string get_prefs_file()
|
||||
{
|
||||
return "/wesnoth-userdata/preferences";
|
||||
}
|
||||
|
||||
std::string get_save_index_file()
|
||||
{
|
||||
return "/wesnoth-userdata/save_index.gz";
|
||||
}
|
||||
|
||||
std::string get_saves_dir()
|
||||
{
|
||||
const std::string dir_path = "/wesnoth-userdata/saves";
|
||||
return get_dir(dir_path);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
std::string get_prefs_file()
|
||||
{
|
||||
return get_user_config_dir() + "/preferences";
|
||||
|
@ -276,6 +296,7 @@ std::string get_saves_dir()
|
|||
const std::string dir_path = get_user_data_dir() + "/saves";
|
||||
return get_dir(dir_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string get_addon_campaigns_dir()
|
||||
{
|
||||
|
|
|
@ -588,7 +588,12 @@ void init_custom_malloc();
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __native_client__
|
||||
int wesnoth_main(int argc, char** argv)
|
||||
#else
|
||||
int main(int argc, char** argv)
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef HAVE_VISUAL_LEAK_DETECTOR
|
||||
|
@ -672,4 +677,3 @@ int main(int argc, char** argv)
|
|||
|
||||
return 0;
|
||||
} // end main
|
||||
|
||||
|
|
7
src/nacl/SConscript
Normal file
7
src/nacl/SConscript
Normal file
|
@ -0,0 +1,7 @@
|
|||
Import("env")
|
||||
|
||||
env.Append(CPPPATH=["#/src/nacl/generated", "#/src/nacl"])
|
||||
|
||||
libwesnoth_nacl = env.Library("wesnoth_nacl", ["plugin.cc"])
|
||||
|
||||
Return("libwesnoth_nacl")
|
2
src/nacl/dir_list.h
Normal file
2
src/nacl/dir_list.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
/* Intentionally empty */
|
||||
|
2
src/nacl/file_list.h
Normal file
2
src/nacl/file_list.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
/* Intentionally empty */
|
||||
|
2
src/nacl/pack_list.h
Normal file
2
src/nacl/pack_list.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
/* Intentionally empty */
|
||||
|
264
src/nacl/plugin.cc
Normal file
264
src/nacl/plugin.cc
Normal file
|
@ -0,0 +1,264 @@
|
|||
// Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the NaCl-LICENSE file.
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ppapi/cpp/instance.h>
|
||||
#include <ppapi/cpp/module.h>
|
||||
#include <ppapi/cpp/rect.h>
|
||||
#include <ppapi/cpp/size.h>
|
||||
#include <ppapi/cpp/file_system.h>
|
||||
|
||||
#include <SDL_video.h>
|
||||
extern int wesnoth_main(int argc, char **argv);
|
||||
#include <SDL.h>
|
||||
#include <SDL_nacl.h>
|
||||
|
||||
#include <nacl-mounts/base/KernelProxy.h>
|
||||
#include <nacl-mounts/base/MainThreadRunner.h>
|
||||
#include <nacl-mounts/http2/HTTP2Mount.h>
|
||||
#include <nacl-mounts/pepper/PepperMount.h>
|
||||
|
||||
|
||||
const char* http_dirs[] = {
|
||||
#include <dir_list.h>
|
||||
};
|
||||
|
||||
struct http_file_info {
|
||||
const char* path;
|
||||
size_t size;
|
||||
} http_files[] = {
|
||||
#include <file_list.h>
|
||||
};
|
||||
|
||||
struct http_pack_info {
|
||||
const char* path;
|
||||
const char* pack_path;
|
||||
off_t offset;
|
||||
} http_packs[] = {
|
||||
#include <pack_list.h>
|
||||
};
|
||||
|
||||
|
||||
class PluginInstance : public pp::Instance {
|
||||
public:
|
||||
explicit PluginInstance(PP_Instance instance) : pp::Instance(instance),
|
||||
sdl_main_thread_(0),
|
||||
width_(0),
|
||||
height_(0),
|
||||
progress_handler_(this),
|
||||
directory_reader_(this) {
|
||||
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
|
||||
RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
|
||||
|
||||
proxy_ = KernelProxy::KPInstance();
|
||||
runner_ = new MainThreadRunner(this);
|
||||
|
||||
fprintf(stderr, "Requesting an HTML5 local persistent filesystem.\n");
|
||||
fflush(stderr);
|
||||
fs_ = new pp::FileSystem(this, PP_FILESYSTEMTYPE_LOCALPERSISTENT);
|
||||
}
|
||||
|
||||
~PluginInstance() {
|
||||
if (sdl_main_thread_) {
|
||||
pthread_join(sdl_main_thread_, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
|
||||
fprintf(stderr, "did change view, new %dx%d, old %dx%d\n",
|
||||
position.size().width(), position.size().height(),
|
||||
width_, height_);
|
||||
fflush(stderr);
|
||||
|
||||
width_ = position.size().width();
|
||||
height_ = position.size().height();
|
||||
|
||||
SDL_NACL_SetInstance(pp_instance(), width_, height_);
|
||||
|
||||
if (sdl_thread_started_ == false) {
|
||||
// It seems this call to SDL_Init is required. Calling from
|
||||
// sdl_main() isn't good enough.
|
||||
// Perhaps it must be called from the main thread?
|
||||
int lval = SDL_Init(SDL_INIT_AUDIO);
|
||||
assert(lval >= 0);
|
||||
if (0 == pthread_create(&sdl_main_thread_, NULL, sdl_thread_static, this)) {
|
||||
sdl_thread_started_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HandleInputEvent(const pp::InputEvent& event) {
|
||||
SDL_NACL_PushEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleMessage(const pp::Var& message) {
|
||||
std::string s = message.AsString();
|
||||
directory_reader_.HandleResponse(s);
|
||||
}
|
||||
|
||||
bool Init(int argc, const char* argn[], const char* argv[]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool sdl_thread_started_;
|
||||
pthread_t sdl_main_thread_;
|
||||
int width_;
|
||||
int height_;
|
||||
KernelProxy* proxy_;
|
||||
MainThreadRunner* runner_;
|
||||
pp::FileSystem* fs_;
|
||||
|
||||
static void* sdl_thread_static(void* param) {
|
||||
return reinterpret_cast<PluginInstance*>(param)->sdl_thread();
|
||||
}
|
||||
|
||||
void* sdl_thread() {
|
||||
fprintf(stderr, "Initializing nacl-mounts.\n");
|
||||
fflush(stderr);
|
||||
|
||||
// Setup writable homedir.
|
||||
PepperMount* pepper_mount = new PepperMount(runner_, fs_, 20 * 1024 * 1024);
|
||||
pepper_mount->SetDirectoryReader(&directory_reader_);
|
||||
pepper_mount->SetPathPrefix("/wesnoth-userdata");
|
||||
|
||||
proxy_->mkdir("/wesnoth-userdata", 0777);
|
||||
int res = proxy_->mount("/wesnoth-userdata", pepper_mount);
|
||||
|
||||
// The following lines can be removed when nacl-mounts starts intercepting mkdir() calls.
|
||||
proxy_->mkdir("/wesnoth-userdata/saves", 0777);
|
||||
|
||||
// Setup r/o data directory in /usr/local/share/wesnoth
|
||||
HTTP2Mount* http2_mount = new HTTP2Mount(runner_, "./usr/local/share/wesnoth");
|
||||
http2_mount->SetLocalCache(fs_, 350*1024*1024, "/wesnoth0", true);
|
||||
http2_mount->SetProgressHandler(&progress_handler_);
|
||||
|
||||
fprintf(stderr, "Registering known files.\n");
|
||||
fflush(stderr);
|
||||
for (int i = 0; i < sizeof(http_dirs) / sizeof(*http_dirs); ++i) {
|
||||
char* path = (char*)http_dirs[i];
|
||||
if (path && *path)
|
||||
http2_mount->AddDir(path);
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(http_files) / sizeof(*http_files); ++i) {
|
||||
char* path = (char*)http_files[i].path;
|
||||
size_t size = http_files[i].size;
|
||||
if (path && *path)
|
||||
http2_mount->AddFile(path, size);
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(http_packs) / sizeof(*http_packs); ++i) {
|
||||
char* path = (char*)http_packs[i].path;
|
||||
char* pack_path = (char*)http_packs[i].pack_path;
|
||||
off_t offset = http_packs[i].offset;
|
||||
if (path && *path) {
|
||||
http2_mount->SetInPack(path, pack_path, offset);
|
||||
}
|
||||
}
|
||||
|
||||
http2_mount->SetInMemory("/fonts/Andagii.ttf", true);
|
||||
http2_mount->SetInMemory("/fonts/DejaVuSans.ttf", true);
|
||||
http2_mount->SetInMemory("/fonts/wqy-zenhei.ttc", true);
|
||||
|
||||
fprintf(stderr, "Mounting the filesystem.\n");
|
||||
fflush(stderr);
|
||||
proxy_->mkdir("/usr", 0777);
|
||||
proxy_->mkdir("/usr/local", 0777);
|
||||
proxy_->mkdir("/usr/local/share", 0777);
|
||||
res = proxy_->mount("/usr/local/share/wesnoth", http2_mount);
|
||||
if (!res) {
|
||||
fprintf(stderr, "FS initialization success.\n");
|
||||
} else {
|
||||
fprintf(stderr, "FS initialization failure.\n");
|
||||
}
|
||||
fflush(stderr);
|
||||
|
||||
// Finally, launch the game.
|
||||
char res_s[100];
|
||||
snprintf(res_s, sizeof(res_s), "%dx%d", width_, height_);
|
||||
static char const * argv[] = {"wesnoth", "-r", res_s, NULL};
|
||||
printf("starting game thread: %s\n", res_s);
|
||||
wesnoth_main(sizeof(argv) / sizeof(*argv) - 1, (char**)argv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
class ProgressHandler : public HTTP2ProgressHandler {
|
||||
public:
|
||||
pp::Instance* instance_;
|
||||
|
||||
ProgressHandler(pp::Instance* instance) : instance_(instance) {}
|
||||
|
||||
void HandleProgress(std::string& path, int64_t bytes, int64_t size) {
|
||||
char buf[100];
|
||||
snprintf(buf, sizeof(buf), "%llu,%llu", (unsigned long long)bytes,
|
||||
(unsigned long long)size);
|
||||
std::string message = "[\"" + path + "\"," + buf + "]";
|
||||
instance_->PostMessage(message);
|
||||
}
|
||||
};
|
||||
|
||||
ProgressHandler progress_handler_;
|
||||
|
||||
class JSDirectoryReader: public DirectoryReader {
|
||||
public:
|
||||
pp::Instance* instance_;
|
||||
pp::CompletionCallback cc_;
|
||||
std::set<std::string>* entries_;
|
||||
|
||||
JSDirectoryReader(pp::Instance* instance) : instance_(instance) {}
|
||||
|
||||
int ReadDirectory(const std::string& path, std::set<std::string>* entries, const pp::CompletionCallback& cc) {
|
||||
cc_ = cc;
|
||||
entries_ = entries;
|
||||
std::string message = "[\"ReadDirectory\",\"" + path + "\"]";
|
||||
instance_->PostMessage(message);
|
||||
}
|
||||
|
||||
void HandleResponse(const std::string& response) {
|
||||
fprintf(stderr, "response: %s\n", response.c_str());
|
||||
std::string::const_iterator ind = response.begin();
|
||||
std::string::const_iterator next = response.begin();
|
||||
while (ind != response.end() && next != response.end()) {
|
||||
if (*next == '\n' && ind != next) {
|
||||
if (*ind == '\n') {
|
||||
++ind;
|
||||
}
|
||||
if (ind != next) {
|
||||
entries_->insert(std::string(ind, next));
|
||||
}
|
||||
ind = next;
|
||||
}
|
||||
++next;
|
||||
}
|
||||
if (ind != next) {
|
||||
std::string last(ind, next-1);
|
||||
if (!last.empty()) {
|
||||
entries_->insert(last);
|
||||
}
|
||||
}
|
||||
cc_.Run(PP_OK);
|
||||
}
|
||||
};
|
||||
|
||||
JSDirectoryReader directory_reader_;
|
||||
};
|
||||
|
||||
class PepperModule : public pp::Module {
|
||||
public:
|
||||
// Create and return a PluginInstanceInstance object.
|
||||
virtual pp::Instance* CreateInstance(PP_Instance instance) {
|
||||
return new PluginInstance(instance);
|
||||
}
|
||||
};
|
||||
|
||||
namespace pp {
|
||||
Module* CreateModule() {
|
||||
return new PepperModule();
|
||||
}
|
||||
} // namespace pp
|
15
utils/nacl/build.sh
Executable file
15
utils/nacl/build.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the NaCl-LICENSE file.
|
||||
|
||||
set -e -x
|
||||
|
||||
ROOT=${NACL_TOOLCHAIN_ROOT:-$HOME/root/nacl-sdk}
|
||||
PATH=$ROOT/bin:$ROOT/x86_64-nacl/usr/bin:$PATH
|
||||
|
||||
PKG_CONFIG_PATH=$ROOT/x86_64-nacl/usr/lib/pkgconfig scons -j15 host=x86_64-nacl \
|
||||
boostdir=$ROOT/x86_64-nacl/usr/include/boost \
|
||||
boostlibdir=$ROOT/x86_64-nacl/usr/lib sdldir=$ROOT/x86_64-nacl/usr nls=no \
|
||||
destdir=$ROOT/x86_64-nacl \
|
||||
build=release wesnoth install
|
15
utils/nacl/build32.sh
Executable file
15
utils/nacl/build32.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the NaCl-LICENSE file.
|
||||
|
||||
set -e -x
|
||||
|
||||
ROOT=${NACL_TOOLCHAIN_ROOT:-$HOME/root/nacl-sdk}
|
||||
PATH=$ROOT/bin:$ROOT/i686-nacl/usr/bin:$PATH
|
||||
|
||||
PKG_CONFIG_PATH=$ROOT/i686-nacl/usr/lib/pkgconfig scons -j15 host=i686-nacl \
|
||||
boostdir=$ROOT/i686-nacl/usr/include/boost \
|
||||
boostlibdir=$ROOT/i686-nacl/usr/lib sdldir=$ROOT/i686-nacl/usr nls=no \
|
||||
destdir=$ROOT/i686-nacl \
|
||||
build=release wesnoth
|
145
utils/nacl/buildpack.py
Normal file
145
utils/nacl/buildpack.py
Normal file
|
@ -0,0 +1,145 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the NaCl-LICENSE file.
|
||||
|
||||
import shutil
|
||||
import glob
|
||||
import os
|
||||
import fnmatch
|
||||
import sys
|
||||
|
||||
|
||||
# pack description format: [root_mask, file_name_mask, file_path_exclusion_mask]
|
||||
# pack will contain
|
||||
# all files under (and including) the expansion of root_mask,
|
||||
# whose names match file_name_mask,
|
||||
# whose full path (with root_mask) does not match full_path_exclusion_mask
|
||||
pack0_masks = [
|
||||
['data/languages', '*', ''],
|
||||
['data/hardwired', '*', ''],
|
||||
['images/game-icon.png', '*', ''],
|
||||
['images/cursors-bw', '*', ''],
|
||||
['images/misc/logo.png', '*', ''],
|
||||
]
|
||||
|
||||
pack1_masks = [
|
||||
['images', '*', ''],
|
||||
['data/*.cfg', '*', ''],
|
||||
['data/gui', '*', ''],
|
||||
['data/themes', '*.cfg', ''],
|
||||
['data/core', '*.cfg', ''],
|
||||
['data/COPYING.txt', '*', ''],
|
||||
['data/core/images/maps/wesnoth.png', '*', ''],
|
||||
['data/ai', '*', ''],
|
||||
['data/campaigns', '_main.cfg', ''],
|
||||
['sounds/button.wav', '*', ''],
|
||||
['sounds/select.wav', '*', ''],
|
||||
]
|
||||
|
||||
# These files are needed to display the campaign list.
|
||||
pack2_masks = [
|
||||
['data/core/images/misc', '*', ''],
|
||||
['data/campaigns', 'campaign_image.png', ''],
|
||||
['data/campaigns', 'campaign_image.jpg', ''],
|
||||
['data/core/images/units/human-loyalists/knight.png', '*', ''],
|
||||
['data/core/images/units/elves-wood/lord.png', '*', ''],
|
||||
['data/core/images/units/human-outlaws/fugitive.png', '*', ''],
|
||||
['data/core/images/units/elves-wood/high-lord.png', '*', ''],
|
||||
['data/core/images/units/human-loyalists/general.png', '*', ''],
|
||||
['data/core/images/units/human-magi/elder-mage.png', '*', ''],
|
||||
['data/core/images/units/undead/soulless-swimmer.png', '*', ''],
|
||||
['data/core/images/units/orcs/ruler.png', '*', ''],
|
||||
['data/campaigns/Heir_To_The_Throne/images/units/konrad-lord-leading.png', '*', ''],
|
||||
['data/campaigns/The_South_Guard/images/deoran/horseman-commander-defend.png', '*', ''],
|
||||
['data/campaigns/Descent_Into_Darkness/images/units/dark-mage.png', '*', ''],
|
||||
['data/campaigns/The_Rise_Of_Wesnoth/images/units/noble-lord.png', '*', ''],
|
||||
['data/campaigns/Under_the_Burning_Suns/images/units/elves-desert/kaleh.png', '*', ''],
|
||||
['data/core/images/items/hammer-runic.png', '*', ''],
|
||||
['data/core/images/items/sceptre-of-fire.png', '*', ''],
|
||||
['data/core/images/scenery/dwarven-doors-closed.png', '*', ''],
|
||||
]
|
||||
|
||||
pack3_masks = [
|
||||
['data', '*.cfg', ''],
|
||||
['data/core/images/terrain', '*', ''],
|
||||
['data/core/images/themes', '*', ''],
|
||||
['data/lua', '*', ''],
|
||||
['sounds', '*', ''],
|
||||
]
|
||||
|
||||
pack4_masks = [
|
||||
['data/core/sounds', '*', ''],
|
||||
]
|
||||
|
||||
packs = [pack0_masks, pack1_masks, pack2_masks, pack3_masks, pack4_masks]
|
||||
|
||||
|
||||
all_files = set()
|
||||
|
||||
def list_path_with_mask(path, mask, exclude_mask):
|
||||
files = set()
|
||||
if os.path.isdir(path):
|
||||
for (dirpath, dirnames, filenames) in os.walk(path):
|
||||
for filename in filenames:
|
||||
if fnmatch.fnmatch(filename, mask) and not fnmatch.fnmatch(os.path.join(dirpath, filename), exclude_mask):
|
||||
files.add(os.path.join(dirpath, filename))
|
||||
else:
|
||||
if fnmatch.fnmatch(path, mask) and not fnmatch.fnmatch(path, exclude_mask):
|
||||
files.add(path)
|
||||
|
||||
return files
|
||||
|
||||
def list_pack_contents(masks):
|
||||
files = set()
|
||||
for (root_path, mask, exclude_mask) in masks:
|
||||
roots = glob.glob(root_path)
|
||||
for root in roots:
|
||||
new_files = list_path_with_mask(root, mask, exclude_mask).difference(all_files)
|
||||
files.update(new_files)
|
||||
all_files.update(new_files)
|
||||
return files
|
||||
|
||||
|
||||
def build_pack(files, out):
|
||||
fout = open(out, "w")
|
||||
out_list = []
|
||||
sz = 0
|
||||
for f in files:
|
||||
data = open(f).read()
|
||||
fout.write(data)
|
||||
out_list.append('{"/%s", "/%s", %d},\n' % (f, out, sz))
|
||||
sz += len(data)
|
||||
fout.close()
|
||||
print '%s: %d files, %d bytes total' % (out, len(files), sz)
|
||||
|
||||
return ''.join(out_list)
|
||||
|
||||
|
||||
|
||||
base_dir = sys.argv[1]
|
||||
out_list = os.path.join(os.getcwd(), 'src/nacl/generated/pack_list.h')
|
||||
os.chdir(base_dir)
|
||||
|
||||
# define additional packs
|
||||
|
||||
packs.append([['data/core/images/units', '*', ''], ['data/core/images/attacks', '*', '']])
|
||||
|
||||
for path in glob.glob(os.path.join(base_dir, 'data/campaigns/*')):
|
||||
path = path[len(base_dir):]
|
||||
print 'Campaign: ' + path
|
||||
packs.append([[path, '*', '']])
|
||||
|
||||
packs.append([['data/core/images/portraits/humans', '*', '']])
|
||||
packs.append([['data/core/images/portraits', '*', '']])
|
||||
packs.append([['data/core/images', '*', '']])
|
||||
packs.append([['data', '*', 'data/core/music/*']])
|
||||
|
||||
# build packs
|
||||
fout_list = open(out_list, 'w')
|
||||
for (index, pack) in enumerate(packs):
|
||||
pack_files = list_pack_contents(pack)
|
||||
out_list_data = build_pack(pack_files, 'pack' + str(index))
|
||||
fout_list.write(out_list_data)
|
||||
fout_list.write('{"", "", 0}\n')
|
||||
fout_list.close()
|
13
utils/nacl/genfs.sh
Executable file
13
utils/nacl/genfs.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the NaCl-LICENSE file.
|
||||
|
||||
BASE=$NACL_SDK_ROOT/toolchain/linux_x86/x86_64-nacl
|
||||
DIRS_OUT=src/nacl/generated/dir_list.h
|
||||
FILES_OUT=src/nacl/generated/file_list.h
|
||||
(cd $BASE/usr/local/share/wesnoth; find -type d) | perl -pe 's/^\.//' | perl -pe 's/^(.*)$/"$1",/' >$DIRS_OUT
|
||||
echo "" >>$DIRS_OUT
|
||||
(cd $BASE/usr/local/share/wesnoth; find -type f -printf "%p %s\n") | perl -pe 's/^\.//' | perl -pe 's/^(.*) (\d+)$/{"$1", $2},/' >$FILES_OUT
|
||||
echo '{"", 0}' >>$FILES_OUT
|
||||
|
41
utils/nacl/howto
Normal file
41
utils/nacl/howto
Normal file
|
@ -0,0 +1,41 @@
|
|||
Building Wesnoth for NativeClient.
|
||||
|
||||
1. Get the NaCl SDK from http://code.google.com/chrome/nativeclient/
|
||||
Setup enviroment:
|
||||
NACL_SDK_ROOT=<path to sdk>
|
||||
NACL_TOOLCHAIN_ROOT=$NACL_SDK_ROOT/pepper_15/toolchain/linux_x86
|
||||
|
||||
2. Get naclports: http://code.google.com/p/naclports/
|
||||
Build the ports for both x86_64 and i686:
|
||||
make NACL_GLIBC=1 NACL_PACKAGES_BITSIZE=32
|
||||
make NACL_GLIBC=1 NACL_PACKAGES_BITSIZE=64
|
||||
This will install all prerequisites under $NACL_TOOLCHAIN_ROOT.
|
||||
|
||||
3. Build Wesnoth.
|
||||
./utils/nacl/build.sh # build and install under $NACL_TOOLCHAIN_ROOT
|
||||
|
||||
# Scan installed files, pack them in bundles.
|
||||
# You can't realistically download 13000 small files over HTTP.
|
||||
mkdir -p src/nacl/generated
|
||||
./utils/nacl/buildpack.py $NACL_TOOLCHAIN_ROOT/x86_64-nacl/usr/local/share/wesnoth/
|
||||
./utils/nacl/genfs
|
||||
|
||||
# Rebuild Wesnoth with the generated file metadata.
|
||||
./utils/nacl/build.sh
|
||||
|
||||
# Build 32-bit version. No need to repeat the scanning step.
|
||||
./utils/nacl/build32.sh
|
||||
cp wesnoth $NACL_TOOLCHAIN_ROOT/x86_64-nacl/usr/local/share/bin/wesnoth32
|
||||
|
||||
4. Deploy
|
||||
Copy stuff from utils/nacl/static to $NACL_TOOLCHAIN_ROOT/x86_64-nacl
|
||||
|
||||
./install.sh inst
|
||||
|
||||
Upload inst/ to any static file hosting.
|
||||
Open wesnoth.html in Chromium >= 15. At the moment you need to either enable NativeClient in
|
||||
about:flags, or (preferred) access it through Chrome Store.
|
||||
|
||||
Warning: NaCl app will download its data with xmlHttpRequest(). This is not compatible with
|
||||
CDNs that use HTTP 302 redirects to another domain for load balancing and do not set CORS
|
||||
headers appropriately.
|
48
utils/nacl/install.sh
Executable file
48
utils/nacl/install.sh
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the NaCl-LICENSE file.
|
||||
|
||||
set -e
|
||||
|
||||
DST=$1
|
||||
|
||||
if [ z$DST == z ]; then
|
||||
echo "Need dstdir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -d $DST ]; then
|
||||
echo "$DST already exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROOT=$NACL_TOOLCHAIN_ROOT/x86_64-nacl
|
||||
WESNOTH=$ROOT/usr/local/share/wesnoth
|
||||
|
||||
mkdir $DST
|
||||
cp -v $ROOT/wesnoth.html $DST/
|
||||
cp -v $ROOT/wesnoth.nmf $DST/
|
||||
cp -v $ROOT/wesnoth.js $DST/
|
||||
cp -v $ROOT/check_browser.js $DST/
|
||||
cp -v $ROOT/peppermount_helper.js $DST/
|
||||
|
||||
mkdir -p $DST/usr/local/bin/
|
||||
cp -v $ROOT/usr/local/bin/wesnoth $ROOT/usr/local/bin/wesnoth32 $DST/usr/local/bin/
|
||||
|
||||
mkdir $DST/lib32 $DST/lib64
|
||||
for lib in `cat $ROOT/wesnoth.nmf | grep '"url": "lib32' | perl -pe 's/^.*?url": "lib32\/(.*)".*/$1/'`; do
|
||||
cp -v $ROOT/lib32/$lib $DST/lib32/$lib
|
||||
done
|
||||
for lib in `cat $ROOT/wesnoth.nmf | grep '"url": "lib64' | perl -pe 's/^.*?url": "lib64\/(.*)".*/$1/'`; do
|
||||
cp -v $ROOT/lib64/$lib $DST/lib64/$lib
|
||||
done
|
||||
|
||||
mkdir -p $DST/usr/local/share/wesnoth
|
||||
cp -v $ROOT/usr/local/share/wesnoth/pack* $DST/usr/local/share/wesnoth/
|
||||
|
||||
mkdir -p $DST/usr/local/share/wesnoth/data/core/music/
|
||||
cp -rv $ROOT/usr/local/share/wesnoth/data/core/music/* $DST/usr/local/share/wesnoth/data/core/music/
|
||||
|
||||
mkdir -p $DST/usr/local/share/wesnoth/fonts/
|
||||
cp -rv $ROOT/usr/local/share/wesnoth/fonts/* $DST/usr/local/share/wesnoth/fonts/
|
178
utils/nacl/static/check_browser.js
Normal file
178
utils/nacl/static/check_browser.js
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the NaCl-LICENSE file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview This file provides a BrowserChecker Javascript class.
|
||||
* Users can create a BrowserChecker object, invoke checkBrowser(|version|),
|
||||
* and then use getIsValidBrowser() and getBrowserSupportStatus()
|
||||
* to determine if the browser version is greater than |version|
|
||||
* and if the Native Client plugin is found.
|
||||
*/
|
||||
|
||||
// Create a namespace object
|
||||
var browser_version = browser_version || {};
|
||||
|
||||
/**
|
||||
* Class to provide checking for version and NativeClient.
|
||||
* @param {integer} arg1 An argument that indicates major version of Chrome we
|
||||
* require, such as 14.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructor for the BrowserChecker. Sets the major version of
|
||||
* Chrome that is required to |minChromeVersion|.
|
||||
* @param minChromeVersion The earliest major version of chrome that
|
||||
* is supported. If the Chrome browser version is less than
|
||||
* |minChromeVersion| then |isValidBrowswer| will be set to false.
|
||||
* @param opt_maxChromeVersion Ignored. Retained for backwards compatibility.
|
||||
* @param appVersion The application version string.
|
||||
* @param plugins The plugins that exist in the browser.
|
||||
* @constructor
|
||||
*/
|
||||
browser_version.BrowserChecker = function(minChromeVersion,
|
||||
appVersion, plugins,
|
||||
opt_maxChromeVersion) {
|
||||
/**
|
||||
* Version specified by the user. This class looks to see if the browser
|
||||
* version is >= |minChromeVersion_|.
|
||||
* @type {integer}
|
||||
* @private
|
||||
*/
|
||||
this.minChromeVersion_ = minChromeVersion;
|
||||
|
||||
/**
|
||||
* List of Browser plugin objects.
|
||||
* @type {Ojbect array}
|
||||
* @private
|
||||
*/
|
||||
this.plugins_ = plugins;
|
||||
|
||||
/**
|
||||
* Application version string from the Browser.
|
||||
* @type {integer}
|
||||
* @private
|
||||
*/
|
||||
this.appVersion_ = appVersion;
|
||||
|
||||
/**
|
||||
* Flag used to indicate if the browser has Native Client and is if the
|
||||
* browser version is recent enough.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isValidBrowser_ = false;
|
||||
|
||||
/**
|
||||
* Actual major version of Chrome -- found by querying the browser.
|
||||
* @type {integer}
|
||||
* @private
|
||||
*/
|
||||
this.chromeVersion_ = null;
|
||||
|
||||
/**
|
||||
* Browser support status. This allows the user to get a detailed status
|
||||
* rather than using this.browserSupportMessage.
|
||||
*/
|
||||
this.browserSupportStatus_ =
|
||||
browser_version.BrowserChecker.StatusValues.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* The values used for BrowserChecker status to indicate success or
|
||||
* a specific error.
|
||||
* @enum {id}
|
||||
*/
|
||||
browser_version.BrowserChecker.StatusValues = {
|
||||
UNKNOWN: 0,
|
||||
NACL_ENABLED: 1,
|
||||
UNKNOWN_BROWSER: 2,
|
||||
CHROME_VERSION_TOO_OLD: 3,
|
||||
NACL_NOT_ENABLED: 4,
|
||||
NOT_USING_SERVER: 5
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the plugin with name |name| exists in the browser.
|
||||
* @param {string} name The name of the plugin.
|
||||
* @param {Object array} plugins The plugins in this browser.
|
||||
* @return {bool} |true| if the plugin is found.
|
||||
*/
|
||||
browser_version.BrowserChecker.prototype.pluginExists = function(name,
|
||||
plugins) {
|
||||
for (var index=0; index < plugins.length; index++) {
|
||||
var plugin = this.plugins_[index];
|
||||
var plugin_name = plugin['name'];
|
||||
// If the plugin is not found, you can use the Javascript console
|
||||
// to see the names of the plugins that were found when debugging.
|
||||
if (plugin_name.indexOf(name) != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns browserSupportStatus_ which indicates if the browser supports
|
||||
* Native Client. Values are defined as literals in
|
||||
* browser_version.BrowserChecker.StatusValues.
|
||||
* @ return {int} Level of NaCl support.
|
||||
*/
|
||||
browser_version.BrowserChecker.prototype.getBrowserSupportStatus = function() {
|
||||
return this.browserSupportStatus_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns isValidBrowser (true/false) to indicate if the browser supports
|
||||
* Native Client.
|
||||
* @ return {bool} If this browser has NativeClient and correct version.
|
||||
*/
|
||||
browser_version.BrowserChecker.prototype.getIsValidBrowser = function() {
|
||||
return this.isValidBrowser_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if this browser can support Native Client applications.
|
||||
* For Chrome browsers, checks to see if the "Native Client" plugin is
|
||||
* enabled.
|
||||
*/
|
||||
browser_version.BrowserChecker.prototype.checkBrowser = function() {
|
||||
var versionPatt = /Chrome\/(\d+)\.(\d+)\.(\d+)\.(\d+)/;
|
||||
var result = this.appVersion_.match(versionPatt);
|
||||
|
||||
// |result| stores the Chrome version number.
|
||||
if (!result) {
|
||||
this.isValidBrowser_ = false;
|
||||
this.browserSupportStatus_ =
|
||||
browser_version.BrowserChecker.StatusValues.UNKNOWN_BROWSER;
|
||||
} else {
|
||||
this.chromeVersion_ = result[1];
|
||||
// We know we have Chrome, check version and/or plugin named Native Client
|
||||
if (this.chromeVersion_ >= this.minChromeVersion_) {
|
||||
var found_nacl = this.pluginExists('Native Client', this.plugins_);
|
||||
if (found_nacl) {
|
||||
this.isValidBrowser_ = true;
|
||||
this.browserSupportStatus_ =
|
||||
browser_version.BrowserChecker.StatusValues.NACL_ENABLED;
|
||||
} else {
|
||||
this.isValidBrowser_ = false;
|
||||
this.browserSupportStatus_ =
|
||||
browser_version.BrowserChecker.StatusValues.NACL_NOT_ENABLED;
|
||||
}
|
||||
} else {
|
||||
// We are in a version that is less than |minChromeVersion_|
|
||||
this.isValidBrowser_ = false;
|
||||
this.browserSupportStatus_ =
|
||||
browser_version.BrowserChecker.StatusValues.CHROME_VERSION_TOO_OLD;
|
||||
}
|
||||
}
|
||||
var my_protocol = window.location.protocol;
|
||||
if (my_protocol.indexOf('file') == 0) {
|
||||
this.isValidBrowser_ = false;
|
||||
this.browserSupportStatus_ =
|
||||
browser_version.BrowserChecker.StatusValues.NOT_USING_SERVER;
|
||||
}
|
||||
}
|
||||
|
75
utils/nacl/static/peppermount_helper.js
Normal file
75
utils/nacl/static/peppermount_helper.js
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the NaCl-LICENSE file.
|
||||
*/
|
||||
|
||||
function toArray(list) {
|
||||
return Array.prototype.slice.call(list || [], 0);
|
||||
}
|
||||
|
||||
function errorHandler(e) {
|
||||
var msg = '';
|
||||
|
||||
switch (e.code) {
|
||||
case FileError.QUOTA_EXCEEDED_ERR:
|
||||
msg = 'QUOTA_EXCEEDED_ERR';
|
||||
break;
|
||||
case FileError.NOT_FOUND_ERR:
|
||||
msg = 'NOT_FOUND_ERR';
|
||||
break;
|
||||
case FileError.SECURITY_ERR:
|
||||
msg = 'SECURITY_ERR';
|
||||
break;
|
||||
case FileError.INVALID_MODIFICATION_ERR:
|
||||
msg = 'INVALID_MODIFICATION_ERR';
|
||||
break;
|
||||
case FileError.INVALID_STATE_ERR:
|
||||
msg = 'INVALID_STATE_ERR';
|
||||
break;
|
||||
default:
|
||||
msg = 'Unknown Error';
|
||||
break;
|
||||
};
|
||||
|
||||
console.log('Error: ' + msg);
|
||||
document.getElementById('wesnoth').postMessage("");
|
||||
}
|
||||
|
||||
function listResults(entries) {
|
||||
s = ''
|
||||
entries.forEach(function(entry, i) {
|
||||
s += entry.name;
|
||||
s += '\n';
|
||||
});
|
||||
console.log('entries: ' + s);
|
||||
document.getElementById('wesnoth').postMessage(s);
|
||||
}
|
||||
|
||||
function readDir(dir) {
|
||||
var dirReader = dir.createReader();
|
||||
var entries = [];
|
||||
|
||||
// Call the reader.readEntries() until no more results are returned.
|
||||
var readEntries = function() {
|
||||
dirReader.readEntries (function(results) {
|
||||
if (!results.length) {
|
||||
listResults(entries.sort());
|
||||
} else {
|
||||
entries = entries.concat(toArray(results));
|
||||
readEntries();
|
||||
}
|
||||
}, errorHandler);
|
||||
};
|
||||
|
||||
readEntries(); // Start reading dirs.
|
||||
}
|
||||
|
||||
|
||||
function HandlePepperMountMessage(data) {
|
||||
path = data[1];
|
||||
onInitFs = function(fs) {
|
||||
fs.root.getDirectory(path, {}, readDir, errorHandler);
|
||||
};
|
||||
window.webkitRequestFileSystem(window.PERSISTENT, 5*1024*1024 /*5MB*/, onInitFs, errorHandler);
|
||||
}
|
28
utils/nacl/static/wesnoth.html
Normal file
28
utils/nacl/static/wesnoth.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html>
|
||||
<!--
|
||||
Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style license that can be
|
||||
found in the NaCl-LICENSE file.
|
||||
-->
|
||||
<head>
|
||||
<title>Wesnoth NativeClient demo</title>
|
||||
<script type="text/javascript" src="check_browser.js"></script>
|
||||
</head>
|
||||
<body style="color:gray;background-color:#776655">
|
||||
<div id="nacl_div" style="text-align:center">
|
||||
<canvas id="progress_bar"
|
||||
width="1024" height="20">
|
||||
Your browser does not support HTML5 Canvas.
|
||||
</canvas>
|
||||
</div>
|
||||
|
||||
<script src="peppermount_helper.js"></script>
|
||||
<script src="wesnoth.js"></script>
|
||||
|
||||
<p style="text-align:center">
|
||||
<a href="http://www.wesnoth.org">Wesnoth</a> |
|
||||
<a href="http://code.google.com/chrome/nativeclient">NativeClient</a>
|
||||
</body>
|
||||
</HTML>
|
143
utils/nacl/static/wesnoth.js
Normal file
143
utils/nacl/static/wesnoth.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The Native Client Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the NaCl-LICENSE file.
|
||||
*/
|
||||
|
||||
function updateProgressBar(percent, message, styleBackground,
|
||||
styleForeground, styleText) {
|
||||
console.log("message: " + message);
|
||||
console.log("progress: " + percent + "%");
|
||||
var progress_bar =
|
||||
document.getElementById('progress_bar');
|
||||
var ctx = progress_bar.getContext('2d');
|
||||
var width = progress_bar.width;
|
||||
ctx.fillStyle = styleForeground ? styleForeground :
|
||||
"#52565a";
|
||||
ctx.fillRect(0, 0, percent * width, 20);
|
||||
ctx.fillStyle = styleBackground ? styleBackground :
|
||||
"#ddccbb";
|
||||
ctx.fillRect(percent * width, 0, width, 20);
|
||||
ctx.fillStyle = styleText ? styleText : "black";
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.font = 'sans-serif';
|
||||
ctx.fillText(message, width / 2, 10, 3 * width / 4);
|
||||
}
|
||||
|
||||
function HandleProgress(event) {
|
||||
var loadPercent = 0.0;
|
||||
var loadPercentString;
|
||||
if (event.lengthComputable && event.total > 0) {
|
||||
loadPercent = event.loaded / event.total;
|
||||
} else {
|
||||
// The total length is not yet known.
|
||||
loadPercent = -1.0;
|
||||
}
|
||||
updateProgressBar(loadPercent, "Initializing Wesnoth (please be patient) ...");
|
||||
}
|
||||
|
||||
function HandleMessage(event) {
|
||||
console.log(event.data);
|
||||
var data = JSON.parse(event.data);
|
||||
console.log(data)
|
||||
console.log(data[0])
|
||||
console.log(data[0] == 'ReadDirectory')
|
||||
if (data[0] == 'ReadDirectory') {
|
||||
HandlePepperMountMessage(data);
|
||||
} else {
|
||||
updateProgressBar(data[1] / data[2], data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function updateStatusFail(message) {
|
||||
updateProgressBar(1, message, 'black',
|
||||
'red', 'black')
|
||||
}
|
||||
|
||||
function moduleLoadError() {
|
||||
var msg = "NaCl module load error: " + document.getElementById('wesnoth').lastError;
|
||||
updateStatusFail(msg);
|
||||
console.log(msg);
|
||||
}
|
||||
|
||||
function moduleLoadAbort() {
|
||||
var msg = "NaCl module load aborted: " + document.getElementById('wesnoth').lastError;
|
||||
updateStatusFail(msg);
|
||||
console.log(msg);
|
||||
}
|
||||
|
||||
function requestQuotaAndStartWesnoth() {
|
||||
quota_required = 380*1024*1024;
|
||||
window.webkitStorageInfo.requestQuota(PERSISTENT, quota_required, function(bytes) {
|
||||
console.log("Persistent storage quota granted: " + bytes + " bytes");
|
||||
if (bytes >= quota_required) {
|
||||
var embed = document.createElement('embed');
|
||||
embed.setAttribute('name', 'nacl_module');
|
||||
embed.setAttribute('id', 'wesnoth');
|
||||
embed.setAttribute('width', 1024);
|
||||
embed.setAttribute('height', 800);
|
||||
embed.setAttribute('src', 'wesnoth.nmf');
|
||||
embed.setAttribute('type', 'application/x-nacl');
|
||||
var div = document.getElementById("nacl_div");
|
||||
div.appendChild(embed);
|
||||
div.addEventListener('progress', HandleProgress, true);
|
||||
div.addEventListener('message', HandleMessage, true);
|
||||
div.addEventListener('error', moduleLoadError, true);
|
||||
div.addEventListener('abort', moduleLoadAbort, true);
|
||||
} else {
|
||||
updateStatusFail("Unsufficient HTML5 file system quota: " + bytes + " bytes");
|
||||
console.log("Unsufficient HTML5 file system quota: " + bytes + " bytes");
|
||||
}
|
||||
}, function(e) {
|
||||
updateStatusFail("HTML5 file system quota request failed");
|
||||
console.log("Quota request error: " + e);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function checkBrowser() {
|
||||
var isValidBrowser = false;
|
||||
var browserSupportStatus = 0;
|
||||
var checker = new browser_version.BrowserChecker(15, // Minumum Chrome version.
|
||||
navigator["appVersion"],
|
||||
navigator["plugins"]);
|
||||
checker.checkBrowser();
|
||||
isValidBrowser = checker.getIsValidBrowser();
|
||||
browserSupportStatus = checker.getBrowserSupportStatus();
|
||||
|
||||
switch (browserSupportStatus) {
|
||||
case browser_version.BrowserChecker.StatusValues.NACL_ENABLED:
|
||||
console.log('Native Client plugin enabled.');
|
||||
break;
|
||||
case browser_version.BrowserChecker.StatusValues.UNKNOWN_BROWSER:
|
||||
updateStatusFail('UNKNOWN BROWSER');
|
||||
break;
|
||||
case browser_version.BrowserChecker.StatusValues.CHROME_VERSION_TOO_OLD:
|
||||
console.log('Chrome too old: You must use Chrome version 15 or later.');
|
||||
updateStatusFail('NEED CHROME 15 OR LATER');
|
||||
break;
|
||||
case browser_version.BrowserChecker.StatusValues.NACL_NOT_ENABLED:
|
||||
console.log(
|
||||
'NaCl disabled: Native Client is not enabled.<br>' +
|
||||
'Please go to <b>chrome://plugins</b> and enable Native Client ' +
|
||||
'plugin.');
|
||||
updateStatusFail('NativeClient NOT ENABLED');
|
||||
break;
|
||||
case browser_version.BrowserChecker.StatusValues.NOT_USING_SERVER:
|
||||
console.log(
|
||||
'file: URL detected, please use a web server to host Native ' +
|
||||
'Client applications.');
|
||||
updateStatusFail('file:// URLs NOT ALLOWED');
|
||||
default:
|
||||
console.log('Unknown error: Unable to detect browser and/or ' +
|
||||
'Native Client support.');
|
||||
updateStatusFail('UNKNOWN ERROR');
|
||||
break;
|
||||
}
|
||||
return isValidBrowser && browserSupportStatus == browser_version.BrowserChecker.StatusValues.NACL_ENABLED;
|
||||
}
|
||||
|
||||
if (checkBrowser())
|
||||
requestQuotaAndStartWesnoth();
|
||||
|
52
utils/nacl/static/wesnoth.nmf
Normal file
52
utils/nacl/static/wesnoth.nmf
Normal file
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"program": {
|
||||
"x86-32": {"url": "lib32/runnable-ld.so"},
|
||||
"x86-64": {"url": "lib64/runnable-ld.so"}
|
||||
},
|
||||
"files": {
|
||||
"libc.so.5e6ad7ea" : {
|
||||
"x86-32" : {"url": "lib32/libc.so.5e6ad7ea"},
|
||||
"x86-64" : {"url": "lib64/libc.so.5e6ad7ea"}
|
||||
},
|
||||
"libdl.so.5e6ad7ea" : {
|
||||
"x86-32" : {"url": "lib32/libdl.so.5e6ad7ea"},
|
||||
"x86-64" : {"url": "lib64/libdl.so.5e6ad7ea"}
|
||||
},
|
||||
"librt.so.5e6ad7ea" : {
|
||||
"x86-32" : {"url": "lib32/librt.so.5e6ad7ea"},
|
||||
"x86-64" : {"url": "lib64/librt.so.5e6ad7ea"}
|
||||
},
|
||||
"libm.so.5e6ad7ea" : {
|
||||
"x86-32" : { "url": "lib32/libm.so.5e6ad7ea"},
|
||||
"x86-64" : { "url": "lib64/libm.so.5e6ad7ea"}
|
||||
},
|
||||
"libgcc_s.so.1" : {
|
||||
"x86-32" : { "url": "lib32/libgcc_s.so.1"},
|
||||
"x86-64" : { "url": "lib64/libgcc_s.so.1"}
|
||||
},
|
||||
"libpthread.so.5e6ad7ea" : {
|
||||
"x86-32" : { "url": "lib32/libpthread.so.5e6ad7ea"},
|
||||
"x86-64" : { "url": "lib64/libpthread.so.5e6ad7ea"}
|
||||
},
|
||||
"libstdc++.so.6" : {
|
||||
"x86-32" : { "url": "lib32/libstdc++.so.6"},
|
||||
"x86-64" : { "url": "lib64/libstdc++.so.6"}
|
||||
},
|
||||
"libplatform.so" : {
|
||||
"x86-32" : { "url": "lib32/libplatform.so"},
|
||||
"x86-64" : { "url": "lib64/libplatform.so"}
|
||||
},
|
||||
"libgio.so" : {
|
||||
"x86-32" : { "url": "lib32/libgio.so"},
|
||||
"x86-64" : { "url": "lib64/libgio.so"}
|
||||
},
|
||||
"libppapi_cpp.so" : {
|
||||
"x86-32" : { "url": "lib32/libppapi_cpp.so"},
|
||||
"x86-64" : { "url": "lib64/libppapi_cpp.so"}
|
||||
},
|
||||
"main.nexe" : {
|
||||
"x86-32" : {"url" : "usr/local/bin/wesnoth32"},
|
||||
"x86-64" : {"url" : "usr/local/bin/wesnoth"}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue